1
// This code conforms with the UFC specification version 1.0
2
// and was automatically generated by FFC version 0.4.3.
11
/// This class defines the interface for a finite element.
13
class ffc_16_finite_element_0_0: public ufc::finite_element
18
ffc_16_finite_element_0_0() : ufc::finite_element()
24
virtual ~ffc_16_finite_element_0_0()
29
/// Return a string identifying the finite element
30
virtual const char* signature() const
32
return "Lagrange finite element of degree 1 on a tetrahedron";
35
/// Return the cell shape
36
virtual ufc::shape cell_shape() const
38
return ufc::tetrahedron;
41
/// Return the dimension of the finite element function space
42
virtual unsigned int space_dimension() const
47
/// Return the rank of the value space
48
virtual unsigned int value_rank() const
53
/// Return the dimension of the value space for axis i
54
virtual unsigned int value_dimension(unsigned int i) const
59
/// Evaluate basis function i at given point in cell
60
virtual void evaluate_basis(unsigned int i,
62
const double* coordinates,
63
const ufc::cell& c) const
65
// Extract vertex coordinates
66
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
92
// Compute determinant of Jacobian
93
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
95
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
115
// Map coordinates to the reference cube
116
if (std::abs(y + z - 1.0) < 1e-14)
119
x = -2.0 * x/(y + z - 1.0) - 1.0;
120
if (std::abs(z - 1.0) < 1e-14)
123
y = 2.0 * y/(1.0 - z) - 1.0;
129
// Map degree of freedom to element degree of freedom
130
const unsigned int dof = i;
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);
138
// Compute psitilde_a
139
const double psitilde_a_0 = 1;
140
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
173
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
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
181
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
184
/// Evaluate order n derivatives of basis function i at given point in cell
185
virtual void evaluate_basis_derivatives(unsigned int i,
188
const double* coordinates,
189
const ufc::cell& c) const
191
// Extract vertex coordinates
192
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
218
// Compute determinant of Jacobian
219
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
221
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
241
// Map coordinates to the reference cube
242
if (std::abs(y + z - 1.0) < 1e-14)
245
x = -2.0 * x/(y + z - 1.0) - 1.0;
246
if (std::abs(z - 1.0) < 1e-14)
249
y = 2.0 * y/(1.0 - z) - 1.0;
252
// Compute number of derivatives
253
unsigned int num_derivatives = 1;
255
for (unsigned int j = 0; j < n; j++)
256
num_derivatives *= 3;
259
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
260
unsigned int **combinations = new unsigned int *[num_derivatives];
262
for (unsigned int j = 0; j < num_derivatives; j++)
264
combinations[j] = new unsigned int [n];
265
for (unsigned int k = 0; k < n; k++)
266
combinations[j][k] = 0;
269
// Generate combinations of derivatives
270
for (unsigned int row = 1; row < num_derivatives; row++)
272
for (unsigned int num = 0; num < row; num++)
274
for (unsigned int col = n-1; col+1 > 0; col--)
276
if (combinations[row][col] + 1 > 2)
277
combinations[row][col] = 0;
280
combinations[row][col] += 1;
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}};
290
// Declare transformation matrix
291
// Declare pointer to two dimensional array and initialise
292
double **transform = new double *[num_derivatives];
294
for (unsigned int j = 0; j < num_derivatives; j++)
296
transform[j] = new double [num_derivatives];
297
for (unsigned int k = 0; k < num_derivatives; k++)
301
// Construct transformation matrix
302
for (unsigned int row = 0; row < num_derivatives; row++)
304
for (unsigned int col = 0; col < num_derivatives; col++)
306
for (unsigned int k = 0; k < n; k++)
307
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
312
for (unsigned int j = 0; j < 1*num_derivatives; j++)
315
// Map degree of freedom to element degree of freedom
316
const unsigned int dof = i;
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);
324
// Compute psitilde_a
325
const double psitilde_a_0 = 1;
326
const double psitilde_a_1 = x;
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;
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;
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;
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}};
352
// Interesting (new) part
353
// Tables of derivatives of the polynomial base (transpose)
354
const static double dmats0[4][4] = \
356
{6.32455532033676, 0, 0, 0},
360
const static double dmats1[4][4] = \
362
{3.16227766016838, 0, 0, 0},
363
{5.47722557505166, 0, 0, 0},
366
const static double dmats2[4][4] = \
368
{3.16227766016838, 0, 0, 0},
369
{1.82574185835055, 0, 0, 0},
370
{5.16397779494322, 0, 0, 0}};
372
// Compute reference derivatives
373
// Declare pointer to array of derivatives on FIAT element
374
double *derivatives = new double [num_derivatives];
376
// Declare coefficients
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;
388
// Loop possible derivatives
389
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
397
// Loop derivative order
398
for (unsigned int j = 0; j < n; j++)
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;
406
if(combinations[deriv_num][j] == 0)
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];
413
if(combinations[deriv_num][j] == 1)
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];
420
if(combinations[deriv_num][j] == 2)
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];
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;
433
// Transform derivatives back to physical element
434
for (unsigned int row = 0; row < num_derivatives; row++)
436
for (unsigned int col = 0; col < num_derivatives; col++)
438
values[row] += transform[row][col]*derivatives[col];
441
// Delete pointer to array of derivatives on FIAT element
442
delete [] derivatives;
444
// Delete pointer to array of combinations of derivatives and transform
445
for (unsigned int row = 0; row < num_derivatives; row++)
447
delete [] combinations[row];
448
delete [] transform[row];
451
delete [] combinations;
455
/// Evaluate order n derivatives of all basis functions at given point in cell
456
virtual void evaluate_basis_derivatives_all(unsigned int n,
458
const double* coordinates,
459
const ufc::cell& c) const
461
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
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
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}}};
474
const double * const * x = c.coordinates;
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];
483
// Compute affine mapping y = F(X)
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];
489
// Evaluate function at physical points
491
f.evaluate(values, y, c);
493
// Map function values using appropriate mapping
494
// Affine map: Do nothing
496
// Note that we do not map the weights (yet).
498
// Take directional components
499
for(int k = 0; k < 1; k++)
500
result += values[k]*D[i][0][k];
501
// Multiply by weights
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
512
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
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
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];
527
/// Return the number of sub elements (for a mixed element)
528
virtual unsigned int num_sub_elements() const
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
536
return new ffc_16_finite_element_0_0();
541
/// This class defines the interface for a finite element.
543
class ffc_16_finite_element_0_1: public ufc::finite_element
548
ffc_16_finite_element_0_1() : ufc::finite_element()
554
virtual ~ffc_16_finite_element_0_1()
559
/// Return a string identifying the finite element
560
virtual const char* signature() const
562
return "Lagrange finite element of degree 1 on a tetrahedron";
565
/// Return the cell shape
566
virtual ufc::shape cell_shape() const
568
return ufc::tetrahedron;
571
/// Return the dimension of the finite element function space
572
virtual unsigned int space_dimension() const
577
/// Return the rank of the value space
578
virtual unsigned int value_rank() const
583
/// Return the dimension of the value space for axis i
584
virtual unsigned int value_dimension(unsigned int i) const
589
/// Evaluate basis function i at given point in cell
590
virtual void evaluate_basis(unsigned int i,
592
const double* coordinates,
593
const ufc::cell& c) const
595
// Extract vertex coordinates
596
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
622
// Compute determinant of Jacobian
623
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
625
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
645
// Map coordinates to the reference cube
646
if (std::abs(y + z - 1.0) < 1e-14)
649
x = -2.0 * x/(y + z - 1.0) - 1.0;
650
if (std::abs(z - 1.0) < 1e-14)
653
y = 2.0 * y/(1.0 - z) - 1.0;
659
// Map degree of freedom to element degree of freedom
660
const unsigned int dof = i;
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);
668
// Compute psitilde_a
669
const double psitilde_a_0 = 1;
670
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
703
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
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
711
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
714
/// Evaluate order n derivatives of basis function i at given point in cell
715
virtual void evaluate_basis_derivatives(unsigned int i,
718
const double* coordinates,
719
const ufc::cell& c) const
721
// Extract vertex coordinates
722
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
748
// Compute determinant of Jacobian
749
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
751
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
771
// Map coordinates to the reference cube
772
if (std::abs(y + z - 1.0) < 1e-14)
775
x = -2.0 * x/(y + z - 1.0) - 1.0;
776
if (std::abs(z - 1.0) < 1e-14)
779
y = 2.0 * y/(1.0 - z) - 1.0;
782
// Compute number of derivatives
783
unsigned int num_derivatives = 1;
785
for (unsigned int j = 0; j < n; j++)
786
num_derivatives *= 3;
789
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
790
unsigned int **combinations = new unsigned int *[num_derivatives];
792
for (unsigned int j = 0; j < num_derivatives; j++)
794
combinations[j] = new unsigned int [n];
795
for (unsigned int k = 0; k < n; k++)
796
combinations[j][k] = 0;
799
// Generate combinations of derivatives
800
for (unsigned int row = 1; row < num_derivatives; row++)
802
for (unsigned int num = 0; num < row; num++)
804
for (unsigned int col = n-1; col+1 > 0; col--)
806
if (combinations[row][col] + 1 > 2)
807
combinations[row][col] = 0;
810
combinations[row][col] += 1;
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}};
820
// Declare transformation matrix
821
// Declare pointer to two dimensional array and initialise
822
double **transform = new double *[num_derivatives];
824
for (unsigned int j = 0; j < num_derivatives; j++)
826
transform[j] = new double [num_derivatives];
827
for (unsigned int k = 0; k < num_derivatives; k++)
831
// Construct transformation matrix
832
for (unsigned int row = 0; row < num_derivatives; row++)
834
for (unsigned int col = 0; col < num_derivatives; col++)
836
for (unsigned int k = 0; k < n; k++)
837
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
842
for (unsigned int j = 0; j < 1*num_derivatives; j++)
845
// Map degree of freedom to element degree of freedom
846
const unsigned int dof = i;
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);
854
// Compute psitilde_a
855
const double psitilde_a_0 = 1;
856
const double psitilde_a_1 = x;
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;
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;
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;
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}};
882
// Interesting (new) part
883
// Tables of derivatives of the polynomial base (transpose)
884
const static double dmats0[4][4] = \
886
{6.32455532033676, 0, 0, 0},
890
const static double dmats1[4][4] = \
892
{3.16227766016838, 0, 0, 0},
893
{5.47722557505166, 0, 0, 0},
896
const static double dmats2[4][4] = \
898
{3.16227766016838, 0, 0, 0},
899
{1.82574185835055, 0, 0, 0},
900
{5.16397779494322, 0, 0, 0}};
902
// Compute reference derivatives
903
// Declare pointer to array of derivatives on FIAT element
904
double *derivatives = new double [num_derivatives];
906
// Declare coefficients
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;
918
// Loop possible derivatives
919
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
927
// Loop derivative order
928
for (unsigned int j = 0; j < n; j++)
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;
936
if(combinations[deriv_num][j] == 0)
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];
943
if(combinations[deriv_num][j] == 1)
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];
950
if(combinations[deriv_num][j] == 2)
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];
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;
963
// Transform derivatives back to physical element
964
for (unsigned int row = 0; row < num_derivatives; row++)
966
for (unsigned int col = 0; col < num_derivatives; col++)
968
values[row] += transform[row][col]*derivatives[col];
971
// Delete pointer to array of derivatives on FIAT element
972
delete [] derivatives;
974
// Delete pointer to array of combinations of derivatives and transform
975
for (unsigned int row = 0; row < num_derivatives; row++)
977
delete [] combinations[row];
978
delete [] transform[row];
981
delete [] combinations;
985
/// Evaluate order n derivatives of all basis functions at given point in cell
986
virtual void evaluate_basis_derivatives_all(unsigned int n,
988
const double* coordinates,
989
const ufc::cell& c) const
991
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
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
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}}};
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];
1013
// Compute affine mapping y = F(X)
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];
1019
// Evaluate function at physical points
1021
f.evaluate(values, y, c);
1023
// Map function values using appropriate mapping
1024
// Affine map: Do nothing
1026
// Note that we do not map the weights (yet).
1028
// Take directional components
1029
for(int k = 0; k < 1; k++)
1030
result += values[k]*D[i][0][k];
1031
// Multiply by weights
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
1042
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
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
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];
1057
/// Return the number of sub elements (for a mixed element)
1058
virtual unsigned int num_sub_elements() const
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
1066
return new ffc_16_finite_element_0_1();
1071
/// This class defines the interface for a finite element.
1073
class ffc_16_finite_element_0_2: public ufc::finite_element
1078
ffc_16_finite_element_0_2() : ufc::finite_element()
1084
virtual ~ffc_16_finite_element_0_2()
1089
/// Return a string identifying the finite element
1090
virtual const char* signature() const
1092
return "Lagrange finite element of degree 1 on a tetrahedron";
1095
/// Return the cell shape
1096
virtual ufc::shape cell_shape() const
1098
return ufc::tetrahedron;
1101
/// Return the dimension of the finite element function space
1102
virtual unsigned int space_dimension() const
1107
/// Return the rank of the value space
1108
virtual unsigned int value_rank() const
1113
/// Return the dimension of the value space for axis i
1114
virtual unsigned int value_dimension(unsigned int i) const
1119
/// Evaluate basis function i at given point in cell
1120
virtual void evaluate_basis(unsigned int i,
1122
const double* coordinates,
1123
const ufc::cell& c) const
1125
// Extract vertex coordinates
1126
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
1152
// Compute determinant of Jacobian
1153
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1155
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
1175
// Map coordinates to the reference cube
1176
if (std::abs(y + z - 1.0) < 1e-14)
1179
x = -2.0 * x/(y + z - 1.0) - 1.0;
1180
if (std::abs(z - 1.0) < 1e-14)
1183
y = 2.0 * y/(1.0 - z) - 1.0;
1189
// Map degree of freedom to element degree of freedom
1190
const unsigned int dof = i;
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);
1198
// Compute psitilde_a
1199
const double psitilde_a_0 = 1;
1200
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
1233
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
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
1241
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
1244
/// Evaluate order n derivatives of basis function i at given point in cell
1245
virtual void evaluate_basis_derivatives(unsigned int i,
1248
const double* coordinates,
1249
const ufc::cell& c) const
1251
// Extract vertex coordinates
1252
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
1278
// Compute determinant of Jacobian
1279
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1281
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
1301
// Map coordinates to the reference cube
1302
if (std::abs(y + z - 1.0) < 1e-14)
1305
x = -2.0 * x/(y + z - 1.0) - 1.0;
1306
if (std::abs(z - 1.0) < 1e-14)
1309
y = 2.0 * y/(1.0 - z) - 1.0;
1312
// Compute number of derivatives
1313
unsigned int num_derivatives = 1;
1315
for (unsigned int j = 0; j < n; j++)
1316
num_derivatives *= 3;
1319
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
1320
unsigned int **combinations = new unsigned int *[num_derivatives];
1322
for (unsigned int j = 0; j < num_derivatives; j++)
1324
combinations[j] = new unsigned int [n];
1325
for (unsigned int k = 0; k < n; k++)
1326
combinations[j][k] = 0;
1329
// Generate combinations of derivatives
1330
for (unsigned int row = 1; row < num_derivatives; row++)
1332
for (unsigned int num = 0; num < row; num++)
1334
for (unsigned int col = n-1; col+1 > 0; col--)
1336
if (combinations[row][col] + 1 > 2)
1337
combinations[row][col] = 0;
1340
combinations[row][col] += 1;
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}};
1350
// Declare transformation matrix
1351
// Declare pointer to two dimensional array and initialise
1352
double **transform = new double *[num_derivatives];
1354
for (unsigned int j = 0; j < num_derivatives; j++)
1356
transform[j] = new double [num_derivatives];
1357
for (unsigned int k = 0; k < num_derivatives; k++)
1358
transform[j][k] = 1;
1361
// Construct transformation matrix
1362
for (unsigned int row = 0; row < num_derivatives; row++)
1364
for (unsigned int col = 0; col < num_derivatives; col++)
1366
for (unsigned int k = 0; k < n; k++)
1367
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
1372
for (unsigned int j = 0; j < 1*num_derivatives; j++)
1375
// Map degree of freedom to element degree of freedom
1376
const unsigned int dof = i;
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);
1384
// Compute psitilde_a
1385
const double psitilde_a_0 = 1;
1386
const double psitilde_a_1 = x;
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;
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;
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;
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}};
1412
// Interesting (new) part
1413
// Tables of derivatives of the polynomial base (transpose)
1414
const static double dmats0[4][4] = \
1416
{6.32455532033676, 0, 0, 0},
1420
const static double dmats1[4][4] = \
1422
{3.16227766016838, 0, 0, 0},
1423
{5.47722557505166, 0, 0, 0},
1426
const static double dmats2[4][4] = \
1428
{3.16227766016838, 0, 0, 0},
1429
{1.82574185835055, 0, 0, 0},
1430
{5.16397779494322, 0, 0, 0}};
1432
// Compute reference derivatives
1433
// Declare pointer to array of derivatives on FIAT element
1434
double *derivatives = new double [num_derivatives];
1436
// Declare coefficients
1437
double coeff0_0 = 0;
1438
double coeff0_1 = 0;
1439
double coeff0_2 = 0;
1440
double coeff0_3 = 0;
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;
1448
// Loop possible derivatives
1449
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
1457
// Loop derivative order
1458
for (unsigned int j = 0; j < n; j++)
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;
1466
if(combinations[deriv_num][j] == 0)
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];
1473
if(combinations[deriv_num][j] == 1)
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];
1480
if(combinations[deriv_num][j] == 2)
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];
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;
1493
// Transform derivatives back to physical element
1494
for (unsigned int row = 0; row < num_derivatives; row++)
1496
for (unsigned int col = 0; col < num_derivatives; col++)
1498
values[row] += transform[row][col]*derivatives[col];
1501
// Delete pointer to array of derivatives on FIAT element
1502
delete [] derivatives;
1504
// Delete pointer to array of combinations of derivatives and transform
1505
for (unsigned int row = 0; row < num_derivatives; row++)
1507
delete [] combinations[row];
1508
delete [] transform[row];
1511
delete [] combinations;
1512
delete [] transform;
1515
/// Evaluate order n derivatives of all basis functions at given point in cell
1516
virtual void evaluate_basis_derivatives_all(unsigned int n,
1518
const double* coordinates,
1519
const ufc::cell& c) const
1521
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
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
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}}};
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];
1543
// Compute affine mapping y = F(X)
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];
1549
// Evaluate function at physical points
1551
f.evaluate(values, y, c);
1553
// Map function values using appropriate mapping
1554
// Affine map: Do nothing
1556
// Note that we do not map the weights (yet).
1558
// Take directional components
1559
for(int k = 0; k < 1; k++)
1560
result += values[k]*D[i][0][k];
1561
// Multiply by weights
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
1572
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
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
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];
1587
/// Return the number of sub elements (for a mixed element)
1588
virtual unsigned int num_sub_elements() const
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
1596
return new ffc_16_finite_element_0_2();
1601
/// This class defines the interface for a finite element.
1603
class ffc_16_finite_element_0: public ufc::finite_element
1608
ffc_16_finite_element_0() : ufc::finite_element()
1614
virtual ~ffc_16_finite_element_0()
1619
/// Return a string identifying the finite element
1620
virtual const char* signature() const
1622
return "Mixed finite element: [Lagrange finite element of degree 1 on a tetrahedron, Lagrange finite element of degree 1 on a tetrahedron, Lagrange finite element of degree 1 on a tetrahedron]";
1625
/// Return the cell shape
1626
virtual ufc::shape cell_shape() const
1628
return ufc::tetrahedron;
1631
/// Return the dimension of the finite element function space
1632
virtual unsigned int space_dimension() const
1637
/// Return the rank of the value space
1638
virtual unsigned int value_rank() const
1643
/// Return the dimension of the value space for axis i
1644
virtual unsigned int value_dimension(unsigned int i) const
1649
/// Evaluate basis function i at given point in cell
1650
virtual void evaluate_basis(unsigned int i,
1652
const double* coordinates,
1653
const ufc::cell& c) const
1655
// Extract vertex coordinates
1656
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
1682
// Compute determinant of Jacobian
1683
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1685
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
1705
// Map coordinates to the reference cube
1706
if (std::abs(y + z - 1.0) < 1e-14)
1709
x = -2.0 * x/(y + z - 1.0) - 1.0;
1710
if (std::abs(z - 1.0) < 1e-14)
1713
y = 2.0 * y/(1.0 - z) - 1.0;
1721
if (0 <= i && i <= 3)
1723
// Map degree of freedom to element degree of freedom
1724
const unsigned int dof = i;
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);
1732
// Compute psitilde_a
1733
const double psitilde_a_0 = 1;
1734
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
1767
values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1770
if (4 <= i && i <= 7)
1772
// Map degree of freedom to element degree of freedom
1773
const unsigned int dof = i - 4;
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);
1781
// Compute psitilde_a
1782
const double psitilde_a_0 = 1;
1783
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
1816
values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1819
if (8 <= i && i <= 11)
1821
// Map degree of freedom to element degree of freedom
1822
const unsigned int dof = i - 8;
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);
1830
// Compute psitilde_a
1831
const double psitilde_a_0 = 1;
1832
const double psitilde_a_1 = x;
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;
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;
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;
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}};
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];
1865
values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
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
1875
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
1878
/// Evaluate order n derivatives of basis function i at given point in cell
1879
virtual void evaluate_basis_derivatives(unsigned int i,
1882
const double* coordinates,
1883
const ufc::cell& c) const
1885
// Extract vertex coordinates
1886
const double * const * element_coordinates = c.coordinates;
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];
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;
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;
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;
1912
// Compute determinant of Jacobian
1913
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1915
// Compute inverse of Jacobian
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]);
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]);
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]);
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;
1935
// Map coordinates to the reference cube
1936
if (std::abs(y + z - 1.0) < 1e-14)
1939
x = -2.0 * x/(y + z - 1.0) - 1.0;
1940
if (std::abs(z - 1.0) < 1e-14)
1943
y = 2.0 * y/(1.0 - z) - 1.0;
1946
// Compute number of derivatives
1947
unsigned int num_derivatives = 1;
1949
for (unsigned int j = 0; j < n; j++)
1950
num_derivatives *= 3;
1953
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
1954
unsigned int **combinations = new unsigned int *[num_derivatives];
1956
for (unsigned int j = 0; j < num_derivatives; j++)
1958
combinations[j] = new unsigned int [n];
1959
for (unsigned int k = 0; k < n; k++)
1960
combinations[j][k] = 0;
1963
// Generate combinations of derivatives
1964
for (unsigned int row = 1; row < num_derivatives; row++)
1966
for (unsigned int num = 0; num < row; num++)
1968
for (unsigned int col = n-1; col+1 > 0; col--)
1970
if (combinations[row][col] + 1 > 2)
1971
combinations[row][col] = 0;
1974
combinations[row][col] += 1;
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}};
1984
// Declare transformation matrix
1985
// Declare pointer to two dimensional array and initialise
1986
double **transform = new double *[num_derivatives];
1988
for (unsigned int j = 0; j < num_derivatives; j++)
1990
transform[j] = new double [num_derivatives];
1991
for (unsigned int k = 0; k < num_derivatives; k++)
1992
transform[j][k] = 1;
1995
// Construct transformation matrix
1996
for (unsigned int row = 0; row < num_derivatives; row++)
1998
for (unsigned int col = 0; col < num_derivatives; col++)
2000
for (unsigned int k = 0; k < n; k++)
2001
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
2006
for (unsigned int j = 0; j < 3*num_derivatives; j++)
2009
if (0 <= i && i <= 3)
2011
// Map degree of freedom to element degree of freedom
2012
const unsigned int dof = i;
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);
2020
// Compute psitilde_a
2021
const double psitilde_a_0 = 1;
2022
const double psitilde_a_1 = x;
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;
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;
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;
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}};
2048
// Interesting (new) part
2049
// Tables of derivatives of the polynomial base (transpose)
2050
const static double dmats0[4][4] = \
2052
{6.32455532033676, 0, 0, 0},
2056
const static double dmats1[4][4] = \
2058
{3.16227766016838, 0, 0, 0},
2059
{5.47722557505166, 0, 0, 0},
2062
const static double dmats2[4][4] = \
2064
{3.16227766016838, 0, 0, 0},
2065
{1.82574185835055, 0, 0, 0},
2066
{5.16397779494322, 0, 0, 0}};
2068
// Compute reference derivatives
2069
// Declare pointer to array of derivatives on FIAT element
2070
double *derivatives = new double [num_derivatives];
2072
// Declare coefficients
2073
double coeff0_0 = 0;
2074
double coeff0_1 = 0;
2075
double coeff0_2 = 0;
2076
double coeff0_3 = 0;
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;
2084
// Loop possible derivatives
2085
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
2093
// Loop derivative order
2094
for (unsigned int j = 0; j < n; j++)
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;
2102
if(combinations[deriv_num][j] == 0)
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];
2109
if(combinations[deriv_num][j] == 1)
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];
2116
if(combinations[deriv_num][j] == 2)
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];
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;
2129
// Transform derivatives back to physical element
2130
for (unsigned int row = 0; row < num_derivatives; row++)
2132
for (unsigned int col = 0; col < num_derivatives; col++)
2134
values[row] += transform[row][col]*derivatives[col];
2137
// Delete pointer to array of derivatives on FIAT element
2138
delete [] derivatives;
2140
// Delete pointer to array of combinations of derivatives and transform
2141
for (unsigned int row = 0; row < num_derivatives; row++)
2143
delete [] combinations[row];
2144
delete [] transform[row];
2147
delete [] combinations;
2148
delete [] transform;
2151
if (4 <= i && i <= 7)
2153
// Map degree of freedom to element degree of freedom
2154
const unsigned int dof = i - 4;
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);
2162
// Compute psitilde_a
2163
const double psitilde_a_0 = 1;
2164
const double psitilde_a_1 = x;
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;
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;
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;
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}};
2190
// Interesting (new) part
2191
// Tables of derivatives of the polynomial base (transpose)
2192
const static double dmats0[4][4] = \
2194
{6.32455532033676, 0, 0, 0},
2198
const static double dmats1[4][4] = \
2200
{3.16227766016838, 0, 0, 0},
2201
{5.47722557505166, 0, 0, 0},
2204
const static double dmats2[4][4] = \
2206
{3.16227766016838, 0, 0, 0},
2207
{1.82574185835055, 0, 0, 0},
2208
{5.16397779494322, 0, 0, 0}};
2210
// Compute reference derivatives
2211
// Declare pointer to array of derivatives on FIAT element
2212
double *derivatives = new double [num_derivatives];
2214
// Declare coefficients
2215
double coeff0_0 = 0;
2216
double coeff0_1 = 0;
2217
double coeff0_2 = 0;
2218
double coeff0_3 = 0;
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;
2226
// Loop possible derivatives
2227
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
2235
// Loop derivative order
2236
for (unsigned int j = 0; j < n; j++)
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;
2244
if(combinations[deriv_num][j] == 0)
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];
2251
if(combinations[deriv_num][j] == 1)
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];
2258
if(combinations[deriv_num][j] == 2)
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];
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;
2271
// Transform derivatives back to physical element
2272
for (unsigned int row = 0; row < num_derivatives; row++)
2274
for (unsigned int col = 0; col < num_derivatives; col++)
2276
values[num_derivatives + row] += transform[row][col]*derivatives[col];
2279
// Delete pointer to array of derivatives on FIAT element
2280
delete [] derivatives;
2282
// Delete pointer to array of combinations of derivatives and transform
2283
for (unsigned int row = 0; row < num_derivatives; row++)
2285
delete [] combinations[row];
2286
delete [] transform[row];
2289
delete [] combinations;
2290
delete [] transform;
2293
if (8 <= i && i <= 11)
2295
// Map degree of freedom to element degree of freedom
2296
const unsigned int dof = i - 8;
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);
2304
// Compute psitilde_a
2305
const double psitilde_a_0 = 1;
2306
const double psitilde_a_1 = x;
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;
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;
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;
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}};
2332
// Interesting (new) part
2333
// Tables of derivatives of the polynomial base (transpose)
2334
const static double dmats0[4][4] = \
2336
{6.32455532033676, 0, 0, 0},
2340
const static double dmats1[4][4] = \
2342
{3.16227766016838, 0, 0, 0},
2343
{5.47722557505166, 0, 0, 0},
2346
const static double dmats2[4][4] = \
2348
{3.16227766016838, 0, 0, 0},
2349
{1.82574185835055, 0, 0, 0},
2350
{5.16397779494322, 0, 0, 0}};
2352
// Compute reference derivatives
2353
// Declare pointer to array of derivatives on FIAT element
2354
double *derivatives = new double [num_derivatives];
2356
// Declare coefficients
2357
double coeff0_0 = 0;
2358
double coeff0_1 = 0;
2359
double coeff0_2 = 0;
2360
double coeff0_3 = 0;
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;
2368
// Loop possible derivatives
2369
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
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];
2377
// Loop derivative order
2378
for (unsigned int j = 0; j < n; j++)
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;
2386
if(combinations[deriv_num][j] == 0)
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];
2393
if(combinations[deriv_num][j] == 1)
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];
2400
if(combinations[deriv_num][j] == 2)
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];
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;
2413
// Transform derivatives back to physical element
2414
for (unsigned int row = 0; row < num_derivatives; row++)
2416
for (unsigned int col = 0; col < num_derivatives; col++)
2418
values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
2421
// Delete pointer to array of derivatives on FIAT element
2422
delete [] derivatives;
2424
// Delete pointer to array of combinations of derivatives and transform
2425
for (unsigned int row = 0; row < num_derivatives; row++)
2427
delete [] combinations[row];
2428
delete [] transform[row];
2431
delete [] combinations;
2432
delete [] transform;
2437
/// Evaluate order n derivatives of all basis functions at given point in cell
2438
virtual void evaluate_basis_derivatives_all(unsigned int n,
2440
const double* coordinates,
2441
const ufc::cell& c) const
2443
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
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
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}}};
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];
2465
// Compute affine mapping y = F(X)
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];
2471
// Evaluate function at physical points
2473
f.evaluate(values, y, c);
2475
// Map function values using appropriate mapping
2476
// Affine map: Do nothing
2478
// Note that we do not map the weights (yet).
2480
// Take directional components
2481
for(int k = 0; k < 3; k++)
2482
result += values[k]*D[i][0][k];
2483
// Multiply by weights
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
2494
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
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
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];
2519
/// Return the number of sub elements (for a mixed element)
2520
virtual unsigned int num_sub_elements() const
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
2531
return new ffc_16_finite_element_0_0();
2534
return new ffc_16_finite_element_0_1();
2537
return new ffc_16_finite_element_0_2();
2545
/// This class defines the interface for a local-to-global mapping of
2546
/// degrees of freedom (dofs).
2548
class ffc_16_dof_map_0_0: public ufc::dof_map
2552
unsigned int __global_dimension;
2557
ffc_16_dof_map_0_0() : ufc::dof_map()
2559
__global_dimension = 0;
2563
virtual ~ffc_16_dof_map_0_0()
2568
/// Return a string identifying the dof map
2569
virtual const char* signature() const
2571
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
2574
/// Return true iff mesh entities of topological dimension d are needed
2575
virtual bool needs_mesh_entities(unsigned int d) const
2595
/// Initialize dof map for mesh (return true iff init_cell() is needed)
2596
virtual bool init_mesh(const ufc::mesh& m)
2598
__global_dimension = m.num_entities[0];
2602
/// Initialize dof map for given cell
2603
virtual void init_cell(const ufc::mesh& m,
2609
/// Finish initialization of dof map for cells
2610
virtual void init_cell_finalize()
2615
/// Return the dimension of the global finite element function space
2616
virtual unsigned int global_dimension() const
2618
return __global_dimension;
2621
/// Return the dimension of the local finite element function space
2622
virtual unsigned int local_dimension() const
2627
// Return the geometric dimension of the coordinates this dof map provides
2628
virtual unsigned int geometric_dimension() const
2630
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2633
/// Return the number of dofs on each cell facet
2634
virtual unsigned int num_facet_dofs() const
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
2642
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2645
/// Tabulate the local-to-global mapping of dofs on a cell
2646
virtual void tabulate_dofs(unsigned int* dofs,
2648
const ufc::cell& c) const
2650
dofs[0] = c.entity_indices[0][0];
2651
dofs[1] = c.entity_indices[0][1];
2652
dofs[2] = c.entity_indices[0][2];
2653
dofs[3] = c.entity_indices[0][3];
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
2685
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
2686
virtual void tabulate_entity_dofs(unsigned int* dofs,
2687
unsigned int d, unsigned int i) const
2689
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2692
/// Tabulate the coordinates of all dofs on a cell
2693
virtual void tabulate_coordinates(double** coordinates,
2694
const ufc::cell& c) const
2696
const double * const * x = c.coordinates;
2697
coordinates[0][0] = x[0][0];
2698
coordinates[0][1] = x[0][1];
2699
coordinates[0][2] = x[0][2];
2700
coordinates[1][0] = x[1][0];
2701
coordinates[1][1] = x[1][1];
2702
coordinates[1][2] = x[1][2];
2703
coordinates[2][0] = x[2][0];
2704
coordinates[2][1] = x[2][1];
2705
coordinates[2][2] = x[2][2];
2706
coordinates[3][0] = x[3][0];
2707
coordinates[3][1] = x[3][1];
2708
coordinates[3][2] = x[3][2];
2711
/// Return the number of sub dof maps (for a mixed element)
2712
virtual unsigned int num_sub_dof_maps() const
2717
/// Create a new dof_map for sub dof map i (for a mixed element)
2718
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
2720
return new ffc_16_dof_map_0_0();
2725
/// This class defines the interface for a local-to-global mapping of
2726
/// degrees of freedom (dofs).
2728
class ffc_16_dof_map_0_1: public ufc::dof_map
2732
unsigned int __global_dimension;
2737
ffc_16_dof_map_0_1() : ufc::dof_map()
2739
__global_dimension = 0;
2743
virtual ~ffc_16_dof_map_0_1()
2748
/// Return a string identifying the dof map
2749
virtual const char* signature() const
2751
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
2754
/// Return true iff mesh entities of topological dimension d are needed
2755
virtual bool needs_mesh_entities(unsigned int d) const
2775
/// Initialize dof map for mesh (return true iff init_cell() is needed)
2776
virtual bool init_mesh(const ufc::mesh& m)
2778
__global_dimension = m.num_entities[0];
2782
/// Initialize dof map for given cell
2783
virtual void init_cell(const ufc::mesh& m,
2789
/// Finish initialization of dof map for cells
2790
virtual void init_cell_finalize()
2795
/// Return the dimension of the global finite element function space
2796
virtual unsigned int global_dimension() const
2798
return __global_dimension;
2801
/// Return the dimension of the local finite element function space
2802
virtual unsigned int local_dimension() const
2807
// Return the geometric dimension of the coordinates this dof map provides
2808
virtual unsigned int geometric_dimension() const
2810
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2813
/// Return the number of dofs on each cell facet
2814
virtual unsigned int num_facet_dofs() const
2819
/// Return the number of dofs associated with each cell entity of dimension d
2820
virtual unsigned int num_entity_dofs(unsigned int d) const
2822
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2825
/// Tabulate the local-to-global mapping of dofs on a cell
2826
virtual void tabulate_dofs(unsigned int* dofs,
2828
const ufc::cell& c) const
2830
dofs[0] = c.entity_indices[0][0];
2831
dofs[1] = c.entity_indices[0][1];
2832
dofs[2] = c.entity_indices[0][2];
2833
dofs[3] = c.entity_indices[0][3];
2836
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
2837
virtual void tabulate_facet_dofs(unsigned int* dofs,
2838
unsigned int facet) const
2865
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
2866
virtual void tabulate_entity_dofs(unsigned int* dofs,
2867
unsigned int d, unsigned int i) const
2869
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2872
/// Tabulate the coordinates of all dofs on a cell
2873
virtual void tabulate_coordinates(double** coordinates,
2874
const ufc::cell& c) const
2876
const double * const * x = c.coordinates;
2877
coordinates[0][0] = x[0][0];
2878
coordinates[0][1] = x[0][1];
2879
coordinates[0][2] = x[0][2];
2880
coordinates[1][0] = x[1][0];
2881
coordinates[1][1] = x[1][1];
2882
coordinates[1][2] = x[1][2];
2883
coordinates[2][0] = x[2][0];
2884
coordinates[2][1] = x[2][1];
2885
coordinates[2][2] = x[2][2];
2886
coordinates[3][0] = x[3][0];
2887
coordinates[3][1] = x[3][1];
2888
coordinates[3][2] = x[3][2];
2891
/// Return the number of sub dof maps (for a mixed element)
2892
virtual unsigned int num_sub_dof_maps() const
2897
/// Create a new dof_map for sub dof map i (for a mixed element)
2898
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
2900
return new ffc_16_dof_map_0_1();
2905
/// This class defines the interface for a local-to-global mapping of
2906
/// degrees of freedom (dofs).
2908
class ffc_16_dof_map_0_2: public ufc::dof_map
2912
unsigned int __global_dimension;
2917
ffc_16_dof_map_0_2() : ufc::dof_map()
2919
__global_dimension = 0;
2923
virtual ~ffc_16_dof_map_0_2()
2928
/// Return a string identifying the dof map
2929
virtual const char* signature() const
2931
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
2934
/// Return true iff mesh entities of topological dimension d are needed
2935
virtual bool needs_mesh_entities(unsigned int d) const
2955
/// Initialize dof map for mesh (return true iff init_cell() is needed)
2956
virtual bool init_mesh(const ufc::mesh& m)
2958
__global_dimension = m.num_entities[0];
2962
/// Initialize dof map for given cell
2963
virtual void init_cell(const ufc::mesh& m,
2969
/// Finish initialization of dof map for cells
2970
virtual void init_cell_finalize()
2975
/// Return the dimension of the global finite element function space
2976
virtual unsigned int global_dimension() const
2978
return __global_dimension;
2981
/// Return the dimension of the local finite element function space
2982
virtual unsigned int local_dimension() const
2987
// Return the geometric dimension of the coordinates this dof map provides
2988
virtual unsigned int geometric_dimension() const
2990
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2993
/// Return the number of dofs on each cell facet
2994
virtual unsigned int num_facet_dofs() const
2999
/// Return the number of dofs associated with each cell entity of dimension d
3000
virtual unsigned int num_entity_dofs(unsigned int d) const
3002
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3005
/// Tabulate the local-to-global mapping of dofs on a cell
3006
virtual void tabulate_dofs(unsigned int* dofs,
3008
const ufc::cell& c) const
3010
dofs[0] = c.entity_indices[0][0];
3011
dofs[1] = c.entity_indices[0][1];
3012
dofs[2] = c.entity_indices[0][2];
3013
dofs[3] = c.entity_indices[0][3];
3016
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
3017
virtual void tabulate_facet_dofs(unsigned int* dofs,
3018
unsigned int facet) const
3045
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
3046
virtual void tabulate_entity_dofs(unsigned int* dofs,
3047
unsigned int d, unsigned int i) const
3049
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3052
/// Tabulate the coordinates of all dofs on a cell
3053
virtual void tabulate_coordinates(double** coordinates,
3054
const ufc::cell& c) const
3056
const double * const * x = c.coordinates;
3057
coordinates[0][0] = x[0][0];
3058
coordinates[0][1] = x[0][1];
3059
coordinates[0][2] = x[0][2];
3060
coordinates[1][0] = x[1][0];
3061
coordinates[1][1] = x[1][1];
3062
coordinates[1][2] = x[1][2];
3063
coordinates[2][0] = x[2][0];
3064
coordinates[2][1] = x[2][1];
3065
coordinates[2][2] = x[2][2];
3066
coordinates[3][0] = x[3][0];
3067
coordinates[3][1] = x[3][1];
3068
coordinates[3][2] = x[3][2];
3071
/// Return the number of sub dof maps (for a mixed element)
3072
virtual unsigned int num_sub_dof_maps() const
3077
/// Create a new dof_map for sub dof map i (for a mixed element)
3078
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
3080
return new ffc_16_dof_map_0_2();
3085
/// This class defines the interface for a local-to-global mapping of
3086
/// degrees of freedom (dofs).
3088
class ffc_16_dof_map_0: public ufc::dof_map
3092
unsigned int __global_dimension;
3097
ffc_16_dof_map_0() : ufc::dof_map()
3099
__global_dimension = 0;
3103
virtual ~ffc_16_dof_map_0()
3108
/// Return a string identifying the dof map
3109
virtual const char* signature() const
3111
return "FFC dof map for Mixed finite element: [Lagrange finite element of degree 1 on a tetrahedron, Lagrange finite element of degree 1 on a tetrahedron, Lagrange finite element of degree 1 on a tetrahedron]";
3114
/// Return true iff mesh entities of topological dimension d are needed
3115
virtual bool needs_mesh_entities(unsigned int d) const
3135
/// Initialize dof map for mesh (return true iff init_cell() is needed)
3136
virtual bool init_mesh(const ufc::mesh& m)
3138
__global_dimension = 3*m.num_entities[0];
3142
/// Initialize dof map for given cell
3143
virtual void init_cell(const ufc::mesh& m,
3149
/// Finish initialization of dof map for cells
3150
virtual void init_cell_finalize()
3155
/// Return the dimension of the global finite element function space
3156
virtual unsigned int global_dimension() const
3158
return __global_dimension;
3161
/// Return the dimension of the local finite element function space
3162
virtual unsigned int local_dimension() const
3167
// Return the geometric dimension of the coordinates this dof map provides
3168
virtual unsigned int geometric_dimension() const
3170
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3173
/// Return the number of dofs on each cell facet
3174
virtual unsigned int num_facet_dofs() const
3179
/// Return the number of dofs associated with each cell entity of dimension d
3180
virtual unsigned int num_entity_dofs(unsigned int d) const
3182
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3185
/// Tabulate the local-to-global mapping of dofs on a cell
3186
virtual void tabulate_dofs(unsigned int* dofs,
3188
const ufc::cell& c) const
3190
dofs[0] = c.entity_indices[0][0];
3191
dofs[1] = c.entity_indices[0][1];
3192
dofs[2] = c.entity_indices[0][2];
3193
dofs[3] = c.entity_indices[0][3];
3194
unsigned int offset = m.num_entities[0];
3195
dofs[4] = offset + c.entity_indices[0][0];
3196
dofs[5] = offset + c.entity_indices[0][1];
3197
dofs[6] = offset + c.entity_indices[0][2];
3198
dofs[7] = offset + c.entity_indices[0][3];
3199
offset = offset + m.num_entities[0];
3200
dofs[8] = offset + c.entity_indices[0][0];
3201
dofs[9] = offset + c.entity_indices[0][1];
3202
dofs[10] = offset + c.entity_indices[0][2];
3203
dofs[11] = offset + c.entity_indices[0][3];
3206
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
3207
virtual void tabulate_facet_dofs(unsigned int* dofs,
3208
unsigned int facet) const
3259
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
3260
virtual void tabulate_entity_dofs(unsigned int* dofs,
3261
unsigned int d, unsigned int i) const
3263
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3266
/// Tabulate the coordinates of all dofs on a cell
3267
virtual void tabulate_coordinates(double** coordinates,
3268
const ufc::cell& c) const
3270
const double * const * x = c.coordinates;
3271
coordinates[0][0] = x[0][0];
3272
coordinates[0][1] = x[0][1];
3273
coordinates[0][2] = x[0][2];
3274
coordinates[1][0] = x[1][0];
3275
coordinates[1][1] = x[1][1];
3276
coordinates[1][2] = x[1][2];
3277
coordinates[2][0] = x[2][0];
3278
coordinates[2][1] = x[2][1];
3279
coordinates[2][2] = x[2][2];
3280
coordinates[3][0] = x[3][0];
3281
coordinates[3][1] = x[3][1];
3282
coordinates[3][2] = x[3][2];
3283
coordinates[4][0] = x[0][0];
3284
coordinates[4][1] = x[0][1];
3285
coordinates[4][2] = x[0][2];
3286
coordinates[5][0] = x[1][0];
3287
coordinates[5][1] = x[1][1];
3288
coordinates[5][2] = x[1][2];
3289
coordinates[6][0] = x[2][0];
3290
coordinates[6][1] = x[2][1];
3291
coordinates[6][2] = x[2][2];
3292
coordinates[7][0] = x[3][0];
3293
coordinates[7][1] = x[3][1];
3294
coordinates[7][2] = x[3][2];
3295
coordinates[8][0] = x[0][0];
3296
coordinates[8][1] = x[0][1];
3297
coordinates[8][2] = x[0][2];
3298
coordinates[9][0] = x[1][0];
3299
coordinates[9][1] = x[1][1];
3300
coordinates[9][2] = x[1][2];
3301
coordinates[10][0] = x[2][0];
3302
coordinates[10][1] = x[2][1];
3303
coordinates[10][2] = x[2][2];
3304
coordinates[11][0] = x[3][0];
3305
coordinates[11][1] = x[3][1];
3306
coordinates[11][2] = x[3][2];
3309
/// Return the number of sub dof maps (for a mixed element)
3310
virtual unsigned int num_sub_dof_maps() const
3315
/// Create a new dof_map for sub dof map i (for a mixed element)
3316
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
3321
return new ffc_16_dof_map_0_0();
3324
return new ffc_16_dof_map_0_1();
3327
return new ffc_16_dof_map_0_2();