1
// This code conforms with the UFC specification version 1.0
2
// and was automatically generated by FFC version 0.4.3.
4
// Warning: This code was generated with the option '-l dolfin'
5
// and contains DOLFIN-specific wrappers that depend on DOLFIN.
7
#ifndef __POISSON3D_1_H
8
#define __POISSON3D_1_H
15
/// This class defines the interface for a finite element.
17
class UFC_Poisson3D_1BilinearForm_finite_element_0: public ufc::finite_element
22
UFC_Poisson3D_1BilinearForm_finite_element_0() : ufc::finite_element()
28
virtual ~UFC_Poisson3D_1BilinearForm_finite_element_0()
33
/// Return a string identifying the finite element
34
virtual const char* signature() const
36
return "Lagrange finite element of degree 1 on a tetrahedron";
39
/// Return the cell shape
40
virtual ufc::shape cell_shape() const
42
return ufc::tetrahedron;
45
/// Return the dimension of the finite element function space
46
virtual unsigned int space_dimension() const
51
/// Return the rank of the value space
52
virtual unsigned int value_rank() const
57
/// Return the dimension of the value space for axis i
58
virtual unsigned int value_dimension(unsigned int i) const
63
/// Evaluate basis function i at given point in cell
64
virtual void evaluate_basis(unsigned int i,
66
const double* coordinates,
67
const ufc::cell& c) const
69
// Extract vertex coordinates
70
const double * const * element_coordinates = c.coordinates;
72
// Compute Jacobian of affine map from reference cell
73
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
74
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
75
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
76
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
77
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
78
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
79
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
80
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
81
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
83
// Compute sub determinants
84
const double d00 = J_11*J_22 - J_12*J_21;
85
const double d01 = J_12*J_20 - J_10*J_22;
86
const double d02 = J_10*J_21 - J_11*J_20;
88
const double d10 = J_02*J_21 - J_01*J_22;
89
const double d11 = J_00*J_22 - J_02*J_20;
90
const double d12 = J_01*J_20 - J_00*J_21;
92
const double d20 = J_01*J_12 - J_02*J_11;
93
const double d21 = J_02*J_10 - J_00*J_12;
94
const double d22 = J_00*J_11 - J_01*J_10;
96
// Compute determinant of Jacobian
97
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
99
// Compute inverse of Jacobian
102
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
103
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
104
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
106
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
107
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
108
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
110
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
111
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
112
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
114
// Get coordinates and map to the UFC reference element
115
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
116
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
117
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
119
// Map coordinates to the reference cube
120
if (std::abs(y + z - 1.0) < 1e-14)
123
x = -2.0 * x/(y + z - 1.0) - 1.0;
124
if (std::abs(z - 1.0) < 1e-14)
127
y = 2.0 * y/(1.0 - z) - 1.0;
133
// Map degree of freedom to element degree of freedom
134
const unsigned int dof = i;
137
const double scalings_y_0 = 1;
138
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
139
const double scalings_z_0 = 1;
140
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
142
// Compute psitilde_a
143
const double psitilde_a_0 = 1;
144
const double psitilde_a_1 = x;
146
// Compute psitilde_bs
147
const double psitilde_bs_0_0 = 1;
148
const double psitilde_bs_0_1 = 1.5*y + 0.5;
149
const double psitilde_bs_1_0 = 1;
151
// Compute psitilde_cs
152
const double psitilde_cs_00_0 = 1;
153
const double psitilde_cs_00_1 = 2*z + 1;
154
const double psitilde_cs_01_0 = 1;
155
const double psitilde_cs_10_0 = 1;
157
// Compute basisvalues
158
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
159
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
160
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
161
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
163
// Table(s) of coefficients
164
const static double coefficients0[4][4] = \
165
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
166
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
167
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
168
{0.288675134594813, 0, 0, 0.223606797749979}};
170
// Extract relevant coefficients
171
const double coeff0_0 = coefficients0[dof][0];
172
const double coeff0_1 = coefficients0[dof][1];
173
const double coeff0_2 = coefficients0[dof][2];
174
const double coeff0_3 = coefficients0[dof][3];
177
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
180
/// Evaluate all basis functions at given point in cell
181
virtual void evaluate_basis_all(double* values,
182
const double* coordinates,
183
const ufc::cell& c) const
185
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
188
/// Evaluate order n derivatives of basis function i at given point in cell
189
virtual void evaluate_basis_derivatives(unsigned int i,
192
const double* coordinates,
193
const ufc::cell& c) const
195
// Extract vertex coordinates
196
const double * const * element_coordinates = c.coordinates;
198
// Compute Jacobian of affine map from reference cell
199
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
200
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
201
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
202
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
203
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
204
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
205
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
206
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
207
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
209
// Compute sub determinants
210
const double d00 = J_11*J_22 - J_12*J_21;
211
const double d01 = J_12*J_20 - J_10*J_22;
212
const double d02 = J_10*J_21 - J_11*J_20;
214
const double d10 = J_02*J_21 - J_01*J_22;
215
const double d11 = J_00*J_22 - J_02*J_20;
216
const double d12 = J_01*J_20 - J_00*J_21;
218
const double d20 = J_01*J_12 - J_02*J_11;
219
const double d21 = J_02*J_10 - J_00*J_12;
220
const double d22 = J_00*J_11 - J_01*J_10;
222
// Compute determinant of Jacobian
223
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
225
// Compute inverse of Jacobian
228
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
229
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
230
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
232
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
233
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
234
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
236
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
237
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
238
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
240
// Get coordinates and map to the UFC reference element
241
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
242
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
243
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
245
// Map coordinates to the reference cube
246
if (std::abs(y + z - 1.0) < 1e-14)
249
x = -2.0 * x/(y + z - 1.0) - 1.0;
250
if (std::abs(z - 1.0) < 1e-14)
253
y = 2.0 * y/(1.0 - z) - 1.0;
256
// Compute number of derivatives
257
unsigned int num_derivatives = 1;
259
for (unsigned int j = 0; j < n; j++)
260
num_derivatives *= 3;
263
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
264
unsigned int **combinations = new unsigned int *[num_derivatives];
266
for (unsigned int j = 0; j < num_derivatives; j++)
268
combinations[j] = new unsigned int [n];
269
for (unsigned int k = 0; k < n; k++)
270
combinations[j][k] = 0;
273
// Generate combinations of derivatives
274
for (unsigned int row = 1; row < num_derivatives; row++)
276
for (unsigned int num = 0; num < row; num++)
278
for (unsigned int col = n-1; col+1 > 0; col--)
280
if (combinations[row][col] + 1 > 2)
281
combinations[row][col] = 0;
284
combinations[row][col] += 1;
291
// Compute inverse of Jacobian
292
const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
294
// Declare transformation matrix
295
// Declare pointer to two dimensional array and initialise
296
double **transform = new double *[num_derivatives];
298
for (unsigned int j = 0; j < num_derivatives; j++)
300
transform[j] = new double [num_derivatives];
301
for (unsigned int k = 0; k < num_derivatives; k++)
305
// Construct transformation matrix
306
for (unsigned int row = 0; row < num_derivatives; row++)
308
for (unsigned int col = 0; col < num_derivatives; col++)
310
for (unsigned int k = 0; k < n; k++)
311
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
316
for (unsigned int j = 0; j < 1*num_derivatives; j++)
319
// Map degree of freedom to element degree of freedom
320
const unsigned int dof = i;
323
const double scalings_y_0 = 1;
324
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
325
const double scalings_z_0 = 1;
326
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
328
// Compute psitilde_a
329
const double psitilde_a_0 = 1;
330
const double psitilde_a_1 = x;
332
// Compute psitilde_bs
333
const double psitilde_bs_0_0 = 1;
334
const double psitilde_bs_0_1 = 1.5*y + 0.5;
335
const double psitilde_bs_1_0 = 1;
337
// Compute psitilde_cs
338
const double psitilde_cs_00_0 = 1;
339
const double psitilde_cs_00_1 = 2*z + 1;
340
const double psitilde_cs_01_0 = 1;
341
const double psitilde_cs_10_0 = 1;
343
// Compute basisvalues
344
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
345
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
346
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
347
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
349
// Table(s) of coefficients
350
const static double coefficients0[4][4] = \
351
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
352
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
353
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
354
{0.288675134594813, 0, 0, 0.223606797749979}};
356
// Interesting (new) part
357
// Tables of derivatives of the polynomial base (transpose)
358
const static double dmats0[4][4] = \
360
{6.32455532033676, 0, 0, 0},
364
const static double dmats1[4][4] = \
366
{3.16227766016838, 0, 0, 0},
367
{5.47722557505166, 0, 0, 0},
370
const static double dmats2[4][4] = \
372
{3.16227766016838, 0, 0, 0},
373
{1.82574185835055, 0, 0, 0},
374
{5.16397779494322, 0, 0, 0}};
376
// Compute reference derivatives
377
// Declare pointer to array of derivatives on FIAT element
378
double *derivatives = new double [num_derivatives];
380
// Declare coefficients
386
// Declare new coefficients
387
double new_coeff0_0 = 0;
388
double new_coeff0_1 = 0;
389
double new_coeff0_2 = 0;
390
double new_coeff0_3 = 0;
392
// Loop possible derivatives
393
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
395
// Get values from coefficients array
396
new_coeff0_0 = coefficients0[dof][0];
397
new_coeff0_1 = coefficients0[dof][1];
398
new_coeff0_2 = coefficients0[dof][2];
399
new_coeff0_3 = coefficients0[dof][3];
401
// Loop derivative order
402
for (unsigned int j = 0; j < n; j++)
404
// Update old coefficients
405
coeff0_0 = new_coeff0_0;
406
coeff0_1 = new_coeff0_1;
407
coeff0_2 = new_coeff0_2;
408
coeff0_3 = new_coeff0_3;
410
if(combinations[deriv_num][j] == 0)
412
new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
413
new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
414
new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
415
new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
417
if(combinations[deriv_num][j] == 1)
419
new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
420
new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
421
new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
422
new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
424
if(combinations[deriv_num][j] == 2)
426
new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
427
new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
428
new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
429
new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
433
// Compute derivatives on reference element as dot product of coefficients and basisvalues
434
derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
437
// Transform derivatives back to physical element
438
for (unsigned int row = 0; row < num_derivatives; row++)
440
for (unsigned int col = 0; col < num_derivatives; col++)
442
values[row] += transform[row][col]*derivatives[col];
445
// Delete pointer to array of derivatives on FIAT element
446
delete [] derivatives;
448
// Delete pointer to array of combinations of derivatives and transform
449
for (unsigned int row = 0; row < num_derivatives; row++)
451
delete [] combinations[row];
452
delete [] transform[row];
455
delete [] combinations;
459
/// Evaluate order n derivatives of all basis functions at given point in cell
460
virtual void evaluate_basis_derivatives_all(unsigned int n,
462
const double* coordinates,
463
const ufc::cell& c) const
465
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
468
/// Evaluate linear functional for dof i on the function f
469
virtual double evaluate_dof(unsigned int i,
470
const ufc::function& f,
471
const ufc::cell& c) const
473
// The reference points, direction and weights:
474
const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
475
const static double W[4][1] = {{1}, {1}, {1}, {1}};
476
const static double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
478
const double * const * x = c.coordinates;
480
// Iterate over the points:
481
// Evaluate basis functions for affine mapping
482
const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
483
const double w1 = X[i][0][0];
484
const double w2 = X[i][0][1];
485
const double w3 = X[i][0][2];
487
// Compute affine mapping y = F(X)
489
y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
490
y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
491
y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
493
// Evaluate function at physical points
495
f.evaluate(values, y, c);
497
// Map function values using appropriate mapping
498
// Affine map: Do nothing
500
// Note that we do not map the weights (yet).
502
// Take directional components
503
for(int k = 0; k < 1; k++)
504
result += values[k]*D[i][0][k];
505
// Multiply by weights
511
/// Evaluate linear functionals for all dofs on the function f
512
virtual void evaluate_dofs(double* values,
513
const ufc::function& f,
514
const ufc::cell& c) const
516
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
519
/// Interpolate vertex values from dof values
520
virtual void interpolate_vertex_values(double* vertex_values,
521
const double* dof_values,
522
const ufc::cell& c) const
524
// Evaluate at vertices and use affine mapping
525
vertex_values[0] = dof_values[0];
526
vertex_values[1] = dof_values[1];
527
vertex_values[2] = dof_values[2];
528
vertex_values[3] = dof_values[3];
531
/// Return the number of sub elements (for a mixed element)
532
virtual unsigned int num_sub_elements() const
537
/// Create a new finite element for sub element i (for a mixed element)
538
virtual ufc::finite_element* create_sub_element(unsigned int i) const
540
return new UFC_Poisson3D_1BilinearForm_finite_element_0();
545
/// This class defines the interface for a finite element.
547
class UFC_Poisson3D_1BilinearForm_finite_element_1: public ufc::finite_element
552
UFC_Poisson3D_1BilinearForm_finite_element_1() : ufc::finite_element()
558
virtual ~UFC_Poisson3D_1BilinearForm_finite_element_1()
563
/// Return a string identifying the finite element
564
virtual const char* signature() const
566
return "Lagrange finite element of degree 1 on a tetrahedron";
569
/// Return the cell shape
570
virtual ufc::shape cell_shape() const
572
return ufc::tetrahedron;
575
/// Return the dimension of the finite element function space
576
virtual unsigned int space_dimension() const
581
/// Return the rank of the value space
582
virtual unsigned int value_rank() const
587
/// Return the dimension of the value space for axis i
588
virtual unsigned int value_dimension(unsigned int i) const
593
/// Evaluate basis function i at given point in cell
594
virtual void evaluate_basis(unsigned int i,
596
const double* coordinates,
597
const ufc::cell& c) const
599
// Extract vertex coordinates
600
const double * const * element_coordinates = c.coordinates;
602
// Compute Jacobian of affine map from reference cell
603
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
604
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
605
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
606
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
607
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
608
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
609
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
610
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
611
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
613
// Compute sub determinants
614
const double d00 = J_11*J_22 - J_12*J_21;
615
const double d01 = J_12*J_20 - J_10*J_22;
616
const double d02 = J_10*J_21 - J_11*J_20;
618
const double d10 = J_02*J_21 - J_01*J_22;
619
const double d11 = J_00*J_22 - J_02*J_20;
620
const double d12 = J_01*J_20 - J_00*J_21;
622
const double d20 = J_01*J_12 - J_02*J_11;
623
const double d21 = J_02*J_10 - J_00*J_12;
624
const double d22 = J_00*J_11 - J_01*J_10;
626
// Compute determinant of Jacobian
627
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
629
// Compute inverse of Jacobian
632
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
633
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
634
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
636
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
637
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
638
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
640
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
641
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
642
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
644
// Get coordinates and map to the UFC reference element
645
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
646
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
647
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
649
// Map coordinates to the reference cube
650
if (std::abs(y + z - 1.0) < 1e-14)
653
x = -2.0 * x/(y + z - 1.0) - 1.0;
654
if (std::abs(z - 1.0) < 1e-14)
657
y = 2.0 * y/(1.0 - z) - 1.0;
663
// Map degree of freedom to element degree of freedom
664
const unsigned int dof = i;
667
const double scalings_y_0 = 1;
668
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
669
const double scalings_z_0 = 1;
670
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
672
// Compute psitilde_a
673
const double psitilde_a_0 = 1;
674
const double psitilde_a_1 = x;
676
// Compute psitilde_bs
677
const double psitilde_bs_0_0 = 1;
678
const double psitilde_bs_0_1 = 1.5*y + 0.5;
679
const double psitilde_bs_1_0 = 1;
681
// Compute psitilde_cs
682
const double psitilde_cs_00_0 = 1;
683
const double psitilde_cs_00_1 = 2*z + 1;
684
const double psitilde_cs_01_0 = 1;
685
const double psitilde_cs_10_0 = 1;
687
// Compute basisvalues
688
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
689
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
690
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
691
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
693
// Table(s) of coefficients
694
const static double coefficients0[4][4] = \
695
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
696
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
697
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
698
{0.288675134594813, 0, 0, 0.223606797749979}};
700
// Extract relevant coefficients
701
const double coeff0_0 = coefficients0[dof][0];
702
const double coeff0_1 = coefficients0[dof][1];
703
const double coeff0_2 = coefficients0[dof][2];
704
const double coeff0_3 = coefficients0[dof][3];
707
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
710
/// Evaluate all basis functions at given point in cell
711
virtual void evaluate_basis_all(double* values,
712
const double* coordinates,
713
const ufc::cell& c) const
715
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
718
/// Evaluate order n derivatives of basis function i at given point in cell
719
virtual void evaluate_basis_derivatives(unsigned int i,
722
const double* coordinates,
723
const ufc::cell& c) const
725
// Extract vertex coordinates
726
const double * const * element_coordinates = c.coordinates;
728
// Compute Jacobian of affine map from reference cell
729
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
730
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
731
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
732
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
733
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
734
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
735
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
736
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
737
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
739
// Compute sub determinants
740
const double d00 = J_11*J_22 - J_12*J_21;
741
const double d01 = J_12*J_20 - J_10*J_22;
742
const double d02 = J_10*J_21 - J_11*J_20;
744
const double d10 = J_02*J_21 - J_01*J_22;
745
const double d11 = J_00*J_22 - J_02*J_20;
746
const double d12 = J_01*J_20 - J_00*J_21;
748
const double d20 = J_01*J_12 - J_02*J_11;
749
const double d21 = J_02*J_10 - J_00*J_12;
750
const double d22 = J_00*J_11 - J_01*J_10;
752
// Compute determinant of Jacobian
753
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
755
// Compute inverse of Jacobian
758
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
759
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
760
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
762
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
763
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
764
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
766
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
767
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
768
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
770
// Get coordinates and map to the UFC reference element
771
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
772
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
773
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
775
// Map coordinates to the reference cube
776
if (std::abs(y + z - 1.0) < 1e-14)
779
x = -2.0 * x/(y + z - 1.0) - 1.0;
780
if (std::abs(z - 1.0) < 1e-14)
783
y = 2.0 * y/(1.0 - z) - 1.0;
786
// Compute number of derivatives
787
unsigned int num_derivatives = 1;
789
for (unsigned int j = 0; j < n; j++)
790
num_derivatives *= 3;
793
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
794
unsigned int **combinations = new unsigned int *[num_derivatives];
796
for (unsigned int j = 0; j < num_derivatives; j++)
798
combinations[j] = new unsigned int [n];
799
for (unsigned int k = 0; k < n; k++)
800
combinations[j][k] = 0;
803
// Generate combinations of derivatives
804
for (unsigned int row = 1; row < num_derivatives; row++)
806
for (unsigned int num = 0; num < row; num++)
808
for (unsigned int col = n-1; col+1 > 0; col--)
810
if (combinations[row][col] + 1 > 2)
811
combinations[row][col] = 0;
814
combinations[row][col] += 1;
821
// Compute inverse of Jacobian
822
const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
824
// Declare transformation matrix
825
// Declare pointer to two dimensional array and initialise
826
double **transform = new double *[num_derivatives];
828
for (unsigned int j = 0; j < num_derivatives; j++)
830
transform[j] = new double [num_derivatives];
831
for (unsigned int k = 0; k < num_derivatives; k++)
835
// Construct transformation matrix
836
for (unsigned int row = 0; row < num_derivatives; row++)
838
for (unsigned int col = 0; col < num_derivatives; col++)
840
for (unsigned int k = 0; k < n; k++)
841
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
846
for (unsigned int j = 0; j < 1*num_derivatives; j++)
849
// Map degree of freedom to element degree of freedom
850
const unsigned int dof = i;
853
const double scalings_y_0 = 1;
854
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
855
const double scalings_z_0 = 1;
856
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
858
// Compute psitilde_a
859
const double psitilde_a_0 = 1;
860
const double psitilde_a_1 = x;
862
// Compute psitilde_bs
863
const double psitilde_bs_0_0 = 1;
864
const double psitilde_bs_0_1 = 1.5*y + 0.5;
865
const double psitilde_bs_1_0 = 1;
867
// Compute psitilde_cs
868
const double psitilde_cs_00_0 = 1;
869
const double psitilde_cs_00_1 = 2*z + 1;
870
const double psitilde_cs_01_0 = 1;
871
const double psitilde_cs_10_0 = 1;
873
// Compute basisvalues
874
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
875
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
876
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
877
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
879
// Table(s) of coefficients
880
const static double coefficients0[4][4] = \
881
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
882
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
883
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
884
{0.288675134594813, 0, 0, 0.223606797749979}};
886
// Interesting (new) part
887
// Tables of derivatives of the polynomial base (transpose)
888
const static double dmats0[4][4] = \
890
{6.32455532033676, 0, 0, 0},
894
const static double dmats1[4][4] = \
896
{3.16227766016838, 0, 0, 0},
897
{5.47722557505166, 0, 0, 0},
900
const static double dmats2[4][4] = \
902
{3.16227766016838, 0, 0, 0},
903
{1.82574185835055, 0, 0, 0},
904
{5.16397779494322, 0, 0, 0}};
906
// Compute reference derivatives
907
// Declare pointer to array of derivatives on FIAT element
908
double *derivatives = new double [num_derivatives];
910
// Declare coefficients
916
// Declare new coefficients
917
double new_coeff0_0 = 0;
918
double new_coeff0_1 = 0;
919
double new_coeff0_2 = 0;
920
double new_coeff0_3 = 0;
922
// Loop possible derivatives
923
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
925
// Get values from coefficients array
926
new_coeff0_0 = coefficients0[dof][0];
927
new_coeff0_1 = coefficients0[dof][1];
928
new_coeff0_2 = coefficients0[dof][2];
929
new_coeff0_3 = coefficients0[dof][3];
931
// Loop derivative order
932
for (unsigned int j = 0; j < n; j++)
934
// Update old coefficients
935
coeff0_0 = new_coeff0_0;
936
coeff0_1 = new_coeff0_1;
937
coeff0_2 = new_coeff0_2;
938
coeff0_3 = new_coeff0_3;
940
if(combinations[deriv_num][j] == 0)
942
new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
943
new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
944
new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
945
new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
947
if(combinations[deriv_num][j] == 1)
949
new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
950
new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
951
new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
952
new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
954
if(combinations[deriv_num][j] == 2)
956
new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
957
new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
958
new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
959
new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
963
// Compute derivatives on reference element as dot product of coefficients and basisvalues
964
derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
967
// Transform derivatives back to physical element
968
for (unsigned int row = 0; row < num_derivatives; row++)
970
for (unsigned int col = 0; col < num_derivatives; col++)
972
values[row] += transform[row][col]*derivatives[col];
975
// Delete pointer to array of derivatives on FIAT element
976
delete [] derivatives;
978
// Delete pointer to array of combinations of derivatives and transform
979
for (unsigned int row = 0; row < num_derivatives; row++)
981
delete [] combinations[row];
982
delete [] transform[row];
985
delete [] combinations;
989
/// Evaluate order n derivatives of all basis functions at given point in cell
990
virtual void evaluate_basis_derivatives_all(unsigned int n,
992
const double* coordinates,
993
const ufc::cell& c) const
995
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
998
/// Evaluate linear functional for dof i on the function f
999
virtual double evaluate_dof(unsigned int i,
1000
const ufc::function& f,
1001
const ufc::cell& c) const
1003
// The reference points, direction and weights:
1004
const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
1005
const static double W[4][1] = {{1}, {1}, {1}, {1}};
1006
const static double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
1008
const double * const * x = c.coordinates;
1009
double result = 0.0;
1010
// Iterate over the points:
1011
// Evaluate basis functions for affine mapping
1012
const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
1013
const double w1 = X[i][0][0];
1014
const double w2 = X[i][0][1];
1015
const double w3 = X[i][0][2];
1017
// Compute affine mapping y = F(X)
1019
y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
1020
y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
1021
y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
1023
// Evaluate function at physical points
1025
f.evaluate(values, y, c);
1027
// Map function values using appropriate mapping
1028
// Affine map: Do nothing
1030
// Note that we do not map the weights (yet).
1032
// Take directional components
1033
for(int k = 0; k < 1; k++)
1034
result += values[k]*D[i][0][k];
1035
// Multiply by weights
1041
/// Evaluate linear functionals for all dofs on the function f
1042
virtual void evaluate_dofs(double* values,
1043
const ufc::function& f,
1044
const ufc::cell& c) const
1046
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1049
/// Interpolate vertex values from dof values
1050
virtual void interpolate_vertex_values(double* vertex_values,
1051
const double* dof_values,
1052
const ufc::cell& c) const
1054
// Evaluate at vertices and use affine mapping
1055
vertex_values[0] = dof_values[0];
1056
vertex_values[1] = dof_values[1];
1057
vertex_values[2] = dof_values[2];
1058
vertex_values[3] = dof_values[3];
1061
/// Return the number of sub elements (for a mixed element)
1062
virtual unsigned int num_sub_elements() const
1067
/// Create a new finite element for sub element i (for a mixed element)
1068
virtual ufc::finite_element* create_sub_element(unsigned int i) const
1070
return new UFC_Poisson3D_1BilinearForm_finite_element_1();
1075
/// This class defines the interface for a local-to-global mapping of
1076
/// degrees of freedom (dofs).
1078
class UFC_Poisson3D_1BilinearForm_dof_map_0: public ufc::dof_map
1082
unsigned int __global_dimension;
1087
UFC_Poisson3D_1BilinearForm_dof_map_0() : ufc::dof_map()
1089
__global_dimension = 0;
1093
virtual ~UFC_Poisson3D_1BilinearForm_dof_map_0()
1098
/// Return a string identifying the dof map
1099
virtual const char* signature() const
1101
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
1104
/// Return true iff mesh entities of topological dimension d are needed
1105
virtual bool needs_mesh_entities(unsigned int d) const
1125
/// Initialize dof map for mesh (return true iff init_cell() is needed)
1126
virtual bool init_mesh(const ufc::mesh& m)
1128
__global_dimension = m.num_entities[0];
1132
/// Initialize dof map for given cell
1133
virtual void init_cell(const ufc::mesh& m,
1139
/// Finish initialization of dof map for cells
1140
virtual void init_cell_finalize()
1145
/// Return the dimension of the global finite element function space
1146
virtual unsigned int global_dimension() const
1148
return __global_dimension;
1151
/// Return the dimension of the local finite element function space
1152
virtual unsigned int local_dimension() const
1157
// Return the geometric dimension of the coordinates this dof map provides
1158
virtual unsigned int geometric_dimension() const
1160
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1163
/// Return the number of dofs on each cell facet
1164
virtual unsigned int num_facet_dofs() const
1169
/// Return the number of dofs associated with each cell entity of dimension d
1170
virtual unsigned int num_entity_dofs(unsigned int d) const
1172
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1175
/// Tabulate the local-to-global mapping of dofs on a cell
1176
virtual void tabulate_dofs(unsigned int* dofs,
1178
const ufc::cell& c) const
1180
dofs[0] = c.entity_indices[0][0];
1181
dofs[1] = c.entity_indices[0][1];
1182
dofs[2] = c.entity_indices[0][2];
1183
dofs[3] = c.entity_indices[0][3];
1186
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
1187
virtual void tabulate_facet_dofs(unsigned int* dofs,
1188
unsigned int facet) const
1215
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
1216
virtual void tabulate_entity_dofs(unsigned int* dofs,
1217
unsigned int d, unsigned int i) const
1219
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1222
/// Tabulate the coordinates of all dofs on a cell
1223
virtual void tabulate_coordinates(double** coordinates,
1224
const ufc::cell& c) const
1226
const double * const * x = c.coordinates;
1227
coordinates[0][0] = x[0][0];
1228
coordinates[0][1] = x[0][1];
1229
coordinates[0][2] = x[0][2];
1230
coordinates[1][0] = x[1][0];
1231
coordinates[1][1] = x[1][1];
1232
coordinates[1][2] = x[1][2];
1233
coordinates[2][0] = x[2][0];
1234
coordinates[2][1] = x[2][1];
1235
coordinates[2][2] = x[2][2];
1236
coordinates[3][0] = x[3][0];
1237
coordinates[3][1] = x[3][1];
1238
coordinates[3][2] = x[3][2];
1241
/// Return the number of sub dof maps (for a mixed element)
1242
virtual unsigned int num_sub_dof_maps() const
1247
/// Create a new dof_map for sub dof map i (for a mixed element)
1248
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
1250
return new UFC_Poisson3D_1BilinearForm_dof_map_0();
1255
/// This class defines the interface for a local-to-global mapping of
1256
/// degrees of freedom (dofs).
1258
class UFC_Poisson3D_1BilinearForm_dof_map_1: public ufc::dof_map
1262
unsigned int __global_dimension;
1267
UFC_Poisson3D_1BilinearForm_dof_map_1() : ufc::dof_map()
1269
__global_dimension = 0;
1273
virtual ~UFC_Poisson3D_1BilinearForm_dof_map_1()
1278
/// Return a string identifying the dof map
1279
virtual const char* signature() const
1281
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
1284
/// Return true iff mesh entities of topological dimension d are needed
1285
virtual bool needs_mesh_entities(unsigned int d) const
1305
/// Initialize dof map for mesh (return true iff init_cell() is needed)
1306
virtual bool init_mesh(const ufc::mesh& m)
1308
__global_dimension = m.num_entities[0];
1312
/// Initialize dof map for given cell
1313
virtual void init_cell(const ufc::mesh& m,
1319
/// Finish initialization of dof map for cells
1320
virtual void init_cell_finalize()
1325
/// Return the dimension of the global finite element function space
1326
virtual unsigned int global_dimension() const
1328
return __global_dimension;
1331
/// Return the dimension of the local finite element function space
1332
virtual unsigned int local_dimension() const
1337
// Return the geometric dimension of the coordinates this dof map provides
1338
virtual unsigned int geometric_dimension() const
1340
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1343
/// Return the number of dofs on each cell facet
1344
virtual unsigned int num_facet_dofs() const
1349
/// Return the number of dofs associated with each cell entity of dimension d
1350
virtual unsigned int num_entity_dofs(unsigned int d) const
1352
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1355
/// Tabulate the local-to-global mapping of dofs on a cell
1356
virtual void tabulate_dofs(unsigned int* dofs,
1358
const ufc::cell& c) const
1360
dofs[0] = c.entity_indices[0][0];
1361
dofs[1] = c.entity_indices[0][1];
1362
dofs[2] = c.entity_indices[0][2];
1363
dofs[3] = c.entity_indices[0][3];
1366
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
1367
virtual void tabulate_facet_dofs(unsigned int* dofs,
1368
unsigned int facet) const
1395
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
1396
virtual void tabulate_entity_dofs(unsigned int* dofs,
1397
unsigned int d, unsigned int i) const
1399
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
1402
/// Tabulate the coordinates of all dofs on a cell
1403
virtual void tabulate_coordinates(double** coordinates,
1404
const ufc::cell& c) const
1406
const double * const * x = c.coordinates;
1407
coordinates[0][0] = x[0][0];
1408
coordinates[0][1] = x[0][1];
1409
coordinates[0][2] = x[0][2];
1410
coordinates[1][0] = x[1][0];
1411
coordinates[1][1] = x[1][1];
1412
coordinates[1][2] = x[1][2];
1413
coordinates[2][0] = x[2][0];
1414
coordinates[2][1] = x[2][1];
1415
coordinates[2][2] = x[2][2];
1416
coordinates[3][0] = x[3][0];
1417
coordinates[3][1] = x[3][1];
1418
coordinates[3][2] = x[3][2];
1421
/// Return the number of sub dof maps (for a mixed element)
1422
virtual unsigned int num_sub_dof_maps() const
1427
/// Create a new dof_map for sub dof map i (for a mixed element)
1428
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
1430
return new UFC_Poisson3D_1BilinearForm_dof_map_1();
1435
/// This class defines the interface for the tabulation of the cell
1436
/// tensor corresponding to the local contribution to a form from
1437
/// the integral over a cell.
1439
class UFC_Poisson3D_1BilinearForm_cell_integral_0: public ufc::cell_integral
1444
UFC_Poisson3D_1BilinearForm_cell_integral_0() : ufc::cell_integral()
1450
virtual ~UFC_Poisson3D_1BilinearForm_cell_integral_0()
1455
/// Tabulate the tensor for the contribution from a local cell
1456
virtual void tabulate_tensor(double* A,
1457
const double * const * w,
1458
const ufc::cell& c) const
1460
// Extract vertex coordinates
1461
const double * const * x = c.coordinates;
1463
// Compute Jacobian of affine map from reference cell
1464
const double J_00 = x[1][0] - x[0][0];
1465
const double J_01 = x[2][0] - x[0][0];
1466
const double J_02 = x[3][0] - x[0][0];
1467
const double J_10 = x[1][1] - x[0][1];
1468
const double J_11 = x[2][1] - x[0][1];
1469
const double J_12 = x[3][1] - x[0][1];
1470
const double J_20 = x[1][2] - x[0][2];
1471
const double J_21 = x[2][2] - x[0][2];
1472
const double J_22 = x[3][2] - x[0][2];
1474
// Compute sub determinants
1475
const double d_00 = J_11*J_22 - J_12*J_21;
1476
const double d_01 = J_12*J_20 - J_10*J_22;
1477
const double d_02 = J_10*J_21 - J_11*J_20;
1479
const double d_10 = J_02*J_21 - J_01*J_22;
1480
const double d_11 = J_00*J_22 - J_02*J_20;
1481
const double d_12 = J_01*J_20 - J_00*J_21;
1483
const double d_20 = J_01*J_12 - J_02*J_11;
1484
const double d_21 = J_02*J_10 - J_00*J_12;
1485
const double d_22 = J_00*J_11 - J_01*J_10;
1487
// Compute determinant of Jacobian
1488
double detJ = J_00*d_00 + J_10*d_10 + J_20*d_20;
1490
// Compute inverse of Jacobian
1491
const double Jinv_00 = d_00 / detJ;
1492
const double Jinv_01 = d_10 / detJ;
1493
const double Jinv_02 = d_20 / detJ;
1494
const double Jinv_10 = d_01 / detJ;
1495
const double Jinv_11 = d_11 / detJ;
1496
const double Jinv_12 = d_21 / detJ;
1497
const double Jinv_20 = d_02 / detJ;
1498
const double Jinv_21 = d_12 / detJ;
1499
const double Jinv_22 = d_22 / detJ;
1502
const double det = std::abs(detJ);
1504
// Compute geometry tensors
1505
const double G0_0_0 = det*(Jinv_00*Jinv_00 + Jinv_01*Jinv_01 + Jinv_02*Jinv_02);
1506
const double G0_0_1 = det*(Jinv_00*Jinv_10 + Jinv_01*Jinv_11 + Jinv_02*Jinv_12);
1507
const double G0_0_2 = det*(Jinv_00*Jinv_20 + Jinv_01*Jinv_21 + Jinv_02*Jinv_22);
1508
const double G0_1_0 = det*(Jinv_10*Jinv_00 + Jinv_11*Jinv_01 + Jinv_12*Jinv_02);
1509
const double G0_1_1 = det*(Jinv_10*Jinv_10 + Jinv_11*Jinv_11 + Jinv_12*Jinv_12);
1510
const double G0_1_2 = det*(Jinv_10*Jinv_20 + Jinv_11*Jinv_21 + Jinv_12*Jinv_22);
1511
const double G0_2_0 = det*(Jinv_20*Jinv_00 + Jinv_21*Jinv_01 + Jinv_22*Jinv_02);
1512
const double G0_2_1 = det*(Jinv_20*Jinv_10 + Jinv_21*Jinv_11 + Jinv_22*Jinv_12);
1513
const double G0_2_2 = det*(Jinv_20*Jinv_20 + Jinv_21*Jinv_21 + Jinv_22*Jinv_22);
1515
// Compute element tensor
1516
A[0] = 0.166666666666666*G0_0_0 + 0.166666666666666*G0_0_1 + 0.166666666666666*G0_0_2 + 0.166666666666666*G0_1_0 + 0.166666666666666*G0_1_1 + 0.166666666666666*G0_1_2 + 0.166666666666666*G0_2_0 + 0.166666666666666*G0_2_1 + 0.166666666666666*G0_2_2;
1517
A[1] = -0.166666666666666*G0_0_0 - 0.166666666666666*G0_1_0 - 0.166666666666666*G0_2_0;
1518
A[2] = -0.166666666666666*G0_0_1 - 0.166666666666666*G0_1_1 - 0.166666666666666*G0_2_1;
1519
A[3] = -0.166666666666666*G0_0_2 - 0.166666666666666*G0_1_2 - 0.166666666666666*G0_2_2;
1520
A[4] = -0.166666666666666*G0_0_0 - 0.166666666666666*G0_0_1 - 0.166666666666666*G0_0_2;
1521
A[5] = 0.166666666666666*G0_0_0;
1522
A[6] = 0.166666666666666*G0_0_1;
1523
A[7] = 0.166666666666666*G0_0_2;
1524
A[8] = -0.166666666666666*G0_1_0 - 0.166666666666666*G0_1_1 - 0.166666666666666*G0_1_2;
1525
A[9] = 0.166666666666666*G0_1_0;
1526
A[10] = 0.166666666666666*G0_1_1;
1527
A[11] = 0.166666666666666*G0_1_2;
1528
A[12] = -0.166666666666666*G0_2_0 - 0.166666666666666*G0_2_1 - 0.166666666666666*G0_2_2;
1529
A[13] = 0.166666666666666*G0_2_0;
1530
A[14] = 0.166666666666666*G0_2_1;
1531
A[15] = 0.166666666666666*G0_2_2;
1536
/// This class defines the interface for the assembly of the global
1537
/// tensor corresponding to a form with r + n arguments, that is, a
1540
/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
1542
/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
1543
/// global tensor A is defined by
1545
/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
1547
/// where each argument Vj represents the application to the
1548
/// sequence of basis functions of Vj and w1, w2, ..., wn are given
1549
/// fixed functions (coefficients).
1551
class UFC_Poisson3D_1BilinearForm: public ufc::form
1556
UFC_Poisson3D_1BilinearForm() : ufc::form()
1562
virtual ~UFC_Poisson3D_1BilinearForm()
1567
/// Return a string identifying the form
1568
virtual const char* signature() const
1570
return "(dXa0/dxb0)(dXa1/dxb0) | ((d/dXa0)vi0)*((d/dXa1)vi1)*dX(0)";
1573
/// Return the rank of the global tensor (r)
1574
virtual unsigned int rank() const
1579
/// Return the number of coefficients (n)
1580
virtual unsigned int num_coefficients() const
1585
/// Return the number of cell integrals
1586
virtual unsigned int num_cell_integrals() const
1591
/// Return the number of exterior facet integrals
1592
virtual unsigned int num_exterior_facet_integrals() const
1597
/// Return the number of interior facet integrals
1598
virtual unsigned int num_interior_facet_integrals() const
1603
/// Create a new finite element for argument function i
1604
virtual ufc::finite_element* create_finite_element(unsigned int i) const
1609
return new UFC_Poisson3D_1BilinearForm_finite_element_0();
1612
return new UFC_Poisson3D_1BilinearForm_finite_element_1();
1618
/// Create a new dof map for argument function i
1619
virtual ufc::dof_map* create_dof_map(unsigned int i) const
1624
return new UFC_Poisson3D_1BilinearForm_dof_map_0();
1627
return new UFC_Poisson3D_1BilinearForm_dof_map_1();
1633
/// Create a new cell integral on sub domain i
1634
virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
1636
return new UFC_Poisson3D_1BilinearForm_cell_integral_0();
1639
/// Create a new exterior facet integral on sub domain i
1640
virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
1645
/// Create a new interior facet integral on sub domain i
1646
virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
1653
/// This class defines the interface for a finite element.
1655
class UFC_Poisson3D_1LinearForm_finite_element_0: public ufc::finite_element
1660
UFC_Poisson3D_1LinearForm_finite_element_0() : ufc::finite_element()
1666
virtual ~UFC_Poisson3D_1LinearForm_finite_element_0()
1671
/// Return a string identifying the finite element
1672
virtual const char* signature() const
1674
return "Lagrange finite element of degree 1 on a tetrahedron";
1677
/// Return the cell shape
1678
virtual ufc::shape cell_shape() const
1680
return ufc::tetrahedron;
1683
/// Return the dimension of the finite element function space
1684
virtual unsigned int space_dimension() const
1689
/// Return the rank of the value space
1690
virtual unsigned int value_rank() const
1695
/// Return the dimension of the value space for axis i
1696
virtual unsigned int value_dimension(unsigned int i) const
1701
/// Evaluate basis function i at given point in cell
1702
virtual void evaluate_basis(unsigned int i,
1704
const double* coordinates,
1705
const ufc::cell& c) const
1707
// Extract vertex coordinates
1708
const double * const * element_coordinates = c.coordinates;
1710
// Compute Jacobian of affine map from reference cell
1711
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1712
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1713
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1714
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1715
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1716
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1717
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1718
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1719
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1721
// Compute sub determinants
1722
const double d00 = J_11*J_22 - J_12*J_21;
1723
const double d01 = J_12*J_20 - J_10*J_22;
1724
const double d02 = J_10*J_21 - J_11*J_20;
1726
const double d10 = J_02*J_21 - J_01*J_22;
1727
const double d11 = J_00*J_22 - J_02*J_20;
1728
const double d12 = J_01*J_20 - J_00*J_21;
1730
const double d20 = J_01*J_12 - J_02*J_11;
1731
const double d21 = J_02*J_10 - J_00*J_12;
1732
const double d22 = J_00*J_11 - J_01*J_10;
1734
// Compute determinant of Jacobian
1735
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1737
// Compute inverse of Jacobian
1739
// Compute constants
1740
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1741
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1742
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1744
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1745
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1746
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1748
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1749
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1750
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1752
// Get coordinates and map to the UFC reference element
1753
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1754
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1755
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1757
// Map coordinates to the reference cube
1758
if (std::abs(y + z - 1.0) < 1e-14)
1761
x = -2.0 * x/(y + z - 1.0) - 1.0;
1762
if (std::abs(z - 1.0) < 1e-14)
1765
y = 2.0 * y/(1.0 - z) - 1.0;
1771
// Map degree of freedom to element degree of freedom
1772
const unsigned int dof = i;
1774
// Generate scalings
1775
const double scalings_y_0 = 1;
1776
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1777
const double scalings_z_0 = 1;
1778
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1780
// Compute psitilde_a
1781
const double psitilde_a_0 = 1;
1782
const double psitilde_a_1 = x;
1784
// Compute psitilde_bs
1785
const double psitilde_bs_0_0 = 1;
1786
const double psitilde_bs_0_1 = 1.5*y + 0.5;
1787
const double psitilde_bs_1_0 = 1;
1789
// Compute psitilde_cs
1790
const double psitilde_cs_00_0 = 1;
1791
const double psitilde_cs_00_1 = 2*z + 1;
1792
const double psitilde_cs_01_0 = 1;
1793
const double psitilde_cs_10_0 = 1;
1795
// Compute basisvalues
1796
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1797
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1798
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1799
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1801
// Table(s) of coefficients
1802
const static double coefficients0[4][4] = \
1803
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1804
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1805
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1806
{0.288675134594813, 0, 0, 0.223606797749979}};
1808
// Extract relevant coefficients
1809
const double coeff0_0 = coefficients0[dof][0];
1810
const double coeff0_1 = coefficients0[dof][1];
1811
const double coeff0_2 = coefficients0[dof][2];
1812
const double coeff0_3 = coefficients0[dof][3];
1815
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
1818
/// Evaluate all basis functions at given point in cell
1819
virtual void evaluate_basis_all(double* values,
1820
const double* coordinates,
1821
const ufc::cell& c) const
1823
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
1826
/// Evaluate order n derivatives of basis function i at given point in cell
1827
virtual void evaluate_basis_derivatives(unsigned int i,
1830
const double* coordinates,
1831
const ufc::cell& c) const
1833
// Extract vertex coordinates
1834
const double * const * element_coordinates = c.coordinates;
1836
// Compute Jacobian of affine map from reference cell
1837
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
1838
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
1839
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
1840
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
1841
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
1842
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
1843
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
1844
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
1845
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
1847
// Compute sub determinants
1848
const double d00 = J_11*J_22 - J_12*J_21;
1849
const double d01 = J_12*J_20 - J_10*J_22;
1850
const double d02 = J_10*J_21 - J_11*J_20;
1852
const double d10 = J_02*J_21 - J_01*J_22;
1853
const double d11 = J_00*J_22 - J_02*J_20;
1854
const double d12 = J_01*J_20 - J_00*J_21;
1856
const double d20 = J_01*J_12 - J_02*J_11;
1857
const double d21 = J_02*J_10 - J_00*J_12;
1858
const double d22 = J_00*J_11 - J_01*J_10;
1860
// Compute determinant of Jacobian
1861
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
1863
// Compute inverse of Jacobian
1865
// Compute constants
1866
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
1867
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
1868
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
1870
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
1871
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
1872
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
1874
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
1875
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
1876
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
1878
// Get coordinates and map to the UFC reference element
1879
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
1880
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
1881
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
1883
// Map coordinates to the reference cube
1884
if (std::abs(y + z - 1.0) < 1e-14)
1887
x = -2.0 * x/(y + z - 1.0) - 1.0;
1888
if (std::abs(z - 1.0) < 1e-14)
1891
y = 2.0 * y/(1.0 - z) - 1.0;
1894
// Compute number of derivatives
1895
unsigned int num_derivatives = 1;
1897
for (unsigned int j = 0; j < n; j++)
1898
num_derivatives *= 3;
1901
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
1902
unsigned int **combinations = new unsigned int *[num_derivatives];
1904
for (unsigned int j = 0; j < num_derivatives; j++)
1906
combinations[j] = new unsigned int [n];
1907
for (unsigned int k = 0; k < n; k++)
1908
combinations[j][k] = 0;
1911
// Generate combinations of derivatives
1912
for (unsigned int row = 1; row < num_derivatives; row++)
1914
for (unsigned int num = 0; num < row; num++)
1916
for (unsigned int col = n-1; col+1 > 0; col--)
1918
if (combinations[row][col] + 1 > 2)
1919
combinations[row][col] = 0;
1922
combinations[row][col] += 1;
1929
// Compute inverse of Jacobian
1930
const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
1932
// Declare transformation matrix
1933
// Declare pointer to two dimensional array and initialise
1934
double **transform = new double *[num_derivatives];
1936
for (unsigned int j = 0; j < num_derivatives; j++)
1938
transform[j] = new double [num_derivatives];
1939
for (unsigned int k = 0; k < num_derivatives; k++)
1940
transform[j][k] = 1;
1943
// Construct transformation matrix
1944
for (unsigned int row = 0; row < num_derivatives; row++)
1946
for (unsigned int col = 0; col < num_derivatives; col++)
1948
for (unsigned int k = 0; k < n; k++)
1949
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
1954
for (unsigned int j = 0; j < 1*num_derivatives; j++)
1957
// Map degree of freedom to element degree of freedom
1958
const unsigned int dof = i;
1960
// Generate scalings
1961
const double scalings_y_0 = 1;
1962
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
1963
const double scalings_z_0 = 1;
1964
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
1966
// Compute psitilde_a
1967
const double psitilde_a_0 = 1;
1968
const double psitilde_a_1 = x;
1970
// Compute psitilde_bs
1971
const double psitilde_bs_0_0 = 1;
1972
const double psitilde_bs_0_1 = 1.5*y + 0.5;
1973
const double psitilde_bs_1_0 = 1;
1975
// Compute psitilde_cs
1976
const double psitilde_cs_00_0 = 1;
1977
const double psitilde_cs_00_1 = 2*z + 1;
1978
const double psitilde_cs_01_0 = 1;
1979
const double psitilde_cs_10_0 = 1;
1981
// Compute basisvalues
1982
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
1983
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
1984
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
1985
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
1987
// Table(s) of coefficients
1988
const static double coefficients0[4][4] = \
1989
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
1990
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
1991
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
1992
{0.288675134594813, 0, 0, 0.223606797749979}};
1994
// Interesting (new) part
1995
// Tables of derivatives of the polynomial base (transpose)
1996
const static double dmats0[4][4] = \
1998
{6.32455532033676, 0, 0, 0},
2002
const static double dmats1[4][4] = \
2004
{3.16227766016838, 0, 0, 0},
2005
{5.47722557505166, 0, 0, 0},
2008
const static double dmats2[4][4] = \
2010
{3.16227766016838, 0, 0, 0},
2011
{1.82574185835055, 0, 0, 0},
2012
{5.16397779494322, 0, 0, 0}};
2014
// Compute reference derivatives
2015
// Declare pointer to array of derivatives on FIAT element
2016
double *derivatives = new double [num_derivatives];
2018
// Declare coefficients
2019
double coeff0_0 = 0;
2020
double coeff0_1 = 0;
2021
double coeff0_2 = 0;
2022
double coeff0_3 = 0;
2024
// Declare new coefficients
2025
double new_coeff0_0 = 0;
2026
double new_coeff0_1 = 0;
2027
double new_coeff0_2 = 0;
2028
double new_coeff0_3 = 0;
2030
// Loop possible derivatives
2031
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2033
// Get values from coefficients array
2034
new_coeff0_0 = coefficients0[dof][0];
2035
new_coeff0_1 = coefficients0[dof][1];
2036
new_coeff0_2 = coefficients0[dof][2];
2037
new_coeff0_3 = coefficients0[dof][3];
2039
// Loop derivative order
2040
for (unsigned int j = 0; j < n; j++)
2042
// Update old coefficients
2043
coeff0_0 = new_coeff0_0;
2044
coeff0_1 = new_coeff0_1;
2045
coeff0_2 = new_coeff0_2;
2046
coeff0_3 = new_coeff0_3;
2048
if(combinations[deriv_num][j] == 0)
2050
new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2051
new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2052
new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2053
new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2055
if(combinations[deriv_num][j] == 1)
2057
new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2058
new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2059
new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2060
new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2062
if(combinations[deriv_num][j] == 2)
2064
new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2065
new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2066
new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2067
new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2071
// Compute derivatives on reference element as dot product of coefficients and basisvalues
2072
derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2075
// Transform derivatives back to physical element
2076
for (unsigned int row = 0; row < num_derivatives; row++)
2078
for (unsigned int col = 0; col < num_derivatives; col++)
2080
values[row] += transform[row][col]*derivatives[col];
2083
// Delete pointer to array of derivatives on FIAT element
2084
delete [] derivatives;
2086
// Delete pointer to array of combinations of derivatives and transform
2087
for (unsigned int row = 0; row < num_derivatives; row++)
2089
delete [] combinations[row];
2090
delete [] transform[row];
2093
delete [] combinations;
2094
delete [] transform;
2097
/// Evaluate order n derivatives of all basis functions at given point in cell
2098
virtual void evaluate_basis_derivatives_all(unsigned int n,
2100
const double* coordinates,
2101
const ufc::cell& c) const
2103
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
2106
/// Evaluate linear functional for dof i on the function f
2107
virtual double evaluate_dof(unsigned int i,
2108
const ufc::function& f,
2109
const ufc::cell& c) const
2111
// The reference points, direction and weights:
2112
const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
2113
const static double W[4][1] = {{1}, {1}, {1}, {1}};
2114
const static double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
2116
const double * const * x = c.coordinates;
2117
double result = 0.0;
2118
// Iterate over the points:
2119
// Evaluate basis functions for affine mapping
2120
const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
2121
const double w1 = X[i][0][0];
2122
const double w2 = X[i][0][1];
2123
const double w3 = X[i][0][2];
2125
// Compute affine mapping y = F(X)
2127
y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
2128
y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
2129
y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
2131
// Evaluate function at physical points
2133
f.evaluate(values, y, c);
2135
// Map function values using appropriate mapping
2136
// Affine map: Do nothing
2138
// Note that we do not map the weights (yet).
2140
// Take directional components
2141
for(int k = 0; k < 1; k++)
2142
result += values[k]*D[i][0][k];
2143
// Multiply by weights
2149
/// Evaluate linear functionals for all dofs on the function f
2150
virtual void evaluate_dofs(double* values,
2151
const ufc::function& f,
2152
const ufc::cell& c) const
2154
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2157
/// Interpolate vertex values from dof values
2158
virtual void interpolate_vertex_values(double* vertex_values,
2159
const double* dof_values,
2160
const ufc::cell& c) const
2162
// Evaluate at vertices and use affine mapping
2163
vertex_values[0] = dof_values[0];
2164
vertex_values[1] = dof_values[1];
2165
vertex_values[2] = dof_values[2];
2166
vertex_values[3] = dof_values[3];
2169
/// Return the number of sub elements (for a mixed element)
2170
virtual unsigned int num_sub_elements() const
2175
/// Create a new finite element for sub element i (for a mixed element)
2176
virtual ufc::finite_element* create_sub_element(unsigned int i) const
2178
return new UFC_Poisson3D_1LinearForm_finite_element_0();
2183
/// This class defines the interface for a finite element.
2185
class UFC_Poisson3D_1LinearForm_finite_element_1: public ufc::finite_element
2190
UFC_Poisson3D_1LinearForm_finite_element_1() : ufc::finite_element()
2196
virtual ~UFC_Poisson3D_1LinearForm_finite_element_1()
2201
/// Return a string identifying the finite element
2202
virtual const char* signature() const
2204
return "Lagrange finite element of degree 1 on a tetrahedron";
2207
/// Return the cell shape
2208
virtual ufc::shape cell_shape() const
2210
return ufc::tetrahedron;
2213
/// Return the dimension of the finite element function space
2214
virtual unsigned int space_dimension() const
2219
/// Return the rank of the value space
2220
virtual unsigned int value_rank() const
2225
/// Return the dimension of the value space for axis i
2226
virtual unsigned int value_dimension(unsigned int i) const
2231
/// Evaluate basis function i at given point in cell
2232
virtual void evaluate_basis(unsigned int i,
2234
const double* coordinates,
2235
const ufc::cell& c) const
2237
// Extract vertex coordinates
2238
const double * const * element_coordinates = c.coordinates;
2240
// Compute Jacobian of affine map from reference cell
2241
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
2242
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
2243
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
2244
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
2245
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
2246
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
2247
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
2248
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
2249
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
2251
// Compute sub determinants
2252
const double d00 = J_11*J_22 - J_12*J_21;
2253
const double d01 = J_12*J_20 - J_10*J_22;
2254
const double d02 = J_10*J_21 - J_11*J_20;
2256
const double d10 = J_02*J_21 - J_01*J_22;
2257
const double d11 = J_00*J_22 - J_02*J_20;
2258
const double d12 = J_01*J_20 - J_00*J_21;
2260
const double d20 = J_01*J_12 - J_02*J_11;
2261
const double d21 = J_02*J_10 - J_00*J_12;
2262
const double d22 = J_00*J_11 - J_01*J_10;
2264
// Compute determinant of Jacobian
2265
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
2267
// Compute inverse of Jacobian
2269
// Compute constants
2270
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
2271
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
2272
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
2274
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
2275
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
2276
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
2278
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
2279
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
2280
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
2282
// Get coordinates and map to the UFC reference element
2283
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
2284
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
2285
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
2287
// Map coordinates to the reference cube
2288
if (std::abs(y + z - 1.0) < 1e-14)
2291
x = -2.0 * x/(y + z - 1.0) - 1.0;
2292
if (std::abs(z - 1.0) < 1e-14)
2295
y = 2.0 * y/(1.0 - z) - 1.0;
2301
// Map degree of freedom to element degree of freedom
2302
const unsigned int dof = i;
2304
// Generate scalings
2305
const double scalings_y_0 = 1;
2306
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2307
const double scalings_z_0 = 1;
2308
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2310
// Compute psitilde_a
2311
const double psitilde_a_0 = 1;
2312
const double psitilde_a_1 = x;
2314
// Compute psitilde_bs
2315
const double psitilde_bs_0_0 = 1;
2316
const double psitilde_bs_0_1 = 1.5*y + 0.5;
2317
const double psitilde_bs_1_0 = 1;
2319
// Compute psitilde_cs
2320
const double psitilde_cs_00_0 = 1;
2321
const double psitilde_cs_00_1 = 2*z + 1;
2322
const double psitilde_cs_01_0 = 1;
2323
const double psitilde_cs_10_0 = 1;
2325
// Compute basisvalues
2326
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2327
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2328
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2329
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2331
// Table(s) of coefficients
2332
const static double coefficients0[4][4] = \
2333
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
2334
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
2335
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
2336
{0.288675134594813, 0, 0, 0.223606797749979}};
2338
// Extract relevant coefficients
2339
const double coeff0_0 = coefficients0[dof][0];
2340
const double coeff0_1 = coefficients0[dof][1];
2341
const double coeff0_2 = coefficients0[dof][2];
2342
const double coeff0_3 = coefficients0[dof][3];
2345
*values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3;
2348
/// Evaluate all basis functions at given point in cell
2349
virtual void evaluate_basis_all(double* values,
2350
const double* coordinates,
2351
const ufc::cell& c) const
2353
throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
2356
/// Evaluate order n derivatives of basis function i at given point in cell
2357
virtual void evaluate_basis_derivatives(unsigned int i,
2360
const double* coordinates,
2361
const ufc::cell& c) const
2363
// Extract vertex coordinates
2364
const double * const * element_coordinates = c.coordinates;
2366
// Compute Jacobian of affine map from reference cell
2367
const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
2368
const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
2369
const double J_02 = element_coordinates[3][0] - element_coordinates[0][0];
2370
const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
2371
const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
2372
const double J_12 = element_coordinates[3][1] - element_coordinates[0][1];
2373
const double J_20 = element_coordinates[1][2] - element_coordinates[0][2];
2374
const double J_21 = element_coordinates[2][2] - element_coordinates[0][2];
2375
const double J_22 = element_coordinates[3][2] - element_coordinates[0][2];
2377
// Compute sub determinants
2378
const double d00 = J_11*J_22 - J_12*J_21;
2379
const double d01 = J_12*J_20 - J_10*J_22;
2380
const double d02 = J_10*J_21 - J_11*J_20;
2382
const double d10 = J_02*J_21 - J_01*J_22;
2383
const double d11 = J_00*J_22 - J_02*J_20;
2384
const double d12 = J_01*J_20 - J_00*J_21;
2386
const double d20 = J_01*J_12 - J_02*J_11;
2387
const double d21 = J_02*J_10 - J_00*J_12;
2388
const double d22 = J_00*J_11 - J_01*J_10;
2390
// Compute determinant of Jacobian
2391
double detJ = J_00*d00 + J_10*d10 + J_20*d20;
2393
// Compute inverse of Jacobian
2395
// Compute constants
2396
const double C0 = d00*(element_coordinates[0][0] - element_coordinates[2][0] - element_coordinates[3][0]) \
2397
+ d10*(element_coordinates[0][1] - element_coordinates[2][1] - element_coordinates[3][1]) \
2398
+ d20*(element_coordinates[0][2] - element_coordinates[2][2] - element_coordinates[3][2]);
2400
const double C1 = d01*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[3][0]) \
2401
+ d11*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[3][1]) \
2402
+ d21*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[3][2]);
2404
const double C2 = d02*(element_coordinates[0][0] - element_coordinates[1][0] - element_coordinates[2][0]) \
2405
+ d12*(element_coordinates[0][1] - element_coordinates[1][1] - element_coordinates[2][1]) \
2406
+ d22*(element_coordinates[0][2] - element_coordinates[1][2] - element_coordinates[2][2]);
2408
// Get coordinates and map to the UFC reference element
2409
double x = (C0 + d00*coordinates[0] + d10*coordinates[1] + d20*coordinates[2]) / detJ;
2410
double y = (C1 + d01*coordinates[0] + d11*coordinates[1] + d21*coordinates[2]) / detJ;
2411
double z = (C2 + d02*coordinates[0] + d12*coordinates[1] + d22*coordinates[2]) / detJ;
2413
// Map coordinates to the reference cube
2414
if (std::abs(y + z - 1.0) < 1e-14)
2417
x = -2.0 * x/(y + z - 1.0) - 1.0;
2418
if (std::abs(z - 1.0) < 1e-14)
2421
y = 2.0 * y/(1.0 - z) - 1.0;
2424
// Compute number of derivatives
2425
unsigned int num_derivatives = 1;
2427
for (unsigned int j = 0; j < n; j++)
2428
num_derivatives *= 3;
2431
// Declare pointer to two dimensional array that holds combinations of derivatives and initialise
2432
unsigned int **combinations = new unsigned int *[num_derivatives];
2434
for (unsigned int j = 0; j < num_derivatives; j++)
2436
combinations[j] = new unsigned int [n];
2437
for (unsigned int k = 0; k < n; k++)
2438
combinations[j][k] = 0;
2441
// Generate combinations of derivatives
2442
for (unsigned int row = 1; row < num_derivatives; row++)
2444
for (unsigned int num = 0; num < row; num++)
2446
for (unsigned int col = n-1; col+1 > 0; col--)
2448
if (combinations[row][col] + 1 > 2)
2449
combinations[row][col] = 0;
2452
combinations[row][col] += 1;
2459
// Compute inverse of Jacobian
2460
const double Jinv[3][3] ={{d00 / detJ, d10 / detJ, d20 / detJ}, {d01 / detJ, d11 / detJ, d21 / detJ}, {d02 / detJ, d12 / detJ, d22 / detJ}};
2462
// Declare transformation matrix
2463
// Declare pointer to two dimensional array and initialise
2464
double **transform = new double *[num_derivatives];
2466
for (unsigned int j = 0; j < num_derivatives; j++)
2468
transform[j] = new double [num_derivatives];
2469
for (unsigned int k = 0; k < num_derivatives; k++)
2470
transform[j][k] = 1;
2473
// Construct transformation matrix
2474
for (unsigned int row = 0; row < num_derivatives; row++)
2476
for (unsigned int col = 0; col < num_derivatives; col++)
2478
for (unsigned int k = 0; k < n; k++)
2479
transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
2484
for (unsigned int j = 0; j < 1*num_derivatives; j++)
2487
// Map degree of freedom to element degree of freedom
2488
const unsigned int dof = i;
2490
// Generate scalings
2491
const double scalings_y_0 = 1;
2492
const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
2493
const double scalings_z_0 = 1;
2494
const double scalings_z_1 = scalings_z_0*(0.5 - 0.5*z);
2496
// Compute psitilde_a
2497
const double psitilde_a_0 = 1;
2498
const double psitilde_a_1 = x;
2500
// Compute psitilde_bs
2501
const double psitilde_bs_0_0 = 1;
2502
const double psitilde_bs_0_1 = 1.5*y + 0.5;
2503
const double psitilde_bs_1_0 = 1;
2505
// Compute psitilde_cs
2506
const double psitilde_cs_00_0 = 1;
2507
const double psitilde_cs_00_1 = 2*z + 1;
2508
const double psitilde_cs_01_0 = 1;
2509
const double psitilde_cs_10_0 = 1;
2511
// Compute basisvalues
2512
const double basisvalue0 = 0.866025403784439*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_0;
2513
const double basisvalue1 = 2.73861278752583*psitilde_a_1*scalings_y_1*psitilde_bs_1_0*scalings_z_1*psitilde_cs_10_0;
2514
const double basisvalue2 = 1.58113883008419*psitilde_a_0*scalings_y_0*psitilde_bs_0_1*scalings_z_1*psitilde_cs_01_0;
2515
const double basisvalue3 = 1.11803398874989*psitilde_a_0*scalings_y_0*psitilde_bs_0_0*scalings_z_0*psitilde_cs_00_1;
2517
// Table(s) of coefficients
2518
const static double coefficients0[4][4] = \
2519
{{0.288675134594813, -0.182574185835055, -0.105409255338946, -0.074535599249993},
2520
{0.288675134594813, 0.182574185835055, -0.105409255338946, -0.074535599249993},
2521
{0.288675134594813, 0, 0.210818510677892, -0.074535599249993},
2522
{0.288675134594813, 0, 0, 0.223606797749979}};
2524
// Interesting (new) part
2525
// Tables of derivatives of the polynomial base (transpose)
2526
const static double dmats0[4][4] = \
2528
{6.32455532033676, 0, 0, 0},
2532
const static double dmats1[4][4] = \
2534
{3.16227766016838, 0, 0, 0},
2535
{5.47722557505166, 0, 0, 0},
2538
const static double dmats2[4][4] = \
2540
{3.16227766016838, 0, 0, 0},
2541
{1.82574185835055, 0, 0, 0},
2542
{5.16397779494322, 0, 0, 0}};
2544
// Compute reference derivatives
2545
// Declare pointer to array of derivatives on FIAT element
2546
double *derivatives = new double [num_derivatives];
2548
// Declare coefficients
2549
double coeff0_0 = 0;
2550
double coeff0_1 = 0;
2551
double coeff0_2 = 0;
2552
double coeff0_3 = 0;
2554
// Declare new coefficients
2555
double new_coeff0_0 = 0;
2556
double new_coeff0_1 = 0;
2557
double new_coeff0_2 = 0;
2558
double new_coeff0_3 = 0;
2560
// Loop possible derivatives
2561
for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
2563
// Get values from coefficients array
2564
new_coeff0_0 = coefficients0[dof][0];
2565
new_coeff0_1 = coefficients0[dof][1];
2566
new_coeff0_2 = coefficients0[dof][2];
2567
new_coeff0_3 = coefficients0[dof][3];
2569
// Loop derivative order
2570
for (unsigned int j = 0; j < n; j++)
2572
// Update old coefficients
2573
coeff0_0 = new_coeff0_0;
2574
coeff0_1 = new_coeff0_1;
2575
coeff0_2 = new_coeff0_2;
2576
coeff0_3 = new_coeff0_3;
2578
if(combinations[deriv_num][j] == 0)
2580
new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0];
2581
new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1];
2582
new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2];
2583
new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3];
2585
if(combinations[deriv_num][j] == 1)
2587
new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0];
2588
new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1];
2589
new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2];
2590
new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3];
2592
if(combinations[deriv_num][j] == 2)
2594
new_coeff0_0 = coeff0_0*dmats2[0][0] + coeff0_1*dmats2[1][0] + coeff0_2*dmats2[2][0] + coeff0_3*dmats2[3][0];
2595
new_coeff0_1 = coeff0_0*dmats2[0][1] + coeff0_1*dmats2[1][1] + coeff0_2*dmats2[2][1] + coeff0_3*dmats2[3][1];
2596
new_coeff0_2 = coeff0_0*dmats2[0][2] + coeff0_1*dmats2[1][2] + coeff0_2*dmats2[2][2] + coeff0_3*dmats2[3][2];
2597
new_coeff0_3 = coeff0_0*dmats2[0][3] + coeff0_1*dmats2[1][3] + coeff0_2*dmats2[2][3] + coeff0_3*dmats2[3][3];
2601
// Compute derivatives on reference element as dot product of coefficients and basisvalues
2602
derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3;
2605
// Transform derivatives back to physical element
2606
for (unsigned int row = 0; row < num_derivatives; row++)
2608
for (unsigned int col = 0; col < num_derivatives; col++)
2610
values[row] += transform[row][col]*derivatives[col];
2613
// Delete pointer to array of derivatives on FIAT element
2614
delete [] derivatives;
2616
// Delete pointer to array of combinations of derivatives and transform
2617
for (unsigned int row = 0; row < num_derivatives; row++)
2619
delete [] combinations[row];
2620
delete [] transform[row];
2623
delete [] combinations;
2624
delete [] transform;
2627
/// Evaluate order n derivatives of all basis functions at given point in cell
2628
virtual void evaluate_basis_derivatives_all(unsigned int n,
2630
const double* coordinates,
2631
const ufc::cell& c) const
2633
throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
2636
/// Evaluate linear functional for dof i on the function f
2637
virtual double evaluate_dof(unsigned int i,
2638
const ufc::function& f,
2639
const ufc::cell& c) const
2641
// The reference points, direction and weights:
2642
const static double X[4][1][3] = {{{0, 0, 0}}, {{1, 0, 0}}, {{0, 1, 0}}, {{0, 0, 1}}};
2643
const static double W[4][1] = {{1}, {1}, {1}, {1}};
2644
const static double D[4][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}};
2646
const double * const * x = c.coordinates;
2647
double result = 0.0;
2648
// Iterate over the points:
2649
// Evaluate basis functions for affine mapping
2650
const double w0 = 1.0 - X[i][0][0] - X[i][0][1] - X[i][0][2];
2651
const double w1 = X[i][0][0];
2652
const double w2 = X[i][0][1];
2653
const double w3 = X[i][0][2];
2655
// Compute affine mapping y = F(X)
2657
y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0] + w3*x[3][0];
2658
y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1] + w3*x[3][1];
2659
y[2] = w0*x[0][2] + w1*x[1][2] + w2*x[2][2] + w3*x[3][2];
2661
// Evaluate function at physical points
2663
f.evaluate(values, y, c);
2665
// Map function values using appropriate mapping
2666
// Affine map: Do nothing
2668
// Note that we do not map the weights (yet).
2670
// Take directional components
2671
for(int k = 0; k < 1; k++)
2672
result += values[k]*D[i][0][k];
2673
// Multiply by weights
2679
/// Evaluate linear functionals for all dofs on the function f
2680
virtual void evaluate_dofs(double* values,
2681
const ufc::function& f,
2682
const ufc::cell& c) const
2684
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2687
/// Interpolate vertex values from dof values
2688
virtual void interpolate_vertex_values(double* vertex_values,
2689
const double* dof_values,
2690
const ufc::cell& c) const
2692
// Evaluate at vertices and use affine mapping
2693
vertex_values[0] = dof_values[0];
2694
vertex_values[1] = dof_values[1];
2695
vertex_values[2] = dof_values[2];
2696
vertex_values[3] = dof_values[3];
2699
/// Return the number of sub elements (for a mixed element)
2700
virtual unsigned int num_sub_elements() const
2705
/// Create a new finite element for sub element i (for a mixed element)
2706
virtual ufc::finite_element* create_sub_element(unsigned int i) const
2708
return new UFC_Poisson3D_1LinearForm_finite_element_1();
2713
/// This class defines the interface for a local-to-global mapping of
2714
/// degrees of freedom (dofs).
2716
class UFC_Poisson3D_1LinearForm_dof_map_0: public ufc::dof_map
2720
unsigned int __global_dimension;
2725
UFC_Poisson3D_1LinearForm_dof_map_0() : ufc::dof_map()
2727
__global_dimension = 0;
2731
virtual ~UFC_Poisson3D_1LinearForm_dof_map_0()
2736
/// Return a string identifying the dof map
2737
virtual const char* signature() const
2739
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
2742
/// Return true iff mesh entities of topological dimension d are needed
2743
virtual bool needs_mesh_entities(unsigned int d) const
2763
/// Initialize dof map for mesh (return true iff init_cell() is needed)
2764
virtual bool init_mesh(const ufc::mesh& m)
2766
__global_dimension = m.num_entities[0];
2770
/// Initialize dof map for given cell
2771
virtual void init_cell(const ufc::mesh& m,
2777
/// Finish initialization of dof map for cells
2778
virtual void init_cell_finalize()
2783
/// Return the dimension of the global finite element function space
2784
virtual unsigned int global_dimension() const
2786
return __global_dimension;
2789
/// Return the dimension of the local finite element function space
2790
virtual unsigned int local_dimension() const
2795
// Return the geometric dimension of the coordinates this dof map provides
2796
virtual unsigned int geometric_dimension() const
2798
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2801
/// Return the number of dofs on each cell facet
2802
virtual unsigned int num_facet_dofs() const
2807
/// Return the number of dofs associated with each cell entity of dimension d
2808
virtual unsigned int num_entity_dofs(unsigned int d) const
2810
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2813
/// Tabulate the local-to-global mapping of dofs on a cell
2814
virtual void tabulate_dofs(unsigned int* dofs,
2816
const ufc::cell& c) const
2818
dofs[0] = c.entity_indices[0][0];
2819
dofs[1] = c.entity_indices[0][1];
2820
dofs[2] = c.entity_indices[0][2];
2821
dofs[3] = c.entity_indices[0][3];
2824
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
2825
virtual void tabulate_facet_dofs(unsigned int* dofs,
2826
unsigned int facet) const
2853
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
2854
virtual void tabulate_entity_dofs(unsigned int* dofs,
2855
unsigned int d, unsigned int i) const
2857
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2860
/// Tabulate the coordinates of all dofs on a cell
2861
virtual void tabulate_coordinates(double** coordinates,
2862
const ufc::cell& c) const
2864
const double * const * x = c.coordinates;
2865
coordinates[0][0] = x[0][0];
2866
coordinates[0][1] = x[0][1];
2867
coordinates[0][2] = x[0][2];
2868
coordinates[1][0] = x[1][0];
2869
coordinates[1][1] = x[1][1];
2870
coordinates[1][2] = x[1][2];
2871
coordinates[2][0] = x[2][0];
2872
coordinates[2][1] = x[2][1];
2873
coordinates[2][2] = x[2][2];
2874
coordinates[3][0] = x[3][0];
2875
coordinates[3][1] = x[3][1];
2876
coordinates[3][2] = x[3][2];
2879
/// Return the number of sub dof maps (for a mixed element)
2880
virtual unsigned int num_sub_dof_maps() const
2885
/// Create a new dof_map for sub dof map i (for a mixed element)
2886
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
2888
return new UFC_Poisson3D_1LinearForm_dof_map_0();
2893
/// This class defines the interface for a local-to-global mapping of
2894
/// degrees of freedom (dofs).
2896
class UFC_Poisson3D_1LinearForm_dof_map_1: public ufc::dof_map
2900
unsigned int __global_dimension;
2905
UFC_Poisson3D_1LinearForm_dof_map_1() : ufc::dof_map()
2907
__global_dimension = 0;
2911
virtual ~UFC_Poisson3D_1LinearForm_dof_map_1()
2916
/// Return a string identifying the dof map
2917
virtual const char* signature() const
2919
return "FFC dof map for Lagrange finite element of degree 1 on a tetrahedron";
2922
/// Return true iff mesh entities of topological dimension d are needed
2923
virtual bool needs_mesh_entities(unsigned int d) const
2943
/// Initialize dof map for mesh (return true iff init_cell() is needed)
2944
virtual bool init_mesh(const ufc::mesh& m)
2946
__global_dimension = m.num_entities[0];
2950
/// Initialize dof map for given cell
2951
virtual void init_cell(const ufc::mesh& m,
2957
/// Finish initialization of dof map for cells
2958
virtual void init_cell_finalize()
2963
/// Return the dimension of the global finite element function space
2964
virtual unsigned int global_dimension() const
2966
return __global_dimension;
2969
/// Return the dimension of the local finite element function space
2970
virtual unsigned int local_dimension() const
2975
// Return the geometric dimension of the coordinates this dof map provides
2976
virtual unsigned int geometric_dimension() const
2978
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2981
/// Return the number of dofs on each cell facet
2982
virtual unsigned int num_facet_dofs() const
2987
/// Return the number of dofs associated with each cell entity of dimension d
2988
virtual unsigned int num_entity_dofs(unsigned int d) const
2990
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
2993
/// Tabulate the local-to-global mapping of dofs on a cell
2994
virtual void tabulate_dofs(unsigned int* dofs,
2996
const ufc::cell& c) const
2998
dofs[0] = c.entity_indices[0][0];
2999
dofs[1] = c.entity_indices[0][1];
3000
dofs[2] = c.entity_indices[0][2];
3001
dofs[3] = c.entity_indices[0][3];
3004
/// Tabulate the local-to-local mapping from facet dofs to cell dofs
3005
virtual void tabulate_facet_dofs(unsigned int* dofs,
3006
unsigned int facet) const
3033
/// Tabulate the local-to-local mapping of dofs on entity (d, i)
3034
virtual void tabulate_entity_dofs(unsigned int* dofs,
3035
unsigned int d, unsigned int i) const
3037
throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
3040
/// Tabulate the coordinates of all dofs on a cell
3041
virtual void tabulate_coordinates(double** coordinates,
3042
const ufc::cell& c) const
3044
const double * const * x = c.coordinates;
3045
coordinates[0][0] = x[0][0];
3046
coordinates[0][1] = x[0][1];
3047
coordinates[0][2] = x[0][2];
3048
coordinates[1][0] = x[1][0];
3049
coordinates[1][1] = x[1][1];
3050
coordinates[1][2] = x[1][2];
3051
coordinates[2][0] = x[2][0];
3052
coordinates[2][1] = x[2][1];
3053
coordinates[2][2] = x[2][2];
3054
coordinates[3][0] = x[3][0];
3055
coordinates[3][1] = x[3][1];
3056
coordinates[3][2] = x[3][2];
3059
/// Return the number of sub dof maps (for a mixed element)
3060
virtual unsigned int num_sub_dof_maps() const
3065
/// Create a new dof_map for sub dof map i (for a mixed element)
3066
virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
3068
return new UFC_Poisson3D_1LinearForm_dof_map_1();
3073
/// This class defines the interface for the tabulation of the cell
3074
/// tensor corresponding to the local contribution to a form from
3075
/// the integral over a cell.
3077
class UFC_Poisson3D_1LinearForm_cell_integral_0: public ufc::cell_integral
3082
UFC_Poisson3D_1LinearForm_cell_integral_0() : ufc::cell_integral()
3088
virtual ~UFC_Poisson3D_1LinearForm_cell_integral_0()
3093
/// Tabulate the tensor for the contribution from a local cell
3094
virtual void tabulate_tensor(double* A,
3095
const double * const * w,
3096
const ufc::cell& c) const
3098
// Extract vertex coordinates
3099
const double * const * x = c.coordinates;
3101
// Compute Jacobian of affine map from reference cell
3102
const double J_00 = x[1][0] - x[0][0];
3103
const double J_01 = x[2][0] - x[0][0];
3104
const double J_02 = x[3][0] - x[0][0];
3105
const double J_10 = x[1][1] - x[0][1];
3106
const double J_11 = x[2][1] - x[0][1];
3107
const double J_12 = x[3][1] - x[0][1];
3108
const double J_20 = x[1][2] - x[0][2];
3109
const double J_21 = x[2][2] - x[0][2];
3110
const double J_22 = x[3][2] - x[0][2];
3112
// Compute sub determinants
3113
const double d_00 = J_11*J_22 - J_12*J_21;
3115
const double d_10 = J_02*J_21 - J_01*J_22;
3117
const double d_20 = J_01*J_12 - J_02*J_11;
3119
// Compute determinant of Jacobian
3120
double detJ = J_00*d_00 + J_10*d_10 + J_20*d_20;
3122
// Compute inverse of Jacobian
3125
const double det = std::abs(detJ);
3127
// Compute coefficients
3128
const double c0_0_0_0 = w[0][0];
3129
const double c0_0_0_1 = w[0][1];
3130
const double c0_0_0_2 = w[0][2];
3131
const double c0_0_0_3 = w[0][3];
3133
// Compute geometry tensors
3134
const double G0_0 = det*c0_0_0_0;
3135
const double G0_1 = det*c0_0_0_1;
3136
const double G0_2 = det*c0_0_0_2;
3137
const double G0_3 = det*c0_0_0_3;
3139
// Compute element tensor
3140
A[0] = 0.0166666666666666*G0_0 + 0.00833333333333331*G0_1 + 0.00833333333333331*G0_2 + 0.00833333333333331*G0_3;
3141
A[1] = 0.00833333333333331*G0_0 + 0.0166666666666666*G0_1 + 0.00833333333333331*G0_2 + 0.00833333333333331*G0_3;
3142
A[2] = 0.00833333333333331*G0_0 + 0.00833333333333331*G0_1 + 0.0166666666666666*G0_2 + 0.00833333333333331*G0_3;
3143
A[3] = 0.00833333333333331*G0_0 + 0.00833333333333331*G0_1 + 0.00833333333333331*G0_2 + 0.0166666666666666*G0_3;
3148
/// This class defines the interface for the assembly of the global
3149
/// tensor corresponding to a form with r + n arguments, that is, a
3152
/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
3154
/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
3155
/// global tensor A is defined by
3157
/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
3159
/// where each argument Vj represents the application to the
3160
/// sequence of basis functions of Vj and w1, w2, ..., wn are given
3161
/// fixed functions (coefficients).
3163
class UFC_Poisson3D_1LinearForm: public ufc::form
3168
UFC_Poisson3D_1LinearForm() : ufc::form()
3174
virtual ~UFC_Poisson3D_1LinearForm()
3179
/// Return a string identifying the form
3180
virtual const char* signature() const
3182
return "w0_a0 | vi0*va0*dX(0)";
3185
/// Return the rank of the global tensor (r)
3186
virtual unsigned int rank() const
3191
/// Return the number of coefficients (n)
3192
virtual unsigned int num_coefficients() const
3197
/// Return the number of cell integrals
3198
virtual unsigned int num_cell_integrals() const
3203
/// Return the number of exterior facet integrals
3204
virtual unsigned int num_exterior_facet_integrals() const
3209
/// Return the number of interior facet integrals
3210
virtual unsigned int num_interior_facet_integrals() const
3215
/// Create a new finite element for argument function i
3216
virtual ufc::finite_element* create_finite_element(unsigned int i) const
3221
return new UFC_Poisson3D_1LinearForm_finite_element_0();
3224
return new UFC_Poisson3D_1LinearForm_finite_element_1();
3230
/// Create a new dof map for argument function i
3231
virtual ufc::dof_map* create_dof_map(unsigned int i) const
3236
return new UFC_Poisson3D_1LinearForm_dof_map_0();
3239
return new UFC_Poisson3D_1LinearForm_dof_map_1();
3245
/// Create a new cell integral on sub domain i
3246
virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
3248
return new UFC_Poisson3D_1LinearForm_cell_integral_0();
3251
/// Create a new exterior facet integral on sub domain i
3252
virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
3257
/// Create a new interior facet integral on sub domain i
3258
virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
3267
#include <dolfin/Form.h>
3269
class Poisson3D_1BilinearForm : public dolfin::Form
3273
Poisson3D_1BilinearForm() : dolfin::Form()
3279
virtual const ufc::form& form() const
3284
/// Return array of coefficients
3285
virtual const dolfin::Array<dolfin::Function*>& coefficients() const
3287
return __coefficients;
3293
UFC_Poisson3D_1BilinearForm __form;
3295
/// Array of coefficients
3296
dolfin::Array<dolfin::Function*> __coefficients;
3300
class Poisson3D_1LinearForm : public dolfin::Form
3304
Poisson3D_1LinearForm(dolfin::Function& w0) : dolfin::Form()
3306
__coefficients.push_back(&w0);
3310
virtual const ufc::form& form() const
3315
/// Return array of coefficients
3316
virtual const dolfin::Array<dolfin::Function*>& coefficients() const
3318
return __coefficients;
3324
UFC_Poisson3D_1LinearForm __form;
3326
/// Array of coefficients
3327
dolfin::Array<dolfin::Function*> __coefficients;