~njansson/dolfin/hpc

« back to all changes in this revision

Viewing changes to src/kernel/elements/ffc_23.h

  • Committer: Johannes Ring
  • Date: 2008-03-05 22:43:06 UTC
  • Revision ID: johannr@simula.no-20080305224306-2npsdyhfdpl2esji
The BIG commit!

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.4.3.
3
 
 
4
 
#ifndef __FFC_23_H
5
 
#define __FFC_23_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 ffc_23_finite_element_0_0: public ufc::finite_element
14
 
{
15
 
public:
16
 
 
17
 
  /// Constructor
18
 
  ffc_23_finite_element_0_0() : ufc::finite_element()
19
 
  {
20
 
    // Do nothing
21
 
  }
22
 
 
23
 
  /// Destructor
24
 
  virtual ~ffc_23_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 "Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
155
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
156
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
157
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
158
 
    
159
 
    // Table(s) of coefficients
160
 
    const static double coefficients0[4][4] = \
161
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
162
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
163
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
164
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
341
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
342
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
343
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
344
 
    
345
 
    // Table(s) of coefficients
346
 
    const static double coefficients0[4][4] = \
347
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
348
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
349
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
350
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
351
 
    
352
 
    // Interesting (new) part
353
 
    // Tables of derivatives of the polynomial base (transpose)
354
 
    const static double dmats0[4][4] = \
355
 
    {{0, 0, 0, 0},
356
 
    {6.32455532033676, 0, 0, 0},
357
 
    {0, 0, 0, 0},
358
 
    {0, 0, 0, 0}};
359
 
    
360
 
    const static double dmats1[4][4] = \
361
 
    {{0, 0, 0, 0},
362
 
    {3.16227766016838, 0, 0, 0},
363
 
    {5.47722557505166, 0, 0, 0},
364
 
    {0, 0, 0, 0}};
365
 
    
366
 
    const static double dmats2[4][4] = \
367
 
    {{0, 0, 0, 0},
368
 
    {3.16227766016838, 0, 0, 0},
369
 
    {1.82574185835055, 0, 0, 0},
370
 
    {5.16397779494322, 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
 
    const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
471
 
    const static double W[4][1] = {{1}, {1}, {1}, {1}};
472
 
    const static 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 ffc_23_finite_element_0_0();
537
 
  }
538
 
 
539
 
};
540
 
 
541
 
/// This class defines the interface for a finite element.
542
 
 
543
 
class ffc_23_finite_element_0_1: public ufc::finite_element
544
 
{
545
 
public:
546
 
 
547
 
  /// Constructor
548
 
  ffc_23_finite_element_0_1() : ufc::finite_element()
549
 
  {
550
 
    // Do nothing
551
 
  }
552
 
 
553
 
  /// Destructor
554
 
  virtual ~ffc_23_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 "Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
685
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
686
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
687
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
688
 
    
689
 
    // Table(s) of coefficients
690
 
    const static double coefficients0[4][4] = \
691
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
692
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
693
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
694
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
871
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
872
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
873
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
874
 
    
875
 
    // Table(s) of coefficients
876
 
    const static double coefficients0[4][4] = \
877
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
878
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
879
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
880
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
881
 
    
882
 
    // Interesting (new) part
883
 
    // Tables of derivatives of the polynomial base (transpose)
884
 
    const static double dmats0[4][4] = \
885
 
    {{0, 0, 0, 0},
886
 
    {6.32455532033676, 0, 0, 0},
887
 
    {0, 0, 0, 0},
888
 
    {0, 0, 0, 0}};
889
 
    
890
 
    const static double dmats1[4][4] = \
891
 
    {{0, 0, 0, 0},
892
 
    {3.16227766016838, 0, 0, 0},
893
 
    {5.47722557505166, 0, 0, 0},
894
 
    {0, 0, 0, 0}};
895
 
    
896
 
    const static double dmats2[4][4] = \
897
 
    {{0, 0, 0, 0},
898
 
    {3.16227766016838, 0, 0, 0},
899
 
    {1.82574185835055, 0, 0, 0},
900
 
    {5.16397779494322, 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
 
    const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
1001
 
    const static double W[4][1] = {{1}, {1}, {1}, {1}};
1002
 
    const static 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 ffc_23_finite_element_0_1();
1067
 
  }
1068
 
 
1069
 
};
1070
 
 
1071
 
/// This class defines the interface for a finite element.
1072
 
 
1073
 
class ffc_23_finite_element_0_2: public ufc::finite_element
1074
 
{
1075
 
public:
1076
 
 
1077
 
  /// Constructor
1078
 
  ffc_23_finite_element_0_2() : ufc::finite_element()
1079
 
  {
1080
 
    // Do nothing
1081
 
  }
1082
 
 
1083
 
  /// Destructor
1084
 
  virtual ~ffc_23_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 "Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1215
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1216
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1217
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1218
 
    
1219
 
    // Table(s) of coefficients
1220
 
    const static double coefficients0[4][4] = \
1221
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1222
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1223
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1224
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1401
 
    const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1402
 
    const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1403
 
    const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1404
 
    
1405
 
    // Table(s) of coefficients
1406
 
    const static double coefficients0[4][4] = \
1407
 
    {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1408
 
    {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1409
 
    {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1410
 
    {0.288675134594813, 0, 0, 0.223606797749979}};
1411
 
    
1412
 
    // Interesting (new) part
1413
 
    // Tables of derivatives of the polynomial base (transpose)
1414
 
    const static double dmats0[4][4] = \
1415
 
    {{0, 0, 0, 0},
1416
 
    {6.32455532033676, 0, 0, 0},
1417
 
    {0, 0, 0, 0},
1418
 
    {0, 0, 0, 0}};
1419
 
    
1420
 
    const static double dmats1[4][4] = \
1421
 
    {{0, 0, 0, 0},
1422
 
    {3.16227766016838, 0, 0, 0},
1423
 
    {5.47722557505166, 0, 0, 0},
1424
 
    {0, 0, 0, 0}};
1425
 
    
1426
 
    const static double dmats2[4][4] = \
1427
 
    {{0, 0, 0, 0},
1428
 
    {3.16227766016838, 0, 0, 0},
1429
 
    {1.82574185835055, 0, 0, 0},
1430
 
    {5.16397779494322, 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
 
    const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
1531
 
    const static double W[4][1] = {{1}, {1}, {1}, {1}};
1532
 
    const static 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 ffc_23_finite_element_0_2();
1597
 
  }
1598
 
 
1599
 
};
1600
 
 
1601
 
/// This class defines the interface for a finite element.
1602
 
 
1603
 
class ffc_23_finite_element_0: public ufc::finite_element
1604
 
{
1605
 
public:
1606
 
 
1607
 
  /// Constructor
1608
 
  ffc_23_finite_element_0() : ufc::finite_element()
1609
 
  {
1610
 
    // Do nothing
1611
 
  }
1612
 
 
1613
 
  /// Destructor
1614
 
  virtual ~ffc_23_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 "Mixed finite element: [Discontinuous Lagrange finite element of degree 1 on a tetrahedron, Discontinuous Lagrange finite element of degree 1 on a tetrahedron, Discontinuous Lagrange finite element of degree 1 on a tetrahedron]";
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1749
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1750
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1751
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1752
 
    
1753
 
      // Table(s) of coefficients
1754
 
      const static double coefficients0[4][4] =   \
1755
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1756
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1757
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1758
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1798
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1799
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1800
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1801
 
    
1802
 
      // Table(s) of coefficients
1803
 
      const static double coefficients0[4][4] =   \
1804
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1805
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1806
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1807
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1847
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1848
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1849
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1850
 
    
1851
 
      // Table(s) of coefficients
1852
 
      const static double coefficients0[4][4] =   \
1853
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1854
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1855
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1856
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
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-14)
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-14)
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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2037
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2038
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2039
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2040
 
    
2041
 
      // Table(s) of coefficients
2042
 
      const static double coefficients0[4][4] =   \
2043
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
2044
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
2045
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
2046
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
2047
 
    
2048
 
      // Interesting (new) part
2049
 
      // Tables of derivatives of the polynomial base (transpose)
2050
 
      const static double dmats0[4][4] =   \
2051
 
      {{0, 0, 0, 0},
2052
 
      {6.32455532033676, 0, 0, 0},
2053
 
      {0, 0, 0, 0},
2054
 
      {0, 0, 0, 0}};
2055
 
    
2056
 
      const static double dmats1[4][4] =   \
2057
 
      {{0, 0, 0, 0},
2058
 
      {3.16227766016838, 0, 0, 0},
2059
 
      {5.47722557505166, 0, 0, 0},
2060
 
      {0, 0, 0, 0}};
2061
 
    
2062
 
      const static double dmats2[4][4] =   \
2063
 
      {{0, 0, 0, 0},
2064
 
      {3.16227766016838, 0, 0, 0},
2065
 
      {1.82574185835055, 0, 0, 0},
2066
 
      {5.16397779494322, 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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2179
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2180
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2181
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2182
 
    
2183
 
      // Table(s) of coefficients
2184
 
      const static double coefficients0[4][4] =   \
2185
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
2186
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
2187
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
2188
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
2189
 
    
2190
 
      // Interesting (new) part
2191
 
      // Tables of derivatives of the polynomial base (transpose)
2192
 
      const static double dmats0[4][4] =   \
2193
 
      {{0, 0, 0, 0},
2194
 
      {6.32455532033676, 0, 0, 0},
2195
 
      {0, 0, 0, 0},
2196
 
      {0, 0, 0, 0}};
2197
 
    
2198
 
      const static double dmats1[4][4] =   \
2199
 
      {{0, 0, 0, 0},
2200
 
      {3.16227766016838, 0, 0, 0},
2201
 
      {5.47722557505166, 0, 0, 0},
2202
 
      {0, 0, 0, 0}};
2203
 
    
2204
 
      const static double dmats2[4][4] =   \
2205
 
      {{0, 0, 0, 0},
2206
 
      {3.16227766016838, 0, 0, 0},
2207
 
      {1.82574185835055, 0, 0, 0},
2208
 
      {5.16397779494322, 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.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2321
 
      const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2322
 
      const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2323
 
      const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2324
 
    
2325
 
      // Table(s) of coefficients
2326
 
      const static double coefficients0[4][4] =   \
2327
 
      {{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
2328
 
      {0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
2329
 
      {0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
2330
 
      {0.288675134594813, 0, 0, 0.223606797749979}};
2331
 
    
2332
 
      // Interesting (new) part
2333
 
      // Tables of derivatives of the polynomial base (transpose)
2334
 
      const static double dmats0[4][4] =   \
2335
 
      {{0, 0, 0, 0},
2336
 
      {6.32455532033676, 0, 0, 0},
2337
 
      {0, 0, 0, 0},
2338
 
      {0, 0, 0, 0}};
2339
 
    
2340
 
      const static double dmats1[4][4] =   \
2341
 
      {{0, 0, 0, 0},
2342
 
      {3.16227766016838, 0, 0, 0},
2343
 
      {5.47722557505166, 0, 0, 0},
2344
 
      {0, 0, 0, 0}};
2345
 
    
2346
 
      const static double dmats2[4][4] =   \
2347
 
      {{0, 0, 0, 0},
2348
 
      {3.16227766016838, 0, 0, 0},
2349
 
      {1.82574185835055, 0, 0, 0},
2350
 
      {5.16397779494322, 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
 
    const static 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
 
    const static double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
2454
 
    const static 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[1] = dof_values[1];
2505
 
    vertex_values[2] = dof_values[2];
2506
 
    vertex_values[3] = dof_values[3];
2507
 
    // Evaluate at vertices and use affine mapping
2508
 
    vertex_values[4] = dof_values[4];
2509
 
    vertex_values[5] = dof_values[5];
2510
 
    vertex_values[6] = dof_values[6];
2511
 
    vertex_values[7] = dof_values[7];
2512
 
    // Evaluate at vertices and use affine mapping
2513
 
    vertex_values[8] = dof_values[8];
2514
 
    vertex_values[9] = dof_values[9];
2515
 
    vertex_values[10] = 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 ffc_23_finite_element_0_0();
2532
 
      break;
2533
 
    case 1:
2534
 
      return new ffc_23_finite_element_0_1();
2535
 
      break;
2536
 
    case 2:
2537
 
      return new ffc_23_finite_element_0_2();
2538
 
      break;
2539
 
    }
2540
 
    return 0;
2541
 
  }
2542
 
 
2543
 
};
2544
 
 
2545
 
/// This class defines the interface for a local-to-global mapping of
2546
 
/// degrees of freedom (dofs).
2547
 
 
2548
 
class ffc_23_dof_map_0_0: public ufc::dof_map
2549
 
{
2550
 
private:
2551
 
 
2552
 
  unsigned int __global_dimension;
2553
 
 
2554
 
public:
2555
 
 
2556
 
  /// Constructor
2557
 
  ffc_23_dof_map_0_0() : ufc::dof_map()
2558
 
  {
2559
 
    __global_dimension = 0;
2560
 
  }
2561
 
 
2562
 
  /// Destructor
2563
 
  virtual ~ffc_23_dof_map_0_0()
2564
 
  {
2565
 
    // Do nothing
2566
 
  }
2567
 
 
2568
 
  /// Return a string identifying the dof map
2569
 
  virtual const char* signature() const
2570
 
  {
2571
 
    return "FFC dof map for Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
2572
 
  }
2573
 
 
2574
 
  /// Return true iff mesh entities of topological dimension d are needed
2575
 
  virtual bool needs_mesh_entities(unsigned int d) const
2576
 
  {
2577
 
    switch ( d )
2578
 
    {
2579
 
    case 0:
2580
 
      return false;
2581
 
      break;
2582
 
    case 1:
2583
 
      return false;
2584
 
      break;
2585
 
    case 2:
2586
 
      return false;
2587
 
      break;
2588
 
    case 3:
2589
 
      return true;
2590
 
      break;
2591
 
    }
2592
 
    return false;
2593
 
  }
2594
 
 
2595
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
2596
 
  virtual bool init_mesh(const ufc::mesh& m)
2597
 
  {
2598
 
    __global_dimension = 4*m.num_entities[3];
2599
 
    return false;
2600
 
  }
2601
 
 
2602
 
  /// Initialize dof map for given cell
2603
 
  virtual void init_cell(const ufc::mesh& m,
2604
 
                         const ufc::cell& c)
2605
 
  {
2606
 
    // Do nothing
2607
 
  }
2608
 
 
2609
 
  /// Finish initialization of dof map for cells
2610
 
  virtual void init_cell_finalize()
2611
 
  {
2612
 
    // Do nothing
2613
 
  }
2614
 
 
2615
 
  /// Return the dimension of the global finite element function space
2616
 
  virtual unsigned int global_dimension() const
2617
 
  {
2618
 
    return __global_dimension;
2619
 
  }
2620
 
 
2621
 
  /// Return the dimension of the local finite element function space
2622
 
  virtual unsigned int local_dimension() const
2623
 
  {
2624
 
    return 4;
2625
 
  }
2626
 
 
2627
 
  // Return the geometric dimension of the coordinates this dof map provides
2628
 
  virtual unsigned int geometric_dimension() const
2629
 
  {
2630
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2631
 
  }
2632
 
 
2633
 
  /// Return the number of dofs on each cell facet
2634
 
  virtual unsigned int num_facet_dofs() const
2635
 
  {
2636
 
    return 0;
2637
 
  }
2638
 
 
2639
 
  /// Return the number of dofs associated with each cell entity of dimension d
2640
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
2641
 
  {
2642
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2643
 
  }
2644
 
 
2645
 
  /// Tabulate the local-to-global mapping of dofs on a cell
2646
 
  virtual void tabulate_dofs(unsigned int* dofs,
2647
 
                             const ufc::mesh& m,
2648
 
                             const ufc::cell& c) const
2649
 
  {
2650
 
    dofs[0] = 4*c.entity_indices[3][0];
2651
 
    dofs[1] = 4*c.entity_indices[3][0] + 1;
2652
 
    dofs[2] = 4*c.entity_indices[3][0] + 2;
2653
 
    dofs[3] = 4*c.entity_indices[3][0] + 3;
2654
 
  }
2655
 
 
2656
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
2657
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
2658
 
                                   unsigned int facet) const
2659
 
  {
2660
 
    switch ( facet )
2661
 
    {
2662
 
    case 0:
2663
 
      
2664
 
      break;
2665
 
    case 1:
2666
 
      
2667
 
      break;
2668
 
    case 2:
2669
 
      
2670
 
      break;
2671
 
    case 3:
2672
 
      
2673
 
      break;
2674
 
    }
2675
 
  }
2676
 
 
2677
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
2678
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
2679
 
                                    unsigned int d, unsigned int i) const
2680
 
  {
2681
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2682
 
  }
2683
 
 
2684
 
  /// Tabulate the coordinates of all dofs on a cell
2685
 
  virtual void tabulate_coordinates(double** coordinates,
2686
 
                                    const ufc::cell& c) const
2687
 
  {
2688
 
    const double * const * x = c.coordinates;
2689
 
    coordinates[0][0] = x[0][0];
2690
 
    coordinates[0][1] = x[0][1];
2691
 
    coordinates[0][2] = x[0][2];
2692
 
    coordinates[1][0] = x[1][0];
2693
 
    coordinates[1][1] = x[1][1];
2694
 
    coordinates[1][2] = x[1][2];
2695
 
    coordinates[2][0] = x[2][0];
2696
 
    coordinates[2][1] = x[2][1];
2697
 
    coordinates[2][2] = x[2][2];
2698
 
    coordinates[3][0] = x[3][0];
2699
 
    coordinates[3][1] = x[3][1];
2700
 
    coordinates[3][2] = x[3][2];
2701
 
  }
2702
 
 
2703
 
  /// Return the number of sub dof maps (for a mixed element)
2704
 
  virtual unsigned int num_sub_dof_maps() const
2705
 
  {
2706
 
    return 1;
2707
 
  }
2708
 
 
2709
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
2710
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
2711
 
  {
2712
 
    return new ffc_23_dof_map_0_0();
2713
 
  }
2714
 
 
2715
 
};
2716
 
 
2717
 
/// This class defines the interface for a local-to-global mapping of
2718
 
/// degrees of freedom (dofs).
2719
 
 
2720
 
class ffc_23_dof_map_0_1: public ufc::dof_map
2721
 
{
2722
 
private:
2723
 
 
2724
 
  unsigned int __global_dimension;
2725
 
 
2726
 
public:
2727
 
 
2728
 
  /// Constructor
2729
 
  ffc_23_dof_map_0_1() : ufc::dof_map()
2730
 
  {
2731
 
    __global_dimension = 0;
2732
 
  }
2733
 
 
2734
 
  /// Destructor
2735
 
  virtual ~ffc_23_dof_map_0_1()
2736
 
  {
2737
 
    // Do nothing
2738
 
  }
2739
 
 
2740
 
  /// Return a string identifying the dof map
2741
 
  virtual const char* signature() const
2742
 
  {
2743
 
    return "FFC dof map for Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
2744
 
  }
2745
 
 
2746
 
  /// Return true iff mesh entities of topological dimension d are needed
2747
 
  virtual bool needs_mesh_entities(unsigned int d) const
2748
 
  {
2749
 
    switch ( d )
2750
 
    {
2751
 
    case 0:
2752
 
      return false;
2753
 
      break;
2754
 
    case 1:
2755
 
      return false;
2756
 
      break;
2757
 
    case 2:
2758
 
      return false;
2759
 
      break;
2760
 
    case 3:
2761
 
      return true;
2762
 
      break;
2763
 
    }
2764
 
    return false;
2765
 
  }
2766
 
 
2767
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
2768
 
  virtual bool init_mesh(const ufc::mesh& m)
2769
 
  {
2770
 
    __global_dimension = 4*m.num_entities[3];
2771
 
    return false;
2772
 
  }
2773
 
 
2774
 
  /// Initialize dof map for given cell
2775
 
  virtual void init_cell(const ufc::mesh& m,
2776
 
                         const ufc::cell& c)
2777
 
  {
2778
 
    // Do nothing
2779
 
  }
2780
 
 
2781
 
  /// Finish initialization of dof map for cells
2782
 
  virtual void init_cell_finalize()
2783
 
  {
2784
 
    // Do nothing
2785
 
  }
2786
 
 
2787
 
  /// Return the dimension of the global finite element function space
2788
 
  virtual unsigned int global_dimension() const
2789
 
  {
2790
 
    return __global_dimension;
2791
 
  }
2792
 
 
2793
 
  /// Return the dimension of the local finite element function space
2794
 
  virtual unsigned int local_dimension() const
2795
 
  {
2796
 
    return 4;
2797
 
  }
2798
 
 
2799
 
  // Return the geometric dimension of the coordinates this dof map provides
2800
 
  virtual unsigned int geometric_dimension() const
2801
 
  {
2802
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2803
 
  }
2804
 
 
2805
 
  /// Return the number of dofs on each cell facet
2806
 
  virtual unsigned int num_facet_dofs() const
2807
 
  {
2808
 
    return 0;
2809
 
  }
2810
 
 
2811
 
  /// Return the number of dofs associated with each cell entity of dimension d
2812
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
2813
 
  {
2814
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2815
 
  }
2816
 
 
2817
 
  /// Tabulate the local-to-global mapping of dofs on a cell
2818
 
  virtual void tabulate_dofs(unsigned int* dofs,
2819
 
                             const ufc::mesh& m,
2820
 
                             const ufc::cell& c) const
2821
 
  {
2822
 
    dofs[0] = 4*c.entity_indices[3][0];
2823
 
    dofs[1] = 4*c.entity_indices[3][0] + 1;
2824
 
    dofs[2] = 4*c.entity_indices[3][0] + 2;
2825
 
    dofs[3] = 4*c.entity_indices[3][0] + 3;
2826
 
  }
2827
 
 
2828
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
2829
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
2830
 
                                   unsigned int facet) const
2831
 
  {
2832
 
    switch ( facet )
2833
 
    {
2834
 
    case 0:
2835
 
      
2836
 
      break;
2837
 
    case 1:
2838
 
      
2839
 
      break;
2840
 
    case 2:
2841
 
      
2842
 
      break;
2843
 
    case 3:
2844
 
      
2845
 
      break;
2846
 
    }
2847
 
  }
2848
 
 
2849
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
2850
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
2851
 
                                    unsigned int d, unsigned int i) const
2852
 
  {
2853
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2854
 
  }
2855
 
 
2856
 
  /// Tabulate the coordinates of all dofs on a cell
2857
 
  virtual void tabulate_coordinates(double** coordinates,
2858
 
                                    const ufc::cell& c) const
2859
 
  {
2860
 
    const double * const * x = c.coordinates;
2861
 
    coordinates[0][0] = x[0][0];
2862
 
    coordinates[0][1] = x[0][1];
2863
 
    coordinates[0][2] = x[0][2];
2864
 
    coordinates[1][0] = x[1][0];
2865
 
    coordinates[1][1] = x[1][1];
2866
 
    coordinates[1][2] = x[1][2];
2867
 
    coordinates[2][0] = x[2][0];
2868
 
    coordinates[2][1] = x[2][1];
2869
 
    coordinates[2][2] = x[2][2];
2870
 
    coordinates[3][0] = x[3][0];
2871
 
    coordinates[3][1] = x[3][1];
2872
 
    coordinates[3][2] = x[3][2];
2873
 
  }
2874
 
 
2875
 
  /// Return the number of sub dof maps (for a mixed element)
2876
 
  virtual unsigned int num_sub_dof_maps() const
2877
 
  {
2878
 
    return 1;
2879
 
  }
2880
 
 
2881
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
2882
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
2883
 
  {
2884
 
    return new ffc_23_dof_map_0_1();
2885
 
  }
2886
 
 
2887
 
};
2888
 
 
2889
 
/// This class defines the interface for a local-to-global mapping of
2890
 
/// degrees of freedom (dofs).
2891
 
 
2892
 
class ffc_23_dof_map_0_2: public ufc::dof_map
2893
 
{
2894
 
private:
2895
 
 
2896
 
  unsigned int __global_dimension;
2897
 
 
2898
 
public:
2899
 
 
2900
 
  /// Constructor
2901
 
  ffc_23_dof_map_0_2() : ufc::dof_map()
2902
 
  {
2903
 
    __global_dimension = 0;
2904
 
  }
2905
 
 
2906
 
  /// Destructor
2907
 
  virtual ~ffc_23_dof_map_0_2()
2908
 
  {
2909
 
    // Do nothing
2910
 
  }
2911
 
 
2912
 
  /// Return a string identifying the dof map
2913
 
  virtual const char* signature() const
2914
 
  {
2915
 
    return "FFC dof map for Discontinuous Lagrange finite element of degree 1 on a tetrahedron";
2916
 
  }
2917
 
 
2918
 
  /// Return true iff mesh entities of topological dimension d are needed
2919
 
  virtual bool needs_mesh_entities(unsigned int d) const
2920
 
  {
2921
 
    switch ( d )
2922
 
    {
2923
 
    case 0:
2924
 
      return false;
2925
 
      break;
2926
 
    case 1:
2927
 
      return false;
2928
 
      break;
2929
 
    case 2:
2930
 
      return false;
2931
 
      break;
2932
 
    case 3:
2933
 
      return true;
2934
 
      break;
2935
 
    }
2936
 
    return false;
2937
 
  }
2938
 
 
2939
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
2940
 
  virtual bool init_mesh(const ufc::mesh& m)
2941
 
  {
2942
 
    __global_dimension = 4*m.num_entities[3];
2943
 
    return false;
2944
 
  }
2945
 
 
2946
 
  /// Initialize dof map for given cell
2947
 
  virtual void init_cell(const ufc::mesh& m,
2948
 
                         const ufc::cell& c)
2949
 
  {
2950
 
    // Do nothing
2951
 
  }
2952
 
 
2953
 
  /// Finish initialization of dof map for cells
2954
 
  virtual void init_cell_finalize()
2955
 
  {
2956
 
    // Do nothing
2957
 
  }
2958
 
 
2959
 
  /// Return the dimension of the global finite element function space
2960
 
  virtual unsigned int global_dimension() const
2961
 
  {
2962
 
    return __global_dimension;
2963
 
  }
2964
 
 
2965
 
  /// Return the dimension of the local finite element function space
2966
 
  virtual unsigned int local_dimension() const
2967
 
  {
2968
 
    return 4;
2969
 
  }
2970
 
 
2971
 
  // Return the geometric dimension of the coordinates this dof map provides
2972
 
  virtual unsigned int geometric_dimension() const
2973
 
  {
2974
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2975
 
  }
2976
 
 
2977
 
  /// Return the number of dofs on each cell facet
2978
 
  virtual unsigned int num_facet_dofs() const
2979
 
  {
2980
 
    return 0;
2981
 
  }
2982
 
 
2983
 
  /// Return the number of dofs associated with each cell entity of dimension d
2984
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
2985
 
  {
2986
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2987
 
  }
2988
 
 
2989
 
  /// Tabulate the local-to-global mapping of dofs on a cell
2990
 
  virtual void tabulate_dofs(unsigned int* dofs,
2991
 
                             const ufc::mesh& m,
2992
 
                             const ufc::cell& c) const
2993
 
  {
2994
 
    dofs[0] = 4*c.entity_indices[3][0];
2995
 
    dofs[1] = 4*c.entity_indices[3][0] + 1;
2996
 
    dofs[2] = 4*c.entity_indices[3][0] + 2;
2997
 
    dofs[3] = 4*c.entity_indices[3][0] + 3;
2998
 
  }
2999
 
 
3000
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
3001
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
3002
 
                                   unsigned int facet) const
3003
 
  {
3004
 
    switch ( facet )
3005
 
    {
3006
 
    case 0:
3007
 
      
3008
 
      break;
3009
 
    case 1:
3010
 
      
3011
 
      break;
3012
 
    case 2:
3013
 
      
3014
 
      break;
3015
 
    case 3:
3016
 
      
3017
 
      break;
3018
 
    }
3019
 
  }
3020
 
 
3021
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
3022
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
3023
 
                                    unsigned int d, unsigned int i) const
3024
 
  {
3025
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3026
 
  }
3027
 
 
3028
 
  /// Tabulate the coordinates of all dofs on a cell
3029
 
  virtual void tabulate_coordinates(double** coordinates,
3030
 
                                    const ufc::cell& c) const
3031
 
  {
3032
 
    const double * const * x = c.coordinates;
3033
 
    coordinates[0][0] = x[0][0];
3034
 
    coordinates[0][1] = x[0][1];
3035
 
    coordinates[0][2] = x[0][2];
3036
 
    coordinates[1][0] = x[1][0];
3037
 
    coordinates[1][1] = x[1][1];
3038
 
    coordinates[1][2] = x[1][2];
3039
 
    coordinates[2][0] = x[2][0];
3040
 
    coordinates[2][1] = x[2][1];
3041
 
    coordinates[2][2] = x[2][2];
3042
 
    coordinates[3][0] = x[3][0];
3043
 
    coordinates[3][1] = x[3][1];
3044
 
    coordinates[3][2] = x[3][2];
3045
 
  }
3046
 
 
3047
 
  /// Return the number of sub dof maps (for a mixed element)
3048
 
  virtual unsigned int num_sub_dof_maps() const
3049
 
  {
3050
 
    return 1;
3051
 
  }
3052
 
 
3053
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
3054
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
3055
 
  {
3056
 
    return new ffc_23_dof_map_0_2();
3057
 
  }
3058
 
 
3059
 
};
3060
 
 
3061
 
/// This class defines the interface for a local-to-global mapping of
3062
 
/// degrees of freedom (dofs).
3063
 
 
3064
 
class ffc_23_dof_map_0: public ufc::dof_map
3065
 
{
3066
 
private:
3067
 
 
3068
 
  unsigned int __global_dimension;
3069
 
 
3070
 
public:
3071
 
 
3072
 
  /// Constructor
3073
 
  ffc_23_dof_map_0() : ufc::dof_map()
3074
 
  {
3075
 
    __global_dimension = 0;
3076
 
  }
3077
 
 
3078
 
  /// Destructor
3079
 
  virtual ~ffc_23_dof_map_0()
3080
 
  {
3081
 
    // Do nothing
3082
 
  }
3083
 
 
3084
 
  /// Return a string identifying the dof map
3085
 
  virtual const char* signature() const
3086
 
  {
3087
 
    return "FFC dof map for Mixed finite element: [Discontinuous Lagrange finite element of degree 1 on a tetrahedron, Discontinuous Lagrange finite element of degree 1 on a tetrahedron, Discontinuous Lagrange finite element of degree 1 on a tetrahedron]";
3088
 
  }
3089
 
 
3090
 
  /// Return true iff mesh entities of topological dimension d are needed
3091
 
  virtual bool needs_mesh_entities(unsigned int d) const
3092
 
  {
3093
 
    switch ( d )
3094
 
    {
3095
 
    case 0:
3096
 
      return false;
3097
 
      break;
3098
 
    case 1:
3099
 
      return false;
3100
 
      break;
3101
 
    case 2:
3102
 
      return false;
3103
 
      break;
3104
 
    case 3:
3105
 
      return true;
3106
 
      break;
3107
 
    }
3108
 
    return false;
3109
 
  }
3110
 
 
3111
 
  /// Initialize dof map for mesh (return true iff init_cell() is needed)
3112
 
  virtual bool init_mesh(const ufc::mesh& m)
3113
 
  {
3114
 
    __global_dimension = 12*m.num_entities[3];
3115
 
    return false;
3116
 
  }
3117
 
 
3118
 
  /// Initialize dof map for given cell
3119
 
  virtual void init_cell(const ufc::mesh& m,
3120
 
                         const ufc::cell& c)
3121
 
  {
3122
 
    // Do nothing
3123
 
  }
3124
 
 
3125
 
  /// Finish initialization of dof map for cells
3126
 
  virtual void init_cell_finalize()
3127
 
  {
3128
 
    // Do nothing
3129
 
  }
3130
 
 
3131
 
  /// Return the dimension of the global finite element function space
3132
 
  virtual unsigned int global_dimension() const
3133
 
  {
3134
 
    return __global_dimension;
3135
 
  }
3136
 
 
3137
 
  /// Return the dimension of the local finite element function space
3138
 
  virtual unsigned int local_dimension() const
3139
 
  {
3140
 
    return 12;
3141
 
  }
3142
 
 
3143
 
  // Return the geometric dimension of the coordinates this dof map provides
3144
 
  virtual unsigned int geometric_dimension() const
3145
 
  {
3146
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3147
 
  }
3148
 
 
3149
 
  /// Return the number of dofs on each cell facet
3150
 
  virtual unsigned int num_facet_dofs() const
3151
 
  {
3152
 
    return 0;
3153
 
  }
3154
 
 
3155
 
  /// Return the number of dofs associated with each cell entity of dimension d
3156
 
  virtual unsigned int num_entity_dofs(unsigned int d) const
3157
 
  {
3158
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3159
 
  }
3160
 
 
3161
 
  /// Tabulate the local-to-global mapping of dofs on a cell
3162
 
  virtual void tabulate_dofs(unsigned int* dofs,
3163
 
                             const ufc::mesh& m,
3164
 
                             const ufc::cell& c) const
3165
 
  {
3166
 
    dofs[0] = 4*c.entity_indices[3][0];
3167
 
    dofs[1] = 4*c.entity_indices[3][0] + 1;
3168
 
    dofs[2] = 4*c.entity_indices[3][0] + 2;
3169
 
    dofs[3] = 4*c.entity_indices[3][0] + 3;
3170
 
    unsigned int offset = 4*m.num_entities[3];
3171
 
    dofs[4] = offset + 4*c.entity_indices[3][0];
3172
 
    dofs[5] = offset + 4*c.entity_indices[3][0] + 1;
3173
 
    dofs[6] = offset + 4*c.entity_indices[3][0] + 2;
3174
 
    dofs[7] = offset + 4*c.entity_indices[3][0] + 3;
3175
 
    offset = offset + 4*m.num_entities[3];
3176
 
    dofs[8] = offset + 4*c.entity_indices[3][0];
3177
 
    dofs[9] = offset + 4*c.entity_indices[3][0] + 1;
3178
 
    dofs[10] = offset + 4*c.entity_indices[3][0] + 2;
3179
 
    dofs[11] = offset + 4*c.entity_indices[3][0] + 3;
3180
 
  }
3181
 
 
3182
 
  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
3183
 
  virtual void tabulate_facet_dofs(unsigned int* dofs,
3184
 
                                   unsigned int facet) const
3185
 
  {
3186
 
    switch ( facet )
3187
 
    {
3188
 
    case 0:
3189
 
      
3190
 
      break;
3191
 
    case 1:
3192
 
      
3193
 
      break;
3194
 
    case 2:
3195
 
      
3196
 
      break;
3197
 
    case 3:
3198
 
      
3199
 
      break;
3200
 
    }
3201
 
  }
3202
 
 
3203
 
  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
3204
 
  virtual void tabulate_entity_dofs(unsigned int* dofs,
3205
 
                                    unsigned int d, unsigned int i) const
3206
 
  {
3207
 
    throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3208
 
  }
3209
 
 
3210
 
  /// Tabulate the coordinates of all dofs on a cell
3211
 
  virtual void tabulate_coordinates(double** coordinates,
3212
 
                                    const ufc::cell& c) const
3213
 
  {
3214
 
    const double * const * x = c.coordinates;
3215
 
    coordinates[0][0] = x[0][0];
3216
 
    coordinates[0][1] = x[0][1];
3217
 
    coordinates[0][2] = x[0][2];
3218
 
    coordinates[1][0] = x[1][0];
3219
 
    coordinates[1][1] = x[1][1];
3220
 
    coordinates[1][2] = x[1][2];
3221
 
    coordinates[2][0] = x[2][0];
3222
 
    coordinates[2][1] = x[2][1];
3223
 
    coordinates[2][2] = x[2][2];
3224
 
    coordinates[3][0] = x[3][0];
3225
 
    coordinates[3][1] = x[3][1];
3226
 
    coordinates[3][2] = x[3][2];
3227
 
    coordinates[4][0] = x[0][0];
3228
 
    coordinates[4][1] = x[0][1];
3229
 
    coordinates[4][2] = x[0][2];
3230
 
    coordinates[5][0] = x[1][0];
3231
 
    coordinates[5][1] = x[1][1];
3232
 
    coordinates[5][2] = x[1][2];
3233
 
    coordinates[6][0] = x[2][0];
3234
 
    coordinates[6][1] = x[2][1];
3235
 
    coordinates[6][2] = x[2][2];
3236
 
    coordinates[7][0] = x[3][0];
3237
 
    coordinates[7][1] = x[3][1];
3238
 
    coordinates[7][2] = x[3][2];
3239
 
    coordinates[8][0] = x[0][0];
3240
 
    coordinates[8][1] = x[0][1];
3241
 
    coordinates[8][2] = x[0][2];
3242
 
    coordinates[9][0] = x[1][0];
3243
 
    coordinates[9][1] = x[1][1];
3244
 
    coordinates[9][2] = x[1][2];
3245
 
    coordinates[10][0] = x[2][0];
3246
 
    coordinates[10][1] = x[2][1];
3247
 
    coordinates[10][2] = x[2][2];
3248
 
    coordinates[11][0] = x[3][0];
3249
 
    coordinates[11][1] = x[3][1];
3250
 
    coordinates[11][2] = x[3][2];
3251
 
  }
3252
 
 
3253
 
  /// Return the number of sub dof maps (for a mixed element)
3254
 
  virtual unsigned int num_sub_dof_maps() const
3255
 
  {
3256
 
    return 3;
3257
 
  }
3258
 
 
3259
 
  /// Create a new dof_map for sub dof map i (for a mixed element)
3260
 
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
3261
 
  {
3262
 
    switch ( i )
3263
 
    {
3264
 
    case 0:
3265
 
      return new ffc_23_dof_map_0_0();
3266
 
      break;
3267
 
    case 1:
3268
 
      return new ffc_23_dof_map_0_1();
3269
 
      break;
3270
 
    case 2:
3271
 
      return new ffc_23_dof_map_0_2();
3272
 
      break;
3273
 
    }
3274
 
    return 0;
3275
 
  }
3276
 
 
3277
 
};
3278
 
 
3279
 
#endif