Upload
rs0004
View
249
Download
0
Embed Size (px)
Citation preview
8/8/2019 Advanced Finite Element
1/172
8/8/2019 Advanced Finite Element
2/172
8/8/2019 Advanced Finite Element
3/172
Workbook of Applications in VectorSpace C++ Library 453
Mixed and Hybrid Finite Element Methods
Eq. 512
where and with over-bar are fixed nodal flux boundary conditions and fixed nodal temperature boundary
conditions, respectively, while h in Eq. 512 can be specified as a function on an element boundary. The fixed
nodal boundary conditions, and , in Eq. 511 and Eq. 512 are encountered frequently in finite element
method and are taken care of by fe.lib as default behaviors behind the scene. This is consistent with the treat-
ment of the result of the displacementboundary conditions as reaction, and substrates out of the nodal force term
as -= K .
By inspecting on Eq. 59 and Eq. 510, the derivatives of temperature field exist. C0-continuity of T on the
element interior and boundaries is required. This is needed to guarantees that Eq. 510 over the entire problemdomain is integrable. Otherwise, the integration goes to infinity at the discontinuities. Two triangular elements
are considered in the following computations. Figure 51a&b shows that two triangular elements with linear tem-
perature field with three corner nodes and either a constant heat flux with one node at the center of the element or
linear heat flux with three nodes at the Gaussian integration points. We notice that the temperature nodes on the
three corners is necessary to ensure the C0-continuity on the element boundaries, while the heat flux, with no
derivatives of heat flux in Eq. 59 and Eq. 510, can be discontinuous at the element boundaries. Therefore, the
constant heat flux element has one node at the center of the element (Figure 51a), and the linear heat flux ele-
ment has three nodes at the Gaussian integration points (Figure 51b). Actually, requiring heat flux to be C0-con-tinuity on the element boundaries, had we use three corner nodes for the heat flux, may cause physically
incorrect conditions.1
Recall in Section 4.2.5, the mixed formulation for one dimensional beam bending problem, we have extended
fe.lib with the object-oriented modeling for developing matrix substructuring to solve system of equations in
submatrices similar to Eq. 58.
1. e.g. as discussed in p.327 in Zienkiewicz, O.C. and R.L. Taylor, 1991, The finite element method, 4th ed., vol. 1.McGraw-Hill, Inc., UK.
f2 T f de
T h dh
e
Ch he+=
h g
h g
f u
Figure 51 Triangluar elements with linear temperature with three corner nodes, and eitherconstant heat flux with one node at the center or linear heat flux with three nodes at three Gaussintegration points.
T-nodesq-nodes
(a) Constantheat flux
(b) Linearheat flux
T = 0oC
T = 30oC
q = 0q = 0
(c)
http://finiteelement.fm.pdf/http://finiteelement.fm.pdf/8/8/2019 Advanced Finite Element
4/172
Advanced Finite Element Methods
454 Workbook of Applications in VectorSpace C++ Library
Chapter 5
The Program Listing 51 implements the constant heat flux triangular element for the mixed formulation. For
global discretization {h, qh}, with its element discretization as qe, the heat flux is constant over entire domain
ofqe. Only one node at the center of the element is needed. However we still need to specify the three corner
nodes in order to (1) compute the coordinates of the center node, (2) define coordinate transformation rule, and(3) perform integration. Therefore, the three additional corner nodes of q
e are defined as geometrical nodes.
The geometrical nodes has no variable associated with them. A simple trick using fe.lib is to disable all geo-
metrical nodes by specifying all these nodes to have Dirichlet type boundary condition, so they will be left out of
the global stiffness matrix. The A-submatrix are defined by
1 double k_x = 1.0, k_y = 1.0,
2 k_inv[2][2] = { {1.0/k_x, 0.0 }, // , for isotropy
3 {0.0, 1.0/k_y }};4 C0 K_inv = MATRIX("int, int, const double*", 2, 2, k_inv[0]);
5 Heat_Mixed_Formulation::Heat_Mixed_Formulation(int en, Global_Discretization& gd) :
6 Element_Formulation_Couple(en, gd) {
7 Quadrature qp(2, 4);
8 H1 L(2, (double*)0, qp),
9 n = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 3, 2, qp),
10 L0 = L[0], L1 = L[1], L2 = 1.0 - L0 - L1; // area coordinates for a triangle
11 n[0] = L0; n[1] = L1; n[2] = L2;12 C0 x = MATRIX("int, int, C0&, int, int", 3, 2, xl, 0, 0);
13 H1 X = n*x;
14 J dv(d(X).det()/2.0);
15 H0 N = INTEGRABLE_VECTOR("int, Quadrature", 4, qp);
16 N[0] = N[1] = N[2] = 0.0; N[3] = 1.0;
17 H0 N_q = ((~N) || C0(0.0)) &
18 (C0(0.0) || (~N) ); //
19 stiff &= ((~N_q) * (K_inv * N_q)) | dv;20 }
The area coordinates for triangle,L0,L1, andL2, are used for coordinate transformation and integration. The first
three nodes are geometrical nodes at three corners and the fourth-node is the q-node at the center. A reference
matrix x (line 12) is constructed to refer to the first three coordinates of xl, which leaves out the q-node. To
compute the Jacobian we notice that there is a factor of 1/2 for a triangular element comparing to the a quadrilat-
eral element where the factor = 1 (note that a factor of 1/6 is to be used for a 3-D tetrahedra element). The q-
shape function, N (line 16), is defined that the first three shape functions corresponding to three geometrical
nodes are zero; i.e., N[0] = N[1] = N[2] = 0. And the fourth shape function is one; i.e., N[3] = 1. The ele-
ment stiffness matrix so constructed will have the size of 8 8, with only the 2 2 submatrix at the lower-right
corner, corresponding to the center q-node, contains no zero components. All the geometrical nodes are to be
specified with Dirichlet type boundary condition. Dummy variables corresponding to these geometrical nodes
will all be eliminated from the global matrix and the global vector. Therefore, the no trivial 2 2 element subma-
trix will enter the global stiffness matrix.
The C-submatrix can be defined as
1 1 ij 1 0
0 1
= =
A q 1 q( ) de
=
8/8/2019 Advanced Finite Element
5/172
8/8/2019 Advanced Finite Element
6/172
Advanced Finite Element Methods
456 Workbook of Applications in VectorSpace C++ Library
Chapter 5
hdisable all geometrical nodes on q
gtop boundary: T = 30o
bottom boundary: T = 0o
for diagonal submatrix A
for off-diagonal submatrix C
A-submatrix element formulation
area coordinates for triangle
linear triangular shape function for
coordinate transformation
= 1.0 (constant over element)
N[0], N[1], N[2] are geometrical nodes
N[3] is constant over element domain
q
ena[0] = first_corner_node_no; ena[1] = first_corner_node_no+1+row_t_node_no;
ena[2] = first_corner_node_no+row_t_node_no;
elem = new Omega_eh(element_no+1, 0, 0, 3, ena); omega_eh_array().add(elem);
}
}}
gh_on_Gamma_h_i::gh_on_Gamma_h_i(int i, int df, Omega_h& omega_h) : gh_on_Gamma_h() {
gh_on_Gamma_h::__initialization(df, omega_h);
if(i == 0) {
for(int j = (row_t_node_no-1)*6*(row_t_node_no-1);
j < (row_t_node_no*row_t_node_no+(row_t_node_no-1)*6*(row_t_node_no-1)); j++)
for(int k = 0; k < 2; k++) {
the_gh_array[node_order(j)](k) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(j)][k] = 0.0;
}
} else if(i == 1) {
for(int j = 0; j < row_t_node_no; j++) {
the_gh_array[node_order(row_t_node_no*(row_t_node_no-1)+j)](0) =
gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(row_t_node_no*(row_t_node_no-1)+j)][0] =
((double)(row_t_node_no-1))*10.0;
the_gh_array[node_order(j)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(j)][0] = 0.0;
}
}
}static const int q_ndf = 2; static Omega_h_i oh_q(0);
static gh_on_Gamma_h_i q_gh(0, q_ndf, oh_q); static U_h q_h(q_ndf, oh_q);
static Global_Discretization q_gd(oh_q, q_gh, q_h);
static const int T_ndf = 1; static Omega_h_i oh_T(1);
static gh_on_Gamma_h_i T_gh(1, T_ndf, oh_T); static U_h T_h(T_ndf, oh_T);
static Global_Discretization T_gd(oh_T, T_gh, T_h);
static Global_Discretization_Couple gdc(T_gd, q_gd);
class Heat_Mixed_Formulation : public Element_Formulation_Couple {
public:
Heat_Mixed_Formulation(Element_Type_Register a) : Element_Formulation_Couple(a) {}Element_Formulation *make(int, Global_Discretization&);
Heat_Mixed_Formulation(int, Global_Discretization&);
Element_Formulation_Couple *make(int, Global_Discretization_Couple&);
Heat_Mixed_Formulation(int, Global_Discretization_Couple&);
};
Element_Formulation* Heat_Mixed_Formulation::make(int en, Global_Discretization& gd) {
return new Heat_Mixed_Formulation(en,gd);
}
Heat_Mixed_Formulation::Heat_Mixed_Formulation(int en, Global_Discretization& gd) :
Element_Formulation_Couple(en, gd) {Quadrature qp(2, 4);
H1 L(2, (double*)0, qp),
n = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 3, 2, qp),
L0 = L[0], L1 = L[1], L2 = 1.0 - L0 - L1;
n[0] = L0; n[1] = L1; n[2] = L2;
C0 x = MATRIX("int, int, C0&, int, int", 3, 2, xl, 0, 0);
H1 X = n*x;
J dv(d(X).det()/2.0);
H0 N = INTEGRABLE_VECTOR("int, Quadrature", 4, qp);
N[0] = N[1] = N[2] = 0.0;
N[3] = 1.0;
8/8/2019 Advanced Finite Element
7/172
8/8/2019 Advanced Finite Element
8/172
Advanced Finite Element Methods
458 Workbook of Applications in VectorSpace C++ Library
Chapter 5
1 Heat_Mixed_Formulation::Heat_Mixed_Formulation(int en, Global_Discretization_Couple& gdc)
2 : Element_Formulation_Couple(en, gdc) {
3 Quadrature qp(2, 4);
4 H1 L(2, (double*)0, qp),5 n = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
6 "int, int, Quadrature", 3/*nen*/, 2/*nsd*/, qp),
7 L0 = L[0], L1 = L[1], L2 = 1.0 - L0 - L1;
8 n[0] = L0; n[1] = L1; n[2] = L2;
9 H1 X = n*xl;
10 H0 nx = d(n) * d(X).inverse();
11 J dv(d(X).det()/2.0);
12 H0 N = INTEGRABLE_VECTOR("int, Quadrature", 4/*nen*/, qp);13 N[0] = N[1] = N[2] = 0.0; N[3] = 1.0;
14 H0 N_q = ( (~N) || C0(0.0)) &
15 (C0(0.0) || (~N)); //
16 stiff &= (nx * N_q) | dv;
17 }
The element stiffness matrix so generated has the size of 3 8. The three rows (number of equations) corre-
sponding to three temperature nodes at the corner. After the element to global mapping, the first 6 columns (cor-responding to the number of dummy variables) for the geometrical nodes will not enter the global stiffness
matrix. Only the last 2 columns (corresponding to the number of variables) for the center q-node will survive.
After the submatrices have been formed, the solution of system of equation in Eq. 58 is the subject ofcon-
straint optimization problem (see Section 2.3.3 in Chapter 2). In the context of finite element problem, the objec-
tive functional for optimization is quadratic. The problem is further restricted to a quadratic programming
problem, in which only one step along the search path is needed to reach the exact solution (see introduction and
its example in page 145). We discuss the range space methodand null space method(see page 149) to solve Eq.58 in the followings.
From first equation ofEq. 58 we have
A + CT = f1 Eq. 513
Considering A is symmetrical positive definitive, therefore it can be inverted, we can solve for q by
= A-1 f1 - A-1CT Eq. 514
Substituting Eq. 514 into second equation ofEq. 58,C = f2, we have
CA-1 f1 - C A-1CT = f2 Eq. 515
Therefore, can also be solved considering that the similarity transformation ofA-1 as C A-1CT preserves
the symmetrical positive definitiveness ofA-1. An alternative view is that C A-1CT is the projection of inverse
C T q de
=
q T
q T
q
T
T
http://optimization.fm.pdf/http://optimization.fm.pdf/http://optimization.fm.pdf/http://optimization.fm.pdf/http://optimization.fm.pdf/http://optimization.fm.pdf/8/8/2019 Advanced Finite Element
9/172
8/8/2019 Advanced Finite Element
10/172
Advanced Finite Element Methods
460 Workbook of Applications in VectorSpace C++ Library
Chapter 5
17 for(int i = 0; i < q_h.total_node_no(); i++)
18 cout
8/8/2019 Advanced Finite Element
11/172
Workbook of Applications in VectorSpace C++ Library 461
Mixed and Hybrid Finite Element Methods
Both the range space and null space method reproduce the exact solution up to round-off error for the current
problem. The nodal temperature solutions at the second row is = 10 oC, and the third row is = 20 oC. All
heat flux center nodes have the values of = [0, -10]T per unit length. The default method in Program Listing
51 is the range space method. The null space method can be activated by setting macro definition__NULL_SPACE_METHOD at compile time.
The linear heat flux with three nodes at the Gaussian integration points (see Figure 51b) can be activated by
setting macro definition __TEST_THREE_NODES_DISCONTINUOUS_HEAT_FLUX at compile time. The
triangular element in this implementation used shape functions degenerated from bilinear 4-node element. The
results of this linear heat flux element is identical to that of the constant heat flux element. Considering that T-
field only for a 3-node triangular element vary linearly. The heat flux, computed from the Fouries law, is the
derivative of the linear T-field, which is constant. Therefore, the linear heat flux element does not give any
improvement in the accuracy of the solution comparing to the constant heat flux element. Actually, the linear
heat flux element produces the same result as the constant heat flux element. This is known as the limitationprin-
ciple by Fraeijs de Veubeke.
With the assistance of object-oriented modeling provided in fe.lib for handling the matrix substructuring, it
may seems to be a piece of cake to implement the multiple-field mixed formulation. It is not so for most existing
finite element programs. It has been remarked that the full-scale multiple-field formulations are rarely imple-
mented for practical computation.1
The discontinuous heat flux field, with nodes reside only inside an element, not only avoid physically incor-
rect conditions as mentioned earlier, but it also has the advantage that the heat flux field can be eliminated at the
element level. Every heat flux node belongs only to its containing element; i.e., there are no shared heat flux
nodes with the neighboring elements. Therefore, from Eq. 516 that
= (C A-1CT)-1 (CA-1 f1 - f2)
We can redefine element stiffness matrix and element force vector as
ke = Ce Ae-1CeT, and fe= CeAe-1 f1e - f2
e Eq. 519
respectively, with
Eq. 520
and,
Eq. 521
1. see p.206 in Hughes, T. J.R., The finite element method: linear static and dynamic finite element analysis, Prentice-Hall,Inc., Englewood Cliffs, New Jersey.
T T
q
T
f2e T f d
e=
T h dhe Ceh he 0=
8/8/2019 Advanced Finite Element
12/172
Advanced Finite Element Methods
462 Workbook of Applications in VectorSpace C++ Library
Chapter 5
Since in this discontinuous heat flux element no heat flux boundary condition can be specified, the temperature
boundary conditions in Eq. 58 are simply
f1 = - Eq. 522
Substituting the element level vector ofEq. 522 into the second equation in Eq. 519, we have
fe = - CeAe-1 - f2e= - Ce Ae-1 - f2
e
= -ke - f2e Eq. 523
The first term in the right-hand-side is consistent with standard implementation of finite element on the essential
boundary conditions. The mixed form ofEq. 519 can be easily implemented which does not require the mecha-
nism provided in the fe.lib to express matrix substructuring. Program Listing 52 implements Eq. 519 (project
mixed_T_heat_conduction in project workspace file fe.dsw). The temperature solutions of the computation
is certainly identical to the full-fledged mixed formulation. The program is significant simplified comparing to
the full-scale mixed formulation.
CT
g g
CeT
gege
CeT
gege
ge ge
8/8/2019 Advanced Finite Element
13/172
Workbook of Applications in VectorSpace C++ Library 463
Mixed and Hybrid Finite Element Methods
#include "include\fe.h"
static row_node_no = 4;
EP::element_pattern EP::ep = EP::SLASH_TRIANGLES;
Omega_h::Omega_h() {double coord[4][2] = {{0.0, 0.0}, {3.0, 0.0}, {3.0, 3.0}, {0.0, 3.0}};
int control_node_flag[4] = {TRUE, TRUE, TRUE, TRUE};
block(this, row_node_no, row_node_no, 4, control_node_flag, coord[0]);
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) { __initialization(df, omega_h);
for(int j = 0; j < row_node_no; j++) {
the_gh_array[node_order(row_node_no*(row_node_no-1)+j)](0) =
the_gh_array[node_order(j)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(row_node_no*(row_node_no-1)+j)][0] =
((double)(row_node_no-1))*10.0;
the_gh_array[node_order(j)][0] = 0.0;
}
}
class HeatMixedT3 : public Element_Formulation {
public:
HeatMixedT3(Element_Type_Register a) : Element_Formulation(a) {}
Element_Formulation *make(int, Global_Discretization&);
HeatMixedT3(int, Global_Discretization&);
};
Element_Formulation* HeatMixedT3::make(int en, Global_Discretization& gd) {
return new HeatMixedT3(en,gd); }double k_x = 1.0, k_y = 1.0, k_inv[2][2] = { {1.0/k_x, 0.0}, { 0.0, 1.0/k_y}};
C0 K_inv = MATRIX("int, int, const double*", 2, 2, k_inv[0]);
HeatMixedT3::HeatMixedT3(int en, Global_Discretization& gd) : Element_Formulation(en, gd) {
Quadrature qp(2, 4);
H1 L(2, (double*)0, qp),
n = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 3, 2, qp),
L0 = L[0], L1 = L[1], L2 = 1.0 - L0 - L1;
n[0] = L0; n[1] = L1; n[2] = L2;
H1 X = n*xl; H0 nx = d(n) * d(X).inverse(); J dv(d(X).det()/2.0);
H0 N = INTEGRABLE_SCALAR("Quadrature", qp); N = 1.0;
H0 N_q = ((~N) || C0(0.0)) &(C0(0.0)|| (~N));
C0 C = (nx * N_q) | dv,
A = ((~N_q) * (K_inv * N_q)) | dv,
A_inv = A.inverse();
stiff &= C*A_inv*(~C);
}
Element_Formulation* Element_Formulation::type_list = 0;
Element_Type_Register element_type_register_instance;
static HeatMixedT3 heatmixedt3_instance(element_type_register_instance);
int main() {int ndf = 1; Omega_h oh; gh_on_Gamma_h gh(ndf, oh); U_h uh(ndf, oh);
Global_Discretization gd(oh, gh, uh);
Matrix_Representation mr(gd);
mr.assembly();
C0 u = ((C0)(mr.rhs())) / ((C0)(mr.lhs()));
uh = u; uh = gh;
cout
8/8/2019 Advanced Finite Element
14/172
Advanced Finite Element Methods
464 Workbook of Applications in VectorSpace C++ Library
Chapter 5
Hourglass Element
For the irreducible formulation in Chapter 4, 2 2 Gaussian integration points are used to compute element
stiffness matrix for bilinear 4-node element.
Eq. 524
where
Eq. 525
and a = 0, 1, 2, 3. A reduced integration (1 Gauss point at the center of the element) will result in rank deficiency
of the element stiffness matrix. The rank of the element stiffness matrix is the number of integration points times
the number of independent relations. In the case of heat conduction, the number of independent relations is the
number of equations relating the heat flux [qx, qy] and the temperature gradients [T/x, T/y] by Fourier lawof heat conduction in 2-D. Therefore, the rank of the stiffness matrix for 1-point Gauss integration rule is 2 (=2 1). For the element stiffness matrix of size 4 4 in Eq. 524, the 1-point Gauss integration leads to rank defi-
ciency of 2 (= 4-2). We can consider that the 1-point integration stiffness matrix is span bybx = {bxa,bya} in Eq.
525, which are bases in 4. The two spurious zero energy modes in the null space are constant solution mode
with nodal solution ofsa = [1, 1, 1, 1] and hourglass mode with nodal solution of ha = [-1, 1, -1, 1]. The hour-
glass mode is illustrated in Figure 52. The two zero energy modes are orthogonal tobx
, and Eq. 526
where we also denote x0 = x, and x1 = y. We notice that for isoparametric coordinate transformation xi =Naxia ,
we have the relation
ke N( )TN( )d
e
BTB( )de
= =
Ba bxa
bya
Na
x----------
Nay
----------
-1
-0.5
0
0.5
1
-1
-0.5
0
0.5
1
-1
-0.5
0
0.5
1
-1
-0.5
0
0.5
-1
-0.5
0
0.5
-1
-0.5
0
.5
1
Figure 52 The hourglass mode for heat conduction problem.
T
bxis 0= bxi
h 0=
8/8/2019 Advanced Finite Element
15/172
Workbook of Applications in VectorSpace C++ Library 465
Mixed and Hybrid Finite Element Methods
Eq. 527
The constant nodal solution sa is considered proper, since a constant temperature field produces no heat flux isas expected, while the hourglass mode ha has gradient far from zero (see Figure 52) but no heat flux production,
which is considered improper. Therefore, we expect the 4-node element stiffness to produce a rank 3 matrix.
The strategy is to use a so-called trial hourglass mode, a , to construct a correct-ranked stiffness ke in a way thatis very economical to compute as
ke = ke(1-point) + ke(hourglass) Eq. 528
The first term on the right hand side, ke(1-point) is standard stiffness matrix computed with only one Gaussianintegration point. The second term ke(hourglass) is to be constructed with the trial hourglass mode a. The generalform of the trial hourglass mode, a , in
4 is span by the four bases [bxa,bya, sa, ha] as
a = a0bxa + a1bya + a2sa+ ha Eq. 529
a is required to be orthogonal with an arbitrary lineartemperature field of Ta
Ta = c0 xa + c1ya + c2sa Eq. 530
For a to be always orthogonal with arbitrary coefficients, ci , in Eq. 530, we have
a xa = 0 , a ya = 0, and asa = 0 Eq. 531
From last part ofEq. 531, no component ofa is in sa, so in Eq. 529 a2 = 0, and we have this equation re-writ-ten as
a = a0bxa + a1bya + ha Eq. 532
Substituting Eq. 532 into a xa = 0 in the first part ofEq. 531, and usingbxa xa = 1, andbya xa = 0 as indicatedin Eq. 527, we have
a0 = - ha xa Eq. 533
Similarly, substituting Eq. 532 into a ya = 0 in the second part ofEq. 531, and usingbya ya = 1, andbxa ya = 0
as in Eq. 527, we have
a1 = - ha ya Eq. 534
Therefore, we show that
a = ha - (ha xa)bxa - (ha ya)bya Eq. 535
The hourglass stiffness can be defined as1
bxixj
Nxi-------x
j
ij= =
8/8/2019 Advanced Finite Element
16/172
Advanced Finite Element Methods
466 Workbook of Applications in VectorSpace C++ Library
Chapter 5
Eq. 536
where
ais
anormalized to
||a||= 2, b = [b
x,b
y]T, and . Program Listing 53 implements the
hourglass element for heat conduction (project hourglass_heat in project workspace filefe.dsw).
We measure the time spent in the computation of stiffness matrix for the heat conduction element with irre-
ducible formulation in Chapter 4. It takes 3.5 seconds to assemble the stiffness on an obsolete 166 MHz PC. For
the mixed formulation in the last section, although we gain significant freedom in terms of formulation, the
assemble of diagonal and off-diagonal stiffness matrices (A and C) takes 6.2 seconds on the same computer. The
hourglass element takes only 0.5 second to assemble the stiffness.
1. see similar derivation for elasticity in p.251-254 in Hughes, T. J.R., The finite element method: linear static and dynamicfinite element analysis, Prentice-Hall, Inc., Englewood Cliffs, New Jersey, and references therein.
ke hourg la ss( )kJ b b( )
12----------------------- ( )
J det x
( )
8/8/2019 Advanced Finite Element
17/172
Workbook of Applications in VectorSpace C++ Library 467
Mixed and Hybrid Finite Element Methods
#include "include\fe.h"
EP::element_pattern EP::ep = EP::QUADRILATERALS_4_NODES;
Omega_h::Omega_h() {
double coord[4][2] = {{0.0, 0.0}, {3.0, 0.0}, {3.0, 3.0}, {0.0, 3.0}};int control_node_flag[4] = {1, 1, 1, 1};
block(this, 4, 4, 4, control_node_flag, coord[0]);
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) {
__initialization(df, omega_h);
int row_node_no = 4;
for(int i = 0; i < row_node_no; i++) {
the_gh_array[node_order(i)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(row_node_no*(row_node_no-1)+i)](0) =
gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(row_node_no*(row_node_no-1)+i)][0] = 30.0;}
}
class HourGlassHeatQ4 : public Element_Formulation { public:
HourGlassHeatQ4(Element_Type_Register a) : Element_Formulation(a) {}
Element_Formulation *make(int, Global_Discretization&);
HourGlassHeatQ4(int, Global_Discretization&);
};
Element_Formulation* HourGlassHeatQ4::make(int en, Global_Discretization& gd) {
return new HourGlassHeatQ4(en,gd);
}
HourGlassHeatQ4::HourGlassHeatQ4(int en, Global_Discretization& gd) :
Element_Formulation(en, gd) {
Quadrature qp(2, 1);
H1 Z(2, (double*)0, qp), Zai, Eta,
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 4, 2, qp);
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (1+Zai)*(1-Eta)/4;
N[2] = (1+Zai)*(1+Eta)/4; N[3] = (1-Zai)*(1+Eta)/4;
H1 X = N*xl; H0 Nx = d(N) * d(X).inverse(); J dv(d(X).det());
double k_ = 1.0; C0 K_standard = (Nx * k_ * (~Nx)) | dv;
C0 h(4, (double*)0); h[3] = 1.0;C0 phi = h - Nx.quadrature_point_value(0)*((~xl)*h);
double factor = 2.0/norm(phi); phi *= factor;
H0 b = Nx(0) & Nx(1);
double j = (double)(d(X).det().quadrature_point_value(0));
C0 K_hourglass = (k_*j*((~b)*b) | dv) /12.0 * (phi%phi);
stiff &= K_standard + K_hourglass;
}
Element_Formulation* Element_Formulation::type_list = 0;
Element_Type_Register element_type_register_instance;
static HourGlassHeatQ4 hourglassheatq4_instance(element_type_register_instance);
int main() {
int ndf = 1; Omega_h oh; gh_on_Gamma_h gh(ndf, oh); U_h uh(ndf, oh);
Global_Discretization gd(oh, gh, uh); Matrix_Representation mr(gd);
mr.assembly();
C0 u = ((C0)(mr.rhs())) / ((C0)(mr.lhs()));
uh = u; uh = gh;
cout
8/8/2019 Advanced Finite Element
18/172
Advanced Finite Element Methods
468 Workbook of Applications in VectorSpace C++ Library
Chapter 5
5.1.2 Mixed Formulation for Plane Elasticity
In the irreducible formulation for plane elasticity, the displacement field, u, is the only variable that the vari-
ation of the Lagrangian functional ( ), derived from the equilibrium equations, is taken as
Eq. 537
where the body force is denoted as b, the strain is defined as , and the differential operator L in matrix
form as
Eq. 538
The traction boundary condition is t = h on h. In the mixed formulation, in addition to the variational approxi-
mation on the equilibrium equations. we will also use the variational approximation to both the constitutiveequations and strain-displacement relations, separately. The interpolation functions (x) in finite elementapproximation of displacement field is taken as
Eq. 539
where is interpolation functions, and is nodal displacements. The subscript e denotes the element
level.
Hellinger-Reissner Variational Principle
In addition to the variational principle based on equilibrium equation in Eq. 537, we consider the constitu-
tive equation
Eq. 540
We also add stress field, , as additional variable in the Lagrangian functional such that
Eq. 541
Eq. 537 and Eq. 541 are the Euler-Lagrange equations corresponding to the Lagrangian functional.
Eq. 542
u( )
u( ) Lu( )T d
uT b d
uTh d
h
=
Lu=
L
x------ 0
0
y------
y------
x------
ue ea x( )uea
ea x( ) uea
D DLu= =
T Lu D 1 ( ) d 0=
u,( )1
2--- T
D
1
d uT
LT
b+( ) d uT
n h( ) dh+=
8/8/2019 Advanced Finite Element
19/172
Workbook of Applications in VectorSpace C++ Library 469
Mixed and Hybrid Finite Element Methods
where t = n (the Cauchys formula). The Euler-Lagrange equations are obtained by taking the directional deriv-atives of the Lagrangian functional with respect to and u, then, make them equal to zero. Eq. 542 is known astheHellinger-Reissner variational principle. The finite element approximation of the stress field has interpola-
tion function
(x) in
Eq. 543
By inspecting Eq. 537 and Eq. 541, stress field has no derivatives taken on it. Therefore, the C0-continuity
requirement on the element boundaries, to ensure the integral equation does not give infinity, can be dropped.
The interpolation functions , in contrast to in Eq. 539, can be taken as piece-wise continuous func-
tions across the entire problem domain. For example, for four stress nodes taken at Gauss integration points with
the natural coordinates
Eq. 544
where a = 0, 1, 2, 3. The shape functions for these four nodes are
Eq. 545
If such discontinuous (at the element boundaries) interpolation is taken, the stress field can be approximated glo-
bally. Because there is no inter-element dependency. The subscript e on can be dropped. The matrix form ofEq. 537 and Eq. 541, at element level, is
Eq. 546
where
Eq. 547
Eq. 548
Eq. 549
Eq. 550
e ea x( )ea
ea x( ) ea x( )
a a,[ ]1
3-------
1
3-------,
1
3-------
1
3-------,
1
3-------
1
3-------,
1
3-------
1
3-------,, , ,
=
ea x( )1
4--- 1 3a+( ) 1 3a+( )
A CT
C 0
u
f1
f2
=
A D 1 ( ) de
=
C B de=
f1 A n( ) e CT
u eu=
f2 b d
e
n( ) de
C n( ) e+=
Ad d Fi i El M h dCh t 5
8/8/2019 Advanced Finite Element
20/172
Advanced Finite Element Methods
470 Workbook of Applications in VectorSpace C++ Library
Chapter 5
where B = L. Again, if discontinuous interpolation on were taken, all terms involving dropped out in Eq.511 and Eq. 512, which are then significantly simplified. To avoid singular conditions as discussed in Eq. 518
we should have the condition to avoid singularity that
Eq. 551
Two quadrilateral elements with four -nodes and eight u-nodes (Q 4/8)1 are used to compute the beam bendingproblem in the higher-order path test in the Chapter 4. The numbers of degree of freedom for the two fields are
n = 8 3 = 24, nu = 13 2-4 = 22, which satisfied the conceptual patch test criterion in Eq. 551. The implemen-tation ofEq. 58 to Eq. 512 is shown in Program Listing 54 (project hellinger_reissner_variational_principle
in project workspace file fe.dsw). They present no new difficulty from the Program Listing 51. The solution
of the tip-deflection is 0.75, which is exact.
1. p.331 in Zienkiewicz, O.C. and R.L. Taylor, 1989, The finite element method, 4th ed., vol. 1. McGraw-Hill, Inc., UK.
n nu
Mi d d H b id Fi it El t M th d
8/8/2019 Advanced Finite Element
21/172
Workbook of Applications in VectorSpace C++ Library 471
Mixed and Hybrid Finite Element Methods
1st element
coordinates of four corner nodes
physcial coordinates at ( )
physcial coordinates at ( )
physcial coordinates at ( )
physcial coordinates at ( )
2nd element
node # 8-20 are geometrical nodes
(serendipity)
1
3
-------1
3
-------,
1
3-------
1
3-------,
1
3-------
1
3-------,
1
3------- 1
3-------,
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
static const int row_node_no = 5; static const int row_segment_no = row_node_no-1;
static const double L_ = 10.0; static const double c_ = 1.0;
static const double h_e_ = L_/((double)row_segment_no);
static const double E_ = 1.e3; static const double v_ = 0.3;
Omega_h_i::Omega_h_i( int i) : Omega_h(0) {
if(i == 0) {
double inv_sqrt3 = 1.0/sqrt(3.0), v[2], xl[4][2], zai, eta; Node *node;
xl[0][0] = 0.0; xl[0][1] = 0.0; xl[1][0] = 2.0*h_e_; xl[1][1] = 0.0;
xl[2][0] = 2.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 0.0; xl[3][1] = 2.0*c_;
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] =(1.0-zai)*(1.0-eta)/4.0*xl[0][j]+(1.0+zai)*(1.0-eta)/4.0*xl[1][j]+(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(0, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(1, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(2, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ 1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(3, 2, v); node_array().add(node);
xl[0][0] = 2.0*h_e_; xl[0][1] = 0.0; xl[1][0] = 4.0*h_e_; xl[1][1] = 0.0;
xl[2][0] = 4.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 2.0*h_e_; xl[3][1] = 2.0*c_;
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(4, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(5, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(6, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++) v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(7, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 0.0; node = new Node(8, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(10, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(12, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 1.0*c_; node = new Node(13, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(14, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(15, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(16, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(17, 2, v); node_array().add(node);
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
22/172
Advanced Finite Element Methods
472 Workbook of Applications in VectorSpace C++ Library
Chapter 5
last four nodes are -nodes
B.C.disable all geometrical nodesu B.C.
fixed B.C. at right-end
Bending Moment on left-end
v[0] = 2.0*h_e_; node = new Node(18, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(19, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(20, 2, v); node_array().add(node);
int ena[12]; Omega_eh *elem;
ena[0] = 8; ena[1] = 10; ena[2] = 18; ena[3] = 16; ena[4] = 9; ena[5] = 14;
ena[6] = 17; ena[7] = 13; ena[8] = 0; ena[9] = 1; ena[10] = 2; ena[11] = 3;
elem = new Omega_eh(0, 0, 0, 12, ena); omega_eh_array().add(elem);
ena[0] = 10; ena[1] = 12; ena[2] = 20; ena[3] = 18; ena[4] = 11; ena[5] = 15;
ena[6] = 19; ena[7] = 14; ena[8] = 4; ena[9] = 5; ena[10] = 6; ena[11] = 7;
elem = new Omega_eh(1, 0, 0, 12, ena); omega_eh_array().add(elem);
} else if(i == 1) { // Omega_u
double v[2]; Node *node;
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(1, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(3, 2, v); node_array().add(node);v[0] = 4.0*h_e_; node = new Node(4, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 1.0*c_; node = new Node(5, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(6, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(7, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(8, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(10, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(12, 2, v); node_array().add(node);
int ena[8]; Omega_eh *elem;
ena[0] = 0; ena[1] = 2; ena[2] = 10; ena[3] = 8; ena[4] = 1; ena[5] = 6; ena[6] = 9; ena[7] = 5;
elem = new Omega_eh(0, 0, 0, 8, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 4; ena[2] = 12; ena[3] = 10; ena[4] = 3; ena[5] = 7; ena[6] = 11; ena[7] = 6;
elem = new Omega_eh(1, 0, 0, 8, ena); omega_eh_array().add(elem);
}
}
gh_on_Gamma_h_i::gh_on_Gamma_h_i(int i, int df, Omega_h& omega_h) : gh_on_Gamma_h() {
gh_on_Gamma_h::__initialization(df, omega_h);
if(i == 0) {
for(int j = 8; j
8/8/2019 Advanced Finite Element
23/172
Workbook of Applications in VectorSpace C++ Library 473
Mixed and Hybrid Finite Element Methods
Q 4/8 element definition
diagonal A-matrix definition
Serendipity shape functions for integra-
ion and coordinate transformation
Step 1: initial four corner nodes
Step 2: add four edge nodes
Step 3: correction of four corner nodes
the presence of four edge nodes
with four nodes at four Gaussintegration points
N0-7 =0 (corresponding to geom. nodes)
N8-11 = a
N
D-1
off-diagonal C-matrix definition
A D 1 ( ) de
=
class ElasticQ84_Mixed_Formulation : public Element_Formulation_Couple {
public:
ElasticQ84_Mixed_Formulation(Element_Type_Register a):Element_Formulation_Couple(a) {}
Element_Formulation *make(int, Global_Discretization&);
ElasticQ84_Mixed_Formulation(int, Global_Discretization&);
Element_Formulation_Couple *make(int, Global_Discretization_Couple&);
ElasticQ84_Mixed_Formulation(int, Global_Discretization_Couple&);
};
Element_Formulation* ElasticQ84_Mixed_Formulation::make(int en,Global_Discretization& gd){
return new ElasticQ84_Mixed_Formulation(en,gd); }
static const double a_ = E_ / (1-pow(v_,2));
static const double Dv[3][3] = { {a_, a_*v_, 0.0 }, {a_*v_, a_, 0.0 }, {0.0, 0.0, a_*(1-v_)/2.0} };
C0 D = MATRIX("int, int, const double*", 3, 3, Dv[0]);
ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(
int en, Global_Discretization& gd) : Element_Formulation_Couple(en, gd) {Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(int, int, Quadrature", 8, 2, qp),
Zai, Eta; Zai &= Z[0]; Eta &= Z[1];
N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;
N[0] = N[0] - (N[4]+N[7])/2.0; N[1] = N[1] - (N[4]+N[5])/2.0;
N[2] = N[2] - (N[5]+N[6])/2.0; N[3] = N[3] - (N[6]+N[7])/2.0;
C0 x = MATRIX("int, int, C0&, int, int", 8, 2, xl, 0, 0);
H1 X = N*x; J dv(d(X).det());
double sqrt3 = sqrt(3.0); C0 zero(0.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4/*nen*/, qp), n8, n9, n10, n11;
H0 zai, eta;
zai &= ((H0)Z[0]); eta &= ((H0)Z[1]);
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n8 &= n[0]; n9 &= n[1]; n10 &= n[2]; n11 &= n[3];
H0 N_sig = ( (n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero | zero ) &
(zero | n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero ) &(zero |(zero | n8) | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 ));
Matrix::Decomposition_Method = Matrix::Cholesky_Decomposition;
C0 D_inv = D.inverse();
Matrix::Decomposition_Method = Matrix::LU_Decomposition;
stiff &= MATRIX("int, int", 36, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 12, 12, stiff, 24, 24);
stiff_sub = -((~N_sig) * (D_inv * N_sig)) | dv;
}
Element_Formulation_Couple* ElasticQ84_Mixed_Formulation::make(
int en, Global_Discretization_Couple& gdc) {return new ElasticQ84_Mixed_Formulation(en,gdc);
}
ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(
int en, Global_Discretization_Couple& gdc) : Element_Formulation_Couple(en, gdc) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 8, 2, qp),
Zai, Eta;
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
24/172
Advanced Finite Element Methods
474 Workbook of Applications in VectorSpace C++ Library
Chapter 5
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;
N[0] = N[0] - (N[4]+N[7])/2.0; N[1] = N[1] - (N[4]+N[5])/2.0;
N[2] = N[2] - (N[5]+N[6])/2.0; N[3] = N[3] - (N[6]+N[7])/2.0;
H1 X = N*xl;
H0 Nx = d(N) * d(X).inverse();
J dv(d(X).det());
H0 w_x = INTEGRABLE_SUBMATRIX("int, int, H0&", 1, 2, Nx),
wx, wy, B;
wx &= w_x[0][0]; wy &= w_x[0][1];
C0 zero(0.0);
B &= (~wx || zero) &
(zero || ~wy ) &
(~wy || ~wx );
double sqrt3 = sqrt(3.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 12/*nen*/, qp),n8, n9, n10, n11, zai, eta;
zai &= (H0)Z[0]; eta &= (H0)Z[1];
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n8 &= n[0]; n9 &= n[1]; n10 &= n[2]; n11 &= n[3];
H0 N_sig = ((n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero | zero ) &
(zero | n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero ) &
(zero |(zero | n8) | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 ));
stiff &= MATRIX("int, int", 16, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 16, 12, stiff, 0, 24);
stiff_sub = ((~B)*N_sig) | dv;
}
Element_Formulation* Element_Formulation::type_list = 0;
static Element_Type_Register element_type_register_instance;
static ElasticQ84_Mixed_Formulation
elasticq84_mixed_formulation_instance(element_type_register_instance);
static Matrix_Representation mr(sigma_gd);
static Matrix_Representation_Couple mrc(gdc, 0, 0, &(mr.rhs()), &mr);
int main() {
mr.assembly();
mrc.assembly();C0 A = ((C0)(mr.lhs())), f_1 = ((C0)(mr.rhs())),
C = ((C0)(mrc.lhs())), f_2 = ((C0)(mrc.rhs()));
Cholesky dnH(-A);
C0 Ainv = -(dnH.inverse());
C0 CAinvCt = C*Ainv*(~C);
LU dCAinvCt(CAinvCt);
cout
8/8/2019 Advanced Finite Element
25/172
Workbook of Applications in VectorSpace C++ Library 475
Mixed and Hybrid Finite Element Methods
Hu-Washizu Variational Principle
In addition to Eq. 537 , the constitutive equations and the strain-displacement relations can be used such as
= D , and = Lu Eq. 552The variational approximation to these two equations are
Eq. 553
Eq. 553 and Eq. 537 are the Euler-Lagange equations of the Lagrangian functional
Eq. 554
The Lagrangian functional in Eq. 554 is known as the Hu-Washizu variational principle. The finite element
approximation to the strain field uses the interpolation functions (x) as
Eq. 555
The matrix form, at element level, ofEq. 537 and Eq. 553 is
Eq. 556
where
Eq. 557
Eq. 558
Eq. 559
Eq. 560
T D ( ) d 0= and T Lu ( ) d
0=,
, u,( ) 12--- TD d
T Lu( ) d
uTb d
uTh d
h
=
e ea x( )ea
A CT 0
C 0 ET
0 E 0
u
f1
f2
f3
=
A D( ) de
=
E B de=
C de
=
f1
A n
( )
eCT n
( )
e=
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
26/172
476 Workbook of Applications in VectorSpace C++ Library
p
Eq. 561
Eq. 562
The condition for non-singular matrices is1
Eq. 563
The Program Listing 55 implements Eq. 556 to Eq. 562 (project hu_washizu_variational_principle inproject workspace file fe.dsw). With the same patch test problem for the Hellinger-Reissner variational princi-
ple in the previous section. We use shape functions with four nodes at Gaussian integration points for both stress
() and strain () fields; i.e., = . This results in C-matrix in Eq. 559 to be symmetrical negative definitive.Care should be taken, if Cholesky decomposition is used, which is applicable to a symmetricalpositive defini-
tive matrix. The displacement (u) shape function is an eight-nodes serendipity element. These choices satisfythe condition in Eq. 563. The coding of matrix substructuring technique supported by fe.lib becomes a little
more elaborated with three-fields (, , u) instead of two-fields (, u).The modification from two-fields problem is minor, however. For the definitions of discretized global
domain and boundary have three index entries as
1 Omega_h_i::Omega_h_i(int i) : Omega_h(0) { // hi2 if(i == 0 || i == 1) { // h or
h
3 ...
4 } else if(i == 2) { // hu
5 ...6 }
7 gh_on_Gamma_h_i::gh_on_Gamma_h_i(int i, int df, Omega_h& omega_h) : gh_on_Gamma_h() { //hi8 gh_on_Gamma_h::__initialization(df, omega_h);
9 if(i == 0) { // h10 ...
11 } else if(i == 1) { // h12 ...
13 } else if(i == 2) { // hu
14 ...
15 }
16 }
The instantiation of global discretized couples are
1. see discussion in p.333-334 in Zienkiewicz, O.C. and R.L. Taylor, 1989, The finite element method, 4th ed., vol. 1.McGraw-Hill, Inc., UK.
f2 C n( ) e ETu
eu
=
f3 b de n( ) d
e E n( ) e+=
n nu+ n and n nu,
Mixed and Hybrid Finite Element Methods
8/8/2019 Advanced Finite Element
27/172
Workbook of Applications in VectorSpace C++ Library 477
define , and
elem # 0 nodal coordinates
1st Gauss point natural coordinates
1st Gauss point physical coordinates
2nd Gauss point natural coordinates
2nd Gauss point physical coordinates
3rd Gauss point natural coordinates3rd Gauss point physical coordinates
4th Gauss point natural coordinates
4th Gauss point physical coordinates
elem # 1 nodal coordinates1st Gauss point natural coordinates
1st Gauss point physical coordinates
2nd Gauss point natural coordinates
2nd Gauss point physical coordinates
3rd Gauss point natural coordinates
3rd Gauss point physical coordinates
4th Gauss point natural coordinates
4th Gauss point physical coordinates
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch Matrix_Representation_Couple::
Assembly_Switch = Matrix_Representation_Couple::ALL;static const int row_node_no = 5; static const int row_segment_no = row_node_no-1;
static const double L_ = 10.0; static const double c_ = 1.0;
static const double h_e_ = L_/((double)row_segment_no);
static const double E_ = 1.e3; static const double v_ = 0.3;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) {
if(i == 0 || i == 1) {
double inv_sqrt3 = 1.0/sqrt(3.0), v[2], xl[4][2], zai, eta;
Node *node;
xl[0][0] = 0.0; xl[0][1] = 0.0; xl[1][0] = 2.0*h_e_; xl[1][1] = 0.0;
xl[2][0] = 2.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 0.0; xl[3][1] = 2.0*c_;
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(0, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+(1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+(1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(1, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = inv_sqrt3;for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(2, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(3, 2, v); node_array().add(node);
xl[0][0] = 2.0*h_e_; xl[0][1] = 0.0; xl[1][0] = 4.0*h_e_; xl[1][1] = 0.0;
xl[2][0] = 4.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 2.0*h_e_; xl[3][1] = 2.0*c_;zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(4, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(5, 2, v); node_array().add(node);zai = inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(6, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(7, 2, v); node_array().add(node);
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
28/172
478 Workbook of Applications in VectorSpace C++ Library
geometrical nodes supply four corner
nodes coordinates to the element level
define elements
first 8 nodes are geometrical nodeslast four nodes are real nodes
u8-node serendipity element
define nodes
define elements
B.C.disable all geometrical nodes
B.C.disable all geometrical nodes
Wu boundary condition
Simpsons integration rule:
{-15 *2/3, 0*4/3, 15*2./3}
= {-5, 0, 5}
v[0] = 0.0; v[1] = 0.0; node = new Node(8, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(10, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(12, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 1.0*c_; node = new Node(13, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(14, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(15, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(16, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(17, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(18, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(19, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(20, 2, v); node_array().add(node);
int ena[12]; Omega_eh *elem;
ena[0] = 8; ena[1] = 10; ena[2] = 18; ena[3] = 16; ena[4] = 9; ena[5] = 14;
ena[6] = 17; ena[7] = 13; ena[8] = 0; ena[9] = 1; ena[10] = 2; ena[11] = 3;elem = new Omega_eh(0, 0, 0, 12, ena); omega_eh_array().add(elem);
ena[0] = 10; ena[1] = 12; ena[2] = 20; ena[3] = 18; ena[4] = 11; ena[5] = 15;
ena[6] = 19; ena[7] = 14; ena[8] = 4; ena[9] = 5; ena[10] = 6; ena[11] = 7;
elem = new Omega_eh(1, 0, 0, 12, ena); omega_eh_array().add(elem);
} else if(i == 2) {
double v[2]; Node *node;
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(1, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(3, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(4, 2, v); node_array().add(node);v[0] = 0.0; v[1] = 1.0*c_; node = new Node(5, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(6, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(7, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(8, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(10, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(12, 2, v); node_array().add(node);
int ena[8]; Omega_eh *elem;
ena[0] = 0; ena[1] = 2; ena[2] = 10; ena[3] = 8; ena[4] = 1; ena[5] = 6; ena[6] = 9; ena[7] = 5;
elem = new Omega_eh(0, 0, 0, 8, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 4; ena[2] = 12; ena[3] = 10; ena[4] = 3; ena[5] = 7; ena[6] = 11; ena[7] = 6;
elem = new Omega_eh(1, 0, 0, 8, ena); omega_eh_array().add(elem);
}
}
gh_on_Gamma_h_i::gh_on_Gamma_h_i(int i, int df, Omega_h& omega_h) : gh_on_Gamma_h() {
gh_on_Gamma_h::__initialization(df, omega_h);
if(i == 0) {
for(int j = 8; j
8/8/2019 Advanced Finite Element
29/172
Workbook of Applications in VectorSpace C++ Library 479
g.d. for defining A matrixh = {x, y, }T
h = {x, y, }T
u , uh = {u, v}T
g.d. u for defining irreducible K matrix
g.d.couple {-} for defining C matrix
g.d.couple {u-} for defining E matrix
diagonals A & K matrices
off-diagonals C & E matrices
diagonals matrices
A matrix formulation
eight nodes serendipity shape function
h = {x, y, }T
K matrix; for iterative method to esti-
mate initial u values
A D( ) de
=
static const int epsilon_ndf = 3; static Omega_h_i oh_epsilon(0);
static gh_on_Gamma_h_i epsilon_gh(0, epsilon_ndf, oh_epsilon);
static U_h epsilon_h(epsilon_ndf, oh_epsilon);
static Global_Discretization *epsilon_type = new Global_Discretization;
static Global_Discretization epsilon_gd(oh_epsilon, epsilon_gh, epsilon_h, epsilon_type);
static const int sigma_ndf = 3; static Omega_h_i oh_sigma(1);static gh_on_Gamma_h_i sigma_gh(1, sigma_ndf, oh_sigma);
static U_h sigma_h(sigma_ndf, oh_sigma);
static Global_Discretization sigma_gd(oh_sigma, sigma_gh, sigma_h);
static const int u_ndf = 2; static Omega_h_i oh_u(2);
static gh_on_Gamma_h_i u_gh(2, u_ndf, oh_u); static U_h u_h(u_ndf, oh_u);
static Global_Discretization *u_type = new Global_Discretization;
static Global_Discretization u_gd(oh_u, u_gh, u_h, u_type);
static Global_Discretization_Couple *sigma_epsilon = new Global_Discretization_Couple();
static Global_Discretization_Couple gdc_sigma_epsilon(sigma_gd, epsilon_gd, sigma_epsilon);
static Global_Discretization_Couple *u_sigma = new Global_Discretization_Couple();
static Global_Discretization_Couple gdc_u_sigma(u_gd, sigma_gd, u_sigma);
class ElasticQ84_Mixed_Formulation : public Element_Formulation_Couple {
public:
ElasticQ84_Mixed_Formulation(Element_Type_Register a):Element_Formulation_Couple(a) {}
Element_Formulation *make(int, Global_Discretization&);
ElasticQ84_Mixed_Formulation(int, Global_Discretization&);
Element_Formulation_Couple *make(int, Global_Discretization_Couple&);
ElasticQ84_Mixed_Formulation(int, Global_Discretization_Couple&);
};
Element_Formulation* ElasticQ84_Mixed_Formulation::make(
int en,Global_Discretization& gd) { return new ElasticQ84_Mixed_Formulation(en,gd); }static const double a_ = E_ / (1-pow(v_,2));
static const double Dv[3][3] = { {a_, a_*v_, 0.0 }, {a_*v_, a_, 0.0}, {0.0, 0.0, a_*(1-v_)/2.0} };
C0 D = MATRIX("int, int, const double*", 3, 3, Dv[0]);
ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(
int en, Global_Discretization& gd) : Element_Formulation_Couple(en, gd) {
if(gd.type() == epsilon_type) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta,
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 8, 2, qp);
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;
N[0] = N[0] - (N[4]+N[7])/2.0; N[1] = N[1] - (N[4]+N[5])/2.0;
N[2] = N[2] - (N[5]+N[6])/2.0; N[3] = N[3] - (N[6]+N[7])/2.0;
C0 x = MATRIX("int, int, C0&, int, int", 8, 2, xl, 0, 0);
H1 X = N*x; J dv(d(X).det()); double sqrt3 = sqrt(3.0); C0 zero(0.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4, qp), n8, n9, n10, n11, zai, eta;
zai &= ((H0)Z[0]); eta &= ((H0)Z[1]);
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n8 &= n[0]; n9 &= n[1]; n10 &= n[2]; n11 &= n[3];
H0 N_epsilon = ((n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero | zero ) &
(zero | n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero ) &
(zero |(zero | n8) | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 ));
stiff &= MATRIX("int, int", 36, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 12, 12, stiff, 24, 24);
stiff_sub = ((~N_epsilon) * (D * N_epsilon)) | dv;
} else {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), , Zai, Eta
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE( "int, int, Quadrature", 8, 2, qp);
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
30/172
480 Workbook of Applications in VectorSpace C++ Library
K is a standard stiffness matrix
off-diagonal matrices
C matrux formulation
h
= {x, y, }T
E matrux formulation
C de
=
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;
N[0] -= (N[4]+N[7])/2.0; N[1] -= (N[4]+N[5])/2.0;N[2] -= (N[5]+N[6])/2.0; N[3] -= (N[6]+N[7])/2.0;
H1 X = N*xl; H0 Nx = d(N) * d(X).inverse(); J dv(d(X).det());
H0 w_x = INTEGRABLE_SUBMATRIX("int, int, H0&", 1, 2, Nx), wx, wy, B;
wx &= w_x[0][0]; wy &= w_x[0][1]; C0 zero(0.0);
B &= (~wx || zero) & (zero || ~wy ) & (~wy || ~wx );
stiff &= ((~B)*D*B)|dv;
}
}
Element_Formulation_Couple* ElasticQ84_Mixed_Formulation::make(int en,
Global_Discretization_Couple& gdc) { return new ElasticQ84_Mixed_Formulation(en,gdc); }ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(int en,
Global_Discretization_Couple& gdc) : Element_Formulation_Couple(en, gdc) {
if(gdc.type() == sigma_epsilon) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta,
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature",8,2, qp);
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;N[0] = N[0] - (N[4]+N[7])/2.0; N[1] = N[1] - (N[4]+N[5])/2.0;
N[2] = N[2] - (N[5]+N[6])/2.0; N[3] = N[3] - (N[6]+N[7])/2.0;
H1 X = N*xl; J dv(d(X).det());
double sqrt3 = sqrt(3.0); C0 zero(0.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4, qp), n8, n9, n10, n11, zai, eta;
zai &= ((H0)Z[0]); eta &= ((H0)Z[1]);
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n8 &= n[0]; n9 &= n[1]; n10 &= n[2]; n11 &= n[3];
H0 N_sig = ((n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero | zero ) &
(zero | n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero ) &
(zero |(zero | n8) | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 ));
H0 N_epsilon; N_epsilon &= N_sig;
stiff &= MATRIX("int, int", 36, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 12, 12, stiff, 24, 24);
stiff_sub = -((~N_sig)*N_epsilon) | dv;
} else {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta,
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE( "int, int, Quadrature",8,2, qp);
Zai &= Z[0]; Eta &= Z[1];N[0] = (1.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0;
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0;
N[4] = (1.0-Zai.pow(2))*(1.0-Eta)/2.0; N[5] = (1.0-Eta.pow(2))*(1.0+Zai)/2.0;
N[6] = (1.0-Zai.pow(2))*(1.0+Eta)/2.0; N[7] = (1.0-Eta.pow(2))*(1.0-Zai)/2.0;
N[0] = N[0] - (N[4]+N[7])/2.0; N[1] = N[1] - (N[4]+N[5])/2.0;
N[2] = N[2] - (N[5]+N[6])/2.0; N[3] = N[3] - (N[6]+N[7])/2.0;
H1 X = N*xl; H0 Nx = d(N) * d(X).inverse(); J dv(d(X).det());
H0 w_x = INTEGRABLE_SUBMATRIX("int, int, H0&", 1, 2, Nx), wx, wy, B;
wx &= w_x[0][0]; wy &= w_x[0][1]; C0 zero(0.0);
B &= (~wx || zero) &
(zero || ~wy ) &
(~wy || ~wx );
Mixed and Hybrid Finite Element Methods
8/8/2019 Advanced Finite Element
31/172
Workbook of Applications in VectorSpace C++ Library 481
double sqrt3 = sqrt(3.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4, qp), n8, n9, n10, n11, zai, eta;
zai &= ((H0)Z[0]); eta &= ((H0)Z[1]);
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n8 &= n[0]; n9 &= n[1]; n10 &= n[2]; n11 &= n[3];H0 N_sig = ((n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero | zero ) &
(zero | n8 | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 | zero ) &
(zero |(zero | n8) | zero | zero | n9 | zero | zero | n10 | zero | zero | n11 ));
stiff &= MATRIX("int, int", 16, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 16, 12, stiff, 0, 24);
stiff_sub = ((~B)*N_sig) | dv;
}
}
Element_Formulation* Element_Formulation::type_list = 0;
static Element_Type_Register element_type_register_instance;
static ElasticQ84_Mixed_Formulation
elasticq84_mixed_formulation_instance(element_type_register_instance);
static Matrix_Representation mr(epsilon_gd);
static Matrix_Representation_Couple mrcC(gdc_sigma_epsilon, 0, 0, &(mr.rhs()), &mr);
static Matrix_Representation_Couple mrcE(gdc_u_sigma, 0, 0, &(mrcC.rhs()), &mrcC);
int main() {
mrcC.assembly();
mr.assembly();
mrcE.assembly();
C0 A = ((C0)(mr.lhs())),
f_1 = ((C0)(mr.rhs())),C = ((C0)(mrcC.lhs())),
f_2 = ((C0)(mrcC.rhs())),
E = ((C0)(mrcE.lhs())),
f_3 = ((C0)(mrcE.rhs()));
Cholesky dnC(-C);
C0 Cinv = -(dnC.inverse()),
CinvA = Cinv*A,
CinvACinv = Cinv*A*Cinv,
ECinvACinv = E*CinvACinv,
ECinvACinvEt = ECinvACinv*(~E);
Cholesky dECinvACinvEt(ECinvACinvEt);
C0 u = dECinvACinvEt * (f_3 - (E*Cinv)*f_1 + ECinvACinv*f_2);
C0 epsilon = -(dnC*(f_2-(~E)*u));
C0 sigma = -(dnC*(f_1-A*epsilon));
epsilon_h = epsilon;
epsilon_h = epsilon_gd.gh_on_gamma_h();
cout
8/8/2019 Advanced Finite Element
32/172
482 Workbook of Applications in VectorSpace C++ Library
1 static const int epsilon_ndf = 3; // ndf 2 static Omega_h_i oh_epsilon(0); // h3 static gh_on_Gamma_h_i epsilon_gh(0, epsilon_ndf, oh_epsilon); // h4 static U_h epsilon_h(epsilon_ndf, oh_epsilon); // x, yxy5 static Global_Discretization *epsilon_type = new Global_Discretization;
6 static Global_Discretization epsilon_gd(oh_epsilon, epsilon_gh, epsilon_h, epsilon_type);
7 static const int sigma_ndf = 3; // ndf 8 static Omega_h_i oh_sigma(1); // h9 static gh_on_Gamma_h_i sigma_gh(1, sigma_ndf, oh_sigma); // h10 static U_h sigma_h(sigma_ndf, oh_sigma); // x, yxy11 static Global_Discretization sigma_gd(oh_sigma, sigma_gh, sigma_h);
12 static const int u_ndf = 2; // ndf u
13 static Omega_h_i oh_u(2); // hu14 static gh_on_Gamma_h_i u_gh(2, u_ndf, oh_u); // hu15 static U_h u_h(u_ndf, oh_u); // ux, uy16 static Global_Discretization *u_type = new Global_Discretization;
17 static Global_Discretization u_gd(oh_u, u_gh, u_h, u_type);
18 static Global_Discretization_Couple *sigma_epsilon = new Global_Discretization_Couple(); //19 static Global_Discretization_Couple gdc_sigma_epsilon(sigma_gd, epsilon_gd, sigma_epsilon);
20 static Global_Discretization_Couple *u_sigma = new Global_Discretization_Couple(); // u-
21 static Global_Discretization_Couple gdc_u_sigma(u_gd, sigma_gd, u_sigma);
Three pointers to Global_Discretization and Global_Discretization_Coupe, epsilon_type, u_type, and
sigma_epsilon, are to be used in Element_Formulation class definitions to switch to corresponding segments of
submatrices definitions.
1 class ElasticQ84_Mixed_Formulation : public Element_Formulation_Couple {
2 public:3 ElasticQ84_Mixed_Formulation(Element_Type_Register a) : Element_Formulation_Couple(a) {}
4 Element_Formulation *make(int, Global_Discretization&); // diagonal submatrices
5 ElasticQ84_Mixed_Formulation(int, Global_Discretization&);
6 Element_Formulation_Couple *make(int, Global_Discretization_Couple&);// off-diagonal submatrices
7 ElasticQ84_Mixed_Formulation(int, Global_Discretization_Couple&);
8 };
9 Element_Formulation* ElasticQ84_Mixed_Formulation::make(int en, Global_Discretization& gd) {
10 return new ElasticQ84_Mixed_Formulation(en,gd);11 }
12 ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(int en, Global_Discretization& gd) :
13 Element_Formulation_Couple(en, gd) {
14 if(gd.type() == epsilon_type) { // define A-Matrix; field15 ...
16 } else { //K-matrix; u-field, for iterative method to estimate initial u values, Z&T p. 361, Eq. 12.99
17 ...
18 }19 }
Mixed and Hybrid Finite Element Methods
8/8/2019 Advanced Finite Element
33/172
Workbook of Applications in VectorSpace C++ Library 483
20 Element_Formulation_Couple* ElasticQ84_Mixed_Formulation::make(
21 int en, Global_Discretization_Couple& gdc) { return new ElasticQ84_Mixed_Formulation(en,gdc); }
22 ElasticQ84_Mixed_Formulation::ElasticQ84_Mixed_Formulation(
23 int en, Global_Discretization_Couple& gdc) : Element_Formulation_Couple(en, gdc) {
24 if(gdc.type() == sigma_epsilon) { // define C-Matrix; fields25 ...
26 } else { // define E-matrix; u- fields27 ...
28 }
29 }
Line 16 is to construct the convergence acceleration matrix if iterative method is used.1 The global solution is
proceeded with to be solved first as
= (EC-1 AC-1 ET)-1 (f3 - EC-1 f1 + EC
-1 AC-1 f2) Eq. 564
After is obtained, we can substituting in the following equation
= C-1 (f2 - ET ) Eq. 565
Then, is solved by substituting in
= C-1 (f1 - A ) Eq. 566
The Matrix_Representations are in instantiated in the followings with the global substructuring solution
1 int main() {
2 Matrix_Representation mr(epsilon_gd);
3 Matrix_Representation_Couple mrcC(gdc_sigma_epsilon, 0, 0, &(mr.rhs()), &mr);
4 Matrix_Representation_Couple mrcE(gdc_u_sigma, 0, 0, &(mrcC.rhs()), &mrcC);
5 mrcC.assembly();
6 mr.assembly();
7 mrcE.assembly();
8 C0 A = ((C0)(mr.lhs())), f_1 = ((C0)(mr.rhs())),
9 C = ((C0)(mrcC.lhs())), f_2 = ((C0)(mrcC.rhs())),
10 E = ((C0)(mrcE.lhs())), f_3 = ((C0)(mrcE.rhs()));
11 Cholesky dnC(-C); // decomposition; C is symmetrical negative definite
12 C0 Cinv = -(dnC.inverse()); // = (EC-1AC-1ET)-1 (f3-EC-1f1+ EC
-1AC-1f2)
13 C0 CinvA = Cinv*A;
14 C0 CinvACinv = CinvA*Cinv;
1. see next section and p. 361 in Zienkiewicz, O.C. and R.L. Taylor, 1989, The finite element method, 4th ed., vol. 1.McGraw-Hill, Inc., UK.
u
u
u u
u
u
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
34/172
484 Workbook of Applications in VectorSpace C++ Library
15 C0 ECinvACinv = E*CinvACinv;
16 C0 ECinvACinvEt = ECinvACinv*(~E);
17 Cholesky dECinvACinvEt(ECinvACinvEt);
18 C0 u = dECinvACinvEt * (f_3 - (E*Cinv)*f_1 + ECinvACinv*f_2);
19 C0 epsilon = -(dnC*(f_2-(~E)*u)); // = C-1(f2-ET )
20 C0 sigma = -(dnC*(f_1-A*epsilon)); // = C-1(f1-A )
21 epsilon_h = epsilon; // update free degree of freedom
22 epsilon_h = epsilon_gd.gh_on_gamma_h(); // update fixed degree of freedom
23 cout
8/8/2019 Advanced Finite Element
35/172
Advanced Finite Element MethodsChapter 5
8/8/2019 Advanced Finite Element
36/172
486 Workbook of Applications in VectorSpace C++ Library
, and Eq. 576
Substituting into Eq. 575 and Eq. 572 gives in matrix form at element level is
Eq. 577
where
Eq. 578
Eq. 579
Eq. 580
Eq. 581
Eq. 582
The solution to substructuring ofEq. 577 is proceeded from its second equation, using symmetrical negative
definitiveness ofV,
Eq. 583
Substituting into the first equation ofEq. 577 gives
Eq. 584
That is,
Eq. 585
Therefore, we first solve , and then substituting back to Eq. 583 for recovering . Program Listing 56
(project incompressible_u_p_formulation in project workspace file fe.dsw) implements the Q 4/9 element
(with an additional center u-node) and test problem in the higher-order patch test.
u Nuu= p Npp=
A CT
C V
u
p
f1
f2
=
A BT D02
3---m m Bd
e
=
C mNp( )TBd
e
=
VNp Np
K---------------------d
e
=
f1 NuTb d
e
NuTt de
Au e CTp e
+=
f2 Cu eVp e
=
p V 1 f2 Cu( )=
Au CTV 1 f2 Cu( )+ f1=
u A CTV 1 C[ ] 1 f1 CTV 1 f2[ ]=
u u p
Mixed and Hybrid Finite Element Methods
8/8/2019 Advanced Finite Element
37/172
Workbook of Applications in VectorSpace C++ Library 487
plane stress modification
define u1st row
2nd row
3rd row
Lagrangian 9-nodes element
define pelem # 0 nodal coordinates
1st Gauss point natural coordinates
1st Gauss point physical coordinates
2nd Gauss point natural coordinates
2nd Gauss point physical coordinates
3rd Gauss point natural coordinates
3rd Gauss point physical coordinates
4th Gauss point natural coordinates
4th Gauss point physical coordinates
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
static const int row_node_no = 5; static const int row_segment_no = row_node_no-1;
static const double L_ = 10.0; static const double c_ = 1.0;
static const double h_e_ = L_/((double)row_segment_no); // half element size
static const double E_ = 1.e3; static const double v_ = 0.3;
static const double lambda_ = v_*E_/((1+v_)*(1-2*v_));
static const double mu_ = E_/(2*(1+v_));
static const double lambda_bar = 2*lambda_*mu_/(lambda_+2*mu_);
static const double K_ = lambda_bar+2.0/3.0*mu_;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) {
if(i == 0) { double v[2]; Node *node;
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(1, 2, v); node_array().add(node);v[0] = 2.0*h_e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(3, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(4, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 1.0*c_; node = new Node(5, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(6, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(7, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(8, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(10, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(12, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(13, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(14, 2, v); node_array().add(node);
int ena[9]; Omega_eh *elem;
ena[0] = 0; ena[1] = 2; ena[2] = 12; ena[3] = 10; ena[4] = 1;
ena[5] = 7; ena[6] = 11; ena[7] = 5; ena[8] = 6;
elem = new Omega_eh(0, 0, 0, 9, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 4; ena[2] = 14; ena[3] = 12; ena[4] = 3;
ena[5] = 9; ena[6] = 13; ena[7] = 7; ena[8] = 8;
elem = new Omega_eh(1, 0, 0, 9, ena); omega_eh_array().add(elem);
} else if(i == 1) { double inv_sqrt3 = 1.0/sqrt(3.0), v[2], xl[4][2], zai, eta; Node *node;xl[0][0] = 0.0; xl[0][1] = 0.0; xl[1][0] = 2.0*h_e_; xl[1][1] = 0.0;
xl[2][0] = 2.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 0.0; xl[3][1] = 2.0*c_;
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(0, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(1, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(2, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];node = new Node(3, 2, v); node_array().add(node);
Advanced Finite Element MethodsChapter 5
elem # 1 nodal coordinatesxl[0][0] = 2 0*h e ; xl[0][1] = 0 0; xl[1][0] = 4 0*h e ; xl[1][1] = 0 0;
8/8/2019 Advanced Finite Element
38/172
488 Workbook of Applications in VectorSpace C++ Library
elem # 1 nodal coordinates
1st Gauss point natural coordinates
1st Gauss point physical coordinates
2nd Gauss point natural coordinates
2nd Gauss point physical coordinates
3rd Gauss point natural coordinates
3rd Gauss point physical coordinates
4th Gauss point natural coordinates
4th Gauss point physical coordinates
geometrical nodes
last four nodes are real pressure-field
nodes
Dirichlet B.C.
Nuemann B.C.
disable all geometrical nodes
xl[0][0] = 2.0 h_e_; xl[0][1] = 0.0; xl[1][0] = 4.0 h_e_; xl[1][1] = 0.0;
xl[2][0] = 4.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 2.0*h_e_; xl[3][1] = 2.0*c_;
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];node = new Node(4, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(5, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(6, 2, v); node_array().add(node);
zai = - inv_sqrt3; eta = inv_sqrt3;
for(int j = 0; j < 2; j++)
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+
(1.0+zai)*(1.0+eta)/4.0*xl[2][j]+ (1.0-zai)*(1.0+eta)/4.0*xl[3][j];
node = new Node(7, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 0.0; node = new Node(8, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(9, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(10, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(12, 2, v); node_array().add(node);v[0] = 0.0; v[1] = 1.0*c_; node = new Node(13, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(14, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(15, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(16, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(17, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(18, 2, v); node_array().add(node);
v[0] = 1.0*h_e_; node = new Node(19, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(20, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(21, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(22, 2, v); node_array().add(node);
int ena[13]; Omega_eh *elem;
ena[0] = 8; ena[1] = 10; ena[2] = 20; ena[3] = 18; ena[4] = 9; ena[5] = 15;
ena[6] = 19; ena[7] = 13; ena[8] = 14; ena[9] = 0; ena[10] = 1; ena[11] = 2; ena[12] = 3;
elem = new Omega_eh(0, 0, 0, 13, ena); omega_eh_array().add(elem);
ena[0] = 10; ena[1] = 12; ena[2] = 22; ena[3] = 20; ena[4] = 11; ena[5] = 17;
ena[6] = 21; ena[7] = 15; ena[8] = 16; ena[9] = 4; ena[10] = 5; ena[11] = 6; ena[12] = 7;
elem = new Omega_eh(1, 0, 0, 13, ena); omega_eh_array().add(elem);
}
}
gh_on_Gamma_h_i::gh_on_Gamma_h_i(int i, int df, Omega_h& omega_h) : gh_on_Gamma_h() {
gh_on_Gamma_h::__initialization(df, omega_h);if(i == 0) {
the_gh_array[node_order(4)](0) = the_gh_array[node_order(9)](0) =
the_gh_array[node_order(14)](0)=the_gh_array[node_order(9)](1)=
gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(10)][0] = -5.0; the_gh_array[node_order(0)][0] = 5.0;
} else if(i == 1) {
for(int j = 8; j
8/8/2019 Advanced Finite Element
39/172
Workbook of Applications in VectorSpace C++ Library 489
u
u = [u, v]T
p
{p-u} global discretization couple
diagonal submatrices
Lagragian 9-node element
A BT D02
3---m m Bd
e
=
VNp Np
K---------------------d
e
=
static gh_on_Gamma_h_i u_gh(0, u_ndf, oh_u); static U_h u_h(u_ndf, oh_u);
static const int p_ndf = 1; static Omega_h_i oh_p(1);
static gh_on_Gamma_h_i p_gh(1, p_ndf, oh_p); static U_h p_h(p_ndf, oh_p);
static Global_Discretization *u_type = new Global_Discretization;
static Global_Discretization u_gd(oh_u, u_gh, u_h, u_type);static Global_Discretization *p_type = new Global_Discretization;
static Global_Discretization p_gd(oh_p, p_gh, p_h, p_type);
static Global_Discretization_Couple *p_u_type = new Global_Discretization_Couple;
static Global_Discretization_Couple gdc(p_gd, u_gd, p_u_type);
class Incompressible_ElasticQ94_Mixed_Formulation : public Element_Formulation_Couple {
public:
Incompressible_ElasticQ94_Mixed_Formulation(Element_Type_Register a) :
Element_Formulation_Couple(a) {}
Element_Formulation *make(int, Global_Discretization&);
Incompressible_ElasticQ94_Mixed_Formulation(int, Global_Discretization&);
Element_Formulation_Couple *make(int, Global_Discretization_Couple&);
Incompressible_ElasticQ94_Mixed_Formulation(int, Global_Discretization_Couple&);
};
Element_Formulation*
Incompressible_ElasticQ94_Mixed_Formulation::make(int en, Global_Discretization& gd) {
return new Incompressible_ElasticQ94_Mixed_Formulation(en,gd);
}
Incompressible_ElasticQ94_Mixed_Formulation::Incompressible_ElasticQ94_Mixed_Formulation
(int en, Global_Discretization& gd) : Element_Formulation_Couple(en, gd) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta,N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE( "int, int, Quadrature", 9, 2, qp);
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (1+Zai)*(1-Eta)/4;
N[2] = (1+Zai)*(1+Eta)/4; N[3] = (1-Zai)*(1+Eta)/4;
N[8] = (1-Zai.pow(2))*(1-Eta.pow(2));
N[0] -= N[8]/4; N[1] -= N[8]/4; N[2] -= N[8]/4; N[3] -= N[8]/4;
N[4] = ((1-Zai.pow(2))*(1-Eta)-N[8])/2; N[5] = ((1-Eta.pow(2))*(1+Zai)-N[8])/2;
N[6] = ((1-Zai.pow(2))*(1+Eta)-N[8])/2; N[7] = ((1-Eta.pow(2))*(1-Zai)-N[8])/2;
N[0] -= (N[4]+N[7])/2; N[1] -= (N[4]+N[5])/2; N[2] -= (N[5]+N[6])/2; N[3] -= (N[6]+N[7])/2;
C0 x = MATRIX("int, int, C0&, int, int", 9, 2, xl, 0, 0);
H1 X = N*x; J dv(d(X).det());
if(gd.type() == u_type) {
H0 Nx = d(N) * d(X).inverse();
double d_0[3][3] = { {2.0, 0.0, 0.0}, {0.0, 2.0, 0.0}, {0.0, 0.0, 1.0}};
C0 D_0 = MATRIX("int, int, const double*", 3, 3, d_0[0]);
double m_0[3] = {1.0, 1.0, 0.0}; C0 m = VECTOR("int, const double*", 3, m_0);
H0 W_x = INTEGRABLE_SUBMATRIX("int, int, H0&", 1, nsd, Nx), Wx, Wy, B;
Wx &= W_x[0][0]; Wy &= W_x[0][1];
B &= (~Wx || C0(0.0) ) &
(C0(0.0) || ~Wy ) &
(~Wy || ~Wx );stiff &= ((~B) * (mu_*(D_0-2.0/3.0*(m%m)) * B)) | dv;
} else if(gd.type() == p_type) {
double sqrt3 = sqrt(3.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4/*nen*/, qp), zai, eta;
zai &= ((H0)Z[0]); eta &= ((H0)Z[1]);
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0;
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
stiff &= MATRIX("int, int", 13, 13);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 4, 4, stiff, 9, 9);
stiff_sub = -((n * (~n)) | dv)/K_;
}}
Advanced Finite Element MethodsChapter 5
Element_Formulation_Couple* Incompressible_ElasticQ94_Mixed_Formulation::make(
8/8/2019 Advanced Finite Element
40/172
490 Workbook of Applications in VectorSpace C++ Library
int en, Global_Discretization_Couple& gdc) {
return new Incompressible_ElasticQ94_Mixed_Formulation(en,gdc);
}
Incompressible_ElasticQ94_Mixed_Formulation::Incompressible_ElasticQ94_Mixed_Formulation
(int en, Global_Discretization_Couple& gdc) : Element_Formulation_Couple(en, gdc) {Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta,
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 9, 2, qp);
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (