~ubuntu-branches/ubuntu/natty/ffc/natty

« back to all changes in this revision

Viewing changes to test/regression/reference/quadrature/HyperElasticity.h

  • Committer: Bazaar Package Importer
  • Author(s): Johannes Ring
  • Date: 2010-02-03 20:22:35 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100203202235-fe8d0kajuvgy2sqn
Tags: 0.9.0-1
* New upstream release.
* debian/control: Bump Standards-Version (no changes needed).
* Update debian/copyright and debian/copyright_hints.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// This code conforms with the UFC specification version 1.0
2
 
// and was automatically generated by FFC version 0.7.0.
3
 
 
4
 
#ifndef __HYPERELASTICITY_H
5
 
#define __HYPERELASTICITY_H
6
 
 
7
 
#include <cmath>
8
 
#include <stdexcept>
9
 
#include <ufc.h>
10
 
 
11
 
/// This class defines the interface for a finite element.
12
 
 
13
 
class hyperelasticity_0_finite_element_0_0: public ufc::finite_element
14
 
{
15
 
public:
16
 
 
17
 
  /// Constructor
18
 
  hyperelasticity_0_finite_element_0_0() : ufc::finite_element()
19
 
  {
20
 
    // Do nothing
21
 
  }
22
 
 
23
 
  /// Destructor
24
 
  virtual ~hyperelasticity_0_finite_element_0_0()
25
 
  {
26
 
    // Do nothing
27
 
  }
28
 
 
29
 
  /// Return a string identifying the finite element
30
 
  virtual const char* signature() const
31
 
  {
32
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
33
 
  }
34
 
 
35
 
  /// Return the cell shape
36
 
  virtual ufc::shape cell_shape() const
37
 
  {
38
 
    return ufc::tetrahedron;
39
 
  }
40
 
 
41
 
  /// Return the dimension of the finite element function space
42
 
  virtual unsigned int space_dimension() const
43
 
  {
44
 
    return 4;
45
 
  }
46
 
 
47
 
  /// Return the rank of the value space
48
 
  virtual unsigned int value_rank() const
49
 
  {
50
 
    return 0;
51
 
  }
52
 
 
53
 
  /// Return the dimension of the value space for axis i
54
 
  virtual unsigned int value_dimension(unsigned int i) const
55
 
  {
56
 
    return 1;
57
 
  }
58
 
 
59
 
  /// Evaluate basis function i at given point in cell
60
 
  virtual void evaluate_basis(unsigned int i,
61
 
                              double* values,
62
 
                              const double* coordinates,
63
 
                              const ufc::cell& c) const
64
 
  {
65
 
    // Extract vertex coordinates
66
 
    const double * const * element_coordinates = c.coordinates;
67
 
    
68
 
    // Compute Jacobian of affine map from reference cell
69
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
70
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
71
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
72
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
73
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
74
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
75
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
76
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
77
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
78
 
    
79
 
    // Compute sub determinants
80
 
    const double d00 = J_11*J_22 - J_12*J_21;
81
 
    const double d01 = J_12*J_20 - J_10*J_22;
82
 
    const double d02 = J_10*J_21 - J_11*J_20;
83
 
    
84
 
    const double d10 = J_02*J_21 - J_01*J_22;
85
 
    const double d11 = J_00*J_22 - J_02*J_20;
86
 
    const double d12 = J_01*J_20 - J_00*J_21;
87
 
    
88
 
    const double d20 = J_01*J_12 - J_02*J_11;
89
 
    const double d21 = J_02*J_10 - J_00*J_12;
90
 
    const double d22 = J_00*J_11 - J_01*J_10;
91
 
    
92
 
    // Compute determinant of Jacobian
93
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
94
 
    
95
 
    // Compute inverse of Jacobian
96
 
    
97
 
    // Compute constants
98
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
99
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
100
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
101
 
    
102
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
103
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
104
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
105
 
    
106
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
107
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
108
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
109
 
    
110
 
    // Get coordinates and map to the UFC reference element
111
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
112
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
113
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
114
 
    
115
 
    // Map coordinates to the reference cube
116
 
    if (std::abs(y + z - 1.0) < 1e-08)
117
 
      x = 1.0;
118
 
    else
119
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
120
 
    if (std::abs(z - 1.0) < 1e-08)
121
 
      y = -1.0;
122
 
    else
123
 
      y = 2.0 * y/(1.0 - z) - 1.0;
124
 
    z = 2.0 * z - 1.0;
125
 
    
126
 
    // Reset values
127
 
    *values = 0;
128
 
    
129
 
    // Map degree of freedom to element degree of freedom
130
 
    const unsigned int dof = i;
131
 
    
132
 
    // Generate scalings
133
 
    const double scalings_y_0 = 1;
134
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
135
 
    const double scalings_z_0 = 1;
136
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
137
 
    
138
 
    // Compute psitilde_a
139
 
    const double psitilde_a_0 = 1;
140
 
    const double psitilde_a_1 = x;
141
 
    
142
 
    // Compute psitilde_bs
143
 
    const double psitilde_bs_0_0 = 1;
144
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
145
 
    const double psitilde_bs_1_0 = 1;
146
 
    
147
 
    // Compute psitilde_cs
148
 
    const double psitilde_cs_00_0 = 1;
149
 
    const double psitilde_cs_00_1 = 2*z + 1;
150
 
    const double psitilde_cs_01_0 = 1;
151
 
    const double psitilde_cs_10_0 = 1;
152
 
    
153
 
    // Compute basisvalues
154
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
155
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
156
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
157
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
158
 
    
159
 
    // Table(s) of coefficients
160
 
    static const double coefficients0[4][4] = \
161
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
162
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
163
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
164
 
    {0.288675135, 0, 0, 0.223606798}};
165
 
    
166
 
    // Extract relevant coefficients
167
 
    const double coeff0_0 = coefficients0[dof][0];
168
 
    const double coeff0_1 = coefficients0[dof][1];
169
 
    const double coeff0_2 = coefficients0[dof][2];
170
 
    const double coeff0_3 = coefficients0[dof][3];
171
 
    
172
 
    // Compute value(s)
173
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
174
 
  }
175
 
 
176
 
  /// Evaluate all basis functions at given point in cell
177
 
  virtual void evaluate_basis_all(double* values,
178
 
                                  const double* coordinates,
179
 
                                  const ufc::cell& c) const
180
 
  {
181
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
182
 
  }
183
 
 
184
 
  /// Evaluate order n derivatives of basis function i at given point in cell
185
 
  virtual void evaluate_basis_derivatives(unsigned int i,
186
 
                                          unsigned int n,
187
 
                                          double* values,
188
 
                                          const double* coordinates,
189
 
                                          const ufc::cell& c) const
190
 
  {
191
 
    // Extract vertex coordinates
192
 
    const double * const * element_coordinates = c.coordinates;
193
 
    
194
 
    // Compute Jacobian of affine map from reference cell
195
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
196
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
197
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
198
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
199
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
200
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
201
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
202
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
203
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
204
 
    
205
 
    // Compute sub determinants
206
 
    const double d00 = J_11*J_22 - J_12*J_21;
207
 
    const double d01 = J_12*J_20 - J_10*J_22;
208
 
    const double d02 = J_10*J_21 - J_11*J_20;
209
 
    
210
 
    const double d10 = J_02*J_21 - J_01*J_22;
211
 
    const double d11 = J_00*J_22 - J_02*J_20;
212
 
    const double d12 = J_01*J_20 - J_00*J_21;
213
 
    
214
 
    const double d20 = J_01*J_12 - J_02*J_11;
215
 
    const double d21 = J_02*J_10 - J_00*J_12;
216
 
    const double d22 = J_00*J_11 - J_01*J_10;
217
 
    
218
 
    // Compute determinant of Jacobian
219
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
220
 
    
221
 
    // Compute inverse of Jacobian
222
 
    
223
 
    // Compute constants
224
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
225
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
226
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
227
 
    
228
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
229
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
230
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
231
 
    
232
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
233
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
234
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
235
 
    
236
 
    // Get coordinates and map to the UFC reference element
237
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
238
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
239
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
240
 
    
241
 
    // Map coordinates to the reference cube
242
 
    if (std::abs(y + z - 1.0) < 1e-08)
243
 
      x = 1.0;
244
 
    else
245
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
246
 
    if (std::abs(z - 1.0) < 1e-08)
247
 
      y = -1.0;
248
 
    else
249
 
      y = 2.0 * y/(1.0 - z) - 1.0;
250
 
    z = 2.0 * z - 1.0;
251
 
    
252
 
    // Compute number of derivatives
253
 
    unsigned int num_derivatives = 1;
254
 
    
255
 
    for (unsigned int j = 0; j < n; j++)
256
 
      num_derivatives *= 3;
257
 
    
258
 
    
259
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
260
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
261
 
    
262
 
    for (unsigned int j = 0; j < num_derivatives; j++)
263
 
    {
264
 
      combinations[j] = new unsigned int [n];
265
 
      for (unsigned int k = 0; k < n; k++)
266
 
        combinations[j][k] = 0;
267
 
    }
268
 
    
269
 
    // Generate combinations of derivatives
270
 
    for (unsigned int row = 1; row < num_derivatives; row++)
271
 
    {
272
 
      for (unsigned int num = 0; num < row; num++)
273
 
      {
274
 
        for (unsigned int col = n-1; col+1 > 0; col--)
275
 
        {
276
 
          if (combinations[row][col] + 1 > 2)
277
 
            combinations[row][col] = 0;
278
 
          else
279
 
          {
280
 
            combinations[row][col] += 1;
281
 
            break;
282
 
          }
283
 
        }
284
 
      }
285
 
    }
286
 
    
287
 
    // Compute inverse of Jacobian
288
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
289
 
    
290
 
    // Declare transformation matrix
291
 
    // Declare pointer to two dimensional array and initialise
292
 
    double **transform = new double *[num_derivatives];
293
 
    
294
 
    for (unsigned int j = 0; j < num_derivatives; j++)
295
 
    {
296
 
      transform[j] = new double [num_derivatives];
297
 
      for (unsigned int k = 0; k < num_derivatives; k++)
298
 
        transform[j][k] = 1;
299
 
    }
300
 
    
301
 
    // Construct transformation matrix
302
 
    for (unsigned int row = 0; row < num_derivatives; row++)
303
 
    {
304
 
      for (unsigned int col = 0; col < num_derivatives; col++)
305
 
      {
306
 
        for (unsigned int k = 0; k < n; k++)
307
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
308
 
      }
309
 
    }
310
 
    
311
 
    // Reset values
312
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
313
 
      values[j] = 0;
314
 
    
315
 
    // Map degree of freedom to element degree of freedom
316
 
    const unsigned int dof = i;
317
 
    
318
 
    // Generate scalings
319
 
    const double scalings_y_0 = 1;
320
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
321
 
    const double scalings_z_0 = 1;
322
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
323
 
    
324
 
    // Compute psitilde_a
325
 
    const double psitilde_a_0 = 1;
326
 
    const double psitilde_a_1 = x;
327
 
    
328
 
    // Compute psitilde_bs
329
 
    const double psitilde_bs_0_0 = 1;
330
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
331
 
    const double psitilde_bs_1_0 = 1;
332
 
    
333
 
    // Compute psitilde_cs
334
 
    const double psitilde_cs_00_0 = 1;
335
 
    const double psitilde_cs_00_1 = 2*z + 1;
336
 
    const double psitilde_cs_01_0 = 1;
337
 
    const double psitilde_cs_10_0 = 1;
338
 
    
339
 
    // Compute basisvalues
340
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
341
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
342
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
343
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
344
 
    
345
 
    // Table(s) of coefficients
346
 
    static const double coefficients0[4][4] = \
347
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
348
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
349
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
350
 
    {0.288675135, 0, 0, 0.223606798}};
351
 
    
352
 
    // Interesting (new) part
353
 
    // Tables of derivatives of the polynomial base (transpose)
354
 
    static const double dmats0[4][4] = \
355
 
    {{0, 0, 0, 0},
356
 
    {6.32455532, 0, 0, 0},
357
 
    {0, 0, 0, 0},
358
 
    {0, 0, 0, 0}};
359
 
    
360
 
    static const double dmats1[4][4] = \
361
 
    {{0, 0, 0, 0},
362
 
    {3.16227766, 0, 0, 0},
363
 
    {5.47722558, 0, 0, 0},
364
 
    {0, 0, 0, 0}};
365
 
    
366
 
    static const double dmats2[4][4] = \
367
 
    {{0, 0, 0, 0},
368
 
    {3.16227766, 0, 0, 0},
369
 
    {1.82574186, 0, 0, 0},
370
 
    {5.16397779, 0, 0, 0}};
371
 
    
372
 
    // Compute reference derivatives
373
 
    // Declare pointer to array of derivatives on FIAT element
374
 
    double *derivatives = new double [num_derivatives];
375
 
    
376
 
    // Declare coefficients
377
 
    double coeff0_0 = 0;
378
 
    double coeff0_1 = 0;
379
 
    double coeff0_2 = 0;
380
 
    double coeff0_3 = 0;
381
 
    
382
 
    // Declare new coefficients
383
 
    double new_coeff0_0 = 0;
384
 
    double new_coeff0_1 = 0;
385
 
    double new_coeff0_2 = 0;
386
 
    double new_coeff0_3 = 0;
387
 
    
388
 
    // Loop possible derivatives
389
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
390
 
    {
391
 
      // Get values from coefficients array
392
 
      new_coeff0_0 = coefficients0[dof][0];
393
 
      new_coeff0_1 = coefficients0[dof][1];
394
 
      new_coeff0_2 = coefficients0[dof][2];
395
 
      new_coeff0_3 = coefficients0[dof][3];
396
 
    
397
 
      // Loop derivative order
398
 
      for (unsigned int j = 0; j < n; j++)
399
 
      {
400
 
        // Update old coefficients
401
 
        coeff0_0 = new_coeff0_0;
402
 
        coeff0_1 = new_coeff0_1;
403
 
        coeff0_2 = new_coeff0_2;
404
 
        coeff0_3 = new_coeff0_3;
405
 
    
406
 
        if(combinations[deriv_num][j] == 0)
407
 
        {
408
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
409
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
410
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
411
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
412
 
        }
413
 
        if(combinations[deriv_num][j] == 1)
414
 
        {
415
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
416
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
417
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
418
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
419
 
        }
420
 
        if(combinations[deriv_num][j] == 2)
421
 
        {
422
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
423
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
424
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
425
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
426
 
        }
427
 
    
428
 
      }
429
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
430
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
431
 
    }
432
 
    
433
 
    // Transform derivatives back to physical element
434
 
    for (unsigned int row = 0; row < num_derivatives; row++)
435
 
    {
436
 
      for (unsigned int col = 0; col < num_derivatives; col++)
437
 
      {
438
 
        values[row] += transform[row][col]*derivatives[col];
439
 
      }
440
 
    }
441
 
    // Delete pointer to array of derivatives on FIAT element
442
 
    delete [] derivatives;
443
 
    
444
 
    // Delete pointer to array of combinations of derivatives and transform
445
 
    for (unsigned int row = 0; row < num_derivatives; row++)
446
 
    {
447
 
      delete [] combinations[row];
448
 
      delete [] transform[row];
449
 
    }
450
 
    
451
 
    delete [] combinations;
452
 
    delete [] transform;
453
 
  }
454
 
 
455
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
456
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
457
 
                                              double* values,
458
 
                                              const double* coordinates,
459
 
                                              const ufc::cell& c) const
460
 
  {
461
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
462
 
  }
463
 
 
464
 
  /// Evaluate linear functional for dof i on the function f
465
 
  virtual double evaluate_dof(unsigned int i,
466
 
                              const ufc::function& f,
467
 
                              const ufc::cell& c) const
468
 
  {
469
 
    // The reference points, direction and weights:
470
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
471
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
472
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
473
 
    
474
 
    const double * const * x = c.coordinates;
475
 
    double result = 0.0;
476
 
    // Iterate over the points:
477
 
    // Evaluate basis functions for affine mapping
478
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
479
 
    const double w1 = X[i][0][0];
480
 
    const double w2 = X[i][0][1];
481
 
    const double w3 = X[i][0][2];
482
 
    
483
 
    // Compute affine mapping y = F(X)
484
 
    double y[3];
485
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
486
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
487
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
488
 
    
489
 
    // Evaluate function at physical points
490
 
    double values[1];
491
 
    f.evaluate(values, y, c);
492
 
    
493
 
    // Map function values using appropriate mapping
494
 
    // Affine map: Do nothing
495
 
    
496
 
    // Note that we do not map the weights (yet).
497
 
    
498
 
    // Take directional components
499
 
    for(int k = 0; k < 1; k++)
500
 
      result += values[k]*D[i][0][k];
501
 
    // Multiply by weights
502
 
    result *= W[i][0];
503
 
    
504
 
    return result;
505
 
  }
506
 
 
507
 
  /// Evaluate linear functionals for all dofs on the function f
508
 
  virtual void evaluate_dofs(double* values,
509
 
                             const ufc::function& f,
510
 
                             const ufc::cell& c) const
511
 
  {
512
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
513
 
  }
514
 
 
515
 
  /// Interpolate vertex values from dof values
516
 
  virtual void interpolate_vertex_values(double* vertex_values,
517
 
                                         const double* dof_values,
518
 
                                         const ufc::cell& c) const
519
 
  {
520
 
    // Evaluate at vertices and use affine mapping
521
 
    vertex_values[0] = dof_values[0];
522
 
    vertex_values[1] = dof_values[1];
523
 
    vertex_values[2] = dof_values[2];
524
 
    vertex_values[3] = dof_values[3];
525
 
  }
526
 
 
527
 
  /// Return the number of sub elements (for a mixed element)
528
 
  virtual unsigned int num_sub_elements() const
529
 
  {
530
 
    return 1;
531
 
  }
532
 
 
533
 
  /// Create a new finite element for sub element i (for a mixed element)
534
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
535
 
  {
536
 
    return new hyperelasticity_0_finite_element_0_0();
537
 
  }
538
 
 
539
 
};
540
 
 
541
 
/// This class defines the interface for a finite element.
542
 
 
543
 
class hyperelasticity_0_finite_element_0_1: public ufc::finite_element
544
 
{
545
 
public:
546
 
 
547
 
  /// Constructor
548
 
  hyperelasticity_0_finite_element_0_1() : ufc::finite_element()
549
 
  {
550
 
    // Do nothing
551
 
  }
552
 
 
553
 
  /// Destructor
554
 
  virtual ~hyperelasticity_0_finite_element_0_1()
555
 
  {
556
 
    // Do nothing
557
 
  }
558
 
 
559
 
  /// Return a string identifying the finite element
560
 
  virtual const char* signature() const
561
 
  {
562
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
563
 
  }
564
 
 
565
 
  /// Return the cell shape
566
 
  virtual ufc::shape cell_shape() const
567
 
  {
568
 
    return ufc::tetrahedron;
569
 
  }
570
 
 
571
 
  /// Return the dimension of the finite element function space
572
 
  virtual unsigned int space_dimension() const
573
 
  {
574
 
    return 4;
575
 
  }
576
 
 
577
 
  /// Return the rank of the value space
578
 
  virtual unsigned int value_rank() const
579
 
  {
580
 
    return 0;
581
 
  }
582
 
 
583
 
  /// Return the dimension of the value space for axis i
584
 
  virtual unsigned int value_dimension(unsigned int i) const
585
 
  {
586
 
    return 1;
587
 
  }
588
 
 
589
 
  /// Evaluate basis function i at given point in cell
590
 
  virtual void evaluate_basis(unsigned int i,
591
 
                              double* values,
592
 
                              const double* coordinates,
593
 
                              const ufc::cell& c) const
594
 
  {
595
 
    // Extract vertex coordinates
596
 
    const double * const * element_coordinates = c.coordinates;
597
 
    
598
 
    // Compute Jacobian of affine map from reference cell
599
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
600
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
601
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
602
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
603
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
604
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
605
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
606
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
607
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
608
 
    
609
 
    // Compute sub determinants
610
 
    const double d00 = J_11*J_22 - J_12*J_21;
611
 
    const double d01 = J_12*J_20 - J_10*J_22;
612
 
    const double d02 = J_10*J_21 - J_11*J_20;
613
 
    
614
 
    const double d10 = J_02*J_21 - J_01*J_22;
615
 
    const double d11 = J_00*J_22 - J_02*J_20;
616
 
    const double d12 = J_01*J_20 - J_00*J_21;
617
 
    
618
 
    const double d20 = J_01*J_12 - J_02*J_11;
619
 
    const double d21 = J_02*J_10 - J_00*J_12;
620
 
    const double d22 = J_00*J_11 - J_01*J_10;
621
 
    
622
 
    // Compute determinant of Jacobian
623
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
624
 
    
625
 
    // Compute inverse of Jacobian
626
 
    
627
 
    // Compute constants
628
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
629
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
630
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
631
 
    
632
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
633
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
634
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
635
 
    
636
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
637
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
638
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
639
 
    
640
 
    // Get coordinates and map to the UFC reference element
641
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
642
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
643
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
644
 
    
645
 
    // Map coordinates to the reference cube
646
 
    if (std::abs(y + z - 1.0) < 1e-08)
647
 
      x = 1.0;
648
 
    else
649
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
650
 
    if (std::abs(z - 1.0) < 1e-08)
651
 
      y = -1.0;
652
 
    else
653
 
      y = 2.0 * y/(1.0 - z) - 1.0;
654
 
    z = 2.0 * z - 1.0;
655
 
    
656
 
    // Reset values
657
 
    *values = 0;
658
 
    
659
 
    // Map degree of freedom to element degree of freedom
660
 
    const unsigned int dof = i;
661
 
    
662
 
    // Generate scalings
663
 
    const double scalings_y_0 = 1;
664
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
665
 
    const double scalings_z_0 = 1;
666
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
667
 
    
668
 
    // Compute psitilde_a
669
 
    const double psitilde_a_0 = 1;
670
 
    const double psitilde_a_1 = x;
671
 
    
672
 
    // Compute psitilde_bs
673
 
    const double psitilde_bs_0_0 = 1;
674
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
675
 
    const double psitilde_bs_1_0 = 1;
676
 
    
677
 
    // Compute psitilde_cs
678
 
    const double psitilde_cs_00_0 = 1;
679
 
    const double psitilde_cs_00_1 = 2*z + 1;
680
 
    const double psitilde_cs_01_0 = 1;
681
 
    const double psitilde_cs_10_0 = 1;
682
 
    
683
 
    // Compute basisvalues
684
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
685
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
686
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
687
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
688
 
    
689
 
    // Table(s) of coefficients
690
 
    static const double coefficients0[4][4] = \
691
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
692
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
693
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
694
 
    {0.288675135, 0, 0, 0.223606798}};
695
 
    
696
 
    // Extract relevant coefficients
697
 
    const double coeff0_0 = coefficients0[dof][0];
698
 
    const double coeff0_1 = coefficients0[dof][1];
699
 
    const double coeff0_2 = coefficients0[dof][2];
700
 
    const double coeff0_3 = coefficients0[dof][3];
701
 
    
702
 
    // Compute value(s)
703
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
704
 
  }
705
 
 
706
 
  /// Evaluate all basis functions at given point in cell
707
 
  virtual void evaluate_basis_all(double* values,
708
 
                                  const double* coordinates,
709
 
                                  const ufc::cell& c) const
710
 
  {
711
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
712
 
  }
713
 
 
714
 
  /// Evaluate order n derivatives of basis function i at given point in cell
715
 
  virtual void evaluate_basis_derivatives(unsigned int i,
716
 
                                          unsigned int n,
717
 
                                          double* values,
718
 
                                          const double* coordinates,
719
 
                                          const ufc::cell& c) const
720
 
  {
721
 
    // Extract vertex coordinates
722
 
    const double * const * element_coordinates = c.coordinates;
723
 
    
724
 
    // Compute Jacobian of affine map from reference cell
725
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
726
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
727
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
728
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
729
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
730
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
731
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
732
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
733
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
734
 
    
735
 
    // Compute sub determinants
736
 
    const double d00 = J_11*J_22 - J_12*J_21;
737
 
    const double d01 = J_12*J_20 - J_10*J_22;
738
 
    const double d02 = J_10*J_21 - J_11*J_20;
739
 
    
740
 
    const double d10 = J_02*J_21 - J_01*J_22;
741
 
    const double d11 = J_00*J_22 - J_02*J_20;
742
 
    const double d12 = J_01*J_20 - J_00*J_21;
743
 
    
744
 
    const double d20 = J_01*J_12 - J_02*J_11;
745
 
    const double d21 = J_02*J_10 - J_00*J_12;
746
 
    const double d22 = J_00*J_11 - J_01*J_10;
747
 
    
748
 
    // Compute determinant of Jacobian
749
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
750
 
    
751
 
    // Compute inverse of Jacobian
752
 
    
753
 
    // Compute constants
754
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
755
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
756
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
757
 
    
758
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
759
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
760
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
761
 
    
762
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
763
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
764
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
765
 
    
766
 
    // Get coordinates and map to the UFC reference element
767
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
768
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
769
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
770
 
    
771
 
    // Map coordinates to the reference cube
772
 
    if (std::abs(y + z - 1.0) < 1e-08)
773
 
      x = 1.0;
774
 
    else
775
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
776
 
    if (std::abs(z - 1.0) < 1e-08)
777
 
      y = -1.0;
778
 
    else
779
 
      y = 2.0 * y/(1.0 - z) - 1.0;
780
 
    z = 2.0 * z - 1.0;
781
 
    
782
 
    // Compute number of derivatives
783
 
    unsigned int num_derivatives = 1;
784
 
    
785
 
    for (unsigned int j = 0; j < n; j++)
786
 
      num_derivatives *= 3;
787
 
    
788
 
    
789
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
790
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
791
 
    
792
 
    for (unsigned int j = 0; j < num_derivatives; j++)
793
 
    {
794
 
      combinations[j] = new unsigned int [n];
795
 
      for (unsigned int k = 0; k < n; k++)
796
 
        combinations[j][k] = 0;
797
 
    }
798
 
    
799
 
    // Generate combinations of derivatives
800
 
    for (unsigned int row = 1; row < num_derivatives; row++)
801
 
    {
802
 
      for (unsigned int num = 0; num < row; num++)
803
 
      {
804
 
        for (unsigned int col = n-1; col+1 > 0; col--)
805
 
        {
806
 
          if (combinations[row][col] + 1 > 2)
807
 
            combinations[row][col] = 0;
808
 
          else
809
 
          {
810
 
            combinations[row][col] += 1;
811
 
            break;
812
 
          }
813
 
        }
814
 
      }
815
 
    }
816
 
    
817
 
    // Compute inverse of Jacobian
818
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
819
 
    
820
 
    // Declare transformation matrix
821
 
    // Declare pointer to two dimensional array and initialise
822
 
    double **transform = new double *[num_derivatives];
823
 
    
824
 
    for (unsigned int j = 0; j < num_derivatives; j++)
825
 
    {
826
 
      transform[j] = new double [num_derivatives];
827
 
      for (unsigned int k = 0; k < num_derivatives; k++)
828
 
        transform[j][k] = 1;
829
 
    }
830
 
    
831
 
    // Construct transformation matrix
832
 
    for (unsigned int row = 0; row < num_derivatives; row++)
833
 
    {
834
 
      for (unsigned int col = 0; col < num_derivatives; col++)
835
 
      {
836
 
        for (unsigned int k = 0; k < n; k++)
837
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
838
 
      }
839
 
    }
840
 
    
841
 
    // Reset values
842
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
843
 
      values[j] = 0;
844
 
    
845
 
    // Map degree of freedom to element degree of freedom
846
 
    const unsigned int dof = i;
847
 
    
848
 
    // Generate scalings
849
 
    const double scalings_y_0 = 1;
850
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
851
 
    const double scalings_z_0 = 1;
852
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
853
 
    
854
 
    // Compute psitilde_a
855
 
    const double psitilde_a_0 = 1;
856
 
    const double psitilde_a_1 = x;
857
 
    
858
 
    // Compute psitilde_bs
859
 
    const double psitilde_bs_0_0 = 1;
860
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
861
 
    const double psitilde_bs_1_0 = 1;
862
 
    
863
 
    // Compute psitilde_cs
864
 
    const double psitilde_cs_00_0 = 1;
865
 
    const double psitilde_cs_00_1 = 2*z + 1;
866
 
    const double psitilde_cs_01_0 = 1;
867
 
    const double psitilde_cs_10_0 = 1;
868
 
    
869
 
    // Compute basisvalues
870
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
871
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
872
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
873
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
874
 
    
875
 
    // Table(s) of coefficients
876
 
    static const double coefficients0[4][4] = \
877
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
878
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
879
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
880
 
    {0.288675135, 0, 0, 0.223606798}};
881
 
    
882
 
    // Interesting (new) part
883
 
    // Tables of derivatives of the polynomial base (transpose)
884
 
    static const double dmats0[4][4] = \
885
 
    {{0, 0, 0, 0},
886
 
    {6.32455532, 0, 0, 0},
887
 
    {0, 0, 0, 0},
888
 
    {0, 0, 0, 0}};
889
 
    
890
 
    static const double dmats1[4][4] = \
891
 
    {{0, 0, 0, 0},
892
 
    {3.16227766, 0, 0, 0},
893
 
    {5.47722558, 0, 0, 0},
894
 
    {0, 0, 0, 0}};
895
 
    
896
 
    static const double dmats2[4][4] = \
897
 
    {{0, 0, 0, 0},
898
 
    {3.16227766, 0, 0, 0},
899
 
    {1.82574186, 0, 0, 0},
900
 
    {5.16397779, 0, 0, 0}};
901
 
    
902
 
    // Compute reference derivatives
903
 
    // Declare pointer to array of derivatives on FIAT element
904
 
    double *derivatives = new double [num_derivatives];
905
 
    
906
 
    // Declare coefficients
907
 
    double coeff0_0 = 0;
908
 
    double coeff0_1 = 0;
909
 
    double coeff0_2 = 0;
910
 
    double coeff0_3 = 0;
911
 
    
912
 
    // Declare new coefficients
913
 
    double new_coeff0_0 = 0;
914
 
    double new_coeff0_1 = 0;
915
 
    double new_coeff0_2 = 0;
916
 
    double new_coeff0_3 = 0;
917
 
    
918
 
    // Loop possible derivatives
919
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
920
 
    {
921
 
      // Get values from coefficients array
922
 
      new_coeff0_0 = coefficients0[dof][0];
923
 
      new_coeff0_1 = coefficients0[dof][1];
924
 
      new_coeff0_2 = coefficients0[dof][2];
925
 
      new_coeff0_3 = coefficients0[dof][3];
926
 
    
927
 
      // Loop derivative order
928
 
      for (unsigned int j = 0; j < n; j++)
929
 
      {
930
 
        // Update old coefficients
931
 
        coeff0_0 = new_coeff0_0;
932
 
        coeff0_1 = new_coeff0_1;
933
 
        coeff0_2 = new_coeff0_2;
934
 
        coeff0_3 = new_coeff0_3;
935
 
    
936
 
        if(combinations[deriv_num][j] == 0)
937
 
        {
938
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
939
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
940
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
941
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
942
 
        }
943
 
        if(combinations[deriv_num][j] == 1)
944
 
        {
945
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
946
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
947
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
948
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
949
 
        }
950
 
        if(combinations[deriv_num][j] == 2)
951
 
        {
952
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
953
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
954
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
955
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
956
 
        }
957
 
    
958
 
      }
959
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
960
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
961
 
    }
962
 
    
963
 
    // Transform derivatives back to physical element
964
 
    for (unsigned int row = 0; row < num_derivatives; row++)
965
 
    {
966
 
      for (unsigned int col = 0; col < num_derivatives; col++)
967
 
      {
968
 
        values[row] += transform[row][col]*derivatives[col];
969
 
      }
970
 
    }
971
 
    // Delete pointer to array of derivatives on FIAT element
972
 
    delete [] derivatives;
973
 
    
974
 
    // Delete pointer to array of combinations of derivatives and transform
975
 
    for (unsigned int row = 0; row < num_derivatives; row++)
976
 
    {
977
 
      delete [] combinations[row];
978
 
      delete [] transform[row];
979
 
    }
980
 
    
981
 
    delete [] combinations;
982
 
    delete [] transform;
983
 
  }
984
 
 
985
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
986
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
987
 
                                              double* values,
988
 
                                              const double* coordinates,
989
 
                                              const ufc::cell& c) const
990
 
  {
991
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
992
 
  }
993
 
 
994
 
  /// Evaluate linear functional for dof i on the function f
995
 
  virtual double evaluate_dof(unsigned int i,
996
 
                              const ufc::function& f,
997
 
                              const ufc::cell& c) const
998
 
  {
999
 
    // The reference points, direction and weights:
1000
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
1001
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
1002
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
1003
 
    
1004
 
    const double * const * x = c.coordinates;
1005
 
    double result = 0.0;
1006
 
    // Iterate over the points:
1007
 
    // Evaluate basis functions for affine mapping
1008
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
1009
 
    const double w1 = X[i][0][0];
1010
 
    const double w2 = X[i][0][1];
1011
 
    const double w3 = X[i][0][2];
1012
 
    
1013
 
    // Compute affine mapping y = F(X)
1014
 
    double y[3];
1015
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
1016
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
1017
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
1018
 
    
1019
 
    // Evaluate function at physical points
1020
 
    double values[1];
1021
 
    f.evaluate(values, y, c);
1022
 
    
1023
 
    // Map function values using appropriate mapping
1024
 
    // Affine map: Do nothing
1025
 
    
1026
 
    // Note that we do not map the weights (yet).
1027
 
    
1028
 
    // Take directional components
1029
 
    for(int k = 0; k < 1; k++)
1030
 
      result += values[k]*D[i][0][k];
1031
 
    // Multiply by weights
1032
 
    result *= W[i][0];
1033
 
    
1034
 
    return result;
1035
 
  }
1036
 
 
1037
 
  /// Evaluate linear functionals for all dofs on the function f
1038
 
  virtual void evaluate_dofs(double* values,
1039
 
                             const ufc::function& f,
1040
 
                             const ufc::cell& c) const
1041
 
  {
1042
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1043
 
  }
1044
 
 
1045
 
  /// Interpolate vertex values from dof values
1046
 
  virtual void interpolate_vertex_values(double* vertex_values,
1047
 
                                         const double* dof_values,
1048
 
                                         const ufc::cell& c) const
1049
 
  {
1050
 
    // Evaluate at vertices and use affine mapping
1051
 
    vertex_values[0] = dof_values[0];
1052
 
    vertex_values[1] = dof_values[1];
1053
 
    vertex_values[2] = dof_values[2];
1054
 
    vertex_values[3] = dof_values[3];
1055
 
  }
1056
 
 
1057
 
  /// Return the number of sub elements (for a mixed element)
1058
 
  virtual unsigned int num_sub_elements() const
1059
 
  {
1060
 
    return 1;
1061
 
  }
1062
 
 
1063
 
  /// Create a new finite element for sub element i (for a mixed element)
1064
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
1065
 
  {
1066
 
    return new hyperelasticity_0_finite_element_0_1();
1067
 
  }
1068
 
 
1069
 
};
1070
 
 
1071
 
/// This class defines the interface for a finite element.
1072
 
 
1073
 
class hyperelasticity_0_finite_element_0_2: public ufc::finite_element
1074
 
{
1075
 
public:
1076
 
 
1077
 
  /// Constructor
1078
 
  hyperelasticity_0_finite_element_0_2() : ufc::finite_element()
1079
 
  {
1080
 
    // Do nothing
1081
 
  }
1082
 
 
1083
 
  /// Destructor
1084
 
  virtual ~hyperelasticity_0_finite_element_0_2()
1085
 
  {
1086
 
    // Do nothing
1087
 
  }
1088
 
 
1089
 
  /// Return a string identifying the finite element
1090
 
  virtual const char* signature() const
1091
 
  {
1092
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
1093
 
  }
1094
 
 
1095
 
  /// Return the cell shape
1096
 
  virtual ufc::shape cell_shape() const
1097
 
  {
1098
 
    return ufc::tetrahedron;
1099
 
  }
1100
 
 
1101
 
  /// Return the dimension of the finite element function space
1102
 
  virtual unsigned int space_dimension() const
1103
 
  {
1104
 
    return 4;
1105
 
  }
1106
 
 
1107
 
  /// Return the rank of the value space
1108
 
  virtual unsigned int value_rank() const
1109
 
  {
1110
 
    return 0;
1111
 
  }
1112
 
 
1113
 
  /// Return the dimension of the value space for axis i
1114
 
  virtual unsigned int value_dimension(unsigned int i) const
1115
 
  {
1116
 
    return 1;
1117
 
  }
1118
 
 
1119
 
  /// Evaluate basis function i at given point in cell
1120
 
  virtual void evaluate_basis(unsigned int i,
1121
 
                              double* values,
1122
 
                              const double* coordinates,
1123
 
                              const ufc::cell& c) const
1124
 
  {
1125
 
    // Extract vertex coordinates
1126
 
    const double * const * element_coordinates = c.coordinates;
1127
 
    
1128
 
    // Compute Jacobian of affine map from reference cell
1129
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1130
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1131
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1132
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1133
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1134
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1135
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1136
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1137
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1138
 
    
1139
 
    // Compute sub determinants
1140
 
    const double d00 = J_11*J_22 - J_12*J_21;
1141
 
    const double d01 = J_12*J_20 - J_10*J_22;
1142
 
    const double d02 = J_10*J_21 - J_11*J_20;
1143
 
    
1144
 
    const double d10 = J_02*J_21 - J_01*J_22;
1145
 
    const double d11 = J_00*J_22 - J_02*J_20;
1146
 
    const double d12 = J_01*J_20 - J_00*J_21;
1147
 
    
1148
 
    const double d20 = J_01*J_12 - J_02*J_11;
1149
 
    const double d21 = J_02*J_10 - J_00*J_12;
1150
 
    const double d22 = J_00*J_11 - J_01*J_10;
1151
 
    
1152
 
    // Compute determinant of Jacobian
1153
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1154
 
    
1155
 
    // Compute inverse of Jacobian
1156
 
    
1157
 
    // Compute constants
1158
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1159
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1160
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1161
 
    
1162
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1163
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1164
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1165
 
    
1166
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1167
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1168
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1169
 
    
1170
 
    // Get coordinates and map to the UFC reference element
1171
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1172
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1173
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1174
 
    
1175
 
    // Map coordinates to the reference cube
1176
 
    if (std::abs(y + z - 1.0) < 1e-08)
1177
 
      x = 1.0;
1178
 
    else
1179
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
1180
 
    if (std::abs(z - 1.0) < 1e-08)
1181
 
      y = -1.0;
1182
 
    else
1183
 
      y = 2.0 * y/(1.0 - z) - 1.0;
1184
 
    z = 2.0 * z - 1.0;
1185
 
    
1186
 
    // Reset values
1187
 
    *values = 0;
1188
 
    
1189
 
    // Map degree of freedom to element degree of freedom
1190
 
    const unsigned int dof = i;
1191
 
    
1192
 
    // Generate scalings
1193
 
    const double scalings_y_0 = 1;
1194
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1195
 
    const double scalings_z_0 = 1;
1196
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1197
 
    
1198
 
    // Compute psitilde_a
1199
 
    const double psitilde_a_0 = 1;
1200
 
    const double psitilde_a_1 = x;
1201
 
    
1202
 
    // Compute psitilde_bs
1203
 
    const double psitilde_bs_0_0 = 1;
1204
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
1205
 
    const double psitilde_bs_1_0 = 1;
1206
 
    
1207
 
    // Compute psitilde_cs
1208
 
    const double psitilde_cs_00_0 = 1;
1209
 
    const double psitilde_cs_00_1 = 2*z + 1;
1210
 
    const double psitilde_cs_01_0 = 1;
1211
 
    const double psitilde_cs_10_0 = 1;
1212
 
    
1213
 
    // Compute basisvalues
1214
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1215
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1216
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1217
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1218
 
    
1219
 
    // Table(s) of coefficients
1220
 
    static const double coefficients0[4][4] = \
1221
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
1222
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
1223
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
1224
 
    {0.288675135, 0, 0, 0.223606798}};
1225
 
    
1226
 
    // Extract relevant coefficients
1227
 
    const double coeff0_0 = coefficients0[dof][0];
1228
 
    const double coeff0_1 = coefficients0[dof][1];
1229
 
    const double coeff0_2 = coefficients0[dof][2];
1230
 
    const double coeff0_3 = coefficients0[dof][3];
1231
 
    
1232
 
    // Compute value(s)
1233
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1234
 
  }
1235
 
 
1236
 
  /// Evaluate all basis functions at given point in cell
1237
 
  virtual void evaluate_basis_all(double* values,
1238
 
                                  const double* coordinates,
1239
 
                                  const ufc::cell& c) const
1240
 
  {
1241
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
1242
 
  }
1243
 
 
1244
 
  /// Evaluate order n derivatives of basis function i at given point in cell
1245
 
  virtual void evaluate_basis_derivatives(unsigned int i,
1246
 
                                          unsigned int n,
1247
 
                                          double* values,
1248
 
                                          const double* coordinates,
1249
 
                                          const ufc::cell& c) const
1250
 
  {
1251
 
    // Extract vertex coordinates
1252
 
    const double * const * element_coordinates = c.coordinates;
1253
 
    
1254
 
    // Compute Jacobian of affine map from reference cell
1255
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1256
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1257
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1258
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1259
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1260
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1261
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1262
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1263
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1264
 
    
1265
 
    // Compute sub determinants
1266
 
    const double d00 = J_11*J_22 - J_12*J_21;
1267
 
    const double d01 = J_12*J_20 - J_10*J_22;
1268
 
    const double d02 = J_10*J_21 - J_11*J_20;
1269
 
    
1270
 
    const double d10 = J_02*J_21 - J_01*J_22;
1271
 
    const double d11 = J_00*J_22 - J_02*J_20;
1272
 
    const double d12 = J_01*J_20 - J_00*J_21;
1273
 
    
1274
 
    const double d20 = J_01*J_12 - J_02*J_11;
1275
 
    const double d21 = J_02*J_10 - J_00*J_12;
1276
 
    const double d22 = J_00*J_11 - J_01*J_10;
1277
 
    
1278
 
    // Compute determinant of Jacobian
1279
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1280
 
    
1281
 
    // Compute inverse of Jacobian
1282
 
    
1283
 
    // Compute constants
1284
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1285
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1286
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1287
 
    
1288
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1289
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1290
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1291
 
    
1292
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1293
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1294
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1295
 
    
1296
 
    // Get coordinates and map to the UFC reference element
1297
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1298
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1299
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1300
 
    
1301
 
    // Map coordinates to the reference cube
1302
 
    if (std::abs(y + z - 1.0) < 1e-08)
1303
 
      x = 1.0;
1304
 
    else
1305
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
1306
 
    if (std::abs(z - 1.0) < 1e-08)
1307
 
      y = -1.0;
1308
 
    else
1309
 
      y = 2.0 * y/(1.0 - z) - 1.0;
1310
 
    z = 2.0 * z - 1.0;
1311
 
    
1312
 
    // Compute number of derivatives
1313
 
    unsigned int num_derivatives = 1;
1314
 
    
1315
 
    for (unsigned int j = 0; j < n; j++)
1316
 
      num_derivatives *= 3;
1317
 
    
1318
 
    
1319
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
1320
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
1321
 
    
1322
 
    for (unsigned int j = 0; j < num_derivatives; j++)
1323
 
    {
1324
 
      combinations[j] = new unsigned int [n];
1325
 
      for (unsigned int k = 0; k < n; k++)
1326
 
        combinations[j][k] = 0;
1327
 
    }
1328
 
    
1329
 
    // Generate combinations of derivatives
1330
 
    for (unsigned int row = 1; row < num_derivatives; row++)
1331
 
    {
1332
 
      for (unsigned int num = 0; num < row; num++)
1333
 
      {
1334
 
        for (unsigned int col = n-1; col+1 > 0; col--)
1335
 
        {
1336
 
          if (combinations[row][col] + 1 > 2)
1337
 
            combinations[row][col] = 0;
1338
 
          else
1339
 
          {
1340
 
            combinations[row][col] += 1;
1341
 
            break;
1342
 
          }
1343
 
        }
1344
 
      }
1345
 
    }
1346
 
    
1347
 
    // Compute inverse of Jacobian
1348
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
1349
 
    
1350
 
    // Declare transformation matrix
1351
 
    // Declare pointer to two dimensional array and initialise
1352
 
    double **transform = new double *[num_derivatives];
1353
 
    
1354
 
    for (unsigned int j = 0; j < num_derivatives; j++)
1355
 
    {
1356
 
      transform[j] = new double [num_derivatives];
1357
 
      for (unsigned int k = 0; k < num_derivatives; k++)
1358
 
        transform[j][k] = 1;
1359
 
    }
1360
 
    
1361
 
    // Construct transformation matrix
1362
 
    for (unsigned int row = 0; row < num_derivatives; row++)
1363
 
    {
1364
 
      for (unsigned int col = 0; col < num_derivatives; col++)
1365
 
      {
1366
 
        for (unsigned int k = 0; k < n; k++)
1367
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
1368
 
      }
1369
 
    }
1370
 
    
1371
 
    // Reset values
1372
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
1373
 
      values[j] = 0;
1374
 
    
1375
 
    // Map degree of freedom to element degree of freedom
1376
 
    const unsigned int dof = i;
1377
 
    
1378
 
    // Generate scalings
1379
 
    const double scalings_y_0 = 1;
1380
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1381
 
    const double scalings_z_0 = 1;
1382
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1383
 
    
1384
 
    // Compute psitilde_a
1385
 
    const double psitilde_a_0 = 1;
1386
 
    const double psitilde_a_1 = x;
1387
 
    
1388
 
    // Compute psitilde_bs
1389
 
    const double psitilde_bs_0_0 = 1;
1390
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
1391
 
    const double psitilde_bs_1_0 = 1;
1392
 
    
1393
 
    // Compute psitilde_cs
1394
 
    const double psitilde_cs_00_0 = 1;
1395
 
    const double psitilde_cs_00_1 = 2*z + 1;
1396
 
    const double psitilde_cs_01_0 = 1;
1397
 
    const double psitilde_cs_10_0 = 1;
1398
 
    
1399
 
    // Compute basisvalues
1400
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1401
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1402
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1403
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1404
 
    
1405
 
    // Table(s) of coefficients
1406
 
    static const double coefficients0[4][4] = \
1407
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
1408
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
1409
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
1410
 
    {0.288675135, 0, 0, 0.223606798}};
1411
 
    
1412
 
    // Interesting (new) part
1413
 
    // Tables of derivatives of the polynomial base (transpose)
1414
 
    static const double dmats0[4][4] = \
1415
 
    {{0, 0, 0, 0},
1416
 
    {6.32455532, 0, 0, 0},
1417
 
    {0, 0, 0, 0},
1418
 
    {0, 0, 0, 0}};
1419
 
    
1420
 
    static const double dmats1[4][4] = \
1421
 
    {{0, 0, 0, 0},
1422
 
    {3.16227766, 0, 0, 0},
1423
 
    {5.47722558, 0, 0, 0},
1424
 
    {0, 0, 0, 0}};
1425
 
    
1426
 
    static const double dmats2[4][4] = \
1427
 
    {{0, 0, 0, 0},
1428
 
    {3.16227766, 0, 0, 0},
1429
 
    {1.82574186, 0, 0, 0},
1430
 
    {5.16397779, 0, 0, 0}};
1431
 
    
1432
 
    // Compute reference derivatives
1433
 
    // Declare pointer to array of derivatives on FIAT element
1434
 
    double *derivatives = new double [num_derivatives];
1435
 
    
1436
 
    // Declare coefficients
1437
 
    double coeff0_0 = 0;
1438
 
    double coeff0_1 = 0;
1439
 
    double coeff0_2 = 0;
1440
 
    double coeff0_3 = 0;
1441
 
    
1442
 
    // Declare new coefficients
1443
 
    double new_coeff0_0 = 0;
1444
 
    double new_coeff0_1 = 0;
1445
 
    double new_coeff0_2 = 0;
1446
 
    double new_coeff0_3 = 0;
1447
 
    
1448
 
    // Loop possible derivatives
1449
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
1450
 
    {
1451
 
      // Get values from coefficients array
1452
 
      new_coeff0_0 = coefficients0[dof][0];
1453
 
      new_coeff0_1 = coefficients0[dof][1];
1454
 
      new_coeff0_2 = coefficients0[dof][2];
1455
 
      new_coeff0_3 = coefficients0[dof][3];
1456
 
    
1457
 
      // Loop derivative order
1458
 
      for (unsigned int j = 0; j < n; j++)
1459
 
      {
1460
 
        // Update old coefficients
1461
 
        coeff0_0 = new_coeff0_0;
1462
 
        coeff0_1 = new_coeff0_1;
1463
 
        coeff0_2 = new_coeff0_2;
1464
 
        coeff0_3 = new_coeff0_3;
1465
 
    
1466
 
        if(combinations[deriv_num][j] == 0)
1467
 
        {
1468
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
1469
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
1470
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
1471
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
1472
 
        }
1473
 
        if(combinations[deriv_num][j] == 1)
1474
 
        {
1475
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
1476
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
1477
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
1478
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
1479
 
        }
1480
 
        if(combinations[deriv_num][j] == 2)
1481
 
        {
1482
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
1483
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
1484
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
1485
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
1486
 
        }
1487
 
    
1488
 
      }
1489
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
1490
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
1491
 
    }
1492
 
    
1493
 
    // Transform derivatives back to physical element
1494
 
    for (unsigned int row = 0; row < num_derivatives; row++)
1495
 
    {
1496
 
      for (unsigned int col = 0; col < num_derivatives; col++)
1497
 
      {
1498
 
        values[row] += transform[row][col]*derivatives[col];
1499
 
      }
1500
 
    }
1501
 
    // Delete pointer to array of derivatives on FIAT element
1502
 
    delete [] derivatives;
1503
 
    
1504
 
    // Delete pointer to array of combinations of derivatives and transform
1505
 
    for (unsigned int row = 0; row < num_derivatives; row++)
1506
 
    {
1507
 
      delete [] combinations[row];
1508
 
      delete [] transform[row];
1509
 
    }
1510
 
    
1511
 
    delete [] combinations;
1512
 
    delete [] transform;
1513
 
  }
1514
 
 
1515
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
1516
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
1517
 
                                              double* values,
1518
 
                                              const double* coordinates,
1519
 
                                              const ufc::cell& c) const
1520
 
  {
1521
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
1522
 
  }
1523
 
 
1524
 
  /// Evaluate linear functional for dof i on the function f
1525
 
  virtual double evaluate_dof(unsigned int i,
1526
 
                              const ufc::function& f,
1527
 
                              const ufc::cell& c) const
1528
 
  {
1529
 
    // The reference points, direction and weights:
1530
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
1531
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
1532
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
1533
 
    
1534
 
    const double * const * x = c.coordinates;
1535
 
    double result = 0.0;
1536
 
    // Iterate over the points:
1537
 
    // Evaluate basis functions for affine mapping
1538
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
1539
 
    const double w1 = X[i][0][0];
1540
 
    const double w2 = X[i][0][1];
1541
 
    const double w3 = X[i][0][2];
1542
 
    
1543
 
    // Compute affine mapping y = F(X)
1544
 
    double y[3];
1545
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
1546
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
1547
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
1548
 
    
1549
 
    // Evaluate function at physical points
1550
 
    double values[1];
1551
 
    f.evaluate(values, y, c);
1552
 
    
1553
 
    // Map function values using appropriate mapping
1554
 
    // Affine map: Do nothing
1555
 
    
1556
 
    // Note that we do not map the weights (yet).
1557
 
    
1558
 
    // Take directional components
1559
 
    for(int k = 0; k < 1; k++)
1560
 
      result += values[k]*D[i][0][k];
1561
 
    // Multiply by weights
1562
 
    result *= W[i][0];
1563
 
    
1564
 
    return result;
1565
 
  }
1566
 
 
1567
 
  /// Evaluate linear functionals for all dofs on the function f
1568
 
  virtual void evaluate_dofs(double* values,
1569
 
                             const ufc::function& f,
1570
 
                             const ufc::cell& c) const
1571
 
  {
1572
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1573
 
  }
1574
 
 
1575
 
  /// Interpolate vertex values from dof values
1576
 
  virtual void interpolate_vertex_values(double* vertex_values,
1577
 
                                         const double* dof_values,
1578
 
                                         const ufc::cell& c) const
1579
 
  {
1580
 
    // Evaluate at vertices and use affine mapping
1581
 
    vertex_values[0] = dof_values[0];
1582
 
    vertex_values[1] = dof_values[1];
1583
 
    vertex_values[2] = dof_values[2];
1584
 
    vertex_values[3] = dof_values[3];
1585
 
  }
1586
 
 
1587
 
  /// Return the number of sub elements (for a mixed element)
1588
 
  virtual unsigned int num_sub_elements() const
1589
 
  {
1590
 
    return 1;
1591
 
  }
1592
 
 
1593
 
  /// Create a new finite element for sub element i (for a mixed element)
1594
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
1595
 
  {
1596
 
    return new hyperelasticity_0_finite_element_0_2();
1597
 
  }
1598
 
 
1599
 
};
1600
 
 
1601
 
/// This class defines the interface for a finite element.
1602
 
 
1603
 
class hyperelasticity_0_finite_element_0: public ufc::finite_element
1604
 
{
1605
 
public:
1606
 
 
1607
 
  /// Constructor
1608
 
  hyperelasticity_0_finite_element_0() : ufc::finite_element()
1609
 
  {
1610
 
    // Do nothing
1611
 
  }
1612
 
 
1613
 
  /// Destructor
1614
 
  virtual ~hyperelasticity_0_finite_element_0()
1615
 
  {
1616
 
    // Do nothing
1617
 
  }
1618
 
 
1619
 
  /// Return a string identifying the finite element
1620
 
  virtual const char* signature() const
1621
 
  {
1622
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
1623
 
  }
1624
 
 
1625
 
  /// Return the cell shape
1626
 
  virtual ufc::shape cell_shape() const
1627
 
  {
1628
 
    return ufc::tetrahedron;
1629
 
  }
1630
 
 
1631
 
  /// Return the dimension of the finite element function space
1632
 
  virtual unsigned int space_dimension() const
1633
 
  {
1634
 
    return 12;
1635
 
  }
1636
 
 
1637
 
  /// Return the rank of the value space
1638
 
  virtual unsigned int value_rank() const
1639
 
  {
1640
 
    return 1;
1641
 
  }
1642
 
 
1643
 
  /// Return the dimension of the value space for axis i
1644
 
  virtual unsigned int value_dimension(unsigned int i) const
1645
 
  {
1646
 
    return 3;
1647
 
  }
1648
 
 
1649
 
  /// Evaluate basis function i at given point in cell
1650
 
  virtual void evaluate_basis(unsigned int i,
1651
 
                              double* values,
1652
 
                              const double* coordinates,
1653
 
                              const ufc::cell& c) const
1654
 
  {
1655
 
    // Extract vertex coordinates
1656
 
    const double * const * element_coordinates = c.coordinates;
1657
 
    
1658
 
    // Compute Jacobian of affine map from reference cell
1659
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1660
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1661
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1662
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1663
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1664
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1665
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1666
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1667
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1668
 
    
1669
 
    // Compute sub determinants
1670
 
    const double d00 = J_11*J_22 - J_12*J_21;
1671
 
    const double d01 = J_12*J_20 - J_10*J_22;
1672
 
    const double d02 = J_10*J_21 - J_11*J_20;
1673
 
    
1674
 
    const double d10 = J_02*J_21 - J_01*J_22;
1675
 
    const double d11 = J_00*J_22 - J_02*J_20;
1676
 
    const double d12 = J_01*J_20 - J_00*J_21;
1677
 
    
1678
 
    const double d20 = J_01*J_12 - J_02*J_11;
1679
 
    const double d21 = J_02*J_10 - J_00*J_12;
1680
 
    const double d22 = J_00*J_11 - J_01*J_10;
1681
 
    
1682
 
    // Compute determinant of Jacobian
1683
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1684
 
    
1685
 
    // Compute inverse of Jacobian
1686
 
    
1687
 
    // Compute constants
1688
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1689
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1690
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1691
 
    
1692
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1693
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1694
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1695
 
    
1696
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1697
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1698
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1699
 
    
1700
 
    // Get coordinates and map to the UFC reference element
1701
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1702
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1703
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1704
 
    
1705
 
    // Map coordinates to the reference cube
1706
 
    if (std::abs(y + z - 1.0) < 1e-08)
1707
 
      x = 1.0;
1708
 
    else
1709
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
1710
 
    if (std::abs(z - 1.0) < 1e-08)
1711
 
      y = -1.0;
1712
 
    else
1713
 
      y = 2.0 * y/(1.0 - z) - 1.0;
1714
 
    z = 2.0 * z - 1.0;
1715
 
    
1716
 
    // Reset values
1717
 
    values[0] = 0;
1718
 
    values[1] = 0;
1719
 
    values[2] = 0;
1720
 
    
1721
 
    if (0 <= i && i <= 3)
1722
 
    {
1723
 
      // Map degree of freedom to element degree of freedom
1724
 
      const unsigned int dof = i;
1725
 
    
1726
 
      // Generate scalings
1727
 
      const double scalings_y_0 = 1;
1728
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1729
 
      const double scalings_z_0 = 1;
1730
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1731
 
    
1732
 
      // Compute psitilde_a
1733
 
      const double psitilde_a_0 = 1;
1734
 
      const double psitilde_a_1 = x;
1735
 
    
1736
 
      // Compute psitilde_bs
1737
 
      const double psitilde_bs_0_0 = 1;
1738
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
1739
 
      const double psitilde_bs_1_0 = 1;
1740
 
    
1741
 
      // Compute psitilde_cs
1742
 
      const double psitilde_cs_00_0 = 1;
1743
 
      const double psitilde_cs_00_1 = 2*z + 1;
1744
 
      const double psitilde_cs_01_0 = 1;
1745
 
      const double psitilde_cs_10_0 = 1;
1746
 
    
1747
 
      // Compute basisvalues
1748
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1749
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1750
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1751
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1752
 
    
1753
 
      // Table(s) of coefficients
1754
 
      static const double coefficients0[4][4] =   \
1755
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
1756
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
1757
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
1758
 
      {0.288675135, 0, 0, 0.223606798}};
1759
 
    
1760
 
      // Extract relevant coefficients
1761
 
      const double coeff0_0 =   coefficients0[dof][0];
1762
 
      const double coeff0_1 =   coefficients0[dof][1];
1763
 
      const double coeff0_2 =   coefficients0[dof][2];
1764
 
      const double coeff0_3 =   coefficients0[dof][3];
1765
 
    
1766
 
      // Compute value(s)
1767
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1768
 
    }
1769
 
    
1770
 
    if (4 <= i && i <= 7)
1771
 
    {
1772
 
      // Map degree of freedom to element degree of freedom
1773
 
      const unsigned int dof = i - 4;
1774
 
    
1775
 
      // Generate scalings
1776
 
      const double scalings_y_0 = 1;
1777
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1778
 
      const double scalings_z_0 = 1;
1779
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1780
 
    
1781
 
      // Compute psitilde_a
1782
 
      const double psitilde_a_0 = 1;
1783
 
      const double psitilde_a_1 = x;
1784
 
    
1785
 
      // Compute psitilde_bs
1786
 
      const double psitilde_bs_0_0 = 1;
1787
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
1788
 
      const double psitilde_bs_1_0 = 1;
1789
 
    
1790
 
      // Compute psitilde_cs
1791
 
      const double psitilde_cs_00_0 = 1;
1792
 
      const double psitilde_cs_00_1 = 2*z + 1;
1793
 
      const double psitilde_cs_01_0 = 1;
1794
 
      const double psitilde_cs_10_0 = 1;
1795
 
    
1796
 
      // Compute basisvalues
1797
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1798
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1799
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1800
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1801
 
    
1802
 
      // Table(s) of coefficients
1803
 
      static const double coefficients0[4][4] =   \
1804
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
1805
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
1806
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
1807
 
      {0.288675135, 0, 0, 0.223606798}};
1808
 
    
1809
 
      // Extract relevant coefficients
1810
 
      const double coeff0_0 =   coefficients0[dof][0];
1811
 
      const double coeff0_1 =   coefficients0[dof][1];
1812
 
      const double coeff0_2 =   coefficients0[dof][2];
1813
 
      const double coeff0_3 =   coefficients0[dof][3];
1814
 
    
1815
 
      // Compute value(s)
1816
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1817
 
    }
1818
 
    
1819
 
    if (8 <= i && i <= 11)
1820
 
    {
1821
 
      // Map degree of freedom to element degree of freedom
1822
 
      const unsigned int dof = i - 8;
1823
 
    
1824
 
      // Generate scalings
1825
 
      const double scalings_y_0 = 1;
1826
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1827
 
      const double scalings_z_0 = 1;
1828
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1829
 
    
1830
 
      // Compute psitilde_a
1831
 
      const double psitilde_a_0 = 1;
1832
 
      const double psitilde_a_1 = x;
1833
 
    
1834
 
      // Compute psitilde_bs
1835
 
      const double psitilde_bs_0_0 = 1;
1836
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
1837
 
      const double psitilde_bs_1_0 = 1;
1838
 
    
1839
 
      // Compute psitilde_cs
1840
 
      const double psitilde_cs_00_0 = 1;
1841
 
      const double psitilde_cs_00_1 = 2*z + 1;
1842
 
      const double psitilde_cs_01_0 = 1;
1843
 
      const double psitilde_cs_10_0 = 1;
1844
 
    
1845
 
      // Compute basisvalues
1846
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1847
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1848
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1849
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1850
 
    
1851
 
      // Table(s) of coefficients
1852
 
      static const double coefficients0[4][4] =   \
1853
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
1854
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
1855
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
1856
 
      {0.288675135, 0, 0, 0.223606798}};
1857
 
    
1858
 
      // Extract relevant coefficients
1859
 
      const double coeff0_0 =   coefficients0[dof][0];
1860
 
      const double coeff0_1 =   coefficients0[dof][1];
1861
 
      const double coeff0_2 =   coefficients0[dof][2];
1862
 
      const double coeff0_3 =   coefficients0[dof][3];
1863
 
    
1864
 
      // Compute value(s)
1865
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1866
 
    }
1867
 
    
1868
 
  }
1869
 
 
1870
 
  /// Evaluate all basis functions at given point in cell
1871
 
  virtual void evaluate_basis_all(double* values,
1872
 
                                  const double* coordinates,
1873
 
                                  const ufc::cell& c) const
1874
 
  {
1875
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
1876
 
  }
1877
 
 
1878
 
  /// Evaluate order n derivatives of basis function i at given point in cell
1879
 
  virtual void evaluate_basis_derivatives(unsigned int i,
1880
 
                                          unsigned int n,
1881
 
                                          double* values,
1882
 
                                          const double* coordinates,
1883
 
                                          const ufc::cell& c) const
1884
 
  {
1885
 
    // Extract vertex coordinates
1886
 
    const double * const * element_coordinates = c.coordinates;
1887
 
    
1888
 
    // Compute Jacobian of affine map from reference cell
1889
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1890
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1891
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1892
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1893
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1894
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1895
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1896
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1897
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1898
 
    
1899
 
    // Compute sub determinants
1900
 
    const double d00 = J_11*J_22 - J_12*J_21;
1901
 
    const double d01 = J_12*J_20 - J_10*J_22;
1902
 
    const double d02 = J_10*J_21 - J_11*J_20;
1903
 
    
1904
 
    const double d10 = J_02*J_21 - J_01*J_22;
1905
 
    const double d11 = J_00*J_22 - J_02*J_20;
1906
 
    const double d12 = J_01*J_20 - J_00*J_21;
1907
 
    
1908
 
    const double d20 = J_01*J_12 - J_02*J_11;
1909
 
    const double d21 = J_02*J_10 - J_00*J_12;
1910
 
    const double d22 = J_00*J_11 - J_01*J_10;
1911
 
    
1912
 
    // Compute determinant of Jacobian
1913
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1914
 
    
1915
 
    // Compute inverse of Jacobian
1916
 
    
1917
 
    // Compute constants
1918
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1919
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1920
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1921
 
    
1922
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1923
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1924
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1925
 
    
1926
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1927
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1928
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1929
 
    
1930
 
    // Get coordinates and map to the UFC reference element
1931
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1932
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1933
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1934
 
    
1935
 
    // Map coordinates to the reference cube
1936
 
    if (std::abs(y + z - 1.0) < 1e-08)
1937
 
      x = 1.0;
1938
 
    else
1939
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
1940
 
    if (std::abs(z - 1.0) < 1e-08)
1941
 
      y = -1.0;
1942
 
    else
1943
 
      y = 2.0 * y/(1.0 - z) - 1.0;
1944
 
    z = 2.0 * z - 1.0;
1945
 
    
1946
 
    // Compute number of derivatives
1947
 
    unsigned int num_derivatives = 1;
1948
 
    
1949
 
    for (unsigned int j = 0; j < n; j++)
1950
 
      num_derivatives *= 3;
1951
 
    
1952
 
    
1953
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
1954
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
1955
 
    
1956
 
    for (unsigned int j = 0; j < num_derivatives; j++)
1957
 
    {
1958
 
      combinations[j] = new unsigned int [n];
1959
 
      for (unsigned int k = 0; k < n; k++)
1960
 
        combinations[j][k] = 0;
1961
 
    }
1962
 
    
1963
 
    // Generate combinations of derivatives
1964
 
    for (unsigned int row = 1; row < num_derivatives; row++)
1965
 
    {
1966
 
      for (unsigned int num = 0; num < row; num++)
1967
 
      {
1968
 
        for (unsigned int col = n-1; col+1 > 0; col--)
1969
 
        {
1970
 
          if (combinations[row][col] + 1 > 2)
1971
 
            combinations[row][col] = 0;
1972
 
          else
1973
 
          {
1974
 
            combinations[row][col] += 1;
1975
 
            break;
1976
 
          }
1977
 
        }
1978
 
      }
1979
 
    }
1980
 
    
1981
 
    // Compute inverse of Jacobian
1982
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
1983
 
    
1984
 
    // Declare transformation matrix
1985
 
    // Declare pointer to two dimensional array and initialise
1986
 
    double **transform = new double *[num_derivatives];
1987
 
    
1988
 
    for (unsigned int j = 0; j < num_derivatives; j++)
1989
 
    {
1990
 
      transform[j] = new double [num_derivatives];
1991
 
      for (unsigned int k = 0; k < num_derivatives; k++)
1992
 
        transform[j][k] = 1;
1993
 
    }
1994
 
    
1995
 
    // Construct transformation matrix
1996
 
    for (unsigned int row = 0; row < num_derivatives; row++)
1997
 
    {
1998
 
      for (unsigned int col = 0; col < num_derivatives; col++)
1999
 
      {
2000
 
        for (unsigned int k = 0; k < n; k++)
2001
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
2002
 
      }
2003
 
    }
2004
 
    
2005
 
    // Reset values
2006
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
2007
 
      values[j] = 0;
2008
 
    
2009
 
    if (0 <= i && i <= 3)
2010
 
    {
2011
 
      // Map degree of freedom to element degree of freedom
2012
 
      const unsigned int dof = i;
2013
 
    
2014
 
      // Generate scalings
2015
 
      const double scalings_y_0 = 1;
2016
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2017
 
      const double scalings_z_0 = 1;
2018
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2019
 
    
2020
 
      // Compute psitilde_a
2021
 
      const double psitilde_a_0 = 1;
2022
 
      const double psitilde_a_1 = x;
2023
 
    
2024
 
      // Compute psitilde_bs
2025
 
      const double psitilde_bs_0_0 = 1;
2026
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
2027
 
      const double psitilde_bs_1_0 = 1;
2028
 
    
2029
 
      // Compute psitilde_cs
2030
 
      const double psitilde_cs_00_0 = 1;
2031
 
      const double psitilde_cs_00_1 = 2*z + 1;
2032
 
      const double psitilde_cs_01_0 = 1;
2033
 
      const double psitilde_cs_10_0 = 1;
2034
 
    
2035
 
      // Compute basisvalues
2036
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2037
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2038
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2039
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2040
 
    
2041
 
      // Table(s) of coefficients
2042
 
      static const double coefficients0[4][4] =   \
2043
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
2044
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
2045
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
2046
 
      {0.288675135, 0, 0, 0.223606798}};
2047
 
    
2048
 
      // Interesting (new) part
2049
 
      // Tables of derivatives of the polynomial base (transpose)
2050
 
      static const double dmats0[4][4] =   \
2051
 
      {{0, 0, 0, 0},
2052
 
      {6.32455532, 0, 0, 0},
2053
 
      {0, 0, 0, 0},
2054
 
      {0, 0, 0, 0}};
2055
 
    
2056
 
      static const double dmats1[4][4] =   \
2057
 
      {{0, 0, 0, 0},
2058
 
      {3.16227766, 0, 0, 0},
2059
 
      {5.47722558, 0, 0, 0},
2060
 
      {0, 0, 0, 0}};
2061
 
    
2062
 
      static const double dmats2[4][4] =   \
2063
 
      {{0, 0, 0, 0},
2064
 
      {3.16227766, 0, 0, 0},
2065
 
      {1.82574186, 0, 0, 0},
2066
 
      {5.16397779, 0, 0, 0}};
2067
 
    
2068
 
      // Compute reference derivatives
2069
 
      // Declare pointer to array of derivatives on FIAT element
2070
 
      double *derivatives = new double [num_derivatives];
2071
 
    
2072
 
      // Declare coefficients
2073
 
      double coeff0_0 = 0;
2074
 
      double coeff0_1 = 0;
2075
 
      double coeff0_2 = 0;
2076
 
      double coeff0_3 = 0;
2077
 
    
2078
 
      // Declare new coefficients
2079
 
      double new_coeff0_0 = 0;
2080
 
      double new_coeff0_1 = 0;
2081
 
      double new_coeff0_2 = 0;
2082
 
      double new_coeff0_3 = 0;
2083
 
    
2084
 
      // Loop possible derivatives
2085
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2086
 
      {
2087
 
        // Get values from coefficients array
2088
 
        new_coeff0_0 = coefficients0[dof][0];
2089
 
        new_coeff0_1 = coefficients0[dof][1];
2090
 
        new_coeff0_2 = coefficients0[dof][2];
2091
 
        new_coeff0_3 = coefficients0[dof][3];
2092
 
    
2093
 
        // Loop derivative order
2094
 
        for (unsigned int j = 0; j < n; j++)
2095
 
        {
2096
 
          // Update old coefficients
2097
 
          coeff0_0 = new_coeff0_0;
2098
 
          coeff0_1 = new_coeff0_1;
2099
 
          coeff0_2 = new_coeff0_2;
2100
 
          coeff0_3 = new_coeff0_3;
2101
 
    
2102
 
          if(combinations[deriv_num][j] == 0)
2103
 
          {
2104
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2105
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2106
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2107
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2108
 
          }
2109
 
          if(combinations[deriv_num][j] == 1)
2110
 
          {
2111
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2112
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2113
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2114
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2115
 
          }
2116
 
          if(combinations[deriv_num][j] == 2)
2117
 
          {
2118
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2119
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2120
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2121
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2122
 
          }
2123
 
    
2124
 
        }
2125
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
2126
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2127
 
      }
2128
 
    
2129
 
      // Transform derivatives back to physical element
2130
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2131
 
      {
2132
 
        for (unsigned int col = 0; col < num_derivatives; col++)
2133
 
        {
2134
 
          values[row] += transform[row][col]*derivatives[col];
2135
 
        }
2136
 
      }
2137
 
      // Delete pointer to array of derivatives on FIAT element
2138
 
      delete [] derivatives;
2139
 
    
2140
 
      // Delete pointer to array of combinations of derivatives and transform
2141
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2142
 
      {
2143
 
        delete [] combinations[row];
2144
 
        delete [] transform[row];
2145
 
      }
2146
 
    
2147
 
      delete [] combinations;
2148
 
      delete [] transform;
2149
 
    }
2150
 
    
2151
 
    if (4 <= i && i <= 7)
2152
 
    {
2153
 
      // Map degree of freedom to element degree of freedom
2154
 
      const unsigned int dof = i - 4;
2155
 
    
2156
 
      // Generate scalings
2157
 
      const double scalings_y_0 = 1;
2158
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2159
 
      const double scalings_z_0 = 1;
2160
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2161
 
    
2162
 
      // Compute psitilde_a
2163
 
      const double psitilde_a_0 = 1;
2164
 
      const double psitilde_a_1 = x;
2165
 
    
2166
 
      // Compute psitilde_bs
2167
 
      const double psitilde_bs_0_0 = 1;
2168
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
2169
 
      const double psitilde_bs_1_0 = 1;
2170
 
    
2171
 
      // Compute psitilde_cs
2172
 
      const double psitilde_cs_00_0 = 1;
2173
 
      const double psitilde_cs_00_1 = 2*z + 1;
2174
 
      const double psitilde_cs_01_0 = 1;
2175
 
      const double psitilde_cs_10_0 = 1;
2176
 
    
2177
 
      // Compute basisvalues
2178
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2179
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2180
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2181
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2182
 
    
2183
 
      // Table(s) of coefficients
2184
 
      static const double coefficients0[4][4] =   \
2185
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
2186
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
2187
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
2188
 
      {0.288675135, 0, 0, 0.223606798}};
2189
 
    
2190
 
      // Interesting (new) part
2191
 
      // Tables of derivatives of the polynomial base (transpose)
2192
 
      static const double dmats0[4][4] =   \
2193
 
      {{0, 0, 0, 0},
2194
 
      {6.32455532, 0, 0, 0},
2195
 
      {0, 0, 0, 0},
2196
 
      {0, 0, 0, 0}};
2197
 
    
2198
 
      static const double dmats1[4][4] =   \
2199
 
      {{0, 0, 0, 0},
2200
 
      {3.16227766, 0, 0, 0},
2201
 
      {5.47722558, 0, 0, 0},
2202
 
      {0, 0, 0, 0}};
2203
 
    
2204
 
      static const double dmats2[4][4] =   \
2205
 
      {{0, 0, 0, 0},
2206
 
      {3.16227766, 0, 0, 0},
2207
 
      {1.82574186, 0, 0, 0},
2208
 
      {5.16397779, 0, 0, 0}};
2209
 
    
2210
 
      // Compute reference derivatives
2211
 
      // Declare pointer to array of derivatives on FIAT element
2212
 
      double *derivatives = new double [num_derivatives];
2213
 
    
2214
 
      // Declare coefficients
2215
 
      double coeff0_0 = 0;
2216
 
      double coeff0_1 = 0;
2217
 
      double coeff0_2 = 0;
2218
 
      double coeff0_3 = 0;
2219
 
    
2220
 
      // Declare new coefficients
2221
 
      double new_coeff0_0 = 0;
2222
 
      double new_coeff0_1 = 0;
2223
 
      double new_coeff0_2 = 0;
2224
 
      double new_coeff0_3 = 0;
2225
 
    
2226
 
      // Loop possible derivatives
2227
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2228
 
      {
2229
 
        // Get values from coefficients array
2230
 
        new_coeff0_0 = coefficients0[dof][0];
2231
 
        new_coeff0_1 = coefficients0[dof][1];
2232
 
        new_coeff0_2 = coefficients0[dof][2];
2233
 
        new_coeff0_3 = coefficients0[dof][3];
2234
 
    
2235
 
        // Loop derivative order
2236
 
        for (unsigned int j = 0; j < n; j++)
2237
 
        {
2238
 
          // Update old coefficients
2239
 
          coeff0_0 = new_coeff0_0;
2240
 
          coeff0_1 = new_coeff0_1;
2241
 
          coeff0_2 = new_coeff0_2;
2242
 
          coeff0_3 = new_coeff0_3;
2243
 
    
2244
 
          if(combinations[deriv_num][j] == 0)
2245
 
          {
2246
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2247
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2248
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2249
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2250
 
          }
2251
 
          if(combinations[deriv_num][j] == 1)
2252
 
          {
2253
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2254
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2255
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2256
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2257
 
          }
2258
 
          if(combinations[deriv_num][j] == 2)
2259
 
          {
2260
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2261
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2262
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2263
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2264
 
          }
2265
 
    
2266
 
        }
2267
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
2268
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2269
 
      }
2270
 
    
2271
 
      // Transform derivatives back to physical element
2272
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2273
 
      {
2274
 
        for (unsigned int col = 0; col < num_derivatives; col++)
2275
 
        {
2276
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
2277
 
        }
2278
 
      }
2279
 
      // Delete pointer to array of derivatives on FIAT element
2280
 
      delete [] derivatives;
2281
 
    
2282
 
      // Delete pointer to array of combinations of derivatives and transform
2283
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2284
 
      {
2285
 
        delete [] combinations[row];
2286
 
        delete [] transform[row];
2287
 
      }
2288
 
    
2289
 
      delete [] combinations;
2290
 
      delete [] transform;
2291
 
    }
2292
 
    
2293
 
    if (8 <= i && i <= 11)
2294
 
    {
2295
 
      // Map degree of freedom to element degree of freedom
2296
 
      const unsigned int dof = i - 8;
2297
 
    
2298
 
      // Generate scalings
2299
 
      const double scalings_y_0 = 1;
2300
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2301
 
      const double scalings_z_0 = 1;
2302
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2303
 
    
2304
 
      // Compute psitilde_a
2305
 
      const double psitilde_a_0 = 1;
2306
 
      const double psitilde_a_1 = x;
2307
 
    
2308
 
      // Compute psitilde_bs
2309
 
      const double psitilde_bs_0_0 = 1;
2310
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
2311
 
      const double psitilde_bs_1_0 = 1;
2312
 
    
2313
 
      // Compute psitilde_cs
2314
 
      const double psitilde_cs_00_0 = 1;
2315
 
      const double psitilde_cs_00_1 = 2*z + 1;
2316
 
      const double psitilde_cs_01_0 = 1;
2317
 
      const double psitilde_cs_10_0 = 1;
2318
 
    
2319
 
      // Compute basisvalues
2320
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2321
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2322
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2323
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2324
 
    
2325
 
      // Table(s) of coefficients
2326
 
      static const double coefficients0[4][4] =   \
2327
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
2328
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
2329
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
2330
 
      {0.288675135, 0, 0, 0.223606798}};
2331
 
    
2332
 
      // Interesting (new) part
2333
 
      // Tables of derivatives of the polynomial base (transpose)
2334
 
      static const double dmats0[4][4] =   \
2335
 
      {{0, 0, 0, 0},
2336
 
      {6.32455532, 0, 0, 0},
2337
 
      {0, 0, 0, 0},
2338
 
      {0, 0, 0, 0}};
2339
 
    
2340
 
      static const double dmats1[4][4] =   \
2341
 
      {{0, 0, 0, 0},
2342
 
      {3.16227766, 0, 0, 0},
2343
 
      {5.47722558, 0, 0, 0},
2344
 
      {0, 0, 0, 0}};
2345
 
    
2346
 
      static const double dmats2[4][4] =   \
2347
 
      {{0, 0, 0, 0},
2348
 
      {3.16227766, 0, 0, 0},
2349
 
      {1.82574186, 0, 0, 0},
2350
 
      {5.16397779, 0, 0, 0}};
2351
 
    
2352
 
      // Compute reference derivatives
2353
 
      // Declare pointer to array of derivatives on FIAT element
2354
 
      double *derivatives = new double [num_derivatives];
2355
 
    
2356
 
      // Declare coefficients
2357
 
      double coeff0_0 = 0;
2358
 
      double coeff0_1 = 0;
2359
 
      double coeff0_2 = 0;
2360
 
      double coeff0_3 = 0;
2361
 
    
2362
 
      // Declare new coefficients
2363
 
      double new_coeff0_0 = 0;
2364
 
      double new_coeff0_1 = 0;
2365
 
      double new_coeff0_2 = 0;
2366
 
      double new_coeff0_3 = 0;
2367
 
    
2368
 
      // Loop possible derivatives
2369
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2370
 
      {
2371
 
        // Get values from coefficients array
2372
 
        new_coeff0_0 = coefficients0[dof][0];
2373
 
        new_coeff0_1 = coefficients0[dof][1];
2374
 
        new_coeff0_2 = coefficients0[dof][2];
2375
 
        new_coeff0_3 = coefficients0[dof][3];
2376
 
    
2377
 
        // Loop derivative order
2378
 
        for (unsigned int j = 0; j < n; j++)
2379
 
        {
2380
 
          // Update old coefficients
2381
 
          coeff0_0 = new_coeff0_0;
2382
 
          coeff0_1 = new_coeff0_1;
2383
 
          coeff0_2 = new_coeff0_2;
2384
 
          coeff0_3 = new_coeff0_3;
2385
 
    
2386
 
          if(combinations[deriv_num][j] == 0)
2387
 
          {
2388
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2389
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2390
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2391
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2392
 
          }
2393
 
          if(combinations[deriv_num][j] == 1)
2394
 
          {
2395
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2396
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2397
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2398
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2399
 
          }
2400
 
          if(combinations[deriv_num][j] == 2)
2401
 
          {
2402
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2403
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2404
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2405
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2406
 
          }
2407
 
    
2408
 
        }
2409
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
2410
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2411
 
      }
2412
 
    
2413
 
      // Transform derivatives back to physical element
2414
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2415
 
      {
2416
 
        for (unsigned int col = 0; col < num_derivatives; col++)
2417
 
        {
2418
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
2419
 
        }
2420
 
      }
2421
 
      // Delete pointer to array of derivatives on FIAT element
2422
 
      delete [] derivatives;
2423
 
    
2424
 
      // Delete pointer to array of combinations of derivatives and transform
2425
 
      for (unsigned int row = 0; row < num_derivatives; row++)
2426
 
      {
2427
 
        delete [] combinations[row];
2428
 
        delete [] transform[row];
2429
 
      }
2430
 
    
2431
 
      delete [] combinations;
2432
 
      delete [] transform;
2433
 
    }
2434
 
    
2435
 
  }
2436
 
 
2437
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
2438
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
2439
 
                                              double* values,
2440
 
                                              const double* coordinates,
2441
 
                                              const ufc::cell& c) const
2442
 
  {
2443
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
2444
 
  }
2445
 
 
2446
 
  /// Evaluate linear functional for dof i on the function f
2447
 
  virtual double evaluate_dof(unsigned int i,
2448
 
                              const ufc::function& f,
2449
 
                              const ufc::cell& c) const
2450
 
  {
2451
 
    // The reference points, direction and weights:
2452
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
2453
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
2454
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
2455
 
    
2456
 
    const double * const * x = c.coordinates;
2457
 
    double result = 0.0;
2458
 
    // Iterate over the points:
2459
 
    // Evaluate basis functions for affine mapping
2460
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
2461
 
    const double w1 = X[i][0][0];
2462
 
    const double w2 = X[i][0][1];
2463
 
    const double w3 = X[i][0][2];
2464
 
    
2465
 
    // Compute affine mapping y = F(X)
2466
 
    double y[3];
2467
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
2468
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
2469
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
2470
 
    
2471
 
    // Evaluate function at physical points
2472
 
    double values[3];
2473
 
    f.evaluate(values, y, c);
2474
 
    
2475
 
    // Map function values using appropriate mapping
2476
 
    // Affine map: Do nothing
2477
 
    
2478
 
    // Note that we do not map the weights (yet).
2479
 
    
2480
 
    // Take directional components
2481
 
    for(int k = 0; k < 3; k++)
2482
 
      result += values[k]*D[i][0][k];
2483
 
    // Multiply by weights
2484
 
    result *= W[i][0];
2485
 
    
2486
 
    return result;
2487
 
  }
2488
 
 
2489
 
  /// Evaluate linear functionals for all dofs on the function f
2490
 
  virtual void evaluate_dofs(double* values,
2491
 
                             const ufc::function& f,
2492
 
                             const ufc::cell& c) const
2493
 
  {
2494
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2495
 
  }
2496
 
 
2497
 
  /// Interpolate vertex values from dof values
2498
 
  virtual void interpolate_vertex_values(double* vertex_values,
2499
 
                                         const double* dof_values,
2500
 
                                         const ufc::cell& c) const
2501
 
  {
2502
 
    // Evaluate at vertices and use affine mapping
2503
 
    vertex_values[0] = dof_values[0];
2504
 
    vertex_values[3] = dof_values[1];
2505
 
    vertex_values[6] = dof_values[2];
2506
 
    vertex_values[9] = dof_values[3];
2507
 
    // Evaluate at vertices and use affine mapping
2508
 
    vertex_values[1] = dof_values[4];
2509
 
    vertex_values[4] = dof_values[5];
2510
 
    vertex_values[7] = dof_values[6];
2511
 
    vertex_values[10] = dof_values[7];
2512
 
    // Evaluate at vertices and use affine mapping
2513
 
    vertex_values[2] = dof_values[8];
2514
 
    vertex_values[5] = dof_values[9];
2515
 
    vertex_values[8] = dof_values[10];
2516
 
    vertex_values[11] = dof_values[11];
2517
 
  }
2518
 
 
2519
 
  /// Return the number of sub elements (for a mixed element)
2520
 
  virtual unsigned int num_sub_elements() const
2521
 
  {
2522
 
    return 3;
2523
 
  }
2524
 
 
2525
 
  /// Create a new finite element for sub element i (for a mixed element)
2526
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
2527
 
  {
2528
 
    switch ( i )
2529
 
    {
2530
 
    case 0:
2531
 
      return new hyperelasticity_0_finite_element_0_0();
2532
 
      break;
2533
 
    case 1:
2534
 
      return new hyperelasticity_0_finite_element_0_1();
2535
 
      break;
2536
 
    case 2:
2537
 
      return new hyperelasticity_0_finite_element_0_2();
2538
 
      break;
2539
 
    }
2540
 
    return 0;
2541
 
  }
2542
 
 
2543
 
};
2544
 
 
2545
 
/// This class defines the interface for a finite element.
2546
 
 
2547
 
class hyperelasticity_0_finite_element_1_0: public ufc::finite_element
2548
 
{
2549
 
public:
2550
 
 
2551
 
  /// Constructor
2552
 
  hyperelasticity_0_finite_element_1_0() : ufc::finite_element()
2553
 
  {
2554
 
    // Do nothing
2555
 
  }
2556
 
 
2557
 
  /// Destructor
2558
 
  virtual ~hyperelasticity_0_finite_element_1_0()
2559
 
  {
2560
 
    // Do nothing
2561
 
  }
2562
 
 
2563
 
  /// Return a string identifying the finite element
2564
 
  virtual const char* signature() const
2565
 
  {
2566
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
2567
 
  }
2568
 
 
2569
 
  /// Return the cell shape
2570
 
  virtual ufc::shape cell_shape() const
2571
 
  {
2572
 
    return ufc::tetrahedron;
2573
 
  }
2574
 
 
2575
 
  /// Return the dimension of the finite element function space
2576
 
  virtual unsigned int space_dimension() const
2577
 
  {
2578
 
    return 4;
2579
 
  }
2580
 
 
2581
 
  /// Return the rank of the value space
2582
 
  virtual unsigned int value_rank() const
2583
 
  {
2584
 
    return 0;
2585
 
  }
2586
 
 
2587
 
  /// Return the dimension of the value space for axis i
2588
 
  virtual unsigned int value_dimension(unsigned int i) const
2589
 
  {
2590
 
    return 1;
2591
 
  }
2592
 
 
2593
 
  /// Evaluate basis function i at given point in cell
2594
 
  virtual void evaluate_basis(unsigned int i,
2595
 
                              double* values,
2596
 
                              const double* coordinates,
2597
 
                              const ufc::cell& c) const
2598
 
  {
2599
 
    // Extract vertex coordinates
2600
 
    const double * const * element_coordinates = c.coordinates;
2601
 
    
2602
 
    // Compute Jacobian of affine map from reference cell
2603
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
2604
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
2605
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
2606
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
2607
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
2608
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
2609
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
2610
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
2611
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
2612
 
    
2613
 
    // Compute sub determinants
2614
 
    const double d00 = J_11*J_22 - J_12*J_21;
2615
 
    const double d01 = J_12*J_20 - J_10*J_22;
2616
 
    const double d02 = J_10*J_21 - J_11*J_20;
2617
 
    
2618
 
    const double d10 = J_02*J_21 - J_01*J_22;
2619
 
    const double d11 = J_00*J_22 - J_02*J_20;
2620
 
    const double d12 = J_01*J_20 - J_00*J_21;
2621
 
    
2622
 
    const double d20 = J_01*J_12 - J_02*J_11;
2623
 
    const double d21 = J_02*J_10 - J_00*J_12;
2624
 
    const double d22 = J_00*J_11 - J_01*J_10;
2625
 
    
2626
 
    // Compute determinant of Jacobian
2627
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
2628
 
    
2629
 
    // Compute inverse of Jacobian
2630
 
    
2631
 
    // Compute constants
2632
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
2633
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
2634
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
2635
 
    
2636
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
2637
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
2638
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
2639
 
    
2640
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
2641
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
2642
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
2643
 
    
2644
 
    // Get coordinates and map to the UFC reference element
2645
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
2646
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
2647
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
2648
 
    
2649
 
    // Map coordinates to the reference cube
2650
 
    if (std::abs(y + z - 1.0) < 1e-08)
2651
 
      x = 1.0;
2652
 
    else
2653
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
2654
 
    if (std::abs(z - 1.0) < 1e-08)
2655
 
      y = -1.0;
2656
 
    else
2657
 
      y = 2.0 * y/(1.0 - z) - 1.0;
2658
 
    z = 2.0 * z - 1.0;
2659
 
    
2660
 
    // Reset values
2661
 
    *values = 0;
2662
 
    
2663
 
    // Map degree of freedom to element degree of freedom
2664
 
    const unsigned int dof = i;
2665
 
    
2666
 
    // Generate scalings
2667
 
    const double scalings_y_0 = 1;
2668
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2669
 
    const double scalings_z_0 = 1;
2670
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2671
 
    
2672
 
    // Compute psitilde_a
2673
 
    const double psitilde_a_0 = 1;
2674
 
    const double psitilde_a_1 = x;
2675
 
    
2676
 
    // Compute psitilde_bs
2677
 
    const double psitilde_bs_0_0 = 1;
2678
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
2679
 
    const double psitilde_bs_1_0 = 1;
2680
 
    
2681
 
    // Compute psitilde_cs
2682
 
    const double psitilde_cs_00_0 = 1;
2683
 
    const double psitilde_cs_00_1 = 2*z + 1;
2684
 
    const double psitilde_cs_01_0 = 1;
2685
 
    const double psitilde_cs_10_0 = 1;
2686
 
    
2687
 
    // Compute basisvalues
2688
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2689
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2690
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2691
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2692
 
    
2693
 
    // Table(s) of coefficients
2694
 
    static const double coefficients0[4][4] = \
2695
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
2696
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
2697
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
2698
 
    {0.288675135, 0, 0, 0.223606798}};
2699
 
    
2700
 
    // Extract relevant coefficients
2701
 
    const double coeff0_0 = coefficients0[dof][0];
2702
 
    const double coeff0_1 = coefficients0[dof][1];
2703
 
    const double coeff0_2 = coefficients0[dof][2];
2704
 
    const double coeff0_3 = coefficients0[dof][3];
2705
 
    
2706
 
    // Compute value(s)
2707
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
2708
 
  }
2709
 
 
2710
 
  /// Evaluate all basis functions at given point in cell
2711
 
  virtual void evaluate_basis_all(double* values,
2712
 
                                  const double* coordinates,
2713
 
                                  const ufc::cell& c) const
2714
 
  {
2715
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
2716
 
  }
2717
 
 
2718
 
  /// Evaluate order n derivatives of basis function i at given point in cell
2719
 
  virtual void evaluate_basis_derivatives(unsigned int i,
2720
 
                                          unsigned int n,
2721
 
                                          double* values,
2722
 
                                          const double* coordinates,
2723
 
                                          const ufc::cell& c) const
2724
 
  {
2725
 
    // Extract vertex coordinates
2726
 
    const double * const * element_coordinates = c.coordinates;
2727
 
    
2728
 
    // Compute Jacobian of affine map from reference cell
2729
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
2730
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
2731
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
2732
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
2733
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
2734
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
2735
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
2736
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
2737
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
2738
 
    
2739
 
    // Compute sub determinants
2740
 
    const double d00 = J_11*J_22 - J_12*J_21;
2741
 
    const double d01 = J_12*J_20 - J_10*J_22;
2742
 
    const double d02 = J_10*J_21 - J_11*J_20;
2743
 
    
2744
 
    const double d10 = J_02*J_21 - J_01*J_22;
2745
 
    const double d11 = J_00*J_22 - J_02*J_20;
2746
 
    const double d12 = J_01*J_20 - J_00*J_21;
2747
 
    
2748
 
    const double d20 = J_01*J_12 - J_02*J_11;
2749
 
    const double d21 = J_02*J_10 - J_00*J_12;
2750
 
    const double d22 = J_00*J_11 - J_01*J_10;
2751
 
    
2752
 
    // Compute determinant of Jacobian
2753
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
2754
 
    
2755
 
    // Compute inverse of Jacobian
2756
 
    
2757
 
    // Compute constants
2758
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
2759
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
2760
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
2761
 
    
2762
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
2763
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
2764
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
2765
 
    
2766
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
2767
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
2768
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
2769
 
    
2770
 
    // Get coordinates and map to the UFC reference element
2771
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
2772
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
2773
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
2774
 
    
2775
 
    // Map coordinates to the reference cube
2776
 
    if (std::abs(y + z - 1.0) < 1e-08)
2777
 
      x = 1.0;
2778
 
    else
2779
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
2780
 
    if (std::abs(z - 1.0) < 1e-08)
2781
 
      y = -1.0;
2782
 
    else
2783
 
      y = 2.0 * y/(1.0 - z) - 1.0;
2784
 
    z = 2.0 * z - 1.0;
2785
 
    
2786
 
    // Compute number of derivatives
2787
 
    unsigned int num_derivatives = 1;
2788
 
    
2789
 
    for (unsigned int j = 0; j < n; j++)
2790
 
      num_derivatives *= 3;
2791
 
    
2792
 
    
2793
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
2794
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
2795
 
    
2796
 
    for (unsigned int j = 0; j < num_derivatives; j++)
2797
 
    {
2798
 
      combinations[j] = new unsigned int [n];
2799
 
      for (unsigned int k = 0; k < n; k++)
2800
 
        combinations[j][k] = 0;
2801
 
    }
2802
 
    
2803
 
    // Generate combinations of derivatives
2804
 
    for (unsigned int row = 1; row < num_derivatives; row++)
2805
 
    {
2806
 
      for (unsigned int num = 0; num < row; num++)
2807
 
      {
2808
 
        for (unsigned int col = n-1; col+1 > 0; col--)
2809
 
        {
2810
 
          if (combinations[row][col] + 1 > 2)
2811
 
            combinations[row][col] = 0;
2812
 
          else
2813
 
          {
2814
 
            combinations[row][col] += 1;
2815
 
            break;
2816
 
          }
2817
 
        }
2818
 
      }
2819
 
    }
2820
 
    
2821
 
    // Compute inverse of Jacobian
2822
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
2823
 
    
2824
 
    // Declare transformation matrix
2825
 
    // Declare pointer to two dimensional array and initialise
2826
 
    double **transform = new double *[num_derivatives];
2827
 
    
2828
 
    for (unsigned int j = 0; j < num_derivatives; j++)
2829
 
    {
2830
 
      transform[j] = new double [num_derivatives];
2831
 
      for (unsigned int k = 0; k < num_derivatives; k++)
2832
 
        transform[j][k] = 1;
2833
 
    }
2834
 
    
2835
 
    // Construct transformation matrix
2836
 
    for (unsigned int row = 0; row < num_derivatives; row++)
2837
 
    {
2838
 
      for (unsigned int col = 0; col < num_derivatives; col++)
2839
 
      {
2840
 
        for (unsigned int k = 0; k < n; k++)
2841
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
2842
 
      }
2843
 
    }
2844
 
    
2845
 
    // Reset values
2846
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
2847
 
      values[j] = 0;
2848
 
    
2849
 
    // Map degree of freedom to element degree of freedom
2850
 
    const unsigned int dof = i;
2851
 
    
2852
 
    // Generate scalings
2853
 
    const double scalings_y_0 = 1;
2854
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2855
 
    const double scalings_z_0 = 1;
2856
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2857
 
    
2858
 
    // Compute psitilde_a
2859
 
    const double psitilde_a_0 = 1;
2860
 
    const double psitilde_a_1 = x;
2861
 
    
2862
 
    // Compute psitilde_bs
2863
 
    const double psitilde_bs_0_0 = 1;
2864
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
2865
 
    const double psitilde_bs_1_0 = 1;
2866
 
    
2867
 
    // Compute psitilde_cs
2868
 
    const double psitilde_cs_00_0 = 1;
2869
 
    const double psitilde_cs_00_1 = 2*z + 1;
2870
 
    const double psitilde_cs_01_0 = 1;
2871
 
    const double psitilde_cs_10_0 = 1;
2872
 
    
2873
 
    // Compute basisvalues
2874
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2875
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2876
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2877
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2878
 
    
2879
 
    // Table(s) of coefficients
2880
 
    static const double coefficients0[4][4] = \
2881
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
2882
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
2883
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
2884
 
    {0.288675135, 0, 0, 0.223606798}};
2885
 
    
2886
 
    // Interesting (new) part
2887
 
    // Tables of derivatives of the polynomial base (transpose)
2888
 
    static const double dmats0[4][4] = \
2889
 
    {{0, 0, 0, 0},
2890
 
    {6.32455532, 0, 0, 0},
2891
 
    {0, 0, 0, 0},
2892
 
    {0, 0, 0, 0}};
2893
 
    
2894
 
    static const double dmats1[4][4] = \
2895
 
    {{0, 0, 0, 0},
2896
 
    {3.16227766, 0, 0, 0},
2897
 
    {5.47722558, 0, 0, 0},
2898
 
    {0, 0, 0, 0}};
2899
 
    
2900
 
    static const double dmats2[4][4] = \
2901
 
    {{0, 0, 0, 0},
2902
 
    {3.16227766, 0, 0, 0},
2903
 
    {1.82574186, 0, 0, 0},
2904
 
    {5.16397779, 0, 0, 0}};
2905
 
    
2906
 
    // Compute reference derivatives
2907
 
    // Declare pointer to array of derivatives on FIAT element
2908
 
    double *derivatives = new double [num_derivatives];
2909
 
    
2910
 
    // Declare coefficients
2911
 
    double coeff0_0 = 0;
2912
 
    double coeff0_1 = 0;
2913
 
    double coeff0_2 = 0;
2914
 
    double coeff0_3 = 0;
2915
 
    
2916
 
    // Declare new coefficients
2917
 
    double new_coeff0_0 = 0;
2918
 
    double new_coeff0_1 = 0;
2919
 
    double new_coeff0_2 = 0;
2920
 
    double new_coeff0_3 = 0;
2921
 
    
2922
 
    // Loop possible derivatives
2923
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2924
 
    {
2925
 
      // Get values from coefficients array
2926
 
      new_coeff0_0 = coefficients0[dof][0];
2927
 
      new_coeff0_1 = coefficients0[dof][1];
2928
 
      new_coeff0_2 = coefficients0[dof][2];
2929
 
      new_coeff0_3 = coefficients0[dof][3];
2930
 
    
2931
 
      // Loop derivative order
2932
 
      for (unsigned int j = 0; j < n; j++)
2933
 
      {
2934
 
        // Update old coefficients
2935
 
        coeff0_0 = new_coeff0_0;
2936
 
        coeff0_1 = new_coeff0_1;
2937
 
        coeff0_2 = new_coeff0_2;
2938
 
        coeff0_3 = new_coeff0_3;
2939
 
    
2940
 
        if(combinations[deriv_num][j] == 0)
2941
 
        {
2942
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2943
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2944
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2945
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2946
 
        }
2947
 
        if(combinations[deriv_num][j] == 1)
2948
 
        {
2949
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2950
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2951
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2952
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2953
 
        }
2954
 
        if(combinations[deriv_num][j] == 2)
2955
 
        {
2956
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2957
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2958
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2959
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2960
 
        }
2961
 
    
2962
 
      }
2963
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
2964
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2965
 
    }
2966
 
    
2967
 
    // Transform derivatives back to physical element
2968
 
    for (unsigned int row = 0; row < num_derivatives; row++)
2969
 
    {
2970
 
      for (unsigned int col = 0; col < num_derivatives; col++)
2971
 
      {
2972
 
        values[row] += transform[row][col]*derivatives[col];
2973
 
      }
2974
 
    }
2975
 
    // Delete pointer to array of derivatives on FIAT element
2976
 
    delete [] derivatives;
2977
 
    
2978
 
    // Delete pointer to array of combinations of derivatives and transform
2979
 
    for (unsigned int row = 0; row < num_derivatives; row++)
2980
 
    {
2981
 
      delete [] combinations[row];
2982
 
      delete [] transform[row];
2983
 
    }
2984
 
    
2985
 
    delete [] combinations;
2986
 
    delete [] transform;
2987
 
  }
2988
 
 
2989
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
2990
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
2991
 
                                              double* values,
2992
 
                                              const double* coordinates,
2993
 
                                              const ufc::cell& c) const
2994
 
  {
2995
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
2996
 
  }
2997
 
 
2998
 
  /// Evaluate linear functional for dof i on the function f
2999
 
  virtual double evaluate_dof(unsigned int i,
3000
 
                              const ufc::function& f,
3001
 
                              const ufc::cell& c) const
3002
 
  {
3003
 
    // The reference points, direction and weights:
3004
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
3005
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
3006
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
3007
 
    
3008
 
    const double * const * x = c.coordinates;
3009
 
    double result = 0.0;
3010
 
    // Iterate over the points:
3011
 
    // Evaluate basis functions for affine mapping
3012
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
3013
 
    const double w1 = X[i][0][0];
3014
 
    const double w2 = X[i][0][1];
3015
 
    const double w3 = X[i][0][2];
3016
 
    
3017
 
    // Compute affine mapping y = F(X)
3018
 
    double y[3];
3019
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
3020
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
3021
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
3022
 
    
3023
 
    // Evaluate function at physical points
3024
 
    double values[1];
3025
 
    f.evaluate(values, y, c);
3026
 
    
3027
 
    // Map function values using appropriate mapping
3028
 
    // Affine map: Do nothing
3029
 
    
3030
 
    // Note that we do not map the weights (yet).
3031
 
    
3032
 
    // Take directional components
3033
 
    for(int k = 0; k < 1; k++)
3034
 
      result += values[k]*D[i][0][k];
3035
 
    // Multiply by weights
3036
 
    result *= W[i][0];
3037
 
    
3038
 
    return result;
3039
 
  }
3040
 
 
3041
 
  /// Evaluate linear functionals for all dofs on the function f
3042
 
  virtual void evaluate_dofs(double* values,
3043
 
                             const ufc::function& f,
3044
 
                             const ufc::cell& c) const
3045
 
  {
3046
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3047
 
  }
3048
 
 
3049
 
  /// Interpolate vertex values from dof values
3050
 
  virtual void interpolate_vertex_values(double* vertex_values,
3051
 
                                         const double* dof_values,
3052
 
                                         const ufc::cell& c) const
3053
 
  {
3054
 
    // Evaluate at vertices and use affine mapping
3055
 
    vertex_values[0] = dof_values[0];
3056
 
    vertex_values[1] = dof_values[1];
3057
 
    vertex_values[2] = dof_values[2];
3058
 
    vertex_values[3] = dof_values[3];
3059
 
  }
3060
 
 
3061
 
  /// Return the number of sub elements (for a mixed element)
3062
 
  virtual unsigned int num_sub_elements() const
3063
 
  {
3064
 
    return 1;
3065
 
  }
3066
 
 
3067
 
  /// Create a new finite element for sub element i (for a mixed element)
3068
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
3069
 
  {
3070
 
    return new hyperelasticity_0_finite_element_1_0();
3071
 
  }
3072
 
 
3073
 
};
3074
 
 
3075
 
/// This class defines the interface for a finite element.
3076
 
 
3077
 
class hyperelasticity_0_finite_element_1_1: public ufc::finite_element
3078
 
{
3079
 
public:
3080
 
 
3081
 
  /// Constructor
3082
 
  hyperelasticity_0_finite_element_1_1() : ufc::finite_element()
3083
 
  {
3084
 
    // Do nothing
3085
 
  }
3086
 
 
3087
 
  /// Destructor
3088
 
  virtual ~hyperelasticity_0_finite_element_1_1()
3089
 
  {
3090
 
    // Do nothing
3091
 
  }
3092
 
 
3093
 
  /// Return a string identifying the finite element
3094
 
  virtual const char* signature() const
3095
 
  {
3096
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
3097
 
  }
3098
 
 
3099
 
  /// Return the cell shape
3100
 
  virtual ufc::shape cell_shape() const
3101
 
  {
3102
 
    return ufc::tetrahedron;
3103
 
  }
3104
 
 
3105
 
  /// Return the dimension of the finite element function space
3106
 
  virtual unsigned int space_dimension() const
3107
 
  {
3108
 
    return 4;
3109
 
  }
3110
 
 
3111
 
  /// Return the rank of the value space
3112
 
  virtual unsigned int value_rank() const
3113
 
  {
3114
 
    return 0;
3115
 
  }
3116
 
 
3117
 
  /// Return the dimension of the value space for axis i
3118
 
  virtual unsigned int value_dimension(unsigned int i) const
3119
 
  {
3120
 
    return 1;
3121
 
  }
3122
 
 
3123
 
  /// Evaluate basis function i at given point in cell
3124
 
  virtual void evaluate_basis(unsigned int i,
3125
 
                              double* values,
3126
 
                              const double* coordinates,
3127
 
                              const ufc::cell& c) const
3128
 
  {
3129
 
    // Extract vertex coordinates
3130
 
    const double * const * element_coordinates = c.coordinates;
3131
 
    
3132
 
    // Compute Jacobian of affine map from reference cell
3133
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
3134
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
3135
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
3136
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
3137
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
3138
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
3139
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
3140
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
3141
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
3142
 
    
3143
 
    // Compute sub determinants
3144
 
    const double d00 = J_11*J_22 - J_12*J_21;
3145
 
    const double d01 = J_12*J_20 - J_10*J_22;
3146
 
    const double d02 = J_10*J_21 - J_11*J_20;
3147
 
    
3148
 
    const double d10 = J_02*J_21 - J_01*J_22;
3149
 
    const double d11 = J_00*J_22 - J_02*J_20;
3150
 
    const double d12 = J_01*J_20 - J_00*J_21;
3151
 
    
3152
 
    const double d20 = J_01*J_12 - J_02*J_11;
3153
 
    const double d21 = J_02*J_10 - J_00*J_12;
3154
 
    const double d22 = J_00*J_11 - J_01*J_10;
3155
 
    
3156
 
    // Compute determinant of Jacobian
3157
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
3158
 
    
3159
 
    // Compute inverse of Jacobian
3160
 
    
3161
 
    // Compute constants
3162
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
3163
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
3164
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
3165
 
    
3166
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
3167
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
3168
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
3169
 
    
3170
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
3171
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
3172
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
3173
 
    
3174
 
    // Get coordinates and map to the UFC reference element
3175
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
3176
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
3177
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
3178
 
    
3179
 
    // Map coordinates to the reference cube
3180
 
    if (std::abs(y + z - 1.0) < 1e-08)
3181
 
      x = 1.0;
3182
 
    else
3183
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
3184
 
    if (std::abs(z - 1.0) < 1e-08)
3185
 
      y = -1.0;
3186
 
    else
3187
 
      y = 2.0 * y/(1.0 - z) - 1.0;
3188
 
    z = 2.0 * z - 1.0;
3189
 
    
3190
 
    // Reset values
3191
 
    *values = 0;
3192
 
    
3193
 
    // Map degree of freedom to element degree of freedom
3194
 
    const unsigned int dof = i;
3195
 
    
3196
 
    // Generate scalings
3197
 
    const double scalings_y_0 = 1;
3198
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
3199
 
    const double scalings_z_0 = 1;
3200
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
3201
 
    
3202
 
    // Compute psitilde_a
3203
 
    const double psitilde_a_0 = 1;
3204
 
    const double psitilde_a_1 = x;
3205
 
    
3206
 
    // Compute psitilde_bs
3207
 
    const double psitilde_bs_0_0 = 1;
3208
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
3209
 
    const double psitilde_bs_1_0 = 1;
3210
 
    
3211
 
    // Compute psitilde_cs
3212
 
    const double psitilde_cs_00_0 = 1;
3213
 
    const double psitilde_cs_00_1 = 2*z + 1;
3214
 
    const double psitilde_cs_01_0 = 1;
3215
 
    const double psitilde_cs_10_0 = 1;
3216
 
    
3217
 
    // Compute basisvalues
3218
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
3219
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
3220
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
3221
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
3222
 
    
3223
 
    // Table(s) of coefficients
3224
 
    static const double coefficients0[4][4] = \
3225
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
3226
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
3227
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
3228
 
    {0.288675135, 0, 0, 0.223606798}};
3229
 
    
3230
 
    // Extract relevant coefficients
3231
 
    const double coeff0_0 = coefficients0[dof][0];
3232
 
    const double coeff0_1 = coefficients0[dof][1];
3233
 
    const double coeff0_2 = coefficients0[dof][2];
3234
 
    const double coeff0_3 = coefficients0[dof][3];
3235
 
    
3236
 
    // Compute value(s)
3237
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
3238
 
  }
3239
 
 
3240
 
  /// Evaluate all basis functions at given point in cell
3241
 
  virtual void evaluate_basis_all(double* values,
3242
 
                                  const double* coordinates,
3243
 
                                  const ufc::cell& c) const
3244
 
  {
3245
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
3246
 
  }
3247
 
 
3248
 
  /// Evaluate order n derivatives of basis function i at given point in cell
3249
 
  virtual void evaluate_basis_derivatives(unsigned int i,
3250
 
                                          unsigned int n,
3251
 
                                          double* values,
3252
 
                                          const double* coordinates,
3253
 
                                          const ufc::cell& c) const
3254
 
  {
3255
 
    // Extract vertex coordinates
3256
 
    const double * const * element_coordinates = c.coordinates;
3257
 
    
3258
 
    // Compute Jacobian of affine map from reference cell
3259
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
3260
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
3261
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
3262
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
3263
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
3264
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
3265
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
3266
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
3267
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
3268
 
    
3269
 
    // Compute sub determinants
3270
 
    const double d00 = J_11*J_22 - J_12*J_21;
3271
 
    const double d01 = J_12*J_20 - J_10*J_22;
3272
 
    const double d02 = J_10*J_21 - J_11*J_20;
3273
 
    
3274
 
    const double d10 = J_02*J_21 - J_01*J_22;
3275
 
    const double d11 = J_00*J_22 - J_02*J_20;
3276
 
    const double d12 = J_01*J_20 - J_00*J_21;
3277
 
    
3278
 
    const double d20 = J_01*J_12 - J_02*J_11;
3279
 
    const double d21 = J_02*J_10 - J_00*J_12;
3280
 
    const double d22 = J_00*J_11 - J_01*J_10;
3281
 
    
3282
 
    // Compute determinant of Jacobian
3283
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
3284
 
    
3285
 
    // Compute inverse of Jacobian
3286
 
    
3287
 
    // Compute constants
3288
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
3289
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
3290
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
3291
 
    
3292
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
3293
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
3294
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
3295
 
    
3296
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
3297
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
3298
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
3299
 
    
3300
 
    // Get coordinates and map to the UFC reference element
3301
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
3302
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
3303
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
3304
 
    
3305
 
    // Map coordinates to the reference cube
3306
 
    if (std::abs(y + z - 1.0) < 1e-08)
3307
 
      x = 1.0;
3308
 
    else
3309
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
3310
 
    if (std::abs(z - 1.0) < 1e-08)
3311
 
      y = -1.0;
3312
 
    else
3313
 
      y = 2.0 * y/(1.0 - z) - 1.0;
3314
 
    z = 2.0 * z - 1.0;
3315
 
    
3316
 
    // Compute number of derivatives
3317
 
    unsigned int num_derivatives = 1;
3318
 
    
3319
 
    for (unsigned int j = 0; j < n; j++)
3320
 
      num_derivatives *= 3;
3321
 
    
3322
 
    
3323
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
3324
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
3325
 
    
3326
 
    for (unsigned int j = 0; j < num_derivatives; j++)
3327
 
    {
3328
 
      combinations[j] = new unsigned int [n];
3329
 
      for (unsigned int k = 0; k < n; k++)
3330
 
        combinations[j][k] = 0;
3331
 
    }
3332
 
    
3333
 
    // Generate combinations of derivatives
3334
 
    for (unsigned int row = 1; row < num_derivatives; row++)
3335
 
    {
3336
 
      for (unsigned int num = 0; num < row; num++)
3337
 
      {
3338
 
        for (unsigned int col = n-1; col+1 > 0; col--)
3339
 
        {
3340
 
          if (combinations[row][col] + 1 > 2)
3341
 
            combinations[row][col] = 0;
3342
 
          else
3343
 
          {
3344
 
            combinations[row][col] += 1;
3345
 
            break;
3346
 
          }
3347
 
        }
3348
 
      }
3349
 
    }
3350
 
    
3351
 
    // Compute inverse of Jacobian
3352
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
3353
 
    
3354
 
    // Declare transformation matrix
3355
 
    // Declare pointer to two dimensional array and initialise
3356
 
    double **transform = new double *[num_derivatives];
3357
 
    
3358
 
    for (unsigned int j = 0; j < num_derivatives; j++)
3359
 
    {
3360
 
      transform[j] = new double [num_derivatives];
3361
 
      for (unsigned int k = 0; k < num_derivatives; k++)
3362
 
        transform[j][k] = 1;
3363
 
    }
3364
 
    
3365
 
    // Construct transformation matrix
3366
 
    for (unsigned int row = 0; row < num_derivatives; row++)
3367
 
    {
3368
 
      for (unsigned int col = 0; col < num_derivatives; col++)
3369
 
      {
3370
 
        for (unsigned int k = 0; k < n; k++)
3371
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
3372
 
      }
3373
 
    }
3374
 
    
3375
 
    // Reset values
3376
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
3377
 
      values[j] = 0;
3378
 
    
3379
 
    // Map degree of freedom to element degree of freedom
3380
 
    const unsigned int dof = i;
3381
 
    
3382
 
    // Generate scalings
3383
 
    const double scalings_y_0 = 1;
3384
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
3385
 
    const double scalings_z_0 = 1;
3386
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
3387
 
    
3388
 
    // Compute psitilde_a
3389
 
    const double psitilde_a_0 = 1;
3390
 
    const double psitilde_a_1 = x;
3391
 
    
3392
 
    // Compute psitilde_bs
3393
 
    const double psitilde_bs_0_0 = 1;
3394
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
3395
 
    const double psitilde_bs_1_0 = 1;
3396
 
    
3397
 
    // Compute psitilde_cs
3398
 
    const double psitilde_cs_00_0 = 1;
3399
 
    const double psitilde_cs_00_1 = 2*z + 1;
3400
 
    const double psitilde_cs_01_0 = 1;
3401
 
    const double psitilde_cs_10_0 = 1;
3402
 
    
3403
 
    // Compute basisvalues
3404
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
3405
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
3406
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
3407
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
3408
 
    
3409
 
    // Table(s) of coefficients
3410
 
    static const double coefficients0[4][4] = \
3411
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
3412
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
3413
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
3414
 
    {0.288675135, 0, 0, 0.223606798}};
3415
 
    
3416
 
    // Interesting (new) part
3417
 
    // Tables of derivatives of the polynomial base (transpose)
3418
 
    static const double dmats0[4][4] = \
3419
 
    {{0, 0, 0, 0},
3420
 
    {6.32455532, 0, 0, 0},
3421
 
    {0, 0, 0, 0},
3422
 
    {0, 0, 0, 0}};
3423
 
    
3424
 
    static const double dmats1[4][4] = \
3425
 
    {{0, 0, 0, 0},
3426
 
    {3.16227766, 0, 0, 0},
3427
 
    {5.47722558, 0, 0, 0},
3428
 
    {0, 0, 0, 0}};
3429
 
    
3430
 
    static const double dmats2[4][4] = \
3431
 
    {{0, 0, 0, 0},
3432
 
    {3.16227766, 0, 0, 0},
3433
 
    {1.82574186, 0, 0, 0},
3434
 
    {5.16397779, 0, 0, 0}};
3435
 
    
3436
 
    // Compute reference derivatives
3437
 
    // Declare pointer to array of derivatives on FIAT element
3438
 
    double *derivatives = new double [num_derivatives];
3439
 
    
3440
 
    // Declare coefficients
3441
 
    double coeff0_0 = 0;
3442
 
    double coeff0_1 = 0;
3443
 
    double coeff0_2 = 0;
3444
 
    double coeff0_3 = 0;
3445
 
    
3446
 
    // Declare new coefficients
3447
 
    double new_coeff0_0 = 0;
3448
 
    double new_coeff0_1 = 0;
3449
 
    double new_coeff0_2 = 0;
3450
 
    double new_coeff0_3 = 0;
3451
 
    
3452
 
    // Loop possible derivatives
3453
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
3454
 
    {
3455
 
      // Get values from coefficients array
3456
 
      new_coeff0_0 = coefficients0[dof][0];
3457
 
      new_coeff0_1 = coefficients0[dof][1];
3458
 
      new_coeff0_2 = coefficients0[dof][2];
3459
 
      new_coeff0_3 = coefficients0[dof][3];
3460
 
    
3461
 
      // Loop derivative order
3462
 
      for (unsigned int j = 0; j < n; j++)
3463
 
      {
3464
 
        // Update old coefficients
3465
 
        coeff0_0 = new_coeff0_0;
3466
 
        coeff0_1 = new_coeff0_1;
3467
 
        coeff0_2 = new_coeff0_2;
3468
 
        coeff0_3 = new_coeff0_3;
3469
 
    
3470
 
        if(combinations[deriv_num][j] == 0)
3471
 
        {
3472
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
3473
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
3474
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
3475
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
3476
 
        }
3477
 
        if(combinations[deriv_num][j] == 1)
3478
 
        {
3479
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
3480
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
3481
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
3482
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
3483
 
        }
3484
 
        if(combinations[deriv_num][j] == 2)
3485
 
        {
3486
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
3487
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
3488
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
3489
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
3490
 
        }
3491
 
    
3492
 
      }
3493
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
3494
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
3495
 
    }
3496
 
    
3497
 
    // Transform derivatives back to physical element
3498
 
    for (unsigned int row = 0; row < num_derivatives; row++)
3499
 
    {
3500
 
      for (unsigned int col = 0; col < num_derivatives; col++)
3501
 
      {
3502
 
        values[row] += transform[row][col]*derivatives[col];
3503
 
      }
3504
 
    }
3505
 
    // Delete pointer to array of derivatives on FIAT element
3506
 
    delete [] derivatives;
3507
 
    
3508
 
    // Delete pointer to array of combinations of derivatives and transform
3509
 
    for (unsigned int row = 0; row < num_derivatives; row++)
3510
 
    {
3511
 
      delete [] combinations[row];
3512
 
      delete [] transform[row];
3513
 
    }
3514
 
    
3515
 
    delete [] combinations;
3516
 
    delete [] transform;
3517
 
  }
3518
 
 
3519
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
3520
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
3521
 
                                              double* values,
3522
 
                                              const double* coordinates,
3523
 
                                              const ufc::cell& c) const
3524
 
  {
3525
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
3526
 
  }
3527
 
 
3528
 
  /// Evaluate linear functional for dof i on the function f
3529
 
  virtual double evaluate_dof(unsigned int i,
3530
 
                              const ufc::function& f,
3531
 
                              const ufc::cell& c) const
3532
 
  {
3533
 
    // The reference points, direction and weights:
3534
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
3535
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
3536
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
3537
 
    
3538
 
    const double * const * x = c.coordinates;
3539
 
    double result = 0.0;
3540
 
    // Iterate over the points:
3541
 
    // Evaluate basis functions for affine mapping
3542
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
3543
 
    const double w1 = X[i][0][0];
3544
 
    const double w2 = X[i][0][1];
3545
 
    const double w3 = X[i][0][2];
3546
 
    
3547
 
    // Compute affine mapping y = F(X)
3548
 
    double y[3];
3549
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
3550
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
3551
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
3552
 
    
3553
 
    // Evaluate function at physical points
3554
 
    double values[1];
3555
 
    f.evaluate(values, y, c);
3556
 
    
3557
 
    // Map function values using appropriate mapping
3558
 
    // Affine map: Do nothing
3559
 
    
3560
 
    // Note that we do not map the weights (yet).
3561
 
    
3562
 
    // Take directional components
3563
 
    for(int k = 0; k < 1; k++)
3564
 
      result += values[k]*D[i][0][k];
3565
 
    // Multiply by weights
3566
 
    result *= W[i][0];
3567
 
    
3568
 
    return result;
3569
 
  }
3570
 
 
3571
 
  /// Evaluate linear functionals for all dofs on the function f
3572
 
  virtual void evaluate_dofs(double* values,
3573
 
                             const ufc::function& f,
3574
 
                             const ufc::cell& c) const
3575
 
  {
3576
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3577
 
  }
3578
 
 
3579
 
  /// Interpolate vertex values from dof values
3580
 
  virtual void interpolate_vertex_values(double* vertex_values,
3581
 
                                         const double* dof_values,
3582
 
                                         const ufc::cell& c) const
3583
 
  {
3584
 
    // Evaluate at vertices and use affine mapping
3585
 
    vertex_values[0] = dof_values[0];
3586
 
    vertex_values[1] = dof_values[1];
3587
 
    vertex_values[2] = dof_values[2];
3588
 
    vertex_values[3] = dof_values[3];
3589
 
  }
3590
 
 
3591
 
  /// Return the number of sub elements (for a mixed element)
3592
 
  virtual unsigned int num_sub_elements() const
3593
 
  {
3594
 
    return 1;
3595
 
  }
3596
 
 
3597
 
  /// Create a new finite element for sub element i (for a mixed element)
3598
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
3599
 
  {
3600
 
    return new hyperelasticity_0_finite_element_1_1();
3601
 
  }
3602
 
 
3603
 
};
3604
 
 
3605
 
/// This class defines the interface for a finite element.
3606
 
 
3607
 
class hyperelasticity_0_finite_element_1_2: public ufc::finite_element
3608
 
{
3609
 
public:
3610
 
 
3611
 
  /// Constructor
3612
 
  hyperelasticity_0_finite_element_1_2() : ufc::finite_element()
3613
 
  {
3614
 
    // Do nothing
3615
 
  }
3616
 
 
3617
 
  /// Destructor
3618
 
  virtual ~hyperelasticity_0_finite_element_1_2()
3619
 
  {
3620
 
    // Do nothing
3621
 
  }
3622
 
 
3623
 
  /// Return a string identifying the finite element
3624
 
  virtual const char* signature() const
3625
 
  {
3626
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
3627
 
  }
3628
 
 
3629
 
  /// Return the cell shape
3630
 
  virtual ufc::shape cell_shape() const
3631
 
  {
3632
 
    return ufc::tetrahedron;
3633
 
  }
3634
 
 
3635
 
  /// Return the dimension of the finite element function space
3636
 
  virtual unsigned int space_dimension() const
3637
 
  {
3638
 
    return 4;
3639
 
  }
3640
 
 
3641
 
  /// Return the rank of the value space
3642
 
  virtual unsigned int value_rank() const
3643
 
  {
3644
 
    return 0;
3645
 
  }
3646
 
 
3647
 
  /// Return the dimension of the value space for axis i
3648
 
  virtual unsigned int value_dimension(unsigned int i) const
3649
 
  {
3650
 
    return 1;
3651
 
  }
3652
 
 
3653
 
  /// Evaluate basis function i at given point in cell
3654
 
  virtual void evaluate_basis(unsigned int i,
3655
 
                              double* values,
3656
 
                              const double* coordinates,
3657
 
                              const ufc::cell& c) const
3658
 
  {
3659
 
    // Extract vertex coordinates
3660
 
    const double * const * element_coordinates = c.coordinates;
3661
 
    
3662
 
    // Compute Jacobian of affine map from reference cell
3663
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
3664
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
3665
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
3666
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
3667
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
3668
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
3669
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
3670
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
3671
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
3672
 
    
3673
 
    // Compute sub determinants
3674
 
    const double d00 = J_11*J_22 - J_12*J_21;
3675
 
    const double d01 = J_12*J_20 - J_10*J_22;
3676
 
    const double d02 = J_10*J_21 - J_11*J_20;
3677
 
    
3678
 
    const double d10 = J_02*J_21 - J_01*J_22;
3679
 
    const double d11 = J_00*J_22 - J_02*J_20;
3680
 
    const double d12 = J_01*J_20 - J_00*J_21;
3681
 
    
3682
 
    const double d20 = J_01*J_12 - J_02*J_11;
3683
 
    const double d21 = J_02*J_10 - J_00*J_12;
3684
 
    const double d22 = J_00*J_11 - J_01*J_10;
3685
 
    
3686
 
    // Compute determinant of Jacobian
3687
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
3688
 
    
3689
 
    // Compute inverse of Jacobian
3690
 
    
3691
 
    // Compute constants
3692
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
3693
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
3694
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
3695
 
    
3696
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
3697
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
3698
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
3699
 
    
3700
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
3701
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
3702
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
3703
 
    
3704
 
    // Get coordinates and map to the UFC reference element
3705
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
3706
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
3707
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
3708
 
    
3709
 
    // Map coordinates to the reference cube
3710
 
    if (std::abs(y + z - 1.0) < 1e-08)
3711
 
      x = 1.0;
3712
 
    else
3713
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
3714
 
    if (std::abs(z - 1.0) < 1e-08)
3715
 
      y = -1.0;
3716
 
    else
3717
 
      y = 2.0 * y/(1.0 - z) - 1.0;
3718
 
    z = 2.0 * z - 1.0;
3719
 
    
3720
 
    // Reset values
3721
 
    *values = 0;
3722
 
    
3723
 
    // Map degree of freedom to element degree of freedom
3724
 
    const unsigned int dof = i;
3725
 
    
3726
 
    // Generate scalings
3727
 
    const double scalings_y_0 = 1;
3728
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
3729
 
    const double scalings_z_0 = 1;
3730
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
3731
 
    
3732
 
    // Compute psitilde_a
3733
 
    const double psitilde_a_0 = 1;
3734
 
    const double psitilde_a_1 = x;
3735
 
    
3736
 
    // Compute psitilde_bs
3737
 
    const double psitilde_bs_0_0 = 1;
3738
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
3739
 
    const double psitilde_bs_1_0 = 1;
3740
 
    
3741
 
    // Compute psitilde_cs
3742
 
    const double psitilde_cs_00_0 = 1;
3743
 
    const double psitilde_cs_00_1 = 2*z + 1;
3744
 
    const double psitilde_cs_01_0 = 1;
3745
 
    const double psitilde_cs_10_0 = 1;
3746
 
    
3747
 
    // Compute basisvalues
3748
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
3749
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
3750
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
3751
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
3752
 
    
3753
 
    // Table(s) of coefficients
3754
 
    static const double coefficients0[4][4] = \
3755
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
3756
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
3757
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
3758
 
    {0.288675135, 0, 0, 0.223606798}};
3759
 
    
3760
 
    // Extract relevant coefficients
3761
 
    const double coeff0_0 = coefficients0[dof][0];
3762
 
    const double coeff0_1 = coefficients0[dof][1];
3763
 
    const double coeff0_2 = coefficients0[dof][2];
3764
 
    const double coeff0_3 = coefficients0[dof][3];
3765
 
    
3766
 
    // Compute value(s)
3767
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
3768
 
  }
3769
 
 
3770
 
  /// Evaluate all basis functions at given point in cell
3771
 
  virtual void evaluate_basis_all(double* values,
3772
 
                                  const double* coordinates,
3773
 
                                  const ufc::cell& c) const
3774
 
  {
3775
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
3776
 
  }
3777
 
 
3778
 
  /// Evaluate order n derivatives of basis function i at given point in cell
3779
 
  virtual void evaluate_basis_derivatives(unsigned int i,
3780
 
                                          unsigned int n,
3781
 
                                          double* values,
3782
 
                                          const double* coordinates,
3783
 
                                          const ufc::cell& c) const
3784
 
  {
3785
 
    // Extract vertex coordinates
3786
 
    const double * const * element_coordinates = c.coordinates;
3787
 
    
3788
 
    // Compute Jacobian of affine map from reference cell
3789
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
3790
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
3791
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
3792
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
3793
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
3794
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
3795
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
3796
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
3797
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
3798
 
    
3799
 
    // Compute sub determinants
3800
 
    const double d00 = J_11*J_22 - J_12*J_21;
3801
 
    const double d01 = J_12*J_20 - J_10*J_22;
3802
 
    const double d02 = J_10*J_21 - J_11*J_20;
3803
 
    
3804
 
    const double d10 = J_02*J_21 - J_01*J_22;
3805
 
    const double d11 = J_00*J_22 - J_02*J_20;
3806
 
    const double d12 = J_01*J_20 - J_00*J_21;
3807
 
    
3808
 
    const double d20 = J_01*J_12 - J_02*J_11;
3809
 
    const double d21 = J_02*J_10 - J_00*J_12;
3810
 
    const double d22 = J_00*J_11 - J_01*J_10;
3811
 
    
3812
 
    // Compute determinant of Jacobian
3813
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
3814
 
    
3815
 
    // Compute inverse of Jacobian
3816
 
    
3817
 
    // Compute constants
3818
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
3819
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
3820
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
3821
 
    
3822
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
3823
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
3824
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
3825
 
    
3826
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
3827
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
3828
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
3829
 
    
3830
 
    // Get coordinates and map to the UFC reference element
3831
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
3832
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
3833
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
3834
 
    
3835
 
    // Map coordinates to the reference cube
3836
 
    if (std::abs(y + z - 1.0) < 1e-08)
3837
 
      x = 1.0;
3838
 
    else
3839
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
3840
 
    if (std::abs(z - 1.0) < 1e-08)
3841
 
      y = -1.0;
3842
 
    else
3843
 
      y = 2.0 * y/(1.0 - z) - 1.0;
3844
 
    z = 2.0 * z - 1.0;
3845
 
    
3846
 
    // Compute number of derivatives
3847
 
    unsigned int num_derivatives = 1;
3848
 
    
3849
 
    for (unsigned int j = 0; j < n; j++)
3850
 
      num_derivatives *= 3;
3851
 
    
3852
 
    
3853
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
3854
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
3855
 
    
3856
 
    for (unsigned int j = 0; j < num_derivatives; j++)
3857
 
    {
3858
 
      combinations[j] = new unsigned int [n];
3859
 
      for (unsigned int k = 0; k < n; k++)
3860
 
        combinations[j][k] = 0;
3861
 
    }
3862
 
    
3863
 
    // Generate combinations of derivatives
3864
 
    for (unsigned int row = 1; row < num_derivatives; row++)
3865
 
    {
3866
 
      for (unsigned int num = 0; num < row; num++)
3867
 
      {
3868
 
        for (unsigned int col = n-1; col+1 > 0; col--)
3869
 
        {
3870
 
          if (combinations[row][col] + 1 > 2)
3871
 
            combinations[row][col] = 0;
3872
 
          else
3873
 
          {
3874
 
            combinations[row][col] += 1;
3875
 
            break;
3876
 
          }
3877
 
        }
3878
 
      }
3879
 
    }
3880
 
    
3881
 
    // Compute inverse of Jacobian
3882
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
3883
 
    
3884
 
    // Declare transformation matrix
3885
 
    // Declare pointer to two dimensional array and initialise
3886
 
    double **transform = new double *[num_derivatives];
3887
 
    
3888
 
    for (unsigned int j = 0; j < num_derivatives; j++)
3889
 
    {
3890
 
      transform[j] = new double [num_derivatives];
3891
 
      for (unsigned int k = 0; k < num_derivatives; k++)
3892
 
        transform[j][k] = 1;
3893
 
    }
3894
 
    
3895
 
    // Construct transformation matrix
3896
 
    for (unsigned int row = 0; row < num_derivatives; row++)
3897
 
    {
3898
 
      for (unsigned int col = 0; col < num_derivatives; col++)
3899
 
      {
3900
 
        for (unsigned int k = 0; k < n; k++)
3901
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
3902
 
      }
3903
 
    }
3904
 
    
3905
 
    // Reset values
3906
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
3907
 
      values[j] = 0;
3908
 
    
3909
 
    // Map degree of freedom to element degree of freedom
3910
 
    const unsigned int dof = i;
3911
 
    
3912
 
    // Generate scalings
3913
 
    const double scalings_y_0 = 1;
3914
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
3915
 
    const double scalings_z_0 = 1;
3916
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
3917
 
    
3918
 
    // Compute psitilde_a
3919
 
    const double psitilde_a_0 = 1;
3920
 
    const double psitilde_a_1 = x;
3921
 
    
3922
 
    // Compute psitilde_bs
3923
 
    const double psitilde_bs_0_0 = 1;
3924
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
3925
 
    const double psitilde_bs_1_0 = 1;
3926
 
    
3927
 
    // Compute psitilde_cs
3928
 
    const double psitilde_cs_00_0 = 1;
3929
 
    const double psitilde_cs_00_1 = 2*z + 1;
3930
 
    const double psitilde_cs_01_0 = 1;
3931
 
    const double psitilde_cs_10_0 = 1;
3932
 
    
3933
 
    // Compute basisvalues
3934
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
3935
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
3936
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
3937
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
3938
 
    
3939
 
    // Table(s) of coefficients
3940
 
    static const double coefficients0[4][4] = \
3941
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
3942
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
3943
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
3944
 
    {0.288675135, 0, 0, 0.223606798}};
3945
 
    
3946
 
    // Interesting (new) part
3947
 
    // Tables of derivatives of the polynomial base (transpose)
3948
 
    static const double dmats0[4][4] = \
3949
 
    {{0, 0, 0, 0},
3950
 
    {6.32455532, 0, 0, 0},
3951
 
    {0, 0, 0, 0},
3952
 
    {0, 0, 0, 0}};
3953
 
    
3954
 
    static const double dmats1[4][4] = \
3955
 
    {{0, 0, 0, 0},
3956
 
    {3.16227766, 0, 0, 0},
3957
 
    {5.47722558, 0, 0, 0},
3958
 
    {0, 0, 0, 0}};
3959
 
    
3960
 
    static const double dmats2[4][4] = \
3961
 
    {{0, 0, 0, 0},
3962
 
    {3.16227766, 0, 0, 0},
3963
 
    {1.82574186, 0, 0, 0},
3964
 
    {5.16397779, 0, 0, 0}};
3965
 
    
3966
 
    // Compute reference derivatives
3967
 
    // Declare pointer to array of derivatives on FIAT element
3968
 
    double *derivatives = new double [num_derivatives];
3969
 
    
3970
 
    // Declare coefficients
3971
 
    double coeff0_0 = 0;
3972
 
    double coeff0_1 = 0;
3973
 
    double coeff0_2 = 0;
3974
 
    double coeff0_3 = 0;
3975
 
    
3976
 
    // Declare new coefficients
3977
 
    double new_coeff0_0 = 0;
3978
 
    double new_coeff0_1 = 0;
3979
 
    double new_coeff0_2 = 0;
3980
 
    double new_coeff0_3 = 0;
3981
 
    
3982
 
    // Loop possible derivatives
3983
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
3984
 
    {
3985
 
      // Get values from coefficients array
3986
 
      new_coeff0_0 = coefficients0[dof][0];
3987
 
      new_coeff0_1 = coefficients0[dof][1];
3988
 
      new_coeff0_2 = coefficients0[dof][2];
3989
 
      new_coeff0_3 = coefficients0[dof][3];
3990
 
    
3991
 
      // Loop derivative order
3992
 
      for (unsigned int j = 0; j < n; j++)
3993
 
      {
3994
 
        // Update old coefficients
3995
 
        coeff0_0 = new_coeff0_0;
3996
 
        coeff0_1 = new_coeff0_1;
3997
 
        coeff0_2 = new_coeff0_2;
3998
 
        coeff0_3 = new_coeff0_3;
3999
 
    
4000
 
        if(combinations[deriv_num][j] == 0)
4001
 
        {
4002
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
4003
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
4004
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
4005
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
4006
 
        }
4007
 
        if(combinations[deriv_num][j] == 1)
4008
 
        {
4009
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
4010
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
4011
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
4012
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
4013
 
        }
4014
 
        if(combinations[deriv_num][j] == 2)
4015
 
        {
4016
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
4017
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
4018
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
4019
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
4020
 
        }
4021
 
    
4022
 
      }
4023
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
4024
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
4025
 
    }
4026
 
    
4027
 
    // Transform derivatives back to physical element
4028
 
    for (unsigned int row = 0; row < num_derivatives; row++)
4029
 
    {
4030
 
      for (unsigned int col = 0; col < num_derivatives; col++)
4031
 
      {
4032
 
        values[row] += transform[row][col]*derivatives[col];
4033
 
      }
4034
 
    }
4035
 
    // Delete pointer to array of derivatives on FIAT element
4036
 
    delete [] derivatives;
4037
 
    
4038
 
    // Delete pointer to array of combinations of derivatives and transform
4039
 
    for (unsigned int row = 0; row < num_derivatives; row++)
4040
 
    {
4041
 
      delete [] combinations[row];
4042
 
      delete [] transform[row];
4043
 
    }
4044
 
    
4045
 
    delete [] combinations;
4046
 
    delete [] transform;
4047
 
  }
4048
 
 
4049
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
4050
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
4051
 
                                              double* values,
4052
 
                                              const double* coordinates,
4053
 
                                              const ufc::cell& c) const
4054
 
  {
4055
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
4056
 
  }
4057
 
 
4058
 
  /// Evaluate linear functional for dof i on the function f
4059
 
  virtual double evaluate_dof(unsigned int i,
4060
 
                              const ufc::function& f,
4061
 
                              const ufc::cell& c) const
4062
 
  {
4063
 
    // The reference points, direction and weights:
4064
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
4065
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
4066
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
4067
 
    
4068
 
    const double * const * x = c.coordinates;
4069
 
    double result = 0.0;
4070
 
    // Iterate over the points:
4071
 
    // Evaluate basis functions for affine mapping
4072
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
4073
 
    const double w1 = X[i][0][0];
4074
 
    const double w2 = X[i][0][1];
4075
 
    const double w3 = X[i][0][2];
4076
 
    
4077
 
    // Compute affine mapping y = F(X)
4078
 
    double y[3];
4079
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
4080
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
4081
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
4082
 
    
4083
 
    // Evaluate function at physical points
4084
 
    double values[1];
4085
 
    f.evaluate(values, y, c);
4086
 
    
4087
 
    // Map function values using appropriate mapping
4088
 
    // Affine map: Do nothing
4089
 
    
4090
 
    // Note that we do not map the weights (yet).
4091
 
    
4092
 
    // Take directional components
4093
 
    for(int k = 0; k < 1; k++)
4094
 
      result += values[k]*D[i][0][k];
4095
 
    // Multiply by weights
4096
 
    result *= W[i][0];
4097
 
    
4098
 
    return result;
4099
 
  }
4100
 
 
4101
 
  /// Evaluate linear functionals for all dofs on the function f
4102
 
  virtual void evaluate_dofs(double* values,
4103
 
                             const ufc::function& f,
4104
 
                             const ufc::cell& c) const
4105
 
  {
4106
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
4107
 
  }
4108
 
 
4109
 
  /// Interpolate vertex values from dof values
4110
 
  virtual void interpolate_vertex_values(double* vertex_values,
4111
 
                                         const double* dof_values,
4112
 
                                         const ufc::cell& c) const
4113
 
  {
4114
 
    // Evaluate at vertices and use affine mapping
4115
 
    vertex_values[0] = dof_values[0];
4116
 
    vertex_values[1] = dof_values[1];
4117
 
    vertex_values[2] = dof_values[2];
4118
 
    vertex_values[3] = dof_values[3];
4119
 
  }
4120
 
 
4121
 
  /// Return the number of sub elements (for a mixed element)
4122
 
  virtual unsigned int num_sub_elements() const
4123
 
  {
4124
 
    return 1;
4125
 
  }
4126
 
 
4127
 
  /// Create a new finite element for sub element i (for a mixed element)
4128
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
4129
 
  {
4130
 
    return new hyperelasticity_0_finite_element_1_2();
4131
 
  }
4132
 
 
4133
 
};
4134
 
 
4135
 
/// This class defines the interface for a finite element.
4136
 
 
4137
 
class hyperelasticity_0_finite_element_1: public ufc::finite_element
4138
 
{
4139
 
public:
4140
 
 
4141
 
  /// Constructor
4142
 
  hyperelasticity_0_finite_element_1() : ufc::finite_element()
4143
 
  {
4144
 
    // Do nothing
4145
 
  }
4146
 
 
4147
 
  /// Destructor
4148
 
  virtual ~hyperelasticity_0_finite_element_1()
4149
 
  {
4150
 
    // Do nothing
4151
 
  }
4152
 
 
4153
 
  /// Return a string identifying the finite element
4154
 
  virtual const char* signature() const
4155
 
  {
4156
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
4157
 
  }
4158
 
 
4159
 
  /// Return the cell shape
4160
 
  virtual ufc::shape cell_shape() const
4161
 
  {
4162
 
    return ufc::tetrahedron;
4163
 
  }
4164
 
 
4165
 
  /// Return the dimension of the finite element function space
4166
 
  virtual unsigned int space_dimension() const
4167
 
  {
4168
 
    return 12;
4169
 
  }
4170
 
 
4171
 
  /// Return the rank of the value space
4172
 
  virtual unsigned int value_rank() const
4173
 
  {
4174
 
    return 1;
4175
 
  }
4176
 
 
4177
 
  /// Return the dimension of the value space for axis i
4178
 
  virtual unsigned int value_dimension(unsigned int i) const
4179
 
  {
4180
 
    return 3;
4181
 
  }
4182
 
 
4183
 
  /// Evaluate basis function i at given point in cell
4184
 
  virtual void evaluate_basis(unsigned int i,
4185
 
                              double* values,
4186
 
                              const double* coordinates,
4187
 
                              const ufc::cell& c) const
4188
 
  {
4189
 
    // Extract vertex coordinates
4190
 
    const double * const * element_coordinates = c.coordinates;
4191
 
    
4192
 
    // Compute Jacobian of affine map from reference cell
4193
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
4194
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
4195
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
4196
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
4197
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
4198
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
4199
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
4200
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
4201
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
4202
 
    
4203
 
    // Compute sub determinants
4204
 
    const double d00 = J_11*J_22 - J_12*J_21;
4205
 
    const double d01 = J_12*J_20 - J_10*J_22;
4206
 
    const double d02 = J_10*J_21 - J_11*J_20;
4207
 
    
4208
 
    const double d10 = J_02*J_21 - J_01*J_22;
4209
 
    const double d11 = J_00*J_22 - J_02*J_20;
4210
 
    const double d12 = J_01*J_20 - J_00*J_21;
4211
 
    
4212
 
    const double d20 = J_01*J_12 - J_02*J_11;
4213
 
    const double d21 = J_02*J_10 - J_00*J_12;
4214
 
    const double d22 = J_00*J_11 - J_01*J_10;
4215
 
    
4216
 
    // Compute determinant of Jacobian
4217
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
4218
 
    
4219
 
    // Compute inverse of Jacobian
4220
 
    
4221
 
    // Compute constants
4222
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
4223
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
4224
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
4225
 
    
4226
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
4227
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
4228
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
4229
 
    
4230
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
4231
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
4232
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
4233
 
    
4234
 
    // Get coordinates and map to the UFC reference element
4235
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
4236
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
4237
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
4238
 
    
4239
 
    // Map coordinates to the reference cube
4240
 
    if (std::abs(y + z - 1.0) < 1e-08)
4241
 
      x = 1.0;
4242
 
    else
4243
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
4244
 
    if (std::abs(z - 1.0) < 1e-08)
4245
 
      y = -1.0;
4246
 
    else
4247
 
      y = 2.0 * y/(1.0 - z) - 1.0;
4248
 
    z = 2.0 * z - 1.0;
4249
 
    
4250
 
    // Reset values
4251
 
    values[0] = 0;
4252
 
    values[1] = 0;
4253
 
    values[2] = 0;
4254
 
    
4255
 
    if (0 <= i && i <= 3)
4256
 
    {
4257
 
      // Map degree of freedom to element degree of freedom
4258
 
      const unsigned int dof = i;
4259
 
    
4260
 
      // Generate scalings
4261
 
      const double scalings_y_0 = 1;
4262
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4263
 
      const double scalings_z_0 = 1;
4264
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4265
 
    
4266
 
      // Compute psitilde_a
4267
 
      const double psitilde_a_0 = 1;
4268
 
      const double psitilde_a_1 = x;
4269
 
    
4270
 
      // Compute psitilde_bs
4271
 
      const double psitilde_bs_0_0 = 1;
4272
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4273
 
      const double psitilde_bs_1_0 = 1;
4274
 
    
4275
 
      // Compute psitilde_cs
4276
 
      const double psitilde_cs_00_0 = 1;
4277
 
      const double psitilde_cs_00_1 = 2*z + 1;
4278
 
      const double psitilde_cs_01_0 = 1;
4279
 
      const double psitilde_cs_10_0 = 1;
4280
 
    
4281
 
      // Compute basisvalues
4282
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4283
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4284
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4285
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4286
 
    
4287
 
      // Table(s) of coefficients
4288
 
      static const double coefficients0[4][4] =   \
4289
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4290
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4291
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4292
 
      {0.288675135, 0, 0, 0.223606798}};
4293
 
    
4294
 
      // Extract relevant coefficients
4295
 
      const double coeff0_0 =   coefficients0[dof][0];
4296
 
      const double coeff0_1 =   coefficients0[dof][1];
4297
 
      const double coeff0_2 =   coefficients0[dof][2];
4298
 
      const double coeff0_3 =   coefficients0[dof][3];
4299
 
    
4300
 
      // Compute value(s)
4301
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
4302
 
    }
4303
 
    
4304
 
    if (4 <= i && i <= 7)
4305
 
    {
4306
 
      // Map degree of freedom to element degree of freedom
4307
 
      const unsigned int dof = i - 4;
4308
 
    
4309
 
      // Generate scalings
4310
 
      const double scalings_y_0 = 1;
4311
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4312
 
      const double scalings_z_0 = 1;
4313
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4314
 
    
4315
 
      // Compute psitilde_a
4316
 
      const double psitilde_a_0 = 1;
4317
 
      const double psitilde_a_1 = x;
4318
 
    
4319
 
      // Compute psitilde_bs
4320
 
      const double psitilde_bs_0_0 = 1;
4321
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4322
 
      const double psitilde_bs_1_0 = 1;
4323
 
    
4324
 
      // Compute psitilde_cs
4325
 
      const double psitilde_cs_00_0 = 1;
4326
 
      const double psitilde_cs_00_1 = 2*z + 1;
4327
 
      const double psitilde_cs_01_0 = 1;
4328
 
      const double psitilde_cs_10_0 = 1;
4329
 
    
4330
 
      // Compute basisvalues
4331
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4332
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4333
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4334
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4335
 
    
4336
 
      // Table(s) of coefficients
4337
 
      static const double coefficients0[4][4] =   \
4338
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4339
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4340
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4341
 
      {0.288675135, 0, 0, 0.223606798}};
4342
 
    
4343
 
      // Extract relevant coefficients
4344
 
      const double coeff0_0 =   coefficients0[dof][0];
4345
 
      const double coeff0_1 =   coefficients0[dof][1];
4346
 
      const double coeff0_2 =   coefficients0[dof][2];
4347
 
      const double coeff0_3 =   coefficients0[dof][3];
4348
 
    
4349
 
      // Compute value(s)
4350
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
4351
 
    }
4352
 
    
4353
 
    if (8 <= i && i <= 11)
4354
 
    {
4355
 
      // Map degree of freedom to element degree of freedom
4356
 
      const unsigned int dof = i - 8;
4357
 
    
4358
 
      // Generate scalings
4359
 
      const double scalings_y_0 = 1;
4360
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4361
 
      const double scalings_z_0 = 1;
4362
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4363
 
    
4364
 
      // Compute psitilde_a
4365
 
      const double psitilde_a_0 = 1;
4366
 
      const double psitilde_a_1 = x;
4367
 
    
4368
 
      // Compute psitilde_bs
4369
 
      const double psitilde_bs_0_0 = 1;
4370
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4371
 
      const double psitilde_bs_1_0 = 1;
4372
 
    
4373
 
      // Compute psitilde_cs
4374
 
      const double psitilde_cs_00_0 = 1;
4375
 
      const double psitilde_cs_00_1 = 2*z + 1;
4376
 
      const double psitilde_cs_01_0 = 1;
4377
 
      const double psitilde_cs_10_0 = 1;
4378
 
    
4379
 
      // Compute basisvalues
4380
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4381
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4382
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4383
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4384
 
    
4385
 
      // Table(s) of coefficients
4386
 
      static const double coefficients0[4][4] =   \
4387
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4388
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4389
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4390
 
      {0.288675135, 0, 0, 0.223606798}};
4391
 
    
4392
 
      // Extract relevant coefficients
4393
 
      const double coeff0_0 =   coefficients0[dof][0];
4394
 
      const double coeff0_1 =   coefficients0[dof][1];
4395
 
      const double coeff0_2 =   coefficients0[dof][2];
4396
 
      const double coeff0_3 =   coefficients0[dof][3];
4397
 
    
4398
 
      // Compute value(s)
4399
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
4400
 
    }
4401
 
    
4402
 
  }
4403
 
 
4404
 
  /// Evaluate all basis functions at given point in cell
4405
 
  virtual void evaluate_basis_all(double* values,
4406
 
                                  const double* coordinates,
4407
 
                                  const ufc::cell& c) const
4408
 
  {
4409
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
4410
 
  }
4411
 
 
4412
 
  /// Evaluate order n derivatives of basis function i at given point in cell
4413
 
  virtual void evaluate_basis_derivatives(unsigned int i,
4414
 
                                          unsigned int n,
4415
 
                                          double* values,
4416
 
                                          const double* coordinates,
4417
 
                                          const ufc::cell& c) const
4418
 
  {
4419
 
    // Extract vertex coordinates
4420
 
    const double * const * element_coordinates = c.coordinates;
4421
 
    
4422
 
    // Compute Jacobian of affine map from reference cell
4423
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
4424
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
4425
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
4426
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
4427
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
4428
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
4429
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
4430
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
4431
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
4432
 
    
4433
 
    // Compute sub determinants
4434
 
    const double d00 = J_11*J_22 - J_12*J_21;
4435
 
    const double d01 = J_12*J_20 - J_10*J_22;
4436
 
    const double d02 = J_10*J_21 - J_11*J_20;
4437
 
    
4438
 
    const double d10 = J_02*J_21 - J_01*J_22;
4439
 
    const double d11 = J_00*J_22 - J_02*J_20;
4440
 
    const double d12 = J_01*J_20 - J_00*J_21;
4441
 
    
4442
 
    const double d20 = J_01*J_12 - J_02*J_11;
4443
 
    const double d21 = J_02*J_10 - J_00*J_12;
4444
 
    const double d22 = J_00*J_11 - J_01*J_10;
4445
 
    
4446
 
    // Compute determinant of Jacobian
4447
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
4448
 
    
4449
 
    // Compute inverse of Jacobian
4450
 
    
4451
 
    // Compute constants
4452
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
4453
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
4454
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
4455
 
    
4456
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
4457
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
4458
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
4459
 
    
4460
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
4461
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
4462
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
4463
 
    
4464
 
    // Get coordinates and map to the UFC reference element
4465
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
4466
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
4467
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
4468
 
    
4469
 
    // Map coordinates to the reference cube
4470
 
    if (std::abs(y + z - 1.0) < 1e-08)
4471
 
      x = 1.0;
4472
 
    else
4473
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
4474
 
    if (std::abs(z - 1.0) < 1e-08)
4475
 
      y = -1.0;
4476
 
    else
4477
 
      y = 2.0 * y/(1.0 - z) - 1.0;
4478
 
    z = 2.0 * z - 1.0;
4479
 
    
4480
 
    // Compute number of derivatives
4481
 
    unsigned int num_derivatives = 1;
4482
 
    
4483
 
    for (unsigned int j = 0; j < n; j++)
4484
 
      num_derivatives *= 3;
4485
 
    
4486
 
    
4487
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
4488
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
4489
 
    
4490
 
    for (unsigned int j = 0; j < num_derivatives; j++)
4491
 
    {
4492
 
      combinations[j] = new unsigned int [n];
4493
 
      for (unsigned int k = 0; k < n; k++)
4494
 
        combinations[j][k] = 0;
4495
 
    }
4496
 
    
4497
 
    // Generate combinations of derivatives
4498
 
    for (unsigned int row = 1; row < num_derivatives; row++)
4499
 
    {
4500
 
      for (unsigned int num = 0; num < row; num++)
4501
 
      {
4502
 
        for (unsigned int col = n-1; col+1 > 0; col--)
4503
 
        {
4504
 
          if (combinations[row][col] + 1 > 2)
4505
 
            combinations[row][col] = 0;
4506
 
          else
4507
 
          {
4508
 
            combinations[row][col] += 1;
4509
 
            break;
4510
 
          }
4511
 
        }
4512
 
      }
4513
 
    }
4514
 
    
4515
 
    // Compute inverse of Jacobian
4516
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
4517
 
    
4518
 
    // Declare transformation matrix
4519
 
    // Declare pointer to two dimensional array and initialise
4520
 
    double **transform = new double *[num_derivatives];
4521
 
    
4522
 
    for (unsigned int j = 0; j < num_derivatives; j++)
4523
 
    {
4524
 
      transform[j] = new double [num_derivatives];
4525
 
      for (unsigned int k = 0; k < num_derivatives; k++)
4526
 
        transform[j][k] = 1;
4527
 
    }
4528
 
    
4529
 
    // Construct transformation matrix
4530
 
    for (unsigned int row = 0; row < num_derivatives; row++)
4531
 
    {
4532
 
      for (unsigned int col = 0; col < num_derivatives; col++)
4533
 
      {
4534
 
        for (unsigned int k = 0; k < n; k++)
4535
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
4536
 
      }
4537
 
    }
4538
 
    
4539
 
    // Reset values
4540
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
4541
 
      values[j] = 0;
4542
 
    
4543
 
    if (0 <= i && i <= 3)
4544
 
    {
4545
 
      // Map degree of freedom to element degree of freedom
4546
 
      const unsigned int dof = i;
4547
 
    
4548
 
      // Generate scalings
4549
 
      const double scalings_y_0 = 1;
4550
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4551
 
      const double scalings_z_0 = 1;
4552
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4553
 
    
4554
 
      // Compute psitilde_a
4555
 
      const double psitilde_a_0 = 1;
4556
 
      const double psitilde_a_1 = x;
4557
 
    
4558
 
      // Compute psitilde_bs
4559
 
      const double psitilde_bs_0_0 = 1;
4560
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4561
 
      const double psitilde_bs_1_0 = 1;
4562
 
    
4563
 
      // Compute psitilde_cs
4564
 
      const double psitilde_cs_00_0 = 1;
4565
 
      const double psitilde_cs_00_1 = 2*z + 1;
4566
 
      const double psitilde_cs_01_0 = 1;
4567
 
      const double psitilde_cs_10_0 = 1;
4568
 
    
4569
 
      // Compute basisvalues
4570
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4571
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4572
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4573
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4574
 
    
4575
 
      // Table(s) of coefficients
4576
 
      static const double coefficients0[4][4] =   \
4577
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4578
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4579
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4580
 
      {0.288675135, 0, 0, 0.223606798}};
4581
 
    
4582
 
      // Interesting (new) part
4583
 
      // Tables of derivatives of the polynomial base (transpose)
4584
 
      static const double dmats0[4][4] =   \
4585
 
      {{0, 0, 0, 0},
4586
 
      {6.32455532, 0, 0, 0},
4587
 
      {0, 0, 0, 0},
4588
 
      {0, 0, 0, 0}};
4589
 
    
4590
 
      static const double dmats1[4][4] =   \
4591
 
      {{0, 0, 0, 0},
4592
 
      {3.16227766, 0, 0, 0},
4593
 
      {5.47722558, 0, 0, 0},
4594
 
      {0, 0, 0, 0}};
4595
 
    
4596
 
      static const double dmats2[4][4] =   \
4597
 
      {{0, 0, 0, 0},
4598
 
      {3.16227766, 0, 0, 0},
4599
 
      {1.82574186, 0, 0, 0},
4600
 
      {5.16397779, 0, 0, 0}};
4601
 
    
4602
 
      // Compute reference derivatives
4603
 
      // Declare pointer to array of derivatives on FIAT element
4604
 
      double *derivatives = new double [num_derivatives];
4605
 
    
4606
 
      // Declare coefficients
4607
 
      double coeff0_0 = 0;
4608
 
      double coeff0_1 = 0;
4609
 
      double coeff0_2 = 0;
4610
 
      double coeff0_3 = 0;
4611
 
    
4612
 
      // Declare new coefficients
4613
 
      double new_coeff0_0 = 0;
4614
 
      double new_coeff0_1 = 0;
4615
 
      double new_coeff0_2 = 0;
4616
 
      double new_coeff0_3 = 0;
4617
 
    
4618
 
      // Loop possible derivatives
4619
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
4620
 
      {
4621
 
        // Get values from coefficients array
4622
 
        new_coeff0_0 = coefficients0[dof][0];
4623
 
        new_coeff0_1 = coefficients0[dof][1];
4624
 
        new_coeff0_2 = coefficients0[dof][2];
4625
 
        new_coeff0_3 = coefficients0[dof][3];
4626
 
    
4627
 
        // Loop derivative order
4628
 
        for (unsigned int j = 0; j < n; j++)
4629
 
        {
4630
 
          // Update old coefficients
4631
 
          coeff0_0 = new_coeff0_0;
4632
 
          coeff0_1 = new_coeff0_1;
4633
 
          coeff0_2 = new_coeff0_2;
4634
 
          coeff0_3 = new_coeff0_3;
4635
 
    
4636
 
          if(combinations[deriv_num][j] == 0)
4637
 
          {
4638
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
4639
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
4640
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
4641
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
4642
 
          }
4643
 
          if(combinations[deriv_num][j] == 1)
4644
 
          {
4645
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
4646
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
4647
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
4648
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
4649
 
          }
4650
 
          if(combinations[deriv_num][j] == 2)
4651
 
          {
4652
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
4653
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
4654
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
4655
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
4656
 
          }
4657
 
    
4658
 
        }
4659
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
4660
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
4661
 
      }
4662
 
    
4663
 
      // Transform derivatives back to physical element
4664
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4665
 
      {
4666
 
        for (unsigned int col = 0; col < num_derivatives; col++)
4667
 
        {
4668
 
          values[row] += transform[row][col]*derivatives[col];
4669
 
        }
4670
 
      }
4671
 
      // Delete pointer to array of derivatives on FIAT element
4672
 
      delete [] derivatives;
4673
 
    
4674
 
      // Delete pointer to array of combinations of derivatives and transform
4675
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4676
 
      {
4677
 
        delete [] combinations[row];
4678
 
        delete [] transform[row];
4679
 
      }
4680
 
    
4681
 
      delete [] combinations;
4682
 
      delete [] transform;
4683
 
    }
4684
 
    
4685
 
    if (4 <= i && i <= 7)
4686
 
    {
4687
 
      // Map degree of freedom to element degree of freedom
4688
 
      const unsigned int dof = i - 4;
4689
 
    
4690
 
      // Generate scalings
4691
 
      const double scalings_y_0 = 1;
4692
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4693
 
      const double scalings_z_0 = 1;
4694
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4695
 
    
4696
 
      // Compute psitilde_a
4697
 
      const double psitilde_a_0 = 1;
4698
 
      const double psitilde_a_1 = x;
4699
 
    
4700
 
      // Compute psitilde_bs
4701
 
      const double psitilde_bs_0_0 = 1;
4702
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4703
 
      const double psitilde_bs_1_0 = 1;
4704
 
    
4705
 
      // Compute psitilde_cs
4706
 
      const double psitilde_cs_00_0 = 1;
4707
 
      const double psitilde_cs_00_1 = 2*z + 1;
4708
 
      const double psitilde_cs_01_0 = 1;
4709
 
      const double psitilde_cs_10_0 = 1;
4710
 
    
4711
 
      // Compute basisvalues
4712
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4713
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4714
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4715
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4716
 
    
4717
 
      // Table(s) of coefficients
4718
 
      static const double coefficients0[4][4] =   \
4719
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4720
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4721
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4722
 
      {0.288675135, 0, 0, 0.223606798}};
4723
 
    
4724
 
      // Interesting (new) part
4725
 
      // Tables of derivatives of the polynomial base (transpose)
4726
 
      static const double dmats0[4][4] =   \
4727
 
      {{0, 0, 0, 0},
4728
 
      {6.32455532, 0, 0, 0},
4729
 
      {0, 0, 0, 0},
4730
 
      {0, 0, 0, 0}};
4731
 
    
4732
 
      static const double dmats1[4][4] =   \
4733
 
      {{0, 0, 0, 0},
4734
 
      {3.16227766, 0, 0, 0},
4735
 
      {5.47722558, 0, 0, 0},
4736
 
      {0, 0, 0, 0}};
4737
 
    
4738
 
      static const double dmats2[4][4] =   \
4739
 
      {{0, 0, 0, 0},
4740
 
      {3.16227766, 0, 0, 0},
4741
 
      {1.82574186, 0, 0, 0},
4742
 
      {5.16397779, 0, 0, 0}};
4743
 
    
4744
 
      // Compute reference derivatives
4745
 
      // Declare pointer to array of derivatives on FIAT element
4746
 
      double *derivatives = new double [num_derivatives];
4747
 
    
4748
 
      // Declare coefficients
4749
 
      double coeff0_0 = 0;
4750
 
      double coeff0_1 = 0;
4751
 
      double coeff0_2 = 0;
4752
 
      double coeff0_3 = 0;
4753
 
    
4754
 
      // Declare new coefficients
4755
 
      double new_coeff0_0 = 0;
4756
 
      double new_coeff0_1 = 0;
4757
 
      double new_coeff0_2 = 0;
4758
 
      double new_coeff0_3 = 0;
4759
 
    
4760
 
      // Loop possible derivatives
4761
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
4762
 
      {
4763
 
        // Get values from coefficients array
4764
 
        new_coeff0_0 = coefficients0[dof][0];
4765
 
        new_coeff0_1 = coefficients0[dof][1];
4766
 
        new_coeff0_2 = coefficients0[dof][2];
4767
 
        new_coeff0_3 = coefficients0[dof][3];
4768
 
    
4769
 
        // Loop derivative order
4770
 
        for (unsigned int j = 0; j < n; j++)
4771
 
        {
4772
 
          // Update old coefficients
4773
 
          coeff0_0 = new_coeff0_0;
4774
 
          coeff0_1 = new_coeff0_1;
4775
 
          coeff0_2 = new_coeff0_2;
4776
 
          coeff0_3 = new_coeff0_3;
4777
 
    
4778
 
          if(combinations[deriv_num][j] == 0)
4779
 
          {
4780
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
4781
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
4782
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
4783
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
4784
 
          }
4785
 
          if(combinations[deriv_num][j] == 1)
4786
 
          {
4787
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
4788
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
4789
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
4790
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
4791
 
          }
4792
 
          if(combinations[deriv_num][j] == 2)
4793
 
          {
4794
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
4795
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
4796
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
4797
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
4798
 
          }
4799
 
    
4800
 
        }
4801
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
4802
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
4803
 
      }
4804
 
    
4805
 
      // Transform derivatives back to physical element
4806
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4807
 
      {
4808
 
        for (unsigned int col = 0; col < num_derivatives; col++)
4809
 
        {
4810
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
4811
 
        }
4812
 
      }
4813
 
      // Delete pointer to array of derivatives on FIAT element
4814
 
      delete [] derivatives;
4815
 
    
4816
 
      // Delete pointer to array of combinations of derivatives and transform
4817
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4818
 
      {
4819
 
        delete [] combinations[row];
4820
 
        delete [] transform[row];
4821
 
      }
4822
 
    
4823
 
      delete [] combinations;
4824
 
      delete [] transform;
4825
 
    }
4826
 
    
4827
 
    if (8 <= i && i <= 11)
4828
 
    {
4829
 
      // Map degree of freedom to element degree of freedom
4830
 
      const unsigned int dof = i - 8;
4831
 
    
4832
 
      // Generate scalings
4833
 
      const double scalings_y_0 = 1;
4834
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
4835
 
      const double scalings_z_0 = 1;
4836
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
4837
 
    
4838
 
      // Compute psitilde_a
4839
 
      const double psitilde_a_0 = 1;
4840
 
      const double psitilde_a_1 = x;
4841
 
    
4842
 
      // Compute psitilde_bs
4843
 
      const double psitilde_bs_0_0 = 1;
4844
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
4845
 
      const double psitilde_bs_1_0 = 1;
4846
 
    
4847
 
      // Compute psitilde_cs
4848
 
      const double psitilde_cs_00_0 = 1;
4849
 
      const double psitilde_cs_00_1 = 2*z + 1;
4850
 
      const double psitilde_cs_01_0 = 1;
4851
 
      const double psitilde_cs_10_0 = 1;
4852
 
    
4853
 
      // Compute basisvalues
4854
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
4855
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
4856
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
4857
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
4858
 
    
4859
 
      // Table(s) of coefficients
4860
 
      static const double coefficients0[4][4] =   \
4861
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
4862
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
4863
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
4864
 
      {0.288675135, 0, 0, 0.223606798}};
4865
 
    
4866
 
      // Interesting (new) part
4867
 
      // Tables of derivatives of the polynomial base (transpose)
4868
 
      static const double dmats0[4][4] =   \
4869
 
      {{0, 0, 0, 0},
4870
 
      {6.32455532, 0, 0, 0},
4871
 
      {0, 0, 0, 0},
4872
 
      {0, 0, 0, 0}};
4873
 
    
4874
 
      static const double dmats1[4][4] =   \
4875
 
      {{0, 0, 0, 0},
4876
 
      {3.16227766, 0, 0, 0},
4877
 
      {5.47722558, 0, 0, 0},
4878
 
      {0, 0, 0, 0}};
4879
 
    
4880
 
      static const double dmats2[4][4] =   \
4881
 
      {{0, 0, 0, 0},
4882
 
      {3.16227766, 0, 0, 0},
4883
 
      {1.82574186, 0, 0, 0},
4884
 
      {5.16397779, 0, 0, 0}};
4885
 
    
4886
 
      // Compute reference derivatives
4887
 
      // Declare pointer to array of derivatives on FIAT element
4888
 
      double *derivatives = new double [num_derivatives];
4889
 
    
4890
 
      // Declare coefficients
4891
 
      double coeff0_0 = 0;
4892
 
      double coeff0_1 = 0;
4893
 
      double coeff0_2 = 0;
4894
 
      double coeff0_3 = 0;
4895
 
    
4896
 
      // Declare new coefficients
4897
 
      double new_coeff0_0 = 0;
4898
 
      double new_coeff0_1 = 0;
4899
 
      double new_coeff0_2 = 0;
4900
 
      double new_coeff0_3 = 0;
4901
 
    
4902
 
      // Loop possible derivatives
4903
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
4904
 
      {
4905
 
        // Get values from coefficients array
4906
 
        new_coeff0_0 = coefficients0[dof][0];
4907
 
        new_coeff0_1 = coefficients0[dof][1];
4908
 
        new_coeff0_2 = coefficients0[dof][2];
4909
 
        new_coeff0_3 = coefficients0[dof][3];
4910
 
    
4911
 
        // Loop derivative order
4912
 
        for (unsigned int j = 0; j < n; j++)
4913
 
        {
4914
 
          // Update old coefficients
4915
 
          coeff0_0 = new_coeff0_0;
4916
 
          coeff0_1 = new_coeff0_1;
4917
 
          coeff0_2 = new_coeff0_2;
4918
 
          coeff0_3 = new_coeff0_3;
4919
 
    
4920
 
          if(combinations[deriv_num][j] == 0)
4921
 
          {
4922
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
4923
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
4924
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
4925
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
4926
 
          }
4927
 
          if(combinations[deriv_num][j] == 1)
4928
 
          {
4929
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
4930
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
4931
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
4932
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
4933
 
          }
4934
 
          if(combinations[deriv_num][j] == 2)
4935
 
          {
4936
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
4937
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
4938
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
4939
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
4940
 
          }
4941
 
    
4942
 
        }
4943
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
4944
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
4945
 
      }
4946
 
    
4947
 
      // Transform derivatives back to physical element
4948
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4949
 
      {
4950
 
        for (unsigned int col = 0; col < num_derivatives; col++)
4951
 
        {
4952
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
4953
 
        }
4954
 
      }
4955
 
      // Delete pointer to array of derivatives on FIAT element
4956
 
      delete [] derivatives;
4957
 
    
4958
 
      // Delete pointer to array of combinations of derivatives and transform
4959
 
      for (unsigned int row = 0; row < num_derivatives; row++)
4960
 
      {
4961
 
        delete [] combinations[row];
4962
 
        delete [] transform[row];
4963
 
      }
4964
 
    
4965
 
      delete [] combinations;
4966
 
      delete [] transform;
4967
 
    }
4968
 
    
4969
 
  }
4970
 
 
4971
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
4972
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
4973
 
                                              double* values,
4974
 
                                              const double* coordinates,
4975
 
                                              const ufc::cell& c) const
4976
 
  {
4977
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
4978
 
  }
4979
 
 
4980
 
  /// Evaluate linear functional for dof i on the function f
4981
 
  virtual double evaluate_dof(unsigned int i,
4982
 
                              const ufc::function& f,
4983
 
                              const ufc::cell& c) const
4984
 
  {
4985
 
    // The reference points, direction and weights:
4986
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
4987
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
4988
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
4989
 
    
4990
 
    const double * const * x = c.coordinates;
4991
 
    double result = 0.0;
4992
 
    // Iterate over the points:
4993
 
    // Evaluate basis functions for affine mapping
4994
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
4995
 
    const double w1 = X[i][0][0];
4996
 
    const double w2 = X[i][0][1];
4997
 
    const double w3 = X[i][0][2];
4998
 
    
4999
 
    // Compute affine mapping y = F(X)
5000
 
    double y[3];
5001
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
5002
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
5003
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
5004
 
    
5005
 
    // Evaluate function at physical points
5006
 
    double values[3];
5007
 
    f.evaluate(values, y, c);
5008
 
    
5009
 
    // Map function values using appropriate mapping
5010
 
    // Affine map: Do nothing
5011
 
    
5012
 
    // Note that we do not map the weights (yet).
5013
 
    
5014
 
    // Take directional components
5015
 
    for(int k = 0; k < 3; k++)
5016
 
      result += values[k]*D[i][0][k];
5017
 
    // Multiply by weights
5018
 
    result *= W[i][0];
5019
 
    
5020
 
    return result;
5021
 
  }
5022
 
 
5023
 
  /// Evaluate linear functionals for all dofs on the function f
5024
 
  virtual void evaluate_dofs(double* values,
5025
 
                             const ufc::function& f,
5026
 
                             const ufc::cell& c) const
5027
 
  {
5028
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
5029
 
  }
5030
 
 
5031
 
  /// Interpolate vertex values from dof values
5032
 
  virtual void interpolate_vertex_values(double* vertex_values,
5033
 
                                         const double* dof_values,
5034
 
                                         const ufc::cell& c) const
5035
 
  {
5036
 
    // Evaluate at vertices and use affine mapping
5037
 
    vertex_values[0] = dof_values[0];
5038
 
    vertex_values[3] = dof_values[1];
5039
 
    vertex_values[6] = dof_values[2];
5040
 
    vertex_values[9] = dof_values[3];
5041
 
    // Evaluate at vertices and use affine mapping
5042
 
    vertex_values[1] = dof_values[4];
5043
 
    vertex_values[4] = dof_values[5];
5044
 
    vertex_values[7] = dof_values[6];
5045
 
    vertex_values[10] = dof_values[7];
5046
 
    // Evaluate at vertices and use affine mapping
5047
 
    vertex_values[2] = dof_values[8];
5048
 
    vertex_values[5] = dof_values[9];
5049
 
    vertex_values[8] = dof_values[10];
5050
 
    vertex_values[11] = dof_values[11];
5051
 
  }
5052
 
 
5053
 
  /// Return the number of sub elements (for a mixed element)
5054
 
  virtual unsigned int num_sub_elements() const
5055
 
  {
5056
 
    return 3;
5057
 
  }
5058
 
 
5059
 
  /// Create a new finite element for sub element i (for a mixed element)
5060
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
5061
 
  {
5062
 
    switch ( i )
5063
 
    {
5064
 
    case 0:
5065
 
      return new hyperelasticity_0_finite_element_1_0();
5066
 
      break;
5067
 
    case 1:
5068
 
      return new hyperelasticity_0_finite_element_1_1();
5069
 
      break;
5070
 
    case 2:
5071
 
      return new hyperelasticity_0_finite_element_1_2();
5072
 
      break;
5073
 
    }
5074
 
    return 0;
5075
 
  }
5076
 
 
5077
 
};
5078
 
 
5079
 
/// This class defines the interface for a finite element.
5080
 
 
5081
 
class hyperelasticity_0_finite_element_2_0: public ufc::finite_element
5082
 
{
5083
 
public:
5084
 
 
5085
 
  /// Constructor
5086
 
  hyperelasticity_0_finite_element_2_0() : ufc::finite_element()
5087
 
  {
5088
 
    // Do nothing
5089
 
  }
5090
 
 
5091
 
  /// Destructor
5092
 
  virtual ~hyperelasticity_0_finite_element_2_0()
5093
 
  {
5094
 
    // Do nothing
5095
 
  }
5096
 
 
5097
 
  /// Return a string identifying the finite element
5098
 
  virtual const char* signature() const
5099
 
  {
5100
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
5101
 
  }
5102
 
 
5103
 
  /// Return the cell shape
5104
 
  virtual ufc::shape cell_shape() const
5105
 
  {
5106
 
    return ufc::tetrahedron;
5107
 
  }
5108
 
 
5109
 
  /// Return the dimension of the finite element function space
5110
 
  virtual unsigned int space_dimension() const
5111
 
  {
5112
 
    return 4;
5113
 
  }
5114
 
 
5115
 
  /// Return the rank of the value space
5116
 
  virtual unsigned int value_rank() const
5117
 
  {
5118
 
    return 0;
5119
 
  }
5120
 
 
5121
 
  /// Return the dimension of the value space for axis i
5122
 
  virtual unsigned int value_dimension(unsigned int i) const
5123
 
  {
5124
 
    return 1;
5125
 
  }
5126
 
 
5127
 
  /// Evaluate basis function i at given point in cell
5128
 
  virtual void evaluate_basis(unsigned int i,
5129
 
                              double* values,
5130
 
                              const double* coordinates,
5131
 
                              const ufc::cell& c) const
5132
 
  {
5133
 
    // Extract vertex coordinates
5134
 
    const double * const * element_coordinates = c.coordinates;
5135
 
    
5136
 
    // Compute Jacobian of affine map from reference cell
5137
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
5138
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
5139
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
5140
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
5141
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
5142
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
5143
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
5144
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
5145
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
5146
 
    
5147
 
    // Compute sub determinants
5148
 
    const double d00 = J_11*J_22 - J_12*J_21;
5149
 
    const double d01 = J_12*J_20 - J_10*J_22;
5150
 
    const double d02 = J_10*J_21 - J_11*J_20;
5151
 
    
5152
 
    const double d10 = J_02*J_21 - J_01*J_22;
5153
 
    const double d11 = J_00*J_22 - J_02*J_20;
5154
 
    const double d12 = J_01*J_20 - J_00*J_21;
5155
 
    
5156
 
    const double d20 = J_01*J_12 - J_02*J_11;
5157
 
    const double d21 = J_02*J_10 - J_00*J_12;
5158
 
    const double d22 = J_00*J_11 - J_01*J_10;
5159
 
    
5160
 
    // Compute determinant of Jacobian
5161
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
5162
 
    
5163
 
    // Compute inverse of Jacobian
5164
 
    
5165
 
    // Compute constants
5166
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
5167
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
5168
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
5169
 
    
5170
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
5171
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
5172
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
5173
 
    
5174
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
5175
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
5176
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
5177
 
    
5178
 
    // Get coordinates and map to the UFC reference element
5179
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
5180
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
5181
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
5182
 
    
5183
 
    // Map coordinates to the reference cube
5184
 
    if (std::abs(y + z - 1.0) < 1e-08)
5185
 
      x = 1.0;
5186
 
    else
5187
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
5188
 
    if (std::abs(z - 1.0) < 1e-08)
5189
 
      y = -1.0;
5190
 
    else
5191
 
      y = 2.0 * y/(1.0 - z) - 1.0;
5192
 
    z = 2.0 * z - 1.0;
5193
 
    
5194
 
    // Reset values
5195
 
    *values = 0;
5196
 
    
5197
 
    // Map degree of freedom to element degree of freedom
5198
 
    const unsigned int dof = i;
5199
 
    
5200
 
    // Generate scalings
5201
 
    const double scalings_y_0 = 1;
5202
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
5203
 
    const double scalings_z_0 = 1;
5204
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
5205
 
    
5206
 
    // Compute psitilde_a
5207
 
    const double psitilde_a_0 = 1;
5208
 
    const double psitilde_a_1 = x;
5209
 
    
5210
 
    // Compute psitilde_bs
5211
 
    const double psitilde_bs_0_0 = 1;
5212
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
5213
 
    const double psitilde_bs_1_0 = 1;
5214
 
    
5215
 
    // Compute psitilde_cs
5216
 
    const double psitilde_cs_00_0 = 1;
5217
 
    const double psitilde_cs_00_1 = 2*z + 1;
5218
 
    const double psitilde_cs_01_0 = 1;
5219
 
    const double psitilde_cs_10_0 = 1;
5220
 
    
5221
 
    // Compute basisvalues
5222
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
5223
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
5224
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
5225
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
5226
 
    
5227
 
    // Table(s) of coefficients
5228
 
    static const double coefficients0[4][4] = \
5229
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
5230
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
5231
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
5232
 
    {0.288675135, 0, 0, 0.223606798}};
5233
 
    
5234
 
    // Extract relevant coefficients
5235
 
    const double coeff0_0 = coefficients0[dof][0];
5236
 
    const double coeff0_1 = coefficients0[dof][1];
5237
 
    const double coeff0_2 = coefficients0[dof][2];
5238
 
    const double coeff0_3 = coefficients0[dof][3];
5239
 
    
5240
 
    // Compute value(s)
5241
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
5242
 
  }
5243
 
 
5244
 
  /// Evaluate all basis functions at given point in cell
5245
 
  virtual void evaluate_basis_all(double* values,
5246
 
                                  const double* coordinates,
5247
 
                                  const ufc::cell& c) const
5248
 
  {
5249
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
5250
 
  }
5251
 
 
5252
 
  /// Evaluate order n derivatives of basis function i at given point in cell
5253
 
  virtual void evaluate_basis_derivatives(unsigned int i,
5254
 
                                          unsigned int n,
5255
 
                                          double* values,
5256
 
                                          const double* coordinates,
5257
 
                                          const ufc::cell& c) const
5258
 
  {
5259
 
    // Extract vertex coordinates
5260
 
    const double * const * element_coordinates = c.coordinates;
5261
 
    
5262
 
    // Compute Jacobian of affine map from reference cell
5263
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
5264
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
5265
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
5266
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
5267
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
5268
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
5269
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
5270
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
5271
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
5272
 
    
5273
 
    // Compute sub determinants
5274
 
    const double d00 = J_11*J_22 - J_12*J_21;
5275
 
    const double d01 = J_12*J_20 - J_10*J_22;
5276
 
    const double d02 = J_10*J_21 - J_11*J_20;
5277
 
    
5278
 
    const double d10 = J_02*J_21 - J_01*J_22;
5279
 
    const double d11 = J_00*J_22 - J_02*J_20;
5280
 
    const double d12 = J_01*J_20 - J_00*J_21;
5281
 
    
5282
 
    const double d20 = J_01*J_12 - J_02*J_11;
5283
 
    const double d21 = J_02*J_10 - J_00*J_12;
5284
 
    const double d22 = J_00*J_11 - J_01*J_10;
5285
 
    
5286
 
    // Compute determinant of Jacobian
5287
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
5288
 
    
5289
 
    // Compute inverse of Jacobian
5290
 
    
5291
 
    // Compute constants
5292
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
5293
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
5294
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
5295
 
    
5296
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
5297
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
5298
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
5299
 
    
5300
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
5301
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
5302
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
5303
 
    
5304
 
    // Get coordinates and map to the UFC reference element
5305
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
5306
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
5307
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
5308
 
    
5309
 
    // Map coordinates to the reference cube
5310
 
    if (std::abs(y + z - 1.0) < 1e-08)
5311
 
      x = 1.0;
5312
 
    else
5313
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
5314
 
    if (std::abs(z - 1.0) < 1e-08)
5315
 
      y = -1.0;
5316
 
    else
5317
 
      y = 2.0 * y/(1.0 - z) - 1.0;
5318
 
    z = 2.0 * z - 1.0;
5319
 
    
5320
 
    // Compute number of derivatives
5321
 
    unsigned int num_derivatives = 1;
5322
 
    
5323
 
    for (unsigned int j = 0; j < n; j++)
5324
 
      num_derivatives *= 3;
5325
 
    
5326
 
    
5327
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
5328
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
5329
 
    
5330
 
    for (unsigned int j = 0; j < num_derivatives; j++)
5331
 
    {
5332
 
      combinations[j] = new unsigned int [n];
5333
 
      for (unsigned int k = 0; k < n; k++)
5334
 
        combinations[j][k] = 0;
5335
 
    }
5336
 
    
5337
 
    // Generate combinations of derivatives
5338
 
    for (unsigned int row = 1; row < num_derivatives; row++)
5339
 
    {
5340
 
      for (unsigned int num = 0; num < row; num++)
5341
 
      {
5342
 
        for (unsigned int col = n-1; col+1 > 0; col--)
5343
 
        {
5344
 
          if (combinations[row][col] + 1 > 2)
5345
 
            combinations[row][col] = 0;
5346
 
          else
5347
 
          {
5348
 
            combinations[row][col] += 1;
5349
 
            break;
5350
 
          }
5351
 
        }
5352
 
      }
5353
 
    }
5354
 
    
5355
 
    // Compute inverse of Jacobian
5356
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
5357
 
    
5358
 
    // Declare transformation matrix
5359
 
    // Declare pointer to two dimensional array and initialise
5360
 
    double **transform = new double *[num_derivatives];
5361
 
    
5362
 
    for (unsigned int j = 0; j < num_derivatives; j++)
5363
 
    {
5364
 
      transform[j] = new double [num_derivatives];
5365
 
      for (unsigned int k = 0; k < num_derivatives; k++)
5366
 
        transform[j][k] = 1;
5367
 
    }
5368
 
    
5369
 
    // Construct transformation matrix
5370
 
    for (unsigned int row = 0; row < num_derivatives; row++)
5371
 
    {
5372
 
      for (unsigned int col = 0; col < num_derivatives; col++)
5373
 
      {
5374
 
        for (unsigned int k = 0; k < n; k++)
5375
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
5376
 
      }
5377
 
    }
5378
 
    
5379
 
    // Reset values
5380
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
5381
 
      values[j] = 0;
5382
 
    
5383
 
    // Map degree of freedom to element degree of freedom
5384
 
    const unsigned int dof = i;
5385
 
    
5386
 
    // Generate scalings
5387
 
    const double scalings_y_0 = 1;
5388
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
5389
 
    const double scalings_z_0 = 1;
5390
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
5391
 
    
5392
 
    // Compute psitilde_a
5393
 
    const double psitilde_a_0 = 1;
5394
 
    const double psitilde_a_1 = x;
5395
 
    
5396
 
    // Compute psitilde_bs
5397
 
    const double psitilde_bs_0_0 = 1;
5398
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
5399
 
    const double psitilde_bs_1_0 = 1;
5400
 
    
5401
 
    // Compute psitilde_cs
5402
 
    const double psitilde_cs_00_0 = 1;
5403
 
    const double psitilde_cs_00_1 = 2*z + 1;
5404
 
    const double psitilde_cs_01_0 = 1;
5405
 
    const double psitilde_cs_10_0 = 1;
5406
 
    
5407
 
    // Compute basisvalues
5408
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
5409
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
5410
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
5411
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
5412
 
    
5413
 
    // Table(s) of coefficients
5414
 
    static const double coefficients0[4][4] = \
5415
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
5416
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
5417
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
5418
 
    {0.288675135, 0, 0, 0.223606798}};
5419
 
    
5420
 
    // Interesting (new) part
5421
 
    // Tables of derivatives of the polynomial base (transpose)
5422
 
    static const double dmats0[4][4] = \
5423
 
    {{0, 0, 0, 0},
5424
 
    {6.32455532, 0, 0, 0},
5425
 
    {0, 0, 0, 0},
5426
 
    {0, 0, 0, 0}};
5427
 
    
5428
 
    static const double dmats1[4][4] = \
5429
 
    {{0, 0, 0, 0},
5430
 
    {3.16227766, 0, 0, 0},
5431
 
    {5.47722558, 0, 0, 0},
5432
 
    {0, 0, 0, 0}};
5433
 
    
5434
 
    static const double dmats2[4][4] = \
5435
 
    {{0, 0, 0, 0},
5436
 
    {3.16227766, 0, 0, 0},
5437
 
    {1.82574186, 0, 0, 0},
5438
 
    {5.16397779, 0, 0, 0}};
5439
 
    
5440
 
    // Compute reference derivatives
5441
 
    // Declare pointer to array of derivatives on FIAT element
5442
 
    double *derivatives = new double [num_derivatives];
5443
 
    
5444
 
    // Declare coefficients
5445
 
    double coeff0_0 = 0;
5446
 
    double coeff0_1 = 0;
5447
 
    double coeff0_2 = 0;
5448
 
    double coeff0_3 = 0;
5449
 
    
5450
 
    // Declare new coefficients
5451
 
    double new_coeff0_0 = 0;
5452
 
    double new_coeff0_1 = 0;
5453
 
    double new_coeff0_2 = 0;
5454
 
    double new_coeff0_3 = 0;
5455
 
    
5456
 
    // Loop possible derivatives
5457
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
5458
 
    {
5459
 
      // Get values from coefficients array
5460
 
      new_coeff0_0 = coefficients0[dof][0];
5461
 
      new_coeff0_1 = coefficients0[dof][1];
5462
 
      new_coeff0_2 = coefficients0[dof][2];
5463
 
      new_coeff0_3 = coefficients0[dof][3];
5464
 
    
5465
 
      // Loop derivative order
5466
 
      for (unsigned int j = 0; j < n; j++)
5467
 
      {
5468
 
        // Update old coefficients
5469
 
        coeff0_0 = new_coeff0_0;
5470
 
        coeff0_1 = new_coeff0_1;
5471
 
        coeff0_2 = new_coeff0_2;
5472
 
        coeff0_3 = new_coeff0_3;
5473
 
    
5474
 
        if(combinations[deriv_num][j] == 0)
5475
 
        {
5476
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
5477
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
5478
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
5479
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
5480
 
        }
5481
 
        if(combinations[deriv_num][j] == 1)
5482
 
        {
5483
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
5484
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
5485
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
5486
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
5487
 
        }
5488
 
        if(combinations[deriv_num][j] == 2)
5489
 
        {
5490
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
5491
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
5492
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
5493
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
5494
 
        }
5495
 
    
5496
 
      }
5497
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
5498
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
5499
 
    }
5500
 
    
5501
 
    // Transform derivatives back to physical element
5502
 
    for (unsigned int row = 0; row < num_derivatives; row++)
5503
 
    {
5504
 
      for (unsigned int col = 0; col < num_derivatives; col++)
5505
 
      {
5506
 
        values[row] += transform[row][col]*derivatives[col];
5507
 
      }
5508
 
    }
5509
 
    // Delete pointer to array of derivatives on FIAT element
5510
 
    delete [] derivatives;
5511
 
    
5512
 
    // Delete pointer to array of combinations of derivatives and transform
5513
 
    for (unsigned int row = 0; row < num_derivatives; row++)
5514
 
    {
5515
 
      delete [] combinations[row];
5516
 
      delete [] transform[row];
5517
 
    }
5518
 
    
5519
 
    delete [] combinations;
5520
 
    delete [] transform;
5521
 
  }
5522
 
 
5523
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
5524
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
5525
 
                                              double* values,
5526
 
                                              const double* coordinates,
5527
 
                                              const ufc::cell& c) const
5528
 
  {
5529
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
5530
 
  }
5531
 
 
5532
 
  /// Evaluate linear functional for dof i on the function f
5533
 
  virtual double evaluate_dof(unsigned int i,
5534
 
                              const ufc::function& f,
5535
 
                              const ufc::cell& c) const
5536
 
  {
5537
 
    // The reference points, direction and weights:
5538
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
5539
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
5540
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
5541
 
    
5542
 
    const double * const * x = c.coordinates;
5543
 
    double result = 0.0;
5544
 
    // Iterate over the points:
5545
 
    // Evaluate basis functions for affine mapping
5546
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
5547
 
    const double w1 = X[i][0][0];
5548
 
    const double w2 = X[i][0][1];
5549
 
    const double w3 = X[i][0][2];
5550
 
    
5551
 
    // Compute affine mapping y = F(X)
5552
 
    double y[3];
5553
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
5554
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
5555
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
5556
 
    
5557
 
    // Evaluate function at physical points
5558
 
    double values[1];
5559
 
    f.evaluate(values, y, c);
5560
 
    
5561
 
    // Map function values using appropriate mapping
5562
 
    // Affine map: Do nothing
5563
 
    
5564
 
    // Note that we do not map the weights (yet).
5565
 
    
5566
 
    // Take directional components
5567
 
    for(int k = 0; k < 1; k++)
5568
 
      result += values[k]*D[i][0][k];
5569
 
    // Multiply by weights
5570
 
    result *= W[i][0];
5571
 
    
5572
 
    return result;
5573
 
  }
5574
 
 
5575
 
  /// Evaluate linear functionals for all dofs on the function f
5576
 
  virtual void evaluate_dofs(double* values,
5577
 
                             const ufc::function& f,
5578
 
                             const ufc::cell& c) const
5579
 
  {
5580
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
5581
 
  }
5582
 
 
5583
 
  /// Interpolate vertex values from dof values
5584
 
  virtual void interpolate_vertex_values(double* vertex_values,
5585
 
                                         const double* dof_values,
5586
 
                                         const ufc::cell& c) const
5587
 
  {
5588
 
    // Evaluate at vertices and use affine mapping
5589
 
    vertex_values[0] = dof_values[0];
5590
 
    vertex_values[1] = dof_values[1];
5591
 
    vertex_values[2] = dof_values[2];
5592
 
    vertex_values[3] = dof_values[3];
5593
 
  }
5594
 
 
5595
 
  /// Return the number of sub elements (for a mixed element)
5596
 
  virtual unsigned int num_sub_elements() const
5597
 
  {
5598
 
    return 1;
5599
 
  }
5600
 
 
5601
 
  /// Create a new finite element for sub element i (for a mixed element)
5602
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
5603
 
  {
5604
 
    return new hyperelasticity_0_finite_element_2_0();
5605
 
  }
5606
 
 
5607
 
};
5608
 
 
5609
 
/// This class defines the interface for a finite element.
5610
 
 
5611
 
class hyperelasticity_0_finite_element_2_1: public ufc::finite_element
5612
 
{
5613
 
public:
5614
 
 
5615
 
  /// Constructor
5616
 
  hyperelasticity_0_finite_element_2_1() : ufc::finite_element()
5617
 
  {
5618
 
    // Do nothing
5619
 
  }
5620
 
 
5621
 
  /// Destructor
5622
 
  virtual ~hyperelasticity_0_finite_element_2_1()
5623
 
  {
5624
 
    // Do nothing
5625
 
  }
5626
 
 
5627
 
  /// Return a string identifying the finite element
5628
 
  virtual const char* signature() const
5629
 
  {
5630
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
5631
 
  }
5632
 
 
5633
 
  /// Return the cell shape
5634
 
  virtual ufc::shape cell_shape() const
5635
 
  {
5636
 
    return ufc::tetrahedron;
5637
 
  }
5638
 
 
5639
 
  /// Return the dimension of the finite element function space
5640
 
  virtual unsigned int space_dimension() const
5641
 
  {
5642
 
    return 4;
5643
 
  }
5644
 
 
5645
 
  /// Return the rank of the value space
5646
 
  virtual unsigned int value_rank() const
5647
 
  {
5648
 
    return 0;
5649
 
  }
5650
 
 
5651
 
  /// Return the dimension of the value space for axis i
5652
 
  virtual unsigned int value_dimension(unsigned int i) const
5653
 
  {
5654
 
    return 1;
5655
 
  }
5656
 
 
5657
 
  /// Evaluate basis function i at given point in cell
5658
 
  virtual void evaluate_basis(unsigned int i,
5659
 
                              double* values,
5660
 
                              const double* coordinates,
5661
 
                              const ufc::cell& c) const
5662
 
  {
5663
 
    // Extract vertex coordinates
5664
 
    const double * const * element_coordinates = c.coordinates;
5665
 
    
5666
 
    // Compute Jacobian of affine map from reference cell
5667
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
5668
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
5669
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
5670
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
5671
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
5672
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
5673
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
5674
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
5675
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
5676
 
    
5677
 
    // Compute sub determinants
5678
 
    const double d00 = J_11*J_22 - J_12*J_21;
5679
 
    const double d01 = J_12*J_20 - J_10*J_22;
5680
 
    const double d02 = J_10*J_21 - J_11*J_20;
5681
 
    
5682
 
    const double d10 = J_02*J_21 - J_01*J_22;
5683
 
    const double d11 = J_00*J_22 - J_02*J_20;
5684
 
    const double d12 = J_01*J_20 - J_00*J_21;
5685
 
    
5686
 
    const double d20 = J_01*J_12 - J_02*J_11;
5687
 
    const double d21 = J_02*J_10 - J_00*J_12;
5688
 
    const double d22 = J_00*J_11 - J_01*J_10;
5689
 
    
5690
 
    // Compute determinant of Jacobian
5691
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
5692
 
    
5693
 
    // Compute inverse of Jacobian
5694
 
    
5695
 
    // Compute constants
5696
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
5697
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
5698
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
5699
 
    
5700
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
5701
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
5702
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
5703
 
    
5704
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
5705
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
5706
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
5707
 
    
5708
 
    // Get coordinates and map to the UFC reference element
5709
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
5710
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
5711
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
5712
 
    
5713
 
    // Map coordinates to the reference cube
5714
 
    if (std::abs(y + z - 1.0) < 1e-08)
5715
 
      x = 1.0;
5716
 
    else
5717
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
5718
 
    if (std::abs(z - 1.0) < 1e-08)
5719
 
      y = -1.0;
5720
 
    else
5721
 
      y = 2.0 * y/(1.0 - z) - 1.0;
5722
 
    z = 2.0 * z - 1.0;
5723
 
    
5724
 
    // Reset values
5725
 
    *values = 0;
5726
 
    
5727
 
    // Map degree of freedom to element degree of freedom
5728
 
    const unsigned int dof = i;
5729
 
    
5730
 
    // Generate scalings
5731
 
    const double scalings_y_0 = 1;
5732
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
5733
 
    const double scalings_z_0 = 1;
5734
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
5735
 
    
5736
 
    // Compute psitilde_a
5737
 
    const double psitilde_a_0 = 1;
5738
 
    const double psitilde_a_1 = x;
5739
 
    
5740
 
    // Compute psitilde_bs
5741
 
    const double psitilde_bs_0_0 = 1;
5742
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
5743
 
    const double psitilde_bs_1_0 = 1;
5744
 
    
5745
 
    // Compute psitilde_cs
5746
 
    const double psitilde_cs_00_0 = 1;
5747
 
    const double psitilde_cs_00_1 = 2*z + 1;
5748
 
    const double psitilde_cs_01_0 = 1;
5749
 
    const double psitilde_cs_10_0 = 1;
5750
 
    
5751
 
    // Compute basisvalues
5752
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
5753
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
5754
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
5755
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
5756
 
    
5757
 
    // Table(s) of coefficients
5758
 
    static const double coefficients0[4][4] = \
5759
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
5760
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
5761
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
5762
 
    {0.288675135, 0, 0, 0.223606798}};
5763
 
    
5764
 
    // Extract relevant coefficients
5765
 
    const double coeff0_0 = coefficients0[dof][0];
5766
 
    const double coeff0_1 = coefficients0[dof][1];
5767
 
    const double coeff0_2 = coefficients0[dof][2];
5768
 
    const double coeff0_3 = coefficients0[dof][3];
5769
 
    
5770
 
    // Compute value(s)
5771
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
5772
 
  }
5773
 
 
5774
 
  /// Evaluate all basis functions at given point in cell
5775
 
  virtual void evaluate_basis_all(double* values,
5776
 
                                  const double* coordinates,
5777
 
                                  const ufc::cell& c) const
5778
 
  {
5779
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
5780
 
  }
5781
 
 
5782
 
  /// Evaluate order n derivatives of basis function i at given point in cell
5783
 
  virtual void evaluate_basis_derivatives(unsigned int i,
5784
 
                                          unsigned int n,
5785
 
                                          double* values,
5786
 
                                          const double* coordinates,
5787
 
                                          const ufc::cell& c) const
5788
 
  {
5789
 
    // Extract vertex coordinates
5790
 
    const double * const * element_coordinates = c.coordinates;
5791
 
    
5792
 
    // Compute Jacobian of affine map from reference cell
5793
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
5794
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
5795
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
5796
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
5797
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
5798
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
5799
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
5800
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
5801
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
5802
 
    
5803
 
    // Compute sub determinants
5804
 
    const double d00 = J_11*J_22 - J_12*J_21;
5805
 
    const double d01 = J_12*J_20 - J_10*J_22;
5806
 
    const double d02 = J_10*J_21 - J_11*J_20;
5807
 
    
5808
 
    const double d10 = J_02*J_21 - J_01*J_22;
5809
 
    const double d11 = J_00*J_22 - J_02*J_20;
5810
 
    const double d12 = J_01*J_20 - J_00*J_21;
5811
 
    
5812
 
    const double d20 = J_01*J_12 - J_02*J_11;
5813
 
    const double d21 = J_02*J_10 - J_00*J_12;
5814
 
    const double d22 = J_00*J_11 - J_01*J_10;
5815
 
    
5816
 
    // Compute determinant of Jacobian
5817
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
5818
 
    
5819
 
    // Compute inverse of Jacobian
5820
 
    
5821
 
    // Compute constants
5822
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
5823
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
5824
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
5825
 
    
5826
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
5827
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
5828
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
5829
 
    
5830
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
5831
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
5832
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
5833
 
    
5834
 
    // Get coordinates and map to the UFC reference element
5835
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
5836
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
5837
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
5838
 
    
5839
 
    // Map coordinates to the reference cube
5840
 
    if (std::abs(y + z - 1.0) < 1e-08)
5841
 
      x = 1.0;
5842
 
    else
5843
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
5844
 
    if (std::abs(z - 1.0) < 1e-08)
5845
 
      y = -1.0;
5846
 
    else
5847
 
      y = 2.0 * y/(1.0 - z) - 1.0;
5848
 
    z = 2.0 * z - 1.0;
5849
 
    
5850
 
    // Compute number of derivatives
5851
 
    unsigned int num_derivatives = 1;
5852
 
    
5853
 
    for (unsigned int j = 0; j < n; j++)
5854
 
      num_derivatives *= 3;
5855
 
    
5856
 
    
5857
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
5858
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
5859
 
    
5860
 
    for (unsigned int j = 0; j < num_derivatives; j++)
5861
 
    {
5862
 
      combinations[j] = new unsigned int [n];
5863
 
      for (unsigned int k = 0; k < n; k++)
5864
 
        combinations[j][k] = 0;
5865
 
    }
5866
 
    
5867
 
    // Generate combinations of derivatives
5868
 
    for (unsigned int row = 1; row < num_derivatives; row++)
5869
 
    {
5870
 
      for (unsigned int num = 0; num < row; num++)
5871
 
      {
5872
 
        for (unsigned int col = n-1; col+1 > 0; col--)
5873
 
        {
5874
 
          if (combinations[row][col] + 1 > 2)
5875
 
            combinations[row][col] = 0;
5876
 
          else
5877
 
          {
5878
 
            combinations[row][col] += 1;
5879
 
            break;
5880
 
          }
5881
 
        }
5882
 
      }
5883
 
    }
5884
 
    
5885
 
    // Compute inverse of Jacobian
5886
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
5887
 
    
5888
 
    // Declare transformation matrix
5889
 
    // Declare pointer to two dimensional array and initialise
5890
 
    double **transform = new double *[num_derivatives];
5891
 
    
5892
 
    for (unsigned int j = 0; j < num_derivatives; j++)
5893
 
    {
5894
 
      transform[j] = new double [num_derivatives];
5895
 
      for (unsigned int k = 0; k < num_derivatives; k++)
5896
 
        transform[j][k] = 1;
5897
 
    }
5898
 
    
5899
 
    // Construct transformation matrix
5900
 
    for (unsigned int row = 0; row < num_derivatives; row++)
5901
 
    {
5902
 
      for (unsigned int col = 0; col < num_derivatives; col++)
5903
 
      {
5904
 
        for (unsigned int k = 0; k < n; k++)
5905
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
5906
 
      }
5907
 
    }
5908
 
    
5909
 
    // Reset values
5910
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
5911
 
      values[j] = 0;
5912
 
    
5913
 
    // Map degree of freedom to element degree of freedom
5914
 
    const unsigned int dof = i;
5915
 
    
5916
 
    // Generate scalings
5917
 
    const double scalings_y_0 = 1;
5918
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
5919
 
    const double scalings_z_0 = 1;
5920
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
5921
 
    
5922
 
    // Compute psitilde_a
5923
 
    const double psitilde_a_0 = 1;
5924
 
    const double psitilde_a_1 = x;
5925
 
    
5926
 
    // Compute psitilde_bs
5927
 
    const double psitilde_bs_0_0 = 1;
5928
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
5929
 
    const double psitilde_bs_1_0 = 1;
5930
 
    
5931
 
    // Compute psitilde_cs
5932
 
    const double psitilde_cs_00_0 = 1;
5933
 
    const double psitilde_cs_00_1 = 2*z + 1;
5934
 
    const double psitilde_cs_01_0 = 1;
5935
 
    const double psitilde_cs_10_0 = 1;
5936
 
    
5937
 
    // Compute basisvalues
5938
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
5939
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
5940
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
5941
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
5942
 
    
5943
 
    // Table(s) of coefficients
5944
 
    static const double coefficients0[4][4] = \
5945
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
5946
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
5947
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
5948
 
    {0.288675135, 0, 0, 0.223606798}};
5949
 
    
5950
 
    // Interesting (new) part
5951
 
    // Tables of derivatives of the polynomial base (transpose)
5952
 
    static const double dmats0[4][4] = \
5953
 
    {{0, 0, 0, 0},
5954
 
    {6.32455532, 0, 0, 0},
5955
 
    {0, 0, 0, 0},
5956
 
    {0, 0, 0, 0}};
5957
 
    
5958
 
    static const double dmats1[4][4] = \
5959
 
    {{0, 0, 0, 0},
5960
 
    {3.16227766, 0, 0, 0},
5961
 
    {5.47722558, 0, 0, 0},
5962
 
    {0, 0, 0, 0}};
5963
 
    
5964
 
    static const double dmats2[4][4] = \
5965
 
    {{0, 0, 0, 0},
5966
 
    {3.16227766, 0, 0, 0},
5967
 
    {1.82574186, 0, 0, 0},
5968
 
    {5.16397779, 0, 0, 0}};
5969
 
    
5970
 
    // Compute reference derivatives
5971
 
    // Declare pointer to array of derivatives on FIAT element
5972
 
    double *derivatives = new double [num_derivatives];
5973
 
    
5974
 
    // Declare coefficients
5975
 
    double coeff0_0 = 0;
5976
 
    double coeff0_1 = 0;
5977
 
    double coeff0_2 = 0;
5978
 
    double coeff0_3 = 0;
5979
 
    
5980
 
    // Declare new coefficients
5981
 
    double new_coeff0_0 = 0;
5982
 
    double new_coeff0_1 = 0;
5983
 
    double new_coeff0_2 = 0;
5984
 
    double new_coeff0_3 = 0;
5985
 
    
5986
 
    // Loop possible derivatives
5987
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
5988
 
    {
5989
 
      // Get values from coefficients array
5990
 
      new_coeff0_0 = coefficients0[dof][0];
5991
 
      new_coeff0_1 = coefficients0[dof][1];
5992
 
      new_coeff0_2 = coefficients0[dof][2];
5993
 
      new_coeff0_3 = coefficients0[dof][3];
5994
 
    
5995
 
      // Loop derivative order
5996
 
      for (unsigned int j = 0; j < n; j++)
5997
 
      {
5998
 
        // Update old coefficients
5999
 
        coeff0_0 = new_coeff0_0;
6000
 
        coeff0_1 = new_coeff0_1;
6001
 
        coeff0_2 = new_coeff0_2;
6002
 
        coeff0_3 = new_coeff0_3;
6003
 
    
6004
 
        if(combinations[deriv_num][j] == 0)
6005
 
        {
6006
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
6007
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
6008
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
6009
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
6010
 
        }
6011
 
        if(combinations[deriv_num][j] == 1)
6012
 
        {
6013
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
6014
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
6015
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
6016
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
6017
 
        }
6018
 
        if(combinations[deriv_num][j] == 2)
6019
 
        {
6020
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
6021
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
6022
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
6023
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
6024
 
        }
6025
 
    
6026
 
      }
6027
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
6028
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
6029
 
    }
6030
 
    
6031
 
    // Transform derivatives back to physical element
6032
 
    for (unsigned int row = 0; row < num_derivatives; row++)
6033
 
    {
6034
 
      for (unsigned int col = 0; col < num_derivatives; col++)
6035
 
      {
6036
 
        values[row] += transform[row][col]*derivatives[col];
6037
 
      }
6038
 
    }
6039
 
    // Delete pointer to array of derivatives on FIAT element
6040
 
    delete [] derivatives;
6041
 
    
6042
 
    // Delete pointer to array of combinations of derivatives and transform
6043
 
    for (unsigned int row = 0; row < num_derivatives; row++)
6044
 
    {
6045
 
      delete [] combinations[row];
6046
 
      delete [] transform[row];
6047
 
    }
6048
 
    
6049
 
    delete [] combinations;
6050
 
    delete [] transform;
6051
 
  }
6052
 
 
6053
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
6054
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
6055
 
                                              double* values,
6056
 
                                              const double* coordinates,
6057
 
                                              const ufc::cell& c) const
6058
 
  {
6059
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
6060
 
  }
6061
 
 
6062
 
  /// Evaluate linear functional for dof i on the function f
6063
 
  virtual double evaluate_dof(unsigned int i,
6064
 
                              const ufc::function& f,
6065
 
                              const ufc::cell& c) const
6066
 
  {
6067
 
    // The reference points, direction and weights:
6068
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
6069
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
6070
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
6071
 
    
6072
 
    const double * const * x = c.coordinates;
6073
 
    double result = 0.0;
6074
 
    // Iterate over the points:
6075
 
    // Evaluate basis functions for affine mapping
6076
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
6077
 
    const double w1 = X[i][0][0];
6078
 
    const double w2 = X[i][0][1];
6079
 
    const double w3 = X[i][0][2];
6080
 
    
6081
 
    // Compute affine mapping y = F(X)
6082
 
    double y[3];
6083
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
6084
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
6085
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
6086
 
    
6087
 
    // Evaluate function at physical points
6088
 
    double values[1];
6089
 
    f.evaluate(values, y, c);
6090
 
    
6091
 
    // Map function values using appropriate mapping
6092
 
    // Affine map: Do nothing
6093
 
    
6094
 
    // Note that we do not map the weights (yet).
6095
 
    
6096
 
    // Take directional components
6097
 
    for(int k = 0; k < 1; k++)
6098
 
      result += values[k]*D[i][0][k];
6099
 
    // Multiply by weights
6100
 
    result *= W[i][0];
6101
 
    
6102
 
    return result;
6103
 
  }
6104
 
 
6105
 
  /// Evaluate linear functionals for all dofs on the function f
6106
 
  virtual void evaluate_dofs(double* values,
6107
 
                             const ufc::function& f,
6108
 
                             const ufc::cell& c) const
6109
 
  {
6110
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
6111
 
  }
6112
 
 
6113
 
  /// Interpolate vertex values from dof values
6114
 
  virtual void interpolate_vertex_values(double* vertex_values,
6115
 
                                         const double* dof_values,
6116
 
                                         const ufc::cell& c) const
6117
 
  {
6118
 
    // Evaluate at vertices and use affine mapping
6119
 
    vertex_values[0] = dof_values[0];
6120
 
    vertex_values[1] = dof_values[1];
6121
 
    vertex_values[2] = dof_values[2];
6122
 
    vertex_values[3] = dof_values[3];
6123
 
  }
6124
 
 
6125
 
  /// Return the number of sub elements (for a mixed element)
6126
 
  virtual unsigned int num_sub_elements() const
6127
 
  {
6128
 
    return 1;
6129
 
  }
6130
 
 
6131
 
  /// Create a new finite element for sub element i (for a mixed element)
6132
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
6133
 
  {
6134
 
    return new hyperelasticity_0_finite_element_2_1();
6135
 
  }
6136
 
 
6137
 
};
6138
 
 
6139
 
/// This class defines the interface for a finite element.
6140
 
 
6141
 
class hyperelasticity_0_finite_element_2_2: public ufc::finite_element
6142
 
{
6143
 
public:
6144
 
 
6145
 
  /// Constructor
6146
 
  hyperelasticity_0_finite_element_2_2() : ufc::finite_element()
6147
 
  {
6148
 
    // Do nothing
6149
 
  }
6150
 
 
6151
 
  /// Destructor
6152
 
  virtual ~hyperelasticity_0_finite_element_2_2()
6153
 
  {
6154
 
    // Do nothing
6155
 
  }
6156
 
 
6157
 
  /// Return a string identifying the finite element
6158
 
  virtual const char* signature() const
6159
 
  {
6160
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
6161
 
  }
6162
 
 
6163
 
  /// Return the cell shape
6164
 
  virtual ufc::shape cell_shape() const
6165
 
  {
6166
 
    return ufc::tetrahedron;
6167
 
  }
6168
 
 
6169
 
  /// Return the dimension of the finite element function space
6170
 
  virtual unsigned int space_dimension() const
6171
 
  {
6172
 
    return 4;
6173
 
  }
6174
 
 
6175
 
  /// Return the rank of the value space
6176
 
  virtual unsigned int value_rank() const
6177
 
  {
6178
 
    return 0;
6179
 
  }
6180
 
 
6181
 
  /// Return the dimension of the value space for axis i
6182
 
  virtual unsigned int value_dimension(unsigned int i) const
6183
 
  {
6184
 
    return 1;
6185
 
  }
6186
 
 
6187
 
  /// Evaluate basis function i at given point in cell
6188
 
  virtual void evaluate_basis(unsigned int i,
6189
 
                              double* values,
6190
 
                              const double* coordinates,
6191
 
                              const ufc::cell& c) const
6192
 
  {
6193
 
    // Extract vertex coordinates
6194
 
    const double * const * element_coordinates = c.coordinates;
6195
 
    
6196
 
    // Compute Jacobian of affine map from reference cell
6197
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
6198
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
6199
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
6200
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
6201
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
6202
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
6203
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
6204
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
6205
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
6206
 
    
6207
 
    // Compute sub determinants
6208
 
    const double d00 = J_11*J_22 - J_12*J_21;
6209
 
    const double d01 = J_12*J_20 - J_10*J_22;
6210
 
    const double d02 = J_10*J_21 - J_11*J_20;
6211
 
    
6212
 
    const double d10 = J_02*J_21 - J_01*J_22;
6213
 
    const double d11 = J_00*J_22 - J_02*J_20;
6214
 
    const double d12 = J_01*J_20 - J_00*J_21;
6215
 
    
6216
 
    const double d20 = J_01*J_12 - J_02*J_11;
6217
 
    const double d21 = J_02*J_10 - J_00*J_12;
6218
 
    const double d22 = J_00*J_11 - J_01*J_10;
6219
 
    
6220
 
    // Compute determinant of Jacobian
6221
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
6222
 
    
6223
 
    // Compute inverse of Jacobian
6224
 
    
6225
 
    // Compute constants
6226
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
6227
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
6228
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
6229
 
    
6230
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
6231
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
6232
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
6233
 
    
6234
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
6235
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
6236
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
6237
 
    
6238
 
    // Get coordinates and map to the UFC reference element
6239
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
6240
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
6241
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
6242
 
    
6243
 
    // Map coordinates to the reference cube
6244
 
    if (std::abs(y + z - 1.0) < 1e-08)
6245
 
      x = 1.0;
6246
 
    else
6247
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
6248
 
    if (std::abs(z - 1.0) < 1e-08)
6249
 
      y = -1.0;
6250
 
    else
6251
 
      y = 2.0 * y/(1.0 - z) - 1.0;
6252
 
    z = 2.0 * z - 1.0;
6253
 
    
6254
 
    // Reset values
6255
 
    *values = 0;
6256
 
    
6257
 
    // Map degree of freedom to element degree of freedom
6258
 
    const unsigned int dof = i;
6259
 
    
6260
 
    // Generate scalings
6261
 
    const double scalings_y_0 = 1;
6262
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
6263
 
    const double scalings_z_0 = 1;
6264
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
6265
 
    
6266
 
    // Compute psitilde_a
6267
 
    const double psitilde_a_0 = 1;
6268
 
    const double psitilde_a_1 = x;
6269
 
    
6270
 
    // Compute psitilde_bs
6271
 
    const double psitilde_bs_0_0 = 1;
6272
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
6273
 
    const double psitilde_bs_1_0 = 1;
6274
 
    
6275
 
    // Compute psitilde_cs
6276
 
    const double psitilde_cs_00_0 = 1;
6277
 
    const double psitilde_cs_00_1 = 2*z + 1;
6278
 
    const double psitilde_cs_01_0 = 1;
6279
 
    const double psitilde_cs_10_0 = 1;
6280
 
    
6281
 
    // Compute basisvalues
6282
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
6283
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
6284
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
6285
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
6286
 
    
6287
 
    // Table(s) of coefficients
6288
 
    static const double coefficients0[4][4] = \
6289
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
6290
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
6291
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
6292
 
    {0.288675135, 0, 0, 0.223606798}};
6293
 
    
6294
 
    // Extract relevant coefficients
6295
 
    const double coeff0_0 = coefficients0[dof][0];
6296
 
    const double coeff0_1 = coefficients0[dof][1];
6297
 
    const double coeff0_2 = coefficients0[dof][2];
6298
 
    const double coeff0_3 = coefficients0[dof][3];
6299
 
    
6300
 
    // Compute value(s)
6301
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
6302
 
  }
6303
 
 
6304
 
  /// Evaluate all basis functions at given point in cell
6305
 
  virtual void evaluate_basis_all(double* values,
6306
 
                                  const double* coordinates,
6307
 
                                  const ufc::cell& c) const
6308
 
  {
6309
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
6310
 
  }
6311
 
 
6312
 
  /// Evaluate order n derivatives of basis function i at given point in cell
6313
 
  virtual void evaluate_basis_derivatives(unsigned int i,
6314
 
                                          unsigned int n,
6315
 
                                          double* values,
6316
 
                                          const double* coordinates,
6317
 
                                          const ufc::cell& c) const
6318
 
  {
6319
 
    // Extract vertex coordinates
6320
 
    const double * const * element_coordinates = c.coordinates;
6321
 
    
6322
 
    // Compute Jacobian of affine map from reference cell
6323
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
6324
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
6325
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
6326
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
6327
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
6328
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
6329
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
6330
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
6331
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
6332
 
    
6333
 
    // Compute sub determinants
6334
 
    const double d00 = J_11*J_22 - J_12*J_21;
6335
 
    const double d01 = J_12*J_20 - J_10*J_22;
6336
 
    const double d02 = J_10*J_21 - J_11*J_20;
6337
 
    
6338
 
    const double d10 = J_02*J_21 - J_01*J_22;
6339
 
    const double d11 = J_00*J_22 - J_02*J_20;
6340
 
    const double d12 = J_01*J_20 - J_00*J_21;
6341
 
    
6342
 
    const double d20 = J_01*J_12 - J_02*J_11;
6343
 
    const double d21 = J_02*J_10 - J_00*J_12;
6344
 
    const double d22 = J_00*J_11 - J_01*J_10;
6345
 
    
6346
 
    // Compute determinant of Jacobian
6347
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
6348
 
    
6349
 
    // Compute inverse of Jacobian
6350
 
    
6351
 
    // Compute constants
6352
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
6353
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
6354
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
6355
 
    
6356
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
6357
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
6358
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
6359
 
    
6360
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
6361
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
6362
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
6363
 
    
6364
 
    // Get coordinates and map to the UFC reference element
6365
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
6366
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
6367
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
6368
 
    
6369
 
    // Map coordinates to the reference cube
6370
 
    if (std::abs(y + z - 1.0) < 1e-08)
6371
 
      x = 1.0;
6372
 
    else
6373
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
6374
 
    if (std::abs(z - 1.0) < 1e-08)
6375
 
      y = -1.0;
6376
 
    else
6377
 
      y = 2.0 * y/(1.0 - z) - 1.0;
6378
 
    z = 2.0 * z - 1.0;
6379
 
    
6380
 
    // Compute number of derivatives
6381
 
    unsigned int num_derivatives = 1;
6382
 
    
6383
 
    for (unsigned int j = 0; j < n; j++)
6384
 
      num_derivatives *= 3;
6385
 
    
6386
 
    
6387
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
6388
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
6389
 
    
6390
 
    for (unsigned int j = 0; j < num_derivatives; j++)
6391
 
    {
6392
 
      combinations[j] = new unsigned int [n];
6393
 
      for (unsigned int k = 0; k < n; k++)
6394
 
        combinations[j][k] = 0;
6395
 
    }
6396
 
    
6397
 
    // Generate combinations of derivatives
6398
 
    for (unsigned int row = 1; row < num_derivatives; row++)
6399
 
    {
6400
 
      for (unsigned int num = 0; num < row; num++)
6401
 
      {
6402
 
        for (unsigned int col = n-1; col+1 > 0; col--)
6403
 
        {
6404
 
          if (combinations[row][col] + 1 > 2)
6405
 
            combinations[row][col] = 0;
6406
 
          else
6407
 
          {
6408
 
            combinations[row][col] += 1;
6409
 
            break;
6410
 
          }
6411
 
        }
6412
 
      }
6413
 
    }
6414
 
    
6415
 
    // Compute inverse of Jacobian
6416
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
6417
 
    
6418
 
    // Declare transformation matrix
6419
 
    // Declare pointer to two dimensional array and initialise
6420
 
    double **transform = new double *[num_derivatives];
6421
 
    
6422
 
    for (unsigned int j = 0; j < num_derivatives; j++)
6423
 
    {
6424
 
      transform[j] = new double [num_derivatives];
6425
 
      for (unsigned int k = 0; k < num_derivatives; k++)
6426
 
        transform[j][k] = 1;
6427
 
    }
6428
 
    
6429
 
    // Construct transformation matrix
6430
 
    for (unsigned int row = 0; row < num_derivatives; row++)
6431
 
    {
6432
 
      for (unsigned int col = 0; col < num_derivatives; col++)
6433
 
      {
6434
 
        for (unsigned int k = 0; k < n; k++)
6435
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
6436
 
      }
6437
 
    }
6438
 
    
6439
 
    // Reset values
6440
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
6441
 
      values[j] = 0;
6442
 
    
6443
 
    // Map degree of freedom to element degree of freedom
6444
 
    const unsigned int dof = i;
6445
 
    
6446
 
    // Generate scalings
6447
 
    const double scalings_y_0 = 1;
6448
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
6449
 
    const double scalings_z_0 = 1;
6450
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
6451
 
    
6452
 
    // Compute psitilde_a
6453
 
    const double psitilde_a_0 = 1;
6454
 
    const double psitilde_a_1 = x;
6455
 
    
6456
 
    // Compute psitilde_bs
6457
 
    const double psitilde_bs_0_0 = 1;
6458
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
6459
 
    const double psitilde_bs_1_0 = 1;
6460
 
    
6461
 
    // Compute psitilde_cs
6462
 
    const double psitilde_cs_00_0 = 1;
6463
 
    const double psitilde_cs_00_1 = 2*z + 1;
6464
 
    const double psitilde_cs_01_0 = 1;
6465
 
    const double psitilde_cs_10_0 = 1;
6466
 
    
6467
 
    // Compute basisvalues
6468
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
6469
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
6470
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
6471
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
6472
 
    
6473
 
    // Table(s) of coefficients
6474
 
    static const double coefficients0[4][4] = \
6475
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
6476
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
6477
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
6478
 
    {0.288675135, 0, 0, 0.223606798}};
6479
 
    
6480
 
    // Interesting (new) part
6481
 
    // Tables of derivatives of the polynomial base (transpose)
6482
 
    static const double dmats0[4][4] = \
6483
 
    {{0, 0, 0, 0},
6484
 
    {6.32455532, 0, 0, 0},
6485
 
    {0, 0, 0, 0},
6486
 
    {0, 0, 0, 0}};
6487
 
    
6488
 
    static const double dmats1[4][4] = \
6489
 
    {{0, 0, 0, 0},
6490
 
    {3.16227766, 0, 0, 0},
6491
 
    {5.47722558, 0, 0, 0},
6492
 
    {0, 0, 0, 0}};
6493
 
    
6494
 
    static const double dmats2[4][4] = \
6495
 
    {{0, 0, 0, 0},
6496
 
    {3.16227766, 0, 0, 0},
6497
 
    {1.82574186, 0, 0, 0},
6498
 
    {5.16397779, 0, 0, 0}};
6499
 
    
6500
 
    // Compute reference derivatives
6501
 
    // Declare pointer to array of derivatives on FIAT element
6502
 
    double *derivatives = new double [num_derivatives];
6503
 
    
6504
 
    // Declare coefficients
6505
 
    double coeff0_0 = 0;
6506
 
    double coeff0_1 = 0;
6507
 
    double coeff0_2 = 0;
6508
 
    double coeff0_3 = 0;
6509
 
    
6510
 
    // Declare new coefficients
6511
 
    double new_coeff0_0 = 0;
6512
 
    double new_coeff0_1 = 0;
6513
 
    double new_coeff0_2 = 0;
6514
 
    double new_coeff0_3 = 0;
6515
 
    
6516
 
    // Loop possible derivatives
6517
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
6518
 
    {
6519
 
      // Get values from coefficients array
6520
 
      new_coeff0_0 = coefficients0[dof][0];
6521
 
      new_coeff0_1 = coefficients0[dof][1];
6522
 
      new_coeff0_2 = coefficients0[dof][2];
6523
 
      new_coeff0_3 = coefficients0[dof][3];
6524
 
    
6525
 
      // Loop derivative order
6526
 
      for (unsigned int j = 0; j < n; j++)
6527
 
      {
6528
 
        // Update old coefficients
6529
 
        coeff0_0 = new_coeff0_0;
6530
 
        coeff0_1 = new_coeff0_1;
6531
 
        coeff0_2 = new_coeff0_2;
6532
 
        coeff0_3 = new_coeff0_3;
6533
 
    
6534
 
        if(combinations[deriv_num][j] == 0)
6535
 
        {
6536
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
6537
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
6538
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
6539
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
6540
 
        }
6541
 
        if(combinations[deriv_num][j] == 1)
6542
 
        {
6543
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
6544
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
6545
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
6546
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
6547
 
        }
6548
 
        if(combinations[deriv_num][j] == 2)
6549
 
        {
6550
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
6551
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
6552
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
6553
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
6554
 
        }
6555
 
    
6556
 
      }
6557
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
6558
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
6559
 
    }
6560
 
    
6561
 
    // Transform derivatives back to physical element
6562
 
    for (unsigned int row = 0; row < num_derivatives; row++)
6563
 
    {
6564
 
      for (unsigned int col = 0; col < num_derivatives; col++)
6565
 
      {
6566
 
        values[row] += transform[row][col]*derivatives[col];
6567
 
      }
6568
 
    }
6569
 
    // Delete pointer to array of derivatives on FIAT element
6570
 
    delete [] derivatives;
6571
 
    
6572
 
    // Delete pointer to array of combinations of derivatives and transform
6573
 
    for (unsigned int row = 0; row < num_derivatives; row++)
6574
 
    {
6575
 
      delete [] combinations[row];
6576
 
      delete [] transform[row];
6577
 
    }
6578
 
    
6579
 
    delete [] combinations;
6580
 
    delete [] transform;
6581
 
  }
6582
 
 
6583
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
6584
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
6585
 
                                              double* values,
6586
 
                                              const double* coordinates,
6587
 
                                              const ufc::cell& c) const
6588
 
  {
6589
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
6590
 
  }
6591
 
 
6592
 
  /// Evaluate linear functional for dof i on the function f
6593
 
  virtual double evaluate_dof(unsigned int i,
6594
 
                              const ufc::function& f,
6595
 
                              const ufc::cell& c) const
6596
 
  {
6597
 
    // The reference points, direction and weights:
6598
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
6599
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
6600
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
6601
 
    
6602
 
    const double * const * x = c.coordinates;
6603
 
    double result = 0.0;
6604
 
    // Iterate over the points:
6605
 
    // Evaluate basis functions for affine mapping
6606
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
6607
 
    const double w1 = X[i][0][0];
6608
 
    const double w2 = X[i][0][1];
6609
 
    const double w3 = X[i][0][2];
6610
 
    
6611
 
    // Compute affine mapping y = F(X)
6612
 
    double y[3];
6613
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
6614
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
6615
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
6616
 
    
6617
 
    // Evaluate function at physical points
6618
 
    double values[1];
6619
 
    f.evaluate(values, y, c);
6620
 
    
6621
 
    // Map function values using appropriate mapping
6622
 
    // Affine map: Do nothing
6623
 
    
6624
 
    // Note that we do not map the weights (yet).
6625
 
    
6626
 
    // Take directional components
6627
 
    for(int k = 0; k < 1; k++)
6628
 
      result += values[k]*D[i][0][k];
6629
 
    // Multiply by weights
6630
 
    result *= W[i][0];
6631
 
    
6632
 
    return result;
6633
 
  }
6634
 
 
6635
 
  /// Evaluate linear functionals for all dofs on the function f
6636
 
  virtual void evaluate_dofs(double* values,
6637
 
                             const ufc::function& f,
6638
 
                             const ufc::cell& c) const
6639
 
  {
6640
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
6641
 
  }
6642
 
 
6643
 
  /// Interpolate vertex values from dof values
6644
 
  virtual void interpolate_vertex_values(double* vertex_values,
6645
 
                                         const double* dof_values,
6646
 
                                         const ufc::cell& c) const
6647
 
  {
6648
 
    // Evaluate at vertices and use affine mapping
6649
 
    vertex_values[0] = dof_values[0];
6650
 
    vertex_values[1] = dof_values[1];
6651
 
    vertex_values[2] = dof_values[2];
6652
 
    vertex_values[3] = dof_values[3];
6653
 
  }
6654
 
 
6655
 
  /// Return the number of sub elements (for a mixed element)
6656
 
  virtual unsigned int num_sub_elements() const
6657
 
  {
6658
 
    return 1;
6659
 
  }
6660
 
 
6661
 
  /// Create a new finite element for sub element i (for a mixed element)
6662
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
6663
 
  {
6664
 
    return new hyperelasticity_0_finite_element_2_2();
6665
 
  }
6666
 
 
6667
 
};
6668
 
 
6669
 
/// This class defines the interface for a finite element.
6670
 
 
6671
 
class hyperelasticity_0_finite_element_2: public ufc::finite_element
6672
 
{
6673
 
public:
6674
 
 
6675
 
  /// Constructor
6676
 
  hyperelasticity_0_finite_element_2() : ufc::finite_element()
6677
 
  {
6678
 
    // Do nothing
6679
 
  }
6680
 
 
6681
 
  /// Destructor
6682
 
  virtual ~hyperelasticity_0_finite_element_2()
6683
 
  {
6684
 
    // Do nothing
6685
 
  }
6686
 
 
6687
 
  /// Return a string identifying the finite element
6688
 
  virtual const char* signature() const
6689
 
  {
6690
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
6691
 
  }
6692
 
 
6693
 
  /// Return the cell shape
6694
 
  virtual ufc::shape cell_shape() const
6695
 
  {
6696
 
    return ufc::tetrahedron;
6697
 
  }
6698
 
 
6699
 
  /// Return the dimension of the finite element function space
6700
 
  virtual unsigned int space_dimension() const
6701
 
  {
6702
 
    return 12;
6703
 
  }
6704
 
 
6705
 
  /// Return the rank of the value space
6706
 
  virtual unsigned int value_rank() const
6707
 
  {
6708
 
    return 1;
6709
 
  }
6710
 
 
6711
 
  /// Return the dimension of the value space for axis i
6712
 
  virtual unsigned int value_dimension(unsigned int i) const
6713
 
  {
6714
 
    return 3;
6715
 
  }
6716
 
 
6717
 
  /// Evaluate basis function i at given point in cell
6718
 
  virtual void evaluate_basis(unsigned int i,
6719
 
                              double* values,
6720
 
                              const double* coordinates,
6721
 
                              const ufc::cell& c) const
6722
 
  {
6723
 
    // Extract vertex coordinates
6724
 
    const double * const * element_coordinates = c.coordinates;
6725
 
    
6726
 
    // Compute Jacobian of affine map from reference cell
6727
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
6728
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
6729
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
6730
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
6731
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
6732
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
6733
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
6734
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
6735
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
6736
 
    
6737
 
    // Compute sub determinants
6738
 
    const double d00 = J_11*J_22 - J_12*J_21;
6739
 
    const double d01 = J_12*J_20 - J_10*J_22;
6740
 
    const double d02 = J_10*J_21 - J_11*J_20;
6741
 
    
6742
 
    const double d10 = J_02*J_21 - J_01*J_22;
6743
 
    const double d11 = J_00*J_22 - J_02*J_20;
6744
 
    const double d12 = J_01*J_20 - J_00*J_21;
6745
 
    
6746
 
    const double d20 = J_01*J_12 - J_02*J_11;
6747
 
    const double d21 = J_02*J_10 - J_00*J_12;
6748
 
    const double d22 = J_00*J_11 - J_01*J_10;
6749
 
    
6750
 
    // Compute determinant of Jacobian
6751
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
6752
 
    
6753
 
    // Compute inverse of Jacobian
6754
 
    
6755
 
    // Compute constants
6756
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
6757
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
6758
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
6759
 
    
6760
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
6761
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
6762
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
6763
 
    
6764
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
6765
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
6766
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
6767
 
    
6768
 
    // Get coordinates and map to the UFC reference element
6769
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
6770
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
6771
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
6772
 
    
6773
 
    // Map coordinates to the reference cube
6774
 
    if (std::abs(y + z - 1.0) < 1e-08)
6775
 
      x = 1.0;
6776
 
    else
6777
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
6778
 
    if (std::abs(z - 1.0) < 1e-08)
6779
 
      y = -1.0;
6780
 
    else
6781
 
      y = 2.0 * y/(1.0 - z) - 1.0;
6782
 
    z = 2.0 * z - 1.0;
6783
 
    
6784
 
    // Reset values
6785
 
    values[0] = 0;
6786
 
    values[1] = 0;
6787
 
    values[2] = 0;
6788
 
    
6789
 
    if (0 <= i && i <= 3)
6790
 
    {
6791
 
      // Map degree of freedom to element degree of freedom
6792
 
      const unsigned int dof = i;
6793
 
    
6794
 
      // Generate scalings
6795
 
      const double scalings_y_0 = 1;
6796
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
6797
 
      const double scalings_z_0 = 1;
6798
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
6799
 
    
6800
 
      // Compute psitilde_a
6801
 
      const double psitilde_a_0 = 1;
6802
 
      const double psitilde_a_1 = x;
6803
 
    
6804
 
      // Compute psitilde_bs
6805
 
      const double psitilde_bs_0_0 = 1;
6806
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
6807
 
      const double psitilde_bs_1_0 = 1;
6808
 
    
6809
 
      // Compute psitilde_cs
6810
 
      const double psitilde_cs_00_0 = 1;
6811
 
      const double psitilde_cs_00_1 = 2*z + 1;
6812
 
      const double psitilde_cs_01_0 = 1;
6813
 
      const double psitilde_cs_10_0 = 1;
6814
 
    
6815
 
      // Compute basisvalues
6816
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
6817
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
6818
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
6819
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
6820
 
    
6821
 
      // Table(s) of coefficients
6822
 
      static const double coefficients0[4][4] =   \
6823
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
6824
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
6825
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
6826
 
      {0.288675135, 0, 0, 0.223606798}};
6827
 
    
6828
 
      // Extract relevant coefficients
6829
 
      const double coeff0_0 =   coefficients0[dof][0];
6830
 
      const double coeff0_1 =   coefficients0[dof][1];
6831
 
      const double coeff0_2 =   coefficients0[dof][2];
6832
 
      const double coeff0_3 =   coefficients0[dof][3];
6833
 
    
6834
 
      // Compute value(s)
6835
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
6836
 
    }
6837
 
    
6838
 
    if (4 <= i && i <= 7)
6839
 
    {
6840
 
      // Map degree of freedom to element degree of freedom
6841
 
      const unsigned int dof = i - 4;
6842
 
    
6843
 
      // Generate scalings
6844
 
      const double scalings_y_0 = 1;
6845
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
6846
 
      const double scalings_z_0 = 1;
6847
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
6848
 
    
6849
 
      // Compute psitilde_a
6850
 
      const double psitilde_a_0 = 1;
6851
 
      const double psitilde_a_1 = x;
6852
 
    
6853
 
      // Compute psitilde_bs
6854
 
      const double psitilde_bs_0_0 = 1;
6855
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
6856
 
      const double psitilde_bs_1_0 = 1;
6857
 
    
6858
 
      // Compute psitilde_cs
6859
 
      const double psitilde_cs_00_0 = 1;
6860
 
      const double psitilde_cs_00_1 = 2*z + 1;
6861
 
      const double psitilde_cs_01_0 = 1;
6862
 
      const double psitilde_cs_10_0 = 1;
6863
 
    
6864
 
      // Compute basisvalues
6865
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
6866
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
6867
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
6868
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
6869
 
    
6870
 
      // Table(s) of coefficients
6871
 
      static const double coefficients0[4][4] =   \
6872
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
6873
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
6874
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
6875
 
      {0.288675135, 0, 0, 0.223606798}};
6876
 
    
6877
 
      // Extract relevant coefficients
6878
 
      const double coeff0_0 =   coefficients0[dof][0];
6879
 
      const double coeff0_1 =   coefficients0[dof][1];
6880
 
      const double coeff0_2 =   coefficients0[dof][2];
6881
 
      const double coeff0_3 =   coefficients0[dof][3];
6882
 
    
6883
 
      // Compute value(s)
6884
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
6885
 
    }
6886
 
    
6887
 
    if (8 <= i && i <= 11)
6888
 
    {
6889
 
      // Map degree of freedom to element degree of freedom
6890
 
      const unsigned int dof = i - 8;
6891
 
    
6892
 
      // Generate scalings
6893
 
      const double scalings_y_0 = 1;
6894
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
6895
 
      const double scalings_z_0 = 1;
6896
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
6897
 
    
6898
 
      // Compute psitilde_a
6899
 
      const double psitilde_a_0 = 1;
6900
 
      const double psitilde_a_1 = x;
6901
 
    
6902
 
      // Compute psitilde_bs
6903
 
      const double psitilde_bs_0_0 = 1;
6904
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
6905
 
      const double psitilde_bs_1_0 = 1;
6906
 
    
6907
 
      // Compute psitilde_cs
6908
 
      const double psitilde_cs_00_0 = 1;
6909
 
      const double psitilde_cs_00_1 = 2*z + 1;
6910
 
      const double psitilde_cs_01_0 = 1;
6911
 
      const double psitilde_cs_10_0 = 1;
6912
 
    
6913
 
      // Compute basisvalues
6914
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
6915
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
6916
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
6917
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
6918
 
    
6919
 
      // Table(s) of coefficients
6920
 
      static const double coefficients0[4][4] =   \
6921
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
6922
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
6923
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
6924
 
      {0.288675135, 0, 0, 0.223606798}};
6925
 
    
6926
 
      // Extract relevant coefficients
6927
 
      const double coeff0_0 =   coefficients0[dof][0];
6928
 
      const double coeff0_1 =   coefficients0[dof][1];
6929
 
      const double coeff0_2 =   coefficients0[dof][2];
6930
 
      const double coeff0_3 =   coefficients0[dof][3];
6931
 
    
6932
 
      // Compute value(s)
6933
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
6934
 
    }
6935
 
    
6936
 
  }
6937
 
 
6938
 
  /// Evaluate all basis functions at given point in cell
6939
 
  virtual void evaluate_basis_all(double* values,
6940
 
                                  const double* coordinates,
6941
 
                                  const ufc::cell& c) const
6942
 
  {
6943
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
6944
 
  }
6945
 
 
6946
 
  /// Evaluate order n derivatives of basis function i at given point in cell
6947
 
  virtual void evaluate_basis_derivatives(unsigned int i,
6948
 
                                          unsigned int n,
6949
 
                                          double* values,
6950
 
                                          const double* coordinates,
6951
 
                                          const ufc::cell& c) const
6952
 
  {
6953
 
    // Extract vertex coordinates
6954
 
    const double * const * element_coordinates = c.coordinates;
6955
 
    
6956
 
    // Compute Jacobian of affine map from reference cell
6957
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
6958
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
6959
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
6960
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
6961
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
6962
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
6963
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
6964
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
6965
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
6966
 
    
6967
 
    // Compute sub determinants
6968
 
    const double d00 = J_11*J_22 - J_12*J_21;
6969
 
    const double d01 = J_12*J_20 - J_10*J_22;
6970
 
    const double d02 = J_10*J_21 - J_11*J_20;
6971
 
    
6972
 
    const double d10 = J_02*J_21 - J_01*J_22;
6973
 
    const double d11 = J_00*J_22 - J_02*J_20;
6974
 
    const double d12 = J_01*J_20 - J_00*J_21;
6975
 
    
6976
 
    const double d20 = J_01*J_12 - J_02*J_11;
6977
 
    const double d21 = J_02*J_10 - J_00*J_12;
6978
 
    const double d22 = J_00*J_11 - J_01*J_10;
6979
 
    
6980
 
    // Compute determinant of Jacobian
6981
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
6982
 
    
6983
 
    // Compute inverse of Jacobian
6984
 
    
6985
 
    // Compute constants
6986
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
6987
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
6988
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
6989
 
    
6990
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
6991
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
6992
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
6993
 
    
6994
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
6995
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
6996
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
6997
 
    
6998
 
    // Get coordinates and map to the UFC reference element
6999
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
7000
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
7001
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
7002
 
    
7003
 
    // Map coordinates to the reference cube
7004
 
    if (std::abs(y + z - 1.0) < 1e-08)
7005
 
      x = 1.0;
7006
 
    else
7007
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
7008
 
    if (std::abs(z - 1.0) < 1e-08)
7009
 
      y = -1.0;
7010
 
    else
7011
 
      y = 2.0 * y/(1.0 - z) - 1.0;
7012
 
    z = 2.0 * z - 1.0;
7013
 
    
7014
 
    // Compute number of derivatives
7015
 
    unsigned int num_derivatives = 1;
7016
 
    
7017
 
    for (unsigned int j = 0; j < n; j++)
7018
 
      num_derivatives *= 3;
7019
 
    
7020
 
    
7021
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
7022
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
7023
 
    
7024
 
    for (unsigned int j = 0; j < num_derivatives; j++)
7025
 
    {
7026
 
      combinations[j] = new unsigned int [n];
7027
 
      for (unsigned int k = 0; k < n; k++)
7028
 
        combinations[j][k] = 0;
7029
 
    }
7030
 
    
7031
 
    // Generate combinations of derivatives
7032
 
    for (unsigned int row = 1; row < num_derivatives; row++)
7033
 
    {
7034
 
      for (unsigned int num = 0; num < row; num++)
7035
 
      {
7036
 
        for (unsigned int col = n-1; col+1 > 0; col--)
7037
 
        {
7038
 
          if (combinations[row][col] + 1 > 2)
7039
 
            combinations[row][col] = 0;
7040
 
          else
7041
 
          {
7042
 
            combinations[row][col] += 1;
7043
 
            break;
7044
 
          }
7045
 
        }
7046
 
      }
7047
 
    }
7048
 
    
7049
 
    // Compute inverse of Jacobian
7050
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
7051
 
    
7052
 
    // Declare transformation matrix
7053
 
    // Declare pointer to two dimensional array and initialise
7054
 
    double **transform = new double *[num_derivatives];
7055
 
    
7056
 
    for (unsigned int j = 0; j < num_derivatives; j++)
7057
 
    {
7058
 
      transform[j] = new double [num_derivatives];
7059
 
      for (unsigned int k = 0; k < num_derivatives; k++)
7060
 
        transform[j][k] = 1;
7061
 
    }
7062
 
    
7063
 
    // Construct transformation matrix
7064
 
    for (unsigned int row = 0; row < num_derivatives; row++)
7065
 
    {
7066
 
      for (unsigned int col = 0; col < num_derivatives; col++)
7067
 
      {
7068
 
        for (unsigned int k = 0; k < n; k++)
7069
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
7070
 
      }
7071
 
    }
7072
 
    
7073
 
    // Reset values
7074
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
7075
 
      values[j] = 0;
7076
 
    
7077
 
    if (0 <= i && i <= 3)
7078
 
    {
7079
 
      // Map degree of freedom to element degree of freedom
7080
 
      const unsigned int dof = i;
7081
 
    
7082
 
      // Generate scalings
7083
 
      const double scalings_y_0 = 1;
7084
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
7085
 
      const double scalings_z_0 = 1;
7086
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
7087
 
    
7088
 
      // Compute psitilde_a
7089
 
      const double psitilde_a_0 = 1;
7090
 
      const double psitilde_a_1 = x;
7091
 
    
7092
 
      // Compute psitilde_bs
7093
 
      const double psitilde_bs_0_0 = 1;
7094
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
7095
 
      const double psitilde_bs_1_0 = 1;
7096
 
    
7097
 
      // Compute psitilde_cs
7098
 
      const double psitilde_cs_00_0 = 1;
7099
 
      const double psitilde_cs_00_1 = 2*z + 1;
7100
 
      const double psitilde_cs_01_0 = 1;
7101
 
      const double psitilde_cs_10_0 = 1;
7102
 
    
7103
 
      // Compute basisvalues
7104
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
7105
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
7106
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
7107
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
7108
 
    
7109
 
      // Table(s) of coefficients
7110
 
      static const double coefficients0[4][4] =   \
7111
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
7112
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
7113
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
7114
 
      {0.288675135, 0, 0, 0.223606798}};
7115
 
    
7116
 
      // Interesting (new) part
7117
 
      // Tables of derivatives of the polynomial base (transpose)
7118
 
      static const double dmats0[4][4] =   \
7119
 
      {{0, 0, 0, 0},
7120
 
      {6.32455532, 0, 0, 0},
7121
 
      {0, 0, 0, 0},
7122
 
      {0, 0, 0, 0}};
7123
 
    
7124
 
      static const double dmats1[4][4] =   \
7125
 
      {{0, 0, 0, 0},
7126
 
      {3.16227766, 0, 0, 0},
7127
 
      {5.47722558, 0, 0, 0},
7128
 
      {0, 0, 0, 0}};
7129
 
    
7130
 
      static const double dmats2[4][4] =   \
7131
 
      {{0, 0, 0, 0},
7132
 
      {3.16227766, 0, 0, 0},
7133
 
      {1.82574186, 0, 0, 0},
7134
 
      {5.16397779, 0, 0, 0}};
7135
 
    
7136
 
      // Compute reference derivatives
7137
 
      // Declare pointer to array of derivatives on FIAT element
7138
 
      double *derivatives = new double [num_derivatives];
7139
 
    
7140
 
      // Declare coefficients
7141
 
      double coeff0_0 = 0;
7142
 
      double coeff0_1 = 0;
7143
 
      double coeff0_2 = 0;
7144
 
      double coeff0_3 = 0;
7145
 
    
7146
 
      // Declare new coefficients
7147
 
      double new_coeff0_0 = 0;
7148
 
      double new_coeff0_1 = 0;
7149
 
      double new_coeff0_2 = 0;
7150
 
      double new_coeff0_3 = 0;
7151
 
    
7152
 
      // Loop possible derivatives
7153
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
7154
 
      {
7155
 
        // Get values from coefficients array
7156
 
        new_coeff0_0 = coefficients0[dof][0];
7157
 
        new_coeff0_1 = coefficients0[dof][1];
7158
 
        new_coeff0_2 = coefficients0[dof][2];
7159
 
        new_coeff0_3 = coefficients0[dof][3];
7160
 
    
7161
 
        // Loop derivative order
7162
 
        for (unsigned int j = 0; j < n; j++)
7163
 
        {
7164
 
          // Update old coefficients
7165
 
          coeff0_0 = new_coeff0_0;
7166
 
          coeff0_1 = new_coeff0_1;
7167
 
          coeff0_2 = new_coeff0_2;
7168
 
          coeff0_3 = new_coeff0_3;
7169
 
    
7170
 
          if(combinations[deriv_num][j] == 0)
7171
 
          {
7172
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
7173
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
7174
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
7175
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
7176
 
          }
7177
 
          if(combinations[deriv_num][j] == 1)
7178
 
          {
7179
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
7180
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
7181
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
7182
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
7183
 
          }
7184
 
          if(combinations[deriv_num][j] == 2)
7185
 
          {
7186
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
7187
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
7188
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
7189
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
7190
 
          }
7191
 
    
7192
 
        }
7193
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
7194
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
7195
 
      }
7196
 
    
7197
 
      // Transform derivatives back to physical element
7198
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7199
 
      {
7200
 
        for (unsigned int col = 0; col < num_derivatives; col++)
7201
 
        {
7202
 
          values[row] += transform[row][col]*derivatives[col];
7203
 
        }
7204
 
      }
7205
 
      // Delete pointer to array of derivatives on FIAT element
7206
 
      delete [] derivatives;
7207
 
    
7208
 
      // Delete pointer to array of combinations of derivatives and transform
7209
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7210
 
      {
7211
 
        delete [] combinations[row];
7212
 
        delete [] transform[row];
7213
 
      }
7214
 
    
7215
 
      delete [] combinations;
7216
 
      delete [] transform;
7217
 
    }
7218
 
    
7219
 
    if (4 <= i && i <= 7)
7220
 
    {
7221
 
      // Map degree of freedom to element degree of freedom
7222
 
      const unsigned int dof = i - 4;
7223
 
    
7224
 
      // Generate scalings
7225
 
      const double scalings_y_0 = 1;
7226
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
7227
 
      const double scalings_z_0 = 1;
7228
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
7229
 
    
7230
 
      // Compute psitilde_a
7231
 
      const double psitilde_a_0 = 1;
7232
 
      const double psitilde_a_1 = x;
7233
 
    
7234
 
      // Compute psitilde_bs
7235
 
      const double psitilde_bs_0_0 = 1;
7236
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
7237
 
      const double psitilde_bs_1_0 = 1;
7238
 
    
7239
 
      // Compute psitilde_cs
7240
 
      const double psitilde_cs_00_0 = 1;
7241
 
      const double psitilde_cs_00_1 = 2*z + 1;
7242
 
      const double psitilde_cs_01_0 = 1;
7243
 
      const double psitilde_cs_10_0 = 1;
7244
 
    
7245
 
      // Compute basisvalues
7246
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
7247
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
7248
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
7249
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
7250
 
    
7251
 
      // Table(s) of coefficients
7252
 
      static const double coefficients0[4][4] =   \
7253
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
7254
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
7255
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
7256
 
      {0.288675135, 0, 0, 0.223606798}};
7257
 
    
7258
 
      // Interesting (new) part
7259
 
      // Tables of derivatives of the polynomial base (transpose)
7260
 
      static const double dmats0[4][4] =   \
7261
 
      {{0, 0, 0, 0},
7262
 
      {6.32455532, 0, 0, 0},
7263
 
      {0, 0, 0, 0},
7264
 
      {0, 0, 0, 0}};
7265
 
    
7266
 
      static const double dmats1[4][4] =   \
7267
 
      {{0, 0, 0, 0},
7268
 
      {3.16227766, 0, 0, 0},
7269
 
      {5.47722558, 0, 0, 0},
7270
 
      {0, 0, 0, 0}};
7271
 
    
7272
 
      static const double dmats2[4][4] =   \
7273
 
      {{0, 0, 0, 0},
7274
 
      {3.16227766, 0, 0, 0},
7275
 
      {1.82574186, 0, 0, 0},
7276
 
      {5.16397779, 0, 0, 0}};
7277
 
    
7278
 
      // Compute reference derivatives
7279
 
      // Declare pointer to array of derivatives on FIAT element
7280
 
      double *derivatives = new double [num_derivatives];
7281
 
    
7282
 
      // Declare coefficients
7283
 
      double coeff0_0 = 0;
7284
 
      double coeff0_1 = 0;
7285
 
      double coeff0_2 = 0;
7286
 
      double coeff0_3 = 0;
7287
 
    
7288
 
      // Declare new coefficients
7289
 
      double new_coeff0_0 = 0;
7290
 
      double new_coeff0_1 = 0;
7291
 
      double new_coeff0_2 = 0;
7292
 
      double new_coeff0_3 = 0;
7293
 
    
7294
 
      // Loop possible derivatives
7295
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
7296
 
      {
7297
 
        // Get values from coefficients array
7298
 
        new_coeff0_0 = coefficients0[dof][0];
7299
 
        new_coeff0_1 = coefficients0[dof][1];
7300
 
        new_coeff0_2 = coefficients0[dof][2];
7301
 
        new_coeff0_3 = coefficients0[dof][3];
7302
 
    
7303
 
        // Loop derivative order
7304
 
        for (unsigned int j = 0; j < n; j++)
7305
 
        {
7306
 
          // Update old coefficients
7307
 
          coeff0_0 = new_coeff0_0;
7308
 
          coeff0_1 = new_coeff0_1;
7309
 
          coeff0_2 = new_coeff0_2;
7310
 
          coeff0_3 = new_coeff0_3;
7311
 
    
7312
 
          if(combinations[deriv_num][j] == 0)
7313
 
          {
7314
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
7315
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
7316
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
7317
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
7318
 
          }
7319
 
          if(combinations[deriv_num][j] == 1)
7320
 
          {
7321
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
7322
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
7323
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
7324
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
7325
 
          }
7326
 
          if(combinations[deriv_num][j] == 2)
7327
 
          {
7328
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
7329
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
7330
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
7331
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
7332
 
          }
7333
 
    
7334
 
        }
7335
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
7336
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
7337
 
      }
7338
 
    
7339
 
      // Transform derivatives back to physical element
7340
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7341
 
      {
7342
 
        for (unsigned int col = 0; col < num_derivatives; col++)
7343
 
        {
7344
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
7345
 
        }
7346
 
      }
7347
 
      // Delete pointer to array of derivatives on FIAT element
7348
 
      delete [] derivatives;
7349
 
    
7350
 
      // Delete pointer to array of combinations of derivatives and transform
7351
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7352
 
      {
7353
 
        delete [] combinations[row];
7354
 
        delete [] transform[row];
7355
 
      }
7356
 
    
7357
 
      delete [] combinations;
7358
 
      delete [] transform;
7359
 
    }
7360
 
    
7361
 
    if (8 <= i && i <= 11)
7362
 
    {
7363
 
      // Map degree of freedom to element degree of freedom
7364
 
      const unsigned int dof = i - 8;
7365
 
    
7366
 
      // Generate scalings
7367
 
      const double scalings_y_0 = 1;
7368
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
7369
 
      const double scalings_z_0 = 1;
7370
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
7371
 
    
7372
 
      // Compute psitilde_a
7373
 
      const double psitilde_a_0 = 1;
7374
 
      const double psitilde_a_1 = x;
7375
 
    
7376
 
      // Compute psitilde_bs
7377
 
      const double psitilde_bs_0_0 = 1;
7378
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
7379
 
      const double psitilde_bs_1_0 = 1;
7380
 
    
7381
 
      // Compute psitilde_cs
7382
 
      const double psitilde_cs_00_0 = 1;
7383
 
      const double psitilde_cs_00_1 = 2*z + 1;
7384
 
      const double psitilde_cs_01_0 = 1;
7385
 
      const double psitilde_cs_10_0 = 1;
7386
 
    
7387
 
      // Compute basisvalues
7388
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
7389
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
7390
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
7391
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
7392
 
    
7393
 
      // Table(s) of coefficients
7394
 
      static const double coefficients0[4][4] =   \
7395
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
7396
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
7397
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
7398
 
      {0.288675135, 0, 0, 0.223606798}};
7399
 
    
7400
 
      // Interesting (new) part
7401
 
      // Tables of derivatives of the polynomial base (transpose)
7402
 
      static const double dmats0[4][4] =   \
7403
 
      {{0, 0, 0, 0},
7404
 
      {6.32455532, 0, 0, 0},
7405
 
      {0, 0, 0, 0},
7406
 
      {0, 0, 0, 0}};
7407
 
    
7408
 
      static const double dmats1[4][4] =   \
7409
 
      {{0, 0, 0, 0},
7410
 
      {3.16227766, 0, 0, 0},
7411
 
      {5.47722558, 0, 0, 0},
7412
 
      {0, 0, 0, 0}};
7413
 
    
7414
 
      static const double dmats2[4][4] =   \
7415
 
      {{0, 0, 0, 0},
7416
 
      {3.16227766, 0, 0, 0},
7417
 
      {1.82574186, 0, 0, 0},
7418
 
      {5.16397779, 0, 0, 0}};
7419
 
    
7420
 
      // Compute reference derivatives
7421
 
      // Declare pointer to array of derivatives on FIAT element
7422
 
      double *derivatives = new double [num_derivatives];
7423
 
    
7424
 
      // Declare coefficients
7425
 
      double coeff0_0 = 0;
7426
 
      double coeff0_1 = 0;
7427
 
      double coeff0_2 = 0;
7428
 
      double coeff0_3 = 0;
7429
 
    
7430
 
      // Declare new coefficients
7431
 
      double new_coeff0_0 = 0;
7432
 
      double new_coeff0_1 = 0;
7433
 
      double new_coeff0_2 = 0;
7434
 
      double new_coeff0_3 = 0;
7435
 
    
7436
 
      // Loop possible derivatives
7437
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
7438
 
      {
7439
 
        // Get values from coefficients array
7440
 
        new_coeff0_0 = coefficients0[dof][0];
7441
 
        new_coeff0_1 = coefficients0[dof][1];
7442
 
        new_coeff0_2 = coefficients0[dof][2];
7443
 
        new_coeff0_3 = coefficients0[dof][3];
7444
 
    
7445
 
        // Loop derivative order
7446
 
        for (unsigned int j = 0; j < n; j++)
7447
 
        {
7448
 
          // Update old coefficients
7449
 
          coeff0_0 = new_coeff0_0;
7450
 
          coeff0_1 = new_coeff0_1;
7451
 
          coeff0_2 = new_coeff0_2;
7452
 
          coeff0_3 = new_coeff0_3;
7453
 
    
7454
 
          if(combinations[deriv_num][j] == 0)
7455
 
          {
7456
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
7457
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
7458
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
7459
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
7460
 
          }
7461
 
          if(combinations[deriv_num][j] == 1)
7462
 
          {
7463
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
7464
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
7465
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
7466
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
7467
 
          }
7468
 
          if(combinations[deriv_num][j] == 2)
7469
 
          {
7470
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
7471
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
7472
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
7473
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
7474
 
          }
7475
 
    
7476
 
        }
7477
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
7478
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
7479
 
      }
7480
 
    
7481
 
      // Transform derivatives back to physical element
7482
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7483
 
      {
7484
 
        for (unsigned int col = 0; col < num_derivatives; col++)
7485
 
        {
7486
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
7487
 
        }
7488
 
      }
7489
 
      // Delete pointer to array of derivatives on FIAT element
7490
 
      delete [] derivatives;
7491
 
    
7492
 
      // Delete pointer to array of combinations of derivatives and transform
7493
 
      for (unsigned int row = 0; row < num_derivatives; row++)
7494
 
      {
7495
 
        delete [] combinations[row];
7496
 
        delete [] transform[row];
7497
 
      }
7498
 
    
7499
 
      delete [] combinations;
7500
 
      delete [] transform;
7501
 
    }
7502
 
    
7503
 
  }
7504
 
 
7505
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
7506
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
7507
 
                                              double* values,
7508
 
                                              const double* coordinates,
7509
 
                                              const ufc::cell& c) const
7510
 
  {
7511
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
7512
 
  }
7513
 
 
7514
 
  /// Evaluate linear functional for dof i on the function f
7515
 
  virtual double evaluate_dof(unsigned int i,
7516
 
                              const ufc::function& f,
7517
 
                              const ufc::cell& c) const
7518
 
  {
7519
 
    // The reference points, direction and weights:
7520
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
7521
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
7522
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
7523
 
    
7524
 
    const double * const * x = c.coordinates;
7525
 
    double result = 0.0;
7526
 
    // Iterate over the points:
7527
 
    // Evaluate basis functions for affine mapping
7528
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
7529
 
    const double w1 = X[i][0][0];
7530
 
    const double w2 = X[i][0][1];
7531
 
    const double w3 = X[i][0][2];
7532
 
    
7533
 
    // Compute affine mapping y = F(X)
7534
 
    double y[3];
7535
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
7536
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
7537
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
7538
 
    
7539
 
    // Evaluate function at physical points
7540
 
    double values[3];
7541
 
    f.evaluate(values, y, c);
7542
 
    
7543
 
    // Map function values using appropriate mapping
7544
 
    // Affine map: Do nothing
7545
 
    
7546
 
    // Note that we do not map the weights (yet).
7547
 
    
7548
 
    // Take directional components
7549
 
    for(int k = 0; k < 3; k++)
7550
 
      result += values[k]*D[i][0][k];
7551
 
    // Multiply by weights
7552
 
    result *= W[i][0];
7553
 
    
7554
 
    return result;
7555
 
  }
7556
 
 
7557
 
  /// Evaluate linear functionals for all dofs on the function f
7558
 
  virtual void evaluate_dofs(double* values,
7559
 
                             const ufc::function& f,
7560
 
                             const ufc::cell& c) const
7561
 
  {
7562
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
7563
 
  }
7564
 
 
7565
 
  /// Interpolate vertex values from dof values
7566
 
  virtual void interpolate_vertex_values(double* vertex_values,
7567
 
                                         const double* dof_values,
7568
 
                                         const ufc::cell& c) const
7569
 
  {
7570
 
    // Evaluate at vertices and use affine mapping
7571
 
    vertex_values[0] = dof_values[0];
7572
 
    vertex_values[3] = dof_values[1];
7573
 
    vertex_values[6] = dof_values[2];
7574
 
    vertex_values[9] = dof_values[3];
7575
 
    // Evaluate at vertices and use affine mapping
7576
 
    vertex_values[1] = dof_values[4];
7577
 
    vertex_values[4] = dof_values[5];
7578
 
    vertex_values[7] = dof_values[6];
7579
 
    vertex_values[10] = dof_values[7];
7580
 
    // Evaluate at vertices and use affine mapping
7581
 
    vertex_values[2] = dof_values[8];
7582
 
    vertex_values[5] = dof_values[9];
7583
 
    vertex_values[8] = dof_values[10];
7584
 
    vertex_values[11] = dof_values[11];
7585
 
  }
7586
 
 
7587
 
  /// Return the number of sub elements (for a mixed element)
7588
 
  virtual unsigned int num_sub_elements() const
7589
 
  {
7590
 
    return 3;
7591
 
  }
7592
 
 
7593
 
  /// Create a new finite element for sub element i (for a mixed element)
7594
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
7595
 
  {
7596
 
    switch ( i )
7597
 
    {
7598
 
    case 0:
7599
 
      return new hyperelasticity_0_finite_element_2_0();
7600
 
      break;
7601
 
    case 1:
7602
 
      return new hyperelasticity_0_finite_element_2_1();
7603
 
      break;
7604
 
    case 2:
7605
 
      return new hyperelasticity_0_finite_element_2_2();
7606
 
      break;
7607
 
    }
7608
 
    return 0;
7609
 
  }
7610
 
 
7611
 
};
7612
 
 
7613
 
/// This class defines the interface for a finite element.
7614
 
 
7615
 
class hyperelasticity_0_finite_element_3: public ufc::finite_element
7616
 
{
7617
 
public:
7618
 
 
7619
 
  /// Constructor
7620
 
  hyperelasticity_0_finite_element_3() : ufc::finite_element()
7621
 
  {
7622
 
    // Do nothing
7623
 
  }
7624
 
 
7625
 
  /// Destructor
7626
 
  virtual ~hyperelasticity_0_finite_element_3()
7627
 
  {
7628
 
    // Do nothing
7629
 
  }
7630
 
 
7631
 
  /// Return a string identifying the finite element
7632
 
  virtual const char* signature() const
7633
 
  {
7634
 
    return "FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
7635
 
  }
7636
 
 
7637
 
  /// Return the cell shape
7638
 
  virtual ufc::shape cell_shape() const
7639
 
  {
7640
 
    return ufc::tetrahedron;
7641
 
  }
7642
 
 
7643
 
  /// Return the dimension of the finite element function space
7644
 
  virtual unsigned int space_dimension() const
7645
 
  {
7646
 
    return 1;
7647
 
  }
7648
 
 
7649
 
  /// Return the rank of the value space
7650
 
  virtual unsigned int value_rank() const
7651
 
  {
7652
 
    return 0;
7653
 
  }
7654
 
 
7655
 
  /// Return the dimension of the value space for axis i
7656
 
  virtual unsigned int value_dimension(unsigned int i) const
7657
 
  {
7658
 
    return 1;
7659
 
  }
7660
 
 
7661
 
  /// Evaluate basis function i at given point in cell
7662
 
  virtual void evaluate_basis(unsigned int i,
7663
 
                              double* values,
7664
 
                              const double* coordinates,
7665
 
                              const ufc::cell& c) const
7666
 
  {
7667
 
    // Extract vertex coordinates
7668
 
    const double * const * element_coordinates = c.coordinates;
7669
 
    
7670
 
    // Compute Jacobian of affine map from reference cell
7671
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
7672
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
7673
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
7674
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
7675
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
7676
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
7677
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
7678
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
7679
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
7680
 
    
7681
 
    // Compute sub determinants
7682
 
    const double d00 = J_11*J_22 - J_12*J_21;
7683
 
    const double d01 = J_12*J_20 - J_10*J_22;
7684
 
    const double d02 = J_10*J_21 - J_11*J_20;
7685
 
    
7686
 
    const double d10 = J_02*J_21 - J_01*J_22;
7687
 
    const double d11 = J_00*J_22 - J_02*J_20;
7688
 
    const double d12 = J_01*J_20 - J_00*J_21;
7689
 
    
7690
 
    const double d20 = J_01*J_12 - J_02*J_11;
7691
 
    const double d21 = J_02*J_10 - J_00*J_12;
7692
 
    const double d22 = J_00*J_11 - J_01*J_10;
7693
 
    
7694
 
    // Compute determinant of Jacobian
7695
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
7696
 
    
7697
 
    // Compute inverse of Jacobian
7698
 
    
7699
 
    // Compute constants
7700
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
7701
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
7702
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
7703
 
    
7704
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
7705
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
7706
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
7707
 
    
7708
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
7709
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
7710
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
7711
 
    
7712
 
    // Get coordinates and map to the UFC reference element
7713
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
7714
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
7715
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
7716
 
    
7717
 
    // Map coordinates to the reference cube
7718
 
    if (std::abs(y + z - 1.0) < 1e-08)
7719
 
      x = 1.0;
7720
 
    else
7721
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
7722
 
    if (std::abs(z - 1.0) < 1e-08)
7723
 
      y = -1.0;
7724
 
    else
7725
 
      y = 2.0 * y/(1.0 - z) - 1.0;
7726
 
    z = 2.0 * z - 1.0;
7727
 
    
7728
 
    // Reset values
7729
 
    *values = 0;
7730
 
    
7731
 
    // Map degree of freedom to element degree of freedom
7732
 
    const unsigned int dof = i;
7733
 
    
7734
 
    // Generate scalings
7735
 
    const double scalings_y_0 = 1;
7736
 
    const double scalings_z_0 = 1;
7737
 
    
7738
 
    // Compute psitilde_a
7739
 
    const double psitilde_a_0 = 1;
7740
 
    
7741
 
    // Compute psitilde_bs
7742
 
    const double psitilde_bs_0_0 = 1;
7743
 
    
7744
 
    // Compute psitilde_cs
7745
 
    const double psitilde_cs_00_0 = 1;
7746
 
    
7747
 
    // Compute basisvalues
7748
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
7749
 
    
7750
 
    // Table(s) of coefficients
7751
 
    static const double coefficients0[1][1] = \
7752
 
    {{1.15470054}};
7753
 
    
7754
 
    // Extract relevant coefficients
7755
 
    const double coeff0_0 = coefficients0[dof][0];
7756
 
    
7757
 
    // Compute value(s)
7758
 
    *values = coeff0_0*basisvalue0;
7759
 
  }
7760
 
 
7761
 
  /// Evaluate all basis functions at given point in cell
7762
 
  virtual void evaluate_basis_all(double* values,
7763
 
                                  const double* coordinates,
7764
 
                                  const ufc::cell& c) const
7765
 
  {
7766
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
7767
 
  }
7768
 
 
7769
 
  /// Evaluate order n derivatives of basis function i at given point in cell
7770
 
  virtual void evaluate_basis_derivatives(unsigned int i,
7771
 
                                          unsigned int n,
7772
 
                                          double* values,
7773
 
                                          const double* coordinates,
7774
 
                                          const ufc::cell& c) const
7775
 
  {
7776
 
    // Extract vertex coordinates
7777
 
    const double * const * element_coordinates = c.coordinates;
7778
 
    
7779
 
    // Compute Jacobian of affine map from reference cell
7780
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
7781
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
7782
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
7783
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
7784
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
7785
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
7786
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
7787
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
7788
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
7789
 
    
7790
 
    // Compute sub determinants
7791
 
    const double d00 = J_11*J_22 - J_12*J_21;
7792
 
    const double d01 = J_12*J_20 - J_10*J_22;
7793
 
    const double d02 = J_10*J_21 - J_11*J_20;
7794
 
    
7795
 
    const double d10 = J_02*J_21 - J_01*J_22;
7796
 
    const double d11 = J_00*J_22 - J_02*J_20;
7797
 
    const double d12 = J_01*J_20 - J_00*J_21;
7798
 
    
7799
 
    const double d20 = J_01*J_12 - J_02*J_11;
7800
 
    const double d21 = J_02*J_10 - J_00*J_12;
7801
 
    const double d22 = J_00*J_11 - J_01*J_10;
7802
 
    
7803
 
    // Compute determinant of Jacobian
7804
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
7805
 
    
7806
 
    // Compute inverse of Jacobian
7807
 
    
7808
 
    // Compute constants
7809
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
7810
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
7811
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
7812
 
    
7813
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
7814
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
7815
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
7816
 
    
7817
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
7818
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
7819
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
7820
 
    
7821
 
    // Get coordinates and map to the UFC reference element
7822
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
7823
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
7824
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
7825
 
    
7826
 
    // Map coordinates to the reference cube
7827
 
    if (std::abs(y + z - 1.0) < 1e-08)
7828
 
      x = 1.0;
7829
 
    else
7830
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
7831
 
    if (std::abs(z - 1.0) < 1e-08)
7832
 
      y = -1.0;
7833
 
    else
7834
 
      y = 2.0 * y/(1.0 - z) - 1.0;
7835
 
    z = 2.0 * z - 1.0;
7836
 
    
7837
 
    // Compute number of derivatives
7838
 
    unsigned int num_derivatives = 1;
7839
 
    
7840
 
    for (unsigned int j = 0; j < n; j++)
7841
 
      num_derivatives *= 3;
7842
 
    
7843
 
    
7844
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
7845
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
7846
 
    
7847
 
    for (unsigned int j = 0; j < num_derivatives; j++)
7848
 
    {
7849
 
      combinations[j] = new unsigned int [n];
7850
 
      for (unsigned int k = 0; k < n; k++)
7851
 
        combinations[j][k] = 0;
7852
 
    }
7853
 
    
7854
 
    // Generate combinations of derivatives
7855
 
    for (unsigned int row = 1; row < num_derivatives; row++)
7856
 
    {
7857
 
      for (unsigned int num = 0; num < row; num++)
7858
 
      {
7859
 
        for (unsigned int col = n-1; col+1 > 0; col--)
7860
 
        {
7861
 
          if (combinations[row][col] + 1 > 2)
7862
 
            combinations[row][col] = 0;
7863
 
          else
7864
 
          {
7865
 
            combinations[row][col] += 1;
7866
 
            break;
7867
 
          }
7868
 
        }
7869
 
      }
7870
 
    }
7871
 
    
7872
 
    // Compute inverse of Jacobian
7873
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
7874
 
    
7875
 
    // Declare transformation matrix
7876
 
    // Declare pointer to two dimensional array and initialise
7877
 
    double **transform = new double *[num_derivatives];
7878
 
    
7879
 
    for (unsigned int j = 0; j < num_derivatives; j++)
7880
 
    {
7881
 
      transform[j] = new double [num_derivatives];
7882
 
      for (unsigned int k = 0; k < num_derivatives; k++)
7883
 
        transform[j][k] = 1;
7884
 
    }
7885
 
    
7886
 
    // Construct transformation matrix
7887
 
    for (unsigned int row = 0; row < num_derivatives; row++)
7888
 
    {
7889
 
      for (unsigned int col = 0; col < num_derivatives; col++)
7890
 
      {
7891
 
        for (unsigned int k = 0; k < n; k++)
7892
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
7893
 
      }
7894
 
    }
7895
 
    
7896
 
    // Reset values
7897
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
7898
 
      values[j] = 0;
7899
 
    
7900
 
    // Map degree of freedom to element degree of freedom
7901
 
    const unsigned int dof = i;
7902
 
    
7903
 
    // Generate scalings
7904
 
    const double scalings_y_0 = 1;
7905
 
    const double scalings_z_0 = 1;
7906
 
    
7907
 
    // Compute psitilde_a
7908
 
    const double psitilde_a_0 = 1;
7909
 
    
7910
 
    // Compute psitilde_bs
7911
 
    const double psitilde_bs_0_0 = 1;
7912
 
    
7913
 
    // Compute psitilde_cs
7914
 
    const double psitilde_cs_00_0 = 1;
7915
 
    
7916
 
    // Compute basisvalues
7917
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
7918
 
    
7919
 
    // Table(s) of coefficients
7920
 
    static const double coefficients0[1][1] = \
7921
 
    {{1.15470054}};
7922
 
    
7923
 
    // Interesting (new) part
7924
 
    // Tables of derivatives of the polynomial base (transpose)
7925
 
    static const double dmats0[1][1] = \
7926
 
    {{0}};
7927
 
    
7928
 
    static const double dmats1[1][1] = \
7929
 
    {{0}};
7930
 
    
7931
 
    static const double dmats2[1][1] = \
7932
 
    {{0}};
7933
 
    
7934
 
    // Compute reference derivatives
7935
 
    // Declare pointer to array of derivatives on FIAT element
7936
 
    double *derivatives = new double [num_derivatives];
7937
 
    
7938
 
    // Declare coefficients
7939
 
    double coeff0_0 = 0;
7940
 
    
7941
 
    // Declare new coefficients
7942
 
    double new_coeff0_0 = 0;
7943
 
    
7944
 
    // Loop possible derivatives
7945
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
7946
 
    {
7947
 
      // Get values from coefficients array
7948
 
      new_coeff0_0 = coefficients0[dof][0];
7949
 
    
7950
 
      // Loop derivative order
7951
 
      for (unsigned int j = 0; j < n; j++)
7952
 
      {
7953
 
        // Update old coefficients
7954
 
        coeff0_0 = new_coeff0_0;
7955
 
    
7956
 
        if(combinations[deriv_num][j] == 0)
7957
 
        {
7958
 
          new_coeff0_0 = coeff0_0*dmats0[0][0];
7959
 
        }
7960
 
        if(combinations[deriv_num][j] == 1)
7961
 
        {
7962
 
          new_coeff0_0 = coeff0_0*dmats1[0][0];
7963
 
        }
7964
 
        if(combinations[deriv_num][j] == 2)
7965
 
        {
7966
 
          new_coeff0_0 = coeff0_0*dmats2[0][0];
7967
 
        }
7968
 
    
7969
 
      }
7970
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
7971
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0;
7972
 
    }
7973
 
    
7974
 
    // Transform derivatives back to physical element
7975
 
    for (unsigned int row = 0; row < num_derivatives; row++)
7976
 
    {
7977
 
      for (unsigned int col = 0; col < num_derivatives; col++)
7978
 
      {
7979
 
        values[row] += transform[row][col]*derivatives[col];
7980
 
      }
7981
 
    }
7982
 
    // Delete pointer to array of derivatives on FIAT element
7983
 
    delete [] derivatives;
7984
 
    
7985
 
    // Delete pointer to array of combinations of derivatives and transform
7986
 
    for (unsigned int row = 0; row < num_derivatives; row++)
7987
 
    {
7988
 
      delete [] combinations[row];
7989
 
      delete [] transform[row];
7990
 
    }
7991
 
    
7992
 
    delete [] combinations;
7993
 
    delete [] transform;
7994
 
  }
7995
 
 
7996
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
7997
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
7998
 
                                              double* values,
7999
 
                                              const double* coordinates,
8000
 
                                              const ufc::cell& c) const
8001
 
  {
8002
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
8003
 
  }
8004
 
 
8005
 
  /// Evaluate linear functional for dof i on the function f
8006
 
  virtual double evaluate_dof(unsigned int i,
8007
 
                              const ufc::function& f,
8008
 
                              const ufc::cell& c) const
8009
 
  {
8010
 
    // The reference points, direction and weights:
8011
 
    static const double X[1][1][3] = {{{0.25, 0.25, 0.25}}};
8012
 
    static const double W[1][1] = {{1}};
8013
 
    static const double D[1][1][1] = {{{1}}};
8014
 
    
8015
 
    const double * const * x = c.coordinates;
8016
 
    double result = 0.0;
8017
 
    // Iterate over the points:
8018
 
    // Evaluate basis functions for affine mapping
8019
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
8020
 
    const double w1 = X[i][0][0];
8021
 
    const double w2 = X[i][0][1];
8022
 
    const double w3 = X[i][0][2];
8023
 
    
8024
 
    // Compute affine mapping y = F(X)
8025
 
    double y[3];
8026
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
8027
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
8028
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
8029
 
    
8030
 
    // Evaluate function at physical points
8031
 
    double values[1];
8032
 
    f.evaluate(values, y, c);
8033
 
    
8034
 
    // Map function values using appropriate mapping
8035
 
    // Affine map: Do nothing
8036
 
    
8037
 
    // Note that we do not map the weights (yet).
8038
 
    
8039
 
    // Take directional components
8040
 
    for(int k = 0; k < 1; k++)
8041
 
      result += values[k]*D[i][0][k];
8042
 
    // Multiply by weights
8043
 
    result *= W[i][0];
8044
 
    
8045
 
    return result;
8046
 
  }
8047
 
 
8048
 
  /// Evaluate linear functionals for all dofs on the function f
8049
 
  virtual void evaluate_dofs(double* values,
8050
 
                             const ufc::function& f,
8051
 
                             const ufc::cell& c) const
8052
 
  {
8053
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8054
 
  }
8055
 
 
8056
 
  /// Interpolate vertex values from dof values
8057
 
  virtual void interpolate_vertex_values(double* vertex_values,
8058
 
                                         const double* dof_values,
8059
 
                                         const ufc::cell& c) const
8060
 
  {
8061
 
    // Evaluate at vertices and use affine mapping
8062
 
    vertex_values[0] = dof_values[0];
8063
 
    vertex_values[1] = dof_values[0];
8064
 
    vertex_values[2] = dof_values[0];
8065
 
    vertex_values[3] = dof_values[0];
8066
 
  }
8067
 
 
8068
 
  /// Return the number of sub elements (for a mixed element)
8069
 
  virtual unsigned int num_sub_elements() const
8070
 
  {
8071
 
    return 1;
8072
 
  }
8073
 
 
8074
 
  /// Create a new finite element for sub element i (for a mixed element)
8075
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
8076
 
  {
8077
 
    return new hyperelasticity_0_finite_element_3();
8078
 
  }
8079
 
 
8080
 
};
8081
 
 
8082
 
/// This class defines the interface for a finite element.
8083
 
 
8084
 
class hyperelasticity_0_finite_element_4: public ufc::finite_element
8085
 
{
8086
 
public:
8087
 
 
8088
 
  /// Constructor
8089
 
  hyperelasticity_0_finite_element_4() : ufc::finite_element()
8090
 
  {
8091
 
    // Do nothing
8092
 
  }
8093
 
 
8094
 
  /// Destructor
8095
 
  virtual ~hyperelasticity_0_finite_element_4()
8096
 
  {
8097
 
    // Do nothing
8098
 
  }
8099
 
 
8100
 
  /// Return a string identifying the finite element
8101
 
  virtual const char* signature() const
8102
 
  {
8103
 
    return "FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
8104
 
  }
8105
 
 
8106
 
  /// Return the cell shape
8107
 
  virtual ufc::shape cell_shape() const
8108
 
  {
8109
 
    return ufc::tetrahedron;
8110
 
  }
8111
 
 
8112
 
  /// Return the dimension of the finite element function space
8113
 
  virtual unsigned int space_dimension() const
8114
 
  {
8115
 
    return 1;
8116
 
  }
8117
 
 
8118
 
  /// Return the rank of the value space
8119
 
  virtual unsigned int value_rank() const
8120
 
  {
8121
 
    return 0;
8122
 
  }
8123
 
 
8124
 
  /// Return the dimension of the value space for axis i
8125
 
  virtual unsigned int value_dimension(unsigned int i) const
8126
 
  {
8127
 
    return 1;
8128
 
  }
8129
 
 
8130
 
  /// Evaluate basis function i at given point in cell
8131
 
  virtual void evaluate_basis(unsigned int i,
8132
 
                              double* values,
8133
 
                              const double* coordinates,
8134
 
                              const ufc::cell& c) const
8135
 
  {
8136
 
    // Extract vertex coordinates
8137
 
    const double * const * element_coordinates = c.coordinates;
8138
 
    
8139
 
    // Compute Jacobian of affine map from reference cell
8140
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
8141
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
8142
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
8143
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
8144
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
8145
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
8146
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
8147
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
8148
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
8149
 
    
8150
 
    // Compute sub determinants
8151
 
    const double d00 = J_11*J_22 - J_12*J_21;
8152
 
    const double d01 = J_12*J_20 - J_10*J_22;
8153
 
    const double d02 = J_10*J_21 - J_11*J_20;
8154
 
    
8155
 
    const double d10 = J_02*J_21 - J_01*J_22;
8156
 
    const double d11 = J_00*J_22 - J_02*J_20;
8157
 
    const double d12 = J_01*J_20 - J_00*J_21;
8158
 
    
8159
 
    const double d20 = J_01*J_12 - J_02*J_11;
8160
 
    const double d21 = J_02*J_10 - J_00*J_12;
8161
 
    const double d22 = J_00*J_11 - J_01*J_10;
8162
 
    
8163
 
    // Compute determinant of Jacobian
8164
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
8165
 
    
8166
 
    // Compute inverse of Jacobian
8167
 
    
8168
 
    // Compute constants
8169
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
8170
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
8171
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
8172
 
    
8173
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
8174
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
8175
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
8176
 
    
8177
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
8178
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
8179
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
8180
 
    
8181
 
    // Get coordinates and map to the UFC reference element
8182
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
8183
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
8184
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
8185
 
    
8186
 
    // Map coordinates to the reference cube
8187
 
    if (std::abs(y + z - 1.0) < 1e-08)
8188
 
      x = 1.0;
8189
 
    else
8190
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
8191
 
    if (std::abs(z - 1.0) < 1e-08)
8192
 
      y = -1.0;
8193
 
    else
8194
 
      y = 2.0 * y/(1.0 - z) - 1.0;
8195
 
    z = 2.0 * z - 1.0;
8196
 
    
8197
 
    // Reset values
8198
 
    *values = 0;
8199
 
    
8200
 
    // Map degree of freedom to element degree of freedom
8201
 
    const unsigned int dof = i;
8202
 
    
8203
 
    // Generate scalings
8204
 
    const double scalings_y_0 = 1;
8205
 
    const double scalings_z_0 = 1;
8206
 
    
8207
 
    // Compute psitilde_a
8208
 
    const double psitilde_a_0 = 1;
8209
 
    
8210
 
    // Compute psitilde_bs
8211
 
    const double psitilde_bs_0_0 = 1;
8212
 
    
8213
 
    // Compute psitilde_cs
8214
 
    const double psitilde_cs_00_0 = 1;
8215
 
    
8216
 
    // Compute basisvalues
8217
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
8218
 
    
8219
 
    // Table(s) of coefficients
8220
 
    static const double coefficients0[1][1] = \
8221
 
    {{1.15470054}};
8222
 
    
8223
 
    // Extract relevant coefficients
8224
 
    const double coeff0_0 = coefficients0[dof][0];
8225
 
    
8226
 
    // Compute value(s)
8227
 
    *values = coeff0_0*basisvalue0;
8228
 
  }
8229
 
 
8230
 
  /// Evaluate all basis functions at given point in cell
8231
 
  virtual void evaluate_basis_all(double* values,
8232
 
                                  const double* coordinates,
8233
 
                                  const ufc::cell& c) const
8234
 
  {
8235
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
8236
 
  }
8237
 
 
8238
 
  /// Evaluate order n derivatives of basis function i at given point in cell
8239
 
  virtual void evaluate_basis_derivatives(unsigned int i,
8240
 
                                          unsigned int n,
8241
 
                                          double* values,
8242
 
                                          const double* coordinates,
8243
 
                                          const ufc::cell& c) const
8244
 
  {
8245
 
    // Extract vertex coordinates
8246
 
    const double * const * element_coordinates = c.coordinates;
8247
 
    
8248
 
    // Compute Jacobian of affine map from reference cell
8249
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
8250
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
8251
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
8252
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
8253
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
8254
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
8255
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
8256
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
8257
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
8258
 
    
8259
 
    // Compute sub determinants
8260
 
    const double d00 = J_11*J_22 - J_12*J_21;
8261
 
    const double d01 = J_12*J_20 - J_10*J_22;
8262
 
    const double d02 = J_10*J_21 - J_11*J_20;
8263
 
    
8264
 
    const double d10 = J_02*J_21 - J_01*J_22;
8265
 
    const double d11 = J_00*J_22 - J_02*J_20;
8266
 
    const double d12 = J_01*J_20 - J_00*J_21;
8267
 
    
8268
 
    const double d20 = J_01*J_12 - J_02*J_11;
8269
 
    const double d21 = J_02*J_10 - J_00*J_12;
8270
 
    const double d22 = J_00*J_11 - J_01*J_10;
8271
 
    
8272
 
    // Compute determinant of Jacobian
8273
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
8274
 
    
8275
 
    // Compute inverse of Jacobian
8276
 
    
8277
 
    // Compute constants
8278
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
8279
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
8280
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
8281
 
    
8282
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
8283
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
8284
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
8285
 
    
8286
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
8287
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
8288
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
8289
 
    
8290
 
    // Get coordinates and map to the UFC reference element
8291
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
8292
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
8293
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
8294
 
    
8295
 
    // Map coordinates to the reference cube
8296
 
    if (std::abs(y + z - 1.0) < 1e-08)
8297
 
      x = 1.0;
8298
 
    else
8299
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
8300
 
    if (std::abs(z - 1.0) < 1e-08)
8301
 
      y = -1.0;
8302
 
    else
8303
 
      y = 2.0 * y/(1.0 - z) - 1.0;
8304
 
    z = 2.0 * z - 1.0;
8305
 
    
8306
 
    // Compute number of derivatives
8307
 
    unsigned int num_derivatives = 1;
8308
 
    
8309
 
    for (unsigned int j = 0; j < n; j++)
8310
 
      num_derivatives *= 3;
8311
 
    
8312
 
    
8313
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
8314
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
8315
 
    
8316
 
    for (unsigned int j = 0; j < num_derivatives; j++)
8317
 
    {
8318
 
      combinations[j] = new unsigned int [n];
8319
 
      for (unsigned int k = 0; k < n; k++)
8320
 
        combinations[j][k] = 0;
8321
 
    }
8322
 
    
8323
 
    // Generate combinations of derivatives
8324
 
    for (unsigned int row = 1; row < num_derivatives; row++)
8325
 
    {
8326
 
      for (unsigned int num = 0; num < row; num++)
8327
 
      {
8328
 
        for (unsigned int col = n-1; col+1 > 0; col--)
8329
 
        {
8330
 
          if (combinations[row][col] + 1 > 2)
8331
 
            combinations[row][col] = 0;
8332
 
          else
8333
 
          {
8334
 
            combinations[row][col] += 1;
8335
 
            break;
8336
 
          }
8337
 
        }
8338
 
      }
8339
 
    }
8340
 
    
8341
 
    // Compute inverse of Jacobian
8342
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
8343
 
    
8344
 
    // Declare transformation matrix
8345
 
    // Declare pointer to two dimensional array and initialise
8346
 
    double **transform = new double *[num_derivatives];
8347
 
    
8348
 
    for (unsigned int j = 0; j < num_derivatives; j++)
8349
 
    {
8350
 
      transform[j] = new double [num_derivatives];
8351
 
      for (unsigned int k = 0; k < num_derivatives; k++)
8352
 
        transform[j][k] = 1;
8353
 
    }
8354
 
    
8355
 
    // Construct transformation matrix
8356
 
    for (unsigned int row = 0; row < num_derivatives; row++)
8357
 
    {
8358
 
      for (unsigned int col = 0; col < num_derivatives; col++)
8359
 
      {
8360
 
        for (unsigned int k = 0; k < n; k++)
8361
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
8362
 
      }
8363
 
    }
8364
 
    
8365
 
    // Reset values
8366
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
8367
 
      values[j] = 0;
8368
 
    
8369
 
    // Map degree of freedom to element degree of freedom
8370
 
    const unsigned int dof = i;
8371
 
    
8372
 
    // Generate scalings
8373
 
    const double scalings_y_0 = 1;
8374
 
    const double scalings_z_0 = 1;
8375
 
    
8376
 
    // Compute psitilde_a
8377
 
    const double psitilde_a_0 = 1;
8378
 
    
8379
 
    // Compute psitilde_bs
8380
 
    const double psitilde_bs_0_0 = 1;
8381
 
    
8382
 
    // Compute psitilde_cs
8383
 
    const double psitilde_cs_00_0 = 1;
8384
 
    
8385
 
    // Compute basisvalues
8386
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
8387
 
    
8388
 
    // Table(s) of coefficients
8389
 
    static const double coefficients0[1][1] = \
8390
 
    {{1.15470054}};
8391
 
    
8392
 
    // Interesting (new) part
8393
 
    // Tables of derivatives of the polynomial base (transpose)
8394
 
    static const double dmats0[1][1] = \
8395
 
    {{0}};
8396
 
    
8397
 
    static const double dmats1[1][1] = \
8398
 
    {{0}};
8399
 
    
8400
 
    static const double dmats2[1][1] = \
8401
 
    {{0}};
8402
 
    
8403
 
    // Compute reference derivatives
8404
 
    // Declare pointer to array of derivatives on FIAT element
8405
 
    double *derivatives = new double [num_derivatives];
8406
 
    
8407
 
    // Declare coefficients
8408
 
    double coeff0_0 = 0;
8409
 
    
8410
 
    // Declare new coefficients
8411
 
    double new_coeff0_0 = 0;
8412
 
    
8413
 
    // Loop possible derivatives
8414
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
8415
 
    {
8416
 
      // Get values from coefficients array
8417
 
      new_coeff0_0 = coefficients0[dof][0];
8418
 
    
8419
 
      // Loop derivative order
8420
 
      for (unsigned int j = 0; j < n; j++)
8421
 
      {
8422
 
        // Update old coefficients
8423
 
        coeff0_0 = new_coeff0_0;
8424
 
    
8425
 
        if(combinations[deriv_num][j] == 0)
8426
 
        {
8427
 
          new_coeff0_0 = coeff0_0*dmats0[0][0];
8428
 
        }
8429
 
        if(combinations[deriv_num][j] == 1)
8430
 
        {
8431
 
          new_coeff0_0 = coeff0_0*dmats1[0][0];
8432
 
        }
8433
 
        if(combinations[deriv_num][j] == 2)
8434
 
        {
8435
 
          new_coeff0_0 = coeff0_0*dmats2[0][0];
8436
 
        }
8437
 
    
8438
 
      }
8439
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
8440
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0;
8441
 
    }
8442
 
    
8443
 
    // Transform derivatives back to physical element
8444
 
    for (unsigned int row = 0; row < num_derivatives; row++)
8445
 
    {
8446
 
      for (unsigned int col = 0; col < num_derivatives; col++)
8447
 
      {
8448
 
        values[row] += transform[row][col]*derivatives[col];
8449
 
      }
8450
 
    }
8451
 
    // Delete pointer to array of derivatives on FIAT element
8452
 
    delete [] derivatives;
8453
 
    
8454
 
    // Delete pointer to array of combinations of derivatives and transform
8455
 
    for (unsigned int row = 0; row < num_derivatives; row++)
8456
 
    {
8457
 
      delete [] combinations[row];
8458
 
      delete [] transform[row];
8459
 
    }
8460
 
    
8461
 
    delete [] combinations;
8462
 
    delete [] transform;
8463
 
  }
8464
 
 
8465
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
8466
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
8467
 
                                              double* values,
8468
 
                                              const double* coordinates,
8469
 
                                              const ufc::cell& c) const
8470
 
  {
8471
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
8472
 
  }
8473
 
 
8474
 
  /// Evaluate linear functional for dof i on the function f
8475
 
  virtual double evaluate_dof(unsigned int i,
8476
 
                              const ufc::function& f,
8477
 
                              const ufc::cell& c) const
8478
 
  {
8479
 
    // The reference points, direction and weights:
8480
 
    static const double X[1][1][3] = {{{0.25, 0.25, 0.25}}};
8481
 
    static const double W[1][1] = {{1}};
8482
 
    static const double D[1][1][1] = {{{1}}};
8483
 
    
8484
 
    const double * const * x = c.coordinates;
8485
 
    double result = 0.0;
8486
 
    // Iterate over the points:
8487
 
    // Evaluate basis functions for affine mapping
8488
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
8489
 
    const double w1 = X[i][0][0];
8490
 
    const double w2 = X[i][0][1];
8491
 
    const double w3 = X[i][0][2];
8492
 
    
8493
 
    // Compute affine mapping y = F(X)
8494
 
    double y[3];
8495
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
8496
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
8497
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
8498
 
    
8499
 
    // Evaluate function at physical points
8500
 
    double values[1];
8501
 
    f.evaluate(values, y, c);
8502
 
    
8503
 
    // Map function values using appropriate mapping
8504
 
    // Affine map: Do nothing
8505
 
    
8506
 
    // Note that we do not map the weights (yet).
8507
 
    
8508
 
    // Take directional components
8509
 
    for(int k = 0; k < 1; k++)
8510
 
      result += values[k]*D[i][0][k];
8511
 
    // Multiply by weights
8512
 
    result *= W[i][0];
8513
 
    
8514
 
    return result;
8515
 
  }
8516
 
 
8517
 
  /// Evaluate linear functionals for all dofs on the function f
8518
 
  virtual void evaluate_dofs(double* values,
8519
 
                             const ufc::function& f,
8520
 
                             const ufc::cell& c) const
8521
 
  {
8522
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8523
 
  }
8524
 
 
8525
 
  /// Interpolate vertex values from dof values
8526
 
  virtual void interpolate_vertex_values(double* vertex_values,
8527
 
                                         const double* dof_values,
8528
 
                                         const ufc::cell& c) const
8529
 
  {
8530
 
    // Evaluate at vertices and use affine mapping
8531
 
    vertex_values[0] = dof_values[0];
8532
 
    vertex_values[1] = dof_values[0];
8533
 
    vertex_values[2] = dof_values[0];
8534
 
    vertex_values[3] = dof_values[0];
8535
 
  }
8536
 
 
8537
 
  /// Return the number of sub elements (for a mixed element)
8538
 
  virtual unsigned int num_sub_elements() const
8539
 
  {
8540
 
    return 1;
8541
 
  }
8542
 
 
8543
 
  /// Create a new finite element for sub element i (for a mixed element)
8544
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
8545
 
  {
8546
 
    return new hyperelasticity_0_finite_element_4();
8547
 
  }
8548
 
 
8549
 
};
8550
 
 
8551
 
/// This class defines the interface for a local-to-global mapping of
8552
 
/// degrees of freedom (dofs).
8553
 
 
8554
 
class hyperelasticity_0_dof_map_0_0: public ufc::dof_map
8555
 
{
8556
 
private:
8557
 
 
8558
 
  unsigned int __global_dimension;
8559
 
 
8560
 
public:
8561
 
 
8562
 
  /// Constructor
8563
 
  hyperelasticity_0_dof_map_0_0() : ufc::dof_map()
8564
 
  {
8565
 
    __global_dimension = 0;
8566
 
  }
8567
 
 
8568
 
  /// Destructor
8569
 
  virtual ~hyperelasticity_0_dof_map_0_0()
8570
 
  {
8571
 
    // Do nothing
8572
 
  }
8573
 
 
8574
 
  /// Return a string identifying the dof map
8575
 
  virtual const char* signature() const
8576
 
  {
8577
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
8578
 
  }
8579
 
 
8580
 
  /// Return true iff mesh entities of topological dimension d are needed
8581
 
  virtual bool needs_mesh_entities(unsigned int d) const
8582
 
  {
8583
 
    switch ( d )
8584
 
    {
8585
 
    case 0:
8586
 
      return true;
8587
 
      break;
8588
 
    case 1:
8589
 
      return false;
8590
 
      break;
8591
 
    case 2:
8592
 
      return false;
8593
 
      break;
8594
 
    case 3:
8595
 
      return false;
8596
 
      break;
8597
 
    }
8598
 
    return false;
8599
 
  }
8600
 
 
8601
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
8602
 
  virtual bool init_mesh(const ufc::mesh& m)
8603
 
  {
8604
 
    __global_dimension = m.num_entities[0];
8605
 
    return false;
8606
 
  }
8607
 
 
8608
 
  /// Initialize dof map for given cell
8609
 
  virtual void init_cell(const ufc::mesh& m,
8610
 
                         const ufc::cell& c)
8611
 
  {
8612
 
    // Do nothing
8613
 
  }
8614
 
 
8615
 
  /// Finish initialization of dof map for cells
8616
 
  virtual void init_cell_finalize()
8617
 
  {
8618
 
    // Do nothing
8619
 
  }
8620
 
 
8621
 
  /// Return the dimension of the global finite element function space
8622
 
  virtual unsigned int global_dimension() const
8623
 
  {
8624
 
    return __global_dimension;
8625
 
  }
8626
 
 
8627
 
  /// Return the dimension of the local finite element function space for a cell
8628
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
8629
 
  {
8630
 
    return 4;
8631
 
  }
8632
 
 
8633
 
  /// Return the maximum dimension of the local finite element function space
8634
 
  virtual unsigned int max_local_dimension() const
8635
 
  {
8636
 
    return 4;
8637
 
  }
8638
 
 
8639
 
  // Return the geometric dimension of the coordinates this dof map provides
8640
 
  virtual unsigned int geometric_dimension() const
8641
 
  {
8642
 
    return 3;
8643
 
  }
8644
 
 
8645
 
  /// Return the number of dofs on each cell facet
8646
 
  virtual unsigned int num_facet_dofs() const
8647
 
  {
8648
 
    return 3;
8649
 
  }
8650
 
 
8651
 
  /// Return the number of dofs associated with each cell entity of dimension d
8652
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
8653
 
  {
8654
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8655
 
  }
8656
 
 
8657
 
  /// Tabulate the local-to-global mapping of dofs on a cell
8658
 
  virtual void tabulate_dofs(unsigned int* dofs,
8659
 
                             const ufc::mesh& m,
8660
 
                             const ufc::cell& c) const
8661
 
  {
8662
 
    dofs[0] = c.entity_indices[0][0];
8663
 
    dofs[1] = c.entity_indices[0][1];
8664
 
    dofs[2] = c.entity_indices[0][2];
8665
 
    dofs[3] = c.entity_indices[0][3];
8666
 
  }
8667
 
 
8668
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
8669
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
8670
 
                                   unsigned int facet) const
8671
 
  {
8672
 
    switch ( facet )
8673
 
    {
8674
 
    case 0:
8675
 
      dofs[0] = 1;
8676
 
      dofs[1] = 2;
8677
 
      dofs[2] = 3;
8678
 
      break;
8679
 
    case 1:
8680
 
      dofs[0] = 0;
8681
 
      dofs[1] = 2;
8682
 
      dofs[2] = 3;
8683
 
      break;
8684
 
    case 2:
8685
 
      dofs[0] = 0;
8686
 
      dofs[1] = 1;
8687
 
      dofs[2] = 3;
8688
 
      break;
8689
 
    case 3:
8690
 
      dofs[0] = 0;
8691
 
      dofs[1] = 1;
8692
 
      dofs[2] = 2;
8693
 
      break;
8694
 
    }
8695
 
  }
8696
 
 
8697
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
8698
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
8699
 
                                    unsigned int d, unsigned int i) const
8700
 
  {
8701
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8702
 
  }
8703
 
 
8704
 
  /// Tabulate the coordinates of all dofs on a cell
8705
 
  virtual void tabulate_coordinates(double** coordinates,
8706
 
                                    const ufc::cell& c) const
8707
 
  {
8708
 
    const double * const * x = c.coordinates;
8709
 
    coordinates[0][0] = x[0][0];
8710
 
    coordinates[0][1] = x[0][1];
8711
 
    coordinates[0][2] = x[0][2];
8712
 
    coordinates[1][0] = x[1][0];
8713
 
    coordinates[1][1] = x[1][1];
8714
 
    coordinates[1][2] = x[1][2];
8715
 
    coordinates[2][0] = x[2][0];
8716
 
    coordinates[2][1] = x[2][1];
8717
 
    coordinates[2][2] = x[2][2];
8718
 
    coordinates[3][0] = x[3][0];
8719
 
    coordinates[3][1] = x[3][1];
8720
 
    coordinates[3][2] = x[3][2];
8721
 
  }
8722
 
 
8723
 
  /// Return the number of sub dof maps (for a mixed element)
8724
 
  virtual unsigned int num_sub_dof_maps() const
8725
 
  {
8726
 
    return 1;
8727
 
  }
8728
 
 
8729
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
8730
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
8731
 
  {
8732
 
    return new hyperelasticity_0_dof_map_0_0();
8733
 
  }
8734
 
 
8735
 
};
8736
 
 
8737
 
/// This class defines the interface for a local-to-global mapping of
8738
 
/// degrees of freedom (dofs).
8739
 
 
8740
 
class hyperelasticity_0_dof_map_0_1: public ufc::dof_map
8741
 
{
8742
 
private:
8743
 
 
8744
 
  unsigned int __global_dimension;
8745
 
 
8746
 
public:
8747
 
 
8748
 
  /// Constructor
8749
 
  hyperelasticity_0_dof_map_0_1() : ufc::dof_map()
8750
 
  {
8751
 
    __global_dimension = 0;
8752
 
  }
8753
 
 
8754
 
  /// Destructor
8755
 
  virtual ~hyperelasticity_0_dof_map_0_1()
8756
 
  {
8757
 
    // Do nothing
8758
 
  }
8759
 
 
8760
 
  /// Return a string identifying the dof map
8761
 
  virtual const char* signature() const
8762
 
  {
8763
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
8764
 
  }
8765
 
 
8766
 
  /// Return true iff mesh entities of topological dimension d are needed
8767
 
  virtual bool needs_mesh_entities(unsigned int d) const
8768
 
  {
8769
 
    switch ( d )
8770
 
    {
8771
 
    case 0:
8772
 
      return true;
8773
 
      break;
8774
 
    case 1:
8775
 
      return false;
8776
 
      break;
8777
 
    case 2:
8778
 
      return false;
8779
 
      break;
8780
 
    case 3:
8781
 
      return false;
8782
 
      break;
8783
 
    }
8784
 
    return false;
8785
 
  }
8786
 
 
8787
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
8788
 
  virtual bool init_mesh(const ufc::mesh& m)
8789
 
  {
8790
 
    __global_dimension = m.num_entities[0];
8791
 
    return false;
8792
 
  }
8793
 
 
8794
 
  /// Initialize dof map for given cell
8795
 
  virtual void init_cell(const ufc::mesh& m,
8796
 
                         const ufc::cell& c)
8797
 
  {
8798
 
    // Do nothing
8799
 
  }
8800
 
 
8801
 
  /// Finish initialization of dof map for cells
8802
 
  virtual void init_cell_finalize()
8803
 
  {
8804
 
    // Do nothing
8805
 
  }
8806
 
 
8807
 
  /// Return the dimension of the global finite element function space
8808
 
  virtual unsigned int global_dimension() const
8809
 
  {
8810
 
    return __global_dimension;
8811
 
  }
8812
 
 
8813
 
  /// Return the dimension of the local finite element function space for a cell
8814
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
8815
 
  {
8816
 
    return 4;
8817
 
  }
8818
 
 
8819
 
  /// Return the maximum dimension of the local finite element function space
8820
 
  virtual unsigned int max_local_dimension() const
8821
 
  {
8822
 
    return 4;
8823
 
  }
8824
 
 
8825
 
  // Return the geometric dimension of the coordinates this dof map provides
8826
 
  virtual unsigned int geometric_dimension() const
8827
 
  {
8828
 
    return 3;
8829
 
  }
8830
 
 
8831
 
  /// Return the number of dofs on each cell facet
8832
 
  virtual unsigned int num_facet_dofs() const
8833
 
  {
8834
 
    return 3;
8835
 
  }
8836
 
 
8837
 
  /// Return the number of dofs associated with each cell entity of dimension d
8838
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
8839
 
  {
8840
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8841
 
  }
8842
 
 
8843
 
  /// Tabulate the local-to-global mapping of dofs on a cell
8844
 
  virtual void tabulate_dofs(unsigned int* dofs,
8845
 
                             const ufc::mesh& m,
8846
 
                             const ufc::cell& c) const
8847
 
  {
8848
 
    dofs[0] = c.entity_indices[0][0];
8849
 
    dofs[1] = c.entity_indices[0][1];
8850
 
    dofs[2] = c.entity_indices[0][2];
8851
 
    dofs[3] = c.entity_indices[0][3];
8852
 
  }
8853
 
 
8854
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
8855
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
8856
 
                                   unsigned int facet) const
8857
 
  {
8858
 
    switch ( facet )
8859
 
    {
8860
 
    case 0:
8861
 
      dofs[0] = 1;
8862
 
      dofs[1] = 2;
8863
 
      dofs[2] = 3;
8864
 
      break;
8865
 
    case 1:
8866
 
      dofs[0] = 0;
8867
 
      dofs[1] = 2;
8868
 
      dofs[2] = 3;
8869
 
      break;
8870
 
    case 2:
8871
 
      dofs[0] = 0;
8872
 
      dofs[1] = 1;
8873
 
      dofs[2] = 3;
8874
 
      break;
8875
 
    case 3:
8876
 
      dofs[0] = 0;
8877
 
      dofs[1] = 1;
8878
 
      dofs[2] = 2;
8879
 
      break;
8880
 
    }
8881
 
  }
8882
 
 
8883
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
8884
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
8885
 
                                    unsigned int d, unsigned int i) const
8886
 
  {
8887
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
8888
 
  }
8889
 
 
8890
 
  /// Tabulate the coordinates of all dofs on a cell
8891
 
  virtual void tabulate_coordinates(double** coordinates,
8892
 
                                    const ufc::cell& c) const
8893
 
  {
8894
 
    const double * const * x = c.coordinates;
8895
 
    coordinates[0][0] = x[0][0];
8896
 
    coordinates[0][1] = x[0][1];
8897
 
    coordinates[0][2] = x[0][2];
8898
 
    coordinates[1][0] = x[1][0];
8899
 
    coordinates[1][1] = x[1][1];
8900
 
    coordinates[1][2] = x[1][2];
8901
 
    coordinates[2][0] = x[2][0];
8902
 
    coordinates[2][1] = x[2][1];
8903
 
    coordinates[2][2] = x[2][2];
8904
 
    coordinates[3][0] = x[3][0];
8905
 
    coordinates[3][1] = x[3][1];
8906
 
    coordinates[3][2] = x[3][2];
8907
 
  }
8908
 
 
8909
 
  /// Return the number of sub dof maps (for a mixed element)
8910
 
  virtual unsigned int num_sub_dof_maps() const
8911
 
  {
8912
 
    return 1;
8913
 
  }
8914
 
 
8915
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
8916
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
8917
 
  {
8918
 
    return new hyperelasticity_0_dof_map_0_1();
8919
 
  }
8920
 
 
8921
 
};
8922
 
 
8923
 
/// This class defines the interface for a local-to-global mapping of
8924
 
/// degrees of freedom (dofs).
8925
 
 
8926
 
class hyperelasticity_0_dof_map_0_2: public ufc::dof_map
8927
 
{
8928
 
private:
8929
 
 
8930
 
  unsigned int __global_dimension;
8931
 
 
8932
 
public:
8933
 
 
8934
 
  /// Constructor
8935
 
  hyperelasticity_0_dof_map_0_2() : ufc::dof_map()
8936
 
  {
8937
 
    __global_dimension = 0;
8938
 
  }
8939
 
 
8940
 
  /// Destructor
8941
 
  virtual ~hyperelasticity_0_dof_map_0_2()
8942
 
  {
8943
 
    // Do nothing
8944
 
  }
8945
 
 
8946
 
  /// Return a string identifying the dof map
8947
 
  virtual const char* signature() const
8948
 
  {
8949
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
8950
 
  }
8951
 
 
8952
 
  /// Return true iff mesh entities of topological dimension d are needed
8953
 
  virtual bool needs_mesh_entities(unsigned int d) const
8954
 
  {
8955
 
    switch ( d )
8956
 
    {
8957
 
    case 0:
8958
 
      return true;
8959
 
      break;
8960
 
    case 1:
8961
 
      return false;
8962
 
      break;
8963
 
    case 2:
8964
 
      return false;
8965
 
      break;
8966
 
    case 3:
8967
 
      return false;
8968
 
      break;
8969
 
    }
8970
 
    return false;
8971
 
  }
8972
 
 
8973
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
8974
 
  virtual bool init_mesh(const ufc::mesh& m)
8975
 
  {
8976
 
    __global_dimension = m.num_entities[0];
8977
 
    return false;
8978
 
  }
8979
 
 
8980
 
  /// Initialize dof map for given cell
8981
 
  virtual void init_cell(const ufc::mesh& m,
8982
 
                         const ufc::cell& c)
8983
 
  {
8984
 
    // Do nothing
8985
 
  }
8986
 
 
8987
 
  /// Finish initialization of dof map for cells
8988
 
  virtual void init_cell_finalize()
8989
 
  {
8990
 
    // Do nothing
8991
 
  }
8992
 
 
8993
 
  /// Return the dimension of the global finite element function space
8994
 
  virtual unsigned int global_dimension() const
8995
 
  {
8996
 
    return __global_dimension;
8997
 
  }
8998
 
 
8999
 
  /// Return the dimension of the local finite element function space for a cell
9000
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
9001
 
  {
9002
 
    return 4;
9003
 
  }
9004
 
 
9005
 
  /// Return the maximum dimension of the local finite element function space
9006
 
  virtual unsigned int max_local_dimension() const
9007
 
  {
9008
 
    return 4;
9009
 
  }
9010
 
 
9011
 
  // Return the geometric dimension of the coordinates this dof map provides
9012
 
  virtual unsigned int geometric_dimension() const
9013
 
  {
9014
 
    return 3;
9015
 
  }
9016
 
 
9017
 
  /// Return the number of dofs on each cell facet
9018
 
  virtual unsigned int num_facet_dofs() const
9019
 
  {
9020
 
    return 3;
9021
 
  }
9022
 
 
9023
 
  /// Return the number of dofs associated with each cell entity of dimension d
9024
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
9025
 
  {
9026
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9027
 
  }
9028
 
 
9029
 
  /// Tabulate the local-to-global mapping of dofs on a cell
9030
 
  virtual void tabulate_dofs(unsigned int* dofs,
9031
 
                             const ufc::mesh& m,
9032
 
                             const ufc::cell& c) const
9033
 
  {
9034
 
    dofs[0] = c.entity_indices[0][0];
9035
 
    dofs[1] = c.entity_indices[0][1];
9036
 
    dofs[2] = c.entity_indices[0][2];
9037
 
    dofs[3] = c.entity_indices[0][3];
9038
 
  }
9039
 
 
9040
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
9041
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
9042
 
                                   unsigned int facet) const
9043
 
  {
9044
 
    switch ( facet )
9045
 
    {
9046
 
    case 0:
9047
 
      dofs[0] = 1;
9048
 
      dofs[1] = 2;
9049
 
      dofs[2] = 3;
9050
 
      break;
9051
 
    case 1:
9052
 
      dofs[0] = 0;
9053
 
      dofs[1] = 2;
9054
 
      dofs[2] = 3;
9055
 
      break;
9056
 
    case 2:
9057
 
      dofs[0] = 0;
9058
 
      dofs[1] = 1;
9059
 
      dofs[2] = 3;
9060
 
      break;
9061
 
    case 3:
9062
 
      dofs[0] = 0;
9063
 
      dofs[1] = 1;
9064
 
      dofs[2] = 2;
9065
 
      break;
9066
 
    }
9067
 
  }
9068
 
 
9069
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
9070
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
9071
 
                                    unsigned int d, unsigned int i) const
9072
 
  {
9073
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9074
 
  }
9075
 
 
9076
 
  /// Tabulate the coordinates of all dofs on a cell
9077
 
  virtual void tabulate_coordinates(double** coordinates,
9078
 
                                    const ufc::cell& c) const
9079
 
  {
9080
 
    const double * const * x = c.coordinates;
9081
 
    coordinates[0][0] = x[0][0];
9082
 
    coordinates[0][1] = x[0][1];
9083
 
    coordinates[0][2] = x[0][2];
9084
 
    coordinates[1][0] = x[1][0];
9085
 
    coordinates[1][1] = x[1][1];
9086
 
    coordinates[1][2] = x[1][2];
9087
 
    coordinates[2][0] = x[2][0];
9088
 
    coordinates[2][1] = x[2][1];
9089
 
    coordinates[2][2] = x[2][2];
9090
 
    coordinates[3][0] = x[3][0];
9091
 
    coordinates[3][1] = x[3][1];
9092
 
    coordinates[3][2] = x[3][2];
9093
 
  }
9094
 
 
9095
 
  /// Return the number of sub dof maps (for a mixed element)
9096
 
  virtual unsigned int num_sub_dof_maps() const
9097
 
  {
9098
 
    return 1;
9099
 
  }
9100
 
 
9101
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
9102
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
9103
 
  {
9104
 
    return new hyperelasticity_0_dof_map_0_2();
9105
 
  }
9106
 
 
9107
 
};
9108
 
 
9109
 
/// This class defines the interface for a local-to-global mapping of
9110
 
/// degrees of freedom (dofs).
9111
 
 
9112
 
class hyperelasticity_0_dof_map_0: public ufc::dof_map
9113
 
{
9114
 
private:
9115
 
 
9116
 
  unsigned int __global_dimension;
9117
 
 
9118
 
public:
9119
 
 
9120
 
  /// Constructor
9121
 
  hyperelasticity_0_dof_map_0() : ufc::dof_map()
9122
 
  {
9123
 
    __global_dimension = 0;
9124
 
  }
9125
 
 
9126
 
  /// Destructor
9127
 
  virtual ~hyperelasticity_0_dof_map_0()
9128
 
  {
9129
 
    // Do nothing
9130
 
  }
9131
 
 
9132
 
  /// Return a string identifying the dof map
9133
 
  virtual const char* signature() const
9134
 
  {
9135
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
9136
 
  }
9137
 
 
9138
 
  /// Return true iff mesh entities of topological dimension d are needed
9139
 
  virtual bool needs_mesh_entities(unsigned int d) const
9140
 
  {
9141
 
    switch ( d )
9142
 
    {
9143
 
    case 0:
9144
 
      return true;
9145
 
      break;
9146
 
    case 1:
9147
 
      return false;
9148
 
      break;
9149
 
    case 2:
9150
 
      return false;
9151
 
      break;
9152
 
    case 3:
9153
 
      return false;
9154
 
      break;
9155
 
    }
9156
 
    return false;
9157
 
  }
9158
 
 
9159
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
9160
 
  virtual bool init_mesh(const ufc::mesh& m)
9161
 
  {
9162
 
    __global_dimension = 3*m.num_entities[0];
9163
 
    return false;
9164
 
  }
9165
 
 
9166
 
  /// Initialize dof map for given cell
9167
 
  virtual void init_cell(const ufc::mesh& m,
9168
 
                         const ufc::cell& c)
9169
 
  {
9170
 
    // Do nothing
9171
 
  }
9172
 
 
9173
 
  /// Finish initialization of dof map for cells
9174
 
  virtual void init_cell_finalize()
9175
 
  {
9176
 
    // Do nothing
9177
 
  }
9178
 
 
9179
 
  /// Return the dimension of the global finite element function space
9180
 
  virtual unsigned int global_dimension() const
9181
 
  {
9182
 
    return __global_dimension;
9183
 
  }
9184
 
 
9185
 
  /// Return the dimension of the local finite element function space for a cell
9186
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
9187
 
  {
9188
 
    return 12;
9189
 
  }
9190
 
 
9191
 
  /// Return the maximum dimension of the local finite element function space
9192
 
  virtual unsigned int max_local_dimension() const
9193
 
  {
9194
 
    return 12;
9195
 
  }
9196
 
 
9197
 
  // Return the geometric dimension of the coordinates this dof map provides
9198
 
  virtual unsigned int geometric_dimension() const
9199
 
  {
9200
 
    return 3;
9201
 
  }
9202
 
 
9203
 
  /// Return the number of dofs on each cell facet
9204
 
  virtual unsigned int num_facet_dofs() const
9205
 
  {
9206
 
    return 9;
9207
 
  }
9208
 
 
9209
 
  /// Return the number of dofs associated with each cell entity of dimension d
9210
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
9211
 
  {
9212
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9213
 
  }
9214
 
 
9215
 
  /// Tabulate the local-to-global mapping of dofs on a cell
9216
 
  virtual void tabulate_dofs(unsigned int* dofs,
9217
 
                             const ufc::mesh& m,
9218
 
                             const ufc::cell& c) const
9219
 
  {
9220
 
    dofs[0] = c.entity_indices[0][0];
9221
 
    dofs[1] = c.entity_indices[0][1];
9222
 
    dofs[2] = c.entity_indices[0][2];
9223
 
    dofs[3] = c.entity_indices[0][3];
9224
 
    unsigned int offset = m.num_entities[0];
9225
 
    dofs[4] = offset + c.entity_indices[0][0];
9226
 
    dofs[5] = offset + c.entity_indices[0][1];
9227
 
    dofs[6] = offset + c.entity_indices[0][2];
9228
 
    dofs[7] = offset + c.entity_indices[0][3];
9229
 
    offset = offset + m.num_entities[0];
9230
 
    dofs[8] = offset + c.entity_indices[0][0];
9231
 
    dofs[9] = offset + c.entity_indices[0][1];
9232
 
    dofs[10] = offset + c.entity_indices[0][2];
9233
 
    dofs[11] = offset + c.entity_indices[0][3];
9234
 
  }
9235
 
 
9236
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
9237
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
9238
 
                                   unsigned int facet) const
9239
 
  {
9240
 
    switch ( facet )
9241
 
    {
9242
 
    case 0:
9243
 
      dofs[0] = 1;
9244
 
      dofs[1] = 2;
9245
 
      dofs[2] = 3;
9246
 
      dofs[3] = 5;
9247
 
      dofs[4] = 6;
9248
 
      dofs[5] = 7;
9249
 
      dofs[6] = 9;
9250
 
      dofs[7] = 10;
9251
 
      dofs[8] = 11;
9252
 
      break;
9253
 
    case 1:
9254
 
      dofs[0] = 0;
9255
 
      dofs[1] = 2;
9256
 
      dofs[2] = 3;
9257
 
      dofs[3] = 4;
9258
 
      dofs[4] = 6;
9259
 
      dofs[5] = 7;
9260
 
      dofs[6] = 8;
9261
 
      dofs[7] = 10;
9262
 
      dofs[8] = 11;
9263
 
      break;
9264
 
    case 2:
9265
 
      dofs[0] = 0;
9266
 
      dofs[1] = 1;
9267
 
      dofs[2] = 3;
9268
 
      dofs[3] = 4;
9269
 
      dofs[4] = 5;
9270
 
      dofs[5] = 7;
9271
 
      dofs[6] = 8;
9272
 
      dofs[7] = 9;
9273
 
      dofs[8] = 11;
9274
 
      break;
9275
 
    case 3:
9276
 
      dofs[0] = 0;
9277
 
      dofs[1] = 1;
9278
 
      dofs[2] = 2;
9279
 
      dofs[3] = 4;
9280
 
      dofs[4] = 5;
9281
 
      dofs[5] = 6;
9282
 
      dofs[6] = 8;
9283
 
      dofs[7] = 9;
9284
 
      dofs[8] = 10;
9285
 
      break;
9286
 
    }
9287
 
  }
9288
 
 
9289
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
9290
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
9291
 
                                    unsigned int d, unsigned int i) const
9292
 
  {
9293
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9294
 
  }
9295
 
 
9296
 
  /// Tabulate the coordinates of all dofs on a cell
9297
 
  virtual void tabulate_coordinates(double** coordinates,
9298
 
                                    const ufc::cell& c) const
9299
 
  {
9300
 
    const double * const * x = c.coordinates;
9301
 
    coordinates[0][0] = x[0][0];
9302
 
    coordinates[0][1] = x[0][1];
9303
 
    coordinates[0][2] = x[0][2];
9304
 
    coordinates[1][0] = x[1][0];
9305
 
    coordinates[1][1] = x[1][1];
9306
 
    coordinates[1][2] = x[1][2];
9307
 
    coordinates[2][0] = x[2][0];
9308
 
    coordinates[2][1] = x[2][1];
9309
 
    coordinates[2][2] = x[2][2];
9310
 
    coordinates[3][0] = x[3][0];
9311
 
    coordinates[3][1] = x[3][1];
9312
 
    coordinates[3][2] = x[3][2];
9313
 
    coordinates[4][0] = x[0][0];
9314
 
    coordinates[4][1] = x[0][1];
9315
 
    coordinates[4][2] = x[0][2];
9316
 
    coordinates[5][0] = x[1][0];
9317
 
    coordinates[5][1] = x[1][1];
9318
 
    coordinates[5][2] = x[1][2];
9319
 
    coordinates[6][0] = x[2][0];
9320
 
    coordinates[6][1] = x[2][1];
9321
 
    coordinates[6][2] = x[2][2];
9322
 
    coordinates[7][0] = x[3][0];
9323
 
    coordinates[7][1] = x[3][1];
9324
 
    coordinates[7][2] = x[3][2];
9325
 
    coordinates[8][0] = x[0][0];
9326
 
    coordinates[8][1] = x[0][1];
9327
 
    coordinates[8][2] = x[0][2];
9328
 
    coordinates[9][0] = x[1][0];
9329
 
    coordinates[9][1] = x[1][1];
9330
 
    coordinates[9][2] = x[1][2];
9331
 
    coordinates[10][0] = x[2][0];
9332
 
    coordinates[10][1] = x[2][1];
9333
 
    coordinates[10][2] = x[2][2];
9334
 
    coordinates[11][0] = x[3][0];
9335
 
    coordinates[11][1] = x[3][1];
9336
 
    coordinates[11][2] = x[3][2];
9337
 
  }
9338
 
 
9339
 
  /// Return the number of sub dof maps (for a mixed element)
9340
 
  virtual unsigned int num_sub_dof_maps() const
9341
 
  {
9342
 
    return 3;
9343
 
  }
9344
 
 
9345
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
9346
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
9347
 
  {
9348
 
    switch ( i )
9349
 
    {
9350
 
    case 0:
9351
 
      return new hyperelasticity_0_dof_map_0_0();
9352
 
      break;
9353
 
    case 1:
9354
 
      return new hyperelasticity_0_dof_map_0_1();
9355
 
      break;
9356
 
    case 2:
9357
 
      return new hyperelasticity_0_dof_map_0_2();
9358
 
      break;
9359
 
    }
9360
 
    return 0;
9361
 
  }
9362
 
 
9363
 
};
9364
 
 
9365
 
/// This class defines the interface for a local-to-global mapping of
9366
 
/// degrees of freedom (dofs).
9367
 
 
9368
 
class hyperelasticity_0_dof_map_1_0: public ufc::dof_map
9369
 
{
9370
 
private:
9371
 
 
9372
 
  unsigned int __global_dimension;
9373
 
 
9374
 
public:
9375
 
 
9376
 
  /// Constructor
9377
 
  hyperelasticity_0_dof_map_1_0() : ufc::dof_map()
9378
 
  {
9379
 
    __global_dimension = 0;
9380
 
  }
9381
 
 
9382
 
  /// Destructor
9383
 
  virtual ~hyperelasticity_0_dof_map_1_0()
9384
 
  {
9385
 
    // Do nothing
9386
 
  }
9387
 
 
9388
 
  /// Return a string identifying the dof map
9389
 
  virtual const char* signature() const
9390
 
  {
9391
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
9392
 
  }
9393
 
 
9394
 
  /// Return true iff mesh entities of topological dimension d are needed
9395
 
  virtual bool needs_mesh_entities(unsigned int d) const
9396
 
  {
9397
 
    switch ( d )
9398
 
    {
9399
 
    case 0:
9400
 
      return true;
9401
 
      break;
9402
 
    case 1:
9403
 
      return false;
9404
 
      break;
9405
 
    case 2:
9406
 
      return false;
9407
 
      break;
9408
 
    case 3:
9409
 
      return false;
9410
 
      break;
9411
 
    }
9412
 
    return false;
9413
 
  }
9414
 
 
9415
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
9416
 
  virtual bool init_mesh(const ufc::mesh& m)
9417
 
  {
9418
 
    __global_dimension = m.num_entities[0];
9419
 
    return false;
9420
 
  }
9421
 
 
9422
 
  /// Initialize dof map for given cell
9423
 
  virtual void init_cell(const ufc::mesh& m,
9424
 
                         const ufc::cell& c)
9425
 
  {
9426
 
    // Do nothing
9427
 
  }
9428
 
 
9429
 
  /// Finish initialization of dof map for cells
9430
 
  virtual void init_cell_finalize()
9431
 
  {
9432
 
    // Do nothing
9433
 
  }
9434
 
 
9435
 
  /// Return the dimension of the global finite element function space
9436
 
  virtual unsigned int global_dimension() const
9437
 
  {
9438
 
    return __global_dimension;
9439
 
  }
9440
 
 
9441
 
  /// Return the dimension of the local finite element function space for a cell
9442
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
9443
 
  {
9444
 
    return 4;
9445
 
  }
9446
 
 
9447
 
  /// Return the maximum dimension of the local finite element function space
9448
 
  virtual unsigned int max_local_dimension() const
9449
 
  {
9450
 
    return 4;
9451
 
  }
9452
 
 
9453
 
  // Return the geometric dimension of the coordinates this dof map provides
9454
 
  virtual unsigned int geometric_dimension() const
9455
 
  {
9456
 
    return 3;
9457
 
  }
9458
 
 
9459
 
  /// Return the number of dofs on each cell facet
9460
 
  virtual unsigned int num_facet_dofs() const
9461
 
  {
9462
 
    return 3;
9463
 
  }
9464
 
 
9465
 
  /// Return the number of dofs associated with each cell entity of dimension d
9466
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
9467
 
  {
9468
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9469
 
  }
9470
 
 
9471
 
  /// Tabulate the local-to-global mapping of dofs on a cell
9472
 
  virtual void tabulate_dofs(unsigned int* dofs,
9473
 
                             const ufc::mesh& m,
9474
 
                             const ufc::cell& c) const
9475
 
  {
9476
 
    dofs[0] = c.entity_indices[0][0];
9477
 
    dofs[1] = c.entity_indices[0][1];
9478
 
    dofs[2] = c.entity_indices[0][2];
9479
 
    dofs[3] = c.entity_indices[0][3];
9480
 
  }
9481
 
 
9482
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
9483
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
9484
 
                                   unsigned int facet) const
9485
 
  {
9486
 
    switch ( facet )
9487
 
    {
9488
 
    case 0:
9489
 
      dofs[0] = 1;
9490
 
      dofs[1] = 2;
9491
 
      dofs[2] = 3;
9492
 
      break;
9493
 
    case 1:
9494
 
      dofs[0] = 0;
9495
 
      dofs[1] = 2;
9496
 
      dofs[2] = 3;
9497
 
      break;
9498
 
    case 2:
9499
 
      dofs[0] = 0;
9500
 
      dofs[1] = 1;
9501
 
      dofs[2] = 3;
9502
 
      break;
9503
 
    case 3:
9504
 
      dofs[0] = 0;
9505
 
      dofs[1] = 1;
9506
 
      dofs[2] = 2;
9507
 
      break;
9508
 
    }
9509
 
  }
9510
 
 
9511
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
9512
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
9513
 
                                    unsigned int d, unsigned int i) const
9514
 
  {
9515
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9516
 
  }
9517
 
 
9518
 
  /// Tabulate the coordinates of all dofs on a cell
9519
 
  virtual void tabulate_coordinates(double** coordinates,
9520
 
                                    const ufc::cell& c) const
9521
 
  {
9522
 
    const double * const * x = c.coordinates;
9523
 
    coordinates[0][0] = x[0][0];
9524
 
    coordinates[0][1] = x[0][1];
9525
 
    coordinates[0][2] = x[0][2];
9526
 
    coordinates[1][0] = x[1][0];
9527
 
    coordinates[1][1] = x[1][1];
9528
 
    coordinates[1][2] = x[1][2];
9529
 
    coordinates[2][0] = x[2][0];
9530
 
    coordinates[2][1] = x[2][1];
9531
 
    coordinates[2][2] = x[2][2];
9532
 
    coordinates[3][0] = x[3][0];
9533
 
    coordinates[3][1] = x[3][1];
9534
 
    coordinates[3][2] = x[3][2];
9535
 
  }
9536
 
 
9537
 
  /// Return the number of sub dof maps (for a mixed element)
9538
 
  virtual unsigned int num_sub_dof_maps() const
9539
 
  {
9540
 
    return 1;
9541
 
  }
9542
 
 
9543
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
9544
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
9545
 
  {
9546
 
    return new hyperelasticity_0_dof_map_1_0();
9547
 
  }
9548
 
 
9549
 
};
9550
 
 
9551
 
/// This class defines the interface for a local-to-global mapping of
9552
 
/// degrees of freedom (dofs).
9553
 
 
9554
 
class hyperelasticity_0_dof_map_1_1: public ufc::dof_map
9555
 
{
9556
 
private:
9557
 
 
9558
 
  unsigned int __global_dimension;
9559
 
 
9560
 
public:
9561
 
 
9562
 
  /// Constructor
9563
 
  hyperelasticity_0_dof_map_1_1() : ufc::dof_map()
9564
 
  {
9565
 
    __global_dimension = 0;
9566
 
  }
9567
 
 
9568
 
  /// Destructor
9569
 
  virtual ~hyperelasticity_0_dof_map_1_1()
9570
 
  {
9571
 
    // Do nothing
9572
 
  }
9573
 
 
9574
 
  /// Return a string identifying the dof map
9575
 
  virtual const char* signature() const
9576
 
  {
9577
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
9578
 
  }
9579
 
 
9580
 
  /// Return true iff mesh entities of topological dimension d are needed
9581
 
  virtual bool needs_mesh_entities(unsigned int d) const
9582
 
  {
9583
 
    switch ( d )
9584
 
    {
9585
 
    case 0:
9586
 
      return true;
9587
 
      break;
9588
 
    case 1:
9589
 
      return false;
9590
 
      break;
9591
 
    case 2:
9592
 
      return false;
9593
 
      break;
9594
 
    case 3:
9595
 
      return false;
9596
 
      break;
9597
 
    }
9598
 
    return false;
9599
 
  }
9600
 
 
9601
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
9602
 
  virtual bool init_mesh(const ufc::mesh& m)
9603
 
  {
9604
 
    __global_dimension = m.num_entities[0];
9605
 
    return false;
9606
 
  }
9607
 
 
9608
 
  /// Initialize dof map for given cell
9609
 
  virtual void init_cell(const ufc::mesh& m,
9610
 
                         const ufc::cell& c)
9611
 
  {
9612
 
    // Do nothing
9613
 
  }
9614
 
 
9615
 
  /// Finish initialization of dof map for cells
9616
 
  virtual void init_cell_finalize()
9617
 
  {
9618
 
    // Do nothing
9619
 
  }
9620
 
 
9621
 
  /// Return the dimension of the global finite element function space
9622
 
  virtual unsigned int global_dimension() const
9623
 
  {
9624
 
    return __global_dimension;
9625
 
  }
9626
 
 
9627
 
  /// Return the dimension of the local finite element function space for a cell
9628
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
9629
 
  {
9630
 
    return 4;
9631
 
  }
9632
 
 
9633
 
  /// Return the maximum dimension of the local finite element function space
9634
 
  virtual unsigned int max_local_dimension() const
9635
 
  {
9636
 
    return 4;
9637
 
  }
9638
 
 
9639
 
  // Return the geometric dimension of the coordinates this dof map provides
9640
 
  virtual unsigned int geometric_dimension() const
9641
 
  {
9642
 
    return 3;
9643
 
  }
9644
 
 
9645
 
  /// Return the number of dofs on each cell facet
9646
 
  virtual unsigned int num_facet_dofs() const
9647
 
  {
9648
 
    return 3;
9649
 
  }
9650
 
 
9651
 
  /// Return the number of dofs associated with each cell entity of dimension d
9652
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
9653
 
  {
9654
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9655
 
  }
9656
 
 
9657
 
  /// Tabulate the local-to-global mapping of dofs on a cell
9658
 
  virtual void tabulate_dofs(unsigned int* dofs,
9659
 
                             const ufc::mesh& m,
9660
 
                             const ufc::cell& c) const
9661
 
  {
9662
 
    dofs[0] = c.entity_indices[0][0];
9663
 
    dofs[1] = c.entity_indices[0][1];
9664
 
    dofs[2] = c.entity_indices[0][2];
9665
 
    dofs[3] = c.entity_indices[0][3];
9666
 
  }
9667
 
 
9668
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
9669
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
9670
 
                                   unsigned int facet) const
9671
 
  {
9672
 
    switch ( facet )
9673
 
    {
9674
 
    case 0:
9675
 
      dofs[0] = 1;
9676
 
      dofs[1] = 2;
9677
 
      dofs[2] = 3;
9678
 
      break;
9679
 
    case 1:
9680
 
      dofs[0] = 0;
9681
 
      dofs[1] = 2;
9682
 
      dofs[2] = 3;
9683
 
      break;
9684
 
    case 2:
9685
 
      dofs[0] = 0;
9686
 
      dofs[1] = 1;
9687
 
      dofs[2] = 3;
9688
 
      break;
9689
 
    case 3:
9690
 
      dofs[0] = 0;
9691
 
      dofs[1] = 1;
9692
 
      dofs[2] = 2;
9693
 
      break;
9694
 
    }
9695
 
  }
9696
 
 
9697
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
9698
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
9699
 
                                    unsigned int d, unsigned int i) const
9700
 
  {
9701
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9702
 
  }
9703
 
 
9704
 
  /// Tabulate the coordinates of all dofs on a cell
9705
 
  virtual void tabulate_coordinates(double** coordinates,
9706
 
                                    const ufc::cell& c) const
9707
 
  {
9708
 
    const double * const * x = c.coordinates;
9709
 
    coordinates[0][0] = x[0][0];
9710
 
    coordinates[0][1] = x[0][1];
9711
 
    coordinates[0][2] = x[0][2];
9712
 
    coordinates[1][0] = x[1][0];
9713
 
    coordinates[1][1] = x[1][1];
9714
 
    coordinates[1][2] = x[1][2];
9715
 
    coordinates[2][0] = x[2][0];
9716
 
    coordinates[2][1] = x[2][1];
9717
 
    coordinates[2][2] = x[2][2];
9718
 
    coordinates[3][0] = x[3][0];
9719
 
    coordinates[3][1] = x[3][1];
9720
 
    coordinates[3][2] = x[3][2];
9721
 
  }
9722
 
 
9723
 
  /// Return the number of sub dof maps (for a mixed element)
9724
 
  virtual unsigned int num_sub_dof_maps() const
9725
 
  {
9726
 
    return 1;
9727
 
  }
9728
 
 
9729
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
9730
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
9731
 
  {
9732
 
    return new hyperelasticity_0_dof_map_1_1();
9733
 
  }
9734
 
 
9735
 
};
9736
 
 
9737
 
/// This class defines the interface for a local-to-global mapping of
9738
 
/// degrees of freedom (dofs).
9739
 
 
9740
 
class hyperelasticity_0_dof_map_1_2: public ufc::dof_map
9741
 
{
9742
 
private:
9743
 
 
9744
 
  unsigned int __global_dimension;
9745
 
 
9746
 
public:
9747
 
 
9748
 
  /// Constructor
9749
 
  hyperelasticity_0_dof_map_1_2() : ufc::dof_map()
9750
 
  {
9751
 
    __global_dimension = 0;
9752
 
  }
9753
 
 
9754
 
  /// Destructor
9755
 
  virtual ~hyperelasticity_0_dof_map_1_2()
9756
 
  {
9757
 
    // Do nothing
9758
 
  }
9759
 
 
9760
 
  /// Return a string identifying the dof map
9761
 
  virtual const char* signature() const
9762
 
  {
9763
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
9764
 
  }
9765
 
 
9766
 
  /// Return true iff mesh entities of topological dimension d are needed
9767
 
  virtual bool needs_mesh_entities(unsigned int d) const
9768
 
  {
9769
 
    switch ( d )
9770
 
    {
9771
 
    case 0:
9772
 
      return true;
9773
 
      break;
9774
 
    case 1:
9775
 
      return false;
9776
 
      break;
9777
 
    case 2:
9778
 
      return false;
9779
 
      break;
9780
 
    case 3:
9781
 
      return false;
9782
 
      break;
9783
 
    }
9784
 
    return false;
9785
 
  }
9786
 
 
9787
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
9788
 
  virtual bool init_mesh(const ufc::mesh& m)
9789
 
  {
9790
 
    __global_dimension = m.num_entities[0];
9791
 
    return false;
9792
 
  }
9793
 
 
9794
 
  /// Initialize dof map for given cell
9795
 
  virtual void init_cell(const ufc::mesh& m,
9796
 
                         const ufc::cell& c)
9797
 
  {
9798
 
    // Do nothing
9799
 
  }
9800
 
 
9801
 
  /// Finish initialization of dof map for cells
9802
 
  virtual void init_cell_finalize()
9803
 
  {
9804
 
    // Do nothing
9805
 
  }
9806
 
 
9807
 
  /// Return the dimension of the global finite element function space
9808
 
  virtual unsigned int global_dimension() const
9809
 
  {
9810
 
    return __global_dimension;
9811
 
  }
9812
 
 
9813
 
  /// Return the dimension of the local finite element function space for a cell
9814
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
9815
 
  {
9816
 
    return 4;
9817
 
  }
9818
 
 
9819
 
  /// Return the maximum dimension of the local finite element function space
9820
 
  virtual unsigned int max_local_dimension() const
9821
 
  {
9822
 
    return 4;
9823
 
  }
9824
 
 
9825
 
  // Return the geometric dimension of the coordinates this dof map provides
9826
 
  virtual unsigned int geometric_dimension() const
9827
 
  {
9828
 
    return 3;
9829
 
  }
9830
 
 
9831
 
  /// Return the number of dofs on each cell facet
9832
 
  virtual unsigned int num_facet_dofs() const
9833
 
  {
9834
 
    return 3;
9835
 
  }
9836
 
 
9837
 
  /// Return the number of dofs associated with each cell entity of dimension d
9838
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
9839
 
  {
9840
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9841
 
  }
9842
 
 
9843
 
  /// Tabulate the local-to-global mapping of dofs on a cell
9844
 
  virtual void tabulate_dofs(unsigned int* dofs,
9845
 
                             const ufc::mesh& m,
9846
 
                             const ufc::cell& c) const
9847
 
  {
9848
 
    dofs[0] = c.entity_indices[0][0];
9849
 
    dofs[1] = c.entity_indices[0][1];
9850
 
    dofs[2] = c.entity_indices[0][2];
9851
 
    dofs[3] = c.entity_indices[0][3];
9852
 
  }
9853
 
 
9854
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
9855
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
9856
 
                                   unsigned int facet) const
9857
 
  {
9858
 
    switch ( facet )
9859
 
    {
9860
 
    case 0:
9861
 
      dofs[0] = 1;
9862
 
      dofs[1] = 2;
9863
 
      dofs[2] = 3;
9864
 
      break;
9865
 
    case 1:
9866
 
      dofs[0] = 0;
9867
 
      dofs[1] = 2;
9868
 
      dofs[2] = 3;
9869
 
      break;
9870
 
    case 2:
9871
 
      dofs[0] = 0;
9872
 
      dofs[1] = 1;
9873
 
      dofs[2] = 3;
9874
 
      break;
9875
 
    case 3:
9876
 
      dofs[0] = 0;
9877
 
      dofs[1] = 1;
9878
 
      dofs[2] = 2;
9879
 
      break;
9880
 
    }
9881
 
  }
9882
 
 
9883
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
9884
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
9885
 
                                    unsigned int d, unsigned int i) const
9886
 
  {
9887
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
9888
 
  }
9889
 
 
9890
 
  /// Tabulate the coordinates of all dofs on a cell
9891
 
  virtual void tabulate_coordinates(double** coordinates,
9892
 
                                    const ufc::cell& c) const
9893
 
  {
9894
 
    const double * const * x = c.coordinates;
9895
 
    coordinates[0][0] = x[0][0];
9896
 
    coordinates[0][1] = x[0][1];
9897
 
    coordinates[0][2] = x[0][2];
9898
 
    coordinates[1][0] = x[1][0];
9899
 
    coordinates[1][1] = x[1][1];
9900
 
    coordinates[1][2] = x[1][2];
9901
 
    coordinates[2][0] = x[2][0];
9902
 
    coordinates[2][1] = x[2][1];
9903
 
    coordinates[2][2] = x[2][2];
9904
 
    coordinates[3][0] = x[3][0];
9905
 
    coordinates[3][1] = x[3][1];
9906
 
    coordinates[3][2] = x[3][2];
9907
 
  }
9908
 
 
9909
 
  /// Return the number of sub dof maps (for a mixed element)
9910
 
  virtual unsigned int num_sub_dof_maps() const
9911
 
  {
9912
 
    return 1;
9913
 
  }
9914
 
 
9915
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
9916
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
9917
 
  {
9918
 
    return new hyperelasticity_0_dof_map_1_2();
9919
 
  }
9920
 
 
9921
 
};
9922
 
 
9923
 
/// This class defines the interface for a local-to-global mapping of
9924
 
/// degrees of freedom (dofs).
9925
 
 
9926
 
class hyperelasticity_0_dof_map_1: public ufc::dof_map
9927
 
{
9928
 
private:
9929
 
 
9930
 
  unsigned int __global_dimension;
9931
 
 
9932
 
public:
9933
 
 
9934
 
  /// Constructor
9935
 
  hyperelasticity_0_dof_map_1() : ufc::dof_map()
9936
 
  {
9937
 
    __global_dimension = 0;
9938
 
  }
9939
 
 
9940
 
  /// Destructor
9941
 
  virtual ~hyperelasticity_0_dof_map_1()
9942
 
  {
9943
 
    // Do nothing
9944
 
  }
9945
 
 
9946
 
  /// Return a string identifying the dof map
9947
 
  virtual const char* signature() const
9948
 
  {
9949
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
9950
 
  }
9951
 
 
9952
 
  /// Return true iff mesh entities of topological dimension d are needed
9953
 
  virtual bool needs_mesh_entities(unsigned int d) const
9954
 
  {
9955
 
    switch ( d )
9956
 
    {
9957
 
    case 0:
9958
 
      return true;
9959
 
      break;
9960
 
    case 1:
9961
 
      return false;
9962
 
      break;
9963
 
    case 2:
9964
 
      return false;
9965
 
      break;
9966
 
    case 3:
9967
 
      return false;
9968
 
      break;
9969
 
    }
9970
 
    return false;
9971
 
  }
9972
 
 
9973
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
9974
 
  virtual bool init_mesh(const ufc::mesh& m)
9975
 
  {
9976
 
    __global_dimension = 3*m.num_entities[0];
9977
 
    return false;
9978
 
  }
9979
 
 
9980
 
  /// Initialize dof map for given cell
9981
 
  virtual void init_cell(const ufc::mesh& m,
9982
 
                         const ufc::cell& c)
9983
 
  {
9984
 
    // Do nothing
9985
 
  }
9986
 
 
9987
 
  /// Finish initialization of dof map for cells
9988
 
  virtual void init_cell_finalize()
9989
 
  {
9990
 
    // Do nothing
9991
 
  }
9992
 
 
9993
 
  /// Return the dimension of the global finite element function space
9994
 
  virtual unsigned int global_dimension() const
9995
 
  {
9996
 
    return __global_dimension;
9997
 
  }
9998
 
 
9999
 
  /// Return the dimension of the local finite element function space for a cell
10000
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
10001
 
  {
10002
 
    return 12;
10003
 
  }
10004
 
 
10005
 
  /// Return the maximum dimension of the local finite element function space
10006
 
  virtual unsigned int max_local_dimension() const
10007
 
  {
10008
 
    return 12;
10009
 
  }
10010
 
 
10011
 
  // Return the geometric dimension of the coordinates this dof map provides
10012
 
  virtual unsigned int geometric_dimension() const
10013
 
  {
10014
 
    return 3;
10015
 
  }
10016
 
 
10017
 
  /// Return the number of dofs on each cell facet
10018
 
  virtual unsigned int num_facet_dofs() const
10019
 
  {
10020
 
    return 9;
10021
 
  }
10022
 
 
10023
 
  /// Return the number of dofs associated with each cell entity of dimension d
10024
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
10025
 
  {
10026
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10027
 
  }
10028
 
 
10029
 
  /// Tabulate the local-to-global mapping of dofs on a cell
10030
 
  virtual void tabulate_dofs(unsigned int* dofs,
10031
 
                             const ufc::mesh& m,
10032
 
                             const ufc::cell& c) const
10033
 
  {
10034
 
    dofs[0] = c.entity_indices[0][0];
10035
 
    dofs[1] = c.entity_indices[0][1];
10036
 
    dofs[2] = c.entity_indices[0][2];
10037
 
    dofs[3] = c.entity_indices[0][3];
10038
 
    unsigned int offset = m.num_entities[0];
10039
 
    dofs[4] = offset + c.entity_indices[0][0];
10040
 
    dofs[5] = offset + c.entity_indices[0][1];
10041
 
    dofs[6] = offset + c.entity_indices[0][2];
10042
 
    dofs[7] = offset + c.entity_indices[0][3];
10043
 
    offset = offset + m.num_entities[0];
10044
 
    dofs[8] = offset + c.entity_indices[0][0];
10045
 
    dofs[9] = offset + c.entity_indices[0][1];
10046
 
    dofs[10] = offset + c.entity_indices[0][2];
10047
 
    dofs[11] = offset + c.entity_indices[0][3];
10048
 
  }
10049
 
 
10050
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
10051
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
10052
 
                                   unsigned int facet) const
10053
 
  {
10054
 
    switch ( facet )
10055
 
    {
10056
 
    case 0:
10057
 
      dofs[0] = 1;
10058
 
      dofs[1] = 2;
10059
 
      dofs[2] = 3;
10060
 
      dofs[3] = 5;
10061
 
      dofs[4] = 6;
10062
 
      dofs[5] = 7;
10063
 
      dofs[6] = 9;
10064
 
      dofs[7] = 10;
10065
 
      dofs[8] = 11;
10066
 
      break;
10067
 
    case 1:
10068
 
      dofs[0] = 0;
10069
 
      dofs[1] = 2;
10070
 
      dofs[2] = 3;
10071
 
      dofs[3] = 4;
10072
 
      dofs[4] = 6;
10073
 
      dofs[5] = 7;
10074
 
      dofs[6] = 8;
10075
 
      dofs[7] = 10;
10076
 
      dofs[8] = 11;
10077
 
      break;
10078
 
    case 2:
10079
 
      dofs[0] = 0;
10080
 
      dofs[1] = 1;
10081
 
      dofs[2] = 3;
10082
 
      dofs[3] = 4;
10083
 
      dofs[4] = 5;
10084
 
      dofs[5] = 7;
10085
 
      dofs[6] = 8;
10086
 
      dofs[7] = 9;
10087
 
      dofs[8] = 11;
10088
 
      break;
10089
 
    case 3:
10090
 
      dofs[0] = 0;
10091
 
      dofs[1] = 1;
10092
 
      dofs[2] = 2;
10093
 
      dofs[3] = 4;
10094
 
      dofs[4] = 5;
10095
 
      dofs[5] = 6;
10096
 
      dofs[6] = 8;
10097
 
      dofs[7] = 9;
10098
 
      dofs[8] = 10;
10099
 
      break;
10100
 
    }
10101
 
  }
10102
 
 
10103
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
10104
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
10105
 
                                    unsigned int d, unsigned int i) const
10106
 
  {
10107
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10108
 
  }
10109
 
 
10110
 
  /// Tabulate the coordinates of all dofs on a cell
10111
 
  virtual void tabulate_coordinates(double** coordinates,
10112
 
                                    const ufc::cell& c) const
10113
 
  {
10114
 
    const double * const * x = c.coordinates;
10115
 
    coordinates[0][0] = x[0][0];
10116
 
    coordinates[0][1] = x[0][1];
10117
 
    coordinates[0][2] = x[0][2];
10118
 
    coordinates[1][0] = x[1][0];
10119
 
    coordinates[1][1] = x[1][1];
10120
 
    coordinates[1][2] = x[1][2];
10121
 
    coordinates[2][0] = x[2][0];
10122
 
    coordinates[2][1] = x[2][1];
10123
 
    coordinates[2][2] = x[2][2];
10124
 
    coordinates[3][0] = x[3][0];
10125
 
    coordinates[3][1] = x[3][1];
10126
 
    coordinates[3][2] = x[3][2];
10127
 
    coordinates[4][0] = x[0][0];
10128
 
    coordinates[4][1] = x[0][1];
10129
 
    coordinates[4][2] = x[0][2];
10130
 
    coordinates[5][0] = x[1][0];
10131
 
    coordinates[5][1] = x[1][1];
10132
 
    coordinates[5][2] = x[1][2];
10133
 
    coordinates[6][0] = x[2][0];
10134
 
    coordinates[6][1] = x[2][1];
10135
 
    coordinates[6][2] = x[2][2];
10136
 
    coordinates[7][0] = x[3][0];
10137
 
    coordinates[7][1] = x[3][1];
10138
 
    coordinates[7][2] = x[3][2];
10139
 
    coordinates[8][0] = x[0][0];
10140
 
    coordinates[8][1] = x[0][1];
10141
 
    coordinates[8][2] = x[0][2];
10142
 
    coordinates[9][0] = x[1][0];
10143
 
    coordinates[9][1] = x[1][1];
10144
 
    coordinates[9][2] = x[1][2];
10145
 
    coordinates[10][0] = x[2][0];
10146
 
    coordinates[10][1] = x[2][1];
10147
 
    coordinates[10][2] = x[2][2];
10148
 
    coordinates[11][0] = x[3][0];
10149
 
    coordinates[11][1] = x[3][1];
10150
 
    coordinates[11][2] = x[3][2];
10151
 
  }
10152
 
 
10153
 
  /// Return the number of sub dof maps (for a mixed element)
10154
 
  virtual unsigned int num_sub_dof_maps() const
10155
 
  {
10156
 
    return 3;
10157
 
  }
10158
 
 
10159
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
10160
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
10161
 
  {
10162
 
    switch ( i )
10163
 
    {
10164
 
    case 0:
10165
 
      return new hyperelasticity_0_dof_map_1_0();
10166
 
      break;
10167
 
    case 1:
10168
 
      return new hyperelasticity_0_dof_map_1_1();
10169
 
      break;
10170
 
    case 2:
10171
 
      return new hyperelasticity_0_dof_map_1_2();
10172
 
      break;
10173
 
    }
10174
 
    return 0;
10175
 
  }
10176
 
 
10177
 
};
10178
 
 
10179
 
/// This class defines the interface for a local-to-global mapping of
10180
 
/// degrees of freedom (dofs).
10181
 
 
10182
 
class hyperelasticity_0_dof_map_2_0: public ufc::dof_map
10183
 
{
10184
 
private:
10185
 
 
10186
 
  unsigned int __global_dimension;
10187
 
 
10188
 
public:
10189
 
 
10190
 
  /// Constructor
10191
 
  hyperelasticity_0_dof_map_2_0() : ufc::dof_map()
10192
 
  {
10193
 
    __global_dimension = 0;
10194
 
  }
10195
 
 
10196
 
  /// Destructor
10197
 
  virtual ~hyperelasticity_0_dof_map_2_0()
10198
 
  {
10199
 
    // Do nothing
10200
 
  }
10201
 
 
10202
 
  /// Return a string identifying the dof map
10203
 
  virtual const char* signature() const
10204
 
  {
10205
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
10206
 
  }
10207
 
 
10208
 
  /// Return true iff mesh entities of topological dimension d are needed
10209
 
  virtual bool needs_mesh_entities(unsigned int d) const
10210
 
  {
10211
 
    switch ( d )
10212
 
    {
10213
 
    case 0:
10214
 
      return true;
10215
 
      break;
10216
 
    case 1:
10217
 
      return false;
10218
 
      break;
10219
 
    case 2:
10220
 
      return false;
10221
 
      break;
10222
 
    case 3:
10223
 
      return false;
10224
 
      break;
10225
 
    }
10226
 
    return false;
10227
 
  }
10228
 
 
10229
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
10230
 
  virtual bool init_mesh(const ufc::mesh& m)
10231
 
  {
10232
 
    __global_dimension = m.num_entities[0];
10233
 
    return false;
10234
 
  }
10235
 
 
10236
 
  /// Initialize dof map for given cell
10237
 
  virtual void init_cell(const ufc::mesh& m,
10238
 
                         const ufc::cell& c)
10239
 
  {
10240
 
    // Do nothing
10241
 
  }
10242
 
 
10243
 
  /// Finish initialization of dof map for cells
10244
 
  virtual void init_cell_finalize()
10245
 
  {
10246
 
    // Do nothing
10247
 
  }
10248
 
 
10249
 
  /// Return the dimension of the global finite element function space
10250
 
  virtual unsigned int global_dimension() const
10251
 
  {
10252
 
    return __global_dimension;
10253
 
  }
10254
 
 
10255
 
  /// Return the dimension of the local finite element function space for a cell
10256
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
10257
 
  {
10258
 
    return 4;
10259
 
  }
10260
 
 
10261
 
  /// Return the maximum dimension of the local finite element function space
10262
 
  virtual unsigned int max_local_dimension() const
10263
 
  {
10264
 
    return 4;
10265
 
  }
10266
 
 
10267
 
  // Return the geometric dimension of the coordinates this dof map provides
10268
 
  virtual unsigned int geometric_dimension() const
10269
 
  {
10270
 
    return 3;
10271
 
  }
10272
 
 
10273
 
  /// Return the number of dofs on each cell facet
10274
 
  virtual unsigned int num_facet_dofs() const
10275
 
  {
10276
 
    return 3;
10277
 
  }
10278
 
 
10279
 
  /// Return the number of dofs associated with each cell entity of dimension d
10280
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
10281
 
  {
10282
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10283
 
  }
10284
 
 
10285
 
  /// Tabulate the local-to-global mapping of dofs on a cell
10286
 
  virtual void tabulate_dofs(unsigned int* dofs,
10287
 
                             const ufc::mesh& m,
10288
 
                             const ufc::cell& c) const
10289
 
  {
10290
 
    dofs[0] = c.entity_indices[0][0];
10291
 
    dofs[1] = c.entity_indices[0][1];
10292
 
    dofs[2] = c.entity_indices[0][2];
10293
 
    dofs[3] = c.entity_indices[0][3];
10294
 
  }
10295
 
 
10296
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
10297
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
10298
 
                                   unsigned int facet) const
10299
 
  {
10300
 
    switch ( facet )
10301
 
    {
10302
 
    case 0:
10303
 
      dofs[0] = 1;
10304
 
      dofs[1] = 2;
10305
 
      dofs[2] = 3;
10306
 
      break;
10307
 
    case 1:
10308
 
      dofs[0] = 0;
10309
 
      dofs[1] = 2;
10310
 
      dofs[2] = 3;
10311
 
      break;
10312
 
    case 2:
10313
 
      dofs[0] = 0;
10314
 
      dofs[1] = 1;
10315
 
      dofs[2] = 3;
10316
 
      break;
10317
 
    case 3:
10318
 
      dofs[0] = 0;
10319
 
      dofs[1] = 1;
10320
 
      dofs[2] = 2;
10321
 
      break;
10322
 
    }
10323
 
  }
10324
 
 
10325
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
10326
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
10327
 
                                    unsigned int d, unsigned int i) const
10328
 
  {
10329
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10330
 
  }
10331
 
 
10332
 
  /// Tabulate the coordinates of all dofs on a cell
10333
 
  virtual void tabulate_coordinates(double** coordinates,
10334
 
                                    const ufc::cell& c) const
10335
 
  {
10336
 
    const double * const * x = c.coordinates;
10337
 
    coordinates[0][0] = x[0][0];
10338
 
    coordinates[0][1] = x[0][1];
10339
 
    coordinates[0][2] = x[0][2];
10340
 
    coordinates[1][0] = x[1][0];
10341
 
    coordinates[1][1] = x[1][1];
10342
 
    coordinates[1][2] = x[1][2];
10343
 
    coordinates[2][0] = x[2][0];
10344
 
    coordinates[2][1] = x[2][1];
10345
 
    coordinates[2][2] = x[2][2];
10346
 
    coordinates[3][0] = x[3][0];
10347
 
    coordinates[3][1] = x[3][1];
10348
 
    coordinates[3][2] = x[3][2];
10349
 
  }
10350
 
 
10351
 
  /// Return the number of sub dof maps (for a mixed element)
10352
 
  virtual unsigned int num_sub_dof_maps() const
10353
 
  {
10354
 
    return 1;
10355
 
  }
10356
 
 
10357
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
10358
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
10359
 
  {
10360
 
    return new hyperelasticity_0_dof_map_2_0();
10361
 
  }
10362
 
 
10363
 
};
10364
 
 
10365
 
/// This class defines the interface for a local-to-global mapping of
10366
 
/// degrees of freedom (dofs).
10367
 
 
10368
 
class hyperelasticity_0_dof_map_2_1: public ufc::dof_map
10369
 
{
10370
 
private:
10371
 
 
10372
 
  unsigned int __global_dimension;
10373
 
 
10374
 
public:
10375
 
 
10376
 
  /// Constructor
10377
 
  hyperelasticity_0_dof_map_2_1() : ufc::dof_map()
10378
 
  {
10379
 
    __global_dimension = 0;
10380
 
  }
10381
 
 
10382
 
  /// Destructor
10383
 
  virtual ~hyperelasticity_0_dof_map_2_1()
10384
 
  {
10385
 
    // Do nothing
10386
 
  }
10387
 
 
10388
 
  /// Return a string identifying the dof map
10389
 
  virtual const char* signature() const
10390
 
  {
10391
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
10392
 
  }
10393
 
 
10394
 
  /// Return true iff mesh entities of topological dimension d are needed
10395
 
  virtual bool needs_mesh_entities(unsigned int d) const
10396
 
  {
10397
 
    switch ( d )
10398
 
    {
10399
 
    case 0:
10400
 
      return true;
10401
 
      break;
10402
 
    case 1:
10403
 
      return false;
10404
 
      break;
10405
 
    case 2:
10406
 
      return false;
10407
 
      break;
10408
 
    case 3:
10409
 
      return false;
10410
 
      break;
10411
 
    }
10412
 
    return false;
10413
 
  }
10414
 
 
10415
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
10416
 
  virtual bool init_mesh(const ufc::mesh& m)
10417
 
  {
10418
 
    __global_dimension = m.num_entities[0];
10419
 
    return false;
10420
 
  }
10421
 
 
10422
 
  /// Initialize dof map for given cell
10423
 
  virtual void init_cell(const ufc::mesh& m,
10424
 
                         const ufc::cell& c)
10425
 
  {
10426
 
    // Do nothing
10427
 
  }
10428
 
 
10429
 
  /// Finish initialization of dof map for cells
10430
 
  virtual void init_cell_finalize()
10431
 
  {
10432
 
    // Do nothing
10433
 
  }
10434
 
 
10435
 
  /// Return the dimension of the global finite element function space
10436
 
  virtual unsigned int global_dimension() const
10437
 
  {
10438
 
    return __global_dimension;
10439
 
  }
10440
 
 
10441
 
  /// Return the dimension of the local finite element function space for a cell
10442
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
10443
 
  {
10444
 
    return 4;
10445
 
  }
10446
 
 
10447
 
  /// Return the maximum dimension of the local finite element function space
10448
 
  virtual unsigned int max_local_dimension() const
10449
 
  {
10450
 
    return 4;
10451
 
  }
10452
 
 
10453
 
  // Return the geometric dimension of the coordinates this dof map provides
10454
 
  virtual unsigned int geometric_dimension() const
10455
 
  {
10456
 
    return 3;
10457
 
  }
10458
 
 
10459
 
  /// Return the number of dofs on each cell facet
10460
 
  virtual unsigned int num_facet_dofs() const
10461
 
  {
10462
 
    return 3;
10463
 
  }
10464
 
 
10465
 
  /// Return the number of dofs associated with each cell entity of dimension d
10466
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
10467
 
  {
10468
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10469
 
  }
10470
 
 
10471
 
  /// Tabulate the local-to-global mapping of dofs on a cell
10472
 
  virtual void tabulate_dofs(unsigned int* dofs,
10473
 
                             const ufc::mesh& m,
10474
 
                             const ufc::cell& c) const
10475
 
  {
10476
 
    dofs[0] = c.entity_indices[0][0];
10477
 
    dofs[1] = c.entity_indices[0][1];
10478
 
    dofs[2] = c.entity_indices[0][2];
10479
 
    dofs[3] = c.entity_indices[0][3];
10480
 
  }
10481
 
 
10482
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
10483
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
10484
 
                                   unsigned int facet) const
10485
 
  {
10486
 
    switch ( facet )
10487
 
    {
10488
 
    case 0:
10489
 
      dofs[0] = 1;
10490
 
      dofs[1] = 2;
10491
 
      dofs[2] = 3;
10492
 
      break;
10493
 
    case 1:
10494
 
      dofs[0] = 0;
10495
 
      dofs[1] = 2;
10496
 
      dofs[2] = 3;
10497
 
      break;
10498
 
    case 2:
10499
 
      dofs[0] = 0;
10500
 
      dofs[1] = 1;
10501
 
      dofs[2] = 3;
10502
 
      break;
10503
 
    case 3:
10504
 
      dofs[0] = 0;
10505
 
      dofs[1] = 1;
10506
 
      dofs[2] = 2;
10507
 
      break;
10508
 
    }
10509
 
  }
10510
 
 
10511
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
10512
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
10513
 
                                    unsigned int d, unsigned int i) const
10514
 
  {
10515
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10516
 
  }
10517
 
 
10518
 
  /// Tabulate the coordinates of all dofs on a cell
10519
 
  virtual void tabulate_coordinates(double** coordinates,
10520
 
                                    const ufc::cell& c) const
10521
 
  {
10522
 
    const double * const * x = c.coordinates;
10523
 
    coordinates[0][0] = x[0][0];
10524
 
    coordinates[0][1] = x[0][1];
10525
 
    coordinates[0][2] = x[0][2];
10526
 
    coordinates[1][0] = x[1][0];
10527
 
    coordinates[1][1] = x[1][1];
10528
 
    coordinates[1][2] = x[1][2];
10529
 
    coordinates[2][0] = x[2][0];
10530
 
    coordinates[2][1] = x[2][1];
10531
 
    coordinates[2][2] = x[2][2];
10532
 
    coordinates[3][0] = x[3][0];
10533
 
    coordinates[3][1] = x[3][1];
10534
 
    coordinates[3][2] = x[3][2];
10535
 
  }
10536
 
 
10537
 
  /// Return the number of sub dof maps (for a mixed element)
10538
 
  virtual unsigned int num_sub_dof_maps() const
10539
 
  {
10540
 
    return 1;
10541
 
  }
10542
 
 
10543
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
10544
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
10545
 
  {
10546
 
    return new hyperelasticity_0_dof_map_2_1();
10547
 
  }
10548
 
 
10549
 
};
10550
 
 
10551
 
/// This class defines the interface for a local-to-global mapping of
10552
 
/// degrees of freedom (dofs).
10553
 
 
10554
 
class hyperelasticity_0_dof_map_2_2: public ufc::dof_map
10555
 
{
10556
 
private:
10557
 
 
10558
 
  unsigned int __global_dimension;
10559
 
 
10560
 
public:
10561
 
 
10562
 
  /// Constructor
10563
 
  hyperelasticity_0_dof_map_2_2() : ufc::dof_map()
10564
 
  {
10565
 
    __global_dimension = 0;
10566
 
  }
10567
 
 
10568
 
  /// Destructor
10569
 
  virtual ~hyperelasticity_0_dof_map_2_2()
10570
 
  {
10571
 
    // Do nothing
10572
 
  }
10573
 
 
10574
 
  /// Return a string identifying the dof map
10575
 
  virtual const char* signature() const
10576
 
  {
10577
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
10578
 
  }
10579
 
 
10580
 
  /// Return true iff mesh entities of topological dimension d are needed
10581
 
  virtual bool needs_mesh_entities(unsigned int d) const
10582
 
  {
10583
 
    switch ( d )
10584
 
    {
10585
 
    case 0:
10586
 
      return true;
10587
 
      break;
10588
 
    case 1:
10589
 
      return false;
10590
 
      break;
10591
 
    case 2:
10592
 
      return false;
10593
 
      break;
10594
 
    case 3:
10595
 
      return false;
10596
 
      break;
10597
 
    }
10598
 
    return false;
10599
 
  }
10600
 
 
10601
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
10602
 
  virtual bool init_mesh(const ufc::mesh& m)
10603
 
  {
10604
 
    __global_dimension = m.num_entities[0];
10605
 
    return false;
10606
 
  }
10607
 
 
10608
 
  /// Initialize dof map for given cell
10609
 
  virtual void init_cell(const ufc::mesh& m,
10610
 
                         const ufc::cell& c)
10611
 
  {
10612
 
    // Do nothing
10613
 
  }
10614
 
 
10615
 
  /// Finish initialization of dof map for cells
10616
 
  virtual void init_cell_finalize()
10617
 
  {
10618
 
    // Do nothing
10619
 
  }
10620
 
 
10621
 
  /// Return the dimension of the global finite element function space
10622
 
  virtual unsigned int global_dimension() const
10623
 
  {
10624
 
    return __global_dimension;
10625
 
  }
10626
 
 
10627
 
  /// Return the dimension of the local finite element function space for a cell
10628
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
10629
 
  {
10630
 
    return 4;
10631
 
  }
10632
 
 
10633
 
  /// Return the maximum dimension of the local finite element function space
10634
 
  virtual unsigned int max_local_dimension() const
10635
 
  {
10636
 
    return 4;
10637
 
  }
10638
 
 
10639
 
  // Return the geometric dimension of the coordinates this dof map provides
10640
 
  virtual unsigned int geometric_dimension() const
10641
 
  {
10642
 
    return 3;
10643
 
  }
10644
 
 
10645
 
  /// Return the number of dofs on each cell facet
10646
 
  virtual unsigned int num_facet_dofs() const
10647
 
  {
10648
 
    return 3;
10649
 
  }
10650
 
 
10651
 
  /// Return the number of dofs associated with each cell entity of dimension d
10652
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
10653
 
  {
10654
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10655
 
  }
10656
 
 
10657
 
  /// Tabulate the local-to-global mapping of dofs on a cell
10658
 
  virtual void tabulate_dofs(unsigned int* dofs,
10659
 
                             const ufc::mesh& m,
10660
 
                             const ufc::cell& c) const
10661
 
  {
10662
 
    dofs[0] = c.entity_indices[0][0];
10663
 
    dofs[1] = c.entity_indices[0][1];
10664
 
    dofs[2] = c.entity_indices[0][2];
10665
 
    dofs[3] = c.entity_indices[0][3];
10666
 
  }
10667
 
 
10668
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
10669
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
10670
 
                                   unsigned int facet) const
10671
 
  {
10672
 
    switch ( facet )
10673
 
    {
10674
 
    case 0:
10675
 
      dofs[0] = 1;
10676
 
      dofs[1] = 2;
10677
 
      dofs[2] = 3;
10678
 
      break;
10679
 
    case 1:
10680
 
      dofs[0] = 0;
10681
 
      dofs[1] = 2;
10682
 
      dofs[2] = 3;
10683
 
      break;
10684
 
    case 2:
10685
 
      dofs[0] = 0;
10686
 
      dofs[1] = 1;
10687
 
      dofs[2] = 3;
10688
 
      break;
10689
 
    case 3:
10690
 
      dofs[0] = 0;
10691
 
      dofs[1] = 1;
10692
 
      dofs[2] = 2;
10693
 
      break;
10694
 
    }
10695
 
  }
10696
 
 
10697
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
10698
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
10699
 
                                    unsigned int d, unsigned int i) const
10700
 
  {
10701
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10702
 
  }
10703
 
 
10704
 
  /// Tabulate the coordinates of all dofs on a cell
10705
 
  virtual void tabulate_coordinates(double** coordinates,
10706
 
                                    const ufc::cell& c) const
10707
 
  {
10708
 
    const double * const * x = c.coordinates;
10709
 
    coordinates[0][0] = x[0][0];
10710
 
    coordinates[0][1] = x[0][1];
10711
 
    coordinates[0][2] = x[0][2];
10712
 
    coordinates[1][0] = x[1][0];
10713
 
    coordinates[1][1] = x[1][1];
10714
 
    coordinates[1][2] = x[1][2];
10715
 
    coordinates[2][0] = x[2][0];
10716
 
    coordinates[2][1] = x[2][1];
10717
 
    coordinates[2][2] = x[2][2];
10718
 
    coordinates[3][0] = x[3][0];
10719
 
    coordinates[3][1] = x[3][1];
10720
 
    coordinates[3][2] = x[3][2];
10721
 
  }
10722
 
 
10723
 
  /// Return the number of sub dof maps (for a mixed element)
10724
 
  virtual unsigned int num_sub_dof_maps() const
10725
 
  {
10726
 
    return 1;
10727
 
  }
10728
 
 
10729
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
10730
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
10731
 
  {
10732
 
    return new hyperelasticity_0_dof_map_2_2();
10733
 
  }
10734
 
 
10735
 
};
10736
 
 
10737
 
/// This class defines the interface for a local-to-global mapping of
10738
 
/// degrees of freedom (dofs).
10739
 
 
10740
 
class hyperelasticity_0_dof_map_2: public ufc::dof_map
10741
 
{
10742
 
private:
10743
 
 
10744
 
  unsigned int __global_dimension;
10745
 
 
10746
 
public:
10747
 
 
10748
 
  /// Constructor
10749
 
  hyperelasticity_0_dof_map_2() : ufc::dof_map()
10750
 
  {
10751
 
    __global_dimension = 0;
10752
 
  }
10753
 
 
10754
 
  /// Destructor
10755
 
  virtual ~hyperelasticity_0_dof_map_2()
10756
 
  {
10757
 
    // Do nothing
10758
 
  }
10759
 
 
10760
 
  /// Return a string identifying the dof map
10761
 
  virtual const char* signature() const
10762
 
  {
10763
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
10764
 
  }
10765
 
 
10766
 
  /// Return true iff mesh entities of topological dimension d are needed
10767
 
  virtual bool needs_mesh_entities(unsigned int d) const
10768
 
  {
10769
 
    switch ( d )
10770
 
    {
10771
 
    case 0:
10772
 
      return true;
10773
 
      break;
10774
 
    case 1:
10775
 
      return false;
10776
 
      break;
10777
 
    case 2:
10778
 
      return false;
10779
 
      break;
10780
 
    case 3:
10781
 
      return false;
10782
 
      break;
10783
 
    }
10784
 
    return false;
10785
 
  }
10786
 
 
10787
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
10788
 
  virtual bool init_mesh(const ufc::mesh& m)
10789
 
  {
10790
 
    __global_dimension = 3*m.num_entities[0];
10791
 
    return false;
10792
 
  }
10793
 
 
10794
 
  /// Initialize dof map for given cell
10795
 
  virtual void init_cell(const ufc::mesh& m,
10796
 
                         const ufc::cell& c)
10797
 
  {
10798
 
    // Do nothing
10799
 
  }
10800
 
 
10801
 
  /// Finish initialization of dof map for cells
10802
 
  virtual void init_cell_finalize()
10803
 
  {
10804
 
    // Do nothing
10805
 
  }
10806
 
 
10807
 
  /// Return the dimension of the global finite element function space
10808
 
  virtual unsigned int global_dimension() const
10809
 
  {
10810
 
    return __global_dimension;
10811
 
  }
10812
 
 
10813
 
  /// Return the dimension of the local finite element function space for a cell
10814
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
10815
 
  {
10816
 
    return 12;
10817
 
  }
10818
 
 
10819
 
  /// Return the maximum dimension of the local finite element function space
10820
 
  virtual unsigned int max_local_dimension() const
10821
 
  {
10822
 
    return 12;
10823
 
  }
10824
 
 
10825
 
  // Return the geometric dimension of the coordinates this dof map provides
10826
 
  virtual unsigned int geometric_dimension() const
10827
 
  {
10828
 
    return 3;
10829
 
  }
10830
 
 
10831
 
  /// Return the number of dofs on each cell facet
10832
 
  virtual unsigned int num_facet_dofs() const
10833
 
  {
10834
 
    return 9;
10835
 
  }
10836
 
 
10837
 
  /// Return the number of dofs associated with each cell entity of dimension d
10838
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
10839
 
  {
10840
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10841
 
  }
10842
 
 
10843
 
  /// Tabulate the local-to-global mapping of dofs on a cell
10844
 
  virtual void tabulate_dofs(unsigned int* dofs,
10845
 
                             const ufc::mesh& m,
10846
 
                             const ufc::cell& c) const
10847
 
  {
10848
 
    dofs[0] = c.entity_indices[0][0];
10849
 
    dofs[1] = c.entity_indices[0][1];
10850
 
    dofs[2] = c.entity_indices[0][2];
10851
 
    dofs[3] = c.entity_indices[0][3];
10852
 
    unsigned int offset = m.num_entities[0];
10853
 
    dofs[4] = offset + c.entity_indices[0][0];
10854
 
    dofs[5] = offset + c.entity_indices[0][1];
10855
 
    dofs[6] = offset + c.entity_indices[0][2];
10856
 
    dofs[7] = offset + c.entity_indices[0][3];
10857
 
    offset = offset + m.num_entities[0];
10858
 
    dofs[8] = offset + c.entity_indices[0][0];
10859
 
    dofs[9] = offset + c.entity_indices[0][1];
10860
 
    dofs[10] = offset + c.entity_indices[0][2];
10861
 
    dofs[11] = offset + c.entity_indices[0][3];
10862
 
  }
10863
 
 
10864
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
10865
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
10866
 
                                   unsigned int facet) const
10867
 
  {
10868
 
    switch ( facet )
10869
 
    {
10870
 
    case 0:
10871
 
      dofs[0] = 1;
10872
 
      dofs[1] = 2;
10873
 
      dofs[2] = 3;
10874
 
      dofs[3] = 5;
10875
 
      dofs[4] = 6;
10876
 
      dofs[5] = 7;
10877
 
      dofs[6] = 9;
10878
 
      dofs[7] = 10;
10879
 
      dofs[8] = 11;
10880
 
      break;
10881
 
    case 1:
10882
 
      dofs[0] = 0;
10883
 
      dofs[1] = 2;
10884
 
      dofs[2] = 3;
10885
 
      dofs[3] = 4;
10886
 
      dofs[4] = 6;
10887
 
      dofs[5] = 7;
10888
 
      dofs[6] = 8;
10889
 
      dofs[7] = 10;
10890
 
      dofs[8] = 11;
10891
 
      break;
10892
 
    case 2:
10893
 
      dofs[0] = 0;
10894
 
      dofs[1] = 1;
10895
 
      dofs[2] = 3;
10896
 
      dofs[3] = 4;
10897
 
      dofs[4] = 5;
10898
 
      dofs[5] = 7;
10899
 
      dofs[6] = 8;
10900
 
      dofs[7] = 9;
10901
 
      dofs[8] = 11;
10902
 
      break;
10903
 
    case 3:
10904
 
      dofs[0] = 0;
10905
 
      dofs[1] = 1;
10906
 
      dofs[2] = 2;
10907
 
      dofs[3] = 4;
10908
 
      dofs[4] = 5;
10909
 
      dofs[5] = 6;
10910
 
      dofs[6] = 8;
10911
 
      dofs[7] = 9;
10912
 
      dofs[8] = 10;
10913
 
      break;
10914
 
    }
10915
 
  }
10916
 
 
10917
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
10918
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
10919
 
                                    unsigned int d, unsigned int i) const
10920
 
  {
10921
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
10922
 
  }
10923
 
 
10924
 
  /// Tabulate the coordinates of all dofs on a cell
10925
 
  virtual void tabulate_coordinates(double** coordinates,
10926
 
                                    const ufc::cell& c) const
10927
 
  {
10928
 
    const double * const * x = c.coordinates;
10929
 
    coordinates[0][0] = x[0][0];
10930
 
    coordinates[0][1] = x[0][1];
10931
 
    coordinates[0][2] = x[0][2];
10932
 
    coordinates[1][0] = x[1][0];
10933
 
    coordinates[1][1] = x[1][1];
10934
 
    coordinates[1][2] = x[1][2];
10935
 
    coordinates[2][0] = x[2][0];
10936
 
    coordinates[2][1] = x[2][1];
10937
 
    coordinates[2][2] = x[2][2];
10938
 
    coordinates[3][0] = x[3][0];
10939
 
    coordinates[3][1] = x[3][1];
10940
 
    coordinates[3][2] = x[3][2];
10941
 
    coordinates[4][0] = x[0][0];
10942
 
    coordinates[4][1] = x[0][1];
10943
 
    coordinates[4][2] = x[0][2];
10944
 
    coordinates[5][0] = x[1][0];
10945
 
    coordinates[5][1] = x[1][1];
10946
 
    coordinates[5][2] = x[1][2];
10947
 
    coordinates[6][0] = x[2][0];
10948
 
    coordinates[6][1] = x[2][1];
10949
 
    coordinates[6][2] = x[2][2];
10950
 
    coordinates[7][0] = x[3][0];
10951
 
    coordinates[7][1] = x[3][1];
10952
 
    coordinates[7][2] = x[3][2];
10953
 
    coordinates[8][0] = x[0][0];
10954
 
    coordinates[8][1] = x[0][1];
10955
 
    coordinates[8][2] = x[0][2];
10956
 
    coordinates[9][0] = x[1][0];
10957
 
    coordinates[9][1] = x[1][1];
10958
 
    coordinates[9][2] = x[1][2];
10959
 
    coordinates[10][0] = x[2][0];
10960
 
    coordinates[10][1] = x[2][1];
10961
 
    coordinates[10][2] = x[2][2];
10962
 
    coordinates[11][0] = x[3][0];
10963
 
    coordinates[11][1] = x[3][1];
10964
 
    coordinates[11][2] = x[3][2];
10965
 
  }
10966
 
 
10967
 
  /// Return the number of sub dof maps (for a mixed element)
10968
 
  virtual unsigned int num_sub_dof_maps() const
10969
 
  {
10970
 
    return 3;
10971
 
  }
10972
 
 
10973
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
10974
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
10975
 
  {
10976
 
    switch ( i )
10977
 
    {
10978
 
    case 0:
10979
 
      return new hyperelasticity_0_dof_map_2_0();
10980
 
      break;
10981
 
    case 1:
10982
 
      return new hyperelasticity_0_dof_map_2_1();
10983
 
      break;
10984
 
    case 2:
10985
 
      return new hyperelasticity_0_dof_map_2_2();
10986
 
      break;
10987
 
    }
10988
 
    return 0;
10989
 
  }
10990
 
 
10991
 
};
10992
 
 
10993
 
/// This class defines the interface for a local-to-global mapping of
10994
 
/// degrees of freedom (dofs).
10995
 
 
10996
 
class hyperelasticity_0_dof_map_3: public ufc::dof_map
10997
 
{
10998
 
private:
10999
 
 
11000
 
  unsigned int __global_dimension;
11001
 
 
11002
 
public:
11003
 
 
11004
 
  /// Constructor
11005
 
  hyperelasticity_0_dof_map_3() : ufc::dof_map()
11006
 
  {
11007
 
    __global_dimension = 0;
11008
 
  }
11009
 
 
11010
 
  /// Destructor
11011
 
  virtual ~hyperelasticity_0_dof_map_3()
11012
 
  {
11013
 
    // Do nothing
11014
 
  }
11015
 
 
11016
 
  /// Return a string identifying the dof map
11017
 
  virtual const char* signature() const
11018
 
  {
11019
 
    return "FFC dof map for FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
11020
 
  }
11021
 
 
11022
 
  /// Return true iff mesh entities of topological dimension d are needed
11023
 
  virtual bool needs_mesh_entities(unsigned int d) const
11024
 
  {
11025
 
    switch ( d )
11026
 
    {
11027
 
    case 0:
11028
 
      return false;
11029
 
      break;
11030
 
    case 1:
11031
 
      return false;
11032
 
      break;
11033
 
    case 2:
11034
 
      return false;
11035
 
      break;
11036
 
    case 3:
11037
 
      return true;
11038
 
      break;
11039
 
    }
11040
 
    return false;
11041
 
  }
11042
 
 
11043
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
11044
 
  virtual bool init_mesh(const ufc::mesh& m)
11045
 
  {
11046
 
    __global_dimension = m.num_entities[3];
11047
 
    return false;
11048
 
  }
11049
 
 
11050
 
  /// Initialize dof map for given cell
11051
 
  virtual void init_cell(const ufc::mesh& m,
11052
 
                         const ufc::cell& c)
11053
 
  {
11054
 
    // Do nothing
11055
 
  }
11056
 
 
11057
 
  /// Finish initialization of dof map for cells
11058
 
  virtual void init_cell_finalize()
11059
 
  {
11060
 
    // Do nothing
11061
 
  }
11062
 
 
11063
 
  /// Return the dimension of the global finite element function space
11064
 
  virtual unsigned int global_dimension() const
11065
 
  {
11066
 
    return __global_dimension;
11067
 
  }
11068
 
 
11069
 
  /// Return the dimension of the local finite element function space for a cell
11070
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
11071
 
  {
11072
 
    return 1;
11073
 
  }
11074
 
 
11075
 
  /// Return the maximum dimension of the local finite element function space
11076
 
  virtual unsigned int max_local_dimension() const
11077
 
  {
11078
 
    return 1;
11079
 
  }
11080
 
 
11081
 
  // Return the geometric dimension of the coordinates this dof map provides
11082
 
  virtual unsigned int geometric_dimension() const
11083
 
  {
11084
 
    return 3;
11085
 
  }
11086
 
 
11087
 
  /// Return the number of dofs on each cell facet
11088
 
  virtual unsigned int num_facet_dofs() const
11089
 
  {
11090
 
    return 0;
11091
 
  }
11092
 
 
11093
 
  /// Return the number of dofs associated with each cell entity of dimension d
11094
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
11095
 
  {
11096
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
11097
 
  }
11098
 
 
11099
 
  /// Tabulate the local-to-global mapping of dofs on a cell
11100
 
  virtual void tabulate_dofs(unsigned int* dofs,
11101
 
                             const ufc::mesh& m,
11102
 
                             const ufc::cell& c) const
11103
 
  {
11104
 
    dofs[0] = c.entity_indices[3][0];
11105
 
  }
11106
 
 
11107
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
11108
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
11109
 
                                   unsigned int facet) const
11110
 
  {
11111
 
    switch ( facet )
11112
 
    {
11113
 
    case 0:
11114
 
      
11115
 
      break;
11116
 
    case 1:
11117
 
      
11118
 
      break;
11119
 
    case 2:
11120
 
      
11121
 
      break;
11122
 
    case 3:
11123
 
      
11124
 
      break;
11125
 
    }
11126
 
  }
11127
 
 
11128
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
11129
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
11130
 
                                    unsigned int d, unsigned int i) const
11131
 
  {
11132
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
11133
 
  }
11134
 
 
11135
 
  /// Tabulate the coordinates of all dofs on a cell
11136
 
  virtual void tabulate_coordinates(double** coordinates,
11137
 
                                    const ufc::cell& c) const
11138
 
  {
11139
 
    const double * const * x = c.coordinates;
11140
 
    coordinates[0][0] = 0.25*x[0][0] + 0.25*x[1][0] + 0.25*x[2][0] + 0.25*x[3][0];
11141
 
    coordinates[0][1] = 0.25*x[0][1] + 0.25*x[1][1] + 0.25*x[2][1] + 0.25*x[3][1];
11142
 
    coordinates[0][2] = 0.25*x[0][2] + 0.25*x[1][2] + 0.25*x[2][2] + 0.25*x[3][2];
11143
 
  }
11144
 
 
11145
 
  /// Return the number of sub dof maps (for a mixed element)
11146
 
  virtual unsigned int num_sub_dof_maps() const
11147
 
  {
11148
 
    return 1;
11149
 
  }
11150
 
 
11151
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
11152
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
11153
 
  {
11154
 
    return new hyperelasticity_0_dof_map_3();
11155
 
  }
11156
 
 
11157
 
};
11158
 
 
11159
 
/// This class defines the interface for a local-to-global mapping of
11160
 
/// degrees of freedom (dofs).
11161
 
 
11162
 
class hyperelasticity_0_dof_map_4: public ufc::dof_map
11163
 
{
11164
 
private:
11165
 
 
11166
 
  unsigned int __global_dimension;
11167
 
 
11168
 
public:
11169
 
 
11170
 
  /// Constructor
11171
 
  hyperelasticity_0_dof_map_4() : ufc::dof_map()
11172
 
  {
11173
 
    __global_dimension = 0;
11174
 
  }
11175
 
 
11176
 
  /// Destructor
11177
 
  virtual ~hyperelasticity_0_dof_map_4()
11178
 
  {
11179
 
    // Do nothing
11180
 
  }
11181
 
 
11182
 
  /// Return a string identifying the dof map
11183
 
  virtual const char* signature() const
11184
 
  {
11185
 
    return "FFC dof map for FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
11186
 
  }
11187
 
 
11188
 
  /// Return true iff mesh entities of topological dimension d are needed
11189
 
  virtual bool needs_mesh_entities(unsigned int d) const
11190
 
  {
11191
 
    switch ( d )
11192
 
    {
11193
 
    case 0:
11194
 
      return false;
11195
 
      break;
11196
 
    case 1:
11197
 
      return false;
11198
 
      break;
11199
 
    case 2:
11200
 
      return false;
11201
 
      break;
11202
 
    case 3:
11203
 
      return true;
11204
 
      break;
11205
 
    }
11206
 
    return false;
11207
 
  }
11208
 
 
11209
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
11210
 
  virtual bool init_mesh(const ufc::mesh& m)
11211
 
  {
11212
 
    __global_dimension = m.num_entities[3];
11213
 
    return false;
11214
 
  }
11215
 
 
11216
 
  /// Initialize dof map for given cell
11217
 
  virtual void init_cell(const ufc::mesh& m,
11218
 
                         const ufc::cell& c)
11219
 
  {
11220
 
    // Do nothing
11221
 
  }
11222
 
 
11223
 
  /// Finish initialization of dof map for cells
11224
 
  virtual void init_cell_finalize()
11225
 
  {
11226
 
    // Do nothing
11227
 
  }
11228
 
 
11229
 
  /// Return the dimension of the global finite element function space
11230
 
  virtual unsigned int global_dimension() const
11231
 
  {
11232
 
    return __global_dimension;
11233
 
  }
11234
 
 
11235
 
  /// Return the dimension of the local finite element function space for a cell
11236
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
11237
 
  {
11238
 
    return 1;
11239
 
  }
11240
 
 
11241
 
  /// Return the maximum dimension of the local finite element function space
11242
 
  virtual unsigned int max_local_dimension() const
11243
 
  {
11244
 
    return 1;
11245
 
  }
11246
 
 
11247
 
  // Return the geometric dimension of the coordinates this dof map provides
11248
 
  virtual unsigned int geometric_dimension() const
11249
 
  {
11250
 
    return 3;
11251
 
  }
11252
 
 
11253
 
  /// Return the number of dofs on each cell facet
11254
 
  virtual unsigned int num_facet_dofs() const
11255
 
  {
11256
 
    return 0;
11257
 
  }
11258
 
 
11259
 
  /// Return the number of dofs associated with each cell entity of dimension d
11260
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
11261
 
  {
11262
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
11263
 
  }
11264
 
 
11265
 
  /// Tabulate the local-to-global mapping of dofs on a cell
11266
 
  virtual void tabulate_dofs(unsigned int* dofs,
11267
 
                             const ufc::mesh& m,
11268
 
                             const ufc::cell& c) const
11269
 
  {
11270
 
    dofs[0] = c.entity_indices[3][0];
11271
 
  }
11272
 
 
11273
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
11274
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
11275
 
                                   unsigned int facet) const
11276
 
  {
11277
 
    switch ( facet )
11278
 
    {
11279
 
    case 0:
11280
 
      
11281
 
      break;
11282
 
    case 1:
11283
 
      
11284
 
      break;
11285
 
    case 2:
11286
 
      
11287
 
      break;
11288
 
    case 3:
11289
 
      
11290
 
      break;
11291
 
    }
11292
 
  }
11293
 
 
11294
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
11295
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
11296
 
                                    unsigned int d, unsigned int i) const
11297
 
  {
11298
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
11299
 
  }
11300
 
 
11301
 
  /// Tabulate the coordinates of all dofs on a cell
11302
 
  virtual void tabulate_coordinates(double** coordinates,
11303
 
                                    const ufc::cell& c) const
11304
 
  {
11305
 
    const double * const * x = c.coordinates;
11306
 
    coordinates[0][0] = 0.25*x[0][0] + 0.25*x[1][0] + 0.25*x[2][0] + 0.25*x[3][0];
11307
 
    coordinates[0][1] = 0.25*x[0][1] + 0.25*x[1][1] + 0.25*x[2][1] + 0.25*x[3][1];
11308
 
    coordinates[0][2] = 0.25*x[0][2] + 0.25*x[1][2] + 0.25*x[2][2] + 0.25*x[3][2];
11309
 
  }
11310
 
 
11311
 
  /// Return the number of sub dof maps (for a mixed element)
11312
 
  virtual unsigned int num_sub_dof_maps() const
11313
 
  {
11314
 
    return 1;
11315
 
  }
11316
 
 
11317
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
11318
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
11319
 
  {
11320
 
    return new hyperelasticity_0_dof_map_4();
11321
 
  }
11322
 
 
11323
 
};
11324
 
 
11325
 
/// This class defines the interface for the tabulation of the cell
11326
 
/// tensor corresponding to the local contribution to a form from
11327
 
/// the integral over a cell.
11328
 
 
11329
 
class hyperelasticity_0_cell_integral_0_quadrature: public ufc::cell_integral
11330
 
{
11331
 
public:
11332
 
 
11333
 
  /// Constructor
11334
 
  hyperelasticity_0_cell_integral_0_quadrature() : ufc::cell_integral()
11335
 
  {
11336
 
    // Do nothing
11337
 
  }
11338
 
 
11339
 
  /// Destructor
11340
 
  virtual ~hyperelasticity_0_cell_integral_0_quadrature()
11341
 
  {
11342
 
    // Do nothing
11343
 
  }
11344
 
 
11345
 
  /// Tabulate the tensor for the contribution from a local cell
11346
 
  virtual void tabulate_tensor(double* A,
11347
 
                               const double * const * w,
11348
 
                               const ufc::cell& c) const
11349
 
  {
11350
 
    // Extract vertex coordinates
11351
 
    const double * const * x = c.coordinates;
11352
 
    
11353
 
    // Compute Jacobian of affine map from reference cell
11354
 
    const double J_00 = x[1][0] - x[0][0];
11355
 
    const double J_01 = x[2][0] - x[0][0];
11356
 
    const double J_02 = x[3][0] - x[0][0];
11357
 
    const double J_10 = x[1][1] - x[0][1];
11358
 
    const double J_11 = x[2][1] - x[0][1];
11359
 
    const double J_12 = x[3][1] - x[0][1];
11360
 
    const double J_20 = x[1][2] - x[0][2];
11361
 
    const double J_21 = x[2][2] - x[0][2];
11362
 
    const double J_22 = x[3][2] - x[0][2];
11363
 
    
11364
 
    // Compute sub determinants
11365
 
    const double d_00 = J_11*J_22 - J_12*J_21;
11366
 
    const double d_01 = J_12*J_20 - J_10*J_22;
11367
 
    const double d_02 = J_10*J_21 - J_11*J_20;
11368
 
    
11369
 
    const double d_10 = J_02*J_21 - J_01*J_22;
11370
 
    const double d_11 = J_00*J_22 - J_02*J_20;
11371
 
    const double d_12 = J_01*J_20 - J_00*J_21;
11372
 
    
11373
 
    const double d_20 = J_01*J_12 - J_02*J_11;
11374
 
    const double d_21 = J_02*J_10 - J_00*J_12;
11375
 
    const double d_22 = J_00*J_11 - J_01*J_10;
11376
 
    
11377
 
    // Compute determinant of Jacobian
11378
 
    double detJ = J_00*d_00 + J_10*d_10 + J_20*d_20;
11379
 
    
11380
 
    // Compute inverse of Jacobian
11381
 
    const double Jinv_00 = d_00 / detJ;
11382
 
    const double Jinv_01 = d_10 / detJ;
11383
 
    const double Jinv_02 = d_20 / detJ;
11384
 
    const double Jinv_10 = d_01 / detJ;
11385
 
    const double Jinv_11 = d_11 / detJ;
11386
 
    const double Jinv_12 = d_21 / detJ;
11387
 
    const double Jinv_20 = d_02 / detJ;
11388
 
    const double Jinv_21 = d_12 / detJ;
11389
 
    const double Jinv_22 = d_22 / detJ;
11390
 
    
11391
 
    // Set scale factor
11392
 
    const double det = std::abs(detJ);
11393
 
    
11394
 
    
11395
 
    // Array of quadrature weights
11396
 
    static const double W1 = 0.166666667;
11397
 
    // Quadrature points on the UFC reference element: (0.25, 0.25, 0.25)
11398
 
    
11399
 
    // Value of basis functions at quadrature points.
11400
 
    static const double FE1_C0_D001[1][12] = \
11401
 
    {{-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}};
11402
 
    
11403
 
    static const double FE1_C0_D010[1][12] = \
11404
 
    {{-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
11405
 
    
11406
 
    static const double FE1_C0_D100[1][12] = \
11407
 
    {{-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
11408
 
    
11409
 
    static const double FE1_C1_D001[1][12] = \
11410
 
    {{0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0}};
11411
 
    
11412
 
    static const double FE1_C1_D010[1][12] = \
11413
 
    {{0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0}};
11414
 
    
11415
 
    static const double FE1_C1_D100[1][12] = \
11416
 
    {{0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0}};
11417
 
    
11418
 
    static const double FE1_C2_D001[1][12] = \
11419
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1}};
11420
 
    
11421
 
    static const double FE1_C2_D010[1][12] = \
11422
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0}};
11423
 
    
11424
 
    static const double FE1_C2_D100[1][12] = \
11425
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0}};
11426
 
    
11427
 
    
11428
 
    // Compute element tensor using UFL quadrature representation
11429
 
    // Optimisations: ('simplify expressions', False), ('ignore zero tables', False), ('non zero columns', False), ('remove zero terms', False), ('ignore ones', False)
11430
 
    // Total number of operations to compute element tensor: 776808
11431
 
    
11432
 
    // Loop quadrature points for integral
11433
 
    // Number of operations to compute element tensor for following IP loop = 776808
11434
 
    // Only 1 integration point, omitting IP loop.
11435
 
    
11436
 
    // Function declarations
11437
 
    double F0 = 0;
11438
 
    double F1 = 0;
11439
 
    double F2 = 0;
11440
 
    double F3 = 0;
11441
 
    double F4 = 0;
11442
 
    double F5 = 0;
11443
 
    double F6 = 0;
11444
 
    double F7 = 0;
11445
 
    double F8 = 0;
11446
 
    
11447
 
    // Total number of operations to compute function values = 216
11448
 
    for (unsigned int r = 0; r < 12; r++)
11449
 
    {
11450
 
      F0 += FE1_C0_D100[0][r]*w[0][r];
11451
 
      F1 += FE1_C0_D010[0][r]*w[0][r];
11452
 
      F2 += FE1_C0_D001[0][r]*w[0][r];
11453
 
      F3 += FE1_C1_D100[0][r]*w[0][r];
11454
 
      F4 += FE1_C1_D010[0][r]*w[0][r];
11455
 
      F5 += FE1_C1_D001[0][r]*w[0][r];
11456
 
      F6 += FE1_C2_D100[0][r]*w[0][r];
11457
 
      F7 += FE1_C2_D010[0][r]*w[0][r];
11458
 
      F8 += FE1_C2_D001[0][r]*w[0][r];
11459
 
    }// end loop over 'r'
11460
 
    
11461
 
    // Number of operations for primary indices: 776592
11462
 
    for (unsigned int j = 0; j < 12; j++)
11463
 
    {
11464
 
      for (unsigned int k = 0; k < 12; k++)
11465
 
      {
11466
 
        // Number of operations to compute entry: 5393
11467
 
        A[j*12 + k] += (((((Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2)) + (2*(2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2)*w[1][0] + ((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)) + (2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2) + 2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))))*(Jinv_00*FE1_C2_D100[0][j] + Jinv_10*FE1_C2_D010[0][j] + Jinv_20*FE1_C2_D001[0][j]) + ((2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2)) + ((Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2) + 2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + ((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2)) + (2*(2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2)*w[1][0] + ((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)))*(Jinv_00*FE1_C1_D100[0][j] + Jinv_10*FE1_C1_D010[0][j] + Jinv_20*FE1_C1_D001[0][j]) + (((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2) + 2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((2*(2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2)*w[1][0] + ((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2))) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*w[1][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2) + 2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))*(Jinv_00*FE1_C0_D100[0][j] + Jinv_10*FE1_C0_D010[0][j] + Jinv_20*FE1_C0_D001[0][j])) + (((2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*w[1][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2)) + ((((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2)*w[1][0])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))) + ((Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*w[1][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + 2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)))*(Jinv_02*FE1_C2_D100[0][j] + Jinv_12*FE1_C2_D010[0][j] + Jinv_22*FE1_C2_D001[0][j]) + (((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*w[1][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + 2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + (2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*w[1][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2)) + ((((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2)*w[1][0])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))))*(Jinv_02*FE1_C1_D100[0][j] + Jinv_12*FE1_C1_D010[0][j] + Jinv_22*FE1_C1_D001[0][j]) + (((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2)) + (((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2)*w[1][0])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*w[1][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + 2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)) + ((Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*w[1][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + 2*(((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))/(2)*w[1][0]*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))))*(Jinv_02*FE1_C0_D100[0][j] + Jinv_12*FE1_C0_D010[0][j] + Jinv_22*FE1_C0_D001[0][j])) + ((((Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2) + 2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + (2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2)) + (((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2)*w[1][0])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)))*(Jinv_01*FE1_C2_D100[0][j] + Jinv_11*FE1_C2_D010[0][j] + Jinv_21*FE1_C2_D001[0][j]) + (((Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2)) + (((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2)*w[1][0])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + ((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + 2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2) + 2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)))*(Jinv_01*FE1_C1_D100[0][j] + Jinv_11*FE1_C1_D010[0][j] + Jinv_21*FE1_C1_D001[0][j]) + (((Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + 2*(((Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + (Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)))/(2)*w[1][0]*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*w[1][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2) + 2*(((Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)) + ((Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)) + ((Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)))/(2)*w[1][0]*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)) + ((((2*(Jinv_02*FE1_C1_D100[0][k] + Jinv_12*FE1_C1_D010[0][k] + Jinv_22*FE1_C1_D001[0][k])*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + 2*(Jinv_02*FE1_C2_D100[0][k] + Jinv_12*FE1_C2_D010[0][k] + Jinv_22*FE1_C2_D001[0][k])*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + 2*(Jinv_02*FE1_C0_D100[0][k] + Jinv_12*FE1_C0_D010[0][k] + Jinv_22*FE1_C0_D001[0][k])*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2))/(2) + (2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (2*(Jinv_00*FE1_C1_D100[0][k] + Jinv_10*FE1_C1_D010[0][k] + Jinv_20*FE1_C1_D001[0][k])*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + 2*(Jinv_00*FE1_C0_D100[0][k] + Jinv_10*FE1_C0_D010[0][k] + Jinv_20*FE1_C0_D001[0][k])*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)) + 2*(Jinv_00*FE1_C2_D100[0][k] + Jinv_10*FE1_C2_D010[0][k] + Jinv_20*FE1_C2_D001[0][k])*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8))/(2))*2*w[2][0]/(2) + 2*(2*(Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + 2*(Jinv_01*FE1_C1_D100[0][k] + Jinv_11*FE1_C1_D010[0][k] + Jinv_21*FE1_C1_D001[0][k])*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + 2*(Jinv_01*FE1_C2_D100[0][k] + Jinv_11*FE1_C2_D010[0][k] + Jinv_21*FE1_C2_D001[0][k])*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2)*w[1][0])*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_01*FE1_C0_D100[0][k] + Jinv_11*FE1_C0_D010[0][k] + Jinv_21*FE1_C0_D001[0][k])*(w[2][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[1][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2))))*(Jinv_01*FE1_C0_D100[0][j] + Jinv_11*FE1_C0_D010[0][j] + Jinv_21*FE1_C0_D001[0][j])))*W1*det;
11468
 
      }// end loop over 'k'
11469
 
    }// end loop over 'j'
11470
 
  }
11471
 
 
11472
 
};
11473
 
 
11474
 
/// This class defines the interface for the tabulation of the cell
11475
 
/// tensor corresponding to the local contribution to a form from
11476
 
/// the integral over a cell.
11477
 
 
11478
 
class hyperelasticity_0_cell_integral_0: public ufc::cell_integral
11479
 
{
11480
 
private:
11481
 
 
11482
 
  hyperelasticity_0_cell_integral_0_quadrature integral_0_quadrature;
11483
 
 
11484
 
public:
11485
 
 
11486
 
  /// Constructor
11487
 
  hyperelasticity_0_cell_integral_0() : ufc::cell_integral()
11488
 
  {
11489
 
    // Do nothing
11490
 
  }
11491
 
 
11492
 
  /// Destructor
11493
 
  virtual ~hyperelasticity_0_cell_integral_0()
11494
 
  {
11495
 
    // Do nothing
11496
 
  }
11497
 
 
11498
 
  /// Tabulate the tensor for the contribution from a local cell
11499
 
  virtual void tabulate_tensor(double* A,
11500
 
                               const double * const * w,
11501
 
                               const ufc::cell& c) const
11502
 
  {
11503
 
    // Reset values of the element tensor block
11504
 
    for (unsigned int j = 0; j < 144; j++)
11505
 
      A[j] = 0;
11506
 
    
11507
 
    // Add all contributions to element tensor
11508
 
    integral_0_quadrature.tabulate_tensor(A, w, c);
11509
 
  }
11510
 
 
11511
 
};
11512
 
 
11513
 
/// This class defines the interface for the assembly of the global
11514
 
/// tensor corresponding to a form with r + n arguments, that is, a
11515
 
/// mapping
11516
 
///
11517
 
///     a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
11518
 
///
11519
 
/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
11520
 
/// global tensor A is defined by
11521
 
///
11522
 
///     A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
11523
 
///
11524
 
/// where each argument Vj represents the application to the
11525
 
/// sequence of basis functions of Vj and w1, w2, ..., wn are given
11526
 
/// fixed functions (coefficients).
11527
 
 
11528
 
class hyperelasticity_form_0: public ufc::form
11529
 
{
11530
 
public:
11531
 
 
11532
 
  /// Constructor
11533
 
  hyperelasticity_form_0() : ufc::form()
11534
 
  {
11535
 
    // Do nothing
11536
 
  }
11537
 
 
11538
 
  /// Destructor
11539
 
  virtual ~hyperelasticity_form_0()
11540
 
  {
11541
 
    // Do nothing
11542
 
  }
11543
 
 
11544
 
  /// Return a string identifying the form
11545
 
  virtual const char* signature() const
11546
 
  {
11547
 
    return "Form([Integral(IndexSum(IndexSum(Product(Indexed(ComponentTensor(IndexSum(Sum(Product(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(0),), {Index(0): 3})), MultiIndex((Index(1),), {Index(1): 3})), MultiIndex((Index(1), Index(0)), {Index(0): 3, Index(1): 3})), MultiIndex((Index(2), Index(3)), {Index(2): 3, Index(3): 3})), Indexed(Sum(ComponentTensor(Product(Constant(Cell('tetrahedron', 1, Space(3)), 1), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Indexed(IndexSum(Sum(ComponentTensor(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(8), Index(9), Index(10), Index(11)), {Index(11): 3, Index(8): 3, Index(9): 3, Index(10): 3})), MultiIndex((Index(10), Index(11)), {Index(11): 3, Index(10): 3})), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3})), Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(9), Index(27)), {Index(9): 3, Index(27): 3}))), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3})), ComponentTensor(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(9), Index(27), Index(28), Index(29)), {Index(29): 3, Index(9): 3, Index(28): 3, Index(27): 3})), MultiIndex((Index(28), Index(29)), {Index(29): 3, Index(28): 3})), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3})), Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(8), Index(9)), {Index(8): 3, Index(9): 3}))), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3}))), MultiIndex((Index(9),), {Index(9): 3})), MultiIndex((Index(32), Index(33)), {Index(33): 3, Index(32): 3})), MultiIndex((Index(8), Index(27), Index(32), Index(33)), {Index(33): 3, Index(27): 3, Index(32): 3, Index(8): 3})), MultiIndex((Index(34), Index(34), Index(35), Index(36)), {Index(35): 3, Index(36): 3, Index(34): 3})), MultiIndex((Index(35), Index(36)), {Index(35): 3, Index(36): 3})), MultiIndex((Index(34),), {Index(34): 3})), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3}))), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3})), ComponentTensor(Product(Division(Constant(Cell('tetrahedron', 1, Space(3)), 2), IntValue(2, (), (), {})), Indexed(ComponentTensor(Product(IndexSum(Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(39), Index(39)), {Index(39): 3})), MultiIndex((Index(39),), {Index(39): 3})), Indexed(ComponentTensor(Product(IntValue(2, (), (), {}), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(39), Index(39), Index(40), Index(41)), {Index(40): 3, Index(41): 3, Index(39): 3})), MultiIndex((Index(40), Index(41)), {Index(40): 3, Index(41): 3})), MultiIndex((Index(39),), {Index(39): 3})), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3}))), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3})), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3}))), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3})), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(3), Index(48)), {Index(48): 3, Index(3): 3}))), Product(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(0),), {Index(0): 3})), MultiIndex((Index(1),), {Index(1): 3})), MultiIndex((Index(1), Index(0)), {Index(0): 3, Index(1): 3})), Identity(3)), MultiIndex((Index(2), Index(3)), {Index(2): 3, Index(3): 3})), Indexed(Sum(ComponentTensor(Product(Constant(Cell('tetrahedron', 1, Space(3)), 1), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Indexed(IndexSum(Sum(ComponentTensor(Product(Indexed(ComponentTensor(Division(Indexed(ComponentTensor(IndexSum(Sum(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), Product(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3})), Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), MultiIndex((Index(9), Index(27)), {Index(9): 3, Index(27): 3})), Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(8), Index(9), Index(10), Index(11)), {Index(11): 3, Index(8): 3, Index(9): 3, Index(10): 3})), MultiIndex((Index(10), Index(11)), {Index(11): 3, Index(10): 3})), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3}))), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3})), ComponentTensor(Product(Indexed(ComponentTensor(Division(Indexed(ComponentTensor(IndexSum(Sum(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), Product(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3})), Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), MultiIndex((Index(8), Index(9)), {Index(8): 3, Index(9): 3})), Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(9), Index(27), Index(28), Index(29)), {Index(29): 3, Index(9): 3, Index(28): 3, Index(27): 3})), MultiIndex((Index(28), Index(29)), {Index(29): 3, Index(28): 3})), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3}))), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3}))), MultiIndex((Index(9),), {Index(9): 3})), MultiIndex((Index(32), Index(33)), {Index(33): 3, Index(32): 3})), MultiIndex((Index(8), Index(27), Index(32), Index(33)), {Index(33): 3, Index(27): 3, Index(32): 3, Index(8): 3})), MultiIndex((Index(34), Index(34), Index(35), Index(36)), {Index(35): 3, Index(36): 3, Index(34): 3})), MultiIndex((Index(35), Index(36)), {Index(35): 3, Index(36): 3})), MultiIndex((Index(34),), {Index(34): 3})), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3}))), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3})), ComponentTensor(Product(Division(Constant(Cell('tetrahedron', 1, Space(3)), 2), IntValue(2, (), (), {})), Indexed(ComponentTensor(Product(IndexSum(Indexed(ComponentTensor(Division(Indexed(ComponentTensor(IndexSum(Sum(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), Product(Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3})), Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), MultiIndex((Index(39), Index(39)), {Index(39): 3})), MultiIndex((Index(39),), {Index(39): 3})), Indexed(ComponentTensor(Product(IntValue(2, (), (), {}), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(39), Index(39), Index(40), Index(41)), {Index(40): 3, Index(41): 3, Index(39): 3})), MultiIndex((Index(40), Index(41)), {Index(40): 3, Index(41): 3})), MultiIndex((Index(39),), {Index(39): 3})), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3}))), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3})), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3}))), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3})), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(3), Index(48)), {Index(48): 3, Index(3): 3})))), MultiIndex((Index(3),), {Index(3): 3})), MultiIndex((Index(2), Index(48)), {Index(48): 3, Index(2): 3})), MultiIndex((Index(49), Index(50)), {Index(50): 3, Index(49): 3})), Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(51),), {Index(51): 3})), MultiIndex((Index(52),), {Index(52): 3})), MultiIndex((Index(52), Index(51)), {Index(52): 3, Index(51): 3})), MultiIndex((Index(49), Index(50)), {Index(50): 3, Index(49): 3}))), MultiIndex((Index(49),), {Index(49): 3})), MultiIndex((Index(50),), {Index(50): 3})), Measure('cell', 0, None))])";
11548
 
  }
11549
 
 
11550
 
  /// Return the rank of the global tensor (r)
11551
 
  virtual unsigned int rank() const
11552
 
  {
11553
 
    return 2;
11554
 
  }
11555
 
 
11556
 
  /// Return the number of coefficients (n)
11557
 
  virtual unsigned int num_coefficients() const
11558
 
  {
11559
 
    return 3;
11560
 
  }
11561
 
 
11562
 
  /// Return the number of cell integrals
11563
 
  virtual unsigned int num_cell_integrals() const
11564
 
  {
11565
 
    return 1;
11566
 
  }
11567
 
 
11568
 
  /// Return the number of exterior facet integrals
11569
 
  virtual unsigned int num_exterior_facet_integrals() const
11570
 
  {
11571
 
    return 0;
11572
 
  }
11573
 
 
11574
 
  /// Return the number of interior facet integrals
11575
 
  virtual unsigned int num_interior_facet_integrals() const
11576
 
  {
11577
 
    return 0;
11578
 
  }
11579
 
 
11580
 
  /// Create a new finite element for argument function i
11581
 
  virtual ufc::finite_element* create_finite_element(unsigned int i) const
11582
 
  {
11583
 
    switch ( i )
11584
 
    {
11585
 
    case 0:
11586
 
      return new hyperelasticity_0_finite_element_0();
11587
 
      break;
11588
 
    case 1:
11589
 
      return new hyperelasticity_0_finite_element_1();
11590
 
      break;
11591
 
    case 2:
11592
 
      return new hyperelasticity_0_finite_element_2();
11593
 
      break;
11594
 
    case 3:
11595
 
      return new hyperelasticity_0_finite_element_3();
11596
 
      break;
11597
 
    case 4:
11598
 
      return new hyperelasticity_0_finite_element_4();
11599
 
      break;
11600
 
    }
11601
 
    return 0;
11602
 
  }
11603
 
 
11604
 
  /// Create a new dof map for argument function i
11605
 
  virtual ufc::dof_map* create_dof_map(unsigned int i) const
11606
 
  {
11607
 
    switch ( i )
11608
 
    {
11609
 
    case 0:
11610
 
      return new hyperelasticity_0_dof_map_0();
11611
 
      break;
11612
 
    case 1:
11613
 
      return new hyperelasticity_0_dof_map_1();
11614
 
      break;
11615
 
    case 2:
11616
 
      return new hyperelasticity_0_dof_map_2();
11617
 
      break;
11618
 
    case 3:
11619
 
      return new hyperelasticity_0_dof_map_3();
11620
 
      break;
11621
 
    case 4:
11622
 
      return new hyperelasticity_0_dof_map_4();
11623
 
      break;
11624
 
    }
11625
 
    return 0;
11626
 
  }
11627
 
 
11628
 
  /// Create a new cell integral on sub domain i
11629
 
  virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
11630
 
  {
11631
 
    return new hyperelasticity_0_cell_integral_0();
11632
 
  }
11633
 
 
11634
 
  /// Create a new exterior facet integral on sub domain i
11635
 
  virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
11636
 
  {
11637
 
    return 0;
11638
 
  }
11639
 
 
11640
 
  /// Create a new interior facet integral on sub domain i
11641
 
  virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
11642
 
  {
11643
 
    return 0;
11644
 
  }
11645
 
 
11646
 
};
11647
 
 
11648
 
/// This class defines the interface for a finite element.
11649
 
 
11650
 
class hyperelasticity_1_finite_element_0_0: public ufc::finite_element
11651
 
{
11652
 
public:
11653
 
 
11654
 
  /// Constructor
11655
 
  hyperelasticity_1_finite_element_0_0() : ufc::finite_element()
11656
 
  {
11657
 
    // Do nothing
11658
 
  }
11659
 
 
11660
 
  /// Destructor
11661
 
  virtual ~hyperelasticity_1_finite_element_0_0()
11662
 
  {
11663
 
    // Do nothing
11664
 
  }
11665
 
 
11666
 
  /// Return a string identifying the finite element
11667
 
  virtual const char* signature() const
11668
 
  {
11669
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
11670
 
  }
11671
 
 
11672
 
  /// Return the cell shape
11673
 
  virtual ufc::shape cell_shape() const
11674
 
  {
11675
 
    return ufc::tetrahedron;
11676
 
  }
11677
 
 
11678
 
  /// Return the dimension of the finite element function space
11679
 
  virtual unsigned int space_dimension() const
11680
 
  {
11681
 
    return 4;
11682
 
  }
11683
 
 
11684
 
  /// Return the rank of the value space
11685
 
  virtual unsigned int value_rank() const
11686
 
  {
11687
 
    return 0;
11688
 
  }
11689
 
 
11690
 
  /// Return the dimension of the value space for axis i
11691
 
  virtual unsigned int value_dimension(unsigned int i) const
11692
 
  {
11693
 
    return 1;
11694
 
  }
11695
 
 
11696
 
  /// Evaluate basis function i at given point in cell
11697
 
  virtual void evaluate_basis(unsigned int i,
11698
 
                              double* values,
11699
 
                              const double* coordinates,
11700
 
                              const ufc::cell& c) const
11701
 
  {
11702
 
    // Extract vertex coordinates
11703
 
    const double * const * element_coordinates = c.coordinates;
11704
 
    
11705
 
    // Compute Jacobian of affine map from reference cell
11706
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
11707
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
11708
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
11709
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
11710
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
11711
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
11712
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
11713
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
11714
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
11715
 
    
11716
 
    // Compute sub determinants
11717
 
    const double d00 = J_11*J_22 - J_12*J_21;
11718
 
    const double d01 = J_12*J_20 - J_10*J_22;
11719
 
    const double d02 = J_10*J_21 - J_11*J_20;
11720
 
    
11721
 
    const double d10 = J_02*J_21 - J_01*J_22;
11722
 
    const double d11 = J_00*J_22 - J_02*J_20;
11723
 
    const double d12 = J_01*J_20 - J_00*J_21;
11724
 
    
11725
 
    const double d20 = J_01*J_12 - J_02*J_11;
11726
 
    const double d21 = J_02*J_10 - J_00*J_12;
11727
 
    const double d22 = J_00*J_11 - J_01*J_10;
11728
 
    
11729
 
    // Compute determinant of Jacobian
11730
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
11731
 
    
11732
 
    // Compute inverse of Jacobian
11733
 
    
11734
 
    // Compute constants
11735
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
11736
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
11737
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
11738
 
    
11739
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
11740
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
11741
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
11742
 
    
11743
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
11744
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
11745
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
11746
 
    
11747
 
    // Get coordinates and map to the UFC reference element
11748
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
11749
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
11750
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
11751
 
    
11752
 
    // Map coordinates to the reference cube
11753
 
    if (std::abs(y + z - 1.0) < 1e-08)
11754
 
      x = 1.0;
11755
 
    else
11756
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
11757
 
    if (std::abs(z - 1.0) < 1e-08)
11758
 
      y = -1.0;
11759
 
    else
11760
 
      y = 2.0 * y/(1.0 - z) - 1.0;
11761
 
    z = 2.0 * z - 1.0;
11762
 
    
11763
 
    // Reset values
11764
 
    *values = 0;
11765
 
    
11766
 
    // Map degree of freedom to element degree of freedom
11767
 
    const unsigned int dof = i;
11768
 
    
11769
 
    // Generate scalings
11770
 
    const double scalings_y_0 = 1;
11771
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
11772
 
    const double scalings_z_0 = 1;
11773
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
11774
 
    
11775
 
    // Compute psitilde_a
11776
 
    const double psitilde_a_0 = 1;
11777
 
    const double psitilde_a_1 = x;
11778
 
    
11779
 
    // Compute psitilde_bs
11780
 
    const double psitilde_bs_0_0 = 1;
11781
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
11782
 
    const double psitilde_bs_1_0 = 1;
11783
 
    
11784
 
    // Compute psitilde_cs
11785
 
    const double psitilde_cs_00_0 = 1;
11786
 
    const double psitilde_cs_00_1 = 2*z + 1;
11787
 
    const double psitilde_cs_01_0 = 1;
11788
 
    const double psitilde_cs_10_0 = 1;
11789
 
    
11790
 
    // Compute basisvalues
11791
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
11792
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
11793
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
11794
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
11795
 
    
11796
 
    // Table(s) of coefficients
11797
 
    static const double coefficients0[4][4] = \
11798
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
11799
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
11800
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
11801
 
    {0.288675135, 0, 0, 0.223606798}};
11802
 
    
11803
 
    // Extract relevant coefficients
11804
 
    const double coeff0_0 = coefficients0[dof][0];
11805
 
    const double coeff0_1 = coefficients0[dof][1];
11806
 
    const double coeff0_2 = coefficients0[dof][2];
11807
 
    const double coeff0_3 = coefficients0[dof][3];
11808
 
    
11809
 
    // Compute value(s)
11810
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
11811
 
  }
11812
 
 
11813
 
  /// Evaluate all basis functions at given point in cell
11814
 
  virtual void evaluate_basis_all(double* values,
11815
 
                                  const double* coordinates,
11816
 
                                  const ufc::cell& c) const
11817
 
  {
11818
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
11819
 
  }
11820
 
 
11821
 
  /// Evaluate order n derivatives of basis function i at given point in cell
11822
 
  virtual void evaluate_basis_derivatives(unsigned int i,
11823
 
                                          unsigned int n,
11824
 
                                          double* values,
11825
 
                                          const double* coordinates,
11826
 
                                          const ufc::cell& c) const
11827
 
  {
11828
 
    // Extract vertex coordinates
11829
 
    const double * const * element_coordinates = c.coordinates;
11830
 
    
11831
 
    // Compute Jacobian of affine map from reference cell
11832
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
11833
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
11834
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
11835
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
11836
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
11837
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
11838
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
11839
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
11840
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
11841
 
    
11842
 
    // Compute sub determinants
11843
 
    const double d00 = J_11*J_22 - J_12*J_21;
11844
 
    const double d01 = J_12*J_20 - J_10*J_22;
11845
 
    const double d02 = J_10*J_21 - J_11*J_20;
11846
 
    
11847
 
    const double d10 = J_02*J_21 - J_01*J_22;
11848
 
    const double d11 = J_00*J_22 - J_02*J_20;
11849
 
    const double d12 = J_01*J_20 - J_00*J_21;
11850
 
    
11851
 
    const double d20 = J_01*J_12 - J_02*J_11;
11852
 
    const double d21 = J_02*J_10 - J_00*J_12;
11853
 
    const double d22 = J_00*J_11 - J_01*J_10;
11854
 
    
11855
 
    // Compute determinant of Jacobian
11856
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
11857
 
    
11858
 
    // Compute inverse of Jacobian
11859
 
    
11860
 
    // Compute constants
11861
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
11862
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
11863
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
11864
 
    
11865
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
11866
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
11867
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
11868
 
    
11869
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
11870
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
11871
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
11872
 
    
11873
 
    // Get coordinates and map to the UFC reference element
11874
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
11875
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
11876
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
11877
 
    
11878
 
    // Map coordinates to the reference cube
11879
 
    if (std::abs(y + z - 1.0) < 1e-08)
11880
 
      x = 1.0;
11881
 
    else
11882
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
11883
 
    if (std::abs(z - 1.0) < 1e-08)
11884
 
      y = -1.0;
11885
 
    else
11886
 
      y = 2.0 * y/(1.0 - z) - 1.0;
11887
 
    z = 2.0 * z - 1.0;
11888
 
    
11889
 
    // Compute number of derivatives
11890
 
    unsigned int num_derivatives = 1;
11891
 
    
11892
 
    for (unsigned int j = 0; j < n; j++)
11893
 
      num_derivatives *= 3;
11894
 
    
11895
 
    
11896
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
11897
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
11898
 
    
11899
 
    for (unsigned int j = 0; j < num_derivatives; j++)
11900
 
    {
11901
 
      combinations[j] = new unsigned int [n];
11902
 
      for (unsigned int k = 0; k < n; k++)
11903
 
        combinations[j][k] = 0;
11904
 
    }
11905
 
    
11906
 
    // Generate combinations of derivatives
11907
 
    for (unsigned int row = 1; row < num_derivatives; row++)
11908
 
    {
11909
 
      for (unsigned int num = 0; num < row; num++)
11910
 
      {
11911
 
        for (unsigned int col = n-1; col+1 > 0; col--)
11912
 
        {
11913
 
          if (combinations[row][col] + 1 > 2)
11914
 
            combinations[row][col] = 0;
11915
 
          else
11916
 
          {
11917
 
            combinations[row][col] += 1;
11918
 
            break;
11919
 
          }
11920
 
        }
11921
 
      }
11922
 
    }
11923
 
    
11924
 
    // Compute inverse of Jacobian
11925
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
11926
 
    
11927
 
    // Declare transformation matrix
11928
 
    // Declare pointer to two dimensional array and initialise
11929
 
    double **transform = new double *[num_derivatives];
11930
 
    
11931
 
    for (unsigned int j = 0; j < num_derivatives; j++)
11932
 
    {
11933
 
      transform[j] = new double [num_derivatives];
11934
 
      for (unsigned int k = 0; k < num_derivatives; k++)
11935
 
        transform[j][k] = 1;
11936
 
    }
11937
 
    
11938
 
    // Construct transformation matrix
11939
 
    for (unsigned int row = 0; row < num_derivatives; row++)
11940
 
    {
11941
 
      for (unsigned int col = 0; col < num_derivatives; col++)
11942
 
      {
11943
 
        for (unsigned int k = 0; k < n; k++)
11944
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
11945
 
      }
11946
 
    }
11947
 
    
11948
 
    // Reset values
11949
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
11950
 
      values[j] = 0;
11951
 
    
11952
 
    // Map degree of freedom to element degree of freedom
11953
 
    const unsigned int dof = i;
11954
 
    
11955
 
    // Generate scalings
11956
 
    const double scalings_y_0 = 1;
11957
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
11958
 
    const double scalings_z_0 = 1;
11959
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
11960
 
    
11961
 
    // Compute psitilde_a
11962
 
    const double psitilde_a_0 = 1;
11963
 
    const double psitilde_a_1 = x;
11964
 
    
11965
 
    // Compute psitilde_bs
11966
 
    const double psitilde_bs_0_0 = 1;
11967
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
11968
 
    const double psitilde_bs_1_0 = 1;
11969
 
    
11970
 
    // Compute psitilde_cs
11971
 
    const double psitilde_cs_00_0 = 1;
11972
 
    const double psitilde_cs_00_1 = 2*z + 1;
11973
 
    const double psitilde_cs_01_0 = 1;
11974
 
    const double psitilde_cs_10_0 = 1;
11975
 
    
11976
 
    // Compute basisvalues
11977
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
11978
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
11979
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
11980
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
11981
 
    
11982
 
    // Table(s) of coefficients
11983
 
    static const double coefficients0[4][4] = \
11984
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
11985
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
11986
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
11987
 
    {0.288675135, 0, 0, 0.223606798}};
11988
 
    
11989
 
    // Interesting (new) part
11990
 
    // Tables of derivatives of the polynomial base (transpose)
11991
 
    static const double dmats0[4][4] = \
11992
 
    {{0, 0, 0, 0},
11993
 
    {6.32455532, 0, 0, 0},
11994
 
    {0, 0, 0, 0},
11995
 
    {0, 0, 0, 0}};
11996
 
    
11997
 
    static const double dmats1[4][4] = \
11998
 
    {{0, 0, 0, 0},
11999
 
    {3.16227766, 0, 0, 0},
12000
 
    {5.47722558, 0, 0, 0},
12001
 
    {0, 0, 0, 0}};
12002
 
    
12003
 
    static const double dmats2[4][4] = \
12004
 
    {{0, 0, 0, 0},
12005
 
    {3.16227766, 0, 0, 0},
12006
 
    {1.82574186, 0, 0, 0},
12007
 
    {5.16397779, 0, 0, 0}};
12008
 
    
12009
 
    // Compute reference derivatives
12010
 
    // Declare pointer to array of derivatives on FIAT element
12011
 
    double *derivatives = new double [num_derivatives];
12012
 
    
12013
 
    // Declare coefficients
12014
 
    double coeff0_0 = 0;
12015
 
    double coeff0_1 = 0;
12016
 
    double coeff0_2 = 0;
12017
 
    double coeff0_3 = 0;
12018
 
    
12019
 
    // Declare new coefficients
12020
 
    double new_coeff0_0 = 0;
12021
 
    double new_coeff0_1 = 0;
12022
 
    double new_coeff0_2 = 0;
12023
 
    double new_coeff0_3 = 0;
12024
 
    
12025
 
    // Loop possible derivatives
12026
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
12027
 
    {
12028
 
      // Get values from coefficients array
12029
 
      new_coeff0_0 = coefficients0[dof][0];
12030
 
      new_coeff0_1 = coefficients0[dof][1];
12031
 
      new_coeff0_2 = coefficients0[dof][2];
12032
 
      new_coeff0_3 = coefficients0[dof][3];
12033
 
    
12034
 
      // Loop derivative order
12035
 
      for (unsigned int j = 0; j < n; j++)
12036
 
      {
12037
 
        // Update old coefficients
12038
 
        coeff0_0 = new_coeff0_0;
12039
 
        coeff0_1 = new_coeff0_1;
12040
 
        coeff0_2 = new_coeff0_2;
12041
 
        coeff0_3 = new_coeff0_3;
12042
 
    
12043
 
        if(combinations[deriv_num][j] == 0)
12044
 
        {
12045
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
12046
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
12047
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
12048
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
12049
 
        }
12050
 
        if(combinations[deriv_num][j] == 1)
12051
 
        {
12052
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
12053
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
12054
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
12055
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
12056
 
        }
12057
 
        if(combinations[deriv_num][j] == 2)
12058
 
        {
12059
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
12060
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
12061
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
12062
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
12063
 
        }
12064
 
    
12065
 
      }
12066
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
12067
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
12068
 
    }
12069
 
    
12070
 
    // Transform derivatives back to physical element
12071
 
    for (unsigned int row = 0; row < num_derivatives; row++)
12072
 
    {
12073
 
      for (unsigned int col = 0; col < num_derivatives; col++)
12074
 
      {
12075
 
        values[row] += transform[row][col]*derivatives[col];
12076
 
      }
12077
 
    }
12078
 
    // Delete pointer to array of derivatives on FIAT element
12079
 
    delete [] derivatives;
12080
 
    
12081
 
    // Delete pointer to array of combinations of derivatives and transform
12082
 
    for (unsigned int row = 0; row < num_derivatives; row++)
12083
 
    {
12084
 
      delete [] combinations[row];
12085
 
      delete [] transform[row];
12086
 
    }
12087
 
    
12088
 
    delete [] combinations;
12089
 
    delete [] transform;
12090
 
  }
12091
 
 
12092
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
12093
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
12094
 
                                              double* values,
12095
 
                                              const double* coordinates,
12096
 
                                              const ufc::cell& c) const
12097
 
  {
12098
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
12099
 
  }
12100
 
 
12101
 
  /// Evaluate linear functional for dof i on the function f
12102
 
  virtual double evaluate_dof(unsigned int i,
12103
 
                              const ufc::function& f,
12104
 
                              const ufc::cell& c) const
12105
 
  {
12106
 
    // The reference points, direction and weights:
12107
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
12108
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
12109
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
12110
 
    
12111
 
    const double * const * x = c.coordinates;
12112
 
    double result = 0.0;
12113
 
    // Iterate over the points:
12114
 
    // Evaluate basis functions for affine mapping
12115
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
12116
 
    const double w1 = X[i][0][0];
12117
 
    const double w2 = X[i][0][1];
12118
 
    const double w3 = X[i][0][2];
12119
 
    
12120
 
    // Compute affine mapping y = F(X)
12121
 
    double y[3];
12122
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
12123
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
12124
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
12125
 
    
12126
 
    // Evaluate function at physical points
12127
 
    double values[1];
12128
 
    f.evaluate(values, y, c);
12129
 
    
12130
 
    // Map function values using appropriate mapping
12131
 
    // Affine map: Do nothing
12132
 
    
12133
 
    // Note that we do not map the weights (yet).
12134
 
    
12135
 
    // Take directional components
12136
 
    for(int k = 0; k < 1; k++)
12137
 
      result += values[k]*D[i][0][k];
12138
 
    // Multiply by weights
12139
 
    result *= W[i][0];
12140
 
    
12141
 
    return result;
12142
 
  }
12143
 
 
12144
 
  /// Evaluate linear functionals for all dofs on the function f
12145
 
  virtual void evaluate_dofs(double* values,
12146
 
                             const ufc::function& f,
12147
 
                             const ufc::cell& c) const
12148
 
  {
12149
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
12150
 
  }
12151
 
 
12152
 
  /// Interpolate vertex values from dof values
12153
 
  virtual void interpolate_vertex_values(double* vertex_values,
12154
 
                                         const double* dof_values,
12155
 
                                         const ufc::cell& c) const
12156
 
  {
12157
 
    // Evaluate at vertices and use affine mapping
12158
 
    vertex_values[0] = dof_values[0];
12159
 
    vertex_values[1] = dof_values[1];
12160
 
    vertex_values[2] = dof_values[2];
12161
 
    vertex_values[3] = dof_values[3];
12162
 
  }
12163
 
 
12164
 
  /// Return the number of sub elements (for a mixed element)
12165
 
  virtual unsigned int num_sub_elements() const
12166
 
  {
12167
 
    return 1;
12168
 
  }
12169
 
 
12170
 
  /// Create a new finite element for sub element i (for a mixed element)
12171
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
12172
 
  {
12173
 
    return new hyperelasticity_1_finite_element_0_0();
12174
 
  }
12175
 
 
12176
 
};
12177
 
 
12178
 
/// This class defines the interface for a finite element.
12179
 
 
12180
 
class hyperelasticity_1_finite_element_0_1: public ufc::finite_element
12181
 
{
12182
 
public:
12183
 
 
12184
 
  /// Constructor
12185
 
  hyperelasticity_1_finite_element_0_1() : ufc::finite_element()
12186
 
  {
12187
 
    // Do nothing
12188
 
  }
12189
 
 
12190
 
  /// Destructor
12191
 
  virtual ~hyperelasticity_1_finite_element_0_1()
12192
 
  {
12193
 
    // Do nothing
12194
 
  }
12195
 
 
12196
 
  /// Return a string identifying the finite element
12197
 
  virtual const char* signature() const
12198
 
  {
12199
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
12200
 
  }
12201
 
 
12202
 
  /// Return the cell shape
12203
 
  virtual ufc::shape cell_shape() const
12204
 
  {
12205
 
    return ufc::tetrahedron;
12206
 
  }
12207
 
 
12208
 
  /// Return the dimension of the finite element function space
12209
 
  virtual unsigned int space_dimension() const
12210
 
  {
12211
 
    return 4;
12212
 
  }
12213
 
 
12214
 
  /// Return the rank of the value space
12215
 
  virtual unsigned int value_rank() const
12216
 
  {
12217
 
    return 0;
12218
 
  }
12219
 
 
12220
 
  /// Return the dimension of the value space for axis i
12221
 
  virtual unsigned int value_dimension(unsigned int i) const
12222
 
  {
12223
 
    return 1;
12224
 
  }
12225
 
 
12226
 
  /// Evaluate basis function i at given point in cell
12227
 
  virtual void evaluate_basis(unsigned int i,
12228
 
                              double* values,
12229
 
                              const double* coordinates,
12230
 
                              const ufc::cell& c) const
12231
 
  {
12232
 
    // Extract vertex coordinates
12233
 
    const double * const * element_coordinates = c.coordinates;
12234
 
    
12235
 
    // Compute Jacobian of affine map from reference cell
12236
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
12237
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
12238
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
12239
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
12240
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
12241
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
12242
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
12243
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
12244
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
12245
 
    
12246
 
    // Compute sub determinants
12247
 
    const double d00 = J_11*J_22 - J_12*J_21;
12248
 
    const double d01 = J_12*J_20 - J_10*J_22;
12249
 
    const double d02 = J_10*J_21 - J_11*J_20;
12250
 
    
12251
 
    const double d10 = J_02*J_21 - J_01*J_22;
12252
 
    const double d11 = J_00*J_22 - J_02*J_20;
12253
 
    const double d12 = J_01*J_20 - J_00*J_21;
12254
 
    
12255
 
    const double d20 = J_01*J_12 - J_02*J_11;
12256
 
    const double d21 = J_02*J_10 - J_00*J_12;
12257
 
    const double d22 = J_00*J_11 - J_01*J_10;
12258
 
    
12259
 
    // Compute determinant of Jacobian
12260
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
12261
 
    
12262
 
    // Compute inverse of Jacobian
12263
 
    
12264
 
    // Compute constants
12265
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
12266
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
12267
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
12268
 
    
12269
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
12270
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
12271
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
12272
 
    
12273
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
12274
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
12275
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
12276
 
    
12277
 
    // Get coordinates and map to the UFC reference element
12278
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
12279
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
12280
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
12281
 
    
12282
 
    // Map coordinates to the reference cube
12283
 
    if (std::abs(y + z - 1.0) < 1e-08)
12284
 
      x = 1.0;
12285
 
    else
12286
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
12287
 
    if (std::abs(z - 1.0) < 1e-08)
12288
 
      y = -1.0;
12289
 
    else
12290
 
      y = 2.0 * y/(1.0 - z) - 1.0;
12291
 
    z = 2.0 * z - 1.0;
12292
 
    
12293
 
    // Reset values
12294
 
    *values = 0;
12295
 
    
12296
 
    // Map degree of freedom to element degree of freedom
12297
 
    const unsigned int dof = i;
12298
 
    
12299
 
    // Generate scalings
12300
 
    const double scalings_y_0 = 1;
12301
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
12302
 
    const double scalings_z_0 = 1;
12303
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
12304
 
    
12305
 
    // Compute psitilde_a
12306
 
    const double psitilde_a_0 = 1;
12307
 
    const double psitilde_a_1 = x;
12308
 
    
12309
 
    // Compute psitilde_bs
12310
 
    const double psitilde_bs_0_0 = 1;
12311
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
12312
 
    const double psitilde_bs_1_0 = 1;
12313
 
    
12314
 
    // Compute psitilde_cs
12315
 
    const double psitilde_cs_00_0 = 1;
12316
 
    const double psitilde_cs_00_1 = 2*z + 1;
12317
 
    const double psitilde_cs_01_0 = 1;
12318
 
    const double psitilde_cs_10_0 = 1;
12319
 
    
12320
 
    // Compute basisvalues
12321
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
12322
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
12323
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
12324
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
12325
 
    
12326
 
    // Table(s) of coefficients
12327
 
    static const double coefficients0[4][4] = \
12328
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
12329
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
12330
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
12331
 
    {0.288675135, 0, 0, 0.223606798}};
12332
 
    
12333
 
    // Extract relevant coefficients
12334
 
    const double coeff0_0 = coefficients0[dof][0];
12335
 
    const double coeff0_1 = coefficients0[dof][1];
12336
 
    const double coeff0_2 = coefficients0[dof][2];
12337
 
    const double coeff0_3 = coefficients0[dof][3];
12338
 
    
12339
 
    // Compute value(s)
12340
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
12341
 
  }
12342
 
 
12343
 
  /// Evaluate all basis functions at given point in cell
12344
 
  virtual void evaluate_basis_all(double* values,
12345
 
                                  const double* coordinates,
12346
 
                                  const ufc::cell& c) const
12347
 
  {
12348
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
12349
 
  }
12350
 
 
12351
 
  /// Evaluate order n derivatives of basis function i at given point in cell
12352
 
  virtual void evaluate_basis_derivatives(unsigned int i,
12353
 
                                          unsigned int n,
12354
 
                                          double* values,
12355
 
                                          const double* coordinates,
12356
 
                                          const ufc::cell& c) const
12357
 
  {
12358
 
    // Extract vertex coordinates
12359
 
    const double * const * element_coordinates = c.coordinates;
12360
 
    
12361
 
    // Compute Jacobian of affine map from reference cell
12362
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
12363
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
12364
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
12365
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
12366
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
12367
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
12368
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
12369
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
12370
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
12371
 
    
12372
 
    // Compute sub determinants
12373
 
    const double d00 = J_11*J_22 - J_12*J_21;
12374
 
    const double d01 = J_12*J_20 - J_10*J_22;
12375
 
    const double d02 = J_10*J_21 - J_11*J_20;
12376
 
    
12377
 
    const double d10 = J_02*J_21 - J_01*J_22;
12378
 
    const double d11 = J_00*J_22 - J_02*J_20;
12379
 
    const double d12 = J_01*J_20 - J_00*J_21;
12380
 
    
12381
 
    const double d20 = J_01*J_12 - J_02*J_11;
12382
 
    const double d21 = J_02*J_10 - J_00*J_12;
12383
 
    const double d22 = J_00*J_11 - J_01*J_10;
12384
 
    
12385
 
    // Compute determinant of Jacobian
12386
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
12387
 
    
12388
 
    // Compute inverse of Jacobian
12389
 
    
12390
 
    // Compute constants
12391
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
12392
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
12393
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
12394
 
    
12395
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
12396
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
12397
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
12398
 
    
12399
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
12400
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
12401
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
12402
 
    
12403
 
    // Get coordinates and map to the UFC reference element
12404
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
12405
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
12406
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
12407
 
    
12408
 
    // Map coordinates to the reference cube
12409
 
    if (std::abs(y + z - 1.0) < 1e-08)
12410
 
      x = 1.0;
12411
 
    else
12412
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
12413
 
    if (std::abs(z - 1.0) < 1e-08)
12414
 
      y = -1.0;
12415
 
    else
12416
 
      y = 2.0 * y/(1.0 - z) - 1.0;
12417
 
    z = 2.0 * z - 1.0;
12418
 
    
12419
 
    // Compute number of derivatives
12420
 
    unsigned int num_derivatives = 1;
12421
 
    
12422
 
    for (unsigned int j = 0; j < n; j++)
12423
 
      num_derivatives *= 3;
12424
 
    
12425
 
    
12426
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
12427
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
12428
 
    
12429
 
    for (unsigned int j = 0; j < num_derivatives; j++)
12430
 
    {
12431
 
      combinations[j] = new unsigned int [n];
12432
 
      for (unsigned int k = 0; k < n; k++)
12433
 
        combinations[j][k] = 0;
12434
 
    }
12435
 
    
12436
 
    // Generate combinations of derivatives
12437
 
    for (unsigned int row = 1; row < num_derivatives; row++)
12438
 
    {
12439
 
      for (unsigned int num = 0; num < row; num++)
12440
 
      {
12441
 
        for (unsigned int col = n-1; col+1 > 0; col--)
12442
 
        {
12443
 
          if (combinations[row][col] + 1 > 2)
12444
 
            combinations[row][col] = 0;
12445
 
          else
12446
 
          {
12447
 
            combinations[row][col] += 1;
12448
 
            break;
12449
 
          }
12450
 
        }
12451
 
      }
12452
 
    }
12453
 
    
12454
 
    // Compute inverse of Jacobian
12455
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
12456
 
    
12457
 
    // Declare transformation matrix
12458
 
    // Declare pointer to two dimensional array and initialise
12459
 
    double **transform = new double *[num_derivatives];
12460
 
    
12461
 
    for (unsigned int j = 0; j < num_derivatives; j++)
12462
 
    {
12463
 
      transform[j] = new double [num_derivatives];
12464
 
      for (unsigned int k = 0; k < num_derivatives; k++)
12465
 
        transform[j][k] = 1;
12466
 
    }
12467
 
    
12468
 
    // Construct transformation matrix
12469
 
    for (unsigned int row = 0; row < num_derivatives; row++)
12470
 
    {
12471
 
      for (unsigned int col = 0; col < num_derivatives; col++)
12472
 
      {
12473
 
        for (unsigned int k = 0; k < n; k++)
12474
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
12475
 
      }
12476
 
    }
12477
 
    
12478
 
    // Reset values
12479
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
12480
 
      values[j] = 0;
12481
 
    
12482
 
    // Map degree of freedom to element degree of freedom
12483
 
    const unsigned int dof = i;
12484
 
    
12485
 
    // Generate scalings
12486
 
    const double scalings_y_0 = 1;
12487
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
12488
 
    const double scalings_z_0 = 1;
12489
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
12490
 
    
12491
 
    // Compute psitilde_a
12492
 
    const double psitilde_a_0 = 1;
12493
 
    const double psitilde_a_1 = x;
12494
 
    
12495
 
    // Compute psitilde_bs
12496
 
    const double psitilde_bs_0_0 = 1;
12497
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
12498
 
    const double psitilde_bs_1_0 = 1;
12499
 
    
12500
 
    // Compute psitilde_cs
12501
 
    const double psitilde_cs_00_0 = 1;
12502
 
    const double psitilde_cs_00_1 = 2*z + 1;
12503
 
    const double psitilde_cs_01_0 = 1;
12504
 
    const double psitilde_cs_10_0 = 1;
12505
 
    
12506
 
    // Compute basisvalues
12507
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
12508
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
12509
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
12510
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
12511
 
    
12512
 
    // Table(s) of coefficients
12513
 
    static const double coefficients0[4][4] = \
12514
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
12515
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
12516
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
12517
 
    {0.288675135, 0, 0, 0.223606798}};
12518
 
    
12519
 
    // Interesting (new) part
12520
 
    // Tables of derivatives of the polynomial base (transpose)
12521
 
    static const double dmats0[4][4] = \
12522
 
    {{0, 0, 0, 0},
12523
 
    {6.32455532, 0, 0, 0},
12524
 
    {0, 0, 0, 0},
12525
 
    {0, 0, 0, 0}};
12526
 
    
12527
 
    static const double dmats1[4][4] = \
12528
 
    {{0, 0, 0, 0},
12529
 
    {3.16227766, 0, 0, 0},
12530
 
    {5.47722558, 0, 0, 0},
12531
 
    {0, 0, 0, 0}};
12532
 
    
12533
 
    static const double dmats2[4][4] = \
12534
 
    {{0, 0, 0, 0},
12535
 
    {3.16227766, 0, 0, 0},
12536
 
    {1.82574186, 0, 0, 0},
12537
 
    {5.16397779, 0, 0, 0}};
12538
 
    
12539
 
    // Compute reference derivatives
12540
 
    // Declare pointer to array of derivatives on FIAT element
12541
 
    double *derivatives = new double [num_derivatives];
12542
 
    
12543
 
    // Declare coefficients
12544
 
    double coeff0_0 = 0;
12545
 
    double coeff0_1 = 0;
12546
 
    double coeff0_2 = 0;
12547
 
    double coeff0_3 = 0;
12548
 
    
12549
 
    // Declare new coefficients
12550
 
    double new_coeff0_0 = 0;
12551
 
    double new_coeff0_1 = 0;
12552
 
    double new_coeff0_2 = 0;
12553
 
    double new_coeff0_3 = 0;
12554
 
    
12555
 
    // Loop possible derivatives
12556
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
12557
 
    {
12558
 
      // Get values from coefficients array
12559
 
      new_coeff0_0 = coefficients0[dof][0];
12560
 
      new_coeff0_1 = coefficients0[dof][1];
12561
 
      new_coeff0_2 = coefficients0[dof][2];
12562
 
      new_coeff0_3 = coefficients0[dof][3];
12563
 
    
12564
 
      // Loop derivative order
12565
 
      for (unsigned int j = 0; j < n; j++)
12566
 
      {
12567
 
        // Update old coefficients
12568
 
        coeff0_0 = new_coeff0_0;
12569
 
        coeff0_1 = new_coeff0_1;
12570
 
        coeff0_2 = new_coeff0_2;
12571
 
        coeff0_3 = new_coeff0_3;
12572
 
    
12573
 
        if(combinations[deriv_num][j] == 0)
12574
 
        {
12575
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
12576
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
12577
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
12578
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
12579
 
        }
12580
 
        if(combinations[deriv_num][j] == 1)
12581
 
        {
12582
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
12583
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
12584
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
12585
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
12586
 
        }
12587
 
        if(combinations[deriv_num][j] == 2)
12588
 
        {
12589
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
12590
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
12591
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
12592
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
12593
 
        }
12594
 
    
12595
 
      }
12596
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
12597
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
12598
 
    }
12599
 
    
12600
 
    // Transform derivatives back to physical element
12601
 
    for (unsigned int row = 0; row < num_derivatives; row++)
12602
 
    {
12603
 
      for (unsigned int col = 0; col < num_derivatives; col++)
12604
 
      {
12605
 
        values[row] += transform[row][col]*derivatives[col];
12606
 
      }
12607
 
    }
12608
 
    // Delete pointer to array of derivatives on FIAT element
12609
 
    delete [] derivatives;
12610
 
    
12611
 
    // Delete pointer to array of combinations of derivatives and transform
12612
 
    for (unsigned int row = 0; row < num_derivatives; row++)
12613
 
    {
12614
 
      delete [] combinations[row];
12615
 
      delete [] transform[row];
12616
 
    }
12617
 
    
12618
 
    delete [] combinations;
12619
 
    delete [] transform;
12620
 
  }
12621
 
 
12622
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
12623
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
12624
 
                                              double* values,
12625
 
                                              const double* coordinates,
12626
 
                                              const ufc::cell& c) const
12627
 
  {
12628
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
12629
 
  }
12630
 
 
12631
 
  /// Evaluate linear functional for dof i on the function f
12632
 
  virtual double evaluate_dof(unsigned int i,
12633
 
                              const ufc::function& f,
12634
 
                              const ufc::cell& c) const
12635
 
  {
12636
 
    // The reference points, direction and weights:
12637
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
12638
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
12639
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
12640
 
    
12641
 
    const double * const * x = c.coordinates;
12642
 
    double result = 0.0;
12643
 
    // Iterate over the points:
12644
 
    // Evaluate basis functions for affine mapping
12645
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
12646
 
    const double w1 = X[i][0][0];
12647
 
    const double w2 = X[i][0][1];
12648
 
    const double w3 = X[i][0][2];
12649
 
    
12650
 
    // Compute affine mapping y = F(X)
12651
 
    double y[3];
12652
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
12653
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
12654
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
12655
 
    
12656
 
    // Evaluate function at physical points
12657
 
    double values[1];
12658
 
    f.evaluate(values, y, c);
12659
 
    
12660
 
    // Map function values using appropriate mapping
12661
 
    // Affine map: Do nothing
12662
 
    
12663
 
    // Note that we do not map the weights (yet).
12664
 
    
12665
 
    // Take directional components
12666
 
    for(int k = 0; k < 1; k++)
12667
 
      result += values[k]*D[i][0][k];
12668
 
    // Multiply by weights
12669
 
    result *= W[i][0];
12670
 
    
12671
 
    return result;
12672
 
  }
12673
 
 
12674
 
  /// Evaluate linear functionals for all dofs on the function f
12675
 
  virtual void evaluate_dofs(double* values,
12676
 
                             const ufc::function& f,
12677
 
                             const ufc::cell& c) const
12678
 
  {
12679
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
12680
 
  }
12681
 
 
12682
 
  /// Interpolate vertex values from dof values
12683
 
  virtual void interpolate_vertex_values(double* vertex_values,
12684
 
                                         const double* dof_values,
12685
 
                                         const ufc::cell& c) const
12686
 
  {
12687
 
    // Evaluate at vertices and use affine mapping
12688
 
    vertex_values[0] = dof_values[0];
12689
 
    vertex_values[1] = dof_values[1];
12690
 
    vertex_values[2] = dof_values[2];
12691
 
    vertex_values[3] = dof_values[3];
12692
 
  }
12693
 
 
12694
 
  /// Return the number of sub elements (for a mixed element)
12695
 
  virtual unsigned int num_sub_elements() const
12696
 
  {
12697
 
    return 1;
12698
 
  }
12699
 
 
12700
 
  /// Create a new finite element for sub element i (for a mixed element)
12701
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
12702
 
  {
12703
 
    return new hyperelasticity_1_finite_element_0_1();
12704
 
  }
12705
 
 
12706
 
};
12707
 
 
12708
 
/// This class defines the interface for a finite element.
12709
 
 
12710
 
class hyperelasticity_1_finite_element_0_2: public ufc::finite_element
12711
 
{
12712
 
public:
12713
 
 
12714
 
  /// Constructor
12715
 
  hyperelasticity_1_finite_element_0_2() : ufc::finite_element()
12716
 
  {
12717
 
    // Do nothing
12718
 
  }
12719
 
 
12720
 
  /// Destructor
12721
 
  virtual ~hyperelasticity_1_finite_element_0_2()
12722
 
  {
12723
 
    // Do nothing
12724
 
  }
12725
 
 
12726
 
  /// Return a string identifying the finite element
12727
 
  virtual const char* signature() const
12728
 
  {
12729
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
12730
 
  }
12731
 
 
12732
 
  /// Return the cell shape
12733
 
  virtual ufc::shape cell_shape() const
12734
 
  {
12735
 
    return ufc::tetrahedron;
12736
 
  }
12737
 
 
12738
 
  /// Return the dimension of the finite element function space
12739
 
  virtual unsigned int space_dimension() const
12740
 
  {
12741
 
    return 4;
12742
 
  }
12743
 
 
12744
 
  /// Return the rank of the value space
12745
 
  virtual unsigned int value_rank() const
12746
 
  {
12747
 
    return 0;
12748
 
  }
12749
 
 
12750
 
  /// Return the dimension of the value space for axis i
12751
 
  virtual unsigned int value_dimension(unsigned int i) const
12752
 
  {
12753
 
    return 1;
12754
 
  }
12755
 
 
12756
 
  /// Evaluate basis function i at given point in cell
12757
 
  virtual void evaluate_basis(unsigned int i,
12758
 
                              double* values,
12759
 
                              const double* coordinates,
12760
 
                              const ufc::cell& c) const
12761
 
  {
12762
 
    // Extract vertex coordinates
12763
 
    const double * const * element_coordinates = c.coordinates;
12764
 
    
12765
 
    // Compute Jacobian of affine map from reference cell
12766
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
12767
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
12768
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
12769
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
12770
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
12771
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
12772
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
12773
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
12774
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
12775
 
    
12776
 
    // Compute sub determinants
12777
 
    const double d00 = J_11*J_22 - J_12*J_21;
12778
 
    const double d01 = J_12*J_20 - J_10*J_22;
12779
 
    const double d02 = J_10*J_21 - J_11*J_20;
12780
 
    
12781
 
    const double d10 = J_02*J_21 - J_01*J_22;
12782
 
    const double d11 = J_00*J_22 - J_02*J_20;
12783
 
    const double d12 = J_01*J_20 - J_00*J_21;
12784
 
    
12785
 
    const double d20 = J_01*J_12 - J_02*J_11;
12786
 
    const double d21 = J_02*J_10 - J_00*J_12;
12787
 
    const double d22 = J_00*J_11 - J_01*J_10;
12788
 
    
12789
 
    // Compute determinant of Jacobian
12790
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
12791
 
    
12792
 
    // Compute inverse of Jacobian
12793
 
    
12794
 
    // Compute constants
12795
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
12796
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
12797
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
12798
 
    
12799
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
12800
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
12801
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
12802
 
    
12803
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
12804
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
12805
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
12806
 
    
12807
 
    // Get coordinates and map to the UFC reference element
12808
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
12809
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
12810
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
12811
 
    
12812
 
    // Map coordinates to the reference cube
12813
 
    if (std::abs(y + z - 1.0) < 1e-08)
12814
 
      x = 1.0;
12815
 
    else
12816
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
12817
 
    if (std::abs(z - 1.0) < 1e-08)
12818
 
      y = -1.0;
12819
 
    else
12820
 
      y = 2.0 * y/(1.0 - z) - 1.0;
12821
 
    z = 2.0 * z - 1.0;
12822
 
    
12823
 
    // Reset values
12824
 
    *values = 0;
12825
 
    
12826
 
    // Map degree of freedom to element degree of freedom
12827
 
    const unsigned int dof = i;
12828
 
    
12829
 
    // Generate scalings
12830
 
    const double scalings_y_0 = 1;
12831
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
12832
 
    const double scalings_z_0 = 1;
12833
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
12834
 
    
12835
 
    // Compute psitilde_a
12836
 
    const double psitilde_a_0 = 1;
12837
 
    const double psitilde_a_1 = x;
12838
 
    
12839
 
    // Compute psitilde_bs
12840
 
    const double psitilde_bs_0_0 = 1;
12841
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
12842
 
    const double psitilde_bs_1_0 = 1;
12843
 
    
12844
 
    // Compute psitilde_cs
12845
 
    const double psitilde_cs_00_0 = 1;
12846
 
    const double psitilde_cs_00_1 = 2*z + 1;
12847
 
    const double psitilde_cs_01_0 = 1;
12848
 
    const double psitilde_cs_10_0 = 1;
12849
 
    
12850
 
    // Compute basisvalues
12851
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
12852
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
12853
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
12854
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
12855
 
    
12856
 
    // Table(s) of coefficients
12857
 
    static const double coefficients0[4][4] = \
12858
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
12859
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
12860
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
12861
 
    {0.288675135, 0, 0, 0.223606798}};
12862
 
    
12863
 
    // Extract relevant coefficients
12864
 
    const double coeff0_0 = coefficients0[dof][0];
12865
 
    const double coeff0_1 = coefficients0[dof][1];
12866
 
    const double coeff0_2 = coefficients0[dof][2];
12867
 
    const double coeff0_3 = coefficients0[dof][3];
12868
 
    
12869
 
    // Compute value(s)
12870
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
12871
 
  }
12872
 
 
12873
 
  /// Evaluate all basis functions at given point in cell
12874
 
  virtual void evaluate_basis_all(double* values,
12875
 
                                  const double* coordinates,
12876
 
                                  const ufc::cell& c) const
12877
 
  {
12878
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
12879
 
  }
12880
 
 
12881
 
  /// Evaluate order n derivatives of basis function i at given point in cell
12882
 
  virtual void evaluate_basis_derivatives(unsigned int i,
12883
 
                                          unsigned int n,
12884
 
                                          double* values,
12885
 
                                          const double* coordinates,
12886
 
                                          const ufc::cell& c) const
12887
 
  {
12888
 
    // Extract vertex coordinates
12889
 
    const double * const * element_coordinates = c.coordinates;
12890
 
    
12891
 
    // Compute Jacobian of affine map from reference cell
12892
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
12893
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
12894
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
12895
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
12896
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
12897
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
12898
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
12899
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
12900
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
12901
 
    
12902
 
    // Compute sub determinants
12903
 
    const double d00 = J_11*J_22 - J_12*J_21;
12904
 
    const double d01 = J_12*J_20 - J_10*J_22;
12905
 
    const double d02 = J_10*J_21 - J_11*J_20;
12906
 
    
12907
 
    const double d10 = J_02*J_21 - J_01*J_22;
12908
 
    const double d11 = J_00*J_22 - J_02*J_20;
12909
 
    const double d12 = J_01*J_20 - J_00*J_21;
12910
 
    
12911
 
    const double d20 = J_01*J_12 - J_02*J_11;
12912
 
    const double d21 = J_02*J_10 - J_00*J_12;
12913
 
    const double d22 = J_00*J_11 - J_01*J_10;
12914
 
    
12915
 
    // Compute determinant of Jacobian
12916
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
12917
 
    
12918
 
    // Compute inverse of Jacobian
12919
 
    
12920
 
    // Compute constants
12921
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
12922
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
12923
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
12924
 
    
12925
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
12926
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
12927
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
12928
 
    
12929
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
12930
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
12931
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
12932
 
    
12933
 
    // Get coordinates and map to the UFC reference element
12934
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
12935
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
12936
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
12937
 
    
12938
 
    // Map coordinates to the reference cube
12939
 
    if (std::abs(y + z - 1.0) < 1e-08)
12940
 
      x = 1.0;
12941
 
    else
12942
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
12943
 
    if (std::abs(z - 1.0) < 1e-08)
12944
 
      y = -1.0;
12945
 
    else
12946
 
      y = 2.0 * y/(1.0 - z) - 1.0;
12947
 
    z = 2.0 * z - 1.0;
12948
 
    
12949
 
    // Compute number of derivatives
12950
 
    unsigned int num_derivatives = 1;
12951
 
    
12952
 
    for (unsigned int j = 0; j < n; j++)
12953
 
      num_derivatives *= 3;
12954
 
    
12955
 
    
12956
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
12957
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
12958
 
    
12959
 
    for (unsigned int j = 0; j < num_derivatives; j++)
12960
 
    {
12961
 
      combinations[j] = new unsigned int [n];
12962
 
      for (unsigned int k = 0; k < n; k++)
12963
 
        combinations[j][k] = 0;
12964
 
    }
12965
 
    
12966
 
    // Generate combinations of derivatives
12967
 
    for (unsigned int row = 1; row < num_derivatives; row++)
12968
 
    {
12969
 
      for (unsigned int num = 0; num < row; num++)
12970
 
      {
12971
 
        for (unsigned int col = n-1; col+1 > 0; col--)
12972
 
        {
12973
 
          if (combinations[row][col] + 1 > 2)
12974
 
            combinations[row][col] = 0;
12975
 
          else
12976
 
          {
12977
 
            combinations[row][col] += 1;
12978
 
            break;
12979
 
          }
12980
 
        }
12981
 
      }
12982
 
    }
12983
 
    
12984
 
    // Compute inverse of Jacobian
12985
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
12986
 
    
12987
 
    // Declare transformation matrix
12988
 
    // Declare pointer to two dimensional array and initialise
12989
 
    double **transform = new double *[num_derivatives];
12990
 
    
12991
 
    for (unsigned int j = 0; j < num_derivatives; j++)
12992
 
    {
12993
 
      transform[j] = new double [num_derivatives];
12994
 
      for (unsigned int k = 0; k < num_derivatives; k++)
12995
 
        transform[j][k] = 1;
12996
 
    }
12997
 
    
12998
 
    // Construct transformation matrix
12999
 
    for (unsigned int row = 0; row < num_derivatives; row++)
13000
 
    {
13001
 
      for (unsigned int col = 0; col < num_derivatives; col++)
13002
 
      {
13003
 
        for (unsigned int k = 0; k < n; k++)
13004
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
13005
 
      }
13006
 
    }
13007
 
    
13008
 
    // Reset values
13009
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
13010
 
      values[j] = 0;
13011
 
    
13012
 
    // Map degree of freedom to element degree of freedom
13013
 
    const unsigned int dof = i;
13014
 
    
13015
 
    // Generate scalings
13016
 
    const double scalings_y_0 = 1;
13017
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13018
 
    const double scalings_z_0 = 1;
13019
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13020
 
    
13021
 
    // Compute psitilde_a
13022
 
    const double psitilde_a_0 = 1;
13023
 
    const double psitilde_a_1 = x;
13024
 
    
13025
 
    // Compute psitilde_bs
13026
 
    const double psitilde_bs_0_0 = 1;
13027
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
13028
 
    const double psitilde_bs_1_0 = 1;
13029
 
    
13030
 
    // Compute psitilde_cs
13031
 
    const double psitilde_cs_00_0 = 1;
13032
 
    const double psitilde_cs_00_1 = 2*z + 1;
13033
 
    const double psitilde_cs_01_0 = 1;
13034
 
    const double psitilde_cs_10_0 = 1;
13035
 
    
13036
 
    // Compute basisvalues
13037
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13038
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13039
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13040
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13041
 
    
13042
 
    // Table(s) of coefficients
13043
 
    static const double coefficients0[4][4] = \
13044
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13045
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13046
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
13047
 
    {0.288675135, 0, 0, 0.223606798}};
13048
 
    
13049
 
    // Interesting (new) part
13050
 
    // Tables of derivatives of the polynomial base (transpose)
13051
 
    static const double dmats0[4][4] = \
13052
 
    {{0, 0, 0, 0},
13053
 
    {6.32455532, 0, 0, 0},
13054
 
    {0, 0, 0, 0},
13055
 
    {0, 0, 0, 0}};
13056
 
    
13057
 
    static const double dmats1[4][4] = \
13058
 
    {{0, 0, 0, 0},
13059
 
    {3.16227766, 0, 0, 0},
13060
 
    {5.47722558, 0, 0, 0},
13061
 
    {0, 0, 0, 0}};
13062
 
    
13063
 
    static const double dmats2[4][4] = \
13064
 
    {{0, 0, 0, 0},
13065
 
    {3.16227766, 0, 0, 0},
13066
 
    {1.82574186, 0, 0, 0},
13067
 
    {5.16397779, 0, 0, 0}};
13068
 
    
13069
 
    // Compute reference derivatives
13070
 
    // Declare pointer to array of derivatives on FIAT element
13071
 
    double *derivatives = new double [num_derivatives];
13072
 
    
13073
 
    // Declare coefficients
13074
 
    double coeff0_0 = 0;
13075
 
    double coeff0_1 = 0;
13076
 
    double coeff0_2 = 0;
13077
 
    double coeff0_3 = 0;
13078
 
    
13079
 
    // Declare new coefficients
13080
 
    double new_coeff0_0 = 0;
13081
 
    double new_coeff0_1 = 0;
13082
 
    double new_coeff0_2 = 0;
13083
 
    double new_coeff0_3 = 0;
13084
 
    
13085
 
    // Loop possible derivatives
13086
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
13087
 
    {
13088
 
      // Get values from coefficients array
13089
 
      new_coeff0_0 = coefficients0[dof][0];
13090
 
      new_coeff0_1 = coefficients0[dof][1];
13091
 
      new_coeff0_2 = coefficients0[dof][2];
13092
 
      new_coeff0_3 = coefficients0[dof][3];
13093
 
    
13094
 
      // Loop derivative order
13095
 
      for (unsigned int j = 0; j < n; j++)
13096
 
      {
13097
 
        // Update old coefficients
13098
 
        coeff0_0 = new_coeff0_0;
13099
 
        coeff0_1 = new_coeff0_1;
13100
 
        coeff0_2 = new_coeff0_2;
13101
 
        coeff0_3 = new_coeff0_3;
13102
 
    
13103
 
        if(combinations[deriv_num][j] == 0)
13104
 
        {
13105
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
13106
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
13107
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
13108
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
13109
 
        }
13110
 
        if(combinations[deriv_num][j] == 1)
13111
 
        {
13112
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
13113
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
13114
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
13115
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
13116
 
        }
13117
 
        if(combinations[deriv_num][j] == 2)
13118
 
        {
13119
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
13120
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
13121
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
13122
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
13123
 
        }
13124
 
    
13125
 
      }
13126
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
13127
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
13128
 
    }
13129
 
    
13130
 
    // Transform derivatives back to physical element
13131
 
    for (unsigned int row = 0; row < num_derivatives; row++)
13132
 
    {
13133
 
      for (unsigned int col = 0; col < num_derivatives; col++)
13134
 
      {
13135
 
        values[row] += transform[row][col]*derivatives[col];
13136
 
      }
13137
 
    }
13138
 
    // Delete pointer to array of derivatives on FIAT element
13139
 
    delete [] derivatives;
13140
 
    
13141
 
    // Delete pointer to array of combinations of derivatives and transform
13142
 
    for (unsigned int row = 0; row < num_derivatives; row++)
13143
 
    {
13144
 
      delete [] combinations[row];
13145
 
      delete [] transform[row];
13146
 
    }
13147
 
    
13148
 
    delete [] combinations;
13149
 
    delete [] transform;
13150
 
  }
13151
 
 
13152
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
13153
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
13154
 
                                              double* values,
13155
 
                                              const double* coordinates,
13156
 
                                              const ufc::cell& c) const
13157
 
  {
13158
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
13159
 
  }
13160
 
 
13161
 
  /// Evaluate linear functional for dof i on the function f
13162
 
  virtual double evaluate_dof(unsigned int i,
13163
 
                              const ufc::function& f,
13164
 
                              const ufc::cell& c) const
13165
 
  {
13166
 
    // The reference points, direction and weights:
13167
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
13168
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
13169
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
13170
 
    
13171
 
    const double * const * x = c.coordinates;
13172
 
    double result = 0.0;
13173
 
    // Iterate over the points:
13174
 
    // Evaluate basis functions for affine mapping
13175
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
13176
 
    const double w1 = X[i][0][0];
13177
 
    const double w2 = X[i][0][1];
13178
 
    const double w3 = X[i][0][2];
13179
 
    
13180
 
    // Compute affine mapping y = F(X)
13181
 
    double y[3];
13182
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
13183
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
13184
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
13185
 
    
13186
 
    // Evaluate function at physical points
13187
 
    double values[1];
13188
 
    f.evaluate(values, y, c);
13189
 
    
13190
 
    // Map function values using appropriate mapping
13191
 
    // Affine map: Do nothing
13192
 
    
13193
 
    // Note that we do not map the weights (yet).
13194
 
    
13195
 
    // Take directional components
13196
 
    for(int k = 0; k < 1; k++)
13197
 
      result += values[k]*D[i][0][k];
13198
 
    // Multiply by weights
13199
 
    result *= W[i][0];
13200
 
    
13201
 
    return result;
13202
 
  }
13203
 
 
13204
 
  /// Evaluate linear functionals for all dofs on the function f
13205
 
  virtual void evaluate_dofs(double* values,
13206
 
                             const ufc::function& f,
13207
 
                             const ufc::cell& c) const
13208
 
  {
13209
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
13210
 
  }
13211
 
 
13212
 
  /// Interpolate vertex values from dof values
13213
 
  virtual void interpolate_vertex_values(double* vertex_values,
13214
 
                                         const double* dof_values,
13215
 
                                         const ufc::cell& c) const
13216
 
  {
13217
 
    // Evaluate at vertices and use affine mapping
13218
 
    vertex_values[0] = dof_values[0];
13219
 
    vertex_values[1] = dof_values[1];
13220
 
    vertex_values[2] = dof_values[2];
13221
 
    vertex_values[3] = dof_values[3];
13222
 
  }
13223
 
 
13224
 
  /// Return the number of sub elements (for a mixed element)
13225
 
  virtual unsigned int num_sub_elements() const
13226
 
  {
13227
 
    return 1;
13228
 
  }
13229
 
 
13230
 
  /// Create a new finite element for sub element i (for a mixed element)
13231
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
13232
 
  {
13233
 
    return new hyperelasticity_1_finite_element_0_2();
13234
 
  }
13235
 
 
13236
 
};
13237
 
 
13238
 
/// This class defines the interface for a finite element.
13239
 
 
13240
 
class hyperelasticity_1_finite_element_0: public ufc::finite_element
13241
 
{
13242
 
public:
13243
 
 
13244
 
  /// Constructor
13245
 
  hyperelasticity_1_finite_element_0() : ufc::finite_element()
13246
 
  {
13247
 
    // Do nothing
13248
 
  }
13249
 
 
13250
 
  /// Destructor
13251
 
  virtual ~hyperelasticity_1_finite_element_0()
13252
 
  {
13253
 
    // Do nothing
13254
 
  }
13255
 
 
13256
 
  /// Return a string identifying the finite element
13257
 
  virtual const char* signature() const
13258
 
  {
13259
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
13260
 
  }
13261
 
 
13262
 
  /// Return the cell shape
13263
 
  virtual ufc::shape cell_shape() const
13264
 
  {
13265
 
    return ufc::tetrahedron;
13266
 
  }
13267
 
 
13268
 
  /// Return the dimension of the finite element function space
13269
 
  virtual unsigned int space_dimension() const
13270
 
  {
13271
 
    return 12;
13272
 
  }
13273
 
 
13274
 
  /// Return the rank of the value space
13275
 
  virtual unsigned int value_rank() const
13276
 
  {
13277
 
    return 1;
13278
 
  }
13279
 
 
13280
 
  /// Return the dimension of the value space for axis i
13281
 
  virtual unsigned int value_dimension(unsigned int i) const
13282
 
  {
13283
 
    return 3;
13284
 
  }
13285
 
 
13286
 
  /// Evaluate basis function i at given point in cell
13287
 
  virtual void evaluate_basis(unsigned int i,
13288
 
                              double* values,
13289
 
                              const double* coordinates,
13290
 
                              const ufc::cell& c) const
13291
 
  {
13292
 
    // Extract vertex coordinates
13293
 
    const double * const * element_coordinates = c.coordinates;
13294
 
    
13295
 
    // Compute Jacobian of affine map from reference cell
13296
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
13297
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
13298
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
13299
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
13300
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
13301
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
13302
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
13303
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
13304
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
13305
 
    
13306
 
    // Compute sub determinants
13307
 
    const double d00 = J_11*J_22 - J_12*J_21;
13308
 
    const double d01 = J_12*J_20 - J_10*J_22;
13309
 
    const double d02 = J_10*J_21 - J_11*J_20;
13310
 
    
13311
 
    const double d10 = J_02*J_21 - J_01*J_22;
13312
 
    const double d11 = J_00*J_22 - J_02*J_20;
13313
 
    const double d12 = J_01*J_20 - J_00*J_21;
13314
 
    
13315
 
    const double d20 = J_01*J_12 - J_02*J_11;
13316
 
    const double d21 = J_02*J_10 - J_00*J_12;
13317
 
    const double d22 = J_00*J_11 - J_01*J_10;
13318
 
    
13319
 
    // Compute determinant of Jacobian
13320
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
13321
 
    
13322
 
    // Compute inverse of Jacobian
13323
 
    
13324
 
    // Compute constants
13325
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
13326
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
13327
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
13328
 
    
13329
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
13330
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
13331
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
13332
 
    
13333
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
13334
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
13335
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
13336
 
    
13337
 
    // Get coordinates and map to the UFC reference element
13338
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
13339
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
13340
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
13341
 
    
13342
 
    // Map coordinates to the reference cube
13343
 
    if (std::abs(y + z - 1.0) < 1e-08)
13344
 
      x = 1.0;
13345
 
    else
13346
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
13347
 
    if (std::abs(z - 1.0) < 1e-08)
13348
 
      y = -1.0;
13349
 
    else
13350
 
      y = 2.0 * y/(1.0 - z) - 1.0;
13351
 
    z = 2.0 * z - 1.0;
13352
 
    
13353
 
    // Reset values
13354
 
    values[0] = 0;
13355
 
    values[1] = 0;
13356
 
    values[2] = 0;
13357
 
    
13358
 
    if (0 <= i && i <= 3)
13359
 
    {
13360
 
      // Map degree of freedom to element degree of freedom
13361
 
      const unsigned int dof = i;
13362
 
    
13363
 
      // Generate scalings
13364
 
      const double scalings_y_0 = 1;
13365
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13366
 
      const double scalings_z_0 = 1;
13367
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13368
 
    
13369
 
      // Compute psitilde_a
13370
 
      const double psitilde_a_0 = 1;
13371
 
      const double psitilde_a_1 = x;
13372
 
    
13373
 
      // Compute psitilde_bs
13374
 
      const double psitilde_bs_0_0 = 1;
13375
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13376
 
      const double psitilde_bs_1_0 = 1;
13377
 
    
13378
 
      // Compute psitilde_cs
13379
 
      const double psitilde_cs_00_0 = 1;
13380
 
      const double psitilde_cs_00_1 = 2*z + 1;
13381
 
      const double psitilde_cs_01_0 = 1;
13382
 
      const double psitilde_cs_10_0 = 1;
13383
 
    
13384
 
      // Compute basisvalues
13385
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13386
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13387
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13388
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13389
 
    
13390
 
      // Table(s) of coefficients
13391
 
      static const double coefficients0[4][4] =   \
13392
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13393
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13394
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13395
 
      {0.288675135, 0, 0, 0.223606798}};
13396
 
    
13397
 
      // Extract relevant coefficients
13398
 
      const double coeff0_0 =   coefficients0[dof][0];
13399
 
      const double coeff0_1 =   coefficients0[dof][1];
13400
 
      const double coeff0_2 =   coefficients0[dof][2];
13401
 
      const double coeff0_3 =   coefficients0[dof][3];
13402
 
    
13403
 
      // Compute value(s)
13404
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
13405
 
    }
13406
 
    
13407
 
    if (4 <= i && i <= 7)
13408
 
    {
13409
 
      // Map degree of freedom to element degree of freedom
13410
 
      const unsigned int dof = i - 4;
13411
 
    
13412
 
      // Generate scalings
13413
 
      const double scalings_y_0 = 1;
13414
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13415
 
      const double scalings_z_0 = 1;
13416
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13417
 
    
13418
 
      // Compute psitilde_a
13419
 
      const double psitilde_a_0 = 1;
13420
 
      const double psitilde_a_1 = x;
13421
 
    
13422
 
      // Compute psitilde_bs
13423
 
      const double psitilde_bs_0_0 = 1;
13424
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13425
 
      const double psitilde_bs_1_0 = 1;
13426
 
    
13427
 
      // Compute psitilde_cs
13428
 
      const double psitilde_cs_00_0 = 1;
13429
 
      const double psitilde_cs_00_1 = 2*z + 1;
13430
 
      const double psitilde_cs_01_0 = 1;
13431
 
      const double psitilde_cs_10_0 = 1;
13432
 
    
13433
 
      // Compute basisvalues
13434
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13435
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13436
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13437
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13438
 
    
13439
 
      // Table(s) of coefficients
13440
 
      static const double coefficients0[4][4] =   \
13441
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13442
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13443
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13444
 
      {0.288675135, 0, 0, 0.223606798}};
13445
 
    
13446
 
      // Extract relevant coefficients
13447
 
      const double coeff0_0 =   coefficients0[dof][0];
13448
 
      const double coeff0_1 =   coefficients0[dof][1];
13449
 
      const double coeff0_2 =   coefficients0[dof][2];
13450
 
      const double coeff0_3 =   coefficients0[dof][3];
13451
 
    
13452
 
      // Compute value(s)
13453
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
13454
 
    }
13455
 
    
13456
 
    if (8 <= i && i <= 11)
13457
 
    {
13458
 
      // Map degree of freedom to element degree of freedom
13459
 
      const unsigned int dof = i - 8;
13460
 
    
13461
 
      // Generate scalings
13462
 
      const double scalings_y_0 = 1;
13463
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13464
 
      const double scalings_z_0 = 1;
13465
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13466
 
    
13467
 
      // Compute psitilde_a
13468
 
      const double psitilde_a_0 = 1;
13469
 
      const double psitilde_a_1 = x;
13470
 
    
13471
 
      // Compute psitilde_bs
13472
 
      const double psitilde_bs_0_0 = 1;
13473
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13474
 
      const double psitilde_bs_1_0 = 1;
13475
 
    
13476
 
      // Compute psitilde_cs
13477
 
      const double psitilde_cs_00_0 = 1;
13478
 
      const double psitilde_cs_00_1 = 2*z + 1;
13479
 
      const double psitilde_cs_01_0 = 1;
13480
 
      const double psitilde_cs_10_0 = 1;
13481
 
    
13482
 
      // Compute basisvalues
13483
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13484
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13485
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13486
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13487
 
    
13488
 
      // Table(s) of coefficients
13489
 
      static const double coefficients0[4][4] =   \
13490
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13491
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13492
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13493
 
      {0.288675135, 0, 0, 0.223606798}};
13494
 
    
13495
 
      // Extract relevant coefficients
13496
 
      const double coeff0_0 =   coefficients0[dof][0];
13497
 
      const double coeff0_1 =   coefficients0[dof][1];
13498
 
      const double coeff0_2 =   coefficients0[dof][2];
13499
 
      const double coeff0_3 =   coefficients0[dof][3];
13500
 
    
13501
 
      // Compute value(s)
13502
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
13503
 
    }
13504
 
    
13505
 
  }
13506
 
 
13507
 
  /// Evaluate all basis functions at given point in cell
13508
 
  virtual void evaluate_basis_all(double* values,
13509
 
                                  const double* coordinates,
13510
 
                                  const ufc::cell& c) const
13511
 
  {
13512
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
13513
 
  }
13514
 
 
13515
 
  /// Evaluate order n derivatives of basis function i at given point in cell
13516
 
  virtual void evaluate_basis_derivatives(unsigned int i,
13517
 
                                          unsigned int n,
13518
 
                                          double* values,
13519
 
                                          const double* coordinates,
13520
 
                                          const ufc::cell& c) const
13521
 
  {
13522
 
    // Extract vertex coordinates
13523
 
    const double * const * element_coordinates = c.coordinates;
13524
 
    
13525
 
    // Compute Jacobian of affine map from reference cell
13526
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
13527
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
13528
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
13529
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
13530
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
13531
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
13532
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
13533
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
13534
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
13535
 
    
13536
 
    // Compute sub determinants
13537
 
    const double d00 = J_11*J_22 - J_12*J_21;
13538
 
    const double d01 = J_12*J_20 - J_10*J_22;
13539
 
    const double d02 = J_10*J_21 - J_11*J_20;
13540
 
    
13541
 
    const double d10 = J_02*J_21 - J_01*J_22;
13542
 
    const double d11 = J_00*J_22 - J_02*J_20;
13543
 
    const double d12 = J_01*J_20 - J_00*J_21;
13544
 
    
13545
 
    const double d20 = J_01*J_12 - J_02*J_11;
13546
 
    const double d21 = J_02*J_10 - J_00*J_12;
13547
 
    const double d22 = J_00*J_11 - J_01*J_10;
13548
 
    
13549
 
    // Compute determinant of Jacobian
13550
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
13551
 
    
13552
 
    // Compute inverse of Jacobian
13553
 
    
13554
 
    // Compute constants
13555
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
13556
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
13557
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
13558
 
    
13559
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
13560
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
13561
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
13562
 
    
13563
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
13564
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
13565
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
13566
 
    
13567
 
    // Get coordinates and map to the UFC reference element
13568
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
13569
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
13570
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
13571
 
    
13572
 
    // Map coordinates to the reference cube
13573
 
    if (std::abs(y + z - 1.0) < 1e-08)
13574
 
      x = 1.0;
13575
 
    else
13576
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
13577
 
    if (std::abs(z - 1.0) < 1e-08)
13578
 
      y = -1.0;
13579
 
    else
13580
 
      y = 2.0 * y/(1.0 - z) - 1.0;
13581
 
    z = 2.0 * z - 1.0;
13582
 
    
13583
 
    // Compute number of derivatives
13584
 
    unsigned int num_derivatives = 1;
13585
 
    
13586
 
    for (unsigned int j = 0; j < n; j++)
13587
 
      num_derivatives *= 3;
13588
 
    
13589
 
    
13590
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
13591
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
13592
 
    
13593
 
    for (unsigned int j = 0; j < num_derivatives; j++)
13594
 
    {
13595
 
      combinations[j] = new unsigned int [n];
13596
 
      for (unsigned int k = 0; k < n; k++)
13597
 
        combinations[j][k] = 0;
13598
 
    }
13599
 
    
13600
 
    // Generate combinations of derivatives
13601
 
    for (unsigned int row = 1; row < num_derivatives; row++)
13602
 
    {
13603
 
      for (unsigned int num = 0; num < row; num++)
13604
 
      {
13605
 
        for (unsigned int col = n-1; col+1 > 0; col--)
13606
 
        {
13607
 
          if (combinations[row][col] + 1 > 2)
13608
 
            combinations[row][col] = 0;
13609
 
          else
13610
 
          {
13611
 
            combinations[row][col] += 1;
13612
 
            break;
13613
 
          }
13614
 
        }
13615
 
      }
13616
 
    }
13617
 
    
13618
 
    // Compute inverse of Jacobian
13619
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
13620
 
    
13621
 
    // Declare transformation matrix
13622
 
    // Declare pointer to two dimensional array and initialise
13623
 
    double **transform = new double *[num_derivatives];
13624
 
    
13625
 
    for (unsigned int j = 0; j < num_derivatives; j++)
13626
 
    {
13627
 
      transform[j] = new double [num_derivatives];
13628
 
      for (unsigned int k = 0; k < num_derivatives; k++)
13629
 
        transform[j][k] = 1;
13630
 
    }
13631
 
    
13632
 
    // Construct transformation matrix
13633
 
    for (unsigned int row = 0; row < num_derivatives; row++)
13634
 
    {
13635
 
      for (unsigned int col = 0; col < num_derivatives; col++)
13636
 
      {
13637
 
        for (unsigned int k = 0; k < n; k++)
13638
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
13639
 
      }
13640
 
    }
13641
 
    
13642
 
    // Reset values
13643
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
13644
 
      values[j] = 0;
13645
 
    
13646
 
    if (0 <= i && i <= 3)
13647
 
    {
13648
 
      // Map degree of freedom to element degree of freedom
13649
 
      const unsigned int dof = i;
13650
 
    
13651
 
      // Generate scalings
13652
 
      const double scalings_y_0 = 1;
13653
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13654
 
      const double scalings_z_0 = 1;
13655
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13656
 
    
13657
 
      // Compute psitilde_a
13658
 
      const double psitilde_a_0 = 1;
13659
 
      const double psitilde_a_1 = x;
13660
 
    
13661
 
      // Compute psitilde_bs
13662
 
      const double psitilde_bs_0_0 = 1;
13663
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13664
 
      const double psitilde_bs_1_0 = 1;
13665
 
    
13666
 
      // Compute psitilde_cs
13667
 
      const double psitilde_cs_00_0 = 1;
13668
 
      const double psitilde_cs_00_1 = 2*z + 1;
13669
 
      const double psitilde_cs_01_0 = 1;
13670
 
      const double psitilde_cs_10_0 = 1;
13671
 
    
13672
 
      // Compute basisvalues
13673
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13674
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13675
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13676
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13677
 
    
13678
 
      // Table(s) of coefficients
13679
 
      static const double coefficients0[4][4] =   \
13680
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13681
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13682
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13683
 
      {0.288675135, 0, 0, 0.223606798}};
13684
 
    
13685
 
      // Interesting (new) part
13686
 
      // Tables of derivatives of the polynomial base (transpose)
13687
 
      static const double dmats0[4][4] =   \
13688
 
      {{0, 0, 0, 0},
13689
 
      {6.32455532, 0, 0, 0},
13690
 
      {0, 0, 0, 0},
13691
 
      {0, 0, 0, 0}};
13692
 
    
13693
 
      static const double dmats1[4][4] =   \
13694
 
      {{0, 0, 0, 0},
13695
 
      {3.16227766, 0, 0, 0},
13696
 
      {5.47722558, 0, 0, 0},
13697
 
      {0, 0, 0, 0}};
13698
 
    
13699
 
      static const double dmats2[4][4] =   \
13700
 
      {{0, 0, 0, 0},
13701
 
      {3.16227766, 0, 0, 0},
13702
 
      {1.82574186, 0, 0, 0},
13703
 
      {5.16397779, 0, 0, 0}};
13704
 
    
13705
 
      // Compute reference derivatives
13706
 
      // Declare pointer to array of derivatives on FIAT element
13707
 
      double *derivatives = new double [num_derivatives];
13708
 
    
13709
 
      // Declare coefficients
13710
 
      double coeff0_0 = 0;
13711
 
      double coeff0_1 = 0;
13712
 
      double coeff0_2 = 0;
13713
 
      double coeff0_3 = 0;
13714
 
    
13715
 
      // Declare new coefficients
13716
 
      double new_coeff0_0 = 0;
13717
 
      double new_coeff0_1 = 0;
13718
 
      double new_coeff0_2 = 0;
13719
 
      double new_coeff0_3 = 0;
13720
 
    
13721
 
      // Loop possible derivatives
13722
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
13723
 
      {
13724
 
        // Get values from coefficients array
13725
 
        new_coeff0_0 = coefficients0[dof][0];
13726
 
        new_coeff0_1 = coefficients0[dof][1];
13727
 
        new_coeff0_2 = coefficients0[dof][2];
13728
 
        new_coeff0_3 = coefficients0[dof][3];
13729
 
    
13730
 
        // Loop derivative order
13731
 
        for (unsigned int j = 0; j < n; j++)
13732
 
        {
13733
 
          // Update old coefficients
13734
 
          coeff0_0 = new_coeff0_0;
13735
 
          coeff0_1 = new_coeff0_1;
13736
 
          coeff0_2 = new_coeff0_2;
13737
 
          coeff0_3 = new_coeff0_3;
13738
 
    
13739
 
          if(combinations[deriv_num][j] == 0)
13740
 
          {
13741
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
13742
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
13743
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
13744
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
13745
 
          }
13746
 
          if(combinations[deriv_num][j] == 1)
13747
 
          {
13748
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
13749
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
13750
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
13751
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
13752
 
          }
13753
 
          if(combinations[deriv_num][j] == 2)
13754
 
          {
13755
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
13756
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
13757
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
13758
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
13759
 
          }
13760
 
    
13761
 
        }
13762
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
13763
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
13764
 
      }
13765
 
    
13766
 
      // Transform derivatives back to physical element
13767
 
      for (unsigned int row = 0; row < num_derivatives; row++)
13768
 
      {
13769
 
        for (unsigned int col = 0; col < num_derivatives; col++)
13770
 
        {
13771
 
          values[row] += transform[row][col]*derivatives[col];
13772
 
        }
13773
 
      }
13774
 
      // Delete pointer to array of derivatives on FIAT element
13775
 
      delete [] derivatives;
13776
 
    
13777
 
      // Delete pointer to array of combinations of derivatives and transform
13778
 
      for (unsigned int row = 0; row < num_derivatives; row++)
13779
 
      {
13780
 
        delete [] combinations[row];
13781
 
        delete [] transform[row];
13782
 
      }
13783
 
    
13784
 
      delete [] combinations;
13785
 
      delete [] transform;
13786
 
    }
13787
 
    
13788
 
    if (4 <= i && i <= 7)
13789
 
    {
13790
 
      // Map degree of freedom to element degree of freedom
13791
 
      const unsigned int dof = i - 4;
13792
 
    
13793
 
      // Generate scalings
13794
 
      const double scalings_y_0 = 1;
13795
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13796
 
      const double scalings_z_0 = 1;
13797
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13798
 
    
13799
 
      // Compute psitilde_a
13800
 
      const double psitilde_a_0 = 1;
13801
 
      const double psitilde_a_1 = x;
13802
 
    
13803
 
      // Compute psitilde_bs
13804
 
      const double psitilde_bs_0_0 = 1;
13805
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13806
 
      const double psitilde_bs_1_0 = 1;
13807
 
    
13808
 
      // Compute psitilde_cs
13809
 
      const double psitilde_cs_00_0 = 1;
13810
 
      const double psitilde_cs_00_1 = 2*z + 1;
13811
 
      const double psitilde_cs_01_0 = 1;
13812
 
      const double psitilde_cs_10_0 = 1;
13813
 
    
13814
 
      // Compute basisvalues
13815
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13816
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13817
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13818
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13819
 
    
13820
 
      // Table(s) of coefficients
13821
 
      static const double coefficients0[4][4] =   \
13822
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13823
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13824
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13825
 
      {0.288675135, 0, 0, 0.223606798}};
13826
 
    
13827
 
      // Interesting (new) part
13828
 
      // Tables of derivatives of the polynomial base (transpose)
13829
 
      static const double dmats0[4][4] =   \
13830
 
      {{0, 0, 0, 0},
13831
 
      {6.32455532, 0, 0, 0},
13832
 
      {0, 0, 0, 0},
13833
 
      {0, 0, 0, 0}};
13834
 
    
13835
 
      static const double dmats1[4][4] =   \
13836
 
      {{0, 0, 0, 0},
13837
 
      {3.16227766, 0, 0, 0},
13838
 
      {5.47722558, 0, 0, 0},
13839
 
      {0, 0, 0, 0}};
13840
 
    
13841
 
      static const double dmats2[4][4] =   \
13842
 
      {{0, 0, 0, 0},
13843
 
      {3.16227766, 0, 0, 0},
13844
 
      {1.82574186, 0, 0, 0},
13845
 
      {5.16397779, 0, 0, 0}};
13846
 
    
13847
 
      // Compute reference derivatives
13848
 
      // Declare pointer to array of derivatives on FIAT element
13849
 
      double *derivatives = new double [num_derivatives];
13850
 
    
13851
 
      // Declare coefficients
13852
 
      double coeff0_0 = 0;
13853
 
      double coeff0_1 = 0;
13854
 
      double coeff0_2 = 0;
13855
 
      double coeff0_3 = 0;
13856
 
    
13857
 
      // Declare new coefficients
13858
 
      double new_coeff0_0 = 0;
13859
 
      double new_coeff0_1 = 0;
13860
 
      double new_coeff0_2 = 0;
13861
 
      double new_coeff0_3 = 0;
13862
 
    
13863
 
      // Loop possible derivatives
13864
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
13865
 
      {
13866
 
        // Get values from coefficients array
13867
 
        new_coeff0_0 = coefficients0[dof][0];
13868
 
        new_coeff0_1 = coefficients0[dof][1];
13869
 
        new_coeff0_2 = coefficients0[dof][2];
13870
 
        new_coeff0_3 = coefficients0[dof][3];
13871
 
    
13872
 
        // Loop derivative order
13873
 
        for (unsigned int j = 0; j < n; j++)
13874
 
        {
13875
 
          // Update old coefficients
13876
 
          coeff0_0 = new_coeff0_0;
13877
 
          coeff0_1 = new_coeff0_1;
13878
 
          coeff0_2 = new_coeff0_2;
13879
 
          coeff0_3 = new_coeff0_3;
13880
 
    
13881
 
          if(combinations[deriv_num][j] == 0)
13882
 
          {
13883
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
13884
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
13885
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
13886
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
13887
 
          }
13888
 
          if(combinations[deriv_num][j] == 1)
13889
 
          {
13890
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
13891
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
13892
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
13893
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
13894
 
          }
13895
 
          if(combinations[deriv_num][j] == 2)
13896
 
          {
13897
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
13898
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
13899
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
13900
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
13901
 
          }
13902
 
    
13903
 
        }
13904
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
13905
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
13906
 
      }
13907
 
    
13908
 
      // Transform derivatives back to physical element
13909
 
      for (unsigned int row = 0; row < num_derivatives; row++)
13910
 
      {
13911
 
        for (unsigned int col = 0; col < num_derivatives; col++)
13912
 
        {
13913
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
13914
 
        }
13915
 
      }
13916
 
      // Delete pointer to array of derivatives on FIAT element
13917
 
      delete [] derivatives;
13918
 
    
13919
 
      // Delete pointer to array of combinations of derivatives and transform
13920
 
      for (unsigned int row = 0; row < num_derivatives; row++)
13921
 
      {
13922
 
        delete [] combinations[row];
13923
 
        delete [] transform[row];
13924
 
      }
13925
 
    
13926
 
      delete [] combinations;
13927
 
      delete [] transform;
13928
 
    }
13929
 
    
13930
 
    if (8 <= i && i <= 11)
13931
 
    {
13932
 
      // Map degree of freedom to element degree of freedom
13933
 
      const unsigned int dof = i - 8;
13934
 
    
13935
 
      // Generate scalings
13936
 
      const double scalings_y_0 = 1;
13937
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
13938
 
      const double scalings_z_0 = 1;
13939
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
13940
 
    
13941
 
      // Compute psitilde_a
13942
 
      const double psitilde_a_0 = 1;
13943
 
      const double psitilde_a_1 = x;
13944
 
    
13945
 
      // Compute psitilde_bs
13946
 
      const double psitilde_bs_0_0 = 1;
13947
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
13948
 
      const double psitilde_bs_1_0 = 1;
13949
 
    
13950
 
      // Compute psitilde_cs
13951
 
      const double psitilde_cs_00_0 = 1;
13952
 
      const double psitilde_cs_00_1 = 2*z + 1;
13953
 
      const double psitilde_cs_01_0 = 1;
13954
 
      const double psitilde_cs_10_0 = 1;
13955
 
    
13956
 
      // Compute basisvalues
13957
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
13958
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
13959
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
13960
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
13961
 
    
13962
 
      // Table(s) of coefficients
13963
 
      static const double coefficients0[4][4] =   \
13964
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
13965
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
13966
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
13967
 
      {0.288675135, 0, 0, 0.223606798}};
13968
 
    
13969
 
      // Interesting (new) part
13970
 
      // Tables of derivatives of the polynomial base (transpose)
13971
 
      static const double dmats0[4][4] =   \
13972
 
      {{0, 0, 0, 0},
13973
 
      {6.32455532, 0, 0, 0},
13974
 
      {0, 0, 0, 0},
13975
 
      {0, 0, 0, 0}};
13976
 
    
13977
 
      static const double dmats1[4][4] =   \
13978
 
      {{0, 0, 0, 0},
13979
 
      {3.16227766, 0, 0, 0},
13980
 
      {5.47722558, 0, 0, 0},
13981
 
      {0, 0, 0, 0}};
13982
 
    
13983
 
      static const double dmats2[4][4] =   \
13984
 
      {{0, 0, 0, 0},
13985
 
      {3.16227766, 0, 0, 0},
13986
 
      {1.82574186, 0, 0, 0},
13987
 
      {5.16397779, 0, 0, 0}};
13988
 
    
13989
 
      // Compute reference derivatives
13990
 
      // Declare pointer to array of derivatives on FIAT element
13991
 
      double *derivatives = new double [num_derivatives];
13992
 
    
13993
 
      // Declare coefficients
13994
 
      double coeff0_0 = 0;
13995
 
      double coeff0_1 = 0;
13996
 
      double coeff0_2 = 0;
13997
 
      double coeff0_3 = 0;
13998
 
    
13999
 
      // Declare new coefficients
14000
 
      double new_coeff0_0 = 0;
14001
 
      double new_coeff0_1 = 0;
14002
 
      double new_coeff0_2 = 0;
14003
 
      double new_coeff0_3 = 0;
14004
 
    
14005
 
      // Loop possible derivatives
14006
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
14007
 
      {
14008
 
        // Get values from coefficients array
14009
 
        new_coeff0_0 = coefficients0[dof][0];
14010
 
        new_coeff0_1 = coefficients0[dof][1];
14011
 
        new_coeff0_2 = coefficients0[dof][2];
14012
 
        new_coeff0_3 = coefficients0[dof][3];
14013
 
    
14014
 
        // Loop derivative order
14015
 
        for (unsigned int j = 0; j < n; j++)
14016
 
        {
14017
 
          // Update old coefficients
14018
 
          coeff0_0 = new_coeff0_0;
14019
 
          coeff0_1 = new_coeff0_1;
14020
 
          coeff0_2 = new_coeff0_2;
14021
 
          coeff0_3 = new_coeff0_3;
14022
 
    
14023
 
          if(combinations[deriv_num][j] == 0)
14024
 
          {
14025
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
14026
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
14027
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
14028
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
14029
 
          }
14030
 
          if(combinations[deriv_num][j] == 1)
14031
 
          {
14032
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
14033
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
14034
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
14035
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
14036
 
          }
14037
 
          if(combinations[deriv_num][j] == 2)
14038
 
          {
14039
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
14040
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
14041
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
14042
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
14043
 
          }
14044
 
    
14045
 
        }
14046
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
14047
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
14048
 
      }
14049
 
    
14050
 
      // Transform derivatives back to physical element
14051
 
      for (unsigned int row = 0; row < num_derivatives; row++)
14052
 
      {
14053
 
        for (unsigned int col = 0; col < num_derivatives; col++)
14054
 
        {
14055
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
14056
 
        }
14057
 
      }
14058
 
      // Delete pointer to array of derivatives on FIAT element
14059
 
      delete [] derivatives;
14060
 
    
14061
 
      // Delete pointer to array of combinations of derivatives and transform
14062
 
      for (unsigned int row = 0; row < num_derivatives; row++)
14063
 
      {
14064
 
        delete [] combinations[row];
14065
 
        delete [] transform[row];
14066
 
      }
14067
 
    
14068
 
      delete [] combinations;
14069
 
      delete [] transform;
14070
 
    }
14071
 
    
14072
 
  }
14073
 
 
14074
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
14075
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
14076
 
                                              double* values,
14077
 
                                              const double* coordinates,
14078
 
                                              const ufc::cell& c) const
14079
 
  {
14080
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
14081
 
  }
14082
 
 
14083
 
  /// Evaluate linear functional for dof i on the function f
14084
 
  virtual double evaluate_dof(unsigned int i,
14085
 
                              const ufc::function& f,
14086
 
                              const ufc::cell& c) const
14087
 
  {
14088
 
    // The reference points, direction and weights:
14089
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
14090
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
14091
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
14092
 
    
14093
 
    const double * const * x = c.coordinates;
14094
 
    double result = 0.0;
14095
 
    // Iterate over the points:
14096
 
    // Evaluate basis functions for affine mapping
14097
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
14098
 
    const double w1 = X[i][0][0];
14099
 
    const double w2 = X[i][0][1];
14100
 
    const double w3 = X[i][0][2];
14101
 
    
14102
 
    // Compute affine mapping y = F(X)
14103
 
    double y[3];
14104
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
14105
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
14106
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
14107
 
    
14108
 
    // Evaluate function at physical points
14109
 
    double values[3];
14110
 
    f.evaluate(values, y, c);
14111
 
    
14112
 
    // Map function values using appropriate mapping
14113
 
    // Affine map: Do nothing
14114
 
    
14115
 
    // Note that we do not map the weights (yet).
14116
 
    
14117
 
    // Take directional components
14118
 
    for(int k = 0; k < 3; k++)
14119
 
      result += values[k]*D[i][0][k];
14120
 
    // Multiply by weights
14121
 
    result *= W[i][0];
14122
 
    
14123
 
    return result;
14124
 
  }
14125
 
 
14126
 
  /// Evaluate linear functionals for all dofs on the function f
14127
 
  virtual void evaluate_dofs(double* values,
14128
 
                             const ufc::function& f,
14129
 
                             const ufc::cell& c) const
14130
 
  {
14131
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
14132
 
  }
14133
 
 
14134
 
  /// Interpolate vertex values from dof values
14135
 
  virtual void interpolate_vertex_values(double* vertex_values,
14136
 
                                         const double* dof_values,
14137
 
                                         const ufc::cell& c) const
14138
 
  {
14139
 
    // Evaluate at vertices and use affine mapping
14140
 
    vertex_values[0] = dof_values[0];
14141
 
    vertex_values[3] = dof_values[1];
14142
 
    vertex_values[6] = dof_values[2];
14143
 
    vertex_values[9] = dof_values[3];
14144
 
    // Evaluate at vertices and use affine mapping
14145
 
    vertex_values[1] = dof_values[4];
14146
 
    vertex_values[4] = dof_values[5];
14147
 
    vertex_values[7] = dof_values[6];
14148
 
    vertex_values[10] = dof_values[7];
14149
 
    // Evaluate at vertices and use affine mapping
14150
 
    vertex_values[2] = dof_values[8];
14151
 
    vertex_values[5] = dof_values[9];
14152
 
    vertex_values[8] = dof_values[10];
14153
 
    vertex_values[11] = dof_values[11];
14154
 
  }
14155
 
 
14156
 
  /// Return the number of sub elements (for a mixed element)
14157
 
  virtual unsigned int num_sub_elements() const
14158
 
  {
14159
 
    return 3;
14160
 
  }
14161
 
 
14162
 
  /// Create a new finite element for sub element i (for a mixed element)
14163
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
14164
 
  {
14165
 
    switch ( i )
14166
 
    {
14167
 
    case 0:
14168
 
      return new hyperelasticity_1_finite_element_0_0();
14169
 
      break;
14170
 
    case 1:
14171
 
      return new hyperelasticity_1_finite_element_0_1();
14172
 
      break;
14173
 
    case 2:
14174
 
      return new hyperelasticity_1_finite_element_0_2();
14175
 
      break;
14176
 
    }
14177
 
    return 0;
14178
 
  }
14179
 
 
14180
 
};
14181
 
 
14182
 
/// This class defines the interface for a finite element.
14183
 
 
14184
 
class hyperelasticity_1_finite_element_1_0: public ufc::finite_element
14185
 
{
14186
 
public:
14187
 
 
14188
 
  /// Constructor
14189
 
  hyperelasticity_1_finite_element_1_0() : ufc::finite_element()
14190
 
  {
14191
 
    // Do nothing
14192
 
  }
14193
 
 
14194
 
  /// Destructor
14195
 
  virtual ~hyperelasticity_1_finite_element_1_0()
14196
 
  {
14197
 
    // Do nothing
14198
 
  }
14199
 
 
14200
 
  /// Return a string identifying the finite element
14201
 
  virtual const char* signature() const
14202
 
  {
14203
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
14204
 
  }
14205
 
 
14206
 
  /// Return the cell shape
14207
 
  virtual ufc::shape cell_shape() const
14208
 
  {
14209
 
    return ufc::tetrahedron;
14210
 
  }
14211
 
 
14212
 
  /// Return the dimension of the finite element function space
14213
 
  virtual unsigned int space_dimension() const
14214
 
  {
14215
 
    return 4;
14216
 
  }
14217
 
 
14218
 
  /// Return the rank of the value space
14219
 
  virtual unsigned int value_rank() const
14220
 
  {
14221
 
    return 0;
14222
 
  }
14223
 
 
14224
 
  /// Return the dimension of the value space for axis i
14225
 
  virtual unsigned int value_dimension(unsigned int i) const
14226
 
  {
14227
 
    return 1;
14228
 
  }
14229
 
 
14230
 
  /// Evaluate basis function i at given point in cell
14231
 
  virtual void evaluate_basis(unsigned int i,
14232
 
                              double* values,
14233
 
                              const double* coordinates,
14234
 
                              const ufc::cell& c) const
14235
 
  {
14236
 
    // Extract vertex coordinates
14237
 
    const double * const * element_coordinates = c.coordinates;
14238
 
    
14239
 
    // Compute Jacobian of affine map from reference cell
14240
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
14241
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
14242
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
14243
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
14244
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
14245
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
14246
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
14247
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
14248
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
14249
 
    
14250
 
    // Compute sub determinants
14251
 
    const double d00 = J_11*J_22 - J_12*J_21;
14252
 
    const double d01 = J_12*J_20 - J_10*J_22;
14253
 
    const double d02 = J_10*J_21 - J_11*J_20;
14254
 
    
14255
 
    const double d10 = J_02*J_21 - J_01*J_22;
14256
 
    const double d11 = J_00*J_22 - J_02*J_20;
14257
 
    const double d12 = J_01*J_20 - J_00*J_21;
14258
 
    
14259
 
    const double d20 = J_01*J_12 - J_02*J_11;
14260
 
    const double d21 = J_02*J_10 - J_00*J_12;
14261
 
    const double d22 = J_00*J_11 - J_01*J_10;
14262
 
    
14263
 
    // Compute determinant of Jacobian
14264
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
14265
 
    
14266
 
    // Compute inverse of Jacobian
14267
 
    
14268
 
    // Compute constants
14269
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
14270
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
14271
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
14272
 
    
14273
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
14274
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
14275
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
14276
 
    
14277
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
14278
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
14279
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
14280
 
    
14281
 
    // Get coordinates and map to the UFC reference element
14282
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
14283
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
14284
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
14285
 
    
14286
 
    // Map coordinates to the reference cube
14287
 
    if (std::abs(y + z - 1.0) < 1e-08)
14288
 
      x = 1.0;
14289
 
    else
14290
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
14291
 
    if (std::abs(z - 1.0) < 1e-08)
14292
 
      y = -1.0;
14293
 
    else
14294
 
      y = 2.0 * y/(1.0 - z) - 1.0;
14295
 
    z = 2.0 * z - 1.0;
14296
 
    
14297
 
    // Reset values
14298
 
    *values = 0;
14299
 
    
14300
 
    // Map degree of freedom to element degree of freedom
14301
 
    const unsigned int dof = i;
14302
 
    
14303
 
    // Generate scalings
14304
 
    const double scalings_y_0 = 1;
14305
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
14306
 
    const double scalings_z_0 = 1;
14307
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
14308
 
    
14309
 
    // Compute psitilde_a
14310
 
    const double psitilde_a_0 = 1;
14311
 
    const double psitilde_a_1 = x;
14312
 
    
14313
 
    // Compute psitilde_bs
14314
 
    const double psitilde_bs_0_0 = 1;
14315
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
14316
 
    const double psitilde_bs_1_0 = 1;
14317
 
    
14318
 
    // Compute psitilde_cs
14319
 
    const double psitilde_cs_00_0 = 1;
14320
 
    const double psitilde_cs_00_1 = 2*z + 1;
14321
 
    const double psitilde_cs_01_0 = 1;
14322
 
    const double psitilde_cs_10_0 = 1;
14323
 
    
14324
 
    // Compute basisvalues
14325
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
14326
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
14327
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
14328
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
14329
 
    
14330
 
    // Table(s) of coefficients
14331
 
    static const double coefficients0[4][4] = \
14332
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
14333
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
14334
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
14335
 
    {0.288675135, 0, 0, 0.223606798}};
14336
 
    
14337
 
    // Extract relevant coefficients
14338
 
    const double coeff0_0 = coefficients0[dof][0];
14339
 
    const double coeff0_1 = coefficients0[dof][1];
14340
 
    const double coeff0_2 = coefficients0[dof][2];
14341
 
    const double coeff0_3 = coefficients0[dof][3];
14342
 
    
14343
 
    // Compute value(s)
14344
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
14345
 
  }
14346
 
 
14347
 
  /// Evaluate all basis functions at given point in cell
14348
 
  virtual void evaluate_basis_all(double* values,
14349
 
                                  const double* coordinates,
14350
 
                                  const ufc::cell& c) const
14351
 
  {
14352
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
14353
 
  }
14354
 
 
14355
 
  /// Evaluate order n derivatives of basis function i at given point in cell
14356
 
  virtual void evaluate_basis_derivatives(unsigned int i,
14357
 
                                          unsigned int n,
14358
 
                                          double* values,
14359
 
                                          const double* coordinates,
14360
 
                                          const ufc::cell& c) const
14361
 
  {
14362
 
    // Extract vertex coordinates
14363
 
    const double * const * element_coordinates = c.coordinates;
14364
 
    
14365
 
    // Compute Jacobian of affine map from reference cell
14366
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
14367
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
14368
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
14369
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
14370
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
14371
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
14372
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
14373
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
14374
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
14375
 
    
14376
 
    // Compute sub determinants
14377
 
    const double d00 = J_11*J_22 - J_12*J_21;
14378
 
    const double d01 = J_12*J_20 - J_10*J_22;
14379
 
    const double d02 = J_10*J_21 - J_11*J_20;
14380
 
    
14381
 
    const double d10 = J_02*J_21 - J_01*J_22;
14382
 
    const double d11 = J_00*J_22 - J_02*J_20;
14383
 
    const double d12 = J_01*J_20 - J_00*J_21;
14384
 
    
14385
 
    const double d20 = J_01*J_12 - J_02*J_11;
14386
 
    const double d21 = J_02*J_10 - J_00*J_12;
14387
 
    const double d22 = J_00*J_11 - J_01*J_10;
14388
 
    
14389
 
    // Compute determinant of Jacobian
14390
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
14391
 
    
14392
 
    // Compute inverse of Jacobian
14393
 
    
14394
 
    // Compute constants
14395
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
14396
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
14397
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
14398
 
    
14399
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
14400
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
14401
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
14402
 
    
14403
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
14404
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
14405
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
14406
 
    
14407
 
    // Get coordinates and map to the UFC reference element
14408
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
14409
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
14410
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
14411
 
    
14412
 
    // Map coordinates to the reference cube
14413
 
    if (std::abs(y + z - 1.0) < 1e-08)
14414
 
      x = 1.0;
14415
 
    else
14416
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
14417
 
    if (std::abs(z - 1.0) < 1e-08)
14418
 
      y = -1.0;
14419
 
    else
14420
 
      y = 2.0 * y/(1.0 - z) - 1.0;
14421
 
    z = 2.0 * z - 1.0;
14422
 
    
14423
 
    // Compute number of derivatives
14424
 
    unsigned int num_derivatives = 1;
14425
 
    
14426
 
    for (unsigned int j = 0; j < n; j++)
14427
 
      num_derivatives *= 3;
14428
 
    
14429
 
    
14430
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
14431
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
14432
 
    
14433
 
    for (unsigned int j = 0; j < num_derivatives; j++)
14434
 
    {
14435
 
      combinations[j] = new unsigned int [n];
14436
 
      for (unsigned int k = 0; k < n; k++)
14437
 
        combinations[j][k] = 0;
14438
 
    }
14439
 
    
14440
 
    // Generate combinations of derivatives
14441
 
    for (unsigned int row = 1; row < num_derivatives; row++)
14442
 
    {
14443
 
      for (unsigned int num = 0; num < row; num++)
14444
 
      {
14445
 
        for (unsigned int col = n-1; col+1 > 0; col--)
14446
 
        {
14447
 
          if (combinations[row][col] + 1 > 2)
14448
 
            combinations[row][col] = 0;
14449
 
          else
14450
 
          {
14451
 
            combinations[row][col] += 1;
14452
 
            break;
14453
 
          }
14454
 
        }
14455
 
      }
14456
 
    }
14457
 
    
14458
 
    // Compute inverse of Jacobian
14459
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
14460
 
    
14461
 
    // Declare transformation matrix
14462
 
    // Declare pointer to two dimensional array and initialise
14463
 
    double **transform = new double *[num_derivatives];
14464
 
    
14465
 
    for (unsigned int j = 0; j < num_derivatives; j++)
14466
 
    {
14467
 
      transform[j] = new double [num_derivatives];
14468
 
      for (unsigned int k = 0; k < num_derivatives; k++)
14469
 
        transform[j][k] = 1;
14470
 
    }
14471
 
    
14472
 
    // Construct transformation matrix
14473
 
    for (unsigned int row = 0; row < num_derivatives; row++)
14474
 
    {
14475
 
      for (unsigned int col = 0; col < num_derivatives; col++)
14476
 
      {
14477
 
        for (unsigned int k = 0; k < n; k++)
14478
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
14479
 
      }
14480
 
    }
14481
 
    
14482
 
    // Reset values
14483
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
14484
 
      values[j] = 0;
14485
 
    
14486
 
    // Map degree of freedom to element degree of freedom
14487
 
    const unsigned int dof = i;
14488
 
    
14489
 
    // Generate scalings
14490
 
    const double scalings_y_0 = 1;
14491
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
14492
 
    const double scalings_z_0 = 1;
14493
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
14494
 
    
14495
 
    // Compute psitilde_a
14496
 
    const double psitilde_a_0 = 1;
14497
 
    const double psitilde_a_1 = x;
14498
 
    
14499
 
    // Compute psitilde_bs
14500
 
    const double psitilde_bs_0_0 = 1;
14501
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
14502
 
    const double psitilde_bs_1_0 = 1;
14503
 
    
14504
 
    // Compute psitilde_cs
14505
 
    const double psitilde_cs_00_0 = 1;
14506
 
    const double psitilde_cs_00_1 = 2*z + 1;
14507
 
    const double psitilde_cs_01_0 = 1;
14508
 
    const double psitilde_cs_10_0 = 1;
14509
 
    
14510
 
    // Compute basisvalues
14511
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
14512
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
14513
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
14514
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
14515
 
    
14516
 
    // Table(s) of coefficients
14517
 
    static const double coefficients0[4][4] = \
14518
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
14519
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
14520
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
14521
 
    {0.288675135, 0, 0, 0.223606798}};
14522
 
    
14523
 
    // Interesting (new) part
14524
 
    // Tables of derivatives of the polynomial base (transpose)
14525
 
    static const double dmats0[4][4] = \
14526
 
    {{0, 0, 0, 0},
14527
 
    {6.32455532, 0, 0, 0},
14528
 
    {0, 0, 0, 0},
14529
 
    {0, 0, 0, 0}};
14530
 
    
14531
 
    static const double dmats1[4][4] = \
14532
 
    {{0, 0, 0, 0},
14533
 
    {3.16227766, 0, 0, 0},
14534
 
    {5.47722558, 0, 0, 0},
14535
 
    {0, 0, 0, 0}};
14536
 
    
14537
 
    static const double dmats2[4][4] = \
14538
 
    {{0, 0, 0, 0},
14539
 
    {3.16227766, 0, 0, 0},
14540
 
    {1.82574186, 0, 0, 0},
14541
 
    {5.16397779, 0, 0, 0}};
14542
 
    
14543
 
    // Compute reference derivatives
14544
 
    // Declare pointer to array of derivatives on FIAT element
14545
 
    double *derivatives = new double [num_derivatives];
14546
 
    
14547
 
    // Declare coefficients
14548
 
    double coeff0_0 = 0;
14549
 
    double coeff0_1 = 0;
14550
 
    double coeff0_2 = 0;
14551
 
    double coeff0_3 = 0;
14552
 
    
14553
 
    // Declare new coefficients
14554
 
    double new_coeff0_0 = 0;
14555
 
    double new_coeff0_1 = 0;
14556
 
    double new_coeff0_2 = 0;
14557
 
    double new_coeff0_3 = 0;
14558
 
    
14559
 
    // Loop possible derivatives
14560
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
14561
 
    {
14562
 
      // Get values from coefficients array
14563
 
      new_coeff0_0 = coefficients0[dof][0];
14564
 
      new_coeff0_1 = coefficients0[dof][1];
14565
 
      new_coeff0_2 = coefficients0[dof][2];
14566
 
      new_coeff0_3 = coefficients0[dof][3];
14567
 
    
14568
 
      // Loop derivative order
14569
 
      for (unsigned int j = 0; j < n; j++)
14570
 
      {
14571
 
        // Update old coefficients
14572
 
        coeff0_0 = new_coeff0_0;
14573
 
        coeff0_1 = new_coeff0_1;
14574
 
        coeff0_2 = new_coeff0_2;
14575
 
        coeff0_3 = new_coeff0_3;
14576
 
    
14577
 
        if(combinations[deriv_num][j] == 0)
14578
 
        {
14579
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
14580
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
14581
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
14582
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
14583
 
        }
14584
 
        if(combinations[deriv_num][j] == 1)
14585
 
        {
14586
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
14587
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
14588
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
14589
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
14590
 
        }
14591
 
        if(combinations[deriv_num][j] == 2)
14592
 
        {
14593
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
14594
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
14595
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
14596
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
14597
 
        }
14598
 
    
14599
 
      }
14600
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
14601
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
14602
 
    }
14603
 
    
14604
 
    // Transform derivatives back to physical element
14605
 
    for (unsigned int row = 0; row < num_derivatives; row++)
14606
 
    {
14607
 
      for (unsigned int col = 0; col < num_derivatives; col++)
14608
 
      {
14609
 
        values[row] += transform[row][col]*derivatives[col];
14610
 
      }
14611
 
    }
14612
 
    // Delete pointer to array of derivatives on FIAT element
14613
 
    delete [] derivatives;
14614
 
    
14615
 
    // Delete pointer to array of combinations of derivatives and transform
14616
 
    for (unsigned int row = 0; row < num_derivatives; row++)
14617
 
    {
14618
 
      delete [] combinations[row];
14619
 
      delete [] transform[row];
14620
 
    }
14621
 
    
14622
 
    delete [] combinations;
14623
 
    delete [] transform;
14624
 
  }
14625
 
 
14626
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
14627
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
14628
 
                                              double* values,
14629
 
                                              const double* coordinates,
14630
 
                                              const ufc::cell& c) const
14631
 
  {
14632
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
14633
 
  }
14634
 
 
14635
 
  /// Evaluate linear functional for dof i on the function f
14636
 
  virtual double evaluate_dof(unsigned int i,
14637
 
                              const ufc::function& f,
14638
 
                              const ufc::cell& c) const
14639
 
  {
14640
 
    // The reference points, direction and weights:
14641
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
14642
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
14643
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
14644
 
    
14645
 
    const double * const * x = c.coordinates;
14646
 
    double result = 0.0;
14647
 
    // Iterate over the points:
14648
 
    // Evaluate basis functions for affine mapping
14649
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
14650
 
    const double w1 = X[i][0][0];
14651
 
    const double w2 = X[i][0][1];
14652
 
    const double w3 = X[i][0][2];
14653
 
    
14654
 
    // Compute affine mapping y = F(X)
14655
 
    double y[3];
14656
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
14657
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
14658
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
14659
 
    
14660
 
    // Evaluate function at physical points
14661
 
    double values[1];
14662
 
    f.evaluate(values, y, c);
14663
 
    
14664
 
    // Map function values using appropriate mapping
14665
 
    // Affine map: Do nothing
14666
 
    
14667
 
    // Note that we do not map the weights (yet).
14668
 
    
14669
 
    // Take directional components
14670
 
    for(int k = 0; k < 1; k++)
14671
 
      result += values[k]*D[i][0][k];
14672
 
    // Multiply by weights
14673
 
    result *= W[i][0];
14674
 
    
14675
 
    return result;
14676
 
  }
14677
 
 
14678
 
  /// Evaluate linear functionals for all dofs on the function f
14679
 
  virtual void evaluate_dofs(double* values,
14680
 
                             const ufc::function& f,
14681
 
                             const ufc::cell& c) const
14682
 
  {
14683
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
14684
 
  }
14685
 
 
14686
 
  /// Interpolate vertex values from dof values
14687
 
  virtual void interpolate_vertex_values(double* vertex_values,
14688
 
                                         const double* dof_values,
14689
 
                                         const ufc::cell& c) const
14690
 
  {
14691
 
    // Evaluate at vertices and use affine mapping
14692
 
    vertex_values[0] = dof_values[0];
14693
 
    vertex_values[1] = dof_values[1];
14694
 
    vertex_values[2] = dof_values[2];
14695
 
    vertex_values[3] = dof_values[3];
14696
 
  }
14697
 
 
14698
 
  /// Return the number of sub elements (for a mixed element)
14699
 
  virtual unsigned int num_sub_elements() const
14700
 
  {
14701
 
    return 1;
14702
 
  }
14703
 
 
14704
 
  /// Create a new finite element for sub element i (for a mixed element)
14705
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
14706
 
  {
14707
 
    return new hyperelasticity_1_finite_element_1_0();
14708
 
  }
14709
 
 
14710
 
};
14711
 
 
14712
 
/// This class defines the interface for a finite element.
14713
 
 
14714
 
class hyperelasticity_1_finite_element_1_1: public ufc::finite_element
14715
 
{
14716
 
public:
14717
 
 
14718
 
  /// Constructor
14719
 
  hyperelasticity_1_finite_element_1_1() : ufc::finite_element()
14720
 
  {
14721
 
    // Do nothing
14722
 
  }
14723
 
 
14724
 
  /// Destructor
14725
 
  virtual ~hyperelasticity_1_finite_element_1_1()
14726
 
  {
14727
 
    // Do nothing
14728
 
  }
14729
 
 
14730
 
  /// Return a string identifying the finite element
14731
 
  virtual const char* signature() const
14732
 
  {
14733
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
14734
 
  }
14735
 
 
14736
 
  /// Return the cell shape
14737
 
  virtual ufc::shape cell_shape() const
14738
 
  {
14739
 
    return ufc::tetrahedron;
14740
 
  }
14741
 
 
14742
 
  /// Return the dimension of the finite element function space
14743
 
  virtual unsigned int space_dimension() const
14744
 
  {
14745
 
    return 4;
14746
 
  }
14747
 
 
14748
 
  /// Return the rank of the value space
14749
 
  virtual unsigned int value_rank() const
14750
 
  {
14751
 
    return 0;
14752
 
  }
14753
 
 
14754
 
  /// Return the dimension of the value space for axis i
14755
 
  virtual unsigned int value_dimension(unsigned int i) const
14756
 
  {
14757
 
    return 1;
14758
 
  }
14759
 
 
14760
 
  /// Evaluate basis function i at given point in cell
14761
 
  virtual void evaluate_basis(unsigned int i,
14762
 
                              double* values,
14763
 
                              const double* coordinates,
14764
 
                              const ufc::cell& c) const
14765
 
  {
14766
 
    // Extract vertex coordinates
14767
 
    const double * const * element_coordinates = c.coordinates;
14768
 
    
14769
 
    // Compute Jacobian of affine map from reference cell
14770
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
14771
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
14772
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
14773
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
14774
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
14775
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
14776
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
14777
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
14778
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
14779
 
    
14780
 
    // Compute sub determinants
14781
 
    const double d00 = J_11*J_22 - J_12*J_21;
14782
 
    const double d01 = J_12*J_20 - J_10*J_22;
14783
 
    const double d02 = J_10*J_21 - J_11*J_20;
14784
 
    
14785
 
    const double d10 = J_02*J_21 - J_01*J_22;
14786
 
    const double d11 = J_00*J_22 - J_02*J_20;
14787
 
    const double d12 = J_01*J_20 - J_00*J_21;
14788
 
    
14789
 
    const double d20 = J_01*J_12 - J_02*J_11;
14790
 
    const double d21 = J_02*J_10 - J_00*J_12;
14791
 
    const double d22 = J_00*J_11 - J_01*J_10;
14792
 
    
14793
 
    // Compute determinant of Jacobian
14794
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
14795
 
    
14796
 
    // Compute inverse of Jacobian
14797
 
    
14798
 
    // Compute constants
14799
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
14800
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
14801
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
14802
 
    
14803
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
14804
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
14805
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
14806
 
    
14807
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
14808
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
14809
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
14810
 
    
14811
 
    // Get coordinates and map to the UFC reference element
14812
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
14813
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
14814
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
14815
 
    
14816
 
    // Map coordinates to the reference cube
14817
 
    if (std::abs(y + z - 1.0) < 1e-08)
14818
 
      x = 1.0;
14819
 
    else
14820
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
14821
 
    if (std::abs(z - 1.0) < 1e-08)
14822
 
      y = -1.0;
14823
 
    else
14824
 
      y = 2.0 * y/(1.0 - z) - 1.0;
14825
 
    z = 2.0 * z - 1.0;
14826
 
    
14827
 
    // Reset values
14828
 
    *values = 0;
14829
 
    
14830
 
    // Map degree of freedom to element degree of freedom
14831
 
    const unsigned int dof = i;
14832
 
    
14833
 
    // Generate scalings
14834
 
    const double scalings_y_0 = 1;
14835
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
14836
 
    const double scalings_z_0 = 1;
14837
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
14838
 
    
14839
 
    // Compute psitilde_a
14840
 
    const double psitilde_a_0 = 1;
14841
 
    const double psitilde_a_1 = x;
14842
 
    
14843
 
    // Compute psitilde_bs
14844
 
    const double psitilde_bs_0_0 = 1;
14845
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
14846
 
    const double psitilde_bs_1_0 = 1;
14847
 
    
14848
 
    // Compute psitilde_cs
14849
 
    const double psitilde_cs_00_0 = 1;
14850
 
    const double psitilde_cs_00_1 = 2*z + 1;
14851
 
    const double psitilde_cs_01_0 = 1;
14852
 
    const double psitilde_cs_10_0 = 1;
14853
 
    
14854
 
    // Compute basisvalues
14855
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
14856
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
14857
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
14858
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
14859
 
    
14860
 
    // Table(s) of coefficients
14861
 
    static const double coefficients0[4][4] = \
14862
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
14863
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
14864
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
14865
 
    {0.288675135, 0, 0, 0.223606798}};
14866
 
    
14867
 
    // Extract relevant coefficients
14868
 
    const double coeff0_0 = coefficients0[dof][0];
14869
 
    const double coeff0_1 = coefficients0[dof][1];
14870
 
    const double coeff0_2 = coefficients0[dof][2];
14871
 
    const double coeff0_3 = coefficients0[dof][3];
14872
 
    
14873
 
    // Compute value(s)
14874
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
14875
 
  }
14876
 
 
14877
 
  /// Evaluate all basis functions at given point in cell
14878
 
  virtual void evaluate_basis_all(double* values,
14879
 
                                  const double* coordinates,
14880
 
                                  const ufc::cell& c) const
14881
 
  {
14882
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
14883
 
  }
14884
 
 
14885
 
  /// Evaluate order n derivatives of basis function i at given point in cell
14886
 
  virtual void evaluate_basis_derivatives(unsigned int i,
14887
 
                                          unsigned int n,
14888
 
                                          double* values,
14889
 
                                          const double* coordinates,
14890
 
                                          const ufc::cell& c) const
14891
 
  {
14892
 
    // Extract vertex coordinates
14893
 
    const double * const * element_coordinates = c.coordinates;
14894
 
    
14895
 
    // Compute Jacobian of affine map from reference cell
14896
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
14897
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
14898
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
14899
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
14900
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
14901
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
14902
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
14903
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
14904
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
14905
 
    
14906
 
    // Compute sub determinants
14907
 
    const double d00 = J_11*J_22 - J_12*J_21;
14908
 
    const double d01 = J_12*J_20 - J_10*J_22;
14909
 
    const double d02 = J_10*J_21 - J_11*J_20;
14910
 
    
14911
 
    const double d10 = J_02*J_21 - J_01*J_22;
14912
 
    const double d11 = J_00*J_22 - J_02*J_20;
14913
 
    const double d12 = J_01*J_20 - J_00*J_21;
14914
 
    
14915
 
    const double d20 = J_01*J_12 - J_02*J_11;
14916
 
    const double d21 = J_02*J_10 - J_00*J_12;
14917
 
    const double d22 = J_00*J_11 - J_01*J_10;
14918
 
    
14919
 
    // Compute determinant of Jacobian
14920
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
14921
 
    
14922
 
    // Compute inverse of Jacobian
14923
 
    
14924
 
    // Compute constants
14925
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
14926
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
14927
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
14928
 
    
14929
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
14930
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
14931
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
14932
 
    
14933
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
14934
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
14935
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
14936
 
    
14937
 
    // Get coordinates and map to the UFC reference element
14938
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
14939
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
14940
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
14941
 
    
14942
 
    // Map coordinates to the reference cube
14943
 
    if (std::abs(y + z - 1.0) < 1e-08)
14944
 
      x = 1.0;
14945
 
    else
14946
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
14947
 
    if (std::abs(z - 1.0) < 1e-08)
14948
 
      y = -1.0;
14949
 
    else
14950
 
      y = 2.0 * y/(1.0 - z) - 1.0;
14951
 
    z = 2.0 * z - 1.0;
14952
 
    
14953
 
    // Compute number of derivatives
14954
 
    unsigned int num_derivatives = 1;
14955
 
    
14956
 
    for (unsigned int j = 0; j < n; j++)
14957
 
      num_derivatives *= 3;
14958
 
    
14959
 
    
14960
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
14961
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
14962
 
    
14963
 
    for (unsigned int j = 0; j < num_derivatives; j++)
14964
 
    {
14965
 
      combinations[j] = new unsigned int [n];
14966
 
      for (unsigned int k = 0; k < n; k++)
14967
 
        combinations[j][k] = 0;
14968
 
    }
14969
 
    
14970
 
    // Generate combinations of derivatives
14971
 
    for (unsigned int row = 1; row < num_derivatives; row++)
14972
 
    {
14973
 
      for (unsigned int num = 0; num < row; num++)
14974
 
      {
14975
 
        for (unsigned int col = n-1; col+1 > 0; col--)
14976
 
        {
14977
 
          if (combinations[row][col] + 1 > 2)
14978
 
            combinations[row][col] = 0;
14979
 
          else
14980
 
          {
14981
 
            combinations[row][col] += 1;
14982
 
            break;
14983
 
          }
14984
 
        }
14985
 
      }
14986
 
    }
14987
 
    
14988
 
    // Compute inverse of Jacobian
14989
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
14990
 
    
14991
 
    // Declare transformation matrix
14992
 
    // Declare pointer to two dimensional array and initialise
14993
 
    double **transform = new double *[num_derivatives];
14994
 
    
14995
 
    for (unsigned int j = 0; j < num_derivatives; j++)
14996
 
    {
14997
 
      transform[j] = new double [num_derivatives];
14998
 
      for (unsigned int k = 0; k < num_derivatives; k++)
14999
 
        transform[j][k] = 1;
15000
 
    }
15001
 
    
15002
 
    // Construct transformation matrix
15003
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15004
 
    {
15005
 
      for (unsigned int col = 0; col < num_derivatives; col++)
15006
 
      {
15007
 
        for (unsigned int k = 0; k < n; k++)
15008
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
15009
 
      }
15010
 
    }
15011
 
    
15012
 
    // Reset values
15013
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
15014
 
      values[j] = 0;
15015
 
    
15016
 
    // Map degree of freedom to element degree of freedom
15017
 
    const unsigned int dof = i;
15018
 
    
15019
 
    // Generate scalings
15020
 
    const double scalings_y_0 = 1;
15021
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15022
 
    const double scalings_z_0 = 1;
15023
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
15024
 
    
15025
 
    // Compute psitilde_a
15026
 
    const double psitilde_a_0 = 1;
15027
 
    const double psitilde_a_1 = x;
15028
 
    
15029
 
    // Compute psitilde_bs
15030
 
    const double psitilde_bs_0_0 = 1;
15031
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
15032
 
    const double psitilde_bs_1_0 = 1;
15033
 
    
15034
 
    // Compute psitilde_cs
15035
 
    const double psitilde_cs_00_0 = 1;
15036
 
    const double psitilde_cs_00_1 = 2*z + 1;
15037
 
    const double psitilde_cs_01_0 = 1;
15038
 
    const double psitilde_cs_10_0 = 1;
15039
 
    
15040
 
    // Compute basisvalues
15041
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
15042
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
15043
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
15044
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
15045
 
    
15046
 
    // Table(s) of coefficients
15047
 
    static const double coefficients0[4][4] = \
15048
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
15049
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
15050
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
15051
 
    {0.288675135, 0, 0, 0.223606798}};
15052
 
    
15053
 
    // Interesting (new) part
15054
 
    // Tables of derivatives of the polynomial base (transpose)
15055
 
    static const double dmats0[4][4] = \
15056
 
    {{0, 0, 0, 0},
15057
 
    {6.32455532, 0, 0, 0},
15058
 
    {0, 0, 0, 0},
15059
 
    {0, 0, 0, 0}};
15060
 
    
15061
 
    static const double dmats1[4][4] = \
15062
 
    {{0, 0, 0, 0},
15063
 
    {3.16227766, 0, 0, 0},
15064
 
    {5.47722558, 0, 0, 0},
15065
 
    {0, 0, 0, 0}};
15066
 
    
15067
 
    static const double dmats2[4][4] = \
15068
 
    {{0, 0, 0, 0},
15069
 
    {3.16227766, 0, 0, 0},
15070
 
    {1.82574186, 0, 0, 0},
15071
 
    {5.16397779, 0, 0, 0}};
15072
 
    
15073
 
    // Compute reference derivatives
15074
 
    // Declare pointer to array of derivatives on FIAT element
15075
 
    double *derivatives = new double [num_derivatives];
15076
 
    
15077
 
    // Declare coefficients
15078
 
    double coeff0_0 = 0;
15079
 
    double coeff0_1 = 0;
15080
 
    double coeff0_2 = 0;
15081
 
    double coeff0_3 = 0;
15082
 
    
15083
 
    // Declare new coefficients
15084
 
    double new_coeff0_0 = 0;
15085
 
    double new_coeff0_1 = 0;
15086
 
    double new_coeff0_2 = 0;
15087
 
    double new_coeff0_3 = 0;
15088
 
    
15089
 
    // Loop possible derivatives
15090
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
15091
 
    {
15092
 
      // Get values from coefficients array
15093
 
      new_coeff0_0 = coefficients0[dof][0];
15094
 
      new_coeff0_1 = coefficients0[dof][1];
15095
 
      new_coeff0_2 = coefficients0[dof][2];
15096
 
      new_coeff0_3 = coefficients0[dof][3];
15097
 
    
15098
 
      // Loop derivative order
15099
 
      for (unsigned int j = 0; j < n; j++)
15100
 
      {
15101
 
        // Update old coefficients
15102
 
        coeff0_0 = new_coeff0_0;
15103
 
        coeff0_1 = new_coeff0_1;
15104
 
        coeff0_2 = new_coeff0_2;
15105
 
        coeff0_3 = new_coeff0_3;
15106
 
    
15107
 
        if(combinations[deriv_num][j] == 0)
15108
 
        {
15109
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
15110
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
15111
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
15112
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
15113
 
        }
15114
 
        if(combinations[deriv_num][j] == 1)
15115
 
        {
15116
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
15117
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
15118
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
15119
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
15120
 
        }
15121
 
        if(combinations[deriv_num][j] == 2)
15122
 
        {
15123
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
15124
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
15125
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
15126
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
15127
 
        }
15128
 
    
15129
 
      }
15130
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
15131
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
15132
 
    }
15133
 
    
15134
 
    // Transform derivatives back to physical element
15135
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15136
 
    {
15137
 
      for (unsigned int col = 0; col < num_derivatives; col++)
15138
 
      {
15139
 
        values[row] += transform[row][col]*derivatives[col];
15140
 
      }
15141
 
    }
15142
 
    // Delete pointer to array of derivatives on FIAT element
15143
 
    delete [] derivatives;
15144
 
    
15145
 
    // Delete pointer to array of combinations of derivatives and transform
15146
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15147
 
    {
15148
 
      delete [] combinations[row];
15149
 
      delete [] transform[row];
15150
 
    }
15151
 
    
15152
 
    delete [] combinations;
15153
 
    delete [] transform;
15154
 
  }
15155
 
 
15156
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
15157
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
15158
 
                                              double* values,
15159
 
                                              const double* coordinates,
15160
 
                                              const ufc::cell& c) const
15161
 
  {
15162
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
15163
 
  }
15164
 
 
15165
 
  /// Evaluate linear functional for dof i on the function f
15166
 
  virtual double evaluate_dof(unsigned int i,
15167
 
                              const ufc::function& f,
15168
 
                              const ufc::cell& c) const
15169
 
  {
15170
 
    // The reference points, direction and weights:
15171
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
15172
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
15173
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
15174
 
    
15175
 
    const double * const * x = c.coordinates;
15176
 
    double result = 0.0;
15177
 
    // Iterate over the points:
15178
 
    // Evaluate basis functions for affine mapping
15179
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
15180
 
    const double w1 = X[i][0][0];
15181
 
    const double w2 = X[i][0][1];
15182
 
    const double w3 = X[i][0][2];
15183
 
    
15184
 
    // Compute affine mapping y = F(X)
15185
 
    double y[3];
15186
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
15187
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
15188
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
15189
 
    
15190
 
    // Evaluate function at physical points
15191
 
    double values[1];
15192
 
    f.evaluate(values, y, c);
15193
 
    
15194
 
    // Map function values using appropriate mapping
15195
 
    // Affine map: Do nothing
15196
 
    
15197
 
    // Note that we do not map the weights (yet).
15198
 
    
15199
 
    // Take directional components
15200
 
    for(int k = 0; k < 1; k++)
15201
 
      result += values[k]*D[i][0][k];
15202
 
    // Multiply by weights
15203
 
    result *= W[i][0];
15204
 
    
15205
 
    return result;
15206
 
  }
15207
 
 
15208
 
  /// Evaluate linear functionals for all dofs on the function f
15209
 
  virtual void evaluate_dofs(double* values,
15210
 
                             const ufc::function& f,
15211
 
                             const ufc::cell& c) const
15212
 
  {
15213
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
15214
 
  }
15215
 
 
15216
 
  /// Interpolate vertex values from dof values
15217
 
  virtual void interpolate_vertex_values(double* vertex_values,
15218
 
                                         const double* dof_values,
15219
 
                                         const ufc::cell& c) const
15220
 
  {
15221
 
    // Evaluate at vertices and use affine mapping
15222
 
    vertex_values[0] = dof_values[0];
15223
 
    vertex_values[1] = dof_values[1];
15224
 
    vertex_values[2] = dof_values[2];
15225
 
    vertex_values[3] = dof_values[3];
15226
 
  }
15227
 
 
15228
 
  /// Return the number of sub elements (for a mixed element)
15229
 
  virtual unsigned int num_sub_elements() const
15230
 
  {
15231
 
    return 1;
15232
 
  }
15233
 
 
15234
 
  /// Create a new finite element for sub element i (for a mixed element)
15235
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
15236
 
  {
15237
 
    return new hyperelasticity_1_finite_element_1_1();
15238
 
  }
15239
 
 
15240
 
};
15241
 
 
15242
 
/// This class defines the interface for a finite element.
15243
 
 
15244
 
class hyperelasticity_1_finite_element_1_2: public ufc::finite_element
15245
 
{
15246
 
public:
15247
 
 
15248
 
  /// Constructor
15249
 
  hyperelasticity_1_finite_element_1_2() : ufc::finite_element()
15250
 
  {
15251
 
    // Do nothing
15252
 
  }
15253
 
 
15254
 
  /// Destructor
15255
 
  virtual ~hyperelasticity_1_finite_element_1_2()
15256
 
  {
15257
 
    // Do nothing
15258
 
  }
15259
 
 
15260
 
  /// Return a string identifying the finite element
15261
 
  virtual const char* signature() const
15262
 
  {
15263
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
15264
 
  }
15265
 
 
15266
 
  /// Return the cell shape
15267
 
  virtual ufc::shape cell_shape() const
15268
 
  {
15269
 
    return ufc::tetrahedron;
15270
 
  }
15271
 
 
15272
 
  /// Return the dimension of the finite element function space
15273
 
  virtual unsigned int space_dimension() const
15274
 
  {
15275
 
    return 4;
15276
 
  }
15277
 
 
15278
 
  /// Return the rank of the value space
15279
 
  virtual unsigned int value_rank() const
15280
 
  {
15281
 
    return 0;
15282
 
  }
15283
 
 
15284
 
  /// Return the dimension of the value space for axis i
15285
 
  virtual unsigned int value_dimension(unsigned int i) const
15286
 
  {
15287
 
    return 1;
15288
 
  }
15289
 
 
15290
 
  /// Evaluate basis function i at given point in cell
15291
 
  virtual void evaluate_basis(unsigned int i,
15292
 
                              double* values,
15293
 
                              const double* coordinates,
15294
 
                              const ufc::cell& c) const
15295
 
  {
15296
 
    // Extract vertex coordinates
15297
 
    const double * const * element_coordinates = c.coordinates;
15298
 
    
15299
 
    // Compute Jacobian of affine map from reference cell
15300
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
15301
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
15302
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
15303
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
15304
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
15305
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
15306
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
15307
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
15308
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
15309
 
    
15310
 
    // Compute sub determinants
15311
 
    const double d00 = J_11*J_22 - J_12*J_21;
15312
 
    const double d01 = J_12*J_20 - J_10*J_22;
15313
 
    const double d02 = J_10*J_21 - J_11*J_20;
15314
 
    
15315
 
    const double d10 = J_02*J_21 - J_01*J_22;
15316
 
    const double d11 = J_00*J_22 - J_02*J_20;
15317
 
    const double d12 = J_01*J_20 - J_00*J_21;
15318
 
    
15319
 
    const double d20 = J_01*J_12 - J_02*J_11;
15320
 
    const double d21 = J_02*J_10 - J_00*J_12;
15321
 
    const double d22 = J_00*J_11 - J_01*J_10;
15322
 
    
15323
 
    // Compute determinant of Jacobian
15324
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
15325
 
    
15326
 
    // Compute inverse of Jacobian
15327
 
    
15328
 
    // Compute constants
15329
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
15330
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
15331
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
15332
 
    
15333
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
15334
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
15335
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
15336
 
    
15337
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
15338
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
15339
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
15340
 
    
15341
 
    // Get coordinates and map to the UFC reference element
15342
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
15343
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
15344
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
15345
 
    
15346
 
    // Map coordinates to the reference cube
15347
 
    if (std::abs(y + z - 1.0) < 1e-08)
15348
 
      x = 1.0;
15349
 
    else
15350
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
15351
 
    if (std::abs(z - 1.0) < 1e-08)
15352
 
      y = -1.0;
15353
 
    else
15354
 
      y = 2.0 * y/(1.0 - z) - 1.0;
15355
 
    z = 2.0 * z - 1.0;
15356
 
    
15357
 
    // Reset values
15358
 
    *values = 0;
15359
 
    
15360
 
    // Map degree of freedom to element degree of freedom
15361
 
    const unsigned int dof = i;
15362
 
    
15363
 
    // Generate scalings
15364
 
    const double scalings_y_0 = 1;
15365
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15366
 
    const double scalings_z_0 = 1;
15367
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
15368
 
    
15369
 
    // Compute psitilde_a
15370
 
    const double psitilde_a_0 = 1;
15371
 
    const double psitilde_a_1 = x;
15372
 
    
15373
 
    // Compute psitilde_bs
15374
 
    const double psitilde_bs_0_0 = 1;
15375
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
15376
 
    const double psitilde_bs_1_0 = 1;
15377
 
    
15378
 
    // Compute psitilde_cs
15379
 
    const double psitilde_cs_00_0 = 1;
15380
 
    const double psitilde_cs_00_1 = 2*z + 1;
15381
 
    const double psitilde_cs_01_0 = 1;
15382
 
    const double psitilde_cs_10_0 = 1;
15383
 
    
15384
 
    // Compute basisvalues
15385
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
15386
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
15387
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
15388
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
15389
 
    
15390
 
    // Table(s) of coefficients
15391
 
    static const double coefficients0[4][4] = \
15392
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
15393
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
15394
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
15395
 
    {0.288675135, 0, 0, 0.223606798}};
15396
 
    
15397
 
    // Extract relevant coefficients
15398
 
    const double coeff0_0 = coefficients0[dof][0];
15399
 
    const double coeff0_1 = coefficients0[dof][1];
15400
 
    const double coeff0_2 = coefficients0[dof][2];
15401
 
    const double coeff0_3 = coefficients0[dof][3];
15402
 
    
15403
 
    // Compute value(s)
15404
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
15405
 
  }
15406
 
 
15407
 
  /// Evaluate all basis functions at given point in cell
15408
 
  virtual void evaluate_basis_all(double* values,
15409
 
                                  const double* coordinates,
15410
 
                                  const ufc::cell& c) const
15411
 
  {
15412
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
15413
 
  }
15414
 
 
15415
 
  /// Evaluate order n derivatives of basis function i at given point in cell
15416
 
  virtual void evaluate_basis_derivatives(unsigned int i,
15417
 
                                          unsigned int n,
15418
 
                                          double* values,
15419
 
                                          const double* coordinates,
15420
 
                                          const ufc::cell& c) const
15421
 
  {
15422
 
    // Extract vertex coordinates
15423
 
    const double * const * element_coordinates = c.coordinates;
15424
 
    
15425
 
    // Compute Jacobian of affine map from reference cell
15426
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
15427
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
15428
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
15429
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
15430
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
15431
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
15432
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
15433
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
15434
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
15435
 
    
15436
 
    // Compute sub determinants
15437
 
    const double d00 = J_11*J_22 - J_12*J_21;
15438
 
    const double d01 = J_12*J_20 - J_10*J_22;
15439
 
    const double d02 = J_10*J_21 - J_11*J_20;
15440
 
    
15441
 
    const double d10 = J_02*J_21 - J_01*J_22;
15442
 
    const double d11 = J_00*J_22 - J_02*J_20;
15443
 
    const double d12 = J_01*J_20 - J_00*J_21;
15444
 
    
15445
 
    const double d20 = J_01*J_12 - J_02*J_11;
15446
 
    const double d21 = J_02*J_10 - J_00*J_12;
15447
 
    const double d22 = J_00*J_11 - J_01*J_10;
15448
 
    
15449
 
    // Compute determinant of Jacobian
15450
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
15451
 
    
15452
 
    // Compute inverse of Jacobian
15453
 
    
15454
 
    // Compute constants
15455
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
15456
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
15457
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
15458
 
    
15459
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
15460
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
15461
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
15462
 
    
15463
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
15464
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
15465
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
15466
 
    
15467
 
    // Get coordinates and map to the UFC reference element
15468
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
15469
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
15470
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
15471
 
    
15472
 
    // Map coordinates to the reference cube
15473
 
    if (std::abs(y + z - 1.0) < 1e-08)
15474
 
      x = 1.0;
15475
 
    else
15476
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
15477
 
    if (std::abs(z - 1.0) < 1e-08)
15478
 
      y = -1.0;
15479
 
    else
15480
 
      y = 2.0 * y/(1.0 - z) - 1.0;
15481
 
    z = 2.0 * z - 1.0;
15482
 
    
15483
 
    // Compute number of derivatives
15484
 
    unsigned int num_derivatives = 1;
15485
 
    
15486
 
    for (unsigned int j = 0; j < n; j++)
15487
 
      num_derivatives *= 3;
15488
 
    
15489
 
    
15490
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
15491
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
15492
 
    
15493
 
    for (unsigned int j = 0; j < num_derivatives; j++)
15494
 
    {
15495
 
      combinations[j] = new unsigned int [n];
15496
 
      for (unsigned int k = 0; k < n; k++)
15497
 
        combinations[j][k] = 0;
15498
 
    }
15499
 
    
15500
 
    // Generate combinations of derivatives
15501
 
    for (unsigned int row = 1; row < num_derivatives; row++)
15502
 
    {
15503
 
      for (unsigned int num = 0; num < row; num++)
15504
 
      {
15505
 
        for (unsigned int col = n-1; col+1 > 0; col--)
15506
 
        {
15507
 
          if (combinations[row][col] + 1 > 2)
15508
 
            combinations[row][col] = 0;
15509
 
          else
15510
 
          {
15511
 
            combinations[row][col] += 1;
15512
 
            break;
15513
 
          }
15514
 
        }
15515
 
      }
15516
 
    }
15517
 
    
15518
 
    // Compute inverse of Jacobian
15519
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
15520
 
    
15521
 
    // Declare transformation matrix
15522
 
    // Declare pointer to two dimensional array and initialise
15523
 
    double **transform = new double *[num_derivatives];
15524
 
    
15525
 
    for (unsigned int j = 0; j < num_derivatives; j++)
15526
 
    {
15527
 
      transform[j] = new double [num_derivatives];
15528
 
      for (unsigned int k = 0; k < num_derivatives; k++)
15529
 
        transform[j][k] = 1;
15530
 
    }
15531
 
    
15532
 
    // Construct transformation matrix
15533
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15534
 
    {
15535
 
      for (unsigned int col = 0; col < num_derivatives; col++)
15536
 
      {
15537
 
        for (unsigned int k = 0; k < n; k++)
15538
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
15539
 
      }
15540
 
    }
15541
 
    
15542
 
    // Reset values
15543
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
15544
 
      values[j] = 0;
15545
 
    
15546
 
    // Map degree of freedom to element degree of freedom
15547
 
    const unsigned int dof = i;
15548
 
    
15549
 
    // Generate scalings
15550
 
    const double scalings_y_0 = 1;
15551
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15552
 
    const double scalings_z_0 = 1;
15553
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
15554
 
    
15555
 
    // Compute psitilde_a
15556
 
    const double psitilde_a_0 = 1;
15557
 
    const double psitilde_a_1 = x;
15558
 
    
15559
 
    // Compute psitilde_bs
15560
 
    const double psitilde_bs_0_0 = 1;
15561
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
15562
 
    const double psitilde_bs_1_0 = 1;
15563
 
    
15564
 
    // Compute psitilde_cs
15565
 
    const double psitilde_cs_00_0 = 1;
15566
 
    const double psitilde_cs_00_1 = 2*z + 1;
15567
 
    const double psitilde_cs_01_0 = 1;
15568
 
    const double psitilde_cs_10_0 = 1;
15569
 
    
15570
 
    // Compute basisvalues
15571
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
15572
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
15573
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
15574
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
15575
 
    
15576
 
    // Table(s) of coefficients
15577
 
    static const double coefficients0[4][4] = \
15578
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
15579
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
15580
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
15581
 
    {0.288675135, 0, 0, 0.223606798}};
15582
 
    
15583
 
    // Interesting (new) part
15584
 
    // Tables of derivatives of the polynomial base (transpose)
15585
 
    static const double dmats0[4][4] = \
15586
 
    {{0, 0, 0, 0},
15587
 
    {6.32455532, 0, 0, 0},
15588
 
    {0, 0, 0, 0},
15589
 
    {0, 0, 0, 0}};
15590
 
    
15591
 
    static const double dmats1[4][4] = \
15592
 
    {{0, 0, 0, 0},
15593
 
    {3.16227766, 0, 0, 0},
15594
 
    {5.47722558, 0, 0, 0},
15595
 
    {0, 0, 0, 0}};
15596
 
    
15597
 
    static const double dmats2[4][4] = \
15598
 
    {{0, 0, 0, 0},
15599
 
    {3.16227766, 0, 0, 0},
15600
 
    {1.82574186, 0, 0, 0},
15601
 
    {5.16397779, 0, 0, 0}};
15602
 
    
15603
 
    // Compute reference derivatives
15604
 
    // Declare pointer to array of derivatives on FIAT element
15605
 
    double *derivatives = new double [num_derivatives];
15606
 
    
15607
 
    // Declare coefficients
15608
 
    double coeff0_0 = 0;
15609
 
    double coeff0_1 = 0;
15610
 
    double coeff0_2 = 0;
15611
 
    double coeff0_3 = 0;
15612
 
    
15613
 
    // Declare new coefficients
15614
 
    double new_coeff0_0 = 0;
15615
 
    double new_coeff0_1 = 0;
15616
 
    double new_coeff0_2 = 0;
15617
 
    double new_coeff0_3 = 0;
15618
 
    
15619
 
    // Loop possible derivatives
15620
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
15621
 
    {
15622
 
      // Get values from coefficients array
15623
 
      new_coeff0_0 = coefficients0[dof][0];
15624
 
      new_coeff0_1 = coefficients0[dof][1];
15625
 
      new_coeff0_2 = coefficients0[dof][2];
15626
 
      new_coeff0_3 = coefficients0[dof][3];
15627
 
    
15628
 
      // Loop derivative order
15629
 
      for (unsigned int j = 0; j < n; j++)
15630
 
      {
15631
 
        // Update old coefficients
15632
 
        coeff0_0 = new_coeff0_0;
15633
 
        coeff0_1 = new_coeff0_1;
15634
 
        coeff0_2 = new_coeff0_2;
15635
 
        coeff0_3 = new_coeff0_3;
15636
 
    
15637
 
        if(combinations[deriv_num][j] == 0)
15638
 
        {
15639
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
15640
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
15641
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
15642
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
15643
 
        }
15644
 
        if(combinations[deriv_num][j] == 1)
15645
 
        {
15646
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
15647
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
15648
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
15649
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
15650
 
        }
15651
 
        if(combinations[deriv_num][j] == 2)
15652
 
        {
15653
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
15654
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
15655
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
15656
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
15657
 
        }
15658
 
    
15659
 
      }
15660
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
15661
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
15662
 
    }
15663
 
    
15664
 
    // Transform derivatives back to physical element
15665
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15666
 
    {
15667
 
      for (unsigned int col = 0; col < num_derivatives; col++)
15668
 
      {
15669
 
        values[row] += transform[row][col]*derivatives[col];
15670
 
      }
15671
 
    }
15672
 
    // Delete pointer to array of derivatives on FIAT element
15673
 
    delete [] derivatives;
15674
 
    
15675
 
    // Delete pointer to array of combinations of derivatives and transform
15676
 
    for (unsigned int row = 0; row < num_derivatives; row++)
15677
 
    {
15678
 
      delete [] combinations[row];
15679
 
      delete [] transform[row];
15680
 
    }
15681
 
    
15682
 
    delete [] combinations;
15683
 
    delete [] transform;
15684
 
  }
15685
 
 
15686
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
15687
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
15688
 
                                              double* values,
15689
 
                                              const double* coordinates,
15690
 
                                              const ufc::cell& c) const
15691
 
  {
15692
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
15693
 
  }
15694
 
 
15695
 
  /// Evaluate linear functional for dof i on the function f
15696
 
  virtual double evaluate_dof(unsigned int i,
15697
 
                              const ufc::function& f,
15698
 
                              const ufc::cell& c) const
15699
 
  {
15700
 
    // The reference points, direction and weights:
15701
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
15702
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
15703
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
15704
 
    
15705
 
    const double * const * x = c.coordinates;
15706
 
    double result = 0.0;
15707
 
    // Iterate over the points:
15708
 
    // Evaluate basis functions for affine mapping
15709
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
15710
 
    const double w1 = X[i][0][0];
15711
 
    const double w2 = X[i][0][1];
15712
 
    const double w3 = X[i][0][2];
15713
 
    
15714
 
    // Compute affine mapping y = F(X)
15715
 
    double y[3];
15716
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
15717
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
15718
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
15719
 
    
15720
 
    // Evaluate function at physical points
15721
 
    double values[1];
15722
 
    f.evaluate(values, y, c);
15723
 
    
15724
 
    // Map function values using appropriate mapping
15725
 
    // Affine map: Do nothing
15726
 
    
15727
 
    // Note that we do not map the weights (yet).
15728
 
    
15729
 
    // Take directional components
15730
 
    for(int k = 0; k < 1; k++)
15731
 
      result += values[k]*D[i][0][k];
15732
 
    // Multiply by weights
15733
 
    result *= W[i][0];
15734
 
    
15735
 
    return result;
15736
 
  }
15737
 
 
15738
 
  /// Evaluate linear functionals for all dofs on the function f
15739
 
  virtual void evaluate_dofs(double* values,
15740
 
                             const ufc::function& f,
15741
 
                             const ufc::cell& c) const
15742
 
  {
15743
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
15744
 
  }
15745
 
 
15746
 
  /// Interpolate vertex values from dof values
15747
 
  virtual void interpolate_vertex_values(double* vertex_values,
15748
 
                                         const double* dof_values,
15749
 
                                         const ufc::cell& c) const
15750
 
  {
15751
 
    // Evaluate at vertices and use affine mapping
15752
 
    vertex_values[0] = dof_values[0];
15753
 
    vertex_values[1] = dof_values[1];
15754
 
    vertex_values[2] = dof_values[2];
15755
 
    vertex_values[3] = dof_values[3];
15756
 
  }
15757
 
 
15758
 
  /// Return the number of sub elements (for a mixed element)
15759
 
  virtual unsigned int num_sub_elements() const
15760
 
  {
15761
 
    return 1;
15762
 
  }
15763
 
 
15764
 
  /// Create a new finite element for sub element i (for a mixed element)
15765
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
15766
 
  {
15767
 
    return new hyperelasticity_1_finite_element_1_2();
15768
 
  }
15769
 
 
15770
 
};
15771
 
 
15772
 
/// This class defines the interface for a finite element.
15773
 
 
15774
 
class hyperelasticity_1_finite_element_1: public ufc::finite_element
15775
 
{
15776
 
public:
15777
 
 
15778
 
  /// Constructor
15779
 
  hyperelasticity_1_finite_element_1() : ufc::finite_element()
15780
 
  {
15781
 
    // Do nothing
15782
 
  }
15783
 
 
15784
 
  /// Destructor
15785
 
  virtual ~hyperelasticity_1_finite_element_1()
15786
 
  {
15787
 
    // Do nothing
15788
 
  }
15789
 
 
15790
 
  /// Return a string identifying the finite element
15791
 
  virtual const char* signature() const
15792
 
  {
15793
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
15794
 
  }
15795
 
 
15796
 
  /// Return the cell shape
15797
 
  virtual ufc::shape cell_shape() const
15798
 
  {
15799
 
    return ufc::tetrahedron;
15800
 
  }
15801
 
 
15802
 
  /// Return the dimension of the finite element function space
15803
 
  virtual unsigned int space_dimension() const
15804
 
  {
15805
 
    return 12;
15806
 
  }
15807
 
 
15808
 
  /// Return the rank of the value space
15809
 
  virtual unsigned int value_rank() const
15810
 
  {
15811
 
    return 1;
15812
 
  }
15813
 
 
15814
 
  /// Return the dimension of the value space for axis i
15815
 
  virtual unsigned int value_dimension(unsigned int i) const
15816
 
  {
15817
 
    return 3;
15818
 
  }
15819
 
 
15820
 
  /// Evaluate basis function i at given point in cell
15821
 
  virtual void evaluate_basis(unsigned int i,
15822
 
                              double* values,
15823
 
                              const double* coordinates,
15824
 
                              const ufc::cell& c) const
15825
 
  {
15826
 
    // Extract vertex coordinates
15827
 
    const double * const * element_coordinates = c.coordinates;
15828
 
    
15829
 
    // Compute Jacobian of affine map from reference cell
15830
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
15831
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
15832
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
15833
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
15834
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
15835
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
15836
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
15837
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
15838
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
15839
 
    
15840
 
    // Compute sub determinants
15841
 
    const double d00 = J_11*J_22 - J_12*J_21;
15842
 
    const double d01 = J_12*J_20 - J_10*J_22;
15843
 
    const double d02 = J_10*J_21 - J_11*J_20;
15844
 
    
15845
 
    const double d10 = J_02*J_21 - J_01*J_22;
15846
 
    const double d11 = J_00*J_22 - J_02*J_20;
15847
 
    const double d12 = J_01*J_20 - J_00*J_21;
15848
 
    
15849
 
    const double d20 = J_01*J_12 - J_02*J_11;
15850
 
    const double d21 = J_02*J_10 - J_00*J_12;
15851
 
    const double d22 = J_00*J_11 - J_01*J_10;
15852
 
    
15853
 
    // Compute determinant of Jacobian
15854
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
15855
 
    
15856
 
    // Compute inverse of Jacobian
15857
 
    
15858
 
    // Compute constants
15859
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
15860
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
15861
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
15862
 
    
15863
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
15864
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
15865
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
15866
 
    
15867
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
15868
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
15869
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
15870
 
    
15871
 
    // Get coordinates and map to the UFC reference element
15872
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
15873
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
15874
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
15875
 
    
15876
 
    // Map coordinates to the reference cube
15877
 
    if (std::abs(y + z - 1.0) < 1e-08)
15878
 
      x = 1.0;
15879
 
    else
15880
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
15881
 
    if (std::abs(z - 1.0) < 1e-08)
15882
 
      y = -1.0;
15883
 
    else
15884
 
      y = 2.0 * y/(1.0 - z) - 1.0;
15885
 
    z = 2.0 * z - 1.0;
15886
 
    
15887
 
    // Reset values
15888
 
    values[0] = 0;
15889
 
    values[1] = 0;
15890
 
    values[2] = 0;
15891
 
    
15892
 
    if (0 <= i && i <= 3)
15893
 
    {
15894
 
      // Map degree of freedom to element degree of freedom
15895
 
      const unsigned int dof = i;
15896
 
    
15897
 
      // Generate scalings
15898
 
      const double scalings_y_0 = 1;
15899
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15900
 
      const double scalings_z_0 = 1;
15901
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
15902
 
    
15903
 
      // Compute psitilde_a
15904
 
      const double psitilde_a_0 = 1;
15905
 
      const double psitilde_a_1 = x;
15906
 
    
15907
 
      // Compute psitilde_bs
15908
 
      const double psitilde_bs_0_0 = 1;
15909
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
15910
 
      const double psitilde_bs_1_0 = 1;
15911
 
    
15912
 
      // Compute psitilde_cs
15913
 
      const double psitilde_cs_00_0 = 1;
15914
 
      const double psitilde_cs_00_1 = 2*z + 1;
15915
 
      const double psitilde_cs_01_0 = 1;
15916
 
      const double psitilde_cs_10_0 = 1;
15917
 
    
15918
 
      // Compute basisvalues
15919
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
15920
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
15921
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
15922
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
15923
 
    
15924
 
      // Table(s) of coefficients
15925
 
      static const double coefficients0[4][4] =   \
15926
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
15927
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
15928
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
15929
 
      {0.288675135, 0, 0, 0.223606798}};
15930
 
    
15931
 
      // Extract relevant coefficients
15932
 
      const double coeff0_0 =   coefficients0[dof][0];
15933
 
      const double coeff0_1 =   coefficients0[dof][1];
15934
 
      const double coeff0_2 =   coefficients0[dof][2];
15935
 
      const double coeff0_3 =   coefficients0[dof][3];
15936
 
    
15937
 
      // Compute value(s)
15938
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
15939
 
    }
15940
 
    
15941
 
    if (4 <= i && i <= 7)
15942
 
    {
15943
 
      // Map degree of freedom to element degree of freedom
15944
 
      const unsigned int dof = i - 4;
15945
 
    
15946
 
      // Generate scalings
15947
 
      const double scalings_y_0 = 1;
15948
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15949
 
      const double scalings_z_0 = 1;
15950
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
15951
 
    
15952
 
      // Compute psitilde_a
15953
 
      const double psitilde_a_0 = 1;
15954
 
      const double psitilde_a_1 = x;
15955
 
    
15956
 
      // Compute psitilde_bs
15957
 
      const double psitilde_bs_0_0 = 1;
15958
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
15959
 
      const double psitilde_bs_1_0 = 1;
15960
 
    
15961
 
      // Compute psitilde_cs
15962
 
      const double psitilde_cs_00_0 = 1;
15963
 
      const double psitilde_cs_00_1 = 2*z + 1;
15964
 
      const double psitilde_cs_01_0 = 1;
15965
 
      const double psitilde_cs_10_0 = 1;
15966
 
    
15967
 
      // Compute basisvalues
15968
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
15969
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
15970
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
15971
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
15972
 
    
15973
 
      // Table(s) of coefficients
15974
 
      static const double coefficients0[4][4] =   \
15975
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
15976
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
15977
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
15978
 
      {0.288675135, 0, 0, 0.223606798}};
15979
 
    
15980
 
      // Extract relevant coefficients
15981
 
      const double coeff0_0 =   coefficients0[dof][0];
15982
 
      const double coeff0_1 =   coefficients0[dof][1];
15983
 
      const double coeff0_2 =   coefficients0[dof][2];
15984
 
      const double coeff0_3 =   coefficients0[dof][3];
15985
 
    
15986
 
      // Compute value(s)
15987
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
15988
 
    }
15989
 
    
15990
 
    if (8 <= i && i <= 11)
15991
 
    {
15992
 
      // Map degree of freedom to element degree of freedom
15993
 
      const unsigned int dof = i - 8;
15994
 
    
15995
 
      // Generate scalings
15996
 
      const double scalings_y_0 = 1;
15997
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
15998
 
      const double scalings_z_0 = 1;
15999
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
16000
 
    
16001
 
      // Compute psitilde_a
16002
 
      const double psitilde_a_0 = 1;
16003
 
      const double psitilde_a_1 = x;
16004
 
    
16005
 
      // Compute psitilde_bs
16006
 
      const double psitilde_bs_0_0 = 1;
16007
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
16008
 
      const double psitilde_bs_1_0 = 1;
16009
 
    
16010
 
      // Compute psitilde_cs
16011
 
      const double psitilde_cs_00_0 = 1;
16012
 
      const double psitilde_cs_00_1 = 2*z + 1;
16013
 
      const double psitilde_cs_01_0 = 1;
16014
 
      const double psitilde_cs_10_0 = 1;
16015
 
    
16016
 
      // Compute basisvalues
16017
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
16018
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
16019
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
16020
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
16021
 
    
16022
 
      // Table(s) of coefficients
16023
 
      static const double coefficients0[4][4] =   \
16024
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
16025
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
16026
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
16027
 
      {0.288675135, 0, 0, 0.223606798}};
16028
 
    
16029
 
      // Extract relevant coefficients
16030
 
      const double coeff0_0 =   coefficients0[dof][0];
16031
 
      const double coeff0_1 =   coefficients0[dof][1];
16032
 
      const double coeff0_2 =   coefficients0[dof][2];
16033
 
      const double coeff0_3 =   coefficients0[dof][3];
16034
 
    
16035
 
      // Compute value(s)
16036
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
16037
 
    }
16038
 
    
16039
 
  }
16040
 
 
16041
 
  /// Evaluate all basis functions at given point in cell
16042
 
  virtual void evaluate_basis_all(double* values,
16043
 
                                  const double* coordinates,
16044
 
                                  const ufc::cell& c) const
16045
 
  {
16046
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
16047
 
  }
16048
 
 
16049
 
  /// Evaluate order n derivatives of basis function i at given point in cell
16050
 
  virtual void evaluate_basis_derivatives(unsigned int i,
16051
 
                                          unsigned int n,
16052
 
                                          double* values,
16053
 
                                          const double* coordinates,
16054
 
                                          const ufc::cell& c) const
16055
 
  {
16056
 
    // Extract vertex coordinates
16057
 
    const double * const * element_coordinates = c.coordinates;
16058
 
    
16059
 
    // Compute Jacobian of affine map from reference cell
16060
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
16061
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
16062
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
16063
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
16064
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
16065
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
16066
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
16067
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
16068
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
16069
 
    
16070
 
    // Compute sub determinants
16071
 
    const double d00 = J_11*J_22 - J_12*J_21;
16072
 
    const double d01 = J_12*J_20 - J_10*J_22;
16073
 
    const double d02 = J_10*J_21 - J_11*J_20;
16074
 
    
16075
 
    const double d10 = J_02*J_21 - J_01*J_22;
16076
 
    const double d11 = J_00*J_22 - J_02*J_20;
16077
 
    const double d12 = J_01*J_20 - J_00*J_21;
16078
 
    
16079
 
    const double d20 = J_01*J_12 - J_02*J_11;
16080
 
    const double d21 = J_02*J_10 - J_00*J_12;
16081
 
    const double d22 = J_00*J_11 - J_01*J_10;
16082
 
    
16083
 
    // Compute determinant of Jacobian
16084
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
16085
 
    
16086
 
    // Compute inverse of Jacobian
16087
 
    
16088
 
    // Compute constants
16089
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
16090
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
16091
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
16092
 
    
16093
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
16094
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
16095
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
16096
 
    
16097
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
16098
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
16099
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
16100
 
    
16101
 
    // Get coordinates and map to the UFC reference element
16102
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
16103
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
16104
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
16105
 
    
16106
 
    // Map coordinates to the reference cube
16107
 
    if (std::abs(y + z - 1.0) < 1e-08)
16108
 
      x = 1.0;
16109
 
    else
16110
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
16111
 
    if (std::abs(z - 1.0) < 1e-08)
16112
 
      y = -1.0;
16113
 
    else
16114
 
      y = 2.0 * y/(1.0 - z) - 1.0;
16115
 
    z = 2.0 * z - 1.0;
16116
 
    
16117
 
    // Compute number of derivatives
16118
 
    unsigned int num_derivatives = 1;
16119
 
    
16120
 
    for (unsigned int j = 0; j < n; j++)
16121
 
      num_derivatives *= 3;
16122
 
    
16123
 
    
16124
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
16125
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
16126
 
    
16127
 
    for (unsigned int j = 0; j < num_derivatives; j++)
16128
 
    {
16129
 
      combinations[j] = new unsigned int [n];
16130
 
      for (unsigned int k = 0; k < n; k++)
16131
 
        combinations[j][k] = 0;
16132
 
    }
16133
 
    
16134
 
    // Generate combinations of derivatives
16135
 
    for (unsigned int row = 1; row < num_derivatives; row++)
16136
 
    {
16137
 
      for (unsigned int num = 0; num < row; num++)
16138
 
      {
16139
 
        for (unsigned int col = n-1; col+1 > 0; col--)
16140
 
        {
16141
 
          if (combinations[row][col] + 1 > 2)
16142
 
            combinations[row][col] = 0;
16143
 
          else
16144
 
          {
16145
 
            combinations[row][col] += 1;
16146
 
            break;
16147
 
          }
16148
 
        }
16149
 
      }
16150
 
    }
16151
 
    
16152
 
    // Compute inverse of Jacobian
16153
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
16154
 
    
16155
 
    // Declare transformation matrix
16156
 
    // Declare pointer to two dimensional array and initialise
16157
 
    double **transform = new double *[num_derivatives];
16158
 
    
16159
 
    for (unsigned int j = 0; j < num_derivatives; j++)
16160
 
    {
16161
 
      transform[j] = new double [num_derivatives];
16162
 
      for (unsigned int k = 0; k < num_derivatives; k++)
16163
 
        transform[j][k] = 1;
16164
 
    }
16165
 
    
16166
 
    // Construct transformation matrix
16167
 
    for (unsigned int row = 0; row < num_derivatives; row++)
16168
 
    {
16169
 
      for (unsigned int col = 0; col < num_derivatives; col++)
16170
 
      {
16171
 
        for (unsigned int k = 0; k < n; k++)
16172
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
16173
 
      }
16174
 
    }
16175
 
    
16176
 
    // Reset values
16177
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
16178
 
      values[j] = 0;
16179
 
    
16180
 
    if (0 <= i && i <= 3)
16181
 
    {
16182
 
      // Map degree of freedom to element degree of freedom
16183
 
      const unsigned int dof = i;
16184
 
    
16185
 
      // Generate scalings
16186
 
      const double scalings_y_0 = 1;
16187
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
16188
 
      const double scalings_z_0 = 1;
16189
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
16190
 
    
16191
 
      // Compute psitilde_a
16192
 
      const double psitilde_a_0 = 1;
16193
 
      const double psitilde_a_1 = x;
16194
 
    
16195
 
      // Compute psitilde_bs
16196
 
      const double psitilde_bs_0_0 = 1;
16197
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
16198
 
      const double psitilde_bs_1_0 = 1;
16199
 
    
16200
 
      // Compute psitilde_cs
16201
 
      const double psitilde_cs_00_0 = 1;
16202
 
      const double psitilde_cs_00_1 = 2*z + 1;
16203
 
      const double psitilde_cs_01_0 = 1;
16204
 
      const double psitilde_cs_10_0 = 1;
16205
 
    
16206
 
      // Compute basisvalues
16207
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
16208
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
16209
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
16210
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
16211
 
    
16212
 
      // Table(s) of coefficients
16213
 
      static const double coefficients0[4][4] =   \
16214
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
16215
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
16216
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
16217
 
      {0.288675135, 0, 0, 0.223606798}};
16218
 
    
16219
 
      // Interesting (new) part
16220
 
      // Tables of derivatives of the polynomial base (transpose)
16221
 
      static const double dmats0[4][4] =   \
16222
 
      {{0, 0, 0, 0},
16223
 
      {6.32455532, 0, 0, 0},
16224
 
      {0, 0, 0, 0},
16225
 
      {0, 0, 0, 0}};
16226
 
    
16227
 
      static const double dmats1[4][4] =   \
16228
 
      {{0, 0, 0, 0},
16229
 
      {3.16227766, 0, 0, 0},
16230
 
      {5.47722558, 0, 0, 0},
16231
 
      {0, 0, 0, 0}};
16232
 
    
16233
 
      static const double dmats2[4][4] =   \
16234
 
      {{0, 0, 0, 0},
16235
 
      {3.16227766, 0, 0, 0},
16236
 
      {1.82574186, 0, 0, 0},
16237
 
      {5.16397779, 0, 0, 0}};
16238
 
    
16239
 
      // Compute reference derivatives
16240
 
      // Declare pointer to array of derivatives on FIAT element
16241
 
      double *derivatives = new double [num_derivatives];
16242
 
    
16243
 
      // Declare coefficients
16244
 
      double coeff0_0 = 0;
16245
 
      double coeff0_1 = 0;
16246
 
      double coeff0_2 = 0;
16247
 
      double coeff0_3 = 0;
16248
 
    
16249
 
      // Declare new coefficients
16250
 
      double new_coeff0_0 = 0;
16251
 
      double new_coeff0_1 = 0;
16252
 
      double new_coeff0_2 = 0;
16253
 
      double new_coeff0_3 = 0;
16254
 
    
16255
 
      // Loop possible derivatives
16256
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
16257
 
      {
16258
 
        // Get values from coefficients array
16259
 
        new_coeff0_0 = coefficients0[dof][0];
16260
 
        new_coeff0_1 = coefficients0[dof][1];
16261
 
        new_coeff0_2 = coefficients0[dof][2];
16262
 
        new_coeff0_3 = coefficients0[dof][3];
16263
 
    
16264
 
        // Loop derivative order
16265
 
        for (unsigned int j = 0; j < n; j++)
16266
 
        {
16267
 
          // Update old coefficients
16268
 
          coeff0_0 = new_coeff0_0;
16269
 
          coeff0_1 = new_coeff0_1;
16270
 
          coeff0_2 = new_coeff0_2;
16271
 
          coeff0_3 = new_coeff0_3;
16272
 
    
16273
 
          if(combinations[deriv_num][j] == 0)
16274
 
          {
16275
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
16276
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
16277
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
16278
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
16279
 
          }
16280
 
          if(combinations[deriv_num][j] == 1)
16281
 
          {
16282
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
16283
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
16284
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
16285
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
16286
 
          }
16287
 
          if(combinations[deriv_num][j] == 2)
16288
 
          {
16289
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
16290
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
16291
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
16292
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
16293
 
          }
16294
 
    
16295
 
        }
16296
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
16297
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
16298
 
      }
16299
 
    
16300
 
      // Transform derivatives back to physical element
16301
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16302
 
      {
16303
 
        for (unsigned int col = 0; col < num_derivatives; col++)
16304
 
        {
16305
 
          values[row] += transform[row][col]*derivatives[col];
16306
 
        }
16307
 
      }
16308
 
      // Delete pointer to array of derivatives on FIAT element
16309
 
      delete [] derivatives;
16310
 
    
16311
 
      // Delete pointer to array of combinations of derivatives and transform
16312
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16313
 
      {
16314
 
        delete [] combinations[row];
16315
 
        delete [] transform[row];
16316
 
      }
16317
 
    
16318
 
      delete [] combinations;
16319
 
      delete [] transform;
16320
 
    }
16321
 
    
16322
 
    if (4 <= i && i <= 7)
16323
 
    {
16324
 
      // Map degree of freedom to element degree of freedom
16325
 
      const unsigned int dof = i - 4;
16326
 
    
16327
 
      // Generate scalings
16328
 
      const double scalings_y_0 = 1;
16329
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
16330
 
      const double scalings_z_0 = 1;
16331
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
16332
 
    
16333
 
      // Compute psitilde_a
16334
 
      const double psitilde_a_0 = 1;
16335
 
      const double psitilde_a_1 = x;
16336
 
    
16337
 
      // Compute psitilde_bs
16338
 
      const double psitilde_bs_0_0 = 1;
16339
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
16340
 
      const double psitilde_bs_1_0 = 1;
16341
 
    
16342
 
      // Compute psitilde_cs
16343
 
      const double psitilde_cs_00_0 = 1;
16344
 
      const double psitilde_cs_00_1 = 2*z + 1;
16345
 
      const double psitilde_cs_01_0 = 1;
16346
 
      const double psitilde_cs_10_0 = 1;
16347
 
    
16348
 
      // Compute basisvalues
16349
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
16350
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
16351
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
16352
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
16353
 
    
16354
 
      // Table(s) of coefficients
16355
 
      static const double coefficients0[4][4] =   \
16356
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
16357
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
16358
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
16359
 
      {0.288675135, 0, 0, 0.223606798}};
16360
 
    
16361
 
      // Interesting (new) part
16362
 
      // Tables of derivatives of the polynomial base (transpose)
16363
 
      static const double dmats0[4][4] =   \
16364
 
      {{0, 0, 0, 0},
16365
 
      {6.32455532, 0, 0, 0},
16366
 
      {0, 0, 0, 0},
16367
 
      {0, 0, 0, 0}};
16368
 
    
16369
 
      static const double dmats1[4][4] =   \
16370
 
      {{0, 0, 0, 0},
16371
 
      {3.16227766, 0, 0, 0},
16372
 
      {5.47722558, 0, 0, 0},
16373
 
      {0, 0, 0, 0}};
16374
 
    
16375
 
      static const double dmats2[4][4] =   \
16376
 
      {{0, 0, 0, 0},
16377
 
      {3.16227766, 0, 0, 0},
16378
 
      {1.82574186, 0, 0, 0},
16379
 
      {5.16397779, 0, 0, 0}};
16380
 
    
16381
 
      // Compute reference derivatives
16382
 
      // Declare pointer to array of derivatives on FIAT element
16383
 
      double *derivatives = new double [num_derivatives];
16384
 
    
16385
 
      // Declare coefficients
16386
 
      double coeff0_0 = 0;
16387
 
      double coeff0_1 = 0;
16388
 
      double coeff0_2 = 0;
16389
 
      double coeff0_3 = 0;
16390
 
    
16391
 
      // Declare new coefficients
16392
 
      double new_coeff0_0 = 0;
16393
 
      double new_coeff0_1 = 0;
16394
 
      double new_coeff0_2 = 0;
16395
 
      double new_coeff0_3 = 0;
16396
 
    
16397
 
      // Loop possible derivatives
16398
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
16399
 
      {
16400
 
        // Get values from coefficients array
16401
 
        new_coeff0_0 = coefficients0[dof][0];
16402
 
        new_coeff0_1 = coefficients0[dof][1];
16403
 
        new_coeff0_2 = coefficients0[dof][2];
16404
 
        new_coeff0_3 = coefficients0[dof][3];
16405
 
    
16406
 
        // Loop derivative order
16407
 
        for (unsigned int j = 0; j < n; j++)
16408
 
        {
16409
 
          // Update old coefficients
16410
 
          coeff0_0 = new_coeff0_0;
16411
 
          coeff0_1 = new_coeff0_1;
16412
 
          coeff0_2 = new_coeff0_2;
16413
 
          coeff0_3 = new_coeff0_3;
16414
 
    
16415
 
          if(combinations[deriv_num][j] == 0)
16416
 
          {
16417
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
16418
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
16419
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
16420
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
16421
 
          }
16422
 
          if(combinations[deriv_num][j] == 1)
16423
 
          {
16424
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
16425
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
16426
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
16427
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
16428
 
          }
16429
 
          if(combinations[deriv_num][j] == 2)
16430
 
          {
16431
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
16432
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
16433
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
16434
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
16435
 
          }
16436
 
    
16437
 
        }
16438
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
16439
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
16440
 
      }
16441
 
    
16442
 
      // Transform derivatives back to physical element
16443
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16444
 
      {
16445
 
        for (unsigned int col = 0; col < num_derivatives; col++)
16446
 
        {
16447
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
16448
 
        }
16449
 
      }
16450
 
      // Delete pointer to array of derivatives on FIAT element
16451
 
      delete [] derivatives;
16452
 
    
16453
 
      // Delete pointer to array of combinations of derivatives and transform
16454
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16455
 
      {
16456
 
        delete [] combinations[row];
16457
 
        delete [] transform[row];
16458
 
      }
16459
 
    
16460
 
      delete [] combinations;
16461
 
      delete [] transform;
16462
 
    }
16463
 
    
16464
 
    if (8 <= i && i <= 11)
16465
 
    {
16466
 
      // Map degree of freedom to element degree of freedom
16467
 
      const unsigned int dof = i - 8;
16468
 
    
16469
 
      // Generate scalings
16470
 
      const double scalings_y_0 = 1;
16471
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
16472
 
      const double scalings_z_0 = 1;
16473
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
16474
 
    
16475
 
      // Compute psitilde_a
16476
 
      const double psitilde_a_0 = 1;
16477
 
      const double psitilde_a_1 = x;
16478
 
    
16479
 
      // Compute psitilde_bs
16480
 
      const double psitilde_bs_0_0 = 1;
16481
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
16482
 
      const double psitilde_bs_1_0 = 1;
16483
 
    
16484
 
      // Compute psitilde_cs
16485
 
      const double psitilde_cs_00_0 = 1;
16486
 
      const double psitilde_cs_00_1 = 2*z + 1;
16487
 
      const double psitilde_cs_01_0 = 1;
16488
 
      const double psitilde_cs_10_0 = 1;
16489
 
    
16490
 
      // Compute basisvalues
16491
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
16492
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
16493
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
16494
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
16495
 
    
16496
 
      // Table(s) of coefficients
16497
 
      static const double coefficients0[4][4] =   \
16498
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
16499
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
16500
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
16501
 
      {0.288675135, 0, 0, 0.223606798}};
16502
 
    
16503
 
      // Interesting (new) part
16504
 
      // Tables of derivatives of the polynomial base (transpose)
16505
 
      static const double dmats0[4][4] =   \
16506
 
      {{0, 0, 0, 0},
16507
 
      {6.32455532, 0, 0, 0},
16508
 
      {0, 0, 0, 0},
16509
 
      {0, 0, 0, 0}};
16510
 
    
16511
 
      static const double dmats1[4][4] =   \
16512
 
      {{0, 0, 0, 0},
16513
 
      {3.16227766, 0, 0, 0},
16514
 
      {5.47722558, 0, 0, 0},
16515
 
      {0, 0, 0, 0}};
16516
 
    
16517
 
      static const double dmats2[4][4] =   \
16518
 
      {{0, 0, 0, 0},
16519
 
      {3.16227766, 0, 0, 0},
16520
 
      {1.82574186, 0, 0, 0},
16521
 
      {5.16397779, 0, 0, 0}};
16522
 
    
16523
 
      // Compute reference derivatives
16524
 
      // Declare pointer to array of derivatives on FIAT element
16525
 
      double *derivatives = new double [num_derivatives];
16526
 
    
16527
 
      // Declare coefficients
16528
 
      double coeff0_0 = 0;
16529
 
      double coeff0_1 = 0;
16530
 
      double coeff0_2 = 0;
16531
 
      double coeff0_3 = 0;
16532
 
    
16533
 
      // Declare new coefficients
16534
 
      double new_coeff0_0 = 0;
16535
 
      double new_coeff0_1 = 0;
16536
 
      double new_coeff0_2 = 0;
16537
 
      double new_coeff0_3 = 0;
16538
 
    
16539
 
      // Loop possible derivatives
16540
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
16541
 
      {
16542
 
        // Get values from coefficients array
16543
 
        new_coeff0_0 = coefficients0[dof][0];
16544
 
        new_coeff0_1 = coefficients0[dof][1];
16545
 
        new_coeff0_2 = coefficients0[dof][2];
16546
 
        new_coeff0_3 = coefficients0[dof][3];
16547
 
    
16548
 
        // Loop derivative order
16549
 
        for (unsigned int j = 0; j < n; j++)
16550
 
        {
16551
 
          // Update old coefficients
16552
 
          coeff0_0 = new_coeff0_0;
16553
 
          coeff0_1 = new_coeff0_1;
16554
 
          coeff0_2 = new_coeff0_2;
16555
 
          coeff0_3 = new_coeff0_3;
16556
 
    
16557
 
          if(combinations[deriv_num][j] == 0)
16558
 
          {
16559
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
16560
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
16561
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
16562
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
16563
 
          }
16564
 
          if(combinations[deriv_num][j] == 1)
16565
 
          {
16566
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
16567
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
16568
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
16569
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
16570
 
          }
16571
 
          if(combinations[deriv_num][j] == 2)
16572
 
          {
16573
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
16574
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
16575
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
16576
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
16577
 
          }
16578
 
    
16579
 
        }
16580
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
16581
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
16582
 
      }
16583
 
    
16584
 
      // Transform derivatives back to physical element
16585
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16586
 
      {
16587
 
        for (unsigned int col = 0; col < num_derivatives; col++)
16588
 
        {
16589
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
16590
 
        }
16591
 
      }
16592
 
      // Delete pointer to array of derivatives on FIAT element
16593
 
      delete [] derivatives;
16594
 
    
16595
 
      // Delete pointer to array of combinations of derivatives and transform
16596
 
      for (unsigned int row = 0; row < num_derivatives; row++)
16597
 
      {
16598
 
        delete [] combinations[row];
16599
 
        delete [] transform[row];
16600
 
      }
16601
 
    
16602
 
      delete [] combinations;
16603
 
      delete [] transform;
16604
 
    }
16605
 
    
16606
 
  }
16607
 
 
16608
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
16609
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
16610
 
                                              double* values,
16611
 
                                              const double* coordinates,
16612
 
                                              const ufc::cell& c) const
16613
 
  {
16614
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
16615
 
  }
16616
 
 
16617
 
  /// Evaluate linear functional for dof i on the function f
16618
 
  virtual double evaluate_dof(unsigned int i,
16619
 
                              const ufc::function& f,
16620
 
                              const ufc::cell& c) const
16621
 
  {
16622
 
    // The reference points, direction and weights:
16623
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
16624
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
16625
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
16626
 
    
16627
 
    const double * const * x = c.coordinates;
16628
 
    double result = 0.0;
16629
 
    // Iterate over the points:
16630
 
    // Evaluate basis functions for affine mapping
16631
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
16632
 
    const double w1 = X[i][0][0];
16633
 
    const double w2 = X[i][0][1];
16634
 
    const double w3 = X[i][0][2];
16635
 
    
16636
 
    // Compute affine mapping y = F(X)
16637
 
    double y[3];
16638
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
16639
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
16640
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
16641
 
    
16642
 
    // Evaluate function at physical points
16643
 
    double values[3];
16644
 
    f.evaluate(values, y, c);
16645
 
    
16646
 
    // Map function values using appropriate mapping
16647
 
    // Affine map: Do nothing
16648
 
    
16649
 
    // Note that we do not map the weights (yet).
16650
 
    
16651
 
    // Take directional components
16652
 
    for(int k = 0; k < 3; k++)
16653
 
      result += values[k]*D[i][0][k];
16654
 
    // Multiply by weights
16655
 
    result *= W[i][0];
16656
 
    
16657
 
    return result;
16658
 
  }
16659
 
 
16660
 
  /// Evaluate linear functionals for all dofs on the function f
16661
 
  virtual void evaluate_dofs(double* values,
16662
 
                             const ufc::function& f,
16663
 
                             const ufc::cell& c) const
16664
 
  {
16665
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
16666
 
  }
16667
 
 
16668
 
  /// Interpolate vertex values from dof values
16669
 
  virtual void interpolate_vertex_values(double* vertex_values,
16670
 
                                         const double* dof_values,
16671
 
                                         const ufc::cell& c) const
16672
 
  {
16673
 
    // Evaluate at vertices and use affine mapping
16674
 
    vertex_values[0] = dof_values[0];
16675
 
    vertex_values[3] = dof_values[1];
16676
 
    vertex_values[6] = dof_values[2];
16677
 
    vertex_values[9] = dof_values[3];
16678
 
    // Evaluate at vertices and use affine mapping
16679
 
    vertex_values[1] = dof_values[4];
16680
 
    vertex_values[4] = dof_values[5];
16681
 
    vertex_values[7] = dof_values[6];
16682
 
    vertex_values[10] = dof_values[7];
16683
 
    // Evaluate at vertices and use affine mapping
16684
 
    vertex_values[2] = dof_values[8];
16685
 
    vertex_values[5] = dof_values[9];
16686
 
    vertex_values[8] = dof_values[10];
16687
 
    vertex_values[11] = dof_values[11];
16688
 
  }
16689
 
 
16690
 
  /// Return the number of sub elements (for a mixed element)
16691
 
  virtual unsigned int num_sub_elements() const
16692
 
  {
16693
 
    return 3;
16694
 
  }
16695
 
 
16696
 
  /// Create a new finite element for sub element i (for a mixed element)
16697
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
16698
 
  {
16699
 
    switch ( i )
16700
 
    {
16701
 
    case 0:
16702
 
      return new hyperelasticity_1_finite_element_1_0();
16703
 
      break;
16704
 
    case 1:
16705
 
      return new hyperelasticity_1_finite_element_1_1();
16706
 
      break;
16707
 
    case 2:
16708
 
      return new hyperelasticity_1_finite_element_1_2();
16709
 
      break;
16710
 
    }
16711
 
    return 0;
16712
 
  }
16713
 
 
16714
 
};
16715
 
 
16716
 
/// This class defines the interface for a finite element.
16717
 
 
16718
 
class hyperelasticity_1_finite_element_2_0: public ufc::finite_element
16719
 
{
16720
 
public:
16721
 
 
16722
 
  /// Constructor
16723
 
  hyperelasticity_1_finite_element_2_0() : ufc::finite_element()
16724
 
  {
16725
 
    // Do nothing
16726
 
  }
16727
 
 
16728
 
  /// Destructor
16729
 
  virtual ~hyperelasticity_1_finite_element_2_0()
16730
 
  {
16731
 
    // Do nothing
16732
 
  }
16733
 
 
16734
 
  /// Return a string identifying the finite element
16735
 
  virtual const char* signature() const
16736
 
  {
16737
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
16738
 
  }
16739
 
 
16740
 
  /// Return the cell shape
16741
 
  virtual ufc::shape cell_shape() const
16742
 
  {
16743
 
    return ufc::tetrahedron;
16744
 
  }
16745
 
 
16746
 
  /// Return the dimension of the finite element function space
16747
 
  virtual unsigned int space_dimension() const
16748
 
  {
16749
 
    return 4;
16750
 
  }
16751
 
 
16752
 
  /// Return the rank of the value space
16753
 
  virtual unsigned int value_rank() const
16754
 
  {
16755
 
    return 0;
16756
 
  }
16757
 
 
16758
 
  /// Return the dimension of the value space for axis i
16759
 
  virtual unsigned int value_dimension(unsigned int i) const
16760
 
  {
16761
 
    return 1;
16762
 
  }
16763
 
 
16764
 
  /// Evaluate basis function i at given point in cell
16765
 
  virtual void evaluate_basis(unsigned int i,
16766
 
                              double* values,
16767
 
                              const double* coordinates,
16768
 
                              const ufc::cell& c) const
16769
 
  {
16770
 
    // Extract vertex coordinates
16771
 
    const double * const * element_coordinates = c.coordinates;
16772
 
    
16773
 
    // Compute Jacobian of affine map from reference cell
16774
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
16775
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
16776
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
16777
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
16778
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
16779
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
16780
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
16781
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
16782
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
16783
 
    
16784
 
    // Compute sub determinants
16785
 
    const double d00 = J_11*J_22 - J_12*J_21;
16786
 
    const double d01 = J_12*J_20 - J_10*J_22;
16787
 
    const double d02 = J_10*J_21 - J_11*J_20;
16788
 
    
16789
 
    const double d10 = J_02*J_21 - J_01*J_22;
16790
 
    const double d11 = J_00*J_22 - J_02*J_20;
16791
 
    const double d12 = J_01*J_20 - J_00*J_21;
16792
 
    
16793
 
    const double d20 = J_01*J_12 - J_02*J_11;
16794
 
    const double d21 = J_02*J_10 - J_00*J_12;
16795
 
    const double d22 = J_00*J_11 - J_01*J_10;
16796
 
    
16797
 
    // Compute determinant of Jacobian
16798
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
16799
 
    
16800
 
    // Compute inverse of Jacobian
16801
 
    
16802
 
    // Compute constants
16803
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
16804
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
16805
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
16806
 
    
16807
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
16808
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
16809
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
16810
 
    
16811
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
16812
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
16813
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
16814
 
    
16815
 
    // Get coordinates and map to the UFC reference element
16816
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
16817
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
16818
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
16819
 
    
16820
 
    // Map coordinates to the reference cube
16821
 
    if (std::abs(y + z - 1.0) < 1e-08)
16822
 
      x = 1.0;
16823
 
    else
16824
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
16825
 
    if (std::abs(z - 1.0) < 1e-08)
16826
 
      y = -1.0;
16827
 
    else
16828
 
      y = 2.0 * y/(1.0 - z) - 1.0;
16829
 
    z = 2.0 * z - 1.0;
16830
 
    
16831
 
    // Reset values
16832
 
    *values = 0;
16833
 
    
16834
 
    // Map degree of freedom to element degree of freedom
16835
 
    const unsigned int dof = i;
16836
 
    
16837
 
    // Generate scalings
16838
 
    const double scalings_y_0 = 1;
16839
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
16840
 
    const double scalings_z_0 = 1;
16841
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
16842
 
    
16843
 
    // Compute psitilde_a
16844
 
    const double psitilde_a_0 = 1;
16845
 
    const double psitilde_a_1 = x;
16846
 
    
16847
 
    // Compute psitilde_bs
16848
 
    const double psitilde_bs_0_0 = 1;
16849
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
16850
 
    const double psitilde_bs_1_0 = 1;
16851
 
    
16852
 
    // Compute psitilde_cs
16853
 
    const double psitilde_cs_00_0 = 1;
16854
 
    const double psitilde_cs_00_1 = 2*z + 1;
16855
 
    const double psitilde_cs_01_0 = 1;
16856
 
    const double psitilde_cs_10_0 = 1;
16857
 
    
16858
 
    // Compute basisvalues
16859
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
16860
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
16861
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
16862
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
16863
 
    
16864
 
    // Table(s) of coefficients
16865
 
    static const double coefficients0[4][4] = \
16866
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
16867
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
16868
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
16869
 
    {0.288675135, 0, 0, 0.223606798}};
16870
 
    
16871
 
    // Extract relevant coefficients
16872
 
    const double coeff0_0 = coefficients0[dof][0];
16873
 
    const double coeff0_1 = coefficients0[dof][1];
16874
 
    const double coeff0_2 = coefficients0[dof][2];
16875
 
    const double coeff0_3 = coefficients0[dof][3];
16876
 
    
16877
 
    // Compute value(s)
16878
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
16879
 
  }
16880
 
 
16881
 
  /// Evaluate all basis functions at given point in cell
16882
 
  virtual void evaluate_basis_all(double* values,
16883
 
                                  const double* coordinates,
16884
 
                                  const ufc::cell& c) const
16885
 
  {
16886
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
16887
 
  }
16888
 
 
16889
 
  /// Evaluate order n derivatives of basis function i at given point in cell
16890
 
  virtual void evaluate_basis_derivatives(unsigned int i,
16891
 
                                          unsigned int n,
16892
 
                                          double* values,
16893
 
                                          const double* coordinates,
16894
 
                                          const ufc::cell& c) const
16895
 
  {
16896
 
    // Extract vertex coordinates
16897
 
    const double * const * element_coordinates = c.coordinates;
16898
 
    
16899
 
    // Compute Jacobian of affine map from reference cell
16900
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
16901
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
16902
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
16903
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
16904
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
16905
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
16906
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
16907
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
16908
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
16909
 
    
16910
 
    // Compute sub determinants
16911
 
    const double d00 = J_11*J_22 - J_12*J_21;
16912
 
    const double d01 = J_12*J_20 - J_10*J_22;
16913
 
    const double d02 = J_10*J_21 - J_11*J_20;
16914
 
    
16915
 
    const double d10 = J_02*J_21 - J_01*J_22;
16916
 
    const double d11 = J_00*J_22 - J_02*J_20;
16917
 
    const double d12 = J_01*J_20 - J_00*J_21;
16918
 
    
16919
 
    const double d20 = J_01*J_12 - J_02*J_11;
16920
 
    const double d21 = J_02*J_10 - J_00*J_12;
16921
 
    const double d22 = J_00*J_11 - J_01*J_10;
16922
 
    
16923
 
    // Compute determinant of Jacobian
16924
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
16925
 
    
16926
 
    // Compute inverse of Jacobian
16927
 
    
16928
 
    // Compute constants
16929
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
16930
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
16931
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
16932
 
    
16933
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
16934
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
16935
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
16936
 
    
16937
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
16938
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
16939
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
16940
 
    
16941
 
    // Get coordinates and map to the UFC reference element
16942
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
16943
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
16944
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
16945
 
    
16946
 
    // Map coordinates to the reference cube
16947
 
    if (std::abs(y + z - 1.0) < 1e-08)
16948
 
      x = 1.0;
16949
 
    else
16950
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
16951
 
    if (std::abs(z - 1.0) < 1e-08)
16952
 
      y = -1.0;
16953
 
    else
16954
 
      y = 2.0 * y/(1.0 - z) - 1.0;
16955
 
    z = 2.0 * z - 1.0;
16956
 
    
16957
 
    // Compute number of derivatives
16958
 
    unsigned int num_derivatives = 1;
16959
 
    
16960
 
    for (unsigned int j = 0; j < n; j++)
16961
 
      num_derivatives *= 3;
16962
 
    
16963
 
    
16964
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
16965
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
16966
 
    
16967
 
    for (unsigned int j = 0; j < num_derivatives; j++)
16968
 
    {
16969
 
      combinations[j] = new unsigned int [n];
16970
 
      for (unsigned int k = 0; k < n; k++)
16971
 
        combinations[j][k] = 0;
16972
 
    }
16973
 
    
16974
 
    // Generate combinations of derivatives
16975
 
    for (unsigned int row = 1; row < num_derivatives; row++)
16976
 
    {
16977
 
      for (unsigned int num = 0; num < row; num++)
16978
 
      {
16979
 
        for (unsigned int col = n-1; col+1 > 0; col--)
16980
 
        {
16981
 
          if (combinations[row][col] + 1 > 2)
16982
 
            combinations[row][col] = 0;
16983
 
          else
16984
 
          {
16985
 
            combinations[row][col] += 1;
16986
 
            break;
16987
 
          }
16988
 
        }
16989
 
      }
16990
 
    }
16991
 
    
16992
 
    // Compute inverse of Jacobian
16993
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
16994
 
    
16995
 
    // Declare transformation matrix
16996
 
    // Declare pointer to two dimensional array and initialise
16997
 
    double **transform = new double *[num_derivatives];
16998
 
    
16999
 
    for (unsigned int j = 0; j < num_derivatives; j++)
17000
 
    {
17001
 
      transform[j] = new double [num_derivatives];
17002
 
      for (unsigned int k = 0; k < num_derivatives; k++)
17003
 
        transform[j][k] = 1;
17004
 
    }
17005
 
    
17006
 
    // Construct transformation matrix
17007
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17008
 
    {
17009
 
      for (unsigned int col = 0; col < num_derivatives; col++)
17010
 
      {
17011
 
        for (unsigned int k = 0; k < n; k++)
17012
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
17013
 
      }
17014
 
    }
17015
 
    
17016
 
    // Reset values
17017
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
17018
 
      values[j] = 0;
17019
 
    
17020
 
    // Map degree of freedom to element degree of freedom
17021
 
    const unsigned int dof = i;
17022
 
    
17023
 
    // Generate scalings
17024
 
    const double scalings_y_0 = 1;
17025
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
17026
 
    const double scalings_z_0 = 1;
17027
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
17028
 
    
17029
 
    // Compute psitilde_a
17030
 
    const double psitilde_a_0 = 1;
17031
 
    const double psitilde_a_1 = x;
17032
 
    
17033
 
    // Compute psitilde_bs
17034
 
    const double psitilde_bs_0_0 = 1;
17035
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
17036
 
    const double psitilde_bs_1_0 = 1;
17037
 
    
17038
 
    // Compute psitilde_cs
17039
 
    const double psitilde_cs_00_0 = 1;
17040
 
    const double psitilde_cs_00_1 = 2*z + 1;
17041
 
    const double psitilde_cs_01_0 = 1;
17042
 
    const double psitilde_cs_10_0 = 1;
17043
 
    
17044
 
    // Compute basisvalues
17045
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
17046
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
17047
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
17048
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
17049
 
    
17050
 
    // Table(s) of coefficients
17051
 
    static const double coefficients0[4][4] = \
17052
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
17053
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
17054
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
17055
 
    {0.288675135, 0, 0, 0.223606798}};
17056
 
    
17057
 
    // Interesting (new) part
17058
 
    // Tables of derivatives of the polynomial base (transpose)
17059
 
    static const double dmats0[4][4] = \
17060
 
    {{0, 0, 0, 0},
17061
 
    {6.32455532, 0, 0, 0},
17062
 
    {0, 0, 0, 0},
17063
 
    {0, 0, 0, 0}};
17064
 
    
17065
 
    static const double dmats1[4][4] = \
17066
 
    {{0, 0, 0, 0},
17067
 
    {3.16227766, 0, 0, 0},
17068
 
    {5.47722558, 0, 0, 0},
17069
 
    {0, 0, 0, 0}};
17070
 
    
17071
 
    static const double dmats2[4][4] = \
17072
 
    {{0, 0, 0, 0},
17073
 
    {3.16227766, 0, 0, 0},
17074
 
    {1.82574186, 0, 0, 0},
17075
 
    {5.16397779, 0, 0, 0}};
17076
 
    
17077
 
    // Compute reference derivatives
17078
 
    // Declare pointer to array of derivatives on FIAT element
17079
 
    double *derivatives = new double [num_derivatives];
17080
 
    
17081
 
    // Declare coefficients
17082
 
    double coeff0_0 = 0;
17083
 
    double coeff0_1 = 0;
17084
 
    double coeff0_2 = 0;
17085
 
    double coeff0_3 = 0;
17086
 
    
17087
 
    // Declare new coefficients
17088
 
    double new_coeff0_0 = 0;
17089
 
    double new_coeff0_1 = 0;
17090
 
    double new_coeff0_2 = 0;
17091
 
    double new_coeff0_3 = 0;
17092
 
    
17093
 
    // Loop possible derivatives
17094
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
17095
 
    {
17096
 
      // Get values from coefficients array
17097
 
      new_coeff0_0 = coefficients0[dof][0];
17098
 
      new_coeff0_1 = coefficients0[dof][1];
17099
 
      new_coeff0_2 = coefficients0[dof][2];
17100
 
      new_coeff0_3 = coefficients0[dof][3];
17101
 
    
17102
 
      // Loop derivative order
17103
 
      for (unsigned int j = 0; j < n; j++)
17104
 
      {
17105
 
        // Update old coefficients
17106
 
        coeff0_0 = new_coeff0_0;
17107
 
        coeff0_1 = new_coeff0_1;
17108
 
        coeff0_2 = new_coeff0_2;
17109
 
        coeff0_3 = new_coeff0_3;
17110
 
    
17111
 
        if(combinations[deriv_num][j] == 0)
17112
 
        {
17113
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
17114
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
17115
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
17116
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
17117
 
        }
17118
 
        if(combinations[deriv_num][j] == 1)
17119
 
        {
17120
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
17121
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
17122
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
17123
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
17124
 
        }
17125
 
        if(combinations[deriv_num][j] == 2)
17126
 
        {
17127
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
17128
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
17129
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
17130
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
17131
 
        }
17132
 
    
17133
 
      }
17134
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
17135
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
17136
 
    }
17137
 
    
17138
 
    // Transform derivatives back to physical element
17139
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17140
 
    {
17141
 
      for (unsigned int col = 0; col < num_derivatives; col++)
17142
 
      {
17143
 
        values[row] += transform[row][col]*derivatives[col];
17144
 
      }
17145
 
    }
17146
 
    // Delete pointer to array of derivatives on FIAT element
17147
 
    delete [] derivatives;
17148
 
    
17149
 
    // Delete pointer to array of combinations of derivatives and transform
17150
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17151
 
    {
17152
 
      delete [] combinations[row];
17153
 
      delete [] transform[row];
17154
 
    }
17155
 
    
17156
 
    delete [] combinations;
17157
 
    delete [] transform;
17158
 
  }
17159
 
 
17160
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
17161
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
17162
 
                                              double* values,
17163
 
                                              const double* coordinates,
17164
 
                                              const ufc::cell& c) const
17165
 
  {
17166
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
17167
 
  }
17168
 
 
17169
 
  /// Evaluate linear functional for dof i on the function f
17170
 
  virtual double evaluate_dof(unsigned int i,
17171
 
                              const ufc::function& f,
17172
 
                              const ufc::cell& c) const
17173
 
  {
17174
 
    // The reference points, direction and weights:
17175
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
17176
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
17177
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
17178
 
    
17179
 
    const double * const * x = c.coordinates;
17180
 
    double result = 0.0;
17181
 
    // Iterate over the points:
17182
 
    // Evaluate basis functions for affine mapping
17183
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
17184
 
    const double w1 = X[i][0][0];
17185
 
    const double w2 = X[i][0][1];
17186
 
    const double w3 = X[i][0][2];
17187
 
    
17188
 
    // Compute affine mapping y = F(X)
17189
 
    double y[3];
17190
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
17191
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
17192
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
17193
 
    
17194
 
    // Evaluate function at physical points
17195
 
    double values[1];
17196
 
    f.evaluate(values, y, c);
17197
 
    
17198
 
    // Map function values using appropriate mapping
17199
 
    // Affine map: Do nothing
17200
 
    
17201
 
    // Note that we do not map the weights (yet).
17202
 
    
17203
 
    // Take directional components
17204
 
    for(int k = 0; k < 1; k++)
17205
 
      result += values[k]*D[i][0][k];
17206
 
    // Multiply by weights
17207
 
    result *= W[i][0];
17208
 
    
17209
 
    return result;
17210
 
  }
17211
 
 
17212
 
  /// Evaluate linear functionals for all dofs on the function f
17213
 
  virtual void evaluate_dofs(double* values,
17214
 
                             const ufc::function& f,
17215
 
                             const ufc::cell& c) const
17216
 
  {
17217
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
17218
 
  }
17219
 
 
17220
 
  /// Interpolate vertex values from dof values
17221
 
  virtual void interpolate_vertex_values(double* vertex_values,
17222
 
                                         const double* dof_values,
17223
 
                                         const ufc::cell& c) const
17224
 
  {
17225
 
    // Evaluate at vertices and use affine mapping
17226
 
    vertex_values[0] = dof_values[0];
17227
 
    vertex_values[1] = dof_values[1];
17228
 
    vertex_values[2] = dof_values[2];
17229
 
    vertex_values[3] = dof_values[3];
17230
 
  }
17231
 
 
17232
 
  /// Return the number of sub elements (for a mixed element)
17233
 
  virtual unsigned int num_sub_elements() const
17234
 
  {
17235
 
    return 1;
17236
 
  }
17237
 
 
17238
 
  /// Create a new finite element for sub element i (for a mixed element)
17239
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
17240
 
  {
17241
 
    return new hyperelasticity_1_finite_element_2_0();
17242
 
  }
17243
 
 
17244
 
};
17245
 
 
17246
 
/// This class defines the interface for a finite element.
17247
 
 
17248
 
class hyperelasticity_1_finite_element_2_1: public ufc::finite_element
17249
 
{
17250
 
public:
17251
 
 
17252
 
  /// Constructor
17253
 
  hyperelasticity_1_finite_element_2_1() : ufc::finite_element()
17254
 
  {
17255
 
    // Do nothing
17256
 
  }
17257
 
 
17258
 
  /// Destructor
17259
 
  virtual ~hyperelasticity_1_finite_element_2_1()
17260
 
  {
17261
 
    // Do nothing
17262
 
  }
17263
 
 
17264
 
  /// Return a string identifying the finite element
17265
 
  virtual const char* signature() const
17266
 
  {
17267
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
17268
 
  }
17269
 
 
17270
 
  /// Return the cell shape
17271
 
  virtual ufc::shape cell_shape() const
17272
 
  {
17273
 
    return ufc::tetrahedron;
17274
 
  }
17275
 
 
17276
 
  /// Return the dimension of the finite element function space
17277
 
  virtual unsigned int space_dimension() const
17278
 
  {
17279
 
    return 4;
17280
 
  }
17281
 
 
17282
 
  /// Return the rank of the value space
17283
 
  virtual unsigned int value_rank() const
17284
 
  {
17285
 
    return 0;
17286
 
  }
17287
 
 
17288
 
  /// Return the dimension of the value space for axis i
17289
 
  virtual unsigned int value_dimension(unsigned int i) const
17290
 
  {
17291
 
    return 1;
17292
 
  }
17293
 
 
17294
 
  /// Evaluate basis function i at given point in cell
17295
 
  virtual void evaluate_basis(unsigned int i,
17296
 
                              double* values,
17297
 
                              const double* coordinates,
17298
 
                              const ufc::cell& c) const
17299
 
  {
17300
 
    // Extract vertex coordinates
17301
 
    const double * const * element_coordinates = c.coordinates;
17302
 
    
17303
 
    // Compute Jacobian of affine map from reference cell
17304
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
17305
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
17306
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
17307
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
17308
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
17309
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
17310
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
17311
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
17312
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
17313
 
    
17314
 
    // Compute sub determinants
17315
 
    const double d00 = J_11*J_22 - J_12*J_21;
17316
 
    const double d01 = J_12*J_20 - J_10*J_22;
17317
 
    const double d02 = J_10*J_21 - J_11*J_20;
17318
 
    
17319
 
    const double d10 = J_02*J_21 - J_01*J_22;
17320
 
    const double d11 = J_00*J_22 - J_02*J_20;
17321
 
    const double d12 = J_01*J_20 - J_00*J_21;
17322
 
    
17323
 
    const double d20 = J_01*J_12 - J_02*J_11;
17324
 
    const double d21 = J_02*J_10 - J_00*J_12;
17325
 
    const double d22 = J_00*J_11 - J_01*J_10;
17326
 
    
17327
 
    // Compute determinant of Jacobian
17328
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
17329
 
    
17330
 
    // Compute inverse of Jacobian
17331
 
    
17332
 
    // Compute constants
17333
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
17334
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
17335
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
17336
 
    
17337
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
17338
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
17339
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
17340
 
    
17341
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
17342
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
17343
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
17344
 
    
17345
 
    // Get coordinates and map to the UFC reference element
17346
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
17347
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
17348
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
17349
 
    
17350
 
    // Map coordinates to the reference cube
17351
 
    if (std::abs(y + z - 1.0) < 1e-08)
17352
 
      x = 1.0;
17353
 
    else
17354
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
17355
 
    if (std::abs(z - 1.0) < 1e-08)
17356
 
      y = -1.0;
17357
 
    else
17358
 
      y = 2.0 * y/(1.0 - z) - 1.0;
17359
 
    z = 2.0 * z - 1.0;
17360
 
    
17361
 
    // Reset values
17362
 
    *values = 0;
17363
 
    
17364
 
    // Map degree of freedom to element degree of freedom
17365
 
    const unsigned int dof = i;
17366
 
    
17367
 
    // Generate scalings
17368
 
    const double scalings_y_0 = 1;
17369
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
17370
 
    const double scalings_z_0 = 1;
17371
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
17372
 
    
17373
 
    // Compute psitilde_a
17374
 
    const double psitilde_a_0 = 1;
17375
 
    const double psitilde_a_1 = x;
17376
 
    
17377
 
    // Compute psitilde_bs
17378
 
    const double psitilde_bs_0_0 = 1;
17379
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
17380
 
    const double psitilde_bs_1_0 = 1;
17381
 
    
17382
 
    // Compute psitilde_cs
17383
 
    const double psitilde_cs_00_0 = 1;
17384
 
    const double psitilde_cs_00_1 = 2*z + 1;
17385
 
    const double psitilde_cs_01_0 = 1;
17386
 
    const double psitilde_cs_10_0 = 1;
17387
 
    
17388
 
    // Compute basisvalues
17389
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
17390
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
17391
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
17392
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
17393
 
    
17394
 
    // Table(s) of coefficients
17395
 
    static const double coefficients0[4][4] = \
17396
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
17397
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
17398
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
17399
 
    {0.288675135, 0, 0, 0.223606798}};
17400
 
    
17401
 
    // Extract relevant coefficients
17402
 
    const double coeff0_0 = coefficients0[dof][0];
17403
 
    const double coeff0_1 = coefficients0[dof][1];
17404
 
    const double coeff0_2 = coefficients0[dof][2];
17405
 
    const double coeff0_3 = coefficients0[dof][3];
17406
 
    
17407
 
    // Compute value(s)
17408
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
17409
 
  }
17410
 
 
17411
 
  /// Evaluate all basis functions at given point in cell
17412
 
  virtual void evaluate_basis_all(double* values,
17413
 
                                  const double* coordinates,
17414
 
                                  const ufc::cell& c) const
17415
 
  {
17416
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
17417
 
  }
17418
 
 
17419
 
  /// Evaluate order n derivatives of basis function i at given point in cell
17420
 
  virtual void evaluate_basis_derivatives(unsigned int i,
17421
 
                                          unsigned int n,
17422
 
                                          double* values,
17423
 
                                          const double* coordinates,
17424
 
                                          const ufc::cell& c) const
17425
 
  {
17426
 
    // Extract vertex coordinates
17427
 
    const double * const * element_coordinates = c.coordinates;
17428
 
    
17429
 
    // Compute Jacobian of affine map from reference cell
17430
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
17431
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
17432
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
17433
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
17434
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
17435
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
17436
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
17437
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
17438
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
17439
 
    
17440
 
    // Compute sub determinants
17441
 
    const double d00 = J_11*J_22 - J_12*J_21;
17442
 
    const double d01 = J_12*J_20 - J_10*J_22;
17443
 
    const double d02 = J_10*J_21 - J_11*J_20;
17444
 
    
17445
 
    const double d10 = J_02*J_21 - J_01*J_22;
17446
 
    const double d11 = J_00*J_22 - J_02*J_20;
17447
 
    const double d12 = J_01*J_20 - J_00*J_21;
17448
 
    
17449
 
    const double d20 = J_01*J_12 - J_02*J_11;
17450
 
    const double d21 = J_02*J_10 - J_00*J_12;
17451
 
    const double d22 = J_00*J_11 - J_01*J_10;
17452
 
    
17453
 
    // Compute determinant of Jacobian
17454
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
17455
 
    
17456
 
    // Compute inverse of Jacobian
17457
 
    
17458
 
    // Compute constants
17459
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
17460
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
17461
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
17462
 
    
17463
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
17464
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
17465
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
17466
 
    
17467
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
17468
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
17469
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
17470
 
    
17471
 
    // Get coordinates and map to the UFC reference element
17472
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
17473
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
17474
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
17475
 
    
17476
 
    // Map coordinates to the reference cube
17477
 
    if (std::abs(y + z - 1.0) < 1e-08)
17478
 
      x = 1.0;
17479
 
    else
17480
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
17481
 
    if (std::abs(z - 1.0) < 1e-08)
17482
 
      y = -1.0;
17483
 
    else
17484
 
      y = 2.0 * y/(1.0 - z) - 1.0;
17485
 
    z = 2.0 * z - 1.0;
17486
 
    
17487
 
    // Compute number of derivatives
17488
 
    unsigned int num_derivatives = 1;
17489
 
    
17490
 
    for (unsigned int j = 0; j < n; j++)
17491
 
      num_derivatives *= 3;
17492
 
    
17493
 
    
17494
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
17495
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
17496
 
    
17497
 
    for (unsigned int j = 0; j < num_derivatives; j++)
17498
 
    {
17499
 
      combinations[j] = new unsigned int [n];
17500
 
      for (unsigned int k = 0; k < n; k++)
17501
 
        combinations[j][k] = 0;
17502
 
    }
17503
 
    
17504
 
    // Generate combinations of derivatives
17505
 
    for (unsigned int row = 1; row < num_derivatives; row++)
17506
 
    {
17507
 
      for (unsigned int num = 0; num < row; num++)
17508
 
      {
17509
 
        for (unsigned int col = n-1; col+1 > 0; col--)
17510
 
        {
17511
 
          if (combinations[row][col] + 1 > 2)
17512
 
            combinations[row][col] = 0;
17513
 
          else
17514
 
          {
17515
 
            combinations[row][col] += 1;
17516
 
            break;
17517
 
          }
17518
 
        }
17519
 
      }
17520
 
    }
17521
 
    
17522
 
    // Compute inverse of Jacobian
17523
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
17524
 
    
17525
 
    // Declare transformation matrix
17526
 
    // Declare pointer to two dimensional array and initialise
17527
 
    double **transform = new double *[num_derivatives];
17528
 
    
17529
 
    for (unsigned int j = 0; j < num_derivatives; j++)
17530
 
    {
17531
 
      transform[j] = new double [num_derivatives];
17532
 
      for (unsigned int k = 0; k < num_derivatives; k++)
17533
 
        transform[j][k] = 1;
17534
 
    }
17535
 
    
17536
 
    // Construct transformation matrix
17537
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17538
 
    {
17539
 
      for (unsigned int col = 0; col < num_derivatives; col++)
17540
 
      {
17541
 
        for (unsigned int k = 0; k < n; k++)
17542
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
17543
 
      }
17544
 
    }
17545
 
    
17546
 
    // Reset values
17547
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
17548
 
      values[j] = 0;
17549
 
    
17550
 
    // Map degree of freedom to element degree of freedom
17551
 
    const unsigned int dof = i;
17552
 
    
17553
 
    // Generate scalings
17554
 
    const double scalings_y_0 = 1;
17555
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
17556
 
    const double scalings_z_0 = 1;
17557
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
17558
 
    
17559
 
    // Compute psitilde_a
17560
 
    const double psitilde_a_0 = 1;
17561
 
    const double psitilde_a_1 = x;
17562
 
    
17563
 
    // Compute psitilde_bs
17564
 
    const double psitilde_bs_0_0 = 1;
17565
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
17566
 
    const double psitilde_bs_1_0 = 1;
17567
 
    
17568
 
    // Compute psitilde_cs
17569
 
    const double psitilde_cs_00_0 = 1;
17570
 
    const double psitilde_cs_00_1 = 2*z + 1;
17571
 
    const double psitilde_cs_01_0 = 1;
17572
 
    const double psitilde_cs_10_0 = 1;
17573
 
    
17574
 
    // Compute basisvalues
17575
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
17576
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
17577
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
17578
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
17579
 
    
17580
 
    // Table(s) of coefficients
17581
 
    static const double coefficients0[4][4] = \
17582
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
17583
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
17584
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
17585
 
    {0.288675135, 0, 0, 0.223606798}};
17586
 
    
17587
 
    // Interesting (new) part
17588
 
    // Tables of derivatives of the polynomial base (transpose)
17589
 
    static const double dmats0[4][4] = \
17590
 
    {{0, 0, 0, 0},
17591
 
    {6.32455532, 0, 0, 0},
17592
 
    {0, 0, 0, 0},
17593
 
    {0, 0, 0, 0}};
17594
 
    
17595
 
    static const double dmats1[4][4] = \
17596
 
    {{0, 0, 0, 0},
17597
 
    {3.16227766, 0, 0, 0},
17598
 
    {5.47722558, 0, 0, 0},
17599
 
    {0, 0, 0, 0}};
17600
 
    
17601
 
    static const double dmats2[4][4] = \
17602
 
    {{0, 0, 0, 0},
17603
 
    {3.16227766, 0, 0, 0},
17604
 
    {1.82574186, 0, 0, 0},
17605
 
    {5.16397779, 0, 0, 0}};
17606
 
    
17607
 
    // Compute reference derivatives
17608
 
    // Declare pointer to array of derivatives on FIAT element
17609
 
    double *derivatives = new double [num_derivatives];
17610
 
    
17611
 
    // Declare coefficients
17612
 
    double coeff0_0 = 0;
17613
 
    double coeff0_1 = 0;
17614
 
    double coeff0_2 = 0;
17615
 
    double coeff0_3 = 0;
17616
 
    
17617
 
    // Declare new coefficients
17618
 
    double new_coeff0_0 = 0;
17619
 
    double new_coeff0_1 = 0;
17620
 
    double new_coeff0_2 = 0;
17621
 
    double new_coeff0_3 = 0;
17622
 
    
17623
 
    // Loop possible derivatives
17624
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
17625
 
    {
17626
 
      // Get values from coefficients array
17627
 
      new_coeff0_0 = coefficients0[dof][0];
17628
 
      new_coeff0_1 = coefficients0[dof][1];
17629
 
      new_coeff0_2 = coefficients0[dof][2];
17630
 
      new_coeff0_3 = coefficients0[dof][3];
17631
 
    
17632
 
      // Loop derivative order
17633
 
      for (unsigned int j = 0; j < n; j++)
17634
 
      {
17635
 
        // Update old coefficients
17636
 
        coeff0_0 = new_coeff0_0;
17637
 
        coeff0_1 = new_coeff0_1;
17638
 
        coeff0_2 = new_coeff0_2;
17639
 
        coeff0_3 = new_coeff0_3;
17640
 
    
17641
 
        if(combinations[deriv_num][j] == 0)
17642
 
        {
17643
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
17644
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
17645
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
17646
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
17647
 
        }
17648
 
        if(combinations[deriv_num][j] == 1)
17649
 
        {
17650
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
17651
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
17652
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
17653
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
17654
 
        }
17655
 
        if(combinations[deriv_num][j] == 2)
17656
 
        {
17657
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
17658
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
17659
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
17660
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
17661
 
        }
17662
 
    
17663
 
      }
17664
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
17665
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
17666
 
    }
17667
 
    
17668
 
    // Transform derivatives back to physical element
17669
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17670
 
    {
17671
 
      for (unsigned int col = 0; col < num_derivatives; col++)
17672
 
      {
17673
 
        values[row] += transform[row][col]*derivatives[col];
17674
 
      }
17675
 
    }
17676
 
    // Delete pointer to array of derivatives on FIAT element
17677
 
    delete [] derivatives;
17678
 
    
17679
 
    // Delete pointer to array of combinations of derivatives and transform
17680
 
    for (unsigned int row = 0; row < num_derivatives; row++)
17681
 
    {
17682
 
      delete [] combinations[row];
17683
 
      delete [] transform[row];
17684
 
    }
17685
 
    
17686
 
    delete [] combinations;
17687
 
    delete [] transform;
17688
 
  }
17689
 
 
17690
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
17691
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
17692
 
                                              double* values,
17693
 
                                              const double* coordinates,
17694
 
                                              const ufc::cell& c) const
17695
 
  {
17696
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
17697
 
  }
17698
 
 
17699
 
  /// Evaluate linear functional for dof i on the function f
17700
 
  virtual double evaluate_dof(unsigned int i,
17701
 
                              const ufc::function& f,
17702
 
                              const ufc::cell& c) const
17703
 
  {
17704
 
    // The reference points, direction and weights:
17705
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
17706
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
17707
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
17708
 
    
17709
 
    const double * const * x = c.coordinates;
17710
 
    double result = 0.0;
17711
 
    // Iterate over the points:
17712
 
    // Evaluate basis functions for affine mapping
17713
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
17714
 
    const double w1 = X[i][0][0];
17715
 
    const double w2 = X[i][0][1];
17716
 
    const double w3 = X[i][0][2];
17717
 
    
17718
 
    // Compute affine mapping y = F(X)
17719
 
    double y[3];
17720
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
17721
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
17722
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
17723
 
    
17724
 
    // Evaluate function at physical points
17725
 
    double values[1];
17726
 
    f.evaluate(values, y, c);
17727
 
    
17728
 
    // Map function values using appropriate mapping
17729
 
    // Affine map: Do nothing
17730
 
    
17731
 
    // Note that we do not map the weights (yet).
17732
 
    
17733
 
    // Take directional components
17734
 
    for(int k = 0; k < 1; k++)
17735
 
      result += values[k]*D[i][0][k];
17736
 
    // Multiply by weights
17737
 
    result *= W[i][0];
17738
 
    
17739
 
    return result;
17740
 
  }
17741
 
 
17742
 
  /// Evaluate linear functionals for all dofs on the function f
17743
 
  virtual void evaluate_dofs(double* values,
17744
 
                             const ufc::function& f,
17745
 
                             const ufc::cell& c) const
17746
 
  {
17747
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
17748
 
  }
17749
 
 
17750
 
  /// Interpolate vertex values from dof values
17751
 
  virtual void interpolate_vertex_values(double* vertex_values,
17752
 
                                         const double* dof_values,
17753
 
                                         const ufc::cell& c) const
17754
 
  {
17755
 
    // Evaluate at vertices and use affine mapping
17756
 
    vertex_values[0] = dof_values[0];
17757
 
    vertex_values[1] = dof_values[1];
17758
 
    vertex_values[2] = dof_values[2];
17759
 
    vertex_values[3] = dof_values[3];
17760
 
  }
17761
 
 
17762
 
  /// Return the number of sub elements (for a mixed element)
17763
 
  virtual unsigned int num_sub_elements() const
17764
 
  {
17765
 
    return 1;
17766
 
  }
17767
 
 
17768
 
  /// Create a new finite element for sub element i (for a mixed element)
17769
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
17770
 
  {
17771
 
    return new hyperelasticity_1_finite_element_2_1();
17772
 
  }
17773
 
 
17774
 
};
17775
 
 
17776
 
/// This class defines the interface for a finite element.
17777
 
 
17778
 
class hyperelasticity_1_finite_element_2_2: public ufc::finite_element
17779
 
{
17780
 
public:
17781
 
 
17782
 
  /// Constructor
17783
 
  hyperelasticity_1_finite_element_2_2() : ufc::finite_element()
17784
 
  {
17785
 
    // Do nothing
17786
 
  }
17787
 
 
17788
 
  /// Destructor
17789
 
  virtual ~hyperelasticity_1_finite_element_2_2()
17790
 
  {
17791
 
    // Do nothing
17792
 
  }
17793
 
 
17794
 
  /// Return a string identifying the finite element
17795
 
  virtual const char* signature() const
17796
 
  {
17797
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
17798
 
  }
17799
 
 
17800
 
  /// Return the cell shape
17801
 
  virtual ufc::shape cell_shape() const
17802
 
  {
17803
 
    return ufc::tetrahedron;
17804
 
  }
17805
 
 
17806
 
  /// Return the dimension of the finite element function space
17807
 
  virtual unsigned int space_dimension() const
17808
 
  {
17809
 
    return 4;
17810
 
  }
17811
 
 
17812
 
  /// Return the rank of the value space
17813
 
  virtual unsigned int value_rank() const
17814
 
  {
17815
 
    return 0;
17816
 
  }
17817
 
 
17818
 
  /// Return the dimension of the value space for axis i
17819
 
  virtual unsigned int value_dimension(unsigned int i) const
17820
 
  {
17821
 
    return 1;
17822
 
  }
17823
 
 
17824
 
  /// Evaluate basis function i at given point in cell
17825
 
  virtual void evaluate_basis(unsigned int i,
17826
 
                              double* values,
17827
 
                              const double* coordinates,
17828
 
                              const ufc::cell& c) const
17829
 
  {
17830
 
    // Extract vertex coordinates
17831
 
    const double * const * element_coordinates = c.coordinates;
17832
 
    
17833
 
    // Compute Jacobian of affine map from reference cell
17834
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
17835
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
17836
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
17837
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
17838
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
17839
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
17840
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
17841
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
17842
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
17843
 
    
17844
 
    // Compute sub determinants
17845
 
    const double d00 = J_11*J_22 - J_12*J_21;
17846
 
    const double d01 = J_12*J_20 - J_10*J_22;
17847
 
    const double d02 = J_10*J_21 - J_11*J_20;
17848
 
    
17849
 
    const double d10 = J_02*J_21 - J_01*J_22;
17850
 
    const double d11 = J_00*J_22 - J_02*J_20;
17851
 
    const double d12 = J_01*J_20 - J_00*J_21;
17852
 
    
17853
 
    const double d20 = J_01*J_12 - J_02*J_11;
17854
 
    const double d21 = J_02*J_10 - J_00*J_12;
17855
 
    const double d22 = J_00*J_11 - J_01*J_10;
17856
 
    
17857
 
    // Compute determinant of Jacobian
17858
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
17859
 
    
17860
 
    // Compute inverse of Jacobian
17861
 
    
17862
 
    // Compute constants
17863
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
17864
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
17865
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
17866
 
    
17867
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
17868
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
17869
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
17870
 
    
17871
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
17872
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
17873
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
17874
 
    
17875
 
    // Get coordinates and map to the UFC reference element
17876
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
17877
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
17878
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
17879
 
    
17880
 
    // Map coordinates to the reference cube
17881
 
    if (std::abs(y + z - 1.0) < 1e-08)
17882
 
      x = 1.0;
17883
 
    else
17884
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
17885
 
    if (std::abs(z - 1.0) < 1e-08)
17886
 
      y = -1.0;
17887
 
    else
17888
 
      y = 2.0 * y/(1.0 - z) - 1.0;
17889
 
    z = 2.0 * z - 1.0;
17890
 
    
17891
 
    // Reset values
17892
 
    *values = 0;
17893
 
    
17894
 
    // Map degree of freedom to element degree of freedom
17895
 
    const unsigned int dof = i;
17896
 
    
17897
 
    // Generate scalings
17898
 
    const double scalings_y_0 = 1;
17899
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
17900
 
    const double scalings_z_0 = 1;
17901
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
17902
 
    
17903
 
    // Compute psitilde_a
17904
 
    const double psitilde_a_0 = 1;
17905
 
    const double psitilde_a_1 = x;
17906
 
    
17907
 
    // Compute psitilde_bs
17908
 
    const double psitilde_bs_0_0 = 1;
17909
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
17910
 
    const double psitilde_bs_1_0 = 1;
17911
 
    
17912
 
    // Compute psitilde_cs
17913
 
    const double psitilde_cs_00_0 = 1;
17914
 
    const double psitilde_cs_00_1 = 2*z + 1;
17915
 
    const double psitilde_cs_01_0 = 1;
17916
 
    const double psitilde_cs_10_0 = 1;
17917
 
    
17918
 
    // Compute basisvalues
17919
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
17920
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
17921
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
17922
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
17923
 
    
17924
 
    // Table(s) of coefficients
17925
 
    static const double coefficients0[4][4] = \
17926
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
17927
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
17928
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
17929
 
    {0.288675135, 0, 0, 0.223606798}};
17930
 
    
17931
 
    // Extract relevant coefficients
17932
 
    const double coeff0_0 = coefficients0[dof][0];
17933
 
    const double coeff0_1 = coefficients0[dof][1];
17934
 
    const double coeff0_2 = coefficients0[dof][2];
17935
 
    const double coeff0_3 = coefficients0[dof][3];
17936
 
    
17937
 
    // Compute value(s)
17938
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
17939
 
  }
17940
 
 
17941
 
  /// Evaluate all basis functions at given point in cell
17942
 
  virtual void evaluate_basis_all(double* values,
17943
 
                                  const double* coordinates,
17944
 
                                  const ufc::cell& c) const
17945
 
  {
17946
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
17947
 
  }
17948
 
 
17949
 
  /// Evaluate order n derivatives of basis function i at given point in cell
17950
 
  virtual void evaluate_basis_derivatives(unsigned int i,
17951
 
                                          unsigned int n,
17952
 
                                          double* values,
17953
 
                                          const double* coordinates,
17954
 
                                          const ufc::cell& c) const
17955
 
  {
17956
 
    // Extract vertex coordinates
17957
 
    const double * const * element_coordinates = c.coordinates;
17958
 
    
17959
 
    // Compute Jacobian of affine map from reference cell
17960
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
17961
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
17962
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
17963
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
17964
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
17965
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
17966
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
17967
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
17968
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
17969
 
    
17970
 
    // Compute sub determinants
17971
 
    const double d00 = J_11*J_22 - J_12*J_21;
17972
 
    const double d01 = J_12*J_20 - J_10*J_22;
17973
 
    const double d02 = J_10*J_21 - J_11*J_20;
17974
 
    
17975
 
    const double d10 = J_02*J_21 - J_01*J_22;
17976
 
    const double d11 = J_00*J_22 - J_02*J_20;
17977
 
    const double d12 = J_01*J_20 - J_00*J_21;
17978
 
    
17979
 
    const double d20 = J_01*J_12 - J_02*J_11;
17980
 
    const double d21 = J_02*J_10 - J_00*J_12;
17981
 
    const double d22 = J_00*J_11 - J_01*J_10;
17982
 
    
17983
 
    // Compute determinant of Jacobian
17984
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
17985
 
    
17986
 
    // Compute inverse of Jacobian
17987
 
    
17988
 
    // Compute constants
17989
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
17990
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
17991
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
17992
 
    
17993
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
17994
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
17995
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
17996
 
    
17997
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
17998
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
17999
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
18000
 
    
18001
 
    // Get coordinates and map to the UFC reference element
18002
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
18003
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
18004
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
18005
 
    
18006
 
    // Map coordinates to the reference cube
18007
 
    if (std::abs(y + z - 1.0) < 1e-08)
18008
 
      x = 1.0;
18009
 
    else
18010
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
18011
 
    if (std::abs(z - 1.0) < 1e-08)
18012
 
      y = -1.0;
18013
 
    else
18014
 
      y = 2.0 * y/(1.0 - z) - 1.0;
18015
 
    z = 2.0 * z - 1.0;
18016
 
    
18017
 
    // Compute number of derivatives
18018
 
    unsigned int num_derivatives = 1;
18019
 
    
18020
 
    for (unsigned int j = 0; j < n; j++)
18021
 
      num_derivatives *= 3;
18022
 
    
18023
 
    
18024
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
18025
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
18026
 
    
18027
 
    for (unsigned int j = 0; j < num_derivatives; j++)
18028
 
    {
18029
 
      combinations[j] = new unsigned int [n];
18030
 
      for (unsigned int k = 0; k < n; k++)
18031
 
        combinations[j][k] = 0;
18032
 
    }
18033
 
    
18034
 
    // Generate combinations of derivatives
18035
 
    for (unsigned int row = 1; row < num_derivatives; row++)
18036
 
    {
18037
 
      for (unsigned int num = 0; num < row; num++)
18038
 
      {
18039
 
        for (unsigned int col = n-1; col+1 > 0; col--)
18040
 
        {
18041
 
          if (combinations[row][col] + 1 > 2)
18042
 
            combinations[row][col] = 0;
18043
 
          else
18044
 
          {
18045
 
            combinations[row][col] += 1;
18046
 
            break;
18047
 
          }
18048
 
        }
18049
 
      }
18050
 
    }
18051
 
    
18052
 
    // Compute inverse of Jacobian
18053
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
18054
 
    
18055
 
    // Declare transformation matrix
18056
 
    // Declare pointer to two dimensional array and initialise
18057
 
    double **transform = new double *[num_derivatives];
18058
 
    
18059
 
    for (unsigned int j = 0; j < num_derivatives; j++)
18060
 
    {
18061
 
      transform[j] = new double [num_derivatives];
18062
 
      for (unsigned int k = 0; k < num_derivatives; k++)
18063
 
        transform[j][k] = 1;
18064
 
    }
18065
 
    
18066
 
    // Construct transformation matrix
18067
 
    for (unsigned int row = 0; row < num_derivatives; row++)
18068
 
    {
18069
 
      for (unsigned int col = 0; col < num_derivatives; col++)
18070
 
      {
18071
 
        for (unsigned int k = 0; k < n; k++)
18072
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
18073
 
      }
18074
 
    }
18075
 
    
18076
 
    // Reset values
18077
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
18078
 
      values[j] = 0;
18079
 
    
18080
 
    // Map degree of freedom to element degree of freedom
18081
 
    const unsigned int dof = i;
18082
 
    
18083
 
    // Generate scalings
18084
 
    const double scalings_y_0 = 1;
18085
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18086
 
    const double scalings_z_0 = 1;
18087
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18088
 
    
18089
 
    // Compute psitilde_a
18090
 
    const double psitilde_a_0 = 1;
18091
 
    const double psitilde_a_1 = x;
18092
 
    
18093
 
    // Compute psitilde_bs
18094
 
    const double psitilde_bs_0_0 = 1;
18095
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
18096
 
    const double psitilde_bs_1_0 = 1;
18097
 
    
18098
 
    // Compute psitilde_cs
18099
 
    const double psitilde_cs_00_0 = 1;
18100
 
    const double psitilde_cs_00_1 = 2*z + 1;
18101
 
    const double psitilde_cs_01_0 = 1;
18102
 
    const double psitilde_cs_10_0 = 1;
18103
 
    
18104
 
    // Compute basisvalues
18105
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18106
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18107
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18108
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18109
 
    
18110
 
    // Table(s) of coefficients
18111
 
    static const double coefficients0[4][4] = \
18112
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18113
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18114
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
18115
 
    {0.288675135, 0, 0, 0.223606798}};
18116
 
    
18117
 
    // Interesting (new) part
18118
 
    // Tables of derivatives of the polynomial base (transpose)
18119
 
    static const double dmats0[4][4] = \
18120
 
    {{0, 0, 0, 0},
18121
 
    {6.32455532, 0, 0, 0},
18122
 
    {0, 0, 0, 0},
18123
 
    {0, 0, 0, 0}};
18124
 
    
18125
 
    static const double dmats1[4][4] = \
18126
 
    {{0, 0, 0, 0},
18127
 
    {3.16227766, 0, 0, 0},
18128
 
    {5.47722558, 0, 0, 0},
18129
 
    {0, 0, 0, 0}};
18130
 
    
18131
 
    static const double dmats2[4][4] = \
18132
 
    {{0, 0, 0, 0},
18133
 
    {3.16227766, 0, 0, 0},
18134
 
    {1.82574186, 0, 0, 0},
18135
 
    {5.16397779, 0, 0, 0}};
18136
 
    
18137
 
    // Compute reference derivatives
18138
 
    // Declare pointer to array of derivatives on FIAT element
18139
 
    double *derivatives = new double [num_derivatives];
18140
 
    
18141
 
    // Declare coefficients
18142
 
    double coeff0_0 = 0;
18143
 
    double coeff0_1 = 0;
18144
 
    double coeff0_2 = 0;
18145
 
    double coeff0_3 = 0;
18146
 
    
18147
 
    // Declare new coefficients
18148
 
    double new_coeff0_0 = 0;
18149
 
    double new_coeff0_1 = 0;
18150
 
    double new_coeff0_2 = 0;
18151
 
    double new_coeff0_3 = 0;
18152
 
    
18153
 
    // Loop possible derivatives
18154
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
18155
 
    {
18156
 
      // Get values from coefficients array
18157
 
      new_coeff0_0 = coefficients0[dof][0];
18158
 
      new_coeff0_1 = coefficients0[dof][1];
18159
 
      new_coeff0_2 = coefficients0[dof][2];
18160
 
      new_coeff0_3 = coefficients0[dof][3];
18161
 
    
18162
 
      // Loop derivative order
18163
 
      for (unsigned int j = 0; j < n; j++)
18164
 
      {
18165
 
        // Update old coefficients
18166
 
        coeff0_0 = new_coeff0_0;
18167
 
        coeff0_1 = new_coeff0_1;
18168
 
        coeff0_2 = new_coeff0_2;
18169
 
        coeff0_3 = new_coeff0_3;
18170
 
    
18171
 
        if(combinations[deriv_num][j] == 0)
18172
 
        {
18173
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
18174
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
18175
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
18176
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
18177
 
        }
18178
 
        if(combinations[deriv_num][j] == 1)
18179
 
        {
18180
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
18181
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
18182
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
18183
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
18184
 
        }
18185
 
        if(combinations[deriv_num][j] == 2)
18186
 
        {
18187
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
18188
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
18189
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
18190
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
18191
 
        }
18192
 
    
18193
 
      }
18194
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
18195
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
18196
 
    }
18197
 
    
18198
 
    // Transform derivatives back to physical element
18199
 
    for (unsigned int row = 0; row < num_derivatives; row++)
18200
 
    {
18201
 
      for (unsigned int col = 0; col < num_derivatives; col++)
18202
 
      {
18203
 
        values[row] += transform[row][col]*derivatives[col];
18204
 
      }
18205
 
    }
18206
 
    // Delete pointer to array of derivatives on FIAT element
18207
 
    delete [] derivatives;
18208
 
    
18209
 
    // Delete pointer to array of combinations of derivatives and transform
18210
 
    for (unsigned int row = 0; row < num_derivatives; row++)
18211
 
    {
18212
 
      delete [] combinations[row];
18213
 
      delete [] transform[row];
18214
 
    }
18215
 
    
18216
 
    delete [] combinations;
18217
 
    delete [] transform;
18218
 
  }
18219
 
 
18220
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
18221
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
18222
 
                                              double* values,
18223
 
                                              const double* coordinates,
18224
 
                                              const ufc::cell& c) const
18225
 
  {
18226
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
18227
 
  }
18228
 
 
18229
 
  /// Evaluate linear functional for dof i on the function f
18230
 
  virtual double evaluate_dof(unsigned int i,
18231
 
                              const ufc::function& f,
18232
 
                              const ufc::cell& c) const
18233
 
  {
18234
 
    // The reference points, direction and weights:
18235
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
18236
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
18237
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
18238
 
    
18239
 
    const double * const * x = c.coordinates;
18240
 
    double result = 0.0;
18241
 
    // Iterate over the points:
18242
 
    // Evaluate basis functions for affine mapping
18243
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
18244
 
    const double w1 = X[i][0][0];
18245
 
    const double w2 = X[i][0][1];
18246
 
    const double w3 = X[i][0][2];
18247
 
    
18248
 
    // Compute affine mapping y = F(X)
18249
 
    double y[3];
18250
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
18251
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
18252
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
18253
 
    
18254
 
    // Evaluate function at physical points
18255
 
    double values[1];
18256
 
    f.evaluate(values, y, c);
18257
 
    
18258
 
    // Map function values using appropriate mapping
18259
 
    // Affine map: Do nothing
18260
 
    
18261
 
    // Note that we do not map the weights (yet).
18262
 
    
18263
 
    // Take directional components
18264
 
    for(int k = 0; k < 1; k++)
18265
 
      result += values[k]*D[i][0][k];
18266
 
    // Multiply by weights
18267
 
    result *= W[i][0];
18268
 
    
18269
 
    return result;
18270
 
  }
18271
 
 
18272
 
  /// Evaluate linear functionals for all dofs on the function f
18273
 
  virtual void evaluate_dofs(double* values,
18274
 
                             const ufc::function& f,
18275
 
                             const ufc::cell& c) const
18276
 
  {
18277
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
18278
 
  }
18279
 
 
18280
 
  /// Interpolate vertex values from dof values
18281
 
  virtual void interpolate_vertex_values(double* vertex_values,
18282
 
                                         const double* dof_values,
18283
 
                                         const ufc::cell& c) const
18284
 
  {
18285
 
    // Evaluate at vertices and use affine mapping
18286
 
    vertex_values[0] = dof_values[0];
18287
 
    vertex_values[1] = dof_values[1];
18288
 
    vertex_values[2] = dof_values[2];
18289
 
    vertex_values[3] = dof_values[3];
18290
 
  }
18291
 
 
18292
 
  /// Return the number of sub elements (for a mixed element)
18293
 
  virtual unsigned int num_sub_elements() const
18294
 
  {
18295
 
    return 1;
18296
 
  }
18297
 
 
18298
 
  /// Create a new finite element for sub element i (for a mixed element)
18299
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
18300
 
  {
18301
 
    return new hyperelasticity_1_finite_element_2_2();
18302
 
  }
18303
 
 
18304
 
};
18305
 
 
18306
 
/// This class defines the interface for a finite element.
18307
 
 
18308
 
class hyperelasticity_1_finite_element_2: public ufc::finite_element
18309
 
{
18310
 
public:
18311
 
 
18312
 
  /// Constructor
18313
 
  hyperelasticity_1_finite_element_2() : ufc::finite_element()
18314
 
  {
18315
 
    // Do nothing
18316
 
  }
18317
 
 
18318
 
  /// Destructor
18319
 
  virtual ~hyperelasticity_1_finite_element_2()
18320
 
  {
18321
 
    // Do nothing
18322
 
  }
18323
 
 
18324
 
  /// Return a string identifying the finite element
18325
 
  virtual const char* signature() const
18326
 
  {
18327
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
18328
 
  }
18329
 
 
18330
 
  /// Return the cell shape
18331
 
  virtual ufc::shape cell_shape() const
18332
 
  {
18333
 
    return ufc::tetrahedron;
18334
 
  }
18335
 
 
18336
 
  /// Return the dimension of the finite element function space
18337
 
  virtual unsigned int space_dimension() const
18338
 
  {
18339
 
    return 12;
18340
 
  }
18341
 
 
18342
 
  /// Return the rank of the value space
18343
 
  virtual unsigned int value_rank() const
18344
 
  {
18345
 
    return 1;
18346
 
  }
18347
 
 
18348
 
  /// Return the dimension of the value space for axis i
18349
 
  virtual unsigned int value_dimension(unsigned int i) const
18350
 
  {
18351
 
    return 3;
18352
 
  }
18353
 
 
18354
 
  /// Evaluate basis function i at given point in cell
18355
 
  virtual void evaluate_basis(unsigned int i,
18356
 
                              double* values,
18357
 
                              const double* coordinates,
18358
 
                              const ufc::cell& c) const
18359
 
  {
18360
 
    // Extract vertex coordinates
18361
 
    const double * const * element_coordinates = c.coordinates;
18362
 
    
18363
 
    // Compute Jacobian of affine map from reference cell
18364
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
18365
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
18366
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
18367
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
18368
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
18369
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
18370
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
18371
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
18372
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
18373
 
    
18374
 
    // Compute sub determinants
18375
 
    const double d00 = J_11*J_22 - J_12*J_21;
18376
 
    const double d01 = J_12*J_20 - J_10*J_22;
18377
 
    const double d02 = J_10*J_21 - J_11*J_20;
18378
 
    
18379
 
    const double d10 = J_02*J_21 - J_01*J_22;
18380
 
    const double d11 = J_00*J_22 - J_02*J_20;
18381
 
    const double d12 = J_01*J_20 - J_00*J_21;
18382
 
    
18383
 
    const double d20 = J_01*J_12 - J_02*J_11;
18384
 
    const double d21 = J_02*J_10 - J_00*J_12;
18385
 
    const double d22 = J_00*J_11 - J_01*J_10;
18386
 
    
18387
 
    // Compute determinant of Jacobian
18388
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
18389
 
    
18390
 
    // Compute inverse of Jacobian
18391
 
    
18392
 
    // Compute constants
18393
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
18394
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
18395
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
18396
 
    
18397
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
18398
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
18399
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
18400
 
    
18401
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
18402
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
18403
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
18404
 
    
18405
 
    // Get coordinates and map to the UFC reference element
18406
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
18407
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
18408
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
18409
 
    
18410
 
    // Map coordinates to the reference cube
18411
 
    if (std::abs(y + z - 1.0) < 1e-08)
18412
 
      x = 1.0;
18413
 
    else
18414
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
18415
 
    if (std::abs(z - 1.0) < 1e-08)
18416
 
      y = -1.0;
18417
 
    else
18418
 
      y = 2.0 * y/(1.0 - z) - 1.0;
18419
 
    z = 2.0 * z - 1.0;
18420
 
    
18421
 
    // Reset values
18422
 
    values[0] = 0;
18423
 
    values[1] = 0;
18424
 
    values[2] = 0;
18425
 
    
18426
 
    if (0 <= i && i <= 3)
18427
 
    {
18428
 
      // Map degree of freedom to element degree of freedom
18429
 
      const unsigned int dof = i;
18430
 
    
18431
 
      // Generate scalings
18432
 
      const double scalings_y_0 = 1;
18433
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18434
 
      const double scalings_z_0 = 1;
18435
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18436
 
    
18437
 
      // Compute psitilde_a
18438
 
      const double psitilde_a_0 = 1;
18439
 
      const double psitilde_a_1 = x;
18440
 
    
18441
 
      // Compute psitilde_bs
18442
 
      const double psitilde_bs_0_0 = 1;
18443
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
18444
 
      const double psitilde_bs_1_0 = 1;
18445
 
    
18446
 
      // Compute psitilde_cs
18447
 
      const double psitilde_cs_00_0 = 1;
18448
 
      const double psitilde_cs_00_1 = 2*z + 1;
18449
 
      const double psitilde_cs_01_0 = 1;
18450
 
      const double psitilde_cs_10_0 = 1;
18451
 
    
18452
 
      // Compute basisvalues
18453
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18454
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18455
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18456
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18457
 
    
18458
 
      // Table(s) of coefficients
18459
 
      static const double coefficients0[4][4] =   \
18460
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18461
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18462
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
18463
 
      {0.288675135, 0, 0, 0.223606798}};
18464
 
    
18465
 
      // Extract relevant coefficients
18466
 
      const double coeff0_0 =   coefficients0[dof][0];
18467
 
      const double coeff0_1 =   coefficients0[dof][1];
18468
 
      const double coeff0_2 =   coefficients0[dof][2];
18469
 
      const double coeff0_3 =   coefficients0[dof][3];
18470
 
    
18471
 
      // Compute value(s)
18472
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
18473
 
    }
18474
 
    
18475
 
    if (4 <= i && i <= 7)
18476
 
    {
18477
 
      // Map degree of freedom to element degree of freedom
18478
 
      const unsigned int dof = i - 4;
18479
 
    
18480
 
      // Generate scalings
18481
 
      const double scalings_y_0 = 1;
18482
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18483
 
      const double scalings_z_0 = 1;
18484
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18485
 
    
18486
 
      // Compute psitilde_a
18487
 
      const double psitilde_a_0 = 1;
18488
 
      const double psitilde_a_1 = x;
18489
 
    
18490
 
      // Compute psitilde_bs
18491
 
      const double psitilde_bs_0_0 = 1;
18492
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
18493
 
      const double psitilde_bs_1_0 = 1;
18494
 
    
18495
 
      // Compute psitilde_cs
18496
 
      const double psitilde_cs_00_0 = 1;
18497
 
      const double psitilde_cs_00_1 = 2*z + 1;
18498
 
      const double psitilde_cs_01_0 = 1;
18499
 
      const double psitilde_cs_10_0 = 1;
18500
 
    
18501
 
      // Compute basisvalues
18502
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18503
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18504
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18505
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18506
 
    
18507
 
      // Table(s) of coefficients
18508
 
      static const double coefficients0[4][4] =   \
18509
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18510
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18511
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
18512
 
      {0.288675135, 0, 0, 0.223606798}};
18513
 
    
18514
 
      // Extract relevant coefficients
18515
 
      const double coeff0_0 =   coefficients0[dof][0];
18516
 
      const double coeff0_1 =   coefficients0[dof][1];
18517
 
      const double coeff0_2 =   coefficients0[dof][2];
18518
 
      const double coeff0_3 =   coefficients0[dof][3];
18519
 
    
18520
 
      // Compute value(s)
18521
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
18522
 
    }
18523
 
    
18524
 
    if (8 <= i && i <= 11)
18525
 
    {
18526
 
      // Map degree of freedom to element degree of freedom
18527
 
      const unsigned int dof = i - 8;
18528
 
    
18529
 
      // Generate scalings
18530
 
      const double scalings_y_0 = 1;
18531
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18532
 
      const double scalings_z_0 = 1;
18533
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18534
 
    
18535
 
      // Compute psitilde_a
18536
 
      const double psitilde_a_0 = 1;
18537
 
      const double psitilde_a_1 = x;
18538
 
    
18539
 
      // Compute psitilde_bs
18540
 
      const double psitilde_bs_0_0 = 1;
18541
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
18542
 
      const double psitilde_bs_1_0 = 1;
18543
 
    
18544
 
      // Compute psitilde_cs
18545
 
      const double psitilde_cs_00_0 = 1;
18546
 
      const double psitilde_cs_00_1 = 2*z + 1;
18547
 
      const double psitilde_cs_01_0 = 1;
18548
 
      const double psitilde_cs_10_0 = 1;
18549
 
    
18550
 
      // Compute basisvalues
18551
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18552
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18553
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18554
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18555
 
    
18556
 
      // Table(s) of coefficients
18557
 
      static const double coefficients0[4][4] =   \
18558
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18559
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18560
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
18561
 
      {0.288675135, 0, 0, 0.223606798}};
18562
 
    
18563
 
      // Extract relevant coefficients
18564
 
      const double coeff0_0 =   coefficients0[dof][0];
18565
 
      const double coeff0_1 =   coefficients0[dof][1];
18566
 
      const double coeff0_2 =   coefficients0[dof][2];
18567
 
      const double coeff0_3 =   coefficients0[dof][3];
18568
 
    
18569
 
      // Compute value(s)
18570
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
18571
 
    }
18572
 
    
18573
 
  }
18574
 
 
18575
 
  /// Evaluate all basis functions at given point in cell
18576
 
  virtual void evaluate_basis_all(double* values,
18577
 
                                  const double* coordinates,
18578
 
                                  const ufc::cell& c) const
18579
 
  {
18580
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
18581
 
  }
18582
 
 
18583
 
  /// Evaluate order n derivatives of basis function i at given point in cell
18584
 
  virtual void evaluate_basis_derivatives(unsigned int i,
18585
 
                                          unsigned int n,
18586
 
                                          double* values,
18587
 
                                          const double* coordinates,
18588
 
                                          const ufc::cell& c) const
18589
 
  {
18590
 
    // Extract vertex coordinates
18591
 
    const double * const * element_coordinates = c.coordinates;
18592
 
    
18593
 
    // Compute Jacobian of affine map from reference cell
18594
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
18595
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
18596
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
18597
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
18598
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
18599
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
18600
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
18601
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
18602
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
18603
 
    
18604
 
    // Compute sub determinants
18605
 
    const double d00 = J_11*J_22 - J_12*J_21;
18606
 
    const double d01 = J_12*J_20 - J_10*J_22;
18607
 
    const double d02 = J_10*J_21 - J_11*J_20;
18608
 
    
18609
 
    const double d10 = J_02*J_21 - J_01*J_22;
18610
 
    const double d11 = J_00*J_22 - J_02*J_20;
18611
 
    const double d12 = J_01*J_20 - J_00*J_21;
18612
 
    
18613
 
    const double d20 = J_01*J_12 - J_02*J_11;
18614
 
    const double d21 = J_02*J_10 - J_00*J_12;
18615
 
    const double d22 = J_00*J_11 - J_01*J_10;
18616
 
    
18617
 
    // Compute determinant of Jacobian
18618
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
18619
 
    
18620
 
    // Compute inverse of Jacobian
18621
 
    
18622
 
    // Compute constants
18623
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
18624
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
18625
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
18626
 
    
18627
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
18628
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
18629
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
18630
 
    
18631
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
18632
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
18633
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
18634
 
    
18635
 
    // Get coordinates and map to the UFC reference element
18636
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
18637
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
18638
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
18639
 
    
18640
 
    // Map coordinates to the reference cube
18641
 
    if (std::abs(y + z - 1.0) < 1e-08)
18642
 
      x = 1.0;
18643
 
    else
18644
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
18645
 
    if (std::abs(z - 1.0) < 1e-08)
18646
 
      y = -1.0;
18647
 
    else
18648
 
      y = 2.0 * y/(1.0 - z) - 1.0;
18649
 
    z = 2.0 * z - 1.0;
18650
 
    
18651
 
    // Compute number of derivatives
18652
 
    unsigned int num_derivatives = 1;
18653
 
    
18654
 
    for (unsigned int j = 0; j < n; j++)
18655
 
      num_derivatives *= 3;
18656
 
    
18657
 
    
18658
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
18659
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
18660
 
    
18661
 
    for (unsigned int j = 0; j < num_derivatives; j++)
18662
 
    {
18663
 
      combinations[j] = new unsigned int [n];
18664
 
      for (unsigned int k = 0; k < n; k++)
18665
 
        combinations[j][k] = 0;
18666
 
    }
18667
 
    
18668
 
    // Generate combinations of derivatives
18669
 
    for (unsigned int row = 1; row < num_derivatives; row++)
18670
 
    {
18671
 
      for (unsigned int num = 0; num < row; num++)
18672
 
      {
18673
 
        for (unsigned int col = n-1; col+1 > 0; col--)
18674
 
        {
18675
 
          if (combinations[row][col] + 1 > 2)
18676
 
            combinations[row][col] = 0;
18677
 
          else
18678
 
          {
18679
 
            combinations[row][col] += 1;
18680
 
            break;
18681
 
          }
18682
 
        }
18683
 
      }
18684
 
    }
18685
 
    
18686
 
    // Compute inverse of Jacobian
18687
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
18688
 
    
18689
 
    // Declare transformation matrix
18690
 
    // Declare pointer to two dimensional array and initialise
18691
 
    double **transform = new double *[num_derivatives];
18692
 
    
18693
 
    for (unsigned int j = 0; j < num_derivatives; j++)
18694
 
    {
18695
 
      transform[j] = new double [num_derivatives];
18696
 
      for (unsigned int k = 0; k < num_derivatives; k++)
18697
 
        transform[j][k] = 1;
18698
 
    }
18699
 
    
18700
 
    // Construct transformation matrix
18701
 
    for (unsigned int row = 0; row < num_derivatives; row++)
18702
 
    {
18703
 
      for (unsigned int col = 0; col < num_derivatives; col++)
18704
 
      {
18705
 
        for (unsigned int k = 0; k < n; k++)
18706
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
18707
 
      }
18708
 
    }
18709
 
    
18710
 
    // Reset values
18711
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
18712
 
      values[j] = 0;
18713
 
    
18714
 
    if (0 <= i && i <= 3)
18715
 
    {
18716
 
      // Map degree of freedom to element degree of freedom
18717
 
      const unsigned int dof = i;
18718
 
    
18719
 
      // Generate scalings
18720
 
      const double scalings_y_0 = 1;
18721
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18722
 
      const double scalings_z_0 = 1;
18723
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18724
 
    
18725
 
      // Compute psitilde_a
18726
 
      const double psitilde_a_0 = 1;
18727
 
      const double psitilde_a_1 = x;
18728
 
    
18729
 
      // Compute psitilde_bs
18730
 
      const double psitilde_bs_0_0 = 1;
18731
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
18732
 
      const double psitilde_bs_1_0 = 1;
18733
 
    
18734
 
      // Compute psitilde_cs
18735
 
      const double psitilde_cs_00_0 = 1;
18736
 
      const double psitilde_cs_00_1 = 2*z + 1;
18737
 
      const double psitilde_cs_01_0 = 1;
18738
 
      const double psitilde_cs_10_0 = 1;
18739
 
    
18740
 
      // Compute basisvalues
18741
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18742
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18743
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18744
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18745
 
    
18746
 
      // Table(s) of coefficients
18747
 
      static const double coefficients0[4][4] =   \
18748
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18749
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18750
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
18751
 
      {0.288675135, 0, 0, 0.223606798}};
18752
 
    
18753
 
      // Interesting (new) part
18754
 
      // Tables of derivatives of the polynomial base (transpose)
18755
 
      static const double dmats0[4][4] =   \
18756
 
      {{0, 0, 0, 0},
18757
 
      {6.32455532, 0, 0, 0},
18758
 
      {0, 0, 0, 0},
18759
 
      {0, 0, 0, 0}};
18760
 
    
18761
 
      static const double dmats1[4][4] =   \
18762
 
      {{0, 0, 0, 0},
18763
 
      {3.16227766, 0, 0, 0},
18764
 
      {5.47722558, 0, 0, 0},
18765
 
      {0, 0, 0, 0}};
18766
 
    
18767
 
      static const double dmats2[4][4] =   \
18768
 
      {{0, 0, 0, 0},
18769
 
      {3.16227766, 0, 0, 0},
18770
 
      {1.82574186, 0, 0, 0},
18771
 
      {5.16397779, 0, 0, 0}};
18772
 
    
18773
 
      // Compute reference derivatives
18774
 
      // Declare pointer to array of derivatives on FIAT element
18775
 
      double *derivatives = new double [num_derivatives];
18776
 
    
18777
 
      // Declare coefficients
18778
 
      double coeff0_0 = 0;
18779
 
      double coeff0_1 = 0;
18780
 
      double coeff0_2 = 0;
18781
 
      double coeff0_3 = 0;
18782
 
    
18783
 
      // Declare new coefficients
18784
 
      double new_coeff0_0 = 0;
18785
 
      double new_coeff0_1 = 0;
18786
 
      double new_coeff0_2 = 0;
18787
 
      double new_coeff0_3 = 0;
18788
 
    
18789
 
      // Loop possible derivatives
18790
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
18791
 
      {
18792
 
        // Get values from coefficients array
18793
 
        new_coeff0_0 = coefficients0[dof][0];
18794
 
        new_coeff0_1 = coefficients0[dof][1];
18795
 
        new_coeff0_2 = coefficients0[dof][2];
18796
 
        new_coeff0_3 = coefficients0[dof][3];
18797
 
    
18798
 
        // Loop derivative order
18799
 
        for (unsigned int j = 0; j < n; j++)
18800
 
        {
18801
 
          // Update old coefficients
18802
 
          coeff0_0 = new_coeff0_0;
18803
 
          coeff0_1 = new_coeff0_1;
18804
 
          coeff0_2 = new_coeff0_2;
18805
 
          coeff0_3 = new_coeff0_3;
18806
 
    
18807
 
          if(combinations[deriv_num][j] == 0)
18808
 
          {
18809
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
18810
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
18811
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
18812
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
18813
 
          }
18814
 
          if(combinations[deriv_num][j] == 1)
18815
 
          {
18816
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
18817
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
18818
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
18819
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
18820
 
          }
18821
 
          if(combinations[deriv_num][j] == 2)
18822
 
          {
18823
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
18824
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
18825
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
18826
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
18827
 
          }
18828
 
    
18829
 
        }
18830
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
18831
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
18832
 
      }
18833
 
    
18834
 
      // Transform derivatives back to physical element
18835
 
      for (unsigned int row = 0; row < num_derivatives; row++)
18836
 
      {
18837
 
        for (unsigned int col = 0; col < num_derivatives; col++)
18838
 
        {
18839
 
          values[row] += transform[row][col]*derivatives[col];
18840
 
        }
18841
 
      }
18842
 
      // Delete pointer to array of derivatives on FIAT element
18843
 
      delete [] derivatives;
18844
 
    
18845
 
      // Delete pointer to array of combinations of derivatives and transform
18846
 
      for (unsigned int row = 0; row < num_derivatives; row++)
18847
 
      {
18848
 
        delete [] combinations[row];
18849
 
        delete [] transform[row];
18850
 
      }
18851
 
    
18852
 
      delete [] combinations;
18853
 
      delete [] transform;
18854
 
    }
18855
 
    
18856
 
    if (4 <= i && i <= 7)
18857
 
    {
18858
 
      // Map degree of freedom to element degree of freedom
18859
 
      const unsigned int dof = i - 4;
18860
 
    
18861
 
      // Generate scalings
18862
 
      const double scalings_y_0 = 1;
18863
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
18864
 
      const double scalings_z_0 = 1;
18865
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
18866
 
    
18867
 
      // Compute psitilde_a
18868
 
      const double psitilde_a_0 = 1;
18869
 
      const double psitilde_a_1 = x;
18870
 
    
18871
 
      // Compute psitilde_bs
18872
 
      const double psitilde_bs_0_0 = 1;
18873
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
18874
 
      const double psitilde_bs_1_0 = 1;
18875
 
    
18876
 
      // Compute psitilde_cs
18877
 
      const double psitilde_cs_00_0 = 1;
18878
 
      const double psitilde_cs_00_1 = 2*z + 1;
18879
 
      const double psitilde_cs_01_0 = 1;
18880
 
      const double psitilde_cs_10_0 = 1;
18881
 
    
18882
 
      // Compute basisvalues
18883
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
18884
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
18885
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
18886
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
18887
 
    
18888
 
      // Table(s) of coefficients
18889
 
      static const double coefficients0[4][4] =   \
18890
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
18891
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
18892
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
18893
 
      {0.288675135, 0, 0, 0.223606798}};
18894
 
    
18895
 
      // Interesting (new) part
18896
 
      // Tables of derivatives of the polynomial base (transpose)
18897
 
      static const double dmats0[4][4] =   \
18898
 
      {{0, 0, 0, 0},
18899
 
      {6.32455532, 0, 0, 0},
18900
 
      {0, 0, 0, 0},
18901
 
      {0, 0, 0, 0}};
18902
 
    
18903
 
      static const double dmats1[4][4] =   \
18904
 
      {{0, 0, 0, 0},
18905
 
      {3.16227766, 0, 0, 0},
18906
 
      {5.47722558, 0, 0, 0},
18907
 
      {0, 0, 0, 0}};
18908
 
    
18909
 
      static const double dmats2[4][4] =   \
18910
 
      {{0, 0, 0, 0},
18911
 
      {3.16227766, 0, 0, 0},
18912
 
      {1.82574186, 0, 0, 0},
18913
 
      {5.16397779, 0, 0, 0}};
18914
 
    
18915
 
      // Compute reference derivatives
18916
 
      // Declare pointer to array of derivatives on FIAT element
18917
 
      double *derivatives = new double [num_derivatives];
18918
 
    
18919
 
      // Declare coefficients
18920
 
      double coeff0_0 = 0;
18921
 
      double coeff0_1 = 0;
18922
 
      double coeff0_2 = 0;
18923
 
      double coeff0_3 = 0;
18924
 
    
18925
 
      // Declare new coefficients
18926
 
      double new_coeff0_0 = 0;
18927
 
      double new_coeff0_1 = 0;
18928
 
      double new_coeff0_2 = 0;
18929
 
      double new_coeff0_3 = 0;
18930
 
    
18931
 
      // Loop possible derivatives
18932
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
18933
 
      {
18934
 
        // Get values from coefficients array
18935
 
        new_coeff0_0 = coefficients0[dof][0];
18936
 
        new_coeff0_1 = coefficients0[dof][1];
18937
 
        new_coeff0_2 = coefficients0[dof][2];
18938
 
        new_coeff0_3 = coefficients0[dof][3];
18939
 
    
18940
 
        // Loop derivative order
18941
 
        for (unsigned int j = 0; j < n; j++)
18942
 
        {
18943
 
          // Update old coefficients
18944
 
          coeff0_0 = new_coeff0_0;
18945
 
          coeff0_1 = new_coeff0_1;
18946
 
          coeff0_2 = new_coeff0_2;
18947
 
          coeff0_3 = new_coeff0_3;
18948
 
    
18949
 
          if(combinations[deriv_num][j] == 0)
18950
 
          {
18951
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
18952
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
18953
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
18954
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
18955
 
          }
18956
 
          if(combinations[deriv_num][j] == 1)
18957
 
          {
18958
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
18959
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
18960
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
18961
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
18962
 
          }
18963
 
          if(combinations[deriv_num][j] == 2)
18964
 
          {
18965
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
18966
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
18967
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
18968
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
18969
 
          }
18970
 
    
18971
 
        }
18972
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
18973
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
18974
 
      }
18975
 
    
18976
 
      // Transform derivatives back to physical element
18977
 
      for (unsigned int row = 0; row < num_derivatives; row++)
18978
 
      {
18979
 
        for (unsigned int col = 0; col < num_derivatives; col++)
18980
 
        {
18981
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
18982
 
        }
18983
 
      }
18984
 
      // Delete pointer to array of derivatives on FIAT element
18985
 
      delete [] derivatives;
18986
 
    
18987
 
      // Delete pointer to array of combinations of derivatives and transform
18988
 
      for (unsigned int row = 0; row < num_derivatives; row++)
18989
 
      {
18990
 
        delete [] combinations[row];
18991
 
        delete [] transform[row];
18992
 
      }
18993
 
    
18994
 
      delete [] combinations;
18995
 
      delete [] transform;
18996
 
    }
18997
 
    
18998
 
    if (8 <= i && i <= 11)
18999
 
    {
19000
 
      // Map degree of freedom to element degree of freedom
19001
 
      const unsigned int dof = i - 8;
19002
 
    
19003
 
      // Generate scalings
19004
 
      const double scalings_y_0 = 1;
19005
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
19006
 
      const double scalings_z_0 = 1;
19007
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
19008
 
    
19009
 
      // Compute psitilde_a
19010
 
      const double psitilde_a_0 = 1;
19011
 
      const double psitilde_a_1 = x;
19012
 
    
19013
 
      // Compute psitilde_bs
19014
 
      const double psitilde_bs_0_0 = 1;
19015
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
19016
 
      const double psitilde_bs_1_0 = 1;
19017
 
    
19018
 
      // Compute psitilde_cs
19019
 
      const double psitilde_cs_00_0 = 1;
19020
 
      const double psitilde_cs_00_1 = 2*z + 1;
19021
 
      const double psitilde_cs_01_0 = 1;
19022
 
      const double psitilde_cs_10_0 = 1;
19023
 
    
19024
 
      // Compute basisvalues
19025
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
19026
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
19027
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
19028
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
19029
 
    
19030
 
      // Table(s) of coefficients
19031
 
      static const double coefficients0[4][4] =   \
19032
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
19033
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
19034
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
19035
 
      {0.288675135, 0, 0, 0.223606798}};
19036
 
    
19037
 
      // Interesting (new) part
19038
 
      // Tables of derivatives of the polynomial base (transpose)
19039
 
      static const double dmats0[4][4] =   \
19040
 
      {{0, 0, 0, 0},
19041
 
      {6.32455532, 0, 0, 0},
19042
 
      {0, 0, 0, 0},
19043
 
      {0, 0, 0, 0}};
19044
 
    
19045
 
      static const double dmats1[4][4] =   \
19046
 
      {{0, 0, 0, 0},
19047
 
      {3.16227766, 0, 0, 0},
19048
 
      {5.47722558, 0, 0, 0},
19049
 
      {0, 0, 0, 0}};
19050
 
    
19051
 
      static const double dmats2[4][4] =   \
19052
 
      {{0, 0, 0, 0},
19053
 
      {3.16227766, 0, 0, 0},
19054
 
      {1.82574186, 0, 0, 0},
19055
 
      {5.16397779, 0, 0, 0}};
19056
 
    
19057
 
      // Compute reference derivatives
19058
 
      // Declare pointer to array of derivatives on FIAT element
19059
 
      double *derivatives = new double [num_derivatives];
19060
 
    
19061
 
      // Declare coefficients
19062
 
      double coeff0_0 = 0;
19063
 
      double coeff0_1 = 0;
19064
 
      double coeff0_2 = 0;
19065
 
      double coeff0_3 = 0;
19066
 
    
19067
 
      // Declare new coefficients
19068
 
      double new_coeff0_0 = 0;
19069
 
      double new_coeff0_1 = 0;
19070
 
      double new_coeff0_2 = 0;
19071
 
      double new_coeff0_3 = 0;
19072
 
    
19073
 
      // Loop possible derivatives
19074
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
19075
 
      {
19076
 
        // Get values from coefficients array
19077
 
        new_coeff0_0 = coefficients0[dof][0];
19078
 
        new_coeff0_1 = coefficients0[dof][1];
19079
 
        new_coeff0_2 = coefficients0[dof][2];
19080
 
        new_coeff0_3 = coefficients0[dof][3];
19081
 
    
19082
 
        // Loop derivative order
19083
 
        for (unsigned int j = 0; j < n; j++)
19084
 
        {
19085
 
          // Update old coefficients
19086
 
          coeff0_0 = new_coeff0_0;
19087
 
          coeff0_1 = new_coeff0_1;
19088
 
          coeff0_2 = new_coeff0_2;
19089
 
          coeff0_3 = new_coeff0_3;
19090
 
    
19091
 
          if(combinations[deriv_num][j] == 0)
19092
 
          {
19093
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
19094
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
19095
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
19096
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
19097
 
          }
19098
 
          if(combinations[deriv_num][j] == 1)
19099
 
          {
19100
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
19101
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
19102
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
19103
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
19104
 
          }
19105
 
          if(combinations[deriv_num][j] == 2)
19106
 
          {
19107
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
19108
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
19109
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
19110
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
19111
 
          }
19112
 
    
19113
 
        }
19114
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
19115
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
19116
 
      }
19117
 
    
19118
 
      // Transform derivatives back to physical element
19119
 
      for (unsigned int row = 0; row < num_derivatives; row++)
19120
 
      {
19121
 
        for (unsigned int col = 0; col < num_derivatives; col++)
19122
 
        {
19123
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
19124
 
        }
19125
 
      }
19126
 
      // Delete pointer to array of derivatives on FIAT element
19127
 
      delete [] derivatives;
19128
 
    
19129
 
      // Delete pointer to array of combinations of derivatives and transform
19130
 
      for (unsigned int row = 0; row < num_derivatives; row++)
19131
 
      {
19132
 
        delete [] combinations[row];
19133
 
        delete [] transform[row];
19134
 
      }
19135
 
    
19136
 
      delete [] combinations;
19137
 
      delete [] transform;
19138
 
    }
19139
 
    
19140
 
  }
19141
 
 
19142
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
19143
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
19144
 
                                              double* values,
19145
 
                                              const double* coordinates,
19146
 
                                              const ufc::cell& c) const
19147
 
  {
19148
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
19149
 
  }
19150
 
 
19151
 
  /// Evaluate linear functional for dof i on the function f
19152
 
  virtual double evaluate_dof(unsigned int i,
19153
 
                              const ufc::function& f,
19154
 
                              const ufc::cell& c) const
19155
 
  {
19156
 
    // The reference points, direction and weights:
19157
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
19158
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
19159
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
19160
 
    
19161
 
    const double * const * x = c.coordinates;
19162
 
    double result = 0.0;
19163
 
    // Iterate over the points:
19164
 
    // Evaluate basis functions for affine mapping
19165
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
19166
 
    const double w1 = X[i][0][0];
19167
 
    const double w2 = X[i][0][1];
19168
 
    const double w3 = X[i][0][2];
19169
 
    
19170
 
    // Compute affine mapping y = F(X)
19171
 
    double y[3];
19172
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
19173
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
19174
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
19175
 
    
19176
 
    // Evaluate function at physical points
19177
 
    double values[3];
19178
 
    f.evaluate(values, y, c);
19179
 
    
19180
 
    // Map function values using appropriate mapping
19181
 
    // Affine map: Do nothing
19182
 
    
19183
 
    // Note that we do not map the weights (yet).
19184
 
    
19185
 
    // Take directional components
19186
 
    for(int k = 0; k < 3; k++)
19187
 
      result += values[k]*D[i][0][k];
19188
 
    // Multiply by weights
19189
 
    result *= W[i][0];
19190
 
    
19191
 
    return result;
19192
 
  }
19193
 
 
19194
 
  /// Evaluate linear functionals for all dofs on the function f
19195
 
  virtual void evaluate_dofs(double* values,
19196
 
                             const ufc::function& f,
19197
 
                             const ufc::cell& c) const
19198
 
  {
19199
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
19200
 
  }
19201
 
 
19202
 
  /// Interpolate vertex values from dof values
19203
 
  virtual void interpolate_vertex_values(double* vertex_values,
19204
 
                                         const double* dof_values,
19205
 
                                         const ufc::cell& c) const
19206
 
  {
19207
 
    // Evaluate at vertices and use affine mapping
19208
 
    vertex_values[0] = dof_values[0];
19209
 
    vertex_values[3] = dof_values[1];
19210
 
    vertex_values[6] = dof_values[2];
19211
 
    vertex_values[9] = dof_values[3];
19212
 
    // Evaluate at vertices and use affine mapping
19213
 
    vertex_values[1] = dof_values[4];
19214
 
    vertex_values[4] = dof_values[5];
19215
 
    vertex_values[7] = dof_values[6];
19216
 
    vertex_values[10] = dof_values[7];
19217
 
    // Evaluate at vertices and use affine mapping
19218
 
    vertex_values[2] = dof_values[8];
19219
 
    vertex_values[5] = dof_values[9];
19220
 
    vertex_values[8] = dof_values[10];
19221
 
    vertex_values[11] = dof_values[11];
19222
 
  }
19223
 
 
19224
 
  /// Return the number of sub elements (for a mixed element)
19225
 
  virtual unsigned int num_sub_elements() const
19226
 
  {
19227
 
    return 3;
19228
 
  }
19229
 
 
19230
 
  /// Create a new finite element for sub element i (for a mixed element)
19231
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
19232
 
  {
19233
 
    switch ( i )
19234
 
    {
19235
 
    case 0:
19236
 
      return new hyperelasticity_1_finite_element_2_0();
19237
 
      break;
19238
 
    case 1:
19239
 
      return new hyperelasticity_1_finite_element_2_1();
19240
 
      break;
19241
 
    case 2:
19242
 
      return new hyperelasticity_1_finite_element_2_2();
19243
 
      break;
19244
 
    }
19245
 
    return 0;
19246
 
  }
19247
 
 
19248
 
};
19249
 
 
19250
 
/// This class defines the interface for a finite element.
19251
 
 
19252
 
class hyperelasticity_1_finite_element_3_0: public ufc::finite_element
19253
 
{
19254
 
public:
19255
 
 
19256
 
  /// Constructor
19257
 
  hyperelasticity_1_finite_element_3_0() : ufc::finite_element()
19258
 
  {
19259
 
    // Do nothing
19260
 
  }
19261
 
 
19262
 
  /// Destructor
19263
 
  virtual ~hyperelasticity_1_finite_element_3_0()
19264
 
  {
19265
 
    // Do nothing
19266
 
  }
19267
 
 
19268
 
  /// Return a string identifying the finite element
19269
 
  virtual const char* signature() const
19270
 
  {
19271
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
19272
 
  }
19273
 
 
19274
 
  /// Return the cell shape
19275
 
  virtual ufc::shape cell_shape() const
19276
 
  {
19277
 
    return ufc::tetrahedron;
19278
 
  }
19279
 
 
19280
 
  /// Return the dimension of the finite element function space
19281
 
  virtual unsigned int space_dimension() const
19282
 
  {
19283
 
    return 4;
19284
 
  }
19285
 
 
19286
 
  /// Return the rank of the value space
19287
 
  virtual unsigned int value_rank() const
19288
 
  {
19289
 
    return 0;
19290
 
  }
19291
 
 
19292
 
  /// Return the dimension of the value space for axis i
19293
 
  virtual unsigned int value_dimension(unsigned int i) const
19294
 
  {
19295
 
    return 1;
19296
 
  }
19297
 
 
19298
 
  /// Evaluate basis function i at given point in cell
19299
 
  virtual void evaluate_basis(unsigned int i,
19300
 
                              double* values,
19301
 
                              const double* coordinates,
19302
 
                              const ufc::cell& c) const
19303
 
  {
19304
 
    // Extract vertex coordinates
19305
 
    const double * const * element_coordinates = c.coordinates;
19306
 
    
19307
 
    // Compute Jacobian of affine map from reference cell
19308
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
19309
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
19310
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
19311
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
19312
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
19313
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
19314
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
19315
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
19316
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
19317
 
    
19318
 
    // Compute sub determinants
19319
 
    const double d00 = J_11*J_22 - J_12*J_21;
19320
 
    const double d01 = J_12*J_20 - J_10*J_22;
19321
 
    const double d02 = J_10*J_21 - J_11*J_20;
19322
 
    
19323
 
    const double d10 = J_02*J_21 - J_01*J_22;
19324
 
    const double d11 = J_00*J_22 - J_02*J_20;
19325
 
    const double d12 = J_01*J_20 - J_00*J_21;
19326
 
    
19327
 
    const double d20 = J_01*J_12 - J_02*J_11;
19328
 
    const double d21 = J_02*J_10 - J_00*J_12;
19329
 
    const double d22 = J_00*J_11 - J_01*J_10;
19330
 
    
19331
 
    // Compute determinant of Jacobian
19332
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
19333
 
    
19334
 
    // Compute inverse of Jacobian
19335
 
    
19336
 
    // Compute constants
19337
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
19338
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
19339
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
19340
 
    
19341
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
19342
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
19343
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
19344
 
    
19345
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
19346
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
19347
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
19348
 
    
19349
 
    // Get coordinates and map to the UFC reference element
19350
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
19351
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
19352
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
19353
 
    
19354
 
    // Map coordinates to the reference cube
19355
 
    if (std::abs(y + z - 1.0) < 1e-08)
19356
 
      x = 1.0;
19357
 
    else
19358
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
19359
 
    if (std::abs(z - 1.0) < 1e-08)
19360
 
      y = -1.0;
19361
 
    else
19362
 
      y = 2.0 * y/(1.0 - z) - 1.0;
19363
 
    z = 2.0 * z - 1.0;
19364
 
    
19365
 
    // Reset values
19366
 
    *values = 0;
19367
 
    
19368
 
    // Map degree of freedom to element degree of freedom
19369
 
    const unsigned int dof = i;
19370
 
    
19371
 
    // Generate scalings
19372
 
    const double scalings_y_0 = 1;
19373
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
19374
 
    const double scalings_z_0 = 1;
19375
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
19376
 
    
19377
 
    // Compute psitilde_a
19378
 
    const double psitilde_a_0 = 1;
19379
 
    const double psitilde_a_1 = x;
19380
 
    
19381
 
    // Compute psitilde_bs
19382
 
    const double psitilde_bs_0_0 = 1;
19383
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
19384
 
    const double psitilde_bs_1_0 = 1;
19385
 
    
19386
 
    // Compute psitilde_cs
19387
 
    const double psitilde_cs_00_0 = 1;
19388
 
    const double psitilde_cs_00_1 = 2*z + 1;
19389
 
    const double psitilde_cs_01_0 = 1;
19390
 
    const double psitilde_cs_10_0 = 1;
19391
 
    
19392
 
    // Compute basisvalues
19393
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
19394
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
19395
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
19396
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
19397
 
    
19398
 
    // Table(s) of coefficients
19399
 
    static const double coefficients0[4][4] = \
19400
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
19401
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
19402
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
19403
 
    {0.288675135, 0, 0, 0.223606798}};
19404
 
    
19405
 
    // Extract relevant coefficients
19406
 
    const double coeff0_0 = coefficients0[dof][0];
19407
 
    const double coeff0_1 = coefficients0[dof][1];
19408
 
    const double coeff0_2 = coefficients0[dof][2];
19409
 
    const double coeff0_3 = coefficients0[dof][3];
19410
 
    
19411
 
    // Compute value(s)
19412
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
19413
 
  }
19414
 
 
19415
 
  /// Evaluate all basis functions at given point in cell
19416
 
  virtual void evaluate_basis_all(double* values,
19417
 
                                  const double* coordinates,
19418
 
                                  const ufc::cell& c) const
19419
 
  {
19420
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
19421
 
  }
19422
 
 
19423
 
  /// Evaluate order n derivatives of basis function i at given point in cell
19424
 
  virtual void evaluate_basis_derivatives(unsigned int i,
19425
 
                                          unsigned int n,
19426
 
                                          double* values,
19427
 
                                          const double* coordinates,
19428
 
                                          const ufc::cell& c) const
19429
 
  {
19430
 
    // Extract vertex coordinates
19431
 
    const double * const * element_coordinates = c.coordinates;
19432
 
    
19433
 
    // Compute Jacobian of affine map from reference cell
19434
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
19435
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
19436
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
19437
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
19438
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
19439
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
19440
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
19441
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
19442
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
19443
 
    
19444
 
    // Compute sub determinants
19445
 
    const double d00 = J_11*J_22 - J_12*J_21;
19446
 
    const double d01 = J_12*J_20 - J_10*J_22;
19447
 
    const double d02 = J_10*J_21 - J_11*J_20;
19448
 
    
19449
 
    const double d10 = J_02*J_21 - J_01*J_22;
19450
 
    const double d11 = J_00*J_22 - J_02*J_20;
19451
 
    const double d12 = J_01*J_20 - J_00*J_21;
19452
 
    
19453
 
    const double d20 = J_01*J_12 - J_02*J_11;
19454
 
    const double d21 = J_02*J_10 - J_00*J_12;
19455
 
    const double d22 = J_00*J_11 - J_01*J_10;
19456
 
    
19457
 
    // Compute determinant of Jacobian
19458
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
19459
 
    
19460
 
    // Compute inverse of Jacobian
19461
 
    
19462
 
    // Compute constants
19463
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
19464
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
19465
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
19466
 
    
19467
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
19468
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
19469
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
19470
 
    
19471
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
19472
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
19473
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
19474
 
    
19475
 
    // Get coordinates and map to the UFC reference element
19476
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
19477
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
19478
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
19479
 
    
19480
 
    // Map coordinates to the reference cube
19481
 
    if (std::abs(y + z - 1.0) < 1e-08)
19482
 
      x = 1.0;
19483
 
    else
19484
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
19485
 
    if (std::abs(z - 1.0) < 1e-08)
19486
 
      y = -1.0;
19487
 
    else
19488
 
      y = 2.0 * y/(1.0 - z) - 1.0;
19489
 
    z = 2.0 * z - 1.0;
19490
 
    
19491
 
    // Compute number of derivatives
19492
 
    unsigned int num_derivatives = 1;
19493
 
    
19494
 
    for (unsigned int j = 0; j < n; j++)
19495
 
      num_derivatives *= 3;
19496
 
    
19497
 
    
19498
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
19499
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
19500
 
    
19501
 
    for (unsigned int j = 0; j < num_derivatives; j++)
19502
 
    {
19503
 
      combinations[j] = new unsigned int [n];
19504
 
      for (unsigned int k = 0; k < n; k++)
19505
 
        combinations[j][k] = 0;
19506
 
    }
19507
 
    
19508
 
    // Generate combinations of derivatives
19509
 
    for (unsigned int row = 1; row < num_derivatives; row++)
19510
 
    {
19511
 
      for (unsigned int num = 0; num < row; num++)
19512
 
      {
19513
 
        for (unsigned int col = n-1; col+1 > 0; col--)
19514
 
        {
19515
 
          if (combinations[row][col] + 1 > 2)
19516
 
            combinations[row][col] = 0;
19517
 
          else
19518
 
          {
19519
 
            combinations[row][col] += 1;
19520
 
            break;
19521
 
          }
19522
 
        }
19523
 
      }
19524
 
    }
19525
 
    
19526
 
    // Compute inverse of Jacobian
19527
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
19528
 
    
19529
 
    // Declare transformation matrix
19530
 
    // Declare pointer to two dimensional array and initialise
19531
 
    double **transform = new double *[num_derivatives];
19532
 
    
19533
 
    for (unsigned int j = 0; j < num_derivatives; j++)
19534
 
    {
19535
 
      transform[j] = new double [num_derivatives];
19536
 
      for (unsigned int k = 0; k < num_derivatives; k++)
19537
 
        transform[j][k] = 1;
19538
 
    }
19539
 
    
19540
 
    // Construct transformation matrix
19541
 
    for (unsigned int row = 0; row < num_derivatives; row++)
19542
 
    {
19543
 
      for (unsigned int col = 0; col < num_derivatives; col++)
19544
 
      {
19545
 
        for (unsigned int k = 0; k < n; k++)
19546
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
19547
 
      }
19548
 
    }
19549
 
    
19550
 
    // Reset values
19551
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
19552
 
      values[j] = 0;
19553
 
    
19554
 
    // Map degree of freedom to element degree of freedom
19555
 
    const unsigned int dof = i;
19556
 
    
19557
 
    // Generate scalings
19558
 
    const double scalings_y_0 = 1;
19559
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
19560
 
    const double scalings_z_0 = 1;
19561
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
19562
 
    
19563
 
    // Compute psitilde_a
19564
 
    const double psitilde_a_0 = 1;
19565
 
    const double psitilde_a_1 = x;
19566
 
    
19567
 
    // Compute psitilde_bs
19568
 
    const double psitilde_bs_0_0 = 1;
19569
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
19570
 
    const double psitilde_bs_1_0 = 1;
19571
 
    
19572
 
    // Compute psitilde_cs
19573
 
    const double psitilde_cs_00_0 = 1;
19574
 
    const double psitilde_cs_00_1 = 2*z + 1;
19575
 
    const double psitilde_cs_01_0 = 1;
19576
 
    const double psitilde_cs_10_0 = 1;
19577
 
    
19578
 
    // Compute basisvalues
19579
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
19580
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
19581
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
19582
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
19583
 
    
19584
 
    // Table(s) of coefficients
19585
 
    static const double coefficients0[4][4] = \
19586
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
19587
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
19588
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
19589
 
    {0.288675135, 0, 0, 0.223606798}};
19590
 
    
19591
 
    // Interesting (new) part
19592
 
    // Tables of derivatives of the polynomial base (transpose)
19593
 
    static const double dmats0[4][4] = \
19594
 
    {{0, 0, 0, 0},
19595
 
    {6.32455532, 0, 0, 0},
19596
 
    {0, 0, 0, 0},
19597
 
    {0, 0, 0, 0}};
19598
 
    
19599
 
    static const double dmats1[4][4] = \
19600
 
    {{0, 0, 0, 0},
19601
 
    {3.16227766, 0, 0, 0},
19602
 
    {5.47722558, 0, 0, 0},
19603
 
    {0, 0, 0, 0}};
19604
 
    
19605
 
    static const double dmats2[4][4] = \
19606
 
    {{0, 0, 0, 0},
19607
 
    {3.16227766, 0, 0, 0},
19608
 
    {1.82574186, 0, 0, 0},
19609
 
    {5.16397779, 0, 0, 0}};
19610
 
    
19611
 
    // Compute reference derivatives
19612
 
    // Declare pointer to array of derivatives on FIAT element
19613
 
    double *derivatives = new double [num_derivatives];
19614
 
    
19615
 
    // Declare coefficients
19616
 
    double coeff0_0 = 0;
19617
 
    double coeff0_1 = 0;
19618
 
    double coeff0_2 = 0;
19619
 
    double coeff0_3 = 0;
19620
 
    
19621
 
    // Declare new coefficients
19622
 
    double new_coeff0_0 = 0;
19623
 
    double new_coeff0_1 = 0;
19624
 
    double new_coeff0_2 = 0;
19625
 
    double new_coeff0_3 = 0;
19626
 
    
19627
 
    // Loop possible derivatives
19628
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
19629
 
    {
19630
 
      // Get values from coefficients array
19631
 
      new_coeff0_0 = coefficients0[dof][0];
19632
 
      new_coeff0_1 = coefficients0[dof][1];
19633
 
      new_coeff0_2 = coefficients0[dof][2];
19634
 
      new_coeff0_3 = coefficients0[dof][3];
19635
 
    
19636
 
      // Loop derivative order
19637
 
      for (unsigned int j = 0; j < n; j++)
19638
 
      {
19639
 
        // Update old coefficients
19640
 
        coeff0_0 = new_coeff0_0;
19641
 
        coeff0_1 = new_coeff0_1;
19642
 
        coeff0_2 = new_coeff0_2;
19643
 
        coeff0_3 = new_coeff0_3;
19644
 
    
19645
 
        if(combinations[deriv_num][j] == 0)
19646
 
        {
19647
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
19648
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
19649
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
19650
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
19651
 
        }
19652
 
        if(combinations[deriv_num][j] == 1)
19653
 
        {
19654
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
19655
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
19656
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
19657
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
19658
 
        }
19659
 
        if(combinations[deriv_num][j] == 2)
19660
 
        {
19661
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
19662
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
19663
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
19664
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
19665
 
        }
19666
 
    
19667
 
      }
19668
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
19669
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
19670
 
    }
19671
 
    
19672
 
    // Transform derivatives back to physical element
19673
 
    for (unsigned int row = 0; row < num_derivatives; row++)
19674
 
    {
19675
 
      for (unsigned int col = 0; col < num_derivatives; col++)
19676
 
      {
19677
 
        values[row] += transform[row][col]*derivatives[col];
19678
 
      }
19679
 
    }
19680
 
    // Delete pointer to array of derivatives on FIAT element
19681
 
    delete [] derivatives;
19682
 
    
19683
 
    // Delete pointer to array of combinations of derivatives and transform
19684
 
    for (unsigned int row = 0; row < num_derivatives; row++)
19685
 
    {
19686
 
      delete [] combinations[row];
19687
 
      delete [] transform[row];
19688
 
    }
19689
 
    
19690
 
    delete [] combinations;
19691
 
    delete [] transform;
19692
 
  }
19693
 
 
19694
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
19695
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
19696
 
                                              double* values,
19697
 
                                              const double* coordinates,
19698
 
                                              const ufc::cell& c) const
19699
 
  {
19700
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
19701
 
  }
19702
 
 
19703
 
  /// Evaluate linear functional for dof i on the function f
19704
 
  virtual double evaluate_dof(unsigned int i,
19705
 
                              const ufc::function& f,
19706
 
                              const ufc::cell& c) const
19707
 
  {
19708
 
    // The reference points, direction and weights:
19709
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
19710
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
19711
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
19712
 
    
19713
 
    const double * const * x = c.coordinates;
19714
 
    double result = 0.0;
19715
 
    // Iterate over the points:
19716
 
    // Evaluate basis functions for affine mapping
19717
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
19718
 
    const double w1 = X[i][0][0];
19719
 
    const double w2 = X[i][0][1];
19720
 
    const double w3 = X[i][0][2];
19721
 
    
19722
 
    // Compute affine mapping y = F(X)
19723
 
    double y[3];
19724
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
19725
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
19726
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
19727
 
    
19728
 
    // Evaluate function at physical points
19729
 
    double values[1];
19730
 
    f.evaluate(values, y, c);
19731
 
    
19732
 
    // Map function values using appropriate mapping
19733
 
    // Affine map: Do nothing
19734
 
    
19735
 
    // Note that we do not map the weights (yet).
19736
 
    
19737
 
    // Take directional components
19738
 
    for(int k = 0; k < 1; k++)
19739
 
      result += values[k]*D[i][0][k];
19740
 
    // Multiply by weights
19741
 
    result *= W[i][0];
19742
 
    
19743
 
    return result;
19744
 
  }
19745
 
 
19746
 
  /// Evaluate linear functionals for all dofs on the function f
19747
 
  virtual void evaluate_dofs(double* values,
19748
 
                             const ufc::function& f,
19749
 
                             const ufc::cell& c) const
19750
 
  {
19751
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
19752
 
  }
19753
 
 
19754
 
  /// Interpolate vertex values from dof values
19755
 
  virtual void interpolate_vertex_values(double* vertex_values,
19756
 
                                         const double* dof_values,
19757
 
                                         const ufc::cell& c) const
19758
 
  {
19759
 
    // Evaluate at vertices and use affine mapping
19760
 
    vertex_values[0] = dof_values[0];
19761
 
    vertex_values[1] = dof_values[1];
19762
 
    vertex_values[2] = dof_values[2];
19763
 
    vertex_values[3] = dof_values[3];
19764
 
  }
19765
 
 
19766
 
  /// Return the number of sub elements (for a mixed element)
19767
 
  virtual unsigned int num_sub_elements() const
19768
 
  {
19769
 
    return 1;
19770
 
  }
19771
 
 
19772
 
  /// Create a new finite element for sub element i (for a mixed element)
19773
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
19774
 
  {
19775
 
    return new hyperelasticity_1_finite_element_3_0();
19776
 
  }
19777
 
 
19778
 
};
19779
 
 
19780
 
/// This class defines the interface for a finite element.
19781
 
 
19782
 
class hyperelasticity_1_finite_element_3_1: public ufc::finite_element
19783
 
{
19784
 
public:
19785
 
 
19786
 
  /// Constructor
19787
 
  hyperelasticity_1_finite_element_3_1() : ufc::finite_element()
19788
 
  {
19789
 
    // Do nothing
19790
 
  }
19791
 
 
19792
 
  /// Destructor
19793
 
  virtual ~hyperelasticity_1_finite_element_3_1()
19794
 
  {
19795
 
    // Do nothing
19796
 
  }
19797
 
 
19798
 
  /// Return a string identifying the finite element
19799
 
  virtual const char* signature() const
19800
 
  {
19801
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
19802
 
  }
19803
 
 
19804
 
  /// Return the cell shape
19805
 
  virtual ufc::shape cell_shape() const
19806
 
  {
19807
 
    return ufc::tetrahedron;
19808
 
  }
19809
 
 
19810
 
  /// Return the dimension of the finite element function space
19811
 
  virtual unsigned int space_dimension() const
19812
 
  {
19813
 
    return 4;
19814
 
  }
19815
 
 
19816
 
  /// Return the rank of the value space
19817
 
  virtual unsigned int value_rank() const
19818
 
  {
19819
 
    return 0;
19820
 
  }
19821
 
 
19822
 
  /// Return the dimension of the value space for axis i
19823
 
  virtual unsigned int value_dimension(unsigned int i) const
19824
 
  {
19825
 
    return 1;
19826
 
  }
19827
 
 
19828
 
  /// Evaluate basis function i at given point in cell
19829
 
  virtual void evaluate_basis(unsigned int i,
19830
 
                              double* values,
19831
 
                              const double* coordinates,
19832
 
                              const ufc::cell& c) const
19833
 
  {
19834
 
    // Extract vertex coordinates
19835
 
    const double * const * element_coordinates = c.coordinates;
19836
 
    
19837
 
    // Compute Jacobian of affine map from reference cell
19838
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
19839
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
19840
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
19841
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
19842
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
19843
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
19844
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
19845
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
19846
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
19847
 
    
19848
 
    // Compute sub determinants
19849
 
    const double d00 = J_11*J_22 - J_12*J_21;
19850
 
    const double d01 = J_12*J_20 - J_10*J_22;
19851
 
    const double d02 = J_10*J_21 - J_11*J_20;
19852
 
    
19853
 
    const double d10 = J_02*J_21 - J_01*J_22;
19854
 
    const double d11 = J_00*J_22 - J_02*J_20;
19855
 
    const double d12 = J_01*J_20 - J_00*J_21;
19856
 
    
19857
 
    const double d20 = J_01*J_12 - J_02*J_11;
19858
 
    const double d21 = J_02*J_10 - J_00*J_12;
19859
 
    const double d22 = J_00*J_11 - J_01*J_10;
19860
 
    
19861
 
    // Compute determinant of Jacobian
19862
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
19863
 
    
19864
 
    // Compute inverse of Jacobian
19865
 
    
19866
 
    // Compute constants
19867
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
19868
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
19869
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
19870
 
    
19871
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
19872
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
19873
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
19874
 
    
19875
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
19876
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
19877
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
19878
 
    
19879
 
    // Get coordinates and map to the UFC reference element
19880
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
19881
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
19882
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
19883
 
    
19884
 
    // Map coordinates to the reference cube
19885
 
    if (std::abs(y + z - 1.0) < 1e-08)
19886
 
      x = 1.0;
19887
 
    else
19888
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
19889
 
    if (std::abs(z - 1.0) < 1e-08)
19890
 
      y = -1.0;
19891
 
    else
19892
 
      y = 2.0 * y/(1.0 - z) - 1.0;
19893
 
    z = 2.0 * z - 1.0;
19894
 
    
19895
 
    // Reset values
19896
 
    *values = 0;
19897
 
    
19898
 
    // Map degree of freedom to element degree of freedom
19899
 
    const unsigned int dof = i;
19900
 
    
19901
 
    // Generate scalings
19902
 
    const double scalings_y_0 = 1;
19903
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
19904
 
    const double scalings_z_0 = 1;
19905
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
19906
 
    
19907
 
    // Compute psitilde_a
19908
 
    const double psitilde_a_0 = 1;
19909
 
    const double psitilde_a_1 = x;
19910
 
    
19911
 
    // Compute psitilde_bs
19912
 
    const double psitilde_bs_0_0 = 1;
19913
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
19914
 
    const double psitilde_bs_1_0 = 1;
19915
 
    
19916
 
    // Compute psitilde_cs
19917
 
    const double psitilde_cs_00_0 = 1;
19918
 
    const double psitilde_cs_00_1 = 2*z + 1;
19919
 
    const double psitilde_cs_01_0 = 1;
19920
 
    const double psitilde_cs_10_0 = 1;
19921
 
    
19922
 
    // Compute basisvalues
19923
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
19924
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
19925
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
19926
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
19927
 
    
19928
 
    // Table(s) of coefficients
19929
 
    static const double coefficients0[4][4] = \
19930
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
19931
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
19932
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
19933
 
    {0.288675135, 0, 0, 0.223606798}};
19934
 
    
19935
 
    // Extract relevant coefficients
19936
 
    const double coeff0_0 = coefficients0[dof][0];
19937
 
    const double coeff0_1 = coefficients0[dof][1];
19938
 
    const double coeff0_2 = coefficients0[dof][2];
19939
 
    const double coeff0_3 = coefficients0[dof][3];
19940
 
    
19941
 
    // Compute value(s)
19942
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
19943
 
  }
19944
 
 
19945
 
  /// Evaluate all basis functions at given point in cell
19946
 
  virtual void evaluate_basis_all(double* values,
19947
 
                                  const double* coordinates,
19948
 
                                  const ufc::cell& c) const
19949
 
  {
19950
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
19951
 
  }
19952
 
 
19953
 
  /// Evaluate order n derivatives of basis function i at given point in cell
19954
 
  virtual void evaluate_basis_derivatives(unsigned int i,
19955
 
                                          unsigned int n,
19956
 
                                          double* values,
19957
 
                                          const double* coordinates,
19958
 
                                          const ufc::cell& c) const
19959
 
  {
19960
 
    // Extract vertex coordinates
19961
 
    const double * const * element_coordinates = c.coordinates;
19962
 
    
19963
 
    // Compute Jacobian of affine map from reference cell
19964
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
19965
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
19966
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
19967
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
19968
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
19969
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
19970
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
19971
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
19972
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
19973
 
    
19974
 
    // Compute sub determinants
19975
 
    const double d00 = J_11*J_22 - J_12*J_21;
19976
 
    const double d01 = J_12*J_20 - J_10*J_22;
19977
 
    const double d02 = J_10*J_21 - J_11*J_20;
19978
 
    
19979
 
    const double d10 = J_02*J_21 - J_01*J_22;
19980
 
    const double d11 = J_00*J_22 - J_02*J_20;
19981
 
    const double d12 = J_01*J_20 - J_00*J_21;
19982
 
    
19983
 
    const double d20 = J_01*J_12 - J_02*J_11;
19984
 
    const double d21 = J_02*J_10 - J_00*J_12;
19985
 
    const double d22 = J_00*J_11 - J_01*J_10;
19986
 
    
19987
 
    // Compute determinant of Jacobian
19988
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
19989
 
    
19990
 
    // Compute inverse of Jacobian
19991
 
    
19992
 
    // Compute constants
19993
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
19994
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
19995
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
19996
 
    
19997
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
19998
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
19999
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
20000
 
    
20001
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
20002
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
20003
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
20004
 
    
20005
 
    // Get coordinates and map to the UFC reference element
20006
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
20007
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
20008
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
20009
 
    
20010
 
    // Map coordinates to the reference cube
20011
 
    if (std::abs(y + z - 1.0) < 1e-08)
20012
 
      x = 1.0;
20013
 
    else
20014
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
20015
 
    if (std::abs(z - 1.0) < 1e-08)
20016
 
      y = -1.0;
20017
 
    else
20018
 
      y = 2.0 * y/(1.0 - z) - 1.0;
20019
 
    z = 2.0 * z - 1.0;
20020
 
    
20021
 
    // Compute number of derivatives
20022
 
    unsigned int num_derivatives = 1;
20023
 
    
20024
 
    for (unsigned int j = 0; j < n; j++)
20025
 
      num_derivatives *= 3;
20026
 
    
20027
 
    
20028
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
20029
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
20030
 
    
20031
 
    for (unsigned int j = 0; j < num_derivatives; j++)
20032
 
    {
20033
 
      combinations[j] = new unsigned int [n];
20034
 
      for (unsigned int k = 0; k < n; k++)
20035
 
        combinations[j][k] = 0;
20036
 
    }
20037
 
    
20038
 
    // Generate combinations of derivatives
20039
 
    for (unsigned int row = 1; row < num_derivatives; row++)
20040
 
    {
20041
 
      for (unsigned int num = 0; num < row; num++)
20042
 
      {
20043
 
        for (unsigned int col = n-1; col+1 > 0; col--)
20044
 
        {
20045
 
          if (combinations[row][col] + 1 > 2)
20046
 
            combinations[row][col] = 0;
20047
 
          else
20048
 
          {
20049
 
            combinations[row][col] += 1;
20050
 
            break;
20051
 
          }
20052
 
        }
20053
 
      }
20054
 
    }
20055
 
    
20056
 
    // Compute inverse of Jacobian
20057
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
20058
 
    
20059
 
    // Declare transformation matrix
20060
 
    // Declare pointer to two dimensional array and initialise
20061
 
    double **transform = new double *[num_derivatives];
20062
 
    
20063
 
    for (unsigned int j = 0; j < num_derivatives; j++)
20064
 
    {
20065
 
      transform[j] = new double [num_derivatives];
20066
 
      for (unsigned int k = 0; k < num_derivatives; k++)
20067
 
        transform[j][k] = 1;
20068
 
    }
20069
 
    
20070
 
    // Construct transformation matrix
20071
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20072
 
    {
20073
 
      for (unsigned int col = 0; col < num_derivatives; col++)
20074
 
      {
20075
 
        for (unsigned int k = 0; k < n; k++)
20076
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
20077
 
      }
20078
 
    }
20079
 
    
20080
 
    // Reset values
20081
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
20082
 
      values[j] = 0;
20083
 
    
20084
 
    // Map degree of freedom to element degree of freedom
20085
 
    const unsigned int dof = i;
20086
 
    
20087
 
    // Generate scalings
20088
 
    const double scalings_y_0 = 1;
20089
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
20090
 
    const double scalings_z_0 = 1;
20091
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
20092
 
    
20093
 
    // Compute psitilde_a
20094
 
    const double psitilde_a_0 = 1;
20095
 
    const double psitilde_a_1 = x;
20096
 
    
20097
 
    // Compute psitilde_bs
20098
 
    const double psitilde_bs_0_0 = 1;
20099
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
20100
 
    const double psitilde_bs_1_0 = 1;
20101
 
    
20102
 
    // Compute psitilde_cs
20103
 
    const double psitilde_cs_00_0 = 1;
20104
 
    const double psitilde_cs_00_1 = 2*z + 1;
20105
 
    const double psitilde_cs_01_0 = 1;
20106
 
    const double psitilde_cs_10_0 = 1;
20107
 
    
20108
 
    // Compute basisvalues
20109
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
20110
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
20111
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
20112
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
20113
 
    
20114
 
    // Table(s) of coefficients
20115
 
    static const double coefficients0[4][4] = \
20116
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
20117
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
20118
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
20119
 
    {0.288675135, 0, 0, 0.223606798}};
20120
 
    
20121
 
    // Interesting (new) part
20122
 
    // Tables of derivatives of the polynomial base (transpose)
20123
 
    static const double dmats0[4][4] = \
20124
 
    {{0, 0, 0, 0},
20125
 
    {6.32455532, 0, 0, 0},
20126
 
    {0, 0, 0, 0},
20127
 
    {0, 0, 0, 0}};
20128
 
    
20129
 
    static const double dmats1[4][4] = \
20130
 
    {{0, 0, 0, 0},
20131
 
    {3.16227766, 0, 0, 0},
20132
 
    {5.47722558, 0, 0, 0},
20133
 
    {0, 0, 0, 0}};
20134
 
    
20135
 
    static const double dmats2[4][4] = \
20136
 
    {{0, 0, 0, 0},
20137
 
    {3.16227766, 0, 0, 0},
20138
 
    {1.82574186, 0, 0, 0},
20139
 
    {5.16397779, 0, 0, 0}};
20140
 
    
20141
 
    // Compute reference derivatives
20142
 
    // Declare pointer to array of derivatives on FIAT element
20143
 
    double *derivatives = new double [num_derivatives];
20144
 
    
20145
 
    // Declare coefficients
20146
 
    double coeff0_0 = 0;
20147
 
    double coeff0_1 = 0;
20148
 
    double coeff0_2 = 0;
20149
 
    double coeff0_3 = 0;
20150
 
    
20151
 
    // Declare new coefficients
20152
 
    double new_coeff0_0 = 0;
20153
 
    double new_coeff0_1 = 0;
20154
 
    double new_coeff0_2 = 0;
20155
 
    double new_coeff0_3 = 0;
20156
 
    
20157
 
    // Loop possible derivatives
20158
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
20159
 
    {
20160
 
      // Get values from coefficients array
20161
 
      new_coeff0_0 = coefficients0[dof][0];
20162
 
      new_coeff0_1 = coefficients0[dof][1];
20163
 
      new_coeff0_2 = coefficients0[dof][2];
20164
 
      new_coeff0_3 = coefficients0[dof][3];
20165
 
    
20166
 
      // Loop derivative order
20167
 
      for (unsigned int j = 0; j < n; j++)
20168
 
      {
20169
 
        // Update old coefficients
20170
 
        coeff0_0 = new_coeff0_0;
20171
 
        coeff0_1 = new_coeff0_1;
20172
 
        coeff0_2 = new_coeff0_2;
20173
 
        coeff0_3 = new_coeff0_3;
20174
 
    
20175
 
        if(combinations[deriv_num][j] == 0)
20176
 
        {
20177
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
20178
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
20179
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
20180
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
20181
 
        }
20182
 
        if(combinations[deriv_num][j] == 1)
20183
 
        {
20184
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
20185
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
20186
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
20187
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
20188
 
        }
20189
 
        if(combinations[deriv_num][j] == 2)
20190
 
        {
20191
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
20192
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
20193
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
20194
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
20195
 
        }
20196
 
    
20197
 
      }
20198
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
20199
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
20200
 
    }
20201
 
    
20202
 
    // Transform derivatives back to physical element
20203
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20204
 
    {
20205
 
      for (unsigned int col = 0; col < num_derivatives; col++)
20206
 
      {
20207
 
        values[row] += transform[row][col]*derivatives[col];
20208
 
      }
20209
 
    }
20210
 
    // Delete pointer to array of derivatives on FIAT element
20211
 
    delete [] derivatives;
20212
 
    
20213
 
    // Delete pointer to array of combinations of derivatives and transform
20214
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20215
 
    {
20216
 
      delete [] combinations[row];
20217
 
      delete [] transform[row];
20218
 
    }
20219
 
    
20220
 
    delete [] combinations;
20221
 
    delete [] transform;
20222
 
  }
20223
 
 
20224
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
20225
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
20226
 
                                              double* values,
20227
 
                                              const double* coordinates,
20228
 
                                              const ufc::cell& c) const
20229
 
  {
20230
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
20231
 
  }
20232
 
 
20233
 
  /// Evaluate linear functional for dof i on the function f
20234
 
  virtual double evaluate_dof(unsigned int i,
20235
 
                              const ufc::function& f,
20236
 
                              const ufc::cell& c) const
20237
 
  {
20238
 
    // The reference points, direction and weights:
20239
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
20240
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
20241
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
20242
 
    
20243
 
    const double * const * x = c.coordinates;
20244
 
    double result = 0.0;
20245
 
    // Iterate over the points:
20246
 
    // Evaluate basis functions for affine mapping
20247
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
20248
 
    const double w1 = X[i][0][0];
20249
 
    const double w2 = X[i][0][1];
20250
 
    const double w3 = X[i][0][2];
20251
 
    
20252
 
    // Compute affine mapping y = F(X)
20253
 
    double y[3];
20254
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
20255
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
20256
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
20257
 
    
20258
 
    // Evaluate function at physical points
20259
 
    double values[1];
20260
 
    f.evaluate(values, y, c);
20261
 
    
20262
 
    // Map function values using appropriate mapping
20263
 
    // Affine map: Do nothing
20264
 
    
20265
 
    // Note that we do not map the weights (yet).
20266
 
    
20267
 
    // Take directional components
20268
 
    for(int k = 0; k < 1; k++)
20269
 
      result += values[k]*D[i][0][k];
20270
 
    // Multiply by weights
20271
 
    result *= W[i][0];
20272
 
    
20273
 
    return result;
20274
 
  }
20275
 
 
20276
 
  /// Evaluate linear functionals for all dofs on the function f
20277
 
  virtual void evaluate_dofs(double* values,
20278
 
                             const ufc::function& f,
20279
 
                             const ufc::cell& c) const
20280
 
  {
20281
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
20282
 
  }
20283
 
 
20284
 
  /// Interpolate vertex values from dof values
20285
 
  virtual void interpolate_vertex_values(double* vertex_values,
20286
 
                                         const double* dof_values,
20287
 
                                         const ufc::cell& c) const
20288
 
  {
20289
 
    // Evaluate at vertices and use affine mapping
20290
 
    vertex_values[0] = dof_values[0];
20291
 
    vertex_values[1] = dof_values[1];
20292
 
    vertex_values[2] = dof_values[2];
20293
 
    vertex_values[3] = dof_values[3];
20294
 
  }
20295
 
 
20296
 
  /// Return the number of sub elements (for a mixed element)
20297
 
  virtual unsigned int num_sub_elements() const
20298
 
  {
20299
 
    return 1;
20300
 
  }
20301
 
 
20302
 
  /// Create a new finite element for sub element i (for a mixed element)
20303
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
20304
 
  {
20305
 
    return new hyperelasticity_1_finite_element_3_1();
20306
 
  }
20307
 
 
20308
 
};
20309
 
 
20310
 
/// This class defines the interface for a finite element.
20311
 
 
20312
 
class hyperelasticity_1_finite_element_3_2: public ufc::finite_element
20313
 
{
20314
 
public:
20315
 
 
20316
 
  /// Constructor
20317
 
  hyperelasticity_1_finite_element_3_2() : ufc::finite_element()
20318
 
  {
20319
 
    // Do nothing
20320
 
  }
20321
 
 
20322
 
  /// Destructor
20323
 
  virtual ~hyperelasticity_1_finite_element_3_2()
20324
 
  {
20325
 
    // Do nothing
20326
 
  }
20327
 
 
20328
 
  /// Return a string identifying the finite element
20329
 
  virtual const char* signature() const
20330
 
  {
20331
 
    return "FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
20332
 
  }
20333
 
 
20334
 
  /// Return the cell shape
20335
 
  virtual ufc::shape cell_shape() const
20336
 
  {
20337
 
    return ufc::tetrahedron;
20338
 
  }
20339
 
 
20340
 
  /// Return the dimension of the finite element function space
20341
 
  virtual unsigned int space_dimension() const
20342
 
  {
20343
 
    return 4;
20344
 
  }
20345
 
 
20346
 
  /// Return the rank of the value space
20347
 
  virtual unsigned int value_rank() const
20348
 
  {
20349
 
    return 0;
20350
 
  }
20351
 
 
20352
 
  /// Return the dimension of the value space for axis i
20353
 
  virtual unsigned int value_dimension(unsigned int i) const
20354
 
  {
20355
 
    return 1;
20356
 
  }
20357
 
 
20358
 
  /// Evaluate basis function i at given point in cell
20359
 
  virtual void evaluate_basis(unsigned int i,
20360
 
                              double* values,
20361
 
                              const double* coordinates,
20362
 
                              const ufc::cell& c) const
20363
 
  {
20364
 
    // Extract vertex coordinates
20365
 
    const double * const * element_coordinates = c.coordinates;
20366
 
    
20367
 
    // Compute Jacobian of affine map from reference cell
20368
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
20369
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
20370
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
20371
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
20372
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
20373
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
20374
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
20375
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
20376
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
20377
 
    
20378
 
    // Compute sub determinants
20379
 
    const double d00 = J_11*J_22 - J_12*J_21;
20380
 
    const double d01 = J_12*J_20 - J_10*J_22;
20381
 
    const double d02 = J_10*J_21 - J_11*J_20;
20382
 
    
20383
 
    const double d10 = J_02*J_21 - J_01*J_22;
20384
 
    const double d11 = J_00*J_22 - J_02*J_20;
20385
 
    const double d12 = J_01*J_20 - J_00*J_21;
20386
 
    
20387
 
    const double d20 = J_01*J_12 - J_02*J_11;
20388
 
    const double d21 = J_02*J_10 - J_00*J_12;
20389
 
    const double d22 = J_00*J_11 - J_01*J_10;
20390
 
    
20391
 
    // Compute determinant of Jacobian
20392
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
20393
 
    
20394
 
    // Compute inverse of Jacobian
20395
 
    
20396
 
    // Compute constants
20397
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
20398
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
20399
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
20400
 
    
20401
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
20402
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
20403
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
20404
 
    
20405
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
20406
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
20407
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
20408
 
    
20409
 
    // Get coordinates and map to the UFC reference element
20410
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
20411
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
20412
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
20413
 
    
20414
 
    // Map coordinates to the reference cube
20415
 
    if (std::abs(y + z - 1.0) < 1e-08)
20416
 
      x = 1.0;
20417
 
    else
20418
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
20419
 
    if (std::abs(z - 1.0) < 1e-08)
20420
 
      y = -1.0;
20421
 
    else
20422
 
      y = 2.0 * y/(1.0 - z) - 1.0;
20423
 
    z = 2.0 * z - 1.0;
20424
 
    
20425
 
    // Reset values
20426
 
    *values = 0;
20427
 
    
20428
 
    // Map degree of freedom to element degree of freedom
20429
 
    const unsigned int dof = i;
20430
 
    
20431
 
    // Generate scalings
20432
 
    const double scalings_y_0 = 1;
20433
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
20434
 
    const double scalings_z_0 = 1;
20435
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
20436
 
    
20437
 
    // Compute psitilde_a
20438
 
    const double psitilde_a_0 = 1;
20439
 
    const double psitilde_a_1 = x;
20440
 
    
20441
 
    // Compute psitilde_bs
20442
 
    const double psitilde_bs_0_0 = 1;
20443
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
20444
 
    const double psitilde_bs_1_0 = 1;
20445
 
    
20446
 
    // Compute psitilde_cs
20447
 
    const double psitilde_cs_00_0 = 1;
20448
 
    const double psitilde_cs_00_1 = 2*z + 1;
20449
 
    const double psitilde_cs_01_0 = 1;
20450
 
    const double psitilde_cs_10_0 = 1;
20451
 
    
20452
 
    // Compute basisvalues
20453
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
20454
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
20455
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
20456
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
20457
 
    
20458
 
    // Table(s) of coefficients
20459
 
    static const double coefficients0[4][4] = \
20460
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
20461
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
20462
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
20463
 
    {0.288675135, 0, 0, 0.223606798}};
20464
 
    
20465
 
    // Extract relevant coefficients
20466
 
    const double coeff0_0 = coefficients0[dof][0];
20467
 
    const double coeff0_1 = coefficients0[dof][1];
20468
 
    const double coeff0_2 = coefficients0[dof][2];
20469
 
    const double coeff0_3 = coefficients0[dof][3];
20470
 
    
20471
 
    // Compute value(s)
20472
 
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
20473
 
  }
20474
 
 
20475
 
  /// Evaluate all basis functions at given point in cell
20476
 
  virtual void evaluate_basis_all(double* values,
20477
 
                                  const double* coordinates,
20478
 
                                  const ufc::cell& c) const
20479
 
  {
20480
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
20481
 
  }
20482
 
 
20483
 
  /// Evaluate order n derivatives of basis function i at given point in cell
20484
 
  virtual void evaluate_basis_derivatives(unsigned int i,
20485
 
                                          unsigned int n,
20486
 
                                          double* values,
20487
 
                                          const double* coordinates,
20488
 
                                          const ufc::cell& c) const
20489
 
  {
20490
 
    // Extract vertex coordinates
20491
 
    const double * const * element_coordinates = c.coordinates;
20492
 
    
20493
 
    // Compute Jacobian of affine map from reference cell
20494
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
20495
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
20496
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
20497
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
20498
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
20499
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
20500
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
20501
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
20502
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
20503
 
    
20504
 
    // Compute sub determinants
20505
 
    const double d00 = J_11*J_22 - J_12*J_21;
20506
 
    const double d01 = J_12*J_20 - J_10*J_22;
20507
 
    const double d02 = J_10*J_21 - J_11*J_20;
20508
 
    
20509
 
    const double d10 = J_02*J_21 - J_01*J_22;
20510
 
    const double d11 = J_00*J_22 - J_02*J_20;
20511
 
    const double d12 = J_01*J_20 - J_00*J_21;
20512
 
    
20513
 
    const double d20 = J_01*J_12 - J_02*J_11;
20514
 
    const double d21 = J_02*J_10 - J_00*J_12;
20515
 
    const double d22 = J_00*J_11 - J_01*J_10;
20516
 
    
20517
 
    // Compute determinant of Jacobian
20518
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
20519
 
    
20520
 
    // Compute inverse of Jacobian
20521
 
    
20522
 
    // Compute constants
20523
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
20524
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
20525
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
20526
 
    
20527
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
20528
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
20529
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
20530
 
    
20531
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
20532
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
20533
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
20534
 
    
20535
 
    // Get coordinates and map to the UFC reference element
20536
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
20537
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
20538
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
20539
 
    
20540
 
    // Map coordinates to the reference cube
20541
 
    if (std::abs(y + z - 1.0) < 1e-08)
20542
 
      x = 1.0;
20543
 
    else
20544
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
20545
 
    if (std::abs(z - 1.0) < 1e-08)
20546
 
      y = -1.0;
20547
 
    else
20548
 
      y = 2.0 * y/(1.0 - z) - 1.0;
20549
 
    z = 2.0 * z - 1.0;
20550
 
    
20551
 
    // Compute number of derivatives
20552
 
    unsigned int num_derivatives = 1;
20553
 
    
20554
 
    for (unsigned int j = 0; j < n; j++)
20555
 
      num_derivatives *= 3;
20556
 
    
20557
 
    
20558
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
20559
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
20560
 
    
20561
 
    for (unsigned int j = 0; j < num_derivatives; j++)
20562
 
    {
20563
 
      combinations[j] = new unsigned int [n];
20564
 
      for (unsigned int k = 0; k < n; k++)
20565
 
        combinations[j][k] = 0;
20566
 
    }
20567
 
    
20568
 
    // Generate combinations of derivatives
20569
 
    for (unsigned int row = 1; row < num_derivatives; row++)
20570
 
    {
20571
 
      for (unsigned int num = 0; num < row; num++)
20572
 
      {
20573
 
        for (unsigned int col = n-1; col+1 > 0; col--)
20574
 
        {
20575
 
          if (combinations[row][col] + 1 > 2)
20576
 
            combinations[row][col] = 0;
20577
 
          else
20578
 
          {
20579
 
            combinations[row][col] += 1;
20580
 
            break;
20581
 
          }
20582
 
        }
20583
 
      }
20584
 
    }
20585
 
    
20586
 
    // Compute inverse of Jacobian
20587
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
20588
 
    
20589
 
    // Declare transformation matrix
20590
 
    // Declare pointer to two dimensional array and initialise
20591
 
    double **transform = new double *[num_derivatives];
20592
 
    
20593
 
    for (unsigned int j = 0; j < num_derivatives; j++)
20594
 
    {
20595
 
      transform[j] = new double [num_derivatives];
20596
 
      for (unsigned int k = 0; k < num_derivatives; k++)
20597
 
        transform[j][k] = 1;
20598
 
    }
20599
 
    
20600
 
    // Construct transformation matrix
20601
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20602
 
    {
20603
 
      for (unsigned int col = 0; col < num_derivatives; col++)
20604
 
      {
20605
 
        for (unsigned int k = 0; k < n; k++)
20606
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
20607
 
      }
20608
 
    }
20609
 
    
20610
 
    // Reset values
20611
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
20612
 
      values[j] = 0;
20613
 
    
20614
 
    // Map degree of freedom to element degree of freedom
20615
 
    const unsigned int dof = i;
20616
 
    
20617
 
    // Generate scalings
20618
 
    const double scalings_y_0 = 1;
20619
 
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
20620
 
    const double scalings_z_0 = 1;
20621
 
    const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
20622
 
    
20623
 
    // Compute psitilde_a
20624
 
    const double psitilde_a_0 = 1;
20625
 
    const double psitilde_a_1 = x;
20626
 
    
20627
 
    // Compute psitilde_bs
20628
 
    const double psitilde_bs_0_0 = 1;
20629
 
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
20630
 
    const double psitilde_bs_1_0 = 1;
20631
 
    
20632
 
    // Compute psitilde_cs
20633
 
    const double psitilde_cs_00_0 = 1;
20634
 
    const double psitilde_cs_00_1 = 2*z + 1;
20635
 
    const double psitilde_cs_01_0 = 1;
20636
 
    const double psitilde_cs_10_0 = 1;
20637
 
    
20638
 
    // Compute basisvalues
20639
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
20640
 
    const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
20641
 
    const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
20642
 
    const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
20643
 
    
20644
 
    // Table(s) of coefficients
20645
 
    static const double coefficients0[4][4] = \
20646
 
    {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
20647
 
    {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
20648
 
    {0.288675135, 0, 0.210818511, -0.0745355992},
20649
 
    {0.288675135, 0, 0, 0.223606798}};
20650
 
    
20651
 
    // Interesting (new) part
20652
 
    // Tables of derivatives of the polynomial base (transpose)
20653
 
    static const double dmats0[4][4] = \
20654
 
    {{0, 0, 0, 0},
20655
 
    {6.32455532, 0, 0, 0},
20656
 
    {0, 0, 0, 0},
20657
 
    {0, 0, 0, 0}};
20658
 
    
20659
 
    static const double dmats1[4][4] = \
20660
 
    {{0, 0, 0, 0},
20661
 
    {3.16227766, 0, 0, 0},
20662
 
    {5.47722558, 0, 0, 0},
20663
 
    {0, 0, 0, 0}};
20664
 
    
20665
 
    static const double dmats2[4][4] = \
20666
 
    {{0, 0, 0, 0},
20667
 
    {3.16227766, 0, 0, 0},
20668
 
    {1.82574186, 0, 0, 0},
20669
 
    {5.16397779, 0, 0, 0}};
20670
 
    
20671
 
    // Compute reference derivatives
20672
 
    // Declare pointer to array of derivatives on FIAT element
20673
 
    double *derivatives = new double [num_derivatives];
20674
 
    
20675
 
    // Declare coefficients
20676
 
    double coeff0_0 = 0;
20677
 
    double coeff0_1 = 0;
20678
 
    double coeff0_2 = 0;
20679
 
    double coeff0_3 = 0;
20680
 
    
20681
 
    // Declare new coefficients
20682
 
    double new_coeff0_0 = 0;
20683
 
    double new_coeff0_1 = 0;
20684
 
    double new_coeff0_2 = 0;
20685
 
    double new_coeff0_3 = 0;
20686
 
    
20687
 
    // Loop possible derivatives
20688
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
20689
 
    {
20690
 
      // Get values from coefficients array
20691
 
      new_coeff0_0 = coefficients0[dof][0];
20692
 
      new_coeff0_1 = coefficients0[dof][1];
20693
 
      new_coeff0_2 = coefficients0[dof][2];
20694
 
      new_coeff0_3 = coefficients0[dof][3];
20695
 
    
20696
 
      // Loop derivative order
20697
 
      for (unsigned int j = 0; j < n; j++)
20698
 
      {
20699
 
        // Update old coefficients
20700
 
        coeff0_0 = new_coeff0_0;
20701
 
        coeff0_1 = new_coeff0_1;
20702
 
        coeff0_2 = new_coeff0_2;
20703
 
        coeff0_3 = new_coeff0_3;
20704
 
    
20705
 
        if(combinations[deriv_num][j] == 0)
20706
 
        {
20707
 
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
20708
 
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
20709
 
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
20710
 
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
20711
 
        }
20712
 
        if(combinations[deriv_num][j] == 1)
20713
 
        {
20714
 
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
20715
 
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
20716
 
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
20717
 
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
20718
 
        }
20719
 
        if(combinations[deriv_num][j] == 2)
20720
 
        {
20721
 
          new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
20722
 
          new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
20723
 
          new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
20724
 
          new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
20725
 
        }
20726
 
    
20727
 
      }
20728
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
20729
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
20730
 
    }
20731
 
    
20732
 
    // Transform derivatives back to physical element
20733
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20734
 
    {
20735
 
      for (unsigned int col = 0; col < num_derivatives; col++)
20736
 
      {
20737
 
        values[row] += transform[row][col]*derivatives[col];
20738
 
      }
20739
 
    }
20740
 
    // Delete pointer to array of derivatives on FIAT element
20741
 
    delete [] derivatives;
20742
 
    
20743
 
    // Delete pointer to array of combinations of derivatives and transform
20744
 
    for (unsigned int row = 0; row < num_derivatives; row++)
20745
 
    {
20746
 
      delete [] combinations[row];
20747
 
      delete [] transform[row];
20748
 
    }
20749
 
    
20750
 
    delete [] combinations;
20751
 
    delete [] transform;
20752
 
  }
20753
 
 
20754
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
20755
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
20756
 
                                              double* values,
20757
 
                                              const double* coordinates,
20758
 
                                              const ufc::cell& c) const
20759
 
  {
20760
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
20761
 
  }
20762
 
 
20763
 
  /// Evaluate linear functional for dof i on the function f
20764
 
  virtual double evaluate_dof(unsigned int i,
20765
 
                              const ufc::function& f,
20766
 
                              const ufc::cell& c) const
20767
 
  {
20768
 
    // The reference points, direction and weights:
20769
 
    static const double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
20770
 
    static const double W[4][1] = {{1}, {1}, {1}, {1}};
20771
 
    static const double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
20772
 
    
20773
 
    const double * const * x = c.coordinates;
20774
 
    double result = 0.0;
20775
 
    // Iterate over the points:
20776
 
    // Evaluate basis functions for affine mapping
20777
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
20778
 
    const double w1 = X[i][0][0];
20779
 
    const double w2 = X[i][0][1];
20780
 
    const double w3 = X[i][0][2];
20781
 
    
20782
 
    // Compute affine mapping y = F(X)
20783
 
    double y[3];
20784
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
20785
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
20786
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
20787
 
    
20788
 
    // Evaluate function at physical points
20789
 
    double values[1];
20790
 
    f.evaluate(values, y, c);
20791
 
    
20792
 
    // Map function values using appropriate mapping
20793
 
    // Affine map: Do nothing
20794
 
    
20795
 
    // Note that we do not map the weights (yet).
20796
 
    
20797
 
    // Take directional components
20798
 
    for(int k = 0; k < 1; k++)
20799
 
      result += values[k]*D[i][0][k];
20800
 
    // Multiply by weights
20801
 
    result *= W[i][0];
20802
 
    
20803
 
    return result;
20804
 
  }
20805
 
 
20806
 
  /// Evaluate linear functionals for all dofs on the function f
20807
 
  virtual void evaluate_dofs(double* values,
20808
 
                             const ufc::function& f,
20809
 
                             const ufc::cell& c) const
20810
 
  {
20811
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
20812
 
  }
20813
 
 
20814
 
  /// Interpolate vertex values from dof values
20815
 
  virtual void interpolate_vertex_values(double* vertex_values,
20816
 
                                         const double* dof_values,
20817
 
                                         const ufc::cell& c) const
20818
 
  {
20819
 
    // Evaluate at vertices and use affine mapping
20820
 
    vertex_values[0] = dof_values[0];
20821
 
    vertex_values[1] = dof_values[1];
20822
 
    vertex_values[2] = dof_values[2];
20823
 
    vertex_values[3] = dof_values[3];
20824
 
  }
20825
 
 
20826
 
  /// Return the number of sub elements (for a mixed element)
20827
 
  virtual unsigned int num_sub_elements() const
20828
 
  {
20829
 
    return 1;
20830
 
  }
20831
 
 
20832
 
  /// Create a new finite element for sub element i (for a mixed element)
20833
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
20834
 
  {
20835
 
    return new hyperelasticity_1_finite_element_3_2();
20836
 
  }
20837
 
 
20838
 
};
20839
 
 
20840
 
/// This class defines the interface for a finite element.
20841
 
 
20842
 
class hyperelasticity_1_finite_element_3: public ufc::finite_element
20843
 
{
20844
 
public:
20845
 
 
20846
 
  /// Constructor
20847
 
  hyperelasticity_1_finite_element_3() : ufc::finite_element()
20848
 
  {
20849
 
    // Do nothing
20850
 
  }
20851
 
 
20852
 
  /// Destructor
20853
 
  virtual ~hyperelasticity_1_finite_element_3()
20854
 
  {
20855
 
    // Do nothing
20856
 
  }
20857
 
 
20858
 
  /// Return a string identifying the finite element
20859
 
  virtual const char* signature() const
20860
 
  {
20861
 
    return "VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
20862
 
  }
20863
 
 
20864
 
  /// Return the cell shape
20865
 
  virtual ufc::shape cell_shape() const
20866
 
  {
20867
 
    return ufc::tetrahedron;
20868
 
  }
20869
 
 
20870
 
  /// Return the dimension of the finite element function space
20871
 
  virtual unsigned int space_dimension() const
20872
 
  {
20873
 
    return 12;
20874
 
  }
20875
 
 
20876
 
  /// Return the rank of the value space
20877
 
  virtual unsigned int value_rank() const
20878
 
  {
20879
 
    return 1;
20880
 
  }
20881
 
 
20882
 
  /// Return the dimension of the value space for axis i
20883
 
  virtual unsigned int value_dimension(unsigned int i) const
20884
 
  {
20885
 
    return 3;
20886
 
  }
20887
 
 
20888
 
  /// Evaluate basis function i at given point in cell
20889
 
  virtual void evaluate_basis(unsigned int i,
20890
 
                              double* values,
20891
 
                              const double* coordinates,
20892
 
                              const ufc::cell& c) const
20893
 
  {
20894
 
    // Extract vertex coordinates
20895
 
    const double * const * element_coordinates = c.coordinates;
20896
 
    
20897
 
    // Compute Jacobian of affine map from reference cell
20898
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
20899
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
20900
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
20901
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
20902
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
20903
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
20904
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
20905
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
20906
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
20907
 
    
20908
 
    // Compute sub determinants
20909
 
    const double d00 = J_11*J_22 - J_12*J_21;
20910
 
    const double d01 = J_12*J_20 - J_10*J_22;
20911
 
    const double d02 = J_10*J_21 - J_11*J_20;
20912
 
    
20913
 
    const double d10 = J_02*J_21 - J_01*J_22;
20914
 
    const double d11 = J_00*J_22 - J_02*J_20;
20915
 
    const double d12 = J_01*J_20 - J_00*J_21;
20916
 
    
20917
 
    const double d20 = J_01*J_12 - J_02*J_11;
20918
 
    const double d21 = J_02*J_10 - J_00*J_12;
20919
 
    const double d22 = J_00*J_11 - J_01*J_10;
20920
 
    
20921
 
    // Compute determinant of Jacobian
20922
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
20923
 
    
20924
 
    // Compute inverse of Jacobian
20925
 
    
20926
 
    // Compute constants
20927
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
20928
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
20929
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
20930
 
    
20931
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
20932
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
20933
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
20934
 
    
20935
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
20936
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
20937
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
20938
 
    
20939
 
    // Get coordinates and map to the UFC reference element
20940
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
20941
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
20942
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
20943
 
    
20944
 
    // Map coordinates to the reference cube
20945
 
    if (std::abs(y + z - 1.0) < 1e-08)
20946
 
      x = 1.0;
20947
 
    else
20948
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
20949
 
    if (std::abs(z - 1.0) < 1e-08)
20950
 
      y = -1.0;
20951
 
    else
20952
 
      y = 2.0 * y/(1.0 - z) - 1.0;
20953
 
    z = 2.0 * z - 1.0;
20954
 
    
20955
 
    // Reset values
20956
 
    values[0] = 0;
20957
 
    values[1] = 0;
20958
 
    values[2] = 0;
20959
 
    
20960
 
    if (0 <= i && i <= 3)
20961
 
    {
20962
 
      // Map degree of freedom to element degree of freedom
20963
 
      const unsigned int dof = i;
20964
 
    
20965
 
      // Generate scalings
20966
 
      const double scalings_y_0 = 1;
20967
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
20968
 
      const double scalings_z_0 = 1;
20969
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
20970
 
    
20971
 
      // Compute psitilde_a
20972
 
      const double psitilde_a_0 = 1;
20973
 
      const double psitilde_a_1 = x;
20974
 
    
20975
 
      // Compute psitilde_bs
20976
 
      const double psitilde_bs_0_0 = 1;
20977
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
20978
 
      const double psitilde_bs_1_0 = 1;
20979
 
    
20980
 
      // Compute psitilde_cs
20981
 
      const double psitilde_cs_00_0 = 1;
20982
 
      const double psitilde_cs_00_1 = 2*z + 1;
20983
 
      const double psitilde_cs_01_0 = 1;
20984
 
      const double psitilde_cs_10_0 = 1;
20985
 
    
20986
 
      // Compute basisvalues
20987
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
20988
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
20989
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
20990
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
20991
 
    
20992
 
      // Table(s) of coefficients
20993
 
      static const double coefficients0[4][4] =   \
20994
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
20995
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
20996
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
20997
 
      {0.288675135, 0, 0, 0.223606798}};
20998
 
    
20999
 
      // Extract relevant coefficients
21000
 
      const double coeff0_0 =   coefficients0[dof][0];
21001
 
      const double coeff0_1 =   coefficients0[dof][1];
21002
 
      const double coeff0_2 =   coefficients0[dof][2];
21003
 
      const double coeff0_3 =   coefficients0[dof][3];
21004
 
    
21005
 
      // Compute value(s)
21006
 
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
21007
 
    }
21008
 
    
21009
 
    if (4 <= i && i <= 7)
21010
 
    {
21011
 
      // Map degree of freedom to element degree of freedom
21012
 
      const unsigned int dof = i - 4;
21013
 
    
21014
 
      // Generate scalings
21015
 
      const double scalings_y_0 = 1;
21016
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
21017
 
      const double scalings_z_0 = 1;
21018
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
21019
 
    
21020
 
      // Compute psitilde_a
21021
 
      const double psitilde_a_0 = 1;
21022
 
      const double psitilde_a_1 = x;
21023
 
    
21024
 
      // Compute psitilde_bs
21025
 
      const double psitilde_bs_0_0 = 1;
21026
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
21027
 
      const double psitilde_bs_1_0 = 1;
21028
 
    
21029
 
      // Compute psitilde_cs
21030
 
      const double psitilde_cs_00_0 = 1;
21031
 
      const double psitilde_cs_00_1 = 2*z + 1;
21032
 
      const double psitilde_cs_01_0 = 1;
21033
 
      const double psitilde_cs_10_0 = 1;
21034
 
    
21035
 
      // Compute basisvalues
21036
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21037
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
21038
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
21039
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
21040
 
    
21041
 
      // Table(s) of coefficients
21042
 
      static const double coefficients0[4][4] =   \
21043
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
21044
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
21045
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
21046
 
      {0.288675135, 0, 0, 0.223606798}};
21047
 
    
21048
 
      // Extract relevant coefficients
21049
 
      const double coeff0_0 =   coefficients0[dof][0];
21050
 
      const double coeff0_1 =   coefficients0[dof][1];
21051
 
      const double coeff0_2 =   coefficients0[dof][2];
21052
 
      const double coeff0_3 =   coefficients0[dof][3];
21053
 
    
21054
 
      // Compute value(s)
21055
 
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
21056
 
    }
21057
 
    
21058
 
    if (8 <= i && i <= 11)
21059
 
    {
21060
 
      // Map degree of freedom to element degree of freedom
21061
 
      const unsigned int dof = i - 8;
21062
 
    
21063
 
      // Generate scalings
21064
 
      const double scalings_y_0 = 1;
21065
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
21066
 
      const double scalings_z_0 = 1;
21067
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
21068
 
    
21069
 
      // Compute psitilde_a
21070
 
      const double psitilde_a_0 = 1;
21071
 
      const double psitilde_a_1 = x;
21072
 
    
21073
 
      // Compute psitilde_bs
21074
 
      const double psitilde_bs_0_0 = 1;
21075
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
21076
 
      const double psitilde_bs_1_0 = 1;
21077
 
    
21078
 
      // Compute psitilde_cs
21079
 
      const double psitilde_cs_00_0 = 1;
21080
 
      const double psitilde_cs_00_1 = 2*z + 1;
21081
 
      const double psitilde_cs_01_0 = 1;
21082
 
      const double psitilde_cs_10_0 = 1;
21083
 
    
21084
 
      // Compute basisvalues
21085
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21086
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
21087
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
21088
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
21089
 
    
21090
 
      // Table(s) of coefficients
21091
 
      static const double coefficients0[4][4] =   \
21092
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
21093
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
21094
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
21095
 
      {0.288675135, 0, 0, 0.223606798}};
21096
 
    
21097
 
      // Extract relevant coefficients
21098
 
      const double coeff0_0 =   coefficients0[dof][0];
21099
 
      const double coeff0_1 =   coefficients0[dof][1];
21100
 
      const double coeff0_2 =   coefficients0[dof][2];
21101
 
      const double coeff0_3 =   coefficients0[dof][3];
21102
 
    
21103
 
      // Compute value(s)
21104
 
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
21105
 
    }
21106
 
    
21107
 
  }
21108
 
 
21109
 
  /// Evaluate all basis functions at given point in cell
21110
 
  virtual void evaluate_basis_all(double* values,
21111
 
                                  const double* coordinates,
21112
 
                                  const ufc::cell& c) const
21113
 
  {
21114
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
21115
 
  }
21116
 
 
21117
 
  /// Evaluate order n derivatives of basis function i at given point in cell
21118
 
  virtual void evaluate_basis_derivatives(unsigned int i,
21119
 
                                          unsigned int n,
21120
 
                                          double* values,
21121
 
                                          const double* coordinates,
21122
 
                                          const ufc::cell& c) const
21123
 
  {
21124
 
    // Extract vertex coordinates
21125
 
    const double * const * element_coordinates = c.coordinates;
21126
 
    
21127
 
    // Compute Jacobian of affine map from reference cell
21128
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
21129
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
21130
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
21131
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
21132
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
21133
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
21134
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
21135
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
21136
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
21137
 
    
21138
 
    // Compute sub determinants
21139
 
    const double d00 = J_11*J_22 - J_12*J_21;
21140
 
    const double d01 = J_12*J_20 - J_10*J_22;
21141
 
    const double d02 = J_10*J_21 - J_11*J_20;
21142
 
    
21143
 
    const double d10 = J_02*J_21 - J_01*J_22;
21144
 
    const double d11 = J_00*J_22 - J_02*J_20;
21145
 
    const double d12 = J_01*J_20 - J_00*J_21;
21146
 
    
21147
 
    const double d20 = J_01*J_12 - J_02*J_11;
21148
 
    const double d21 = J_02*J_10 - J_00*J_12;
21149
 
    const double d22 = J_00*J_11 - J_01*J_10;
21150
 
    
21151
 
    // Compute determinant of Jacobian
21152
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
21153
 
    
21154
 
    // Compute inverse of Jacobian
21155
 
    
21156
 
    // Compute constants
21157
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
21158
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
21159
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
21160
 
    
21161
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
21162
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
21163
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
21164
 
    
21165
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
21166
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
21167
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
21168
 
    
21169
 
    // Get coordinates and map to the UFC reference element
21170
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
21171
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
21172
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
21173
 
    
21174
 
    // Map coordinates to the reference cube
21175
 
    if (std::abs(y + z - 1.0) < 1e-08)
21176
 
      x = 1.0;
21177
 
    else
21178
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
21179
 
    if (std::abs(z - 1.0) < 1e-08)
21180
 
      y = -1.0;
21181
 
    else
21182
 
      y = 2.0 * y/(1.0 - z) - 1.0;
21183
 
    z = 2.0 * z - 1.0;
21184
 
    
21185
 
    // Compute number of derivatives
21186
 
    unsigned int num_derivatives = 1;
21187
 
    
21188
 
    for (unsigned int j = 0; j < n; j++)
21189
 
      num_derivatives *= 3;
21190
 
    
21191
 
    
21192
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
21193
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
21194
 
    
21195
 
    for (unsigned int j = 0; j < num_derivatives; j++)
21196
 
    {
21197
 
      combinations[j] = new unsigned int [n];
21198
 
      for (unsigned int k = 0; k < n; k++)
21199
 
        combinations[j][k] = 0;
21200
 
    }
21201
 
    
21202
 
    // Generate combinations of derivatives
21203
 
    for (unsigned int row = 1; row < num_derivatives; row++)
21204
 
    {
21205
 
      for (unsigned int num = 0; num < row; num++)
21206
 
      {
21207
 
        for (unsigned int col = n-1; col+1 > 0; col--)
21208
 
        {
21209
 
          if (combinations[row][col] + 1 > 2)
21210
 
            combinations[row][col] = 0;
21211
 
          else
21212
 
          {
21213
 
            combinations[row][col] += 1;
21214
 
            break;
21215
 
          }
21216
 
        }
21217
 
      }
21218
 
    }
21219
 
    
21220
 
    // Compute inverse of Jacobian
21221
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
21222
 
    
21223
 
    // Declare transformation matrix
21224
 
    // Declare pointer to two dimensional array and initialise
21225
 
    double **transform = new double *[num_derivatives];
21226
 
    
21227
 
    for (unsigned int j = 0; j < num_derivatives; j++)
21228
 
    {
21229
 
      transform[j] = new double [num_derivatives];
21230
 
      for (unsigned int k = 0; k < num_derivatives; k++)
21231
 
        transform[j][k] = 1;
21232
 
    }
21233
 
    
21234
 
    // Construct transformation matrix
21235
 
    for (unsigned int row = 0; row < num_derivatives; row++)
21236
 
    {
21237
 
      for (unsigned int col = 0; col < num_derivatives; col++)
21238
 
      {
21239
 
        for (unsigned int k = 0; k < n; k++)
21240
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
21241
 
      }
21242
 
    }
21243
 
    
21244
 
    // Reset values
21245
 
    for (unsigned int j = 0; j < 3*num_derivatives; j++)
21246
 
      values[j] = 0;
21247
 
    
21248
 
    if (0 <= i && i <= 3)
21249
 
    {
21250
 
      // Map degree of freedom to element degree of freedom
21251
 
      const unsigned int dof = i;
21252
 
    
21253
 
      // Generate scalings
21254
 
      const double scalings_y_0 = 1;
21255
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
21256
 
      const double scalings_z_0 = 1;
21257
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
21258
 
    
21259
 
      // Compute psitilde_a
21260
 
      const double psitilde_a_0 = 1;
21261
 
      const double psitilde_a_1 = x;
21262
 
    
21263
 
      // Compute psitilde_bs
21264
 
      const double psitilde_bs_0_0 = 1;
21265
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
21266
 
      const double psitilde_bs_1_0 = 1;
21267
 
    
21268
 
      // Compute psitilde_cs
21269
 
      const double psitilde_cs_00_0 = 1;
21270
 
      const double psitilde_cs_00_1 = 2*z + 1;
21271
 
      const double psitilde_cs_01_0 = 1;
21272
 
      const double psitilde_cs_10_0 = 1;
21273
 
    
21274
 
      // Compute basisvalues
21275
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21276
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
21277
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
21278
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
21279
 
    
21280
 
      // Table(s) of coefficients
21281
 
      static const double coefficients0[4][4] =   \
21282
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
21283
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
21284
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
21285
 
      {0.288675135, 0, 0, 0.223606798}};
21286
 
    
21287
 
      // Interesting (new) part
21288
 
      // Tables of derivatives of the polynomial base (transpose)
21289
 
      static const double dmats0[4][4] =   \
21290
 
      {{0, 0, 0, 0},
21291
 
      {6.32455532, 0, 0, 0},
21292
 
      {0, 0, 0, 0},
21293
 
      {0, 0, 0, 0}};
21294
 
    
21295
 
      static const double dmats1[4][4] =   \
21296
 
      {{0, 0, 0, 0},
21297
 
      {3.16227766, 0, 0, 0},
21298
 
      {5.47722558, 0, 0, 0},
21299
 
      {0, 0, 0, 0}};
21300
 
    
21301
 
      static const double dmats2[4][4] =   \
21302
 
      {{0, 0, 0, 0},
21303
 
      {3.16227766, 0, 0, 0},
21304
 
      {1.82574186, 0, 0, 0},
21305
 
      {5.16397779, 0, 0, 0}};
21306
 
    
21307
 
      // Compute reference derivatives
21308
 
      // Declare pointer to array of derivatives on FIAT element
21309
 
      double *derivatives = new double [num_derivatives];
21310
 
    
21311
 
      // Declare coefficients
21312
 
      double coeff0_0 = 0;
21313
 
      double coeff0_1 = 0;
21314
 
      double coeff0_2 = 0;
21315
 
      double coeff0_3 = 0;
21316
 
    
21317
 
      // Declare new coefficients
21318
 
      double new_coeff0_0 = 0;
21319
 
      double new_coeff0_1 = 0;
21320
 
      double new_coeff0_2 = 0;
21321
 
      double new_coeff0_3 = 0;
21322
 
    
21323
 
      // Loop possible derivatives
21324
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
21325
 
      {
21326
 
        // Get values from coefficients array
21327
 
        new_coeff0_0 = coefficients0[dof][0];
21328
 
        new_coeff0_1 = coefficients0[dof][1];
21329
 
        new_coeff0_2 = coefficients0[dof][2];
21330
 
        new_coeff0_3 = coefficients0[dof][3];
21331
 
    
21332
 
        // Loop derivative order
21333
 
        for (unsigned int j = 0; j < n; j++)
21334
 
        {
21335
 
          // Update old coefficients
21336
 
          coeff0_0 = new_coeff0_0;
21337
 
          coeff0_1 = new_coeff0_1;
21338
 
          coeff0_2 = new_coeff0_2;
21339
 
          coeff0_3 = new_coeff0_3;
21340
 
    
21341
 
          if(combinations[deriv_num][j] == 0)
21342
 
          {
21343
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
21344
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
21345
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
21346
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
21347
 
          }
21348
 
          if(combinations[deriv_num][j] == 1)
21349
 
          {
21350
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
21351
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
21352
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
21353
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
21354
 
          }
21355
 
          if(combinations[deriv_num][j] == 2)
21356
 
          {
21357
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
21358
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
21359
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
21360
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
21361
 
          }
21362
 
    
21363
 
        }
21364
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
21365
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
21366
 
      }
21367
 
    
21368
 
      // Transform derivatives back to physical element
21369
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21370
 
      {
21371
 
        for (unsigned int col = 0; col < num_derivatives; col++)
21372
 
        {
21373
 
          values[row] += transform[row][col]*derivatives[col];
21374
 
        }
21375
 
      }
21376
 
      // Delete pointer to array of derivatives on FIAT element
21377
 
      delete [] derivatives;
21378
 
    
21379
 
      // Delete pointer to array of combinations of derivatives and transform
21380
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21381
 
      {
21382
 
        delete [] combinations[row];
21383
 
        delete [] transform[row];
21384
 
      }
21385
 
    
21386
 
      delete [] combinations;
21387
 
      delete [] transform;
21388
 
    }
21389
 
    
21390
 
    if (4 <= i && i <= 7)
21391
 
    {
21392
 
      // Map degree of freedom to element degree of freedom
21393
 
      const unsigned int dof = i - 4;
21394
 
    
21395
 
      // Generate scalings
21396
 
      const double scalings_y_0 = 1;
21397
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
21398
 
      const double scalings_z_0 = 1;
21399
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
21400
 
    
21401
 
      // Compute psitilde_a
21402
 
      const double psitilde_a_0 = 1;
21403
 
      const double psitilde_a_1 = x;
21404
 
    
21405
 
      // Compute psitilde_bs
21406
 
      const double psitilde_bs_0_0 = 1;
21407
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
21408
 
      const double psitilde_bs_1_0 = 1;
21409
 
    
21410
 
      // Compute psitilde_cs
21411
 
      const double psitilde_cs_00_0 = 1;
21412
 
      const double psitilde_cs_00_1 = 2*z + 1;
21413
 
      const double psitilde_cs_01_0 = 1;
21414
 
      const double psitilde_cs_10_0 = 1;
21415
 
    
21416
 
      // Compute basisvalues
21417
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21418
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
21419
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
21420
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
21421
 
    
21422
 
      // Table(s) of coefficients
21423
 
      static const double coefficients0[4][4] =   \
21424
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
21425
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
21426
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
21427
 
      {0.288675135, 0, 0, 0.223606798}};
21428
 
    
21429
 
      // Interesting (new) part
21430
 
      // Tables of derivatives of the polynomial base (transpose)
21431
 
      static const double dmats0[4][4] =   \
21432
 
      {{0, 0, 0, 0},
21433
 
      {6.32455532, 0, 0, 0},
21434
 
      {0, 0, 0, 0},
21435
 
      {0, 0, 0, 0}};
21436
 
    
21437
 
      static const double dmats1[4][4] =   \
21438
 
      {{0, 0, 0, 0},
21439
 
      {3.16227766, 0, 0, 0},
21440
 
      {5.47722558, 0, 0, 0},
21441
 
      {0, 0, 0, 0}};
21442
 
    
21443
 
      static const double dmats2[4][4] =   \
21444
 
      {{0, 0, 0, 0},
21445
 
      {3.16227766, 0, 0, 0},
21446
 
      {1.82574186, 0, 0, 0},
21447
 
      {5.16397779, 0, 0, 0}};
21448
 
    
21449
 
      // Compute reference derivatives
21450
 
      // Declare pointer to array of derivatives on FIAT element
21451
 
      double *derivatives = new double [num_derivatives];
21452
 
    
21453
 
      // Declare coefficients
21454
 
      double coeff0_0 = 0;
21455
 
      double coeff0_1 = 0;
21456
 
      double coeff0_2 = 0;
21457
 
      double coeff0_3 = 0;
21458
 
    
21459
 
      // Declare new coefficients
21460
 
      double new_coeff0_0 = 0;
21461
 
      double new_coeff0_1 = 0;
21462
 
      double new_coeff0_2 = 0;
21463
 
      double new_coeff0_3 = 0;
21464
 
    
21465
 
      // Loop possible derivatives
21466
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
21467
 
      {
21468
 
        // Get values from coefficients array
21469
 
        new_coeff0_0 = coefficients0[dof][0];
21470
 
        new_coeff0_1 = coefficients0[dof][1];
21471
 
        new_coeff0_2 = coefficients0[dof][2];
21472
 
        new_coeff0_3 = coefficients0[dof][3];
21473
 
    
21474
 
        // Loop derivative order
21475
 
        for (unsigned int j = 0; j < n; j++)
21476
 
        {
21477
 
          // Update old coefficients
21478
 
          coeff0_0 = new_coeff0_0;
21479
 
          coeff0_1 = new_coeff0_1;
21480
 
          coeff0_2 = new_coeff0_2;
21481
 
          coeff0_3 = new_coeff0_3;
21482
 
    
21483
 
          if(combinations[deriv_num][j] == 0)
21484
 
          {
21485
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
21486
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
21487
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
21488
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
21489
 
          }
21490
 
          if(combinations[deriv_num][j] == 1)
21491
 
          {
21492
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
21493
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
21494
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
21495
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
21496
 
          }
21497
 
          if(combinations[deriv_num][j] == 2)
21498
 
          {
21499
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
21500
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
21501
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
21502
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
21503
 
          }
21504
 
    
21505
 
        }
21506
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
21507
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
21508
 
      }
21509
 
    
21510
 
      // Transform derivatives back to physical element
21511
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21512
 
      {
21513
 
        for (unsigned int col = 0; col < num_derivatives; col++)
21514
 
        {
21515
 
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
21516
 
        }
21517
 
      }
21518
 
      // Delete pointer to array of derivatives on FIAT element
21519
 
      delete [] derivatives;
21520
 
    
21521
 
      // Delete pointer to array of combinations of derivatives and transform
21522
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21523
 
      {
21524
 
        delete [] combinations[row];
21525
 
        delete [] transform[row];
21526
 
      }
21527
 
    
21528
 
      delete [] combinations;
21529
 
      delete [] transform;
21530
 
    }
21531
 
    
21532
 
    if (8 <= i && i <= 11)
21533
 
    {
21534
 
      // Map degree of freedom to element degree of freedom
21535
 
      const unsigned int dof = i - 8;
21536
 
    
21537
 
      // Generate scalings
21538
 
      const double scalings_y_0 = 1;
21539
 
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
21540
 
      const double scalings_z_0 = 1;
21541
 
      const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
21542
 
    
21543
 
      // Compute psitilde_a
21544
 
      const double psitilde_a_0 = 1;
21545
 
      const double psitilde_a_1 = x;
21546
 
    
21547
 
      // Compute psitilde_bs
21548
 
      const double psitilde_bs_0_0 = 1;
21549
 
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
21550
 
      const double psitilde_bs_1_0 = 1;
21551
 
    
21552
 
      // Compute psitilde_cs
21553
 
      const double psitilde_cs_00_0 = 1;
21554
 
      const double psitilde_cs_00_1 = 2*z + 1;
21555
 
      const double psitilde_cs_01_0 = 1;
21556
 
      const double psitilde_cs_10_0 = 1;
21557
 
    
21558
 
      // Compute basisvalues
21559
 
      const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21560
 
      const double basisvalue1 = 2.73861279*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
21561
 
      const double basisvalue2 = 1.58113883*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
21562
 
      const double basisvalue3 = 1.11803399*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
21563
 
    
21564
 
      // Table(s) of coefficients
21565
 
      static const double coefficients0[4][4] =   \
21566
 
      {{0.288675135, -0.182574186, -0.105409255, -0.0745355992},
21567
 
      {0.288675135, 0.182574186, -0.105409255, -0.0745355992},
21568
 
      {0.288675135, 0, 0.210818511, -0.0745355992},
21569
 
      {0.288675135, 0, 0, 0.223606798}};
21570
 
    
21571
 
      // Interesting (new) part
21572
 
      // Tables of derivatives of the polynomial base (transpose)
21573
 
      static const double dmats0[4][4] =   \
21574
 
      {{0, 0, 0, 0},
21575
 
      {6.32455532, 0, 0, 0},
21576
 
      {0, 0, 0, 0},
21577
 
      {0, 0, 0, 0}};
21578
 
    
21579
 
      static const double dmats1[4][4] =   \
21580
 
      {{0, 0, 0, 0},
21581
 
      {3.16227766, 0, 0, 0},
21582
 
      {5.47722558, 0, 0, 0},
21583
 
      {0, 0, 0, 0}};
21584
 
    
21585
 
      static const double dmats2[4][4] =   \
21586
 
      {{0, 0, 0, 0},
21587
 
      {3.16227766, 0, 0, 0},
21588
 
      {1.82574186, 0, 0, 0},
21589
 
      {5.16397779, 0, 0, 0}};
21590
 
    
21591
 
      // Compute reference derivatives
21592
 
      // Declare pointer to array of derivatives on FIAT element
21593
 
      double *derivatives = new double [num_derivatives];
21594
 
    
21595
 
      // Declare coefficients
21596
 
      double coeff0_0 = 0;
21597
 
      double coeff0_1 = 0;
21598
 
      double coeff0_2 = 0;
21599
 
      double coeff0_3 = 0;
21600
 
    
21601
 
      // Declare new coefficients
21602
 
      double new_coeff0_0 = 0;
21603
 
      double new_coeff0_1 = 0;
21604
 
      double new_coeff0_2 = 0;
21605
 
      double new_coeff0_3 = 0;
21606
 
    
21607
 
      // Loop possible derivatives
21608
 
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
21609
 
      {
21610
 
        // Get values from coefficients array
21611
 
        new_coeff0_0 = coefficients0[dof][0];
21612
 
        new_coeff0_1 = coefficients0[dof][1];
21613
 
        new_coeff0_2 = coefficients0[dof][2];
21614
 
        new_coeff0_3 = coefficients0[dof][3];
21615
 
    
21616
 
        // Loop derivative order
21617
 
        for (unsigned int j = 0; j < n; j++)
21618
 
        {
21619
 
          // Update old coefficients
21620
 
          coeff0_0 = new_coeff0_0;
21621
 
          coeff0_1 = new_coeff0_1;
21622
 
          coeff0_2 = new_coeff0_2;
21623
 
          coeff0_3 = new_coeff0_3;
21624
 
    
21625
 
          if(combinations[deriv_num][j] == 0)
21626
 
          {
21627
 
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
21628
 
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
21629
 
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
21630
 
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
21631
 
          }
21632
 
          if(combinations[deriv_num][j] == 1)
21633
 
          {
21634
 
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
21635
 
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
21636
 
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
21637
 
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
21638
 
          }
21639
 
          if(combinations[deriv_num][j] == 2)
21640
 
          {
21641
 
            new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
21642
 
            new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
21643
 
            new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
21644
 
            new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
21645
 
          }
21646
 
    
21647
 
        }
21648
 
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
21649
 
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
21650
 
      }
21651
 
    
21652
 
      // Transform derivatives back to physical element
21653
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21654
 
      {
21655
 
        for (unsigned int col = 0; col < num_derivatives; col++)
21656
 
        {
21657
 
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
21658
 
        }
21659
 
      }
21660
 
      // Delete pointer to array of derivatives on FIAT element
21661
 
      delete [] derivatives;
21662
 
    
21663
 
      // Delete pointer to array of combinations of derivatives and transform
21664
 
      for (unsigned int row = 0; row < num_derivatives; row++)
21665
 
      {
21666
 
        delete [] combinations[row];
21667
 
        delete [] transform[row];
21668
 
      }
21669
 
    
21670
 
      delete [] combinations;
21671
 
      delete [] transform;
21672
 
    }
21673
 
    
21674
 
  }
21675
 
 
21676
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
21677
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
21678
 
                                              double* values,
21679
 
                                              const double* coordinates,
21680
 
                                              const ufc::cell& c) const
21681
 
  {
21682
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
21683
 
  }
21684
 
 
21685
 
  /// Evaluate linear functional for dof i on the function f
21686
 
  virtual double evaluate_dof(unsigned int i,
21687
 
                              const ufc::function& f,
21688
 
                              const ufc::cell& c) const
21689
 
  {
21690
 
    // The reference points, direction and weights:
21691
 
    static const double X[12][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
21692
 
    static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
21693
 
    static const double D[12][1][3] = {{{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 1, 0}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}, {{0, 0, 1}}};
21694
 
    
21695
 
    const double * const * x = c.coordinates;
21696
 
    double result = 0.0;
21697
 
    // Iterate over the points:
21698
 
    // Evaluate basis functions for affine mapping
21699
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
21700
 
    const double w1 = X[i][0][0];
21701
 
    const double w2 = X[i][0][1];
21702
 
    const double w3 = X[i][0][2];
21703
 
    
21704
 
    // Compute affine mapping y = F(X)
21705
 
    double y[3];
21706
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
21707
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
21708
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
21709
 
    
21710
 
    // Evaluate function at physical points
21711
 
    double values[3];
21712
 
    f.evaluate(values, y, c);
21713
 
    
21714
 
    // Map function values using appropriate mapping
21715
 
    // Affine map: Do nothing
21716
 
    
21717
 
    // Note that we do not map the weights (yet).
21718
 
    
21719
 
    // Take directional components
21720
 
    for(int k = 0; k < 3; k++)
21721
 
      result += values[k]*D[i][0][k];
21722
 
    // Multiply by weights
21723
 
    result *= W[i][0];
21724
 
    
21725
 
    return result;
21726
 
  }
21727
 
 
21728
 
  /// Evaluate linear functionals for all dofs on the function f
21729
 
  virtual void evaluate_dofs(double* values,
21730
 
                             const ufc::function& f,
21731
 
                             const ufc::cell& c) const
21732
 
  {
21733
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
21734
 
  }
21735
 
 
21736
 
  /// Interpolate vertex values from dof values
21737
 
  virtual void interpolate_vertex_values(double* vertex_values,
21738
 
                                         const double* dof_values,
21739
 
                                         const ufc::cell& c) const
21740
 
  {
21741
 
    // Evaluate at vertices and use affine mapping
21742
 
    vertex_values[0] = dof_values[0];
21743
 
    vertex_values[3] = dof_values[1];
21744
 
    vertex_values[6] = dof_values[2];
21745
 
    vertex_values[9] = dof_values[3];
21746
 
    // Evaluate at vertices and use affine mapping
21747
 
    vertex_values[1] = dof_values[4];
21748
 
    vertex_values[4] = dof_values[5];
21749
 
    vertex_values[7] = dof_values[6];
21750
 
    vertex_values[10] = dof_values[7];
21751
 
    // Evaluate at vertices and use affine mapping
21752
 
    vertex_values[2] = dof_values[8];
21753
 
    vertex_values[5] = dof_values[9];
21754
 
    vertex_values[8] = dof_values[10];
21755
 
    vertex_values[11] = dof_values[11];
21756
 
  }
21757
 
 
21758
 
  /// Return the number of sub elements (for a mixed element)
21759
 
  virtual unsigned int num_sub_elements() const
21760
 
  {
21761
 
    return 3;
21762
 
  }
21763
 
 
21764
 
  /// Create a new finite element for sub element i (for a mixed element)
21765
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
21766
 
  {
21767
 
    switch ( i )
21768
 
    {
21769
 
    case 0:
21770
 
      return new hyperelasticity_1_finite_element_3_0();
21771
 
      break;
21772
 
    case 1:
21773
 
      return new hyperelasticity_1_finite_element_3_1();
21774
 
      break;
21775
 
    case 2:
21776
 
      return new hyperelasticity_1_finite_element_3_2();
21777
 
      break;
21778
 
    }
21779
 
    return 0;
21780
 
  }
21781
 
 
21782
 
};
21783
 
 
21784
 
/// This class defines the interface for a finite element.
21785
 
 
21786
 
class hyperelasticity_1_finite_element_4: public ufc::finite_element
21787
 
{
21788
 
public:
21789
 
 
21790
 
  /// Constructor
21791
 
  hyperelasticity_1_finite_element_4() : ufc::finite_element()
21792
 
  {
21793
 
    // Do nothing
21794
 
  }
21795
 
 
21796
 
  /// Destructor
21797
 
  virtual ~hyperelasticity_1_finite_element_4()
21798
 
  {
21799
 
    // Do nothing
21800
 
  }
21801
 
 
21802
 
  /// Return a string identifying the finite element
21803
 
  virtual const char* signature() const
21804
 
  {
21805
 
    return "FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
21806
 
  }
21807
 
 
21808
 
  /// Return the cell shape
21809
 
  virtual ufc::shape cell_shape() const
21810
 
  {
21811
 
    return ufc::tetrahedron;
21812
 
  }
21813
 
 
21814
 
  /// Return the dimension of the finite element function space
21815
 
  virtual unsigned int space_dimension() const
21816
 
  {
21817
 
    return 1;
21818
 
  }
21819
 
 
21820
 
  /// Return the rank of the value space
21821
 
  virtual unsigned int value_rank() const
21822
 
  {
21823
 
    return 0;
21824
 
  }
21825
 
 
21826
 
  /// Return the dimension of the value space for axis i
21827
 
  virtual unsigned int value_dimension(unsigned int i) const
21828
 
  {
21829
 
    return 1;
21830
 
  }
21831
 
 
21832
 
  /// Evaluate basis function i at given point in cell
21833
 
  virtual void evaluate_basis(unsigned int i,
21834
 
                              double* values,
21835
 
                              const double* coordinates,
21836
 
                              const ufc::cell& c) const
21837
 
  {
21838
 
    // Extract vertex coordinates
21839
 
    const double * const * element_coordinates = c.coordinates;
21840
 
    
21841
 
    // Compute Jacobian of affine map from reference cell
21842
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
21843
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
21844
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
21845
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
21846
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
21847
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
21848
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
21849
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
21850
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
21851
 
    
21852
 
    // Compute sub determinants
21853
 
    const double d00 = J_11*J_22 - J_12*J_21;
21854
 
    const double d01 = J_12*J_20 - J_10*J_22;
21855
 
    const double d02 = J_10*J_21 - J_11*J_20;
21856
 
    
21857
 
    const double d10 = J_02*J_21 - J_01*J_22;
21858
 
    const double d11 = J_00*J_22 - J_02*J_20;
21859
 
    const double d12 = J_01*J_20 - J_00*J_21;
21860
 
    
21861
 
    const double d20 = J_01*J_12 - J_02*J_11;
21862
 
    const double d21 = J_02*J_10 - J_00*J_12;
21863
 
    const double d22 = J_00*J_11 - J_01*J_10;
21864
 
    
21865
 
    // Compute determinant of Jacobian
21866
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
21867
 
    
21868
 
    // Compute inverse of Jacobian
21869
 
    
21870
 
    // Compute constants
21871
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
21872
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
21873
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
21874
 
    
21875
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
21876
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
21877
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
21878
 
    
21879
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
21880
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
21881
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
21882
 
    
21883
 
    // Get coordinates and map to the UFC reference element
21884
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
21885
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
21886
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
21887
 
    
21888
 
    // Map coordinates to the reference cube
21889
 
    if (std::abs(y + z - 1.0) < 1e-08)
21890
 
      x = 1.0;
21891
 
    else
21892
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
21893
 
    if (std::abs(z - 1.0) < 1e-08)
21894
 
      y = -1.0;
21895
 
    else
21896
 
      y = 2.0 * y/(1.0 - z) - 1.0;
21897
 
    z = 2.0 * z - 1.0;
21898
 
    
21899
 
    // Reset values
21900
 
    *values = 0;
21901
 
    
21902
 
    // Map degree of freedom to element degree of freedom
21903
 
    const unsigned int dof = i;
21904
 
    
21905
 
    // Generate scalings
21906
 
    const double scalings_y_0 = 1;
21907
 
    const double scalings_z_0 = 1;
21908
 
    
21909
 
    // Compute psitilde_a
21910
 
    const double psitilde_a_0 = 1;
21911
 
    
21912
 
    // Compute psitilde_bs
21913
 
    const double psitilde_bs_0_0 = 1;
21914
 
    
21915
 
    // Compute psitilde_cs
21916
 
    const double psitilde_cs_00_0 = 1;
21917
 
    
21918
 
    // Compute basisvalues
21919
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
21920
 
    
21921
 
    // Table(s) of coefficients
21922
 
    static const double coefficients0[1][1] = \
21923
 
    {{1.15470054}};
21924
 
    
21925
 
    // Extract relevant coefficients
21926
 
    const double coeff0_0 = coefficients0[dof][0];
21927
 
    
21928
 
    // Compute value(s)
21929
 
    *values = coeff0_0*basisvalue0;
21930
 
  }
21931
 
 
21932
 
  /// Evaluate all basis functions at given point in cell
21933
 
  virtual void evaluate_basis_all(double* values,
21934
 
                                  const double* coordinates,
21935
 
                                  const ufc::cell& c) const
21936
 
  {
21937
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
21938
 
  }
21939
 
 
21940
 
  /// Evaluate order n derivatives of basis function i at given point in cell
21941
 
  virtual void evaluate_basis_derivatives(unsigned int i,
21942
 
                                          unsigned int n,
21943
 
                                          double* values,
21944
 
                                          const double* coordinates,
21945
 
                                          const ufc::cell& c) const
21946
 
  {
21947
 
    // Extract vertex coordinates
21948
 
    const double * const * element_coordinates = c.coordinates;
21949
 
    
21950
 
    // Compute Jacobian of affine map from reference cell
21951
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
21952
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
21953
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
21954
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
21955
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
21956
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
21957
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
21958
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
21959
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
21960
 
    
21961
 
    // Compute sub determinants
21962
 
    const double d00 = J_11*J_22 - J_12*J_21;
21963
 
    const double d01 = J_12*J_20 - J_10*J_22;
21964
 
    const double d02 = J_10*J_21 - J_11*J_20;
21965
 
    
21966
 
    const double d10 = J_02*J_21 - J_01*J_22;
21967
 
    const double d11 = J_00*J_22 - J_02*J_20;
21968
 
    const double d12 = J_01*J_20 - J_00*J_21;
21969
 
    
21970
 
    const double d20 = J_01*J_12 - J_02*J_11;
21971
 
    const double d21 = J_02*J_10 - J_00*J_12;
21972
 
    const double d22 = J_00*J_11 - J_01*J_10;
21973
 
    
21974
 
    // Compute determinant of Jacobian
21975
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
21976
 
    
21977
 
    // Compute inverse of Jacobian
21978
 
    
21979
 
    // Compute constants
21980
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
21981
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
21982
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
21983
 
    
21984
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
21985
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
21986
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
21987
 
    
21988
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
21989
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
21990
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
21991
 
    
21992
 
    // Get coordinates and map to the UFC reference element
21993
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
21994
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
21995
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
21996
 
    
21997
 
    // Map coordinates to the reference cube
21998
 
    if (std::abs(y + z - 1.0) < 1e-08)
21999
 
      x = 1.0;
22000
 
    else
22001
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
22002
 
    if (std::abs(z - 1.0) < 1e-08)
22003
 
      y = -1.0;
22004
 
    else
22005
 
      y = 2.0 * y/(1.0 - z) - 1.0;
22006
 
    z = 2.0 * z - 1.0;
22007
 
    
22008
 
    // Compute number of derivatives
22009
 
    unsigned int num_derivatives = 1;
22010
 
    
22011
 
    for (unsigned int j = 0; j < n; j++)
22012
 
      num_derivatives *= 3;
22013
 
    
22014
 
    
22015
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
22016
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
22017
 
    
22018
 
    for (unsigned int j = 0; j < num_derivatives; j++)
22019
 
    {
22020
 
      combinations[j] = new unsigned int [n];
22021
 
      for (unsigned int k = 0; k < n; k++)
22022
 
        combinations[j][k] = 0;
22023
 
    }
22024
 
    
22025
 
    // Generate combinations of derivatives
22026
 
    for (unsigned int row = 1; row < num_derivatives; row++)
22027
 
    {
22028
 
      for (unsigned int num = 0; num < row; num++)
22029
 
      {
22030
 
        for (unsigned int col = n-1; col+1 > 0; col--)
22031
 
        {
22032
 
          if (combinations[row][col] + 1 > 2)
22033
 
            combinations[row][col] = 0;
22034
 
          else
22035
 
          {
22036
 
            combinations[row][col] += 1;
22037
 
            break;
22038
 
          }
22039
 
        }
22040
 
      }
22041
 
    }
22042
 
    
22043
 
    // Compute inverse of Jacobian
22044
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
22045
 
    
22046
 
    // Declare transformation matrix
22047
 
    // Declare pointer to two dimensional array and initialise
22048
 
    double **transform = new double *[num_derivatives];
22049
 
    
22050
 
    for (unsigned int j = 0; j < num_derivatives; j++)
22051
 
    {
22052
 
      transform[j] = new double [num_derivatives];
22053
 
      for (unsigned int k = 0; k < num_derivatives; k++)
22054
 
        transform[j][k] = 1;
22055
 
    }
22056
 
    
22057
 
    // Construct transformation matrix
22058
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22059
 
    {
22060
 
      for (unsigned int col = 0; col < num_derivatives; col++)
22061
 
      {
22062
 
        for (unsigned int k = 0; k < n; k++)
22063
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
22064
 
      }
22065
 
    }
22066
 
    
22067
 
    // Reset values
22068
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
22069
 
      values[j] = 0;
22070
 
    
22071
 
    // Map degree of freedom to element degree of freedom
22072
 
    const unsigned int dof = i;
22073
 
    
22074
 
    // Generate scalings
22075
 
    const double scalings_y_0 = 1;
22076
 
    const double scalings_z_0 = 1;
22077
 
    
22078
 
    // Compute psitilde_a
22079
 
    const double psitilde_a_0 = 1;
22080
 
    
22081
 
    // Compute psitilde_bs
22082
 
    const double psitilde_bs_0_0 = 1;
22083
 
    
22084
 
    // Compute psitilde_cs
22085
 
    const double psitilde_cs_00_0 = 1;
22086
 
    
22087
 
    // Compute basisvalues
22088
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
22089
 
    
22090
 
    // Table(s) of coefficients
22091
 
    static const double coefficients0[1][1] = \
22092
 
    {{1.15470054}};
22093
 
    
22094
 
    // Interesting (new) part
22095
 
    // Tables of derivatives of the polynomial base (transpose)
22096
 
    static const double dmats0[1][1] = \
22097
 
    {{0}};
22098
 
    
22099
 
    static const double dmats1[1][1] = \
22100
 
    {{0}};
22101
 
    
22102
 
    static const double dmats2[1][1] = \
22103
 
    {{0}};
22104
 
    
22105
 
    // Compute reference derivatives
22106
 
    // Declare pointer to array of derivatives on FIAT element
22107
 
    double *derivatives = new double [num_derivatives];
22108
 
    
22109
 
    // Declare coefficients
22110
 
    double coeff0_0 = 0;
22111
 
    
22112
 
    // Declare new coefficients
22113
 
    double new_coeff0_0 = 0;
22114
 
    
22115
 
    // Loop possible derivatives
22116
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
22117
 
    {
22118
 
      // Get values from coefficients array
22119
 
      new_coeff0_0 = coefficients0[dof][0];
22120
 
    
22121
 
      // Loop derivative order
22122
 
      for (unsigned int j = 0; j < n; j++)
22123
 
      {
22124
 
        // Update old coefficients
22125
 
        coeff0_0 = new_coeff0_0;
22126
 
    
22127
 
        if(combinations[deriv_num][j] == 0)
22128
 
        {
22129
 
          new_coeff0_0 = coeff0_0*dmats0[0][0];
22130
 
        }
22131
 
        if(combinations[deriv_num][j] == 1)
22132
 
        {
22133
 
          new_coeff0_0 = coeff0_0*dmats1[0][0];
22134
 
        }
22135
 
        if(combinations[deriv_num][j] == 2)
22136
 
        {
22137
 
          new_coeff0_0 = coeff0_0*dmats2[0][0];
22138
 
        }
22139
 
    
22140
 
      }
22141
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
22142
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0;
22143
 
    }
22144
 
    
22145
 
    // Transform derivatives back to physical element
22146
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22147
 
    {
22148
 
      for (unsigned int col = 0; col < num_derivatives; col++)
22149
 
      {
22150
 
        values[row] += transform[row][col]*derivatives[col];
22151
 
      }
22152
 
    }
22153
 
    // Delete pointer to array of derivatives on FIAT element
22154
 
    delete [] derivatives;
22155
 
    
22156
 
    // Delete pointer to array of combinations of derivatives and transform
22157
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22158
 
    {
22159
 
      delete [] combinations[row];
22160
 
      delete [] transform[row];
22161
 
    }
22162
 
    
22163
 
    delete [] combinations;
22164
 
    delete [] transform;
22165
 
  }
22166
 
 
22167
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
22168
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
22169
 
                                              double* values,
22170
 
                                              const double* coordinates,
22171
 
                                              const ufc::cell& c) const
22172
 
  {
22173
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
22174
 
  }
22175
 
 
22176
 
  /// Evaluate linear functional for dof i on the function f
22177
 
  virtual double evaluate_dof(unsigned int i,
22178
 
                              const ufc::function& f,
22179
 
                              const ufc::cell& c) const
22180
 
  {
22181
 
    // The reference points, direction and weights:
22182
 
    static const double X[1][1][3] = {{{0.25, 0.25, 0.25}}};
22183
 
    static const double W[1][1] = {{1}};
22184
 
    static const double D[1][1][1] = {{{1}}};
22185
 
    
22186
 
    const double * const * x = c.coordinates;
22187
 
    double result = 0.0;
22188
 
    // Iterate over the points:
22189
 
    // Evaluate basis functions for affine mapping
22190
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
22191
 
    const double w1 = X[i][0][0];
22192
 
    const double w2 = X[i][0][1];
22193
 
    const double w3 = X[i][0][2];
22194
 
    
22195
 
    // Compute affine mapping y = F(X)
22196
 
    double y[3];
22197
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
22198
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
22199
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
22200
 
    
22201
 
    // Evaluate function at physical points
22202
 
    double values[1];
22203
 
    f.evaluate(values, y, c);
22204
 
    
22205
 
    // Map function values using appropriate mapping
22206
 
    // Affine map: Do nothing
22207
 
    
22208
 
    // Note that we do not map the weights (yet).
22209
 
    
22210
 
    // Take directional components
22211
 
    for(int k = 0; k < 1; k++)
22212
 
      result += values[k]*D[i][0][k];
22213
 
    // Multiply by weights
22214
 
    result *= W[i][0];
22215
 
    
22216
 
    return result;
22217
 
  }
22218
 
 
22219
 
  /// Evaluate linear functionals for all dofs on the function f
22220
 
  virtual void evaluate_dofs(double* values,
22221
 
                             const ufc::function& f,
22222
 
                             const ufc::cell& c) const
22223
 
  {
22224
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
22225
 
  }
22226
 
 
22227
 
  /// Interpolate vertex values from dof values
22228
 
  virtual void interpolate_vertex_values(double* vertex_values,
22229
 
                                         const double* dof_values,
22230
 
                                         const ufc::cell& c) const
22231
 
  {
22232
 
    // Evaluate at vertices and use affine mapping
22233
 
    vertex_values[0] = dof_values[0];
22234
 
    vertex_values[1] = dof_values[0];
22235
 
    vertex_values[2] = dof_values[0];
22236
 
    vertex_values[3] = dof_values[0];
22237
 
  }
22238
 
 
22239
 
  /// Return the number of sub elements (for a mixed element)
22240
 
  virtual unsigned int num_sub_elements() const
22241
 
  {
22242
 
    return 1;
22243
 
  }
22244
 
 
22245
 
  /// Create a new finite element for sub element i (for a mixed element)
22246
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
22247
 
  {
22248
 
    return new hyperelasticity_1_finite_element_4();
22249
 
  }
22250
 
 
22251
 
};
22252
 
 
22253
 
/// This class defines the interface for a finite element.
22254
 
 
22255
 
class hyperelasticity_1_finite_element_5: public ufc::finite_element
22256
 
{
22257
 
public:
22258
 
 
22259
 
  /// Constructor
22260
 
  hyperelasticity_1_finite_element_5() : ufc::finite_element()
22261
 
  {
22262
 
    // Do nothing
22263
 
  }
22264
 
 
22265
 
  /// Destructor
22266
 
  virtual ~hyperelasticity_1_finite_element_5()
22267
 
  {
22268
 
    // Do nothing
22269
 
  }
22270
 
 
22271
 
  /// Return a string identifying the finite element
22272
 
  virtual const char* signature() const
22273
 
  {
22274
 
    return "FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
22275
 
  }
22276
 
 
22277
 
  /// Return the cell shape
22278
 
  virtual ufc::shape cell_shape() const
22279
 
  {
22280
 
    return ufc::tetrahedron;
22281
 
  }
22282
 
 
22283
 
  /// Return the dimension of the finite element function space
22284
 
  virtual unsigned int space_dimension() const
22285
 
  {
22286
 
    return 1;
22287
 
  }
22288
 
 
22289
 
  /// Return the rank of the value space
22290
 
  virtual unsigned int value_rank() const
22291
 
  {
22292
 
    return 0;
22293
 
  }
22294
 
 
22295
 
  /// Return the dimension of the value space for axis i
22296
 
  virtual unsigned int value_dimension(unsigned int i) const
22297
 
  {
22298
 
    return 1;
22299
 
  }
22300
 
 
22301
 
  /// Evaluate basis function i at given point in cell
22302
 
  virtual void evaluate_basis(unsigned int i,
22303
 
                              double* values,
22304
 
                              const double* coordinates,
22305
 
                              const ufc::cell& c) const
22306
 
  {
22307
 
    // Extract vertex coordinates
22308
 
    const double * const * element_coordinates = c.coordinates;
22309
 
    
22310
 
    // Compute Jacobian of affine map from reference cell
22311
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
22312
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
22313
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
22314
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
22315
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
22316
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
22317
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
22318
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
22319
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
22320
 
    
22321
 
    // Compute sub determinants
22322
 
    const double d00 = J_11*J_22 - J_12*J_21;
22323
 
    const double d01 = J_12*J_20 - J_10*J_22;
22324
 
    const double d02 = J_10*J_21 - J_11*J_20;
22325
 
    
22326
 
    const double d10 = J_02*J_21 - J_01*J_22;
22327
 
    const double d11 = J_00*J_22 - J_02*J_20;
22328
 
    const double d12 = J_01*J_20 - J_00*J_21;
22329
 
    
22330
 
    const double d20 = J_01*J_12 - J_02*J_11;
22331
 
    const double d21 = J_02*J_10 - J_00*J_12;
22332
 
    const double d22 = J_00*J_11 - J_01*J_10;
22333
 
    
22334
 
    // Compute determinant of Jacobian
22335
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
22336
 
    
22337
 
    // Compute inverse of Jacobian
22338
 
    
22339
 
    // Compute constants
22340
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
22341
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
22342
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
22343
 
    
22344
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
22345
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
22346
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
22347
 
    
22348
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
22349
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
22350
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
22351
 
    
22352
 
    // Get coordinates and map to the UFC reference element
22353
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
22354
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
22355
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
22356
 
    
22357
 
    // Map coordinates to the reference cube
22358
 
    if (std::abs(y + z - 1.0) < 1e-08)
22359
 
      x = 1.0;
22360
 
    else
22361
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
22362
 
    if (std::abs(z - 1.0) < 1e-08)
22363
 
      y = -1.0;
22364
 
    else
22365
 
      y = 2.0 * y/(1.0 - z) - 1.0;
22366
 
    z = 2.0 * z - 1.0;
22367
 
    
22368
 
    // Reset values
22369
 
    *values = 0;
22370
 
    
22371
 
    // Map degree of freedom to element degree of freedom
22372
 
    const unsigned int dof = i;
22373
 
    
22374
 
    // Generate scalings
22375
 
    const double scalings_y_0 = 1;
22376
 
    const double scalings_z_0 = 1;
22377
 
    
22378
 
    // Compute psitilde_a
22379
 
    const double psitilde_a_0 = 1;
22380
 
    
22381
 
    // Compute psitilde_bs
22382
 
    const double psitilde_bs_0_0 = 1;
22383
 
    
22384
 
    // Compute psitilde_cs
22385
 
    const double psitilde_cs_00_0 = 1;
22386
 
    
22387
 
    // Compute basisvalues
22388
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
22389
 
    
22390
 
    // Table(s) of coefficients
22391
 
    static const double coefficients0[1][1] = \
22392
 
    {{1.15470054}};
22393
 
    
22394
 
    // Extract relevant coefficients
22395
 
    const double coeff0_0 = coefficients0[dof][0];
22396
 
    
22397
 
    // Compute value(s)
22398
 
    *values = coeff0_0*basisvalue0;
22399
 
  }
22400
 
 
22401
 
  /// Evaluate all basis functions at given point in cell
22402
 
  virtual void evaluate_basis_all(double* values,
22403
 
                                  const double* coordinates,
22404
 
                                  const ufc::cell& c) const
22405
 
  {
22406
 
    throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
22407
 
  }
22408
 
 
22409
 
  /// Evaluate order n derivatives of basis function i at given point in cell
22410
 
  virtual void evaluate_basis_derivatives(unsigned int i,
22411
 
                                          unsigned int n,
22412
 
                                          double* values,
22413
 
                                          const double* coordinates,
22414
 
                                          const ufc::cell& c) const
22415
 
  {
22416
 
    // Extract vertex coordinates
22417
 
    const double * const * element_coordinates = c.coordinates;
22418
 
    
22419
 
    // Compute Jacobian of affine map from reference cell
22420
 
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
22421
 
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
22422
 
    const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
22423
 
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
22424
 
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
22425
 
    const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
22426
 
    const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
22427
 
    const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
22428
 
    const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
22429
 
    
22430
 
    // Compute sub determinants
22431
 
    const double d00 = J_11*J_22 - J_12*J_21;
22432
 
    const double d01 = J_12*J_20 - J_10*J_22;
22433
 
    const double d02 = J_10*J_21 - J_11*J_20;
22434
 
    
22435
 
    const double d10 = J_02*J_21 - J_01*J_22;
22436
 
    const double d11 = J_00*J_22 - J_02*J_20;
22437
 
    const double d12 = J_01*J_20 - J_00*J_21;
22438
 
    
22439
 
    const double d20 = J_01*J_12 - J_02*J_11;
22440
 
    const double d21 = J_02*J_10 - J_00*J_12;
22441
 
    const double d22 = J_00*J_11 - J_01*J_10;
22442
 
    
22443
 
    // Compute determinant of Jacobian
22444
 
    double detJ = J_00*d00 + J_10*d10 + J_20*d20;
22445
 
    
22446
 
    // Compute inverse of Jacobian
22447
 
    
22448
 
    // Compute constants
22449
 
    const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
22450
 
                    + d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
22451
 
                    + d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
22452
 
    
22453
 
    const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
22454
 
                    + d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
22455
 
                    + d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
22456
 
    
22457
 
    const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
22458
 
                    + d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
22459
 
                    + d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
22460
 
    
22461
 
    // Get coordinates and map to the UFC reference element
22462
 
    double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
22463
 
    double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
22464
 
    double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
22465
 
    
22466
 
    // Map coordinates to the reference cube
22467
 
    if (std::abs(y + z - 1.0) < 1e-08)
22468
 
      x = 1.0;
22469
 
    else
22470
 
      x = -2.0 * x/(y + z - 1.0) - 1.0;
22471
 
    if (std::abs(z - 1.0) < 1e-08)
22472
 
      y = -1.0;
22473
 
    else
22474
 
      y = 2.0 * y/(1.0 - z) - 1.0;
22475
 
    z = 2.0 * z - 1.0;
22476
 
    
22477
 
    // Compute number of derivatives
22478
 
    unsigned int num_derivatives = 1;
22479
 
    
22480
 
    for (unsigned int j = 0; j < n; j++)
22481
 
      num_derivatives *= 3;
22482
 
    
22483
 
    
22484
 
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
22485
 
    unsigned int **combinations = new unsigned int *[num_derivatives];
22486
 
    
22487
 
    for (unsigned int j = 0; j < num_derivatives; j++)
22488
 
    {
22489
 
      combinations[j] = new unsigned int [n];
22490
 
      for (unsigned int k = 0; k < n; k++)
22491
 
        combinations[j][k] = 0;
22492
 
    }
22493
 
    
22494
 
    // Generate combinations of derivatives
22495
 
    for (unsigned int row = 1; row < num_derivatives; row++)
22496
 
    {
22497
 
      for (unsigned int num = 0; num < row; num++)
22498
 
      {
22499
 
        for (unsigned int col = n-1; col+1 > 0; col--)
22500
 
        {
22501
 
          if (combinations[row][col] + 1 > 2)
22502
 
            combinations[row][col] = 0;
22503
 
          else
22504
 
          {
22505
 
            combinations[row][col] += 1;
22506
 
            break;
22507
 
          }
22508
 
        }
22509
 
      }
22510
 
    }
22511
 
    
22512
 
    // Compute inverse of Jacobian
22513
 
    const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
22514
 
    
22515
 
    // Declare transformation matrix
22516
 
    // Declare pointer to two dimensional array and initialise
22517
 
    double **transform = new double *[num_derivatives];
22518
 
    
22519
 
    for (unsigned int j = 0; j < num_derivatives; j++)
22520
 
    {
22521
 
      transform[j] = new double [num_derivatives];
22522
 
      for (unsigned int k = 0; k < num_derivatives; k++)
22523
 
        transform[j][k] = 1;
22524
 
    }
22525
 
    
22526
 
    // Construct transformation matrix
22527
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22528
 
    {
22529
 
      for (unsigned int col = 0; col < num_derivatives; col++)
22530
 
      {
22531
 
        for (unsigned int k = 0; k < n; k++)
22532
 
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
22533
 
      }
22534
 
    }
22535
 
    
22536
 
    // Reset values
22537
 
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
22538
 
      values[j] = 0;
22539
 
    
22540
 
    // Map degree of freedom to element degree of freedom
22541
 
    const unsigned int dof = i;
22542
 
    
22543
 
    // Generate scalings
22544
 
    const double scalings_y_0 = 1;
22545
 
    const double scalings_z_0 = 1;
22546
 
    
22547
 
    // Compute psitilde_a
22548
 
    const double psitilde_a_0 = 1;
22549
 
    
22550
 
    // Compute psitilde_bs
22551
 
    const double psitilde_bs_0_0 = 1;
22552
 
    
22553
 
    // Compute psitilde_cs
22554
 
    const double psitilde_cs_00_0 = 1;
22555
 
    
22556
 
    // Compute basisvalues
22557
 
    const double basisvalue0 = 0.866025404*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
22558
 
    
22559
 
    // Table(s) of coefficients
22560
 
    static const double coefficients0[1][1] = \
22561
 
    {{1.15470054}};
22562
 
    
22563
 
    // Interesting (new) part
22564
 
    // Tables of derivatives of the polynomial base (transpose)
22565
 
    static const double dmats0[1][1] = \
22566
 
    {{0}};
22567
 
    
22568
 
    static const double dmats1[1][1] = \
22569
 
    {{0}};
22570
 
    
22571
 
    static const double dmats2[1][1] = \
22572
 
    {{0}};
22573
 
    
22574
 
    // Compute reference derivatives
22575
 
    // Declare pointer to array of derivatives on FIAT element
22576
 
    double *derivatives = new double [num_derivatives];
22577
 
    
22578
 
    // Declare coefficients
22579
 
    double coeff0_0 = 0;
22580
 
    
22581
 
    // Declare new coefficients
22582
 
    double new_coeff0_0 = 0;
22583
 
    
22584
 
    // Loop possible derivatives
22585
 
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
22586
 
    {
22587
 
      // Get values from coefficients array
22588
 
      new_coeff0_0 = coefficients0[dof][0];
22589
 
    
22590
 
      // Loop derivative order
22591
 
      for (unsigned int j = 0; j < n; j++)
22592
 
      {
22593
 
        // Update old coefficients
22594
 
        coeff0_0 = new_coeff0_0;
22595
 
    
22596
 
        if(combinations[deriv_num][j] == 0)
22597
 
        {
22598
 
          new_coeff0_0 = coeff0_0*dmats0[0][0];
22599
 
        }
22600
 
        if(combinations[deriv_num][j] == 1)
22601
 
        {
22602
 
          new_coeff0_0 = coeff0_0*dmats1[0][0];
22603
 
        }
22604
 
        if(combinations[deriv_num][j] == 2)
22605
 
        {
22606
 
          new_coeff0_0 = coeff0_0*dmats2[0][0];
22607
 
        }
22608
 
    
22609
 
      }
22610
 
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
22611
 
      derivatives[deriv_num] = new_coeff0_0*basisvalue0;
22612
 
    }
22613
 
    
22614
 
    // Transform derivatives back to physical element
22615
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22616
 
    {
22617
 
      for (unsigned int col = 0; col < num_derivatives; col++)
22618
 
      {
22619
 
        values[row] += transform[row][col]*derivatives[col];
22620
 
      }
22621
 
    }
22622
 
    // Delete pointer to array of derivatives on FIAT element
22623
 
    delete [] derivatives;
22624
 
    
22625
 
    // Delete pointer to array of combinations of derivatives and transform
22626
 
    for (unsigned int row = 0; row < num_derivatives; row++)
22627
 
    {
22628
 
      delete [] combinations[row];
22629
 
      delete [] transform[row];
22630
 
    }
22631
 
    
22632
 
    delete [] combinations;
22633
 
    delete [] transform;
22634
 
  }
22635
 
 
22636
 
  /// Evaluate order n derivatives of all basis functions at given point in cell
22637
 
  virtual void evaluate_basis_derivatives_all(unsigned int n,
22638
 
                                              double* values,
22639
 
                                              const double* coordinates,
22640
 
                                              const ufc::cell& c) const
22641
 
  {
22642
 
    throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
22643
 
  }
22644
 
 
22645
 
  /// Evaluate linear functional for dof i on the function f
22646
 
  virtual double evaluate_dof(unsigned int i,
22647
 
                              const ufc::function& f,
22648
 
                              const ufc::cell& c) const
22649
 
  {
22650
 
    // The reference points, direction and weights:
22651
 
    static const double X[1][1][3] = {{{0.25, 0.25, 0.25}}};
22652
 
    static const double W[1][1] = {{1}};
22653
 
    static const double D[1][1][1] = {{{1}}};
22654
 
    
22655
 
    const double * const * x = c.coordinates;
22656
 
    double result = 0.0;
22657
 
    // Iterate over the points:
22658
 
    // Evaluate basis functions for affine mapping
22659
 
    const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
22660
 
    const double w1 = X[i][0][0];
22661
 
    const double w2 = X[i][0][1];
22662
 
    const double w3 = X[i][0][2];
22663
 
    
22664
 
    // Compute affine mapping y = F(X)
22665
 
    double y[3];
22666
 
    y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
22667
 
    y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
22668
 
    y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
22669
 
    
22670
 
    // Evaluate function at physical points
22671
 
    double values[1];
22672
 
    f.evaluate(values, y, c);
22673
 
    
22674
 
    // Map function values using appropriate mapping
22675
 
    // Affine map: Do nothing
22676
 
    
22677
 
    // Note that we do not map the weights (yet).
22678
 
    
22679
 
    // Take directional components
22680
 
    for(int k = 0; k < 1; k++)
22681
 
      result += values[k]*D[i][0][k];
22682
 
    // Multiply by weights
22683
 
    result *= W[i][0];
22684
 
    
22685
 
    return result;
22686
 
  }
22687
 
 
22688
 
  /// Evaluate linear functionals for all dofs on the function f
22689
 
  virtual void evaluate_dofs(double* values,
22690
 
                             const ufc::function& f,
22691
 
                             const ufc::cell& c) const
22692
 
  {
22693
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
22694
 
  }
22695
 
 
22696
 
  /// Interpolate vertex values from dof values
22697
 
  virtual void interpolate_vertex_values(double* vertex_values,
22698
 
                                         const double* dof_values,
22699
 
                                         const ufc::cell& c) const
22700
 
  {
22701
 
    // Evaluate at vertices and use affine mapping
22702
 
    vertex_values[0] = dof_values[0];
22703
 
    vertex_values[1] = dof_values[0];
22704
 
    vertex_values[2] = dof_values[0];
22705
 
    vertex_values[3] = dof_values[0];
22706
 
  }
22707
 
 
22708
 
  /// Return the number of sub elements (for a mixed element)
22709
 
  virtual unsigned int num_sub_elements() const
22710
 
  {
22711
 
    return 1;
22712
 
  }
22713
 
 
22714
 
  /// Create a new finite element for sub element i (for a mixed element)
22715
 
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
22716
 
  {
22717
 
    return new hyperelasticity_1_finite_element_5();
22718
 
  }
22719
 
 
22720
 
};
22721
 
 
22722
 
/// This class defines the interface for a local-to-global mapping of
22723
 
/// degrees of freedom (dofs).
22724
 
 
22725
 
class hyperelasticity_1_dof_map_0_0: public ufc::dof_map
22726
 
{
22727
 
private:
22728
 
 
22729
 
  unsigned int __global_dimension;
22730
 
 
22731
 
public:
22732
 
 
22733
 
  /// Constructor
22734
 
  hyperelasticity_1_dof_map_0_0() : ufc::dof_map()
22735
 
  {
22736
 
    __global_dimension = 0;
22737
 
  }
22738
 
 
22739
 
  /// Destructor
22740
 
  virtual ~hyperelasticity_1_dof_map_0_0()
22741
 
  {
22742
 
    // Do nothing
22743
 
  }
22744
 
 
22745
 
  /// Return a string identifying the dof map
22746
 
  virtual const char* signature() const
22747
 
  {
22748
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
22749
 
  }
22750
 
 
22751
 
  /// Return true iff mesh entities of topological dimension d are needed
22752
 
  virtual bool needs_mesh_entities(unsigned int d) const
22753
 
  {
22754
 
    switch ( d )
22755
 
    {
22756
 
    case 0:
22757
 
      return true;
22758
 
      break;
22759
 
    case 1:
22760
 
      return false;
22761
 
      break;
22762
 
    case 2:
22763
 
      return false;
22764
 
      break;
22765
 
    case 3:
22766
 
      return false;
22767
 
      break;
22768
 
    }
22769
 
    return false;
22770
 
  }
22771
 
 
22772
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
22773
 
  virtual bool init_mesh(const ufc::mesh& m)
22774
 
  {
22775
 
    __global_dimension = m.num_entities[0];
22776
 
    return false;
22777
 
  }
22778
 
 
22779
 
  /// Initialize dof map for given cell
22780
 
  virtual void init_cell(const ufc::mesh& m,
22781
 
                         const ufc::cell& c)
22782
 
  {
22783
 
    // Do nothing
22784
 
  }
22785
 
 
22786
 
  /// Finish initialization of dof map for cells
22787
 
  virtual void init_cell_finalize()
22788
 
  {
22789
 
    // Do nothing
22790
 
  }
22791
 
 
22792
 
  /// Return the dimension of the global finite element function space
22793
 
  virtual unsigned int global_dimension() const
22794
 
  {
22795
 
    return __global_dimension;
22796
 
  }
22797
 
 
22798
 
  /// Return the dimension of the local finite element function space for a cell
22799
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
22800
 
  {
22801
 
    return 4;
22802
 
  }
22803
 
 
22804
 
  /// Return the maximum dimension of the local finite element function space
22805
 
  virtual unsigned int max_local_dimension() const
22806
 
  {
22807
 
    return 4;
22808
 
  }
22809
 
 
22810
 
  // Return the geometric dimension of the coordinates this dof map provides
22811
 
  virtual unsigned int geometric_dimension() const
22812
 
  {
22813
 
    return 3;
22814
 
  }
22815
 
 
22816
 
  /// Return the number of dofs on each cell facet
22817
 
  virtual unsigned int num_facet_dofs() const
22818
 
  {
22819
 
    return 3;
22820
 
  }
22821
 
 
22822
 
  /// Return the number of dofs associated with each cell entity of dimension d
22823
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
22824
 
  {
22825
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
22826
 
  }
22827
 
 
22828
 
  /// Tabulate the local-to-global mapping of dofs on a cell
22829
 
  virtual void tabulate_dofs(unsigned int* dofs,
22830
 
                             const ufc::mesh& m,
22831
 
                             const ufc::cell& c) const
22832
 
  {
22833
 
    dofs[0] = c.entity_indices[0][0];
22834
 
    dofs[1] = c.entity_indices[0][1];
22835
 
    dofs[2] = c.entity_indices[0][2];
22836
 
    dofs[3] = c.entity_indices[0][3];
22837
 
  }
22838
 
 
22839
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
22840
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
22841
 
                                   unsigned int facet) const
22842
 
  {
22843
 
    switch ( facet )
22844
 
    {
22845
 
    case 0:
22846
 
      dofs[0] = 1;
22847
 
      dofs[1] = 2;
22848
 
      dofs[2] = 3;
22849
 
      break;
22850
 
    case 1:
22851
 
      dofs[0] = 0;
22852
 
      dofs[1] = 2;
22853
 
      dofs[2] = 3;
22854
 
      break;
22855
 
    case 2:
22856
 
      dofs[0] = 0;
22857
 
      dofs[1] = 1;
22858
 
      dofs[2] = 3;
22859
 
      break;
22860
 
    case 3:
22861
 
      dofs[0] = 0;
22862
 
      dofs[1] = 1;
22863
 
      dofs[2] = 2;
22864
 
      break;
22865
 
    }
22866
 
  }
22867
 
 
22868
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
22869
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
22870
 
                                    unsigned int d, unsigned int i) const
22871
 
  {
22872
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
22873
 
  }
22874
 
 
22875
 
  /// Tabulate the coordinates of all dofs on a cell
22876
 
  virtual void tabulate_coordinates(double** coordinates,
22877
 
                                    const ufc::cell& c) const
22878
 
  {
22879
 
    const double * const * x = c.coordinates;
22880
 
    coordinates[0][0] = x[0][0];
22881
 
    coordinates[0][1] = x[0][1];
22882
 
    coordinates[0][2] = x[0][2];
22883
 
    coordinates[1][0] = x[1][0];
22884
 
    coordinates[1][1] = x[1][1];
22885
 
    coordinates[1][2] = x[1][2];
22886
 
    coordinates[2][0] = x[2][0];
22887
 
    coordinates[2][1] = x[2][1];
22888
 
    coordinates[2][2] = x[2][2];
22889
 
    coordinates[3][0] = x[3][0];
22890
 
    coordinates[3][1] = x[3][1];
22891
 
    coordinates[3][2] = x[3][2];
22892
 
  }
22893
 
 
22894
 
  /// Return the number of sub dof maps (for a mixed element)
22895
 
  virtual unsigned int num_sub_dof_maps() const
22896
 
  {
22897
 
    return 1;
22898
 
  }
22899
 
 
22900
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
22901
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
22902
 
  {
22903
 
    return new hyperelasticity_1_dof_map_0_0();
22904
 
  }
22905
 
 
22906
 
};
22907
 
 
22908
 
/// This class defines the interface for a local-to-global mapping of
22909
 
/// degrees of freedom (dofs).
22910
 
 
22911
 
class hyperelasticity_1_dof_map_0_1: public ufc::dof_map
22912
 
{
22913
 
private:
22914
 
 
22915
 
  unsigned int __global_dimension;
22916
 
 
22917
 
public:
22918
 
 
22919
 
  /// Constructor
22920
 
  hyperelasticity_1_dof_map_0_1() : ufc::dof_map()
22921
 
  {
22922
 
    __global_dimension = 0;
22923
 
  }
22924
 
 
22925
 
  /// Destructor
22926
 
  virtual ~hyperelasticity_1_dof_map_0_1()
22927
 
  {
22928
 
    // Do nothing
22929
 
  }
22930
 
 
22931
 
  /// Return a string identifying the dof map
22932
 
  virtual const char* signature() const
22933
 
  {
22934
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
22935
 
  }
22936
 
 
22937
 
  /// Return true iff mesh entities of topological dimension d are needed
22938
 
  virtual bool needs_mesh_entities(unsigned int d) const
22939
 
  {
22940
 
    switch ( d )
22941
 
    {
22942
 
    case 0:
22943
 
      return true;
22944
 
      break;
22945
 
    case 1:
22946
 
      return false;
22947
 
      break;
22948
 
    case 2:
22949
 
      return false;
22950
 
      break;
22951
 
    case 3:
22952
 
      return false;
22953
 
      break;
22954
 
    }
22955
 
    return false;
22956
 
  }
22957
 
 
22958
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
22959
 
  virtual bool init_mesh(const ufc::mesh& m)
22960
 
  {
22961
 
    __global_dimension = m.num_entities[0];
22962
 
    return false;
22963
 
  }
22964
 
 
22965
 
  /// Initialize dof map for given cell
22966
 
  virtual void init_cell(const ufc::mesh& m,
22967
 
                         const ufc::cell& c)
22968
 
  {
22969
 
    // Do nothing
22970
 
  }
22971
 
 
22972
 
  /// Finish initialization of dof map for cells
22973
 
  virtual void init_cell_finalize()
22974
 
  {
22975
 
    // Do nothing
22976
 
  }
22977
 
 
22978
 
  /// Return the dimension of the global finite element function space
22979
 
  virtual unsigned int global_dimension() const
22980
 
  {
22981
 
    return __global_dimension;
22982
 
  }
22983
 
 
22984
 
  /// Return the dimension of the local finite element function space for a cell
22985
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
22986
 
  {
22987
 
    return 4;
22988
 
  }
22989
 
 
22990
 
  /// Return the maximum dimension of the local finite element function space
22991
 
  virtual unsigned int max_local_dimension() const
22992
 
  {
22993
 
    return 4;
22994
 
  }
22995
 
 
22996
 
  // Return the geometric dimension of the coordinates this dof map provides
22997
 
  virtual unsigned int geometric_dimension() const
22998
 
  {
22999
 
    return 3;
23000
 
  }
23001
 
 
23002
 
  /// Return the number of dofs on each cell facet
23003
 
  virtual unsigned int num_facet_dofs() const
23004
 
  {
23005
 
    return 3;
23006
 
  }
23007
 
 
23008
 
  /// Return the number of dofs associated with each cell entity of dimension d
23009
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
23010
 
  {
23011
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23012
 
  }
23013
 
 
23014
 
  /// Tabulate the local-to-global mapping of dofs on a cell
23015
 
  virtual void tabulate_dofs(unsigned int* dofs,
23016
 
                             const ufc::mesh& m,
23017
 
                             const ufc::cell& c) const
23018
 
  {
23019
 
    dofs[0] = c.entity_indices[0][0];
23020
 
    dofs[1] = c.entity_indices[0][1];
23021
 
    dofs[2] = c.entity_indices[0][2];
23022
 
    dofs[3] = c.entity_indices[0][3];
23023
 
  }
23024
 
 
23025
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
23026
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
23027
 
                                   unsigned int facet) const
23028
 
  {
23029
 
    switch ( facet )
23030
 
    {
23031
 
    case 0:
23032
 
      dofs[0] = 1;
23033
 
      dofs[1] = 2;
23034
 
      dofs[2] = 3;
23035
 
      break;
23036
 
    case 1:
23037
 
      dofs[0] = 0;
23038
 
      dofs[1] = 2;
23039
 
      dofs[2] = 3;
23040
 
      break;
23041
 
    case 2:
23042
 
      dofs[0] = 0;
23043
 
      dofs[1] = 1;
23044
 
      dofs[2] = 3;
23045
 
      break;
23046
 
    case 3:
23047
 
      dofs[0] = 0;
23048
 
      dofs[1] = 1;
23049
 
      dofs[2] = 2;
23050
 
      break;
23051
 
    }
23052
 
  }
23053
 
 
23054
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
23055
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
23056
 
                                    unsigned int d, unsigned int i) const
23057
 
  {
23058
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23059
 
  }
23060
 
 
23061
 
  /// Tabulate the coordinates of all dofs on a cell
23062
 
  virtual void tabulate_coordinates(double** coordinates,
23063
 
                                    const ufc::cell& c) const
23064
 
  {
23065
 
    const double * const * x = c.coordinates;
23066
 
    coordinates[0][0] = x[0][0];
23067
 
    coordinates[0][1] = x[0][1];
23068
 
    coordinates[0][2] = x[0][2];
23069
 
    coordinates[1][0] = x[1][0];
23070
 
    coordinates[1][1] = x[1][1];
23071
 
    coordinates[1][2] = x[1][2];
23072
 
    coordinates[2][0] = x[2][0];
23073
 
    coordinates[2][1] = x[2][1];
23074
 
    coordinates[2][2] = x[2][2];
23075
 
    coordinates[3][0] = x[3][0];
23076
 
    coordinates[3][1] = x[3][1];
23077
 
    coordinates[3][2] = x[3][2];
23078
 
  }
23079
 
 
23080
 
  /// Return the number of sub dof maps (for a mixed element)
23081
 
  virtual unsigned int num_sub_dof_maps() const
23082
 
  {
23083
 
    return 1;
23084
 
  }
23085
 
 
23086
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
23087
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
23088
 
  {
23089
 
    return new hyperelasticity_1_dof_map_0_1();
23090
 
  }
23091
 
 
23092
 
};
23093
 
 
23094
 
/// This class defines the interface for a local-to-global mapping of
23095
 
/// degrees of freedom (dofs).
23096
 
 
23097
 
class hyperelasticity_1_dof_map_0_2: public ufc::dof_map
23098
 
{
23099
 
private:
23100
 
 
23101
 
  unsigned int __global_dimension;
23102
 
 
23103
 
public:
23104
 
 
23105
 
  /// Constructor
23106
 
  hyperelasticity_1_dof_map_0_2() : ufc::dof_map()
23107
 
  {
23108
 
    __global_dimension = 0;
23109
 
  }
23110
 
 
23111
 
  /// Destructor
23112
 
  virtual ~hyperelasticity_1_dof_map_0_2()
23113
 
  {
23114
 
    // Do nothing
23115
 
  }
23116
 
 
23117
 
  /// Return a string identifying the dof map
23118
 
  virtual const char* signature() const
23119
 
  {
23120
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
23121
 
  }
23122
 
 
23123
 
  /// Return true iff mesh entities of topological dimension d are needed
23124
 
  virtual bool needs_mesh_entities(unsigned int d) const
23125
 
  {
23126
 
    switch ( d )
23127
 
    {
23128
 
    case 0:
23129
 
      return true;
23130
 
      break;
23131
 
    case 1:
23132
 
      return false;
23133
 
      break;
23134
 
    case 2:
23135
 
      return false;
23136
 
      break;
23137
 
    case 3:
23138
 
      return false;
23139
 
      break;
23140
 
    }
23141
 
    return false;
23142
 
  }
23143
 
 
23144
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
23145
 
  virtual bool init_mesh(const ufc::mesh& m)
23146
 
  {
23147
 
    __global_dimension = m.num_entities[0];
23148
 
    return false;
23149
 
  }
23150
 
 
23151
 
  /// Initialize dof map for given cell
23152
 
  virtual void init_cell(const ufc::mesh& m,
23153
 
                         const ufc::cell& c)
23154
 
  {
23155
 
    // Do nothing
23156
 
  }
23157
 
 
23158
 
  /// Finish initialization of dof map for cells
23159
 
  virtual void init_cell_finalize()
23160
 
  {
23161
 
    // Do nothing
23162
 
  }
23163
 
 
23164
 
  /// Return the dimension of the global finite element function space
23165
 
  virtual unsigned int global_dimension() const
23166
 
  {
23167
 
    return __global_dimension;
23168
 
  }
23169
 
 
23170
 
  /// Return the dimension of the local finite element function space for a cell
23171
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
23172
 
  {
23173
 
    return 4;
23174
 
  }
23175
 
 
23176
 
  /// Return the maximum dimension of the local finite element function space
23177
 
  virtual unsigned int max_local_dimension() const
23178
 
  {
23179
 
    return 4;
23180
 
  }
23181
 
 
23182
 
  // Return the geometric dimension of the coordinates this dof map provides
23183
 
  virtual unsigned int geometric_dimension() const
23184
 
  {
23185
 
    return 3;
23186
 
  }
23187
 
 
23188
 
  /// Return the number of dofs on each cell facet
23189
 
  virtual unsigned int num_facet_dofs() const
23190
 
  {
23191
 
    return 3;
23192
 
  }
23193
 
 
23194
 
  /// Return the number of dofs associated with each cell entity of dimension d
23195
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
23196
 
  {
23197
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23198
 
  }
23199
 
 
23200
 
  /// Tabulate the local-to-global mapping of dofs on a cell
23201
 
  virtual void tabulate_dofs(unsigned int* dofs,
23202
 
                             const ufc::mesh& m,
23203
 
                             const ufc::cell& c) const
23204
 
  {
23205
 
    dofs[0] = c.entity_indices[0][0];
23206
 
    dofs[1] = c.entity_indices[0][1];
23207
 
    dofs[2] = c.entity_indices[0][2];
23208
 
    dofs[3] = c.entity_indices[0][3];
23209
 
  }
23210
 
 
23211
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
23212
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
23213
 
                                   unsigned int facet) const
23214
 
  {
23215
 
    switch ( facet )
23216
 
    {
23217
 
    case 0:
23218
 
      dofs[0] = 1;
23219
 
      dofs[1] = 2;
23220
 
      dofs[2] = 3;
23221
 
      break;
23222
 
    case 1:
23223
 
      dofs[0] = 0;
23224
 
      dofs[1] = 2;
23225
 
      dofs[2] = 3;
23226
 
      break;
23227
 
    case 2:
23228
 
      dofs[0] = 0;
23229
 
      dofs[1] = 1;
23230
 
      dofs[2] = 3;
23231
 
      break;
23232
 
    case 3:
23233
 
      dofs[0] = 0;
23234
 
      dofs[1] = 1;
23235
 
      dofs[2] = 2;
23236
 
      break;
23237
 
    }
23238
 
  }
23239
 
 
23240
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
23241
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
23242
 
                                    unsigned int d, unsigned int i) const
23243
 
  {
23244
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23245
 
  }
23246
 
 
23247
 
  /// Tabulate the coordinates of all dofs on a cell
23248
 
  virtual void tabulate_coordinates(double** coordinates,
23249
 
                                    const ufc::cell& c) const
23250
 
  {
23251
 
    const double * const * x = c.coordinates;
23252
 
    coordinates[0][0] = x[0][0];
23253
 
    coordinates[0][1] = x[0][1];
23254
 
    coordinates[0][2] = x[0][2];
23255
 
    coordinates[1][0] = x[1][0];
23256
 
    coordinates[1][1] = x[1][1];
23257
 
    coordinates[1][2] = x[1][2];
23258
 
    coordinates[2][0] = x[2][0];
23259
 
    coordinates[2][1] = x[2][1];
23260
 
    coordinates[2][2] = x[2][2];
23261
 
    coordinates[3][0] = x[3][0];
23262
 
    coordinates[3][1] = x[3][1];
23263
 
    coordinates[3][2] = x[3][2];
23264
 
  }
23265
 
 
23266
 
  /// Return the number of sub dof maps (for a mixed element)
23267
 
  virtual unsigned int num_sub_dof_maps() const
23268
 
  {
23269
 
    return 1;
23270
 
  }
23271
 
 
23272
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
23273
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
23274
 
  {
23275
 
    return new hyperelasticity_1_dof_map_0_2();
23276
 
  }
23277
 
 
23278
 
};
23279
 
 
23280
 
/// This class defines the interface for a local-to-global mapping of
23281
 
/// degrees of freedom (dofs).
23282
 
 
23283
 
class hyperelasticity_1_dof_map_0: public ufc::dof_map
23284
 
{
23285
 
private:
23286
 
 
23287
 
  unsigned int __global_dimension;
23288
 
 
23289
 
public:
23290
 
 
23291
 
  /// Constructor
23292
 
  hyperelasticity_1_dof_map_0() : ufc::dof_map()
23293
 
  {
23294
 
    __global_dimension = 0;
23295
 
  }
23296
 
 
23297
 
  /// Destructor
23298
 
  virtual ~hyperelasticity_1_dof_map_0()
23299
 
  {
23300
 
    // Do nothing
23301
 
  }
23302
 
 
23303
 
  /// Return a string identifying the dof map
23304
 
  virtual const char* signature() const
23305
 
  {
23306
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
23307
 
  }
23308
 
 
23309
 
  /// Return true iff mesh entities of topological dimension d are needed
23310
 
  virtual bool needs_mesh_entities(unsigned int d) const
23311
 
  {
23312
 
    switch ( d )
23313
 
    {
23314
 
    case 0:
23315
 
      return true;
23316
 
      break;
23317
 
    case 1:
23318
 
      return false;
23319
 
      break;
23320
 
    case 2:
23321
 
      return false;
23322
 
      break;
23323
 
    case 3:
23324
 
      return false;
23325
 
      break;
23326
 
    }
23327
 
    return false;
23328
 
  }
23329
 
 
23330
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
23331
 
  virtual bool init_mesh(const ufc::mesh& m)
23332
 
  {
23333
 
    __global_dimension = 3*m.num_entities[0];
23334
 
    return false;
23335
 
  }
23336
 
 
23337
 
  /// Initialize dof map for given cell
23338
 
  virtual void init_cell(const ufc::mesh& m,
23339
 
                         const ufc::cell& c)
23340
 
  {
23341
 
    // Do nothing
23342
 
  }
23343
 
 
23344
 
  /// Finish initialization of dof map for cells
23345
 
  virtual void init_cell_finalize()
23346
 
  {
23347
 
    // Do nothing
23348
 
  }
23349
 
 
23350
 
  /// Return the dimension of the global finite element function space
23351
 
  virtual unsigned int global_dimension() const
23352
 
  {
23353
 
    return __global_dimension;
23354
 
  }
23355
 
 
23356
 
  /// Return the dimension of the local finite element function space for a cell
23357
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
23358
 
  {
23359
 
    return 12;
23360
 
  }
23361
 
 
23362
 
  /// Return the maximum dimension of the local finite element function space
23363
 
  virtual unsigned int max_local_dimension() const
23364
 
  {
23365
 
    return 12;
23366
 
  }
23367
 
 
23368
 
  // Return the geometric dimension of the coordinates this dof map provides
23369
 
  virtual unsigned int geometric_dimension() const
23370
 
  {
23371
 
    return 3;
23372
 
  }
23373
 
 
23374
 
  /// Return the number of dofs on each cell facet
23375
 
  virtual unsigned int num_facet_dofs() const
23376
 
  {
23377
 
    return 9;
23378
 
  }
23379
 
 
23380
 
  /// Return the number of dofs associated with each cell entity of dimension d
23381
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
23382
 
  {
23383
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23384
 
  }
23385
 
 
23386
 
  /// Tabulate the local-to-global mapping of dofs on a cell
23387
 
  virtual void tabulate_dofs(unsigned int* dofs,
23388
 
                             const ufc::mesh& m,
23389
 
                             const ufc::cell& c) const
23390
 
  {
23391
 
    dofs[0] = c.entity_indices[0][0];
23392
 
    dofs[1] = c.entity_indices[0][1];
23393
 
    dofs[2] = c.entity_indices[0][2];
23394
 
    dofs[3] = c.entity_indices[0][3];
23395
 
    unsigned int offset = m.num_entities[0];
23396
 
    dofs[4] = offset + c.entity_indices[0][0];
23397
 
    dofs[5] = offset + c.entity_indices[0][1];
23398
 
    dofs[6] = offset + c.entity_indices[0][2];
23399
 
    dofs[7] = offset + c.entity_indices[0][3];
23400
 
    offset = offset + m.num_entities[0];
23401
 
    dofs[8] = offset + c.entity_indices[0][0];
23402
 
    dofs[9] = offset + c.entity_indices[0][1];
23403
 
    dofs[10] = offset + c.entity_indices[0][2];
23404
 
    dofs[11] = offset + c.entity_indices[0][3];
23405
 
  }
23406
 
 
23407
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
23408
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
23409
 
                                   unsigned int facet) const
23410
 
  {
23411
 
    switch ( facet )
23412
 
    {
23413
 
    case 0:
23414
 
      dofs[0] = 1;
23415
 
      dofs[1] = 2;
23416
 
      dofs[2] = 3;
23417
 
      dofs[3] = 5;
23418
 
      dofs[4] = 6;
23419
 
      dofs[5] = 7;
23420
 
      dofs[6] = 9;
23421
 
      dofs[7] = 10;
23422
 
      dofs[8] = 11;
23423
 
      break;
23424
 
    case 1:
23425
 
      dofs[0] = 0;
23426
 
      dofs[1] = 2;
23427
 
      dofs[2] = 3;
23428
 
      dofs[3] = 4;
23429
 
      dofs[4] = 6;
23430
 
      dofs[5] = 7;
23431
 
      dofs[6] = 8;
23432
 
      dofs[7] = 10;
23433
 
      dofs[8] = 11;
23434
 
      break;
23435
 
    case 2:
23436
 
      dofs[0] = 0;
23437
 
      dofs[1] = 1;
23438
 
      dofs[2] = 3;
23439
 
      dofs[3] = 4;
23440
 
      dofs[4] = 5;
23441
 
      dofs[5] = 7;
23442
 
      dofs[6] = 8;
23443
 
      dofs[7] = 9;
23444
 
      dofs[8] = 11;
23445
 
      break;
23446
 
    case 3:
23447
 
      dofs[0] = 0;
23448
 
      dofs[1] = 1;
23449
 
      dofs[2] = 2;
23450
 
      dofs[3] = 4;
23451
 
      dofs[4] = 5;
23452
 
      dofs[5] = 6;
23453
 
      dofs[6] = 8;
23454
 
      dofs[7] = 9;
23455
 
      dofs[8] = 10;
23456
 
      break;
23457
 
    }
23458
 
  }
23459
 
 
23460
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
23461
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
23462
 
                                    unsigned int d, unsigned int i) const
23463
 
  {
23464
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23465
 
  }
23466
 
 
23467
 
  /// Tabulate the coordinates of all dofs on a cell
23468
 
  virtual void tabulate_coordinates(double** coordinates,
23469
 
                                    const ufc::cell& c) const
23470
 
  {
23471
 
    const double * const * x = c.coordinates;
23472
 
    coordinates[0][0] = x[0][0];
23473
 
    coordinates[0][1] = x[0][1];
23474
 
    coordinates[0][2] = x[0][2];
23475
 
    coordinates[1][0] = x[1][0];
23476
 
    coordinates[1][1] = x[1][1];
23477
 
    coordinates[1][2] = x[1][2];
23478
 
    coordinates[2][0] = x[2][0];
23479
 
    coordinates[2][1] = x[2][1];
23480
 
    coordinates[2][2] = x[2][2];
23481
 
    coordinates[3][0] = x[3][0];
23482
 
    coordinates[3][1] = x[3][1];
23483
 
    coordinates[3][2] = x[3][2];
23484
 
    coordinates[4][0] = x[0][0];
23485
 
    coordinates[4][1] = x[0][1];
23486
 
    coordinates[4][2] = x[0][2];
23487
 
    coordinates[5][0] = x[1][0];
23488
 
    coordinates[5][1] = x[1][1];
23489
 
    coordinates[5][2] = x[1][2];
23490
 
    coordinates[6][0] = x[2][0];
23491
 
    coordinates[6][1] = x[2][1];
23492
 
    coordinates[6][2] = x[2][2];
23493
 
    coordinates[7][0] = x[3][0];
23494
 
    coordinates[7][1] = x[3][1];
23495
 
    coordinates[7][2] = x[3][2];
23496
 
    coordinates[8][0] = x[0][0];
23497
 
    coordinates[8][1] = x[0][1];
23498
 
    coordinates[8][2] = x[0][2];
23499
 
    coordinates[9][0] = x[1][0];
23500
 
    coordinates[9][1] = x[1][1];
23501
 
    coordinates[9][2] = x[1][2];
23502
 
    coordinates[10][0] = x[2][0];
23503
 
    coordinates[10][1] = x[2][1];
23504
 
    coordinates[10][2] = x[2][2];
23505
 
    coordinates[11][0] = x[3][0];
23506
 
    coordinates[11][1] = x[3][1];
23507
 
    coordinates[11][2] = x[3][2];
23508
 
  }
23509
 
 
23510
 
  /// Return the number of sub dof maps (for a mixed element)
23511
 
  virtual unsigned int num_sub_dof_maps() const
23512
 
  {
23513
 
    return 3;
23514
 
  }
23515
 
 
23516
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
23517
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
23518
 
  {
23519
 
    switch ( i )
23520
 
    {
23521
 
    case 0:
23522
 
      return new hyperelasticity_1_dof_map_0_0();
23523
 
      break;
23524
 
    case 1:
23525
 
      return new hyperelasticity_1_dof_map_0_1();
23526
 
      break;
23527
 
    case 2:
23528
 
      return new hyperelasticity_1_dof_map_0_2();
23529
 
      break;
23530
 
    }
23531
 
    return 0;
23532
 
  }
23533
 
 
23534
 
};
23535
 
 
23536
 
/// This class defines the interface for a local-to-global mapping of
23537
 
/// degrees of freedom (dofs).
23538
 
 
23539
 
class hyperelasticity_1_dof_map_1_0: public ufc::dof_map
23540
 
{
23541
 
private:
23542
 
 
23543
 
  unsigned int __global_dimension;
23544
 
 
23545
 
public:
23546
 
 
23547
 
  /// Constructor
23548
 
  hyperelasticity_1_dof_map_1_0() : ufc::dof_map()
23549
 
  {
23550
 
    __global_dimension = 0;
23551
 
  }
23552
 
 
23553
 
  /// Destructor
23554
 
  virtual ~hyperelasticity_1_dof_map_1_0()
23555
 
  {
23556
 
    // Do nothing
23557
 
  }
23558
 
 
23559
 
  /// Return a string identifying the dof map
23560
 
  virtual const char* signature() const
23561
 
  {
23562
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
23563
 
  }
23564
 
 
23565
 
  /// Return true iff mesh entities of topological dimension d are needed
23566
 
  virtual bool needs_mesh_entities(unsigned int d) const
23567
 
  {
23568
 
    switch ( d )
23569
 
    {
23570
 
    case 0:
23571
 
      return true;
23572
 
      break;
23573
 
    case 1:
23574
 
      return false;
23575
 
      break;
23576
 
    case 2:
23577
 
      return false;
23578
 
      break;
23579
 
    case 3:
23580
 
      return false;
23581
 
      break;
23582
 
    }
23583
 
    return false;
23584
 
  }
23585
 
 
23586
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
23587
 
  virtual bool init_mesh(const ufc::mesh& m)
23588
 
  {
23589
 
    __global_dimension = m.num_entities[0];
23590
 
    return false;
23591
 
  }
23592
 
 
23593
 
  /// Initialize dof map for given cell
23594
 
  virtual void init_cell(const ufc::mesh& m,
23595
 
                         const ufc::cell& c)
23596
 
  {
23597
 
    // Do nothing
23598
 
  }
23599
 
 
23600
 
  /// Finish initialization of dof map for cells
23601
 
  virtual void init_cell_finalize()
23602
 
  {
23603
 
    // Do nothing
23604
 
  }
23605
 
 
23606
 
  /// Return the dimension of the global finite element function space
23607
 
  virtual unsigned int global_dimension() const
23608
 
  {
23609
 
    return __global_dimension;
23610
 
  }
23611
 
 
23612
 
  /// Return the dimension of the local finite element function space for a cell
23613
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
23614
 
  {
23615
 
    return 4;
23616
 
  }
23617
 
 
23618
 
  /// Return the maximum dimension of the local finite element function space
23619
 
  virtual unsigned int max_local_dimension() const
23620
 
  {
23621
 
    return 4;
23622
 
  }
23623
 
 
23624
 
  // Return the geometric dimension of the coordinates this dof map provides
23625
 
  virtual unsigned int geometric_dimension() const
23626
 
  {
23627
 
    return 3;
23628
 
  }
23629
 
 
23630
 
  /// Return the number of dofs on each cell facet
23631
 
  virtual unsigned int num_facet_dofs() const
23632
 
  {
23633
 
    return 3;
23634
 
  }
23635
 
 
23636
 
  /// Return the number of dofs associated with each cell entity of dimension d
23637
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
23638
 
  {
23639
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23640
 
  }
23641
 
 
23642
 
  /// Tabulate the local-to-global mapping of dofs on a cell
23643
 
  virtual void tabulate_dofs(unsigned int* dofs,
23644
 
                             const ufc::mesh& m,
23645
 
                             const ufc::cell& c) const
23646
 
  {
23647
 
    dofs[0] = c.entity_indices[0][0];
23648
 
    dofs[1] = c.entity_indices[0][1];
23649
 
    dofs[2] = c.entity_indices[0][2];
23650
 
    dofs[3] = c.entity_indices[0][3];
23651
 
  }
23652
 
 
23653
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
23654
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
23655
 
                                   unsigned int facet) const
23656
 
  {
23657
 
    switch ( facet )
23658
 
    {
23659
 
    case 0:
23660
 
      dofs[0] = 1;
23661
 
      dofs[1] = 2;
23662
 
      dofs[2] = 3;
23663
 
      break;
23664
 
    case 1:
23665
 
      dofs[0] = 0;
23666
 
      dofs[1] = 2;
23667
 
      dofs[2] = 3;
23668
 
      break;
23669
 
    case 2:
23670
 
      dofs[0] = 0;
23671
 
      dofs[1] = 1;
23672
 
      dofs[2] = 3;
23673
 
      break;
23674
 
    case 3:
23675
 
      dofs[0] = 0;
23676
 
      dofs[1] = 1;
23677
 
      dofs[2] = 2;
23678
 
      break;
23679
 
    }
23680
 
  }
23681
 
 
23682
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
23683
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
23684
 
                                    unsigned int d, unsigned int i) const
23685
 
  {
23686
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23687
 
  }
23688
 
 
23689
 
  /// Tabulate the coordinates of all dofs on a cell
23690
 
  virtual void tabulate_coordinates(double** coordinates,
23691
 
                                    const ufc::cell& c) const
23692
 
  {
23693
 
    const double * const * x = c.coordinates;
23694
 
    coordinates[0][0] = x[0][0];
23695
 
    coordinates[0][1] = x[0][1];
23696
 
    coordinates[0][2] = x[0][2];
23697
 
    coordinates[1][0] = x[1][0];
23698
 
    coordinates[1][1] = x[1][1];
23699
 
    coordinates[1][2] = x[1][2];
23700
 
    coordinates[2][0] = x[2][0];
23701
 
    coordinates[2][1] = x[2][1];
23702
 
    coordinates[2][2] = x[2][2];
23703
 
    coordinates[3][0] = x[3][0];
23704
 
    coordinates[3][1] = x[3][1];
23705
 
    coordinates[3][2] = x[3][2];
23706
 
  }
23707
 
 
23708
 
  /// Return the number of sub dof maps (for a mixed element)
23709
 
  virtual unsigned int num_sub_dof_maps() const
23710
 
  {
23711
 
    return 1;
23712
 
  }
23713
 
 
23714
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
23715
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
23716
 
  {
23717
 
    return new hyperelasticity_1_dof_map_1_0();
23718
 
  }
23719
 
 
23720
 
};
23721
 
 
23722
 
/// This class defines the interface for a local-to-global mapping of
23723
 
/// degrees of freedom (dofs).
23724
 
 
23725
 
class hyperelasticity_1_dof_map_1_1: public ufc::dof_map
23726
 
{
23727
 
private:
23728
 
 
23729
 
  unsigned int __global_dimension;
23730
 
 
23731
 
public:
23732
 
 
23733
 
  /// Constructor
23734
 
  hyperelasticity_1_dof_map_1_1() : ufc::dof_map()
23735
 
  {
23736
 
    __global_dimension = 0;
23737
 
  }
23738
 
 
23739
 
  /// Destructor
23740
 
  virtual ~hyperelasticity_1_dof_map_1_1()
23741
 
  {
23742
 
    // Do nothing
23743
 
  }
23744
 
 
23745
 
  /// Return a string identifying the dof map
23746
 
  virtual const char* signature() const
23747
 
  {
23748
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
23749
 
  }
23750
 
 
23751
 
  /// Return true iff mesh entities of topological dimension d are needed
23752
 
  virtual bool needs_mesh_entities(unsigned int d) const
23753
 
  {
23754
 
    switch ( d )
23755
 
    {
23756
 
    case 0:
23757
 
      return true;
23758
 
      break;
23759
 
    case 1:
23760
 
      return false;
23761
 
      break;
23762
 
    case 2:
23763
 
      return false;
23764
 
      break;
23765
 
    case 3:
23766
 
      return false;
23767
 
      break;
23768
 
    }
23769
 
    return false;
23770
 
  }
23771
 
 
23772
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
23773
 
  virtual bool init_mesh(const ufc::mesh& m)
23774
 
  {
23775
 
    __global_dimension = m.num_entities[0];
23776
 
    return false;
23777
 
  }
23778
 
 
23779
 
  /// Initialize dof map for given cell
23780
 
  virtual void init_cell(const ufc::mesh& m,
23781
 
                         const ufc::cell& c)
23782
 
  {
23783
 
    // Do nothing
23784
 
  }
23785
 
 
23786
 
  /// Finish initialization of dof map for cells
23787
 
  virtual void init_cell_finalize()
23788
 
  {
23789
 
    // Do nothing
23790
 
  }
23791
 
 
23792
 
  /// Return the dimension of the global finite element function space
23793
 
  virtual unsigned int global_dimension() const
23794
 
  {
23795
 
    return __global_dimension;
23796
 
  }
23797
 
 
23798
 
  /// Return the dimension of the local finite element function space for a cell
23799
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
23800
 
  {
23801
 
    return 4;
23802
 
  }
23803
 
 
23804
 
  /// Return the maximum dimension of the local finite element function space
23805
 
  virtual unsigned int max_local_dimension() const
23806
 
  {
23807
 
    return 4;
23808
 
  }
23809
 
 
23810
 
  // Return the geometric dimension of the coordinates this dof map provides
23811
 
  virtual unsigned int geometric_dimension() const
23812
 
  {
23813
 
    return 3;
23814
 
  }
23815
 
 
23816
 
  /// Return the number of dofs on each cell facet
23817
 
  virtual unsigned int num_facet_dofs() const
23818
 
  {
23819
 
    return 3;
23820
 
  }
23821
 
 
23822
 
  /// Return the number of dofs associated with each cell entity of dimension d
23823
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
23824
 
  {
23825
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23826
 
  }
23827
 
 
23828
 
  /// Tabulate the local-to-global mapping of dofs on a cell
23829
 
  virtual void tabulate_dofs(unsigned int* dofs,
23830
 
                             const ufc::mesh& m,
23831
 
                             const ufc::cell& c) const
23832
 
  {
23833
 
    dofs[0] = c.entity_indices[0][0];
23834
 
    dofs[1] = c.entity_indices[0][1];
23835
 
    dofs[2] = c.entity_indices[0][2];
23836
 
    dofs[3] = c.entity_indices[0][3];
23837
 
  }
23838
 
 
23839
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
23840
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
23841
 
                                   unsigned int facet) const
23842
 
  {
23843
 
    switch ( facet )
23844
 
    {
23845
 
    case 0:
23846
 
      dofs[0] = 1;
23847
 
      dofs[1] = 2;
23848
 
      dofs[2] = 3;
23849
 
      break;
23850
 
    case 1:
23851
 
      dofs[0] = 0;
23852
 
      dofs[1] = 2;
23853
 
      dofs[2] = 3;
23854
 
      break;
23855
 
    case 2:
23856
 
      dofs[0] = 0;
23857
 
      dofs[1] = 1;
23858
 
      dofs[2] = 3;
23859
 
      break;
23860
 
    case 3:
23861
 
      dofs[0] = 0;
23862
 
      dofs[1] = 1;
23863
 
      dofs[2] = 2;
23864
 
      break;
23865
 
    }
23866
 
  }
23867
 
 
23868
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
23869
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
23870
 
                                    unsigned int d, unsigned int i) const
23871
 
  {
23872
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
23873
 
  }
23874
 
 
23875
 
  /// Tabulate the coordinates of all dofs on a cell
23876
 
  virtual void tabulate_coordinates(double** coordinates,
23877
 
                                    const ufc::cell& c) const
23878
 
  {
23879
 
    const double * const * x = c.coordinates;
23880
 
    coordinates[0][0] = x[0][0];
23881
 
    coordinates[0][1] = x[0][1];
23882
 
    coordinates[0][2] = x[0][2];
23883
 
    coordinates[1][0] = x[1][0];
23884
 
    coordinates[1][1] = x[1][1];
23885
 
    coordinates[1][2] = x[1][2];
23886
 
    coordinates[2][0] = x[2][0];
23887
 
    coordinates[2][1] = x[2][1];
23888
 
    coordinates[2][2] = x[2][2];
23889
 
    coordinates[3][0] = x[3][0];
23890
 
    coordinates[3][1] = x[3][1];
23891
 
    coordinates[3][2] = x[3][2];
23892
 
  }
23893
 
 
23894
 
  /// Return the number of sub dof maps (for a mixed element)
23895
 
  virtual unsigned int num_sub_dof_maps() const
23896
 
  {
23897
 
    return 1;
23898
 
  }
23899
 
 
23900
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
23901
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
23902
 
  {
23903
 
    return new hyperelasticity_1_dof_map_1_1();
23904
 
  }
23905
 
 
23906
 
};
23907
 
 
23908
 
/// This class defines the interface for a local-to-global mapping of
23909
 
/// degrees of freedom (dofs).
23910
 
 
23911
 
class hyperelasticity_1_dof_map_1_2: public ufc::dof_map
23912
 
{
23913
 
private:
23914
 
 
23915
 
  unsigned int __global_dimension;
23916
 
 
23917
 
public:
23918
 
 
23919
 
  /// Constructor
23920
 
  hyperelasticity_1_dof_map_1_2() : ufc::dof_map()
23921
 
  {
23922
 
    __global_dimension = 0;
23923
 
  }
23924
 
 
23925
 
  /// Destructor
23926
 
  virtual ~hyperelasticity_1_dof_map_1_2()
23927
 
  {
23928
 
    // Do nothing
23929
 
  }
23930
 
 
23931
 
  /// Return a string identifying the dof map
23932
 
  virtual const char* signature() const
23933
 
  {
23934
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
23935
 
  }
23936
 
 
23937
 
  /// Return true iff mesh entities of topological dimension d are needed
23938
 
  virtual bool needs_mesh_entities(unsigned int d) const
23939
 
  {
23940
 
    switch ( d )
23941
 
    {
23942
 
    case 0:
23943
 
      return true;
23944
 
      break;
23945
 
    case 1:
23946
 
      return false;
23947
 
      break;
23948
 
    case 2:
23949
 
      return false;
23950
 
      break;
23951
 
    case 3:
23952
 
      return false;
23953
 
      break;
23954
 
    }
23955
 
    return false;
23956
 
  }
23957
 
 
23958
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
23959
 
  virtual bool init_mesh(const ufc::mesh& m)
23960
 
  {
23961
 
    __global_dimension = m.num_entities[0];
23962
 
    return false;
23963
 
  }
23964
 
 
23965
 
  /// Initialize dof map for given cell
23966
 
  virtual void init_cell(const ufc::mesh& m,
23967
 
                         const ufc::cell& c)
23968
 
  {
23969
 
    // Do nothing
23970
 
  }
23971
 
 
23972
 
  /// Finish initialization of dof map for cells
23973
 
  virtual void init_cell_finalize()
23974
 
  {
23975
 
    // Do nothing
23976
 
  }
23977
 
 
23978
 
  /// Return the dimension of the global finite element function space
23979
 
  virtual unsigned int global_dimension() const
23980
 
  {
23981
 
    return __global_dimension;
23982
 
  }
23983
 
 
23984
 
  /// Return the dimension of the local finite element function space for a cell
23985
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
23986
 
  {
23987
 
    return 4;
23988
 
  }
23989
 
 
23990
 
  /// Return the maximum dimension of the local finite element function space
23991
 
  virtual unsigned int max_local_dimension() const
23992
 
  {
23993
 
    return 4;
23994
 
  }
23995
 
 
23996
 
  // Return the geometric dimension of the coordinates this dof map provides
23997
 
  virtual unsigned int geometric_dimension() const
23998
 
  {
23999
 
    return 3;
24000
 
  }
24001
 
 
24002
 
  /// Return the number of dofs on each cell facet
24003
 
  virtual unsigned int num_facet_dofs() const
24004
 
  {
24005
 
    return 3;
24006
 
  }
24007
 
 
24008
 
  /// Return the number of dofs associated with each cell entity of dimension d
24009
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
24010
 
  {
24011
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24012
 
  }
24013
 
 
24014
 
  /// Tabulate the local-to-global mapping of dofs on a cell
24015
 
  virtual void tabulate_dofs(unsigned int* dofs,
24016
 
                             const ufc::mesh& m,
24017
 
                             const ufc::cell& c) const
24018
 
  {
24019
 
    dofs[0] = c.entity_indices[0][0];
24020
 
    dofs[1] = c.entity_indices[0][1];
24021
 
    dofs[2] = c.entity_indices[0][2];
24022
 
    dofs[3] = c.entity_indices[0][3];
24023
 
  }
24024
 
 
24025
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
24026
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
24027
 
                                   unsigned int facet) const
24028
 
  {
24029
 
    switch ( facet )
24030
 
    {
24031
 
    case 0:
24032
 
      dofs[0] = 1;
24033
 
      dofs[1] = 2;
24034
 
      dofs[2] = 3;
24035
 
      break;
24036
 
    case 1:
24037
 
      dofs[0] = 0;
24038
 
      dofs[1] = 2;
24039
 
      dofs[2] = 3;
24040
 
      break;
24041
 
    case 2:
24042
 
      dofs[0] = 0;
24043
 
      dofs[1] = 1;
24044
 
      dofs[2] = 3;
24045
 
      break;
24046
 
    case 3:
24047
 
      dofs[0] = 0;
24048
 
      dofs[1] = 1;
24049
 
      dofs[2] = 2;
24050
 
      break;
24051
 
    }
24052
 
  }
24053
 
 
24054
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
24055
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
24056
 
                                    unsigned int d, unsigned int i) const
24057
 
  {
24058
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24059
 
  }
24060
 
 
24061
 
  /// Tabulate the coordinates of all dofs on a cell
24062
 
  virtual void tabulate_coordinates(double** coordinates,
24063
 
                                    const ufc::cell& c) const
24064
 
  {
24065
 
    const double * const * x = c.coordinates;
24066
 
    coordinates[0][0] = x[0][0];
24067
 
    coordinates[0][1] = x[0][1];
24068
 
    coordinates[0][2] = x[0][2];
24069
 
    coordinates[1][0] = x[1][0];
24070
 
    coordinates[1][1] = x[1][1];
24071
 
    coordinates[1][2] = x[1][2];
24072
 
    coordinates[2][0] = x[2][0];
24073
 
    coordinates[2][1] = x[2][1];
24074
 
    coordinates[2][2] = x[2][2];
24075
 
    coordinates[3][0] = x[3][0];
24076
 
    coordinates[3][1] = x[3][1];
24077
 
    coordinates[3][2] = x[3][2];
24078
 
  }
24079
 
 
24080
 
  /// Return the number of sub dof maps (for a mixed element)
24081
 
  virtual unsigned int num_sub_dof_maps() const
24082
 
  {
24083
 
    return 1;
24084
 
  }
24085
 
 
24086
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
24087
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
24088
 
  {
24089
 
    return new hyperelasticity_1_dof_map_1_2();
24090
 
  }
24091
 
 
24092
 
};
24093
 
 
24094
 
/// This class defines the interface for a local-to-global mapping of
24095
 
/// degrees of freedom (dofs).
24096
 
 
24097
 
class hyperelasticity_1_dof_map_1: public ufc::dof_map
24098
 
{
24099
 
private:
24100
 
 
24101
 
  unsigned int __global_dimension;
24102
 
 
24103
 
public:
24104
 
 
24105
 
  /// Constructor
24106
 
  hyperelasticity_1_dof_map_1() : ufc::dof_map()
24107
 
  {
24108
 
    __global_dimension = 0;
24109
 
  }
24110
 
 
24111
 
  /// Destructor
24112
 
  virtual ~hyperelasticity_1_dof_map_1()
24113
 
  {
24114
 
    // Do nothing
24115
 
  }
24116
 
 
24117
 
  /// Return a string identifying the dof map
24118
 
  virtual const char* signature() const
24119
 
  {
24120
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
24121
 
  }
24122
 
 
24123
 
  /// Return true iff mesh entities of topological dimension d are needed
24124
 
  virtual bool needs_mesh_entities(unsigned int d) const
24125
 
  {
24126
 
    switch ( d )
24127
 
    {
24128
 
    case 0:
24129
 
      return true;
24130
 
      break;
24131
 
    case 1:
24132
 
      return false;
24133
 
      break;
24134
 
    case 2:
24135
 
      return false;
24136
 
      break;
24137
 
    case 3:
24138
 
      return false;
24139
 
      break;
24140
 
    }
24141
 
    return false;
24142
 
  }
24143
 
 
24144
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
24145
 
  virtual bool init_mesh(const ufc::mesh& m)
24146
 
  {
24147
 
    __global_dimension = 3*m.num_entities[0];
24148
 
    return false;
24149
 
  }
24150
 
 
24151
 
  /// Initialize dof map for given cell
24152
 
  virtual void init_cell(const ufc::mesh& m,
24153
 
                         const ufc::cell& c)
24154
 
  {
24155
 
    // Do nothing
24156
 
  }
24157
 
 
24158
 
  /// Finish initialization of dof map for cells
24159
 
  virtual void init_cell_finalize()
24160
 
  {
24161
 
    // Do nothing
24162
 
  }
24163
 
 
24164
 
  /// Return the dimension of the global finite element function space
24165
 
  virtual unsigned int global_dimension() const
24166
 
  {
24167
 
    return __global_dimension;
24168
 
  }
24169
 
 
24170
 
  /// Return the dimension of the local finite element function space for a cell
24171
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
24172
 
  {
24173
 
    return 12;
24174
 
  }
24175
 
 
24176
 
  /// Return the maximum dimension of the local finite element function space
24177
 
  virtual unsigned int max_local_dimension() const
24178
 
  {
24179
 
    return 12;
24180
 
  }
24181
 
 
24182
 
  // Return the geometric dimension of the coordinates this dof map provides
24183
 
  virtual unsigned int geometric_dimension() const
24184
 
  {
24185
 
    return 3;
24186
 
  }
24187
 
 
24188
 
  /// Return the number of dofs on each cell facet
24189
 
  virtual unsigned int num_facet_dofs() const
24190
 
  {
24191
 
    return 9;
24192
 
  }
24193
 
 
24194
 
  /// Return the number of dofs associated with each cell entity of dimension d
24195
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
24196
 
  {
24197
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24198
 
  }
24199
 
 
24200
 
  /// Tabulate the local-to-global mapping of dofs on a cell
24201
 
  virtual void tabulate_dofs(unsigned int* dofs,
24202
 
                             const ufc::mesh& m,
24203
 
                             const ufc::cell& c) const
24204
 
  {
24205
 
    dofs[0] = c.entity_indices[0][0];
24206
 
    dofs[1] = c.entity_indices[0][1];
24207
 
    dofs[2] = c.entity_indices[0][2];
24208
 
    dofs[3] = c.entity_indices[0][3];
24209
 
    unsigned int offset = m.num_entities[0];
24210
 
    dofs[4] = offset + c.entity_indices[0][0];
24211
 
    dofs[5] = offset + c.entity_indices[0][1];
24212
 
    dofs[6] = offset + c.entity_indices[0][2];
24213
 
    dofs[7] = offset + c.entity_indices[0][3];
24214
 
    offset = offset + m.num_entities[0];
24215
 
    dofs[8] = offset + c.entity_indices[0][0];
24216
 
    dofs[9] = offset + c.entity_indices[0][1];
24217
 
    dofs[10] = offset + c.entity_indices[0][2];
24218
 
    dofs[11] = offset + c.entity_indices[0][3];
24219
 
  }
24220
 
 
24221
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
24222
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
24223
 
                                   unsigned int facet) const
24224
 
  {
24225
 
    switch ( facet )
24226
 
    {
24227
 
    case 0:
24228
 
      dofs[0] = 1;
24229
 
      dofs[1] = 2;
24230
 
      dofs[2] = 3;
24231
 
      dofs[3] = 5;
24232
 
      dofs[4] = 6;
24233
 
      dofs[5] = 7;
24234
 
      dofs[6] = 9;
24235
 
      dofs[7] = 10;
24236
 
      dofs[8] = 11;
24237
 
      break;
24238
 
    case 1:
24239
 
      dofs[0] = 0;
24240
 
      dofs[1] = 2;
24241
 
      dofs[2] = 3;
24242
 
      dofs[3] = 4;
24243
 
      dofs[4] = 6;
24244
 
      dofs[5] = 7;
24245
 
      dofs[6] = 8;
24246
 
      dofs[7] = 10;
24247
 
      dofs[8] = 11;
24248
 
      break;
24249
 
    case 2:
24250
 
      dofs[0] = 0;
24251
 
      dofs[1] = 1;
24252
 
      dofs[2] = 3;
24253
 
      dofs[3] = 4;
24254
 
      dofs[4] = 5;
24255
 
      dofs[5] = 7;
24256
 
      dofs[6] = 8;
24257
 
      dofs[7] = 9;
24258
 
      dofs[8] = 11;
24259
 
      break;
24260
 
    case 3:
24261
 
      dofs[0] = 0;
24262
 
      dofs[1] = 1;
24263
 
      dofs[2] = 2;
24264
 
      dofs[3] = 4;
24265
 
      dofs[4] = 5;
24266
 
      dofs[5] = 6;
24267
 
      dofs[6] = 8;
24268
 
      dofs[7] = 9;
24269
 
      dofs[8] = 10;
24270
 
      break;
24271
 
    }
24272
 
  }
24273
 
 
24274
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
24275
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
24276
 
                                    unsigned int d, unsigned int i) const
24277
 
  {
24278
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24279
 
  }
24280
 
 
24281
 
  /// Tabulate the coordinates of all dofs on a cell
24282
 
  virtual void tabulate_coordinates(double** coordinates,
24283
 
                                    const ufc::cell& c) const
24284
 
  {
24285
 
    const double * const * x = c.coordinates;
24286
 
    coordinates[0][0] = x[0][0];
24287
 
    coordinates[0][1] = x[0][1];
24288
 
    coordinates[0][2] = x[0][2];
24289
 
    coordinates[1][0] = x[1][0];
24290
 
    coordinates[1][1] = x[1][1];
24291
 
    coordinates[1][2] = x[1][2];
24292
 
    coordinates[2][0] = x[2][0];
24293
 
    coordinates[2][1] = x[2][1];
24294
 
    coordinates[2][2] = x[2][2];
24295
 
    coordinates[3][0] = x[3][0];
24296
 
    coordinates[3][1] = x[3][1];
24297
 
    coordinates[3][2] = x[3][2];
24298
 
    coordinates[4][0] = x[0][0];
24299
 
    coordinates[4][1] = x[0][1];
24300
 
    coordinates[4][2] = x[0][2];
24301
 
    coordinates[5][0] = x[1][0];
24302
 
    coordinates[5][1] = x[1][1];
24303
 
    coordinates[5][2] = x[1][2];
24304
 
    coordinates[6][0] = x[2][0];
24305
 
    coordinates[6][1] = x[2][1];
24306
 
    coordinates[6][2] = x[2][2];
24307
 
    coordinates[7][0] = x[3][0];
24308
 
    coordinates[7][1] = x[3][1];
24309
 
    coordinates[7][2] = x[3][2];
24310
 
    coordinates[8][0] = x[0][0];
24311
 
    coordinates[8][1] = x[0][1];
24312
 
    coordinates[8][2] = x[0][2];
24313
 
    coordinates[9][0] = x[1][0];
24314
 
    coordinates[9][1] = x[1][1];
24315
 
    coordinates[9][2] = x[1][2];
24316
 
    coordinates[10][0] = x[2][0];
24317
 
    coordinates[10][1] = x[2][1];
24318
 
    coordinates[10][2] = x[2][2];
24319
 
    coordinates[11][0] = x[3][0];
24320
 
    coordinates[11][1] = x[3][1];
24321
 
    coordinates[11][2] = x[3][2];
24322
 
  }
24323
 
 
24324
 
  /// Return the number of sub dof maps (for a mixed element)
24325
 
  virtual unsigned int num_sub_dof_maps() const
24326
 
  {
24327
 
    return 3;
24328
 
  }
24329
 
 
24330
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
24331
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
24332
 
  {
24333
 
    switch ( i )
24334
 
    {
24335
 
    case 0:
24336
 
      return new hyperelasticity_1_dof_map_1_0();
24337
 
      break;
24338
 
    case 1:
24339
 
      return new hyperelasticity_1_dof_map_1_1();
24340
 
      break;
24341
 
    case 2:
24342
 
      return new hyperelasticity_1_dof_map_1_2();
24343
 
      break;
24344
 
    }
24345
 
    return 0;
24346
 
  }
24347
 
 
24348
 
};
24349
 
 
24350
 
/// This class defines the interface for a local-to-global mapping of
24351
 
/// degrees of freedom (dofs).
24352
 
 
24353
 
class hyperelasticity_1_dof_map_2_0: public ufc::dof_map
24354
 
{
24355
 
private:
24356
 
 
24357
 
  unsigned int __global_dimension;
24358
 
 
24359
 
public:
24360
 
 
24361
 
  /// Constructor
24362
 
  hyperelasticity_1_dof_map_2_0() : ufc::dof_map()
24363
 
  {
24364
 
    __global_dimension = 0;
24365
 
  }
24366
 
 
24367
 
  /// Destructor
24368
 
  virtual ~hyperelasticity_1_dof_map_2_0()
24369
 
  {
24370
 
    // Do nothing
24371
 
  }
24372
 
 
24373
 
  /// Return a string identifying the dof map
24374
 
  virtual const char* signature() const
24375
 
  {
24376
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
24377
 
  }
24378
 
 
24379
 
  /// Return true iff mesh entities of topological dimension d are needed
24380
 
  virtual bool needs_mesh_entities(unsigned int d) const
24381
 
  {
24382
 
    switch ( d )
24383
 
    {
24384
 
    case 0:
24385
 
      return true;
24386
 
      break;
24387
 
    case 1:
24388
 
      return false;
24389
 
      break;
24390
 
    case 2:
24391
 
      return false;
24392
 
      break;
24393
 
    case 3:
24394
 
      return false;
24395
 
      break;
24396
 
    }
24397
 
    return false;
24398
 
  }
24399
 
 
24400
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
24401
 
  virtual bool init_mesh(const ufc::mesh& m)
24402
 
  {
24403
 
    __global_dimension = m.num_entities[0];
24404
 
    return false;
24405
 
  }
24406
 
 
24407
 
  /// Initialize dof map for given cell
24408
 
  virtual void init_cell(const ufc::mesh& m,
24409
 
                         const ufc::cell& c)
24410
 
  {
24411
 
    // Do nothing
24412
 
  }
24413
 
 
24414
 
  /// Finish initialization of dof map for cells
24415
 
  virtual void init_cell_finalize()
24416
 
  {
24417
 
    // Do nothing
24418
 
  }
24419
 
 
24420
 
  /// Return the dimension of the global finite element function space
24421
 
  virtual unsigned int global_dimension() const
24422
 
  {
24423
 
    return __global_dimension;
24424
 
  }
24425
 
 
24426
 
  /// Return the dimension of the local finite element function space for a cell
24427
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
24428
 
  {
24429
 
    return 4;
24430
 
  }
24431
 
 
24432
 
  /// Return the maximum dimension of the local finite element function space
24433
 
  virtual unsigned int max_local_dimension() const
24434
 
  {
24435
 
    return 4;
24436
 
  }
24437
 
 
24438
 
  // Return the geometric dimension of the coordinates this dof map provides
24439
 
  virtual unsigned int geometric_dimension() const
24440
 
  {
24441
 
    return 3;
24442
 
  }
24443
 
 
24444
 
  /// Return the number of dofs on each cell facet
24445
 
  virtual unsigned int num_facet_dofs() const
24446
 
  {
24447
 
    return 3;
24448
 
  }
24449
 
 
24450
 
  /// Return the number of dofs associated with each cell entity of dimension d
24451
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
24452
 
  {
24453
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24454
 
  }
24455
 
 
24456
 
  /// Tabulate the local-to-global mapping of dofs on a cell
24457
 
  virtual void tabulate_dofs(unsigned int* dofs,
24458
 
                             const ufc::mesh& m,
24459
 
                             const ufc::cell& c) const
24460
 
  {
24461
 
    dofs[0] = c.entity_indices[0][0];
24462
 
    dofs[1] = c.entity_indices[0][1];
24463
 
    dofs[2] = c.entity_indices[0][2];
24464
 
    dofs[3] = c.entity_indices[0][3];
24465
 
  }
24466
 
 
24467
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
24468
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
24469
 
                                   unsigned int facet) const
24470
 
  {
24471
 
    switch ( facet )
24472
 
    {
24473
 
    case 0:
24474
 
      dofs[0] = 1;
24475
 
      dofs[1] = 2;
24476
 
      dofs[2] = 3;
24477
 
      break;
24478
 
    case 1:
24479
 
      dofs[0] = 0;
24480
 
      dofs[1] = 2;
24481
 
      dofs[2] = 3;
24482
 
      break;
24483
 
    case 2:
24484
 
      dofs[0] = 0;
24485
 
      dofs[1] = 1;
24486
 
      dofs[2] = 3;
24487
 
      break;
24488
 
    case 3:
24489
 
      dofs[0] = 0;
24490
 
      dofs[1] = 1;
24491
 
      dofs[2] = 2;
24492
 
      break;
24493
 
    }
24494
 
  }
24495
 
 
24496
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
24497
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
24498
 
                                    unsigned int d, unsigned int i) const
24499
 
  {
24500
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24501
 
  }
24502
 
 
24503
 
  /// Tabulate the coordinates of all dofs on a cell
24504
 
  virtual void tabulate_coordinates(double** coordinates,
24505
 
                                    const ufc::cell& c) const
24506
 
  {
24507
 
    const double * const * x = c.coordinates;
24508
 
    coordinates[0][0] = x[0][0];
24509
 
    coordinates[0][1] = x[0][1];
24510
 
    coordinates[0][2] = x[0][2];
24511
 
    coordinates[1][0] = x[1][0];
24512
 
    coordinates[1][1] = x[1][1];
24513
 
    coordinates[1][2] = x[1][2];
24514
 
    coordinates[2][0] = x[2][0];
24515
 
    coordinates[2][1] = x[2][1];
24516
 
    coordinates[2][2] = x[2][2];
24517
 
    coordinates[3][0] = x[3][0];
24518
 
    coordinates[3][1] = x[3][1];
24519
 
    coordinates[3][2] = x[3][2];
24520
 
  }
24521
 
 
24522
 
  /// Return the number of sub dof maps (for a mixed element)
24523
 
  virtual unsigned int num_sub_dof_maps() const
24524
 
  {
24525
 
    return 1;
24526
 
  }
24527
 
 
24528
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
24529
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
24530
 
  {
24531
 
    return new hyperelasticity_1_dof_map_2_0();
24532
 
  }
24533
 
 
24534
 
};
24535
 
 
24536
 
/// This class defines the interface for a local-to-global mapping of
24537
 
/// degrees of freedom (dofs).
24538
 
 
24539
 
class hyperelasticity_1_dof_map_2_1: public ufc::dof_map
24540
 
{
24541
 
private:
24542
 
 
24543
 
  unsigned int __global_dimension;
24544
 
 
24545
 
public:
24546
 
 
24547
 
  /// Constructor
24548
 
  hyperelasticity_1_dof_map_2_1() : ufc::dof_map()
24549
 
  {
24550
 
    __global_dimension = 0;
24551
 
  }
24552
 
 
24553
 
  /// Destructor
24554
 
  virtual ~hyperelasticity_1_dof_map_2_1()
24555
 
  {
24556
 
    // Do nothing
24557
 
  }
24558
 
 
24559
 
  /// Return a string identifying the dof map
24560
 
  virtual const char* signature() const
24561
 
  {
24562
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
24563
 
  }
24564
 
 
24565
 
  /// Return true iff mesh entities of topological dimension d are needed
24566
 
  virtual bool needs_mesh_entities(unsigned int d) const
24567
 
  {
24568
 
    switch ( d )
24569
 
    {
24570
 
    case 0:
24571
 
      return true;
24572
 
      break;
24573
 
    case 1:
24574
 
      return false;
24575
 
      break;
24576
 
    case 2:
24577
 
      return false;
24578
 
      break;
24579
 
    case 3:
24580
 
      return false;
24581
 
      break;
24582
 
    }
24583
 
    return false;
24584
 
  }
24585
 
 
24586
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
24587
 
  virtual bool init_mesh(const ufc::mesh& m)
24588
 
  {
24589
 
    __global_dimension = m.num_entities[0];
24590
 
    return false;
24591
 
  }
24592
 
 
24593
 
  /// Initialize dof map for given cell
24594
 
  virtual void init_cell(const ufc::mesh& m,
24595
 
                         const ufc::cell& c)
24596
 
  {
24597
 
    // Do nothing
24598
 
  }
24599
 
 
24600
 
  /// Finish initialization of dof map for cells
24601
 
  virtual void init_cell_finalize()
24602
 
  {
24603
 
    // Do nothing
24604
 
  }
24605
 
 
24606
 
  /// Return the dimension of the global finite element function space
24607
 
  virtual unsigned int global_dimension() const
24608
 
  {
24609
 
    return __global_dimension;
24610
 
  }
24611
 
 
24612
 
  /// Return the dimension of the local finite element function space for a cell
24613
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
24614
 
  {
24615
 
    return 4;
24616
 
  }
24617
 
 
24618
 
  /// Return the maximum dimension of the local finite element function space
24619
 
  virtual unsigned int max_local_dimension() const
24620
 
  {
24621
 
    return 4;
24622
 
  }
24623
 
 
24624
 
  // Return the geometric dimension of the coordinates this dof map provides
24625
 
  virtual unsigned int geometric_dimension() const
24626
 
  {
24627
 
    return 3;
24628
 
  }
24629
 
 
24630
 
  /// Return the number of dofs on each cell facet
24631
 
  virtual unsigned int num_facet_dofs() const
24632
 
  {
24633
 
    return 3;
24634
 
  }
24635
 
 
24636
 
  /// Return the number of dofs associated with each cell entity of dimension d
24637
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
24638
 
  {
24639
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24640
 
  }
24641
 
 
24642
 
  /// Tabulate the local-to-global mapping of dofs on a cell
24643
 
  virtual void tabulate_dofs(unsigned int* dofs,
24644
 
                             const ufc::mesh& m,
24645
 
                             const ufc::cell& c) const
24646
 
  {
24647
 
    dofs[0] = c.entity_indices[0][0];
24648
 
    dofs[1] = c.entity_indices[0][1];
24649
 
    dofs[2] = c.entity_indices[0][2];
24650
 
    dofs[3] = c.entity_indices[0][3];
24651
 
  }
24652
 
 
24653
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
24654
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
24655
 
                                   unsigned int facet) const
24656
 
  {
24657
 
    switch ( facet )
24658
 
    {
24659
 
    case 0:
24660
 
      dofs[0] = 1;
24661
 
      dofs[1] = 2;
24662
 
      dofs[2] = 3;
24663
 
      break;
24664
 
    case 1:
24665
 
      dofs[0] = 0;
24666
 
      dofs[1] = 2;
24667
 
      dofs[2] = 3;
24668
 
      break;
24669
 
    case 2:
24670
 
      dofs[0] = 0;
24671
 
      dofs[1] = 1;
24672
 
      dofs[2] = 3;
24673
 
      break;
24674
 
    case 3:
24675
 
      dofs[0] = 0;
24676
 
      dofs[1] = 1;
24677
 
      dofs[2] = 2;
24678
 
      break;
24679
 
    }
24680
 
  }
24681
 
 
24682
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
24683
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
24684
 
                                    unsigned int d, unsigned int i) const
24685
 
  {
24686
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24687
 
  }
24688
 
 
24689
 
  /// Tabulate the coordinates of all dofs on a cell
24690
 
  virtual void tabulate_coordinates(double** coordinates,
24691
 
                                    const ufc::cell& c) const
24692
 
  {
24693
 
    const double * const * x = c.coordinates;
24694
 
    coordinates[0][0] = x[0][0];
24695
 
    coordinates[0][1] = x[0][1];
24696
 
    coordinates[0][2] = x[0][2];
24697
 
    coordinates[1][0] = x[1][0];
24698
 
    coordinates[1][1] = x[1][1];
24699
 
    coordinates[1][2] = x[1][2];
24700
 
    coordinates[2][0] = x[2][0];
24701
 
    coordinates[2][1] = x[2][1];
24702
 
    coordinates[2][2] = x[2][2];
24703
 
    coordinates[3][0] = x[3][0];
24704
 
    coordinates[3][1] = x[3][1];
24705
 
    coordinates[3][2] = x[3][2];
24706
 
  }
24707
 
 
24708
 
  /// Return the number of sub dof maps (for a mixed element)
24709
 
  virtual unsigned int num_sub_dof_maps() const
24710
 
  {
24711
 
    return 1;
24712
 
  }
24713
 
 
24714
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
24715
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
24716
 
  {
24717
 
    return new hyperelasticity_1_dof_map_2_1();
24718
 
  }
24719
 
 
24720
 
};
24721
 
 
24722
 
/// This class defines the interface for a local-to-global mapping of
24723
 
/// degrees of freedom (dofs).
24724
 
 
24725
 
class hyperelasticity_1_dof_map_2_2: public ufc::dof_map
24726
 
{
24727
 
private:
24728
 
 
24729
 
  unsigned int __global_dimension;
24730
 
 
24731
 
public:
24732
 
 
24733
 
  /// Constructor
24734
 
  hyperelasticity_1_dof_map_2_2() : ufc::dof_map()
24735
 
  {
24736
 
    __global_dimension = 0;
24737
 
  }
24738
 
 
24739
 
  /// Destructor
24740
 
  virtual ~hyperelasticity_1_dof_map_2_2()
24741
 
  {
24742
 
    // Do nothing
24743
 
  }
24744
 
 
24745
 
  /// Return a string identifying the dof map
24746
 
  virtual const char* signature() const
24747
 
  {
24748
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
24749
 
  }
24750
 
 
24751
 
  /// Return true iff mesh entities of topological dimension d are needed
24752
 
  virtual bool needs_mesh_entities(unsigned int d) const
24753
 
  {
24754
 
    switch ( d )
24755
 
    {
24756
 
    case 0:
24757
 
      return true;
24758
 
      break;
24759
 
    case 1:
24760
 
      return false;
24761
 
      break;
24762
 
    case 2:
24763
 
      return false;
24764
 
      break;
24765
 
    case 3:
24766
 
      return false;
24767
 
      break;
24768
 
    }
24769
 
    return false;
24770
 
  }
24771
 
 
24772
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
24773
 
  virtual bool init_mesh(const ufc::mesh& m)
24774
 
  {
24775
 
    __global_dimension = m.num_entities[0];
24776
 
    return false;
24777
 
  }
24778
 
 
24779
 
  /// Initialize dof map for given cell
24780
 
  virtual void init_cell(const ufc::mesh& m,
24781
 
                         const ufc::cell& c)
24782
 
  {
24783
 
    // Do nothing
24784
 
  }
24785
 
 
24786
 
  /// Finish initialization of dof map for cells
24787
 
  virtual void init_cell_finalize()
24788
 
  {
24789
 
    // Do nothing
24790
 
  }
24791
 
 
24792
 
  /// Return the dimension of the global finite element function space
24793
 
  virtual unsigned int global_dimension() const
24794
 
  {
24795
 
    return __global_dimension;
24796
 
  }
24797
 
 
24798
 
  /// Return the dimension of the local finite element function space for a cell
24799
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
24800
 
  {
24801
 
    return 4;
24802
 
  }
24803
 
 
24804
 
  /// Return the maximum dimension of the local finite element function space
24805
 
  virtual unsigned int max_local_dimension() const
24806
 
  {
24807
 
    return 4;
24808
 
  }
24809
 
 
24810
 
  // Return the geometric dimension of the coordinates this dof map provides
24811
 
  virtual unsigned int geometric_dimension() const
24812
 
  {
24813
 
    return 3;
24814
 
  }
24815
 
 
24816
 
  /// Return the number of dofs on each cell facet
24817
 
  virtual unsigned int num_facet_dofs() const
24818
 
  {
24819
 
    return 3;
24820
 
  }
24821
 
 
24822
 
  /// Return the number of dofs associated with each cell entity of dimension d
24823
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
24824
 
  {
24825
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24826
 
  }
24827
 
 
24828
 
  /// Tabulate the local-to-global mapping of dofs on a cell
24829
 
  virtual void tabulate_dofs(unsigned int* dofs,
24830
 
                             const ufc::mesh& m,
24831
 
                             const ufc::cell& c) const
24832
 
  {
24833
 
    dofs[0] = c.entity_indices[0][0];
24834
 
    dofs[1] = c.entity_indices[0][1];
24835
 
    dofs[2] = c.entity_indices[0][2];
24836
 
    dofs[3] = c.entity_indices[0][3];
24837
 
  }
24838
 
 
24839
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
24840
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
24841
 
                                   unsigned int facet) const
24842
 
  {
24843
 
    switch ( facet )
24844
 
    {
24845
 
    case 0:
24846
 
      dofs[0] = 1;
24847
 
      dofs[1] = 2;
24848
 
      dofs[2] = 3;
24849
 
      break;
24850
 
    case 1:
24851
 
      dofs[0] = 0;
24852
 
      dofs[1] = 2;
24853
 
      dofs[2] = 3;
24854
 
      break;
24855
 
    case 2:
24856
 
      dofs[0] = 0;
24857
 
      dofs[1] = 1;
24858
 
      dofs[2] = 3;
24859
 
      break;
24860
 
    case 3:
24861
 
      dofs[0] = 0;
24862
 
      dofs[1] = 1;
24863
 
      dofs[2] = 2;
24864
 
      break;
24865
 
    }
24866
 
  }
24867
 
 
24868
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
24869
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
24870
 
                                    unsigned int d, unsigned int i) const
24871
 
  {
24872
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
24873
 
  }
24874
 
 
24875
 
  /// Tabulate the coordinates of all dofs on a cell
24876
 
  virtual void tabulate_coordinates(double** coordinates,
24877
 
                                    const ufc::cell& c) const
24878
 
  {
24879
 
    const double * const * x = c.coordinates;
24880
 
    coordinates[0][0] = x[0][0];
24881
 
    coordinates[0][1] = x[0][1];
24882
 
    coordinates[0][2] = x[0][2];
24883
 
    coordinates[1][0] = x[1][0];
24884
 
    coordinates[1][1] = x[1][1];
24885
 
    coordinates[1][2] = x[1][2];
24886
 
    coordinates[2][0] = x[2][0];
24887
 
    coordinates[2][1] = x[2][1];
24888
 
    coordinates[2][2] = x[2][2];
24889
 
    coordinates[3][0] = x[3][0];
24890
 
    coordinates[3][1] = x[3][1];
24891
 
    coordinates[3][2] = x[3][2];
24892
 
  }
24893
 
 
24894
 
  /// Return the number of sub dof maps (for a mixed element)
24895
 
  virtual unsigned int num_sub_dof_maps() const
24896
 
  {
24897
 
    return 1;
24898
 
  }
24899
 
 
24900
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
24901
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
24902
 
  {
24903
 
    return new hyperelasticity_1_dof_map_2_2();
24904
 
  }
24905
 
 
24906
 
};
24907
 
 
24908
 
/// This class defines the interface for a local-to-global mapping of
24909
 
/// degrees of freedom (dofs).
24910
 
 
24911
 
class hyperelasticity_1_dof_map_2: public ufc::dof_map
24912
 
{
24913
 
private:
24914
 
 
24915
 
  unsigned int __global_dimension;
24916
 
 
24917
 
public:
24918
 
 
24919
 
  /// Constructor
24920
 
  hyperelasticity_1_dof_map_2() : ufc::dof_map()
24921
 
  {
24922
 
    __global_dimension = 0;
24923
 
  }
24924
 
 
24925
 
  /// Destructor
24926
 
  virtual ~hyperelasticity_1_dof_map_2()
24927
 
  {
24928
 
    // Do nothing
24929
 
  }
24930
 
 
24931
 
  /// Return a string identifying the dof map
24932
 
  virtual const char* signature() const
24933
 
  {
24934
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
24935
 
  }
24936
 
 
24937
 
  /// Return true iff mesh entities of topological dimension d are needed
24938
 
  virtual bool needs_mesh_entities(unsigned int d) const
24939
 
  {
24940
 
    switch ( d )
24941
 
    {
24942
 
    case 0:
24943
 
      return true;
24944
 
      break;
24945
 
    case 1:
24946
 
      return false;
24947
 
      break;
24948
 
    case 2:
24949
 
      return false;
24950
 
      break;
24951
 
    case 3:
24952
 
      return false;
24953
 
      break;
24954
 
    }
24955
 
    return false;
24956
 
  }
24957
 
 
24958
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
24959
 
  virtual bool init_mesh(const ufc::mesh& m)
24960
 
  {
24961
 
    __global_dimension = 3*m.num_entities[0];
24962
 
    return false;
24963
 
  }
24964
 
 
24965
 
  /// Initialize dof map for given cell
24966
 
  virtual void init_cell(const ufc::mesh& m,
24967
 
                         const ufc::cell& c)
24968
 
  {
24969
 
    // Do nothing
24970
 
  }
24971
 
 
24972
 
  /// Finish initialization of dof map for cells
24973
 
  virtual void init_cell_finalize()
24974
 
  {
24975
 
    // Do nothing
24976
 
  }
24977
 
 
24978
 
  /// Return the dimension of the global finite element function space
24979
 
  virtual unsigned int global_dimension() const
24980
 
  {
24981
 
    return __global_dimension;
24982
 
  }
24983
 
 
24984
 
  /// Return the dimension of the local finite element function space for a cell
24985
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
24986
 
  {
24987
 
    return 12;
24988
 
  }
24989
 
 
24990
 
  /// Return the maximum dimension of the local finite element function space
24991
 
  virtual unsigned int max_local_dimension() const
24992
 
  {
24993
 
    return 12;
24994
 
  }
24995
 
 
24996
 
  // Return the geometric dimension of the coordinates this dof map provides
24997
 
  virtual unsigned int geometric_dimension() const
24998
 
  {
24999
 
    return 3;
25000
 
  }
25001
 
 
25002
 
  /// Return the number of dofs on each cell facet
25003
 
  virtual unsigned int num_facet_dofs() const
25004
 
  {
25005
 
    return 9;
25006
 
  }
25007
 
 
25008
 
  /// Return the number of dofs associated with each cell entity of dimension d
25009
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
25010
 
  {
25011
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25012
 
  }
25013
 
 
25014
 
  /// Tabulate the local-to-global mapping of dofs on a cell
25015
 
  virtual void tabulate_dofs(unsigned int* dofs,
25016
 
                             const ufc::mesh& m,
25017
 
                             const ufc::cell& c) const
25018
 
  {
25019
 
    dofs[0] = c.entity_indices[0][0];
25020
 
    dofs[1] = c.entity_indices[0][1];
25021
 
    dofs[2] = c.entity_indices[0][2];
25022
 
    dofs[3] = c.entity_indices[0][3];
25023
 
    unsigned int offset = m.num_entities[0];
25024
 
    dofs[4] = offset + c.entity_indices[0][0];
25025
 
    dofs[5] = offset + c.entity_indices[0][1];
25026
 
    dofs[6] = offset + c.entity_indices[0][2];
25027
 
    dofs[7] = offset + c.entity_indices[0][3];
25028
 
    offset = offset + m.num_entities[0];
25029
 
    dofs[8] = offset + c.entity_indices[0][0];
25030
 
    dofs[9] = offset + c.entity_indices[0][1];
25031
 
    dofs[10] = offset + c.entity_indices[0][2];
25032
 
    dofs[11] = offset + c.entity_indices[0][3];
25033
 
  }
25034
 
 
25035
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
25036
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
25037
 
                                   unsigned int facet) const
25038
 
  {
25039
 
    switch ( facet )
25040
 
    {
25041
 
    case 0:
25042
 
      dofs[0] = 1;
25043
 
      dofs[1] = 2;
25044
 
      dofs[2] = 3;
25045
 
      dofs[3] = 5;
25046
 
      dofs[4] = 6;
25047
 
      dofs[5] = 7;
25048
 
      dofs[6] = 9;
25049
 
      dofs[7] = 10;
25050
 
      dofs[8] = 11;
25051
 
      break;
25052
 
    case 1:
25053
 
      dofs[0] = 0;
25054
 
      dofs[1] = 2;
25055
 
      dofs[2] = 3;
25056
 
      dofs[3] = 4;
25057
 
      dofs[4] = 6;
25058
 
      dofs[5] = 7;
25059
 
      dofs[6] = 8;
25060
 
      dofs[7] = 10;
25061
 
      dofs[8] = 11;
25062
 
      break;
25063
 
    case 2:
25064
 
      dofs[0] = 0;
25065
 
      dofs[1] = 1;
25066
 
      dofs[2] = 3;
25067
 
      dofs[3] = 4;
25068
 
      dofs[4] = 5;
25069
 
      dofs[5] = 7;
25070
 
      dofs[6] = 8;
25071
 
      dofs[7] = 9;
25072
 
      dofs[8] = 11;
25073
 
      break;
25074
 
    case 3:
25075
 
      dofs[0] = 0;
25076
 
      dofs[1] = 1;
25077
 
      dofs[2] = 2;
25078
 
      dofs[3] = 4;
25079
 
      dofs[4] = 5;
25080
 
      dofs[5] = 6;
25081
 
      dofs[6] = 8;
25082
 
      dofs[7] = 9;
25083
 
      dofs[8] = 10;
25084
 
      break;
25085
 
    }
25086
 
  }
25087
 
 
25088
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
25089
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
25090
 
                                    unsigned int d, unsigned int i) const
25091
 
  {
25092
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25093
 
  }
25094
 
 
25095
 
  /// Tabulate the coordinates of all dofs on a cell
25096
 
  virtual void tabulate_coordinates(double** coordinates,
25097
 
                                    const ufc::cell& c) const
25098
 
  {
25099
 
    const double * const * x = c.coordinates;
25100
 
    coordinates[0][0] = x[0][0];
25101
 
    coordinates[0][1] = x[0][1];
25102
 
    coordinates[0][2] = x[0][2];
25103
 
    coordinates[1][0] = x[1][0];
25104
 
    coordinates[1][1] = x[1][1];
25105
 
    coordinates[1][2] = x[1][2];
25106
 
    coordinates[2][0] = x[2][0];
25107
 
    coordinates[2][1] = x[2][1];
25108
 
    coordinates[2][2] = x[2][2];
25109
 
    coordinates[3][0] = x[3][0];
25110
 
    coordinates[3][1] = x[3][1];
25111
 
    coordinates[3][2] = x[3][2];
25112
 
    coordinates[4][0] = x[0][0];
25113
 
    coordinates[4][1] = x[0][1];
25114
 
    coordinates[4][2] = x[0][2];
25115
 
    coordinates[5][0] = x[1][0];
25116
 
    coordinates[5][1] = x[1][1];
25117
 
    coordinates[5][2] = x[1][2];
25118
 
    coordinates[6][0] = x[2][0];
25119
 
    coordinates[6][1] = x[2][1];
25120
 
    coordinates[6][2] = x[2][2];
25121
 
    coordinates[7][0] = x[3][0];
25122
 
    coordinates[7][1] = x[3][1];
25123
 
    coordinates[7][2] = x[3][2];
25124
 
    coordinates[8][0] = x[0][0];
25125
 
    coordinates[8][1] = x[0][1];
25126
 
    coordinates[8][2] = x[0][2];
25127
 
    coordinates[9][0] = x[1][0];
25128
 
    coordinates[9][1] = x[1][1];
25129
 
    coordinates[9][2] = x[1][2];
25130
 
    coordinates[10][0] = x[2][0];
25131
 
    coordinates[10][1] = x[2][1];
25132
 
    coordinates[10][2] = x[2][2];
25133
 
    coordinates[11][0] = x[3][0];
25134
 
    coordinates[11][1] = x[3][1];
25135
 
    coordinates[11][2] = x[3][2];
25136
 
  }
25137
 
 
25138
 
  /// Return the number of sub dof maps (for a mixed element)
25139
 
  virtual unsigned int num_sub_dof_maps() const
25140
 
  {
25141
 
    return 3;
25142
 
  }
25143
 
 
25144
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
25145
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
25146
 
  {
25147
 
    switch ( i )
25148
 
    {
25149
 
    case 0:
25150
 
      return new hyperelasticity_1_dof_map_2_0();
25151
 
      break;
25152
 
    case 1:
25153
 
      return new hyperelasticity_1_dof_map_2_1();
25154
 
      break;
25155
 
    case 2:
25156
 
      return new hyperelasticity_1_dof_map_2_2();
25157
 
      break;
25158
 
    }
25159
 
    return 0;
25160
 
  }
25161
 
 
25162
 
};
25163
 
 
25164
 
/// This class defines the interface for a local-to-global mapping of
25165
 
/// degrees of freedom (dofs).
25166
 
 
25167
 
class hyperelasticity_1_dof_map_3_0: public ufc::dof_map
25168
 
{
25169
 
private:
25170
 
 
25171
 
  unsigned int __global_dimension;
25172
 
 
25173
 
public:
25174
 
 
25175
 
  /// Constructor
25176
 
  hyperelasticity_1_dof_map_3_0() : ufc::dof_map()
25177
 
  {
25178
 
    __global_dimension = 0;
25179
 
  }
25180
 
 
25181
 
  /// Destructor
25182
 
  virtual ~hyperelasticity_1_dof_map_3_0()
25183
 
  {
25184
 
    // Do nothing
25185
 
  }
25186
 
 
25187
 
  /// Return a string identifying the dof map
25188
 
  virtual const char* signature() const
25189
 
  {
25190
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
25191
 
  }
25192
 
 
25193
 
  /// Return true iff mesh entities of topological dimension d are needed
25194
 
  virtual bool needs_mesh_entities(unsigned int d) const
25195
 
  {
25196
 
    switch ( d )
25197
 
    {
25198
 
    case 0:
25199
 
      return true;
25200
 
      break;
25201
 
    case 1:
25202
 
      return false;
25203
 
      break;
25204
 
    case 2:
25205
 
      return false;
25206
 
      break;
25207
 
    case 3:
25208
 
      return false;
25209
 
      break;
25210
 
    }
25211
 
    return false;
25212
 
  }
25213
 
 
25214
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
25215
 
  virtual bool init_mesh(const ufc::mesh& m)
25216
 
  {
25217
 
    __global_dimension = m.num_entities[0];
25218
 
    return false;
25219
 
  }
25220
 
 
25221
 
  /// Initialize dof map for given cell
25222
 
  virtual void init_cell(const ufc::mesh& m,
25223
 
                         const ufc::cell& c)
25224
 
  {
25225
 
    // Do nothing
25226
 
  }
25227
 
 
25228
 
  /// Finish initialization of dof map for cells
25229
 
  virtual void init_cell_finalize()
25230
 
  {
25231
 
    // Do nothing
25232
 
  }
25233
 
 
25234
 
  /// Return the dimension of the global finite element function space
25235
 
  virtual unsigned int global_dimension() const
25236
 
  {
25237
 
    return __global_dimension;
25238
 
  }
25239
 
 
25240
 
  /// Return the dimension of the local finite element function space for a cell
25241
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
25242
 
  {
25243
 
    return 4;
25244
 
  }
25245
 
 
25246
 
  /// Return the maximum dimension of the local finite element function space
25247
 
  virtual unsigned int max_local_dimension() const
25248
 
  {
25249
 
    return 4;
25250
 
  }
25251
 
 
25252
 
  // Return the geometric dimension of the coordinates this dof map provides
25253
 
  virtual unsigned int geometric_dimension() const
25254
 
  {
25255
 
    return 3;
25256
 
  }
25257
 
 
25258
 
  /// Return the number of dofs on each cell facet
25259
 
  virtual unsigned int num_facet_dofs() const
25260
 
  {
25261
 
    return 3;
25262
 
  }
25263
 
 
25264
 
  /// Return the number of dofs associated with each cell entity of dimension d
25265
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
25266
 
  {
25267
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25268
 
  }
25269
 
 
25270
 
  /// Tabulate the local-to-global mapping of dofs on a cell
25271
 
  virtual void tabulate_dofs(unsigned int* dofs,
25272
 
                             const ufc::mesh& m,
25273
 
                             const ufc::cell& c) const
25274
 
  {
25275
 
    dofs[0] = c.entity_indices[0][0];
25276
 
    dofs[1] = c.entity_indices[0][1];
25277
 
    dofs[2] = c.entity_indices[0][2];
25278
 
    dofs[3] = c.entity_indices[0][3];
25279
 
  }
25280
 
 
25281
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
25282
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
25283
 
                                   unsigned int facet) const
25284
 
  {
25285
 
    switch ( facet )
25286
 
    {
25287
 
    case 0:
25288
 
      dofs[0] = 1;
25289
 
      dofs[1] = 2;
25290
 
      dofs[2] = 3;
25291
 
      break;
25292
 
    case 1:
25293
 
      dofs[0] = 0;
25294
 
      dofs[1] = 2;
25295
 
      dofs[2] = 3;
25296
 
      break;
25297
 
    case 2:
25298
 
      dofs[0] = 0;
25299
 
      dofs[1] = 1;
25300
 
      dofs[2] = 3;
25301
 
      break;
25302
 
    case 3:
25303
 
      dofs[0] = 0;
25304
 
      dofs[1] = 1;
25305
 
      dofs[2] = 2;
25306
 
      break;
25307
 
    }
25308
 
  }
25309
 
 
25310
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
25311
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
25312
 
                                    unsigned int d, unsigned int i) const
25313
 
  {
25314
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25315
 
  }
25316
 
 
25317
 
  /// Tabulate the coordinates of all dofs on a cell
25318
 
  virtual void tabulate_coordinates(double** coordinates,
25319
 
                                    const ufc::cell& c) const
25320
 
  {
25321
 
    const double * const * x = c.coordinates;
25322
 
    coordinates[0][0] = x[0][0];
25323
 
    coordinates[0][1] = x[0][1];
25324
 
    coordinates[0][2] = x[0][2];
25325
 
    coordinates[1][0] = x[1][0];
25326
 
    coordinates[1][1] = x[1][1];
25327
 
    coordinates[1][2] = x[1][2];
25328
 
    coordinates[2][0] = x[2][0];
25329
 
    coordinates[2][1] = x[2][1];
25330
 
    coordinates[2][2] = x[2][2];
25331
 
    coordinates[3][0] = x[3][0];
25332
 
    coordinates[3][1] = x[3][1];
25333
 
    coordinates[3][2] = x[3][2];
25334
 
  }
25335
 
 
25336
 
  /// Return the number of sub dof maps (for a mixed element)
25337
 
  virtual unsigned int num_sub_dof_maps() const
25338
 
  {
25339
 
    return 1;
25340
 
  }
25341
 
 
25342
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
25343
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
25344
 
  {
25345
 
    return new hyperelasticity_1_dof_map_3_0();
25346
 
  }
25347
 
 
25348
 
};
25349
 
 
25350
 
/// This class defines the interface for a local-to-global mapping of
25351
 
/// degrees of freedom (dofs).
25352
 
 
25353
 
class hyperelasticity_1_dof_map_3_1: public ufc::dof_map
25354
 
{
25355
 
private:
25356
 
 
25357
 
  unsigned int __global_dimension;
25358
 
 
25359
 
public:
25360
 
 
25361
 
  /// Constructor
25362
 
  hyperelasticity_1_dof_map_3_1() : ufc::dof_map()
25363
 
  {
25364
 
    __global_dimension = 0;
25365
 
  }
25366
 
 
25367
 
  /// Destructor
25368
 
  virtual ~hyperelasticity_1_dof_map_3_1()
25369
 
  {
25370
 
    // Do nothing
25371
 
  }
25372
 
 
25373
 
  /// Return a string identifying the dof map
25374
 
  virtual const char* signature() const
25375
 
  {
25376
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
25377
 
  }
25378
 
 
25379
 
  /// Return true iff mesh entities of topological dimension d are needed
25380
 
  virtual bool needs_mesh_entities(unsigned int d) const
25381
 
  {
25382
 
    switch ( d )
25383
 
    {
25384
 
    case 0:
25385
 
      return true;
25386
 
      break;
25387
 
    case 1:
25388
 
      return false;
25389
 
      break;
25390
 
    case 2:
25391
 
      return false;
25392
 
      break;
25393
 
    case 3:
25394
 
      return false;
25395
 
      break;
25396
 
    }
25397
 
    return false;
25398
 
  }
25399
 
 
25400
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
25401
 
  virtual bool init_mesh(const ufc::mesh& m)
25402
 
  {
25403
 
    __global_dimension = m.num_entities[0];
25404
 
    return false;
25405
 
  }
25406
 
 
25407
 
  /// Initialize dof map for given cell
25408
 
  virtual void init_cell(const ufc::mesh& m,
25409
 
                         const ufc::cell& c)
25410
 
  {
25411
 
    // Do nothing
25412
 
  }
25413
 
 
25414
 
  /// Finish initialization of dof map for cells
25415
 
  virtual void init_cell_finalize()
25416
 
  {
25417
 
    // Do nothing
25418
 
  }
25419
 
 
25420
 
  /// Return the dimension of the global finite element function space
25421
 
  virtual unsigned int global_dimension() const
25422
 
  {
25423
 
    return __global_dimension;
25424
 
  }
25425
 
 
25426
 
  /// Return the dimension of the local finite element function space for a cell
25427
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
25428
 
  {
25429
 
    return 4;
25430
 
  }
25431
 
 
25432
 
  /// Return the maximum dimension of the local finite element function space
25433
 
  virtual unsigned int max_local_dimension() const
25434
 
  {
25435
 
    return 4;
25436
 
  }
25437
 
 
25438
 
  // Return the geometric dimension of the coordinates this dof map provides
25439
 
  virtual unsigned int geometric_dimension() const
25440
 
  {
25441
 
    return 3;
25442
 
  }
25443
 
 
25444
 
  /// Return the number of dofs on each cell facet
25445
 
  virtual unsigned int num_facet_dofs() const
25446
 
  {
25447
 
    return 3;
25448
 
  }
25449
 
 
25450
 
  /// Return the number of dofs associated with each cell entity of dimension d
25451
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
25452
 
  {
25453
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25454
 
  }
25455
 
 
25456
 
  /// Tabulate the local-to-global mapping of dofs on a cell
25457
 
  virtual void tabulate_dofs(unsigned int* dofs,
25458
 
                             const ufc::mesh& m,
25459
 
                             const ufc::cell& c) const
25460
 
  {
25461
 
    dofs[0] = c.entity_indices[0][0];
25462
 
    dofs[1] = c.entity_indices[0][1];
25463
 
    dofs[2] = c.entity_indices[0][2];
25464
 
    dofs[3] = c.entity_indices[0][3];
25465
 
  }
25466
 
 
25467
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
25468
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
25469
 
                                   unsigned int facet) const
25470
 
  {
25471
 
    switch ( facet )
25472
 
    {
25473
 
    case 0:
25474
 
      dofs[0] = 1;
25475
 
      dofs[1] = 2;
25476
 
      dofs[2] = 3;
25477
 
      break;
25478
 
    case 1:
25479
 
      dofs[0] = 0;
25480
 
      dofs[1] = 2;
25481
 
      dofs[2] = 3;
25482
 
      break;
25483
 
    case 2:
25484
 
      dofs[0] = 0;
25485
 
      dofs[1] = 1;
25486
 
      dofs[2] = 3;
25487
 
      break;
25488
 
    case 3:
25489
 
      dofs[0] = 0;
25490
 
      dofs[1] = 1;
25491
 
      dofs[2] = 2;
25492
 
      break;
25493
 
    }
25494
 
  }
25495
 
 
25496
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
25497
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
25498
 
                                    unsigned int d, unsigned int i) const
25499
 
  {
25500
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25501
 
  }
25502
 
 
25503
 
  /// Tabulate the coordinates of all dofs on a cell
25504
 
  virtual void tabulate_coordinates(double** coordinates,
25505
 
                                    const ufc::cell& c) const
25506
 
  {
25507
 
    const double * const * x = c.coordinates;
25508
 
    coordinates[0][0] = x[0][0];
25509
 
    coordinates[0][1] = x[0][1];
25510
 
    coordinates[0][2] = x[0][2];
25511
 
    coordinates[1][0] = x[1][0];
25512
 
    coordinates[1][1] = x[1][1];
25513
 
    coordinates[1][2] = x[1][2];
25514
 
    coordinates[2][0] = x[2][0];
25515
 
    coordinates[2][1] = x[2][1];
25516
 
    coordinates[2][2] = x[2][2];
25517
 
    coordinates[3][0] = x[3][0];
25518
 
    coordinates[3][1] = x[3][1];
25519
 
    coordinates[3][2] = x[3][2];
25520
 
  }
25521
 
 
25522
 
  /// Return the number of sub dof maps (for a mixed element)
25523
 
  virtual unsigned int num_sub_dof_maps() const
25524
 
  {
25525
 
    return 1;
25526
 
  }
25527
 
 
25528
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
25529
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
25530
 
  {
25531
 
    return new hyperelasticity_1_dof_map_3_1();
25532
 
  }
25533
 
 
25534
 
};
25535
 
 
25536
 
/// This class defines the interface for a local-to-global mapping of
25537
 
/// degrees of freedom (dofs).
25538
 
 
25539
 
class hyperelasticity_1_dof_map_3_2: public ufc::dof_map
25540
 
{
25541
 
private:
25542
 
 
25543
 
  unsigned int __global_dimension;
25544
 
 
25545
 
public:
25546
 
 
25547
 
  /// Constructor
25548
 
  hyperelasticity_1_dof_map_3_2() : ufc::dof_map()
25549
 
  {
25550
 
    __global_dimension = 0;
25551
 
  }
25552
 
 
25553
 
  /// Destructor
25554
 
  virtual ~hyperelasticity_1_dof_map_3_2()
25555
 
  {
25556
 
    // Do nothing
25557
 
  }
25558
 
 
25559
 
  /// Return a string identifying the dof map
25560
 
  virtual const char* signature() const
25561
 
  {
25562
 
    return "FFC dof map for FiniteElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1)";
25563
 
  }
25564
 
 
25565
 
  /// Return true iff mesh entities of topological dimension d are needed
25566
 
  virtual bool needs_mesh_entities(unsigned int d) const
25567
 
  {
25568
 
    switch ( d )
25569
 
    {
25570
 
    case 0:
25571
 
      return true;
25572
 
      break;
25573
 
    case 1:
25574
 
      return false;
25575
 
      break;
25576
 
    case 2:
25577
 
      return false;
25578
 
      break;
25579
 
    case 3:
25580
 
      return false;
25581
 
      break;
25582
 
    }
25583
 
    return false;
25584
 
  }
25585
 
 
25586
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
25587
 
  virtual bool init_mesh(const ufc::mesh& m)
25588
 
  {
25589
 
    __global_dimension = m.num_entities[0];
25590
 
    return false;
25591
 
  }
25592
 
 
25593
 
  /// Initialize dof map for given cell
25594
 
  virtual void init_cell(const ufc::mesh& m,
25595
 
                         const ufc::cell& c)
25596
 
  {
25597
 
    // Do nothing
25598
 
  }
25599
 
 
25600
 
  /// Finish initialization of dof map for cells
25601
 
  virtual void init_cell_finalize()
25602
 
  {
25603
 
    // Do nothing
25604
 
  }
25605
 
 
25606
 
  /// Return the dimension of the global finite element function space
25607
 
  virtual unsigned int global_dimension() const
25608
 
  {
25609
 
    return __global_dimension;
25610
 
  }
25611
 
 
25612
 
  /// Return the dimension of the local finite element function space for a cell
25613
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
25614
 
  {
25615
 
    return 4;
25616
 
  }
25617
 
 
25618
 
  /// Return the maximum dimension of the local finite element function space
25619
 
  virtual unsigned int max_local_dimension() const
25620
 
  {
25621
 
    return 4;
25622
 
  }
25623
 
 
25624
 
  // Return the geometric dimension of the coordinates this dof map provides
25625
 
  virtual unsigned int geometric_dimension() const
25626
 
  {
25627
 
    return 3;
25628
 
  }
25629
 
 
25630
 
  /// Return the number of dofs on each cell facet
25631
 
  virtual unsigned int num_facet_dofs() const
25632
 
  {
25633
 
    return 3;
25634
 
  }
25635
 
 
25636
 
  /// Return the number of dofs associated with each cell entity of dimension d
25637
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
25638
 
  {
25639
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25640
 
  }
25641
 
 
25642
 
  /// Tabulate the local-to-global mapping of dofs on a cell
25643
 
  virtual void tabulate_dofs(unsigned int* dofs,
25644
 
                             const ufc::mesh& m,
25645
 
                             const ufc::cell& c) const
25646
 
  {
25647
 
    dofs[0] = c.entity_indices[0][0];
25648
 
    dofs[1] = c.entity_indices[0][1];
25649
 
    dofs[2] = c.entity_indices[0][2];
25650
 
    dofs[3] = c.entity_indices[0][3];
25651
 
  }
25652
 
 
25653
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
25654
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
25655
 
                                   unsigned int facet) const
25656
 
  {
25657
 
    switch ( facet )
25658
 
    {
25659
 
    case 0:
25660
 
      dofs[0] = 1;
25661
 
      dofs[1] = 2;
25662
 
      dofs[2] = 3;
25663
 
      break;
25664
 
    case 1:
25665
 
      dofs[0] = 0;
25666
 
      dofs[1] = 2;
25667
 
      dofs[2] = 3;
25668
 
      break;
25669
 
    case 2:
25670
 
      dofs[0] = 0;
25671
 
      dofs[1] = 1;
25672
 
      dofs[2] = 3;
25673
 
      break;
25674
 
    case 3:
25675
 
      dofs[0] = 0;
25676
 
      dofs[1] = 1;
25677
 
      dofs[2] = 2;
25678
 
      break;
25679
 
    }
25680
 
  }
25681
 
 
25682
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
25683
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
25684
 
                                    unsigned int d, unsigned int i) const
25685
 
  {
25686
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25687
 
  }
25688
 
 
25689
 
  /// Tabulate the coordinates of all dofs on a cell
25690
 
  virtual void tabulate_coordinates(double** coordinates,
25691
 
                                    const ufc::cell& c) const
25692
 
  {
25693
 
    const double * const * x = c.coordinates;
25694
 
    coordinates[0][0] = x[0][0];
25695
 
    coordinates[0][1] = x[0][1];
25696
 
    coordinates[0][2] = x[0][2];
25697
 
    coordinates[1][0] = x[1][0];
25698
 
    coordinates[1][1] = x[1][1];
25699
 
    coordinates[1][2] = x[1][2];
25700
 
    coordinates[2][0] = x[2][0];
25701
 
    coordinates[2][1] = x[2][1];
25702
 
    coordinates[2][2] = x[2][2];
25703
 
    coordinates[3][0] = x[3][0];
25704
 
    coordinates[3][1] = x[3][1];
25705
 
    coordinates[3][2] = x[3][2];
25706
 
  }
25707
 
 
25708
 
  /// Return the number of sub dof maps (for a mixed element)
25709
 
  virtual unsigned int num_sub_dof_maps() const
25710
 
  {
25711
 
    return 1;
25712
 
  }
25713
 
 
25714
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
25715
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
25716
 
  {
25717
 
    return new hyperelasticity_1_dof_map_3_2();
25718
 
  }
25719
 
 
25720
 
};
25721
 
 
25722
 
/// This class defines the interface for a local-to-global mapping of
25723
 
/// degrees of freedom (dofs).
25724
 
 
25725
 
class hyperelasticity_1_dof_map_3: public ufc::dof_map
25726
 
{
25727
 
private:
25728
 
 
25729
 
  unsigned int __global_dimension;
25730
 
 
25731
 
public:
25732
 
 
25733
 
  /// Constructor
25734
 
  hyperelasticity_1_dof_map_3() : ufc::dof_map()
25735
 
  {
25736
 
    __global_dimension = 0;
25737
 
  }
25738
 
 
25739
 
  /// Destructor
25740
 
  virtual ~hyperelasticity_1_dof_map_3()
25741
 
  {
25742
 
    // Do nothing
25743
 
  }
25744
 
 
25745
 
  /// Return a string identifying the dof map
25746
 
  virtual const char* signature() const
25747
 
  {
25748
 
    return "FFC dof map for VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3)";
25749
 
  }
25750
 
 
25751
 
  /// Return true iff mesh entities of topological dimension d are needed
25752
 
  virtual bool needs_mesh_entities(unsigned int d) const
25753
 
  {
25754
 
    switch ( d )
25755
 
    {
25756
 
    case 0:
25757
 
      return true;
25758
 
      break;
25759
 
    case 1:
25760
 
      return false;
25761
 
      break;
25762
 
    case 2:
25763
 
      return false;
25764
 
      break;
25765
 
    case 3:
25766
 
      return false;
25767
 
      break;
25768
 
    }
25769
 
    return false;
25770
 
  }
25771
 
 
25772
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
25773
 
  virtual bool init_mesh(const ufc::mesh& m)
25774
 
  {
25775
 
    __global_dimension = 3*m.num_entities[0];
25776
 
    return false;
25777
 
  }
25778
 
 
25779
 
  /// Initialize dof map for given cell
25780
 
  virtual void init_cell(const ufc::mesh& m,
25781
 
                         const ufc::cell& c)
25782
 
  {
25783
 
    // Do nothing
25784
 
  }
25785
 
 
25786
 
  /// Finish initialization of dof map for cells
25787
 
  virtual void init_cell_finalize()
25788
 
  {
25789
 
    // Do nothing
25790
 
  }
25791
 
 
25792
 
  /// Return the dimension of the global finite element function space
25793
 
  virtual unsigned int global_dimension() const
25794
 
  {
25795
 
    return __global_dimension;
25796
 
  }
25797
 
 
25798
 
  /// Return the dimension of the local finite element function space for a cell
25799
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
25800
 
  {
25801
 
    return 12;
25802
 
  }
25803
 
 
25804
 
  /// Return the maximum dimension of the local finite element function space
25805
 
  virtual unsigned int max_local_dimension() const
25806
 
  {
25807
 
    return 12;
25808
 
  }
25809
 
 
25810
 
  // Return the geometric dimension of the coordinates this dof map provides
25811
 
  virtual unsigned int geometric_dimension() const
25812
 
  {
25813
 
    return 3;
25814
 
  }
25815
 
 
25816
 
  /// Return the number of dofs on each cell facet
25817
 
  virtual unsigned int num_facet_dofs() const
25818
 
  {
25819
 
    return 9;
25820
 
  }
25821
 
 
25822
 
  /// Return the number of dofs associated with each cell entity of dimension d
25823
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
25824
 
  {
25825
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25826
 
  }
25827
 
 
25828
 
  /// Tabulate the local-to-global mapping of dofs on a cell
25829
 
  virtual void tabulate_dofs(unsigned int* dofs,
25830
 
                             const ufc::mesh& m,
25831
 
                             const ufc::cell& c) const
25832
 
  {
25833
 
    dofs[0] = c.entity_indices[0][0];
25834
 
    dofs[1] = c.entity_indices[0][1];
25835
 
    dofs[2] = c.entity_indices[0][2];
25836
 
    dofs[3] = c.entity_indices[0][3];
25837
 
    unsigned int offset = m.num_entities[0];
25838
 
    dofs[4] = offset + c.entity_indices[0][0];
25839
 
    dofs[5] = offset + c.entity_indices[0][1];
25840
 
    dofs[6] = offset + c.entity_indices[0][2];
25841
 
    dofs[7] = offset + c.entity_indices[0][3];
25842
 
    offset = offset + m.num_entities[0];
25843
 
    dofs[8] = offset + c.entity_indices[0][0];
25844
 
    dofs[9] = offset + c.entity_indices[0][1];
25845
 
    dofs[10] = offset + c.entity_indices[0][2];
25846
 
    dofs[11] = offset + c.entity_indices[0][3];
25847
 
  }
25848
 
 
25849
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
25850
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
25851
 
                                   unsigned int facet) const
25852
 
  {
25853
 
    switch ( facet )
25854
 
    {
25855
 
    case 0:
25856
 
      dofs[0] = 1;
25857
 
      dofs[1] = 2;
25858
 
      dofs[2] = 3;
25859
 
      dofs[3] = 5;
25860
 
      dofs[4] = 6;
25861
 
      dofs[5] = 7;
25862
 
      dofs[6] = 9;
25863
 
      dofs[7] = 10;
25864
 
      dofs[8] = 11;
25865
 
      break;
25866
 
    case 1:
25867
 
      dofs[0] = 0;
25868
 
      dofs[1] = 2;
25869
 
      dofs[2] = 3;
25870
 
      dofs[3] = 4;
25871
 
      dofs[4] = 6;
25872
 
      dofs[5] = 7;
25873
 
      dofs[6] = 8;
25874
 
      dofs[7] = 10;
25875
 
      dofs[8] = 11;
25876
 
      break;
25877
 
    case 2:
25878
 
      dofs[0] = 0;
25879
 
      dofs[1] = 1;
25880
 
      dofs[2] = 3;
25881
 
      dofs[3] = 4;
25882
 
      dofs[4] = 5;
25883
 
      dofs[5] = 7;
25884
 
      dofs[6] = 8;
25885
 
      dofs[7] = 9;
25886
 
      dofs[8] = 11;
25887
 
      break;
25888
 
    case 3:
25889
 
      dofs[0] = 0;
25890
 
      dofs[1] = 1;
25891
 
      dofs[2] = 2;
25892
 
      dofs[3] = 4;
25893
 
      dofs[4] = 5;
25894
 
      dofs[5] = 6;
25895
 
      dofs[6] = 8;
25896
 
      dofs[7] = 9;
25897
 
      dofs[8] = 10;
25898
 
      break;
25899
 
    }
25900
 
  }
25901
 
 
25902
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
25903
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
25904
 
                                    unsigned int d, unsigned int i) const
25905
 
  {
25906
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
25907
 
  }
25908
 
 
25909
 
  /// Tabulate the coordinates of all dofs on a cell
25910
 
  virtual void tabulate_coordinates(double** coordinates,
25911
 
                                    const ufc::cell& c) const
25912
 
  {
25913
 
    const double * const * x = c.coordinates;
25914
 
    coordinates[0][0] = x[0][0];
25915
 
    coordinates[0][1] = x[0][1];
25916
 
    coordinates[0][2] = x[0][2];
25917
 
    coordinates[1][0] = x[1][0];
25918
 
    coordinates[1][1] = x[1][1];
25919
 
    coordinates[1][2] = x[1][2];
25920
 
    coordinates[2][0] = x[2][0];
25921
 
    coordinates[2][1] = x[2][1];
25922
 
    coordinates[2][2] = x[2][2];
25923
 
    coordinates[3][0] = x[3][0];
25924
 
    coordinates[3][1] = x[3][1];
25925
 
    coordinates[3][2] = x[3][2];
25926
 
    coordinates[4][0] = x[0][0];
25927
 
    coordinates[4][1] = x[0][1];
25928
 
    coordinates[4][2] = x[0][2];
25929
 
    coordinates[5][0] = x[1][0];
25930
 
    coordinates[5][1] = x[1][1];
25931
 
    coordinates[5][2] = x[1][2];
25932
 
    coordinates[6][0] = x[2][0];
25933
 
    coordinates[6][1] = x[2][1];
25934
 
    coordinates[6][2] = x[2][2];
25935
 
    coordinates[7][0] = x[3][0];
25936
 
    coordinates[7][1] = x[3][1];
25937
 
    coordinates[7][2] = x[3][2];
25938
 
    coordinates[8][0] = x[0][0];
25939
 
    coordinates[8][1] = x[0][1];
25940
 
    coordinates[8][2] = x[0][2];
25941
 
    coordinates[9][0] = x[1][0];
25942
 
    coordinates[9][1] = x[1][1];
25943
 
    coordinates[9][2] = x[1][2];
25944
 
    coordinates[10][0] = x[2][0];
25945
 
    coordinates[10][1] = x[2][1];
25946
 
    coordinates[10][2] = x[2][2];
25947
 
    coordinates[11][0] = x[3][0];
25948
 
    coordinates[11][1] = x[3][1];
25949
 
    coordinates[11][2] = x[3][2];
25950
 
  }
25951
 
 
25952
 
  /// Return the number of sub dof maps (for a mixed element)
25953
 
  virtual unsigned int num_sub_dof_maps() const
25954
 
  {
25955
 
    return 3;
25956
 
  }
25957
 
 
25958
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
25959
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
25960
 
  {
25961
 
    switch ( i )
25962
 
    {
25963
 
    case 0:
25964
 
      return new hyperelasticity_1_dof_map_3_0();
25965
 
      break;
25966
 
    case 1:
25967
 
      return new hyperelasticity_1_dof_map_3_1();
25968
 
      break;
25969
 
    case 2:
25970
 
      return new hyperelasticity_1_dof_map_3_2();
25971
 
      break;
25972
 
    }
25973
 
    return 0;
25974
 
  }
25975
 
 
25976
 
};
25977
 
 
25978
 
/// This class defines the interface for a local-to-global mapping of
25979
 
/// degrees of freedom (dofs).
25980
 
 
25981
 
class hyperelasticity_1_dof_map_4: public ufc::dof_map
25982
 
{
25983
 
private:
25984
 
 
25985
 
  unsigned int __global_dimension;
25986
 
 
25987
 
public:
25988
 
 
25989
 
  /// Constructor
25990
 
  hyperelasticity_1_dof_map_4() : ufc::dof_map()
25991
 
  {
25992
 
    __global_dimension = 0;
25993
 
  }
25994
 
 
25995
 
  /// Destructor
25996
 
  virtual ~hyperelasticity_1_dof_map_4()
25997
 
  {
25998
 
    // Do nothing
25999
 
  }
26000
 
 
26001
 
  /// Return a string identifying the dof map
26002
 
  virtual const char* signature() const
26003
 
  {
26004
 
    return "FFC dof map for FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
26005
 
  }
26006
 
 
26007
 
  /// Return true iff mesh entities of topological dimension d are needed
26008
 
  virtual bool needs_mesh_entities(unsigned int d) const
26009
 
  {
26010
 
    switch ( d )
26011
 
    {
26012
 
    case 0:
26013
 
      return false;
26014
 
      break;
26015
 
    case 1:
26016
 
      return false;
26017
 
      break;
26018
 
    case 2:
26019
 
      return false;
26020
 
      break;
26021
 
    case 3:
26022
 
      return true;
26023
 
      break;
26024
 
    }
26025
 
    return false;
26026
 
  }
26027
 
 
26028
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
26029
 
  virtual bool init_mesh(const ufc::mesh& m)
26030
 
  {
26031
 
    __global_dimension = m.num_entities[3];
26032
 
    return false;
26033
 
  }
26034
 
 
26035
 
  /// Initialize dof map for given cell
26036
 
  virtual void init_cell(const ufc::mesh& m,
26037
 
                         const ufc::cell& c)
26038
 
  {
26039
 
    // Do nothing
26040
 
  }
26041
 
 
26042
 
  /// Finish initialization of dof map for cells
26043
 
  virtual void init_cell_finalize()
26044
 
  {
26045
 
    // Do nothing
26046
 
  }
26047
 
 
26048
 
  /// Return the dimension of the global finite element function space
26049
 
  virtual unsigned int global_dimension() const
26050
 
  {
26051
 
    return __global_dimension;
26052
 
  }
26053
 
 
26054
 
  /// Return the dimension of the local finite element function space for a cell
26055
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
26056
 
  {
26057
 
    return 1;
26058
 
  }
26059
 
 
26060
 
  /// Return the maximum dimension of the local finite element function space
26061
 
  virtual unsigned int max_local_dimension() const
26062
 
  {
26063
 
    return 1;
26064
 
  }
26065
 
 
26066
 
  // Return the geometric dimension of the coordinates this dof map provides
26067
 
  virtual unsigned int geometric_dimension() const
26068
 
  {
26069
 
    return 3;
26070
 
  }
26071
 
 
26072
 
  /// Return the number of dofs on each cell facet
26073
 
  virtual unsigned int num_facet_dofs() const
26074
 
  {
26075
 
    return 0;
26076
 
  }
26077
 
 
26078
 
  /// Return the number of dofs associated with each cell entity of dimension d
26079
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
26080
 
  {
26081
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
26082
 
  }
26083
 
 
26084
 
  /// Tabulate the local-to-global mapping of dofs on a cell
26085
 
  virtual void tabulate_dofs(unsigned int* dofs,
26086
 
                             const ufc::mesh& m,
26087
 
                             const ufc::cell& c) const
26088
 
  {
26089
 
    dofs[0] = c.entity_indices[3][0];
26090
 
  }
26091
 
 
26092
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
26093
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
26094
 
                                   unsigned int facet) const
26095
 
  {
26096
 
    switch ( facet )
26097
 
    {
26098
 
    case 0:
26099
 
      
26100
 
      break;
26101
 
    case 1:
26102
 
      
26103
 
      break;
26104
 
    case 2:
26105
 
      
26106
 
      break;
26107
 
    case 3:
26108
 
      
26109
 
      break;
26110
 
    }
26111
 
  }
26112
 
 
26113
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
26114
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
26115
 
                                    unsigned int d, unsigned int i) const
26116
 
  {
26117
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
26118
 
  }
26119
 
 
26120
 
  /// Tabulate the coordinates of all dofs on a cell
26121
 
  virtual void tabulate_coordinates(double** coordinates,
26122
 
                                    const ufc::cell& c) const
26123
 
  {
26124
 
    const double * const * x = c.coordinates;
26125
 
    coordinates[0][0] = 0.25*x[0][0] + 0.25*x[1][0] + 0.25*x[2][0] + 0.25*x[3][0];
26126
 
    coordinates[0][1] = 0.25*x[0][1] + 0.25*x[1][1] + 0.25*x[2][1] + 0.25*x[3][1];
26127
 
    coordinates[0][2] = 0.25*x[0][2] + 0.25*x[1][2] + 0.25*x[2][2] + 0.25*x[3][2];
26128
 
  }
26129
 
 
26130
 
  /// Return the number of sub dof maps (for a mixed element)
26131
 
  virtual unsigned int num_sub_dof_maps() const
26132
 
  {
26133
 
    return 1;
26134
 
  }
26135
 
 
26136
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
26137
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
26138
 
  {
26139
 
    return new hyperelasticity_1_dof_map_4();
26140
 
  }
26141
 
 
26142
 
};
26143
 
 
26144
 
/// This class defines the interface for a local-to-global mapping of
26145
 
/// degrees of freedom (dofs).
26146
 
 
26147
 
class hyperelasticity_1_dof_map_5: public ufc::dof_map
26148
 
{
26149
 
private:
26150
 
 
26151
 
  unsigned int __global_dimension;
26152
 
 
26153
 
public:
26154
 
 
26155
 
  /// Constructor
26156
 
  hyperelasticity_1_dof_map_5() : ufc::dof_map()
26157
 
  {
26158
 
    __global_dimension = 0;
26159
 
  }
26160
 
 
26161
 
  /// Destructor
26162
 
  virtual ~hyperelasticity_1_dof_map_5()
26163
 
  {
26164
 
    // Do nothing
26165
 
  }
26166
 
 
26167
 
  /// Return a string identifying the dof map
26168
 
  virtual const char* signature() const
26169
 
  {
26170
 
    return "FFC dof map for FiniteElement('Discontinuous Lagrange', Cell('tetrahedron', 1, Space(3)), 0)";
26171
 
  }
26172
 
 
26173
 
  /// Return true iff mesh entities of topological dimension d are needed
26174
 
  virtual bool needs_mesh_entities(unsigned int d) const
26175
 
  {
26176
 
    switch ( d )
26177
 
    {
26178
 
    case 0:
26179
 
      return false;
26180
 
      break;
26181
 
    case 1:
26182
 
      return false;
26183
 
      break;
26184
 
    case 2:
26185
 
      return false;
26186
 
      break;
26187
 
    case 3:
26188
 
      return true;
26189
 
      break;
26190
 
    }
26191
 
    return false;
26192
 
  }
26193
 
 
26194
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
26195
 
  virtual bool init_mesh(const ufc::mesh& m)
26196
 
  {
26197
 
    __global_dimension = m.num_entities[3];
26198
 
    return false;
26199
 
  }
26200
 
 
26201
 
  /// Initialize dof map for given cell
26202
 
  virtual void init_cell(const ufc::mesh& m,
26203
 
                         const ufc::cell& c)
26204
 
  {
26205
 
    // Do nothing
26206
 
  }
26207
 
 
26208
 
  /// Finish initialization of dof map for cells
26209
 
  virtual void init_cell_finalize()
26210
 
  {
26211
 
    // Do nothing
26212
 
  }
26213
 
 
26214
 
  /// Return the dimension of the global finite element function space
26215
 
  virtual unsigned int global_dimension() const
26216
 
  {
26217
 
    return __global_dimension;
26218
 
  }
26219
 
 
26220
 
  /// Return the dimension of the local finite element function space for a cell
26221
 
  virtual unsigned int local_dimension(const ufc::cell& c) const
26222
 
  {
26223
 
    return 1;
26224
 
  }
26225
 
 
26226
 
  /// Return the maximum dimension of the local finite element function space
26227
 
  virtual unsigned int max_local_dimension() const
26228
 
  {
26229
 
    return 1;
26230
 
  }
26231
 
 
26232
 
  // Return the geometric dimension of the coordinates this dof map provides
26233
 
  virtual unsigned int geometric_dimension() const
26234
 
  {
26235
 
    return 3;
26236
 
  }
26237
 
 
26238
 
  /// Return the number of dofs on each cell facet
26239
 
  virtual unsigned int num_facet_dofs() const
26240
 
  {
26241
 
    return 0;
26242
 
  }
26243
 
 
26244
 
  /// Return the number of dofs associated with each cell entity of dimension d
26245
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
26246
 
  {
26247
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
26248
 
  }
26249
 
 
26250
 
  /// Tabulate the local-to-global mapping of dofs on a cell
26251
 
  virtual void tabulate_dofs(unsigned int* dofs,
26252
 
                             const ufc::mesh& m,
26253
 
                             const ufc::cell& c) const
26254
 
  {
26255
 
    dofs[0] = c.entity_indices[3][0];
26256
 
  }
26257
 
 
26258
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
26259
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
26260
 
                                   unsigned int facet) const
26261
 
  {
26262
 
    switch ( facet )
26263
 
    {
26264
 
    case 0:
26265
 
      
26266
 
      break;
26267
 
    case 1:
26268
 
      
26269
 
      break;
26270
 
    case 2:
26271
 
      
26272
 
      break;
26273
 
    case 3:
26274
 
      
26275
 
      break;
26276
 
    }
26277
 
  }
26278
 
 
26279
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
26280
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
26281
 
                                    unsigned int d, unsigned int i) const
26282
 
  {
26283
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
26284
 
  }
26285
 
 
26286
 
  /// Tabulate the coordinates of all dofs on a cell
26287
 
  virtual void tabulate_coordinates(double** coordinates,
26288
 
                                    const ufc::cell& c) const
26289
 
  {
26290
 
    const double * const * x = c.coordinates;
26291
 
    coordinates[0][0] = 0.25*x[0][0] + 0.25*x[1][0] + 0.25*x[2][0] + 0.25*x[3][0];
26292
 
    coordinates[0][1] = 0.25*x[0][1] + 0.25*x[1][1] + 0.25*x[2][1] + 0.25*x[3][1];
26293
 
    coordinates[0][2] = 0.25*x[0][2] + 0.25*x[1][2] + 0.25*x[2][2] + 0.25*x[3][2];
26294
 
  }
26295
 
 
26296
 
  /// Return the number of sub dof maps (for a mixed element)
26297
 
  virtual unsigned int num_sub_dof_maps() const
26298
 
  {
26299
 
    return 1;
26300
 
  }
26301
 
 
26302
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
26303
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
26304
 
  {
26305
 
    return new hyperelasticity_1_dof_map_5();
26306
 
  }
26307
 
 
26308
 
};
26309
 
 
26310
 
/// This class defines the interface for the tabulation of the cell
26311
 
/// tensor corresponding to the local contribution to a form from
26312
 
/// the integral over a cell.
26313
 
 
26314
 
class hyperelasticity_1_cell_integral_0_quadrature: public ufc::cell_integral
26315
 
{
26316
 
public:
26317
 
 
26318
 
  /// Constructor
26319
 
  hyperelasticity_1_cell_integral_0_quadrature() : ufc::cell_integral()
26320
 
  {
26321
 
    // Do nothing
26322
 
  }
26323
 
 
26324
 
  /// Destructor
26325
 
  virtual ~hyperelasticity_1_cell_integral_0_quadrature()
26326
 
  {
26327
 
    // Do nothing
26328
 
  }
26329
 
 
26330
 
  /// Tabulate the tensor for the contribution from a local cell
26331
 
  virtual void tabulate_tensor(double* A,
26332
 
                               const double * const * w,
26333
 
                               const ufc::cell& c) const
26334
 
  {
26335
 
    // Extract vertex coordinates
26336
 
    const double * const * x = c.coordinates;
26337
 
    
26338
 
    // Compute Jacobian of affine map from reference cell
26339
 
    const double J_00 = x[1][0] - x[0][0];
26340
 
    const double J_01 = x[2][0] - x[0][0];
26341
 
    const double J_02 = x[3][0] - x[0][0];
26342
 
    const double J_10 = x[1][1] - x[0][1];
26343
 
    const double J_11 = x[2][1] - x[0][1];
26344
 
    const double J_12 = x[3][1] - x[0][1];
26345
 
    const double J_20 = x[1][2] - x[0][2];
26346
 
    const double J_21 = x[2][2] - x[0][2];
26347
 
    const double J_22 = x[3][2] - x[0][2];
26348
 
    
26349
 
    // Compute sub determinants
26350
 
    const double d_00 = J_11*J_22 - J_12*J_21;
26351
 
    const double d_01 = J_12*J_20 - J_10*J_22;
26352
 
    const double d_02 = J_10*J_21 - J_11*J_20;
26353
 
    
26354
 
    const double d_10 = J_02*J_21 - J_01*J_22;
26355
 
    const double d_11 = J_00*J_22 - J_02*J_20;
26356
 
    const double d_12 = J_01*J_20 - J_00*J_21;
26357
 
    
26358
 
    const double d_20 = J_01*J_12 - J_02*J_11;
26359
 
    const double d_21 = J_02*J_10 - J_00*J_12;
26360
 
    const double d_22 = J_00*J_11 - J_01*J_10;
26361
 
    
26362
 
    // Compute determinant of Jacobian
26363
 
    double detJ = J_00*d_00 + J_10*d_10 + J_20*d_20;
26364
 
    
26365
 
    // Compute inverse of Jacobian
26366
 
    const double Jinv_00 = d_00 / detJ;
26367
 
    const double Jinv_01 = d_10 / detJ;
26368
 
    const double Jinv_02 = d_20 / detJ;
26369
 
    const double Jinv_10 = d_01 / detJ;
26370
 
    const double Jinv_11 = d_11 / detJ;
26371
 
    const double Jinv_12 = d_21 / detJ;
26372
 
    const double Jinv_20 = d_02 / detJ;
26373
 
    const double Jinv_21 = d_12 / detJ;
26374
 
    const double Jinv_22 = d_22 / detJ;
26375
 
    
26376
 
    // Set scale factor
26377
 
    const double det = std::abs(detJ);
26378
 
    
26379
 
    
26380
 
    // Array of quadrature weights
26381
 
    static const double W8[8] = {0.0369798564, 0.0160270406, 0.0211570065, 0.00916942992, 0.0369798564, 0.0160270406, 0.0211570065, 0.00916942992};
26382
 
    // Quadrature points on the UFC reference element: (0.156682637, 0.136054977, 0.122514823), (0.081395667, 0.0706797242, 0.544151844), (0.0658386871, 0.565933165, 0.122514823), (0.0342027932, 0.293998801, 0.544151844), (0.584747563, 0.136054977, 0.122514823), (0.303772765, 0.0706797242, 0.544151844), (0.245713325, 0.565933165, 0.122514823), (0.127646562, 0.293998801, 0.544151844)
26383
 
    
26384
 
    // Value of basis functions at quadrature points.
26385
 
    static const double FE1_C0[8][12] = \
26386
 
    {{0.584747563, 0.156682637, 0.136054977, 0.122514823, 0, 0, 0, 0, 0, 0, 0, 0},
26387
 
    {0.303772765, 0.081395667, 0.0706797242, 0.544151844, 0, 0, 0, 0, 0, 0, 0, 0},
26388
 
    {0.245713325, 0.0658386871, 0.565933165, 0.122514823, 0, 0, 0, 0, 0, 0, 0, 0},
26389
 
    {0.127646562, 0.0342027932, 0.293998801, 0.544151844, 0, 0, 0, 0, 0, 0, 0, 0},
26390
 
    {0.156682637, 0.584747563, 0.136054977, 0.122514823, 0, 0, 0, 0, 0, 0, 0, 0},
26391
 
    {0.081395667, 0.303772765, 0.0706797242, 0.544151844, 0, 0, 0, 0, 0, 0, 0, 0},
26392
 
    {0.0658386871, 0.245713325, 0.565933165, 0.122514823, 0, 0, 0, 0, 0, 0, 0, 0},
26393
 
    {0.0342027932, 0.127646562, 0.293998801, 0.544151844, 0, 0, 0, 0, 0, 0, 0, 0}};
26394
 
    
26395
 
    static const double FE1_C0_D001[8][12] = \
26396
 
    {{-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26397
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26398
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26399
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26400
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26401
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26402
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
26403
 
    {-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}};
26404
 
    
26405
 
    static const double FE1_C0_D010[8][12] = \
26406
 
    {{-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26407
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26408
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26409
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26410
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26411
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26412
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26413
 
    {-1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
26414
 
    
26415
 
    static const double FE1_C0_D100[8][12] = \
26416
 
    {{-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26417
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26418
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26419
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26420
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26421
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26422
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26423
 
    {-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
26424
 
    
26425
 
    static const double FE1_C1[8][12] = \
26426
 
    {{0, 0, 0, 0, 0.584747563, 0.156682637, 0.136054977, 0.122514823, 0, 0, 0, 0},
26427
 
    {0, 0, 0, 0, 0.303772765, 0.081395667, 0.0706797242, 0.544151844, 0, 0, 0, 0},
26428
 
    {0, 0, 0, 0, 0.245713325, 0.0658386871, 0.565933165, 0.122514823, 0, 0, 0, 0},
26429
 
    {0, 0, 0, 0, 0.127646562, 0.0342027932, 0.293998801, 0.544151844, 0, 0, 0, 0},
26430
 
    {0, 0, 0, 0, 0.156682637, 0.584747563, 0.136054977, 0.122514823, 0, 0, 0, 0},
26431
 
    {0, 0, 0, 0, 0.081395667, 0.303772765, 0.0706797242, 0.544151844, 0, 0, 0, 0},
26432
 
    {0, 0, 0, 0, 0.0658386871, 0.245713325, 0.565933165, 0.122514823, 0, 0, 0, 0},
26433
 
    {0, 0, 0, 0, 0.0342027932, 0.127646562, 0.293998801, 0.544151844, 0, 0, 0, 0}};
26434
 
    
26435
 
    static const double FE1_C1_D001[8][12] = \
26436
 
    {{0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26437
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26438
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26439
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26440
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26441
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26442
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0},
26443
 
    {0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0}};
26444
 
    
26445
 
    static const double FE1_C1_D010[8][12] = \
26446
 
    {{0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26447
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26448
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26449
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26450
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26451
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26452
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0},
26453
 
    {0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0}};
26454
 
    
26455
 
    static const double FE1_C1_D100[8][12] = \
26456
 
    {{0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26457
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26458
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26459
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26460
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26461
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26462
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0},
26463
 
    {0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0}};
26464
 
    
26465
 
    static const double FE1_C2[8][12] = \
26466
 
    {{0, 0, 0, 0, 0, 0, 0, 0, 0.584747563, 0.156682637, 0.136054977, 0.122514823},
26467
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.303772765, 0.081395667, 0.0706797242, 0.544151844},
26468
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.245713325, 0.0658386871, 0.565933165, 0.122514823},
26469
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.127646562, 0.0342027932, 0.293998801, 0.544151844},
26470
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.156682637, 0.584747563, 0.136054977, 0.122514823},
26471
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.081395667, 0.303772765, 0.0706797242, 0.544151844},
26472
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.0658386871, 0.245713325, 0.565933165, 0.122514823},
26473
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.0342027932, 0.127646562, 0.293998801, 0.544151844}};
26474
 
    
26475
 
    static const double FE1_C2_D001[8][12] = \
26476
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26477
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26478
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26479
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26480
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26481
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26482
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1},
26483
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1}};
26484
 
    
26485
 
    static const double FE1_C2_D010[8][12] = \
26486
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26487
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26488
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26489
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26490
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26491
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26492
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0},
26493
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0}};
26494
 
    
26495
 
    static const double FE1_C2_D100[8][12] = \
26496
 
    {{0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26497
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26498
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26499
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26500
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26501
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26502
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0},
26503
 
    {0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0}};
26504
 
    
26505
 
    
26506
 
    // Compute element tensor using UFL quadrature representation
26507
 
    // Optimisations: ('simplify expressions', False), ('ignore zero tables', False), ('non zero columns', False), ('remove zero terms', False), ('ignore ones', False)
26508
 
    // Total number of operations to compute element tensor: 232128
26509
 
    
26510
 
    // Loop quadrature points for integral
26511
 
    // Number of operations to compute element tensor for following IP loop = 232128
26512
 
    for (unsigned int ip = 0; ip < 8; ip++)
26513
 
    {
26514
 
      
26515
 
      // Function declarations
26516
 
      double F0 = 0;
26517
 
      double F1 = 0;
26518
 
      double F2 = 0;
26519
 
      double F3 = 0;
26520
 
      double F4 = 0;
26521
 
      double F5 = 0;
26522
 
      double F6 = 0;
26523
 
      double F7 = 0;
26524
 
      double F8 = 0;
26525
 
      double F9 = 0;
26526
 
      double F10 = 0;
26527
 
      double F11 = 0;
26528
 
      
26529
 
      // Total number of operations to compute function values = 288
26530
 
      for (unsigned int r = 0; r < 12; r++)
26531
 
      {
26532
 
        F0 += FE1_C0_D100[ip][r]*w[0][r];
26533
 
        F1 += FE1_C0_D010[ip][r]*w[0][r];
26534
 
        F2 += FE1_C0_D001[ip][r]*w[0][r];
26535
 
        F3 += FE1_C1_D100[ip][r]*w[0][r];
26536
 
        F4 += FE1_C1_D010[ip][r]*w[0][r];
26537
 
        F5 += FE1_C1_D001[ip][r]*w[0][r];
26538
 
        F6 += FE1_C2_D100[ip][r]*w[0][r];
26539
 
        F7 += FE1_C2_D010[ip][r]*w[0][r];
26540
 
        F8 += FE1_C2_D001[ip][r]*w[0][r];
26541
 
        F9 += FE1_C0[ip][r]*w[1][r];
26542
 
        F10 += FE1_C1[ip][r]*w[1][r];
26543
 
        F11 += FE1_C2[ip][r]*w[1][r];
26544
 
      }// end loop over 'r'
26545
 
      
26546
 
      // Number of operations for primary indices: 28728
26547
 
      for (unsigned int j = 0; j < 12; j++)
26548
 
      {
26549
 
        // Number of operations to compute entry: 2394
26550
 
        A[j] += ((FE1_C1[ip][j]*F10 + FE1_C0[ip][j]*F9 + FE1_C2[ip][j]*F11)*-1 + (((Jinv_00*FE1_C2_D100[ip][j] + Jinv_10*FE1_C2_D010[ip][j] + Jinv_20*FE1_C2_D001[ip][j])*((1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2) + (Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(w[3][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2)) + (Jinv_00*FE1_C0_D100[ip][j] + Jinv_10*FE1_C0_D010[ip][j] + Jinv_20*FE1_C0_D001[ip][j])*((Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(w[3][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2)) + (Jinv_00*FE1_C1_D100[ip][j] + Jinv_10*FE1_C1_D010[ip][j] + Jinv_20*FE1_C1_D001[ip][j])*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5))/(2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(w[3][0]*2*(((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*w[3][0]*2*((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2))/(2))) + ((Jinv_02*FE1_C2_D100[ip][j] + Jinv_12*FE1_C2_D010[ip][j] + Jinv_22*FE1_C2_D001[ip][j])*((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*w[3][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*w[3][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(w[3][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2)) + (Jinv_02*FE1_C1_D100[ip][j] + Jinv_12*FE1_C1_D010[ip][j] + Jinv_22*FE1_C1_D001[ip][j])*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*w[3][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*w[3][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(w[3][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2)) + (Jinv_02*FE1_C0_D100[ip][j] + Jinv_12*FE1_C0_D010[ip][j] + Jinv_22*FE1_C0_D001[ip][j])*((1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*w[3][0]*2*((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*w[3][0]*2*((Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5)) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8))/(2) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(w[3][0]*2*(((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2) + w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2))) + ((Jinv_01*FE1_C2_D100[ip][j] + Jinv_11*FE1_C2_D010[ip][j] + Jinv_21*FE1_C2_D001[ip][j])*((1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[3][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2)) + (Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2)) + (Jinv_01*FE1_C0_D100[ip][j] + Jinv_11*FE1_C0_D010[ip][j] + Jinv_21*FE1_C0_D001[ip][j])*((Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[3][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2)) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2)) + (Jinv_01*FE1_C1_D100[ip][j] + Jinv_11*FE1_C1_D010[ip][j] + Jinv_21*FE1_C1_D001[ip][j])*((Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2)))/(2) + (Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*w[3][0]*2*((1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8)))/(2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(w[4][0]/(2)*((((Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8)*(Jinv_00*F6 + Jinv_10*F7 + Jinv_20*F8) + (Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5)*(Jinv_00*F3 + Jinv_10*F4 + Jinv_20*F5) + (1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))*(1 + (Jinv_00*F0 + Jinv_10*F1 + Jinv_20*F2))) + -1)/(2) + (((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2) + (((Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5)*(Jinv_02*F3 + Jinv_12*F4 + Jinv_22*F5) + (Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2)*(Jinv_02*F0 + Jinv_12*F1 + Jinv_22*F2) + (1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))*(1 + (Jinv_02*F6 + Jinv_12*F7 + Jinv_22*F8))) + -1)/(2))*2 + w[3][0]*2*(((Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8)*(Jinv_01*F6 + Jinv_11*F7 + Jinv_21*F8) + (Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2)*(Jinv_01*F0 + Jinv_11*F1 + Jinv_21*F2) + (1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))*(1 + (Jinv_01*F3 + Jinv_11*F4 + Jinv_21*F5))) + -1)/(2))))))*W8[ip]*det;
26551
 
      }// end loop over 'j'
26552
 
    }// end loop over 'ip'
26553
 
  }
26554
 
 
26555
 
};
26556
 
 
26557
 
/// This class defines the interface for the tabulation of the cell
26558
 
/// tensor corresponding to the local contribution to a form from
26559
 
/// the integral over a cell.
26560
 
 
26561
 
class hyperelasticity_1_cell_integral_0: public ufc::cell_integral
26562
 
{
26563
 
private:
26564
 
 
26565
 
  hyperelasticity_1_cell_integral_0_quadrature integral_0_quadrature;
26566
 
 
26567
 
public:
26568
 
 
26569
 
  /// Constructor
26570
 
  hyperelasticity_1_cell_integral_0() : ufc::cell_integral()
26571
 
  {
26572
 
    // Do nothing
26573
 
  }
26574
 
 
26575
 
  /// Destructor
26576
 
  virtual ~hyperelasticity_1_cell_integral_0()
26577
 
  {
26578
 
    // Do nothing
26579
 
  }
26580
 
 
26581
 
  /// Tabulate the tensor for the contribution from a local cell
26582
 
  virtual void tabulate_tensor(double* A,
26583
 
                               const double * const * w,
26584
 
                               const ufc::cell& c) const
26585
 
  {
26586
 
    // Reset values of the element tensor block
26587
 
    for (unsigned int j = 0; j < 12; j++)
26588
 
      A[j] = 0;
26589
 
    
26590
 
    // Add all contributions to element tensor
26591
 
    integral_0_quadrature.tabulate_tensor(A, w, c);
26592
 
  }
26593
 
 
26594
 
};
26595
 
 
26596
 
/// This class defines the interface for the tabulation of the
26597
 
/// exterior facet tensor corresponding to the local contribution to
26598
 
/// a form from the integral over an exterior facet.
26599
 
 
26600
 
class hyperelasticity_1_exterior_facet_integral_0_quadrature: public ufc::exterior_facet_integral
26601
 
{
26602
 
public:
26603
 
 
26604
 
  /// Constructor
26605
 
  hyperelasticity_1_exterior_facet_integral_0_quadrature() : ufc::exterior_facet_integral()
26606
 
  {
26607
 
    // Do nothing
26608
 
  }
26609
 
 
26610
 
  /// Destructor
26611
 
  virtual ~hyperelasticity_1_exterior_facet_integral_0_quadrature()
26612
 
  {
26613
 
    // Do nothing
26614
 
  }
26615
 
 
26616
 
  /// Tabulate the tensor for the contribution from a local exterior facet
26617
 
  virtual void tabulate_tensor(double* A,
26618
 
                               const double * const * w,
26619
 
                               const ufc::cell& c,
26620
 
                               unsigned int facet) const
26621
 
  {
26622
 
    // Extract vertex coordinates
26623
 
    const double * const * x = c.coordinates;
26624
 
    
26625
 
    // Compute Jacobian of affine map from reference cell
26626
 
    
26627
 
    // Compute sub determinants
26628
 
    
26629
 
    
26630
 
    
26631
 
    // Compute determinant of Jacobian
26632
 
    
26633
 
    // Compute inverse of Jacobian
26634
 
    
26635
 
    // Vertices on faces
26636
 
    static unsigned int face_vertices[4][3] = {{1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2}};
26637
 
    
26638
 
    // Get vertices
26639
 
    const unsigned int v0 = face_vertices[facet][0];
26640
 
    const unsigned int v1 = face_vertices[facet][1];
26641
 
    const unsigned int v2 = face_vertices[facet][2];
26642
 
    
26643
 
    // Compute scale factor (area of face scaled by area of reference triangle)
26644
 
    const double a0 = (x[v0][1]*x[v1][2] + x[v0][2]*x[v2][1] + x[v1][1]*x[v2][2])
26645
 
                  - (x[v2][1]*x[v1][2] + x[v2][2]*x[v0][1] + x[v1][1]*x[v0][2]);
26646
 
    const double a1 = (x[v0][2]*x[v1][0] + x[v0][0]*x[v2][2] + x[v1][2]*x[v2][0])
26647
 
                  - (x[v2][2]*x[v1][0] + x[v2][0]*x[v0][2] + x[v1][2]*x[v0][0]);
26648
 
    const double a2 = (x[v0][0]*x[v1][1] + x[v0][1]*x[v2][0] + x[v1][0]*x[v2][1])
26649
 
                  - (x[v2][0]*x[v1][1] + x[v2][1]*x[v0][0] + x[v1][0]*x[v0][1]);
26650
 
    const double det = std::sqrt(a0*a0 + a1*a1 + a2*a2);
26651
 
    
26652
 
    // Compute facet normals from the facet scale factor constants
26653
 
    
26654
 
    
26655
 
    // Array of quadrature weights
26656
 
    static const double W4[4] = {0.159020691, 0.0909793091, 0.159020691, 0.0909793091};
26657
 
    // Quadrature points on the UFC reference element: (0.178558728, 0.155051026), (0.0750311102, 0.644948974), (0.666390246, 0.155051026), (0.280019915, 0.644948974)
26658
 
    
26659
 
    // Value of basis functions at quadrature points.
26660
 
    static const double FE0_f0_C0[4][12] = \
26661
 
    {{0, 0.666390246, 0.178558728, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26662
 
    {0, 0.280019915, 0.0750311102, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0},
26663
 
    {0, 0.178558728, 0.666390246, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26664
 
    {0, 0.0750311102, 0.280019915, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0}};
26665
 
    
26666
 
    static const double FE0_f0_C1[4][12] = \
26667
 
    {{0, 0, 0, 0, 0, 0.666390246, 0.178558728, 0.155051026, 0, 0, 0, 0},
26668
 
    {0, 0, 0, 0, 0, 0.280019915, 0.0750311102, 0.644948974, 0, 0, 0, 0},
26669
 
    {0, 0, 0, 0, 0, 0.178558728, 0.666390246, 0.155051026, 0, 0, 0, 0},
26670
 
    {0, 0, 0, 0, 0, 0.0750311102, 0.280019915, 0.644948974, 0, 0, 0, 0}};
26671
 
    
26672
 
    static const double FE0_f0_C2[4][12] = \
26673
 
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0.666390246, 0.178558728, 0.155051026},
26674
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0.280019915, 0.0750311102, 0.644948974},
26675
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0.178558728, 0.666390246, 0.155051026},
26676
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0750311102, 0.280019915, 0.644948974}};
26677
 
    
26678
 
    static const double FE0_f1_C0[4][12] = \
26679
 
    {{0.666390246, 0, 0.178558728, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26680
 
    {0.280019915, 0, 0.0750311102, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0},
26681
 
    {0.178558728, 0, 0.666390246, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26682
 
    {0.0750311102, 0, 0.280019915, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0}};
26683
 
    
26684
 
    static const double FE0_f1_C1[4][12] = \
26685
 
    {{0, 0, 0, 0, 0.666390246, 0, 0.178558728, 0.155051026, 0, 0, 0, 0},
26686
 
    {0, 0, 0, 0, 0.280019915, 0, 0.0750311102, 0.644948974, 0, 0, 0, 0},
26687
 
    {0, 0, 0, 0, 0.178558728, 0, 0.666390246, 0.155051026, 0, 0, 0, 0},
26688
 
    {0, 0, 0, 0, 0.0750311102, 0, 0.280019915, 0.644948974, 0, 0, 0, 0}};
26689
 
    
26690
 
    static const double FE0_f1_C2[4][12] = \
26691
 
    {{0, 0, 0, 0, 0, 0, 0, 0, 0.666390246, 0, 0.178558728, 0.155051026},
26692
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.280019915, 0, 0.0750311102, 0.644948974},
26693
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.178558728, 0, 0.666390246, 0.155051026},
26694
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.0750311102, 0, 0.280019915, 0.644948974}};
26695
 
    
26696
 
    static const double FE0_f2_C0[4][12] = \
26697
 
    {{0.666390246, 0.178558728, 0, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26698
 
    {0.280019915, 0.0750311102, 0, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0},
26699
 
    {0.178558728, 0.666390246, 0, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0},
26700
 
    {0.0750311102, 0.280019915, 0, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0}};
26701
 
    
26702
 
    static const double FE0_f2_C1[4][12] = \
26703
 
    {{0, 0, 0, 0, 0.666390246, 0.178558728, 0, 0.155051026, 0, 0, 0, 0},
26704
 
    {0, 0, 0, 0, 0.280019915, 0.0750311102, 0, 0.644948974, 0, 0, 0, 0},
26705
 
    {0, 0, 0, 0, 0.178558728, 0.666390246, 0, 0.155051026, 0, 0, 0, 0},
26706
 
    {0, 0, 0, 0, 0.0750311102, 0.280019915, 0, 0.644948974, 0, 0, 0, 0}};
26707
 
    
26708
 
    static const double FE0_f2_C2[4][12] = \
26709
 
    {{0, 0, 0, 0, 0, 0, 0, 0, 0.666390246, 0.178558728, 0, 0.155051026},
26710
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.280019915, 0.0750311102, 0, 0.644948974},
26711
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.178558728, 0.666390246, 0, 0.155051026},
26712
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.0750311102, 0.280019915, 0, 0.644948974}};
26713
 
    
26714
 
    static const double FE0_f3_C0[4][12] = \
26715
 
    {{0.666390246, 0.178558728, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26716
 
    {0.280019915, 0.0750311102, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26717
 
    {0.178558728, 0.666390246, 0.155051026, 0, 0, 0, 0, 0, 0, 0, 0, 0},
26718
 
    {0.0750311102, 0.280019915, 0.644948974, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
26719
 
    
26720
 
    static const double FE0_f3_C1[4][12] = \
26721
 
    {{0, 0, 0, 0, 0.666390246, 0.178558728, 0.155051026, 0, 0, 0, 0, 0},
26722
 
    {0, 0, 0, 0, 0.280019915, 0.0750311102, 0.644948974, 0, 0, 0, 0, 0},
26723
 
    {0, 0, 0, 0, 0.178558728, 0.666390246, 0.155051026, 0, 0, 0, 0, 0},
26724
 
    {0, 0, 0, 0, 0.0750311102, 0.280019915, 0.644948974, 0, 0, 0, 0, 0}};
26725
 
    
26726
 
    static const double FE0_f3_C2[4][12] = \
26727
 
    {{0, 0, 0, 0, 0, 0, 0, 0, 0.666390246, 0.178558728, 0.155051026, 0},
26728
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.280019915, 0.0750311102, 0.644948974, 0},
26729
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.178558728, 0.666390246, 0.155051026, 0},
26730
 
    {0, 0, 0, 0, 0, 0, 0, 0, 0.0750311102, 0.280019915, 0.644948974, 0}};
26731
 
    
26732
 
    
26733
 
    // Compute element tensor using UFL quadrature representation
26734
 
    // Optimisations: ('simplify expressions', False), ('ignore zero tables', False), ('non zero columns', False), ('remove zero terms', False), ('ignore ones', False)
26735
 
    switch ( facet )
26736
 
    {
26737
 
    case 0:
26738
 
      {
26739
 
      // Total number of operations to compute element tensor (from this point): 720
26740
 
      
26741
 
      // Loop quadrature points for integral
26742
 
      // Number of operations to compute element tensor for following IP loop = 720
26743
 
      for (unsigned int ip = 0; ip < 4; ip++)
26744
 
      {
26745
 
        
26746
 
        // Function declarations
26747
 
        double F0 = 0;
26748
 
        double F1 = 0;
26749
 
        double F2 = 0;
26750
 
        
26751
 
        // Total number of operations to compute function values = 72
26752
 
        for (unsigned int r = 0; r < 12; r++)
26753
 
        {
26754
 
          F0 += FE0_f0_C0[ip][r]*w[2][r];
26755
 
          F1 += FE0_f0_C1[ip][r]*w[2][r];
26756
 
          F2 += FE0_f0_C2[ip][r]*w[2][r];
26757
 
        }// end loop over 'r'
26758
 
        
26759
 
        // Number of operations for primary indices: 108
26760
 
        for (unsigned int j = 0; j < 12; j++)
26761
 
        {
26762
 
          // Number of operations to compute entry: 9
26763
 
          A[j] += (FE0_f0_C0[ip][j]*F0 + FE0_f0_C1[ip][j]*F1 + FE0_f0_C2[ip][j]*F2)*-1*W4[ip]*det;
26764
 
        }// end loop over 'j'
26765
 
      }// end loop over 'ip'
26766
 
      }
26767
 
      break;
26768
 
    case 1:
26769
 
      {
26770
 
      // Total number of operations to compute element tensor (from this point): 720
26771
 
      
26772
 
      // Loop quadrature points for integral
26773
 
      // Number of operations to compute element tensor for following IP loop = 720
26774
 
      for (unsigned int ip = 0; ip < 4; ip++)
26775
 
      {
26776
 
        
26777
 
        // Function declarations
26778
 
        double F0 = 0;
26779
 
        double F1 = 0;
26780
 
        double F2 = 0;
26781
 
        
26782
 
        // Total number of operations to compute function values = 72
26783
 
        for (unsigned int r = 0; r < 12; r++)
26784
 
        {
26785
 
          F0 += FE0_f1_C0[ip][r]*w[2][r];
26786
 
          F1 += FE0_f1_C1[ip][r]*w[2][r];
26787
 
          F2 += FE0_f1_C2[ip][r]*w[2][r];
26788
 
        }// end loop over 'r'
26789
 
        
26790
 
        // Number of operations for primary indices: 108
26791
 
        for (unsigned int j = 0; j < 12; j++)
26792
 
        {
26793
 
          // Number of operations to compute entry: 9
26794
 
          A[j] += (FE0_f1_C2[ip][j]*F2 + FE0_f1_C0[ip][j]*F0 + FE0_f1_C1[ip][j]*F1)*-1*W4[ip]*det;
26795
 
        }// end loop over 'j'
26796
 
      }// end loop over 'ip'
26797
 
      }
26798
 
      break;
26799
 
    case 2:
26800
 
      {
26801
 
      // Total number of operations to compute element tensor (from this point): 720
26802
 
      
26803
 
      // Loop quadrature points for integral
26804
 
      // Number of operations to compute element tensor for following IP loop = 720
26805
 
      for (unsigned int ip = 0; ip < 4; ip++)
26806
 
      {
26807
 
        
26808
 
        // Function declarations
26809
 
        double F0 = 0;
26810
 
        double F1 = 0;
26811
 
        double F2 = 0;
26812
 
        
26813
 
        // Total number of operations to compute function values = 72
26814
 
        for (unsigned int r = 0; r < 12; r++)
26815
 
        {
26816
 
          F0 += FE0_f2_C0[ip][r]*w[2][r];
26817
 
          F1 += FE0_f2_C1[ip][r]*w[2][r];
26818
 
          F2 += FE0_f2_C2[ip][r]*w[2][r];
26819
 
        }// end loop over 'r'
26820
 
        
26821
 
        // Number of operations for primary indices: 108
26822
 
        for (unsigned int j = 0; j < 12; j++)
26823
 
        {
26824
 
          // Number of operations to compute entry: 9
26825
 
          A[j] += (FE0_f2_C2[ip][j]*F2 + FE0_f2_C1[ip][j]*F1 + FE0_f2_C0[ip][j]*F0)*-1*W4[ip]*det;
26826
 
        }// end loop over 'j'
26827
 
      }// end loop over 'ip'
26828
 
      }
26829
 
      break;
26830
 
    case 3:
26831
 
      {
26832
 
      // Total number of operations to compute element tensor (from this point): 720
26833
 
      
26834
 
      // Loop quadrature points for integral
26835
 
      // Number of operations to compute element tensor for following IP loop = 720
26836
 
      for (unsigned int ip = 0; ip < 4; ip++)
26837
 
      {
26838
 
        
26839
 
        // Function declarations
26840
 
        double F0 = 0;
26841
 
        double F1 = 0;
26842
 
        double F2 = 0;
26843
 
        
26844
 
        // Total number of operations to compute function values = 72
26845
 
        for (unsigned int r = 0; r < 12; r++)
26846
 
        {
26847
 
          F0 += FE0_f3_C0[ip][r]*w[2][r];
26848
 
          F1 += FE0_f3_C1[ip][r]*w[2][r];
26849
 
          F2 += FE0_f3_C2[ip][r]*w[2][r];
26850
 
        }// end loop over 'r'
26851
 
        
26852
 
        // Number of operations for primary indices: 108
26853
 
        for (unsigned int j = 0; j < 12; j++)
26854
 
        {
26855
 
          // Number of operations to compute entry: 9
26856
 
          A[j] += (FE0_f3_C1[ip][j]*F1 + FE0_f3_C2[ip][j]*F2 + FE0_f3_C0[ip][j]*F0)*-1*W4[ip]*det;
26857
 
        }// end loop over 'j'
26858
 
      }// end loop over 'ip'
26859
 
      }
26860
 
      break;
26861
 
    }
26862
 
  }
26863
 
 
26864
 
};
26865
 
 
26866
 
/// This class defines the interface for the tabulation of the
26867
 
/// exterior facet tensor corresponding to the local contribution to
26868
 
/// a form from the integral over an exterior facet.
26869
 
 
26870
 
class hyperelasticity_1_exterior_facet_integral_0: public ufc::exterior_facet_integral
26871
 
{
26872
 
private:
26873
 
 
26874
 
  hyperelasticity_1_exterior_facet_integral_0_quadrature integral_0_quadrature;
26875
 
 
26876
 
public:
26877
 
 
26878
 
  /// Constructor
26879
 
  hyperelasticity_1_exterior_facet_integral_0() : ufc::exterior_facet_integral()
26880
 
  {
26881
 
    // Do nothing
26882
 
  }
26883
 
 
26884
 
  /// Destructor
26885
 
  virtual ~hyperelasticity_1_exterior_facet_integral_0()
26886
 
  {
26887
 
    // Do nothing
26888
 
  }
26889
 
 
26890
 
  /// Tabulate the tensor for the contribution from a local exterior facet
26891
 
  virtual void tabulate_tensor(double* A,
26892
 
                               const double * const * w,
26893
 
                               const ufc::cell& c,
26894
 
                               unsigned int facet) const
26895
 
  {
26896
 
    // Reset values of the element tensor block
26897
 
    for (unsigned int j = 0; j < 12; j++)
26898
 
      A[j] = 0;
26899
 
    
26900
 
    // Add all contributions to element tensor
26901
 
    integral_0_quadrature.tabulate_tensor(A, w, c, facet);
26902
 
  }
26903
 
 
26904
 
};
26905
 
 
26906
 
/// This class defines the interface for the assembly of the global
26907
 
/// tensor corresponding to a form with r + n arguments, that is, a
26908
 
/// mapping
26909
 
///
26910
 
///     a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
26911
 
///
26912
 
/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
26913
 
/// global tensor A is defined by
26914
 
///
26915
 
///     A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
26916
 
///
26917
 
/// where each argument Vj represents the application to the
26918
 
/// sequence of basis functions of Vj and w1, w2, ..., wn are given
26919
 
/// fixed functions (coefficients).
26920
 
 
26921
 
class hyperelasticity_form_1: public ufc::form
26922
 
{
26923
 
public:
26924
 
 
26925
 
  /// Constructor
26926
 
  hyperelasticity_form_1() : ufc::form()
26927
 
  {
26928
 
    // Do nothing
26929
 
  }
26930
 
 
26931
 
  /// Destructor
26932
 
  virtual ~hyperelasticity_form_1()
26933
 
  {
26934
 
    // Do nothing
26935
 
  }
26936
 
 
26937
 
  /// Return a string identifying the form
26938
 
  virtual const char* signature() const
26939
 
  {
26940
 
    return "Form([Integral(Sum(IndexSum(IndexSum(Product(Indexed(ComponentTensor(IndexSum(Product(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(0),), {Index(0): 3})), MultiIndex((Index(1),), {Index(1): 3})), MultiIndex((Index(1), Index(0)), {Index(0): 3, Index(1): 3})), Identity(3)), MultiIndex((Index(2), Index(3)), {Index(2): 3, Index(3): 3})), Indexed(Sum(ComponentTensor(Product(Constant(Cell('tetrahedron', 1, Space(3)), 3), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Indexed(IndexSum(Sum(ComponentTensor(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(8), Index(9), Index(10), Index(11)), {Index(11): 3, Index(8): 3, Index(9): 3, Index(10): 3})), MultiIndex((Index(10), Index(11)), {Index(11): 3, Index(10): 3})), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3})), Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(9), Index(27)), {Index(9): 3, Index(27): 3}))), MultiIndex((Index(12), Index(13)), {Index(13): 3, Index(12): 3})), ComponentTensor(Product(Indexed(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(9), Index(27), Index(28), Index(29)), {Index(29): 3, Index(9): 3, Index(28): 3, Index(27): 3})), MultiIndex((Index(28), Index(29)), {Index(29): 3, Index(28): 3})), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3})), Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(8), Index(9)), {Index(8): 3, Index(9): 3}))), MultiIndex((Index(30), Index(31)), {Index(31): 3, Index(30): 3}))), MultiIndex((Index(9),), {Index(9): 3})), MultiIndex((Index(32), Index(33)), {Index(33): 3, Index(32): 3})), MultiIndex((Index(8), Index(27), Index(32), Index(33)), {Index(33): 3, Index(27): 3, Index(32): 3, Index(8): 3})), MultiIndex((Index(34), Index(34), Index(35), Index(36)), {Index(35): 3, Index(36): 3, Index(34): 3})), MultiIndex((Index(35), Index(36)), {Index(35): 3, Index(36): 3})), MultiIndex((Index(34),), {Index(34): 3})), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3}))), MultiIndex((Index(37), Index(38)), {Index(37): 3, Index(38): 3})), ComponentTensor(Product(Division(Constant(Cell('tetrahedron', 1, Space(3)), 4), IntValue(2, (), (), {})), Indexed(ComponentTensor(Product(IndexSum(Indexed(Variable(ComponentTensor(Division(Indexed(Sum(ComponentTensor(IndexSum(Product(Indexed(ComponentTensor(Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(14),), {Index(14): 3})), MultiIndex((Index(15),), {Index(15): 3})), MultiIndex((Index(15), Index(14)), {Index(14): 3, Index(15): 3})), Identity(3)), MultiIndex((Index(16), Index(17)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(17), Index(16)), {Index(17): 3, Index(16): 3})), MultiIndex((Index(18), Index(19)), {Index(19): 3, Index(18): 3})), Indexed(Sum(ComponentTensor(Indexed(SpatialDerivative(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(20),), {Index(20): 3})), MultiIndex((Index(21),), {Index(21): 3})), MultiIndex((Index(21), Index(20)), {Index(21): 3, Index(20): 3})), Identity(3)), MultiIndex((Index(19), Index(22)), {Index(22): 3, Index(19): 3}))), MultiIndex((Index(19),), {Index(19): 3})), MultiIndex((Index(18), Index(22)), {Index(22): 3, Index(18): 3})), ComponentTensor(Product(IntValue(-1, (), (), {}), Indexed(Identity(3), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(23), Index(24)), {Index(24): 3, Index(23): 3}))), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), IntValue(2, (), (), {})), MultiIndex((Index(25), Index(26)), {Index(26): 3, Index(25): 3})), Label(0)), MultiIndex((Index(39), Index(39)), {Index(39): 3})), MultiIndex((Index(39),), {Index(39): 3})), Indexed(ComponentTensor(Product(IntValue(2, (), (), {}), Indexed(IndexSum(ComponentTensor(Indexed(ComponentTensor(Product(Indexed(Identity(3), MultiIndex((Index(4), Index(5)), {Index(4): 3, Index(5): 3})), Indexed(Identity(3), MultiIndex((Index(6), Index(7)), {Index(7): 3, Index(6): 3}))), MultiIndex((Index(4), Index(6), Index(5), Index(7)), {Index(7): 3, Index(4): 3, Index(5): 3, Index(6): 3})), MultiIndex((Index(39), Index(39), Index(40), Index(41)), {Index(40): 3, Index(41): 3, Index(39): 3})), MultiIndex((Index(40), Index(41)), {Index(40): 3, Index(41): 3})), MultiIndex((Index(39),), {Index(39): 3})), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3}))), MultiIndex((Index(42), Index(43)), {Index(43): 3, Index(42): 3})), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3}))), MultiIndex((Index(44), Index(45)), {Index(44): 3, Index(45): 3})), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(46), Index(47)), {Index(46): 3, Index(47): 3}))), MultiIndex((Index(3), Index(48)), {Index(48): 3, Index(3): 3}))), MultiIndex((Index(3),), {Index(3): 3})), MultiIndex((Index(2), Index(48)), {Index(48): 3, Index(2): 3})), MultiIndex((Index(49), Index(50)), {Index(50): 3, Index(49): 3})), Indexed(ComponentTensor(Indexed(SpatialDerivative(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(51),), {Index(51): 3})), MultiIndex((Index(52),), {Index(52): 3})), MultiIndex((Index(52), Index(51)), {Index(52): 3, Index(51): 3})), MultiIndex((Index(49), Index(50)), {Index(50): 3, Index(49): 3}))), MultiIndex((Index(49),), {Index(49): 3})), MultiIndex((Index(50),), {Index(50): 3})), Product(IntValue(-1, (), (), {}), IndexSum(Product(Indexed(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(53),), {Index(53): 3})), Indexed(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 1), MultiIndex((Index(53),), {Index(53): 3}))), MultiIndex((Index(53),), {Index(53): 3})))), Measure('cell', 0, None)), Integral(Product(IntValue(-1, (), (), {}), IndexSum(Product(Indexed(BasisFunction(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 0), MultiIndex((Index(54),), {Index(54): 3})), Indexed(Function(VectorElement('Lagrange', Cell('tetrahedron', 1, Space(3)), 1, 3), 2), MultiIndex((Index(54),), {Index(54): 3}))), MultiIndex((Index(54),), {Index(54): 3}))), Measure('exterior_facet', 0, None))])";
26941
 
  }
26942
 
 
26943
 
  /// Return the rank of the global tensor (r)
26944
 
  virtual unsigned int rank() const
26945
 
  {
26946
 
    return 1;
26947
 
  }
26948
 
 
26949
 
  /// Return the number of coefficients (n)
26950
 
  virtual unsigned int num_coefficients() const
26951
 
  {
26952
 
    return 5;
26953
 
  }
26954
 
 
26955
 
  /// Return the number of cell integrals
26956
 
  virtual unsigned int num_cell_integrals() const
26957
 
  {
26958
 
    return 1;
26959
 
  }
26960
 
 
26961
 
  /// Return the number of exterior facet integrals
26962
 
  virtual unsigned int num_exterior_facet_integrals() const
26963
 
  {
26964
 
    return 1;
26965
 
  }
26966
 
 
26967
 
  /// Return the number of interior facet integrals
26968
 
  virtual unsigned int num_interior_facet_integrals() const
26969
 
  {
26970
 
    return 0;
26971
 
  }
26972
 
 
26973
 
  /// Create a new finite element for argument function i
26974
 
  virtual ufc::finite_element* create_finite_element(unsigned int i) const
26975
 
  {
26976
 
    switch ( i )
26977
 
    {
26978
 
    case 0:
26979
 
      return new hyperelasticity_1_finite_element_0();
26980
 
      break;
26981
 
    case 1:
26982
 
      return new hyperelasticity_1_finite_element_1();
26983
 
      break;
26984
 
    case 2:
26985
 
      return new hyperelasticity_1_finite_element_2();
26986
 
      break;
26987
 
    case 3:
26988
 
      return new hyperelasticity_1_finite_element_3();
26989
 
      break;
26990
 
    case 4:
26991
 
      return new hyperelasticity_1_finite_element_4();
26992
 
      break;
26993
 
    case 5:
26994
 
      return new hyperelasticity_1_finite_element_5();
26995
 
      break;
26996
 
    }
26997
 
    return 0;
26998
 
  }
26999
 
 
27000
 
  /// Create a new dof map for argument function i
27001
 
  virtual ufc::dof_map* create_dof_map(unsigned int i) const
27002
 
  {
27003
 
    switch ( i )
27004
 
    {
27005
 
    case 0:
27006
 
      return new hyperelasticity_1_dof_map_0();
27007
 
      break;
27008
 
    case 1:
27009
 
      return new hyperelasticity_1_dof_map_1();
27010
 
      break;
27011
 
    case 2:
27012
 
      return new hyperelasticity_1_dof_map_2();
27013
 
      break;
27014
 
    case 3:
27015
 
      return new hyperelasticity_1_dof_map_3();
27016
 
      break;
27017
 
    case 4:
27018
 
      return new hyperelasticity_1_dof_map_4();
27019
 
      break;
27020
 
    case 5:
27021
 
      return new hyperelasticity_1_dof_map_5();
27022
 
      break;
27023
 
    }
27024
 
    return 0;
27025
 
  }
27026
 
 
27027
 
  /// Create a new cell integral on sub domain i
27028
 
  virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
27029
 
  {
27030
 
    return new hyperelasticity_1_cell_integral_0();
27031
 
  }
27032
 
 
27033
 
  /// Create a new exterior facet integral on sub domain i
27034
 
  virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
27035
 
  {
27036
 
    return new hyperelasticity_1_exterior_facet_integral_0();
27037
 
  }
27038
 
 
27039
 
  /// Create a new interior facet integral on sub domain i
27040
 
  virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
27041
 
  {
27042
 
    return 0;
27043
 
  }
27044
 
 
27045
 
};
27046
 
 
27047
 
#endif