Beruflich Dokumente
Kultur Dokumente
Mixed Formulation
Eq. 4•96 to Eq. 4•98 from Chapter 4 is re-written for convenience as
q = – κ ∇T Eq. 5•2
Eq. 5•1 states that the divergence of the heat flux, “q”, is equal to the internal heat source, f. Eq. 5•2 is the Fourier
law of heat conduction which assumed that the heat flux is linearly related to the negative gradient of the temper-
Integrating by parts and applying divergence theorem on the first term yields
∫ wq ( κ –1 q + ∇T ) dΩ = 0 Eq. 5•6
Ω
Finite element approximation of (1) temperature field, “T”, and (2) heat flux, “q”, are defined as
a
where Tˆ and q̂ a are nodal variables (bases), and “a” is nodal index for temperature and heat flux nodes. φTa
and φ qa are two shape functions which can be different from each other. Substituting Eq. 5•7 into Eq. 5•5 and Eq.
5•6 we have the mixed finite element formulation for the heat conduction problem as1
T f
AC q̂
= 1 Eq. 5•8
C 0 Tˆ f2
where
T
f 1 = – Aĥ Γ eh
– C ĝ Γ eg
Eq. 5•11
1. p.319-324 in Zienkiewicz, O.C. and R.L. Taylor, 1991, “The finite element method”, 4th ed., vol. 1. McGraw-Hill, Inc.,
UK.
f2 = – ∫ φT f dΩ + ∫ φT h dΓ – Cĥ e
Γh
Eq. 5•12
Ωe e
Γh
where h and g with “over-bar” are fixed nodal flux boundary conditions and fixed nodal temperature boundary
conditions, respectively, while “h” in Eq. 5•12 can be specified as a function on an element boundary. The fixed
nodal boundary conditions, h and g , in Eq. 5•11 and Eq. 5•12 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 displacement boundary conditions as reaction, and substrates out of the nodal force term
as “ f -= K u ”.
By inspecting on Eq. 5•9 and Eq. 5•10, 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. 5•10 over the entire problem
domain is integrable. Otherwise, the integration goes to infinity at the discontinuities. Two triangular elements
are considered in the following computations. Figure 5•1a&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. 5•9 and Eq. 5•10, can be discontinuous at the element boundaries. Therefore, the
constant heat flux element has one node at the center of the element (Figure 5•1a), and the linear heat flux ele-
ment has three nodes at the Gaussian integration points (Figure 5•1b). 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. 5•8.
T = 30oC
q=0 q=0
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.
The area coordinates for triangle, L0, L1, and L2, 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
#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_t_node_no = 4; static const double h_e = 1.0;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) {
if(i == 0) {
double xl[3][2], v[2]; Node *node;
Ωq
for(int j = 0; j < row_t_node_no-1; j++) make center q-nodes
for(int k = 0; k < row_t_node_no-1; k++) {
int node_no = (j*(row_t_node_no-1) + k) *2;
xl[0][0] = (double)k; xl[0][1] = (double)j;
corner coordinates
xl[1][0] = (double)(k+1); xl[1][1] = (double)j;
xl[2][0] = (double)(k+1); xl[2][1] = (double)(j+1); geometrical center coordinates
for(int l = 0; l < 2; l++) v[l] = (xl[0][l] + xl[1][l] + xl[2][l])/3.0;
node = new Node(node_no, 2, v); node_array().add(node);
xl[0][0] = (double)k; xl[0][1] = (double)j;
xl[1][0] = (double)(k+1); xl[1][1] = (double)(j+1);
xl[2][0] = (double)k; xl[2][1] = (double)(j+1);
or(int l = 0; l < 2; l++) v[l] = (xl[0][l] + xl[1][l] + xl[2][l])/3.0;
node = new Node(node_no+1, 2, v); node_array().add(node);
}
for(int j = 0; j < row_t_node_no; j++)
for(int k = 0; k < row_t_node_no; k++) {
corner geometrical nodes
int nn = j*row_t_node_no+k+(row_t_node_no-1)*2*(row_t_node_no-1);
v[0] = ((double)k)*h_e; v[1] = ((double)j)*h_e;
node = new Node(nn, 2, v); node_array().add(node);
}
for(int j = 0; j < row_t_node_no-1; j++) make heat flux elements, Ωqe
for(int k = 0; k < row_t_node_no-1; k++) {
int element_no = ((row_t_node_no-1)*j + k)*2,
center_node_no = element_no,
first_corner_node_no = j*row_t_node_no+k +(row_t_node_no-1)*2*(row_t_node_no-1);
int ena[4];
ena[0] = first_corner_node_no+1+row_t_node_no; ena[1] = first_corner_node_no;
ena[2] = first_corner_node_no+1; ena[3] = center_node_no;
Omega_eh* elem = new Omega_eh(element_no, 0, 0, 4, ena);
omega_eh_array().add(elem);
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; ena[3] = center_node_no+1;
elem = new Omega_eh(element_no+1, 0, 0, 4, ena); omega_eh_array().add(elem); ΩΤ
}
} else if(i == 1) {
double v[2]; make T-corner nodes
for(int j = 0; j < row_t_node_no; j++)
for(int k = 0; k < row_t_node_no; k++) {
int nn = j*row_t_node_no+k; v[0] = ((double)k)*h_e; v[1] = ((double)j)*h_e;
Node* node = new Node(nn, 2, v); node_array().add(node);
} make temperature elements, ΩTe
for(int j = 0; j < row_t_node_no-1; j++)
for(int k = 0; k < row_t_node_no-1; k++) {
int element_no = ((row_t_node_no-1)*j + k)*2,
first_corner_node_no = j*row_t_node_no+k, ena[3];
ena[0] = first_corner_node_no+1+row_t_node_no;
ena[1] = first_corner_node_no; ena[2] = first_corner_node_no+1;
Omega_eh* elem = new Omega_eh(element_no, 0, 0, 3, ena);
omega_eh_array().add(elem);
∫ φ q ⊗ ( κ – 1 φ q ) dΩ
H0 N_q = ((~N) || C0(0.0)) &
(C0(0.0)|| (~N)); A =
stiff &= ((~N_q) * (K_inv * N_q)) | dv; Ωe
}
Element_Formulation_Couple* Heat_Mixed_Formulation::make(
int en, Global_Discretization_Couple& gdc) { C-submatrix element formulation
return new Heat_Mixed_Formulation(en,gdc);
}
Heat_Mixed_Formulation::Heat_Mixed_Formulation(int en, Global_Discretization_Couple& gdc)
: Element_Formulation_Couple(en, gdc) {
Quadrature qp(2, 4);
H1 L(2, (double*)0, qp),
n ≡ φ T linear triangular shape function
n = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3/*nen*/, 2/*nsd*/, qp), for both coordinate transformation and
L0 = L[0], L1 = L[1], L2 = 1.0 - L0 - L1; n[0] = L0; n[1] = L1; n[2] = L2; temperature field shape function
H1 X = n*xl;
H0 nx = d(n) * d(X).inverse();
J dv(d(X).det()/2.0); N ≡ φ q= 1.0 (constant over element)
H0 N = INTEGRABLE_VECTOR("int, Quadrature", 4/*nen*/, qp); for heat flux field shape function
N[0] = N[1] = N[2] = 0.0; N[3] = 1.0;
H0 N_q = ((~N) || C0(0.0)) &
(C0(0.0)|| (~N)); C = ∫ ∇φT ⊗ φq dΩ
stiff &= (nx * N_q) | dv; Ωe
}
Element_Formulation* Element_Formulation::type_list = 0;
static Element_Type_Register element_type_register_instance;
static Heat_Mixed_Formulation
heat_mixed_formulation_instance(element_type_register_instance);
Listing 5•1 Substructure method for the mixed formulation of the heat conduction problem with constant
heat flux (project: “mixed_heat_conduction” in project workspace file “fe.dsw”).
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. 5•8 is the subject of con-
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 method and null space method (see page 149) to solve Eq.
5•8 in the followings.
From first equation of Eq. 5•8 we have
A q̂ + CT Tˆ = f1 Eq. 5•13
Considering A is symmetrical positive definitive, therefore it can be inverted, we can solve for q by
Substituting Eq. 5•14 into second equation of Eq. 5•8, C q̂ = f2, we have
Therefore, “ Tˆ ” can also be solved considering that the similarity transformation of A-1 as “C A-1 CT” preserves
the symmetrical positive definitiveness of A-1. An alternative view is that “C A-1 CT” is the projection of inverse
After we obtain the nodal temperature solution “ Tˆ ”, the nodal heat flux solution “ q̂ ” can be solved from Eq.
5•13 as
Eq. 5•16 and Eq. 5•17 is the formula for the range space method. We notice that the size of A-square submatrix
is the number of q̂ -free-variables, denotes as “n q”. The row-size of the C-submatrix is number of Tˆ -free-vari-
ables, denotes as “nT” (C-submatrix has size of nT × nq). Assuming full-row-rank condition for both A and C sub-
matrices. The rank of A-1 is “nq” and the column rank of CT is “nT”. In order to have “C A-1 CT” non-singular for
the inversion of “C A-1 CT” to be possible, we must have
nq ≥ nT Eq. 5•18
Based on the above simplistic linear algebraic discussion, Eq. 5•18 can be used to conceptually performing
“patch test” in the design of “q-T” two-field mixed finite element.1 However, a mathematically more rigorous
theorem on the existence and uniqueness of the constraint optimization problem (in the abstract form of the sad-
dle-point problem) is known as LBB-condition (coined by Ladyzhenskaya-Babuska-Brezzi and is also known as
inf-sup condition).2 The implementation of the range space method is
1 int main() {
2 Matrix_Representation mr(q_gd);
3 Matrix_Representation_Couple mrc(gdc, 0, 0, &(mr.rhs()), &mr);
4 mrc.assembly();
5 mr.assembly();
6 C0 A = ((C0)(mr.lhs())), f_1 = ((C0)(mr.rhs())),
7 C = ((C0)(mrc.lhs())), f_2 = ((C0)(mrc.rhs()));
8 Cholesky dA(A); // Cholesky decomposition on Hessian A
9 C0 Ainv = dA.inverse(),
10 CAinvCt = C*Ainv*(~C);
11 Cholesky dCAinvCt(CAinvCt); // Cholesky decomposition on C A-1 CT
12 C0 T = dCAinvCt*((C*Ainv*f_1)-f_2),
13 q = dA*(f_1-(~C)*T);
14 q_h = q; // update free degree of freedom
15 q_h = q_gd.gh_on_gamma_h(); // update fixed degree of freedom
16 cout << "heat flow:" << endl;
1. p.324-327 in Zienkiewicz, O.C. and R.L. Taylor, 1989, “The finite element method”, 4th ed., vol. 1. McGraw-Hill, Inc.,
UK.
2. see Brezzi, F, and M. Fortin, 1991, “Mixed and hybrid finite element method”, Spring-Berlag New York, Inc.
respectively, with
f 2e = – ∫ φ T f dΩ Eq. 5•20
Ωe
and,
∫ φT h dΓ – C e ĥ
Γ he
= 0 Eq. 5•21
Γ he
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
f1 = - C ĝ Γg
Eq. 5•22
Substituting the element level vector of Eq. 5•22 into the second equation in Eq. 5•19, we have
T T
fe = - Ce Ae-1 C e ĝ e Γ ge
- f2e= - Ce Ae-1 C e ĝ e Γ ge
- f2e
= -ke ĝ e Γ ge
- f2e Eq. 5•23
The first term in the right-hand-side is consistent with standard implementation of finite element on the essential
boundary conditions. The mixed form of Eq. 5•19 can be easily implemented which does not require the mecha-
nism provided in the “fe.lib” to express matrix substructuring. Program Listing 5•2 implements Eq. 5•19 (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.
#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;
C = ∫ ∇φT ⊗ φq dΩ
H0 N_q = ((~N) || C0(0.0)) & Ωe
(C0(0.0)|| (~N));
C0 C = (nx * N_q) | dv,
A = ((~N_q) * (K_inv * N_q)) | dv,
A = ∫ φq ⊗ ( κ –1 φq ) dΩ
Ωe
A_inv = A.inverse();
stiff &= C*A_inv*(~C); k = (CA-1CT)
}
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 << uh << endl;
return 0;
}
Listing 5•2 Mixed formulation with discontinuous temperature field (C0 continuity dropped) reduces to
temperature field only formulation (project: “mixed_t_field_heat_conduction”).
where
∂N a
----------
b xa ∂x
Ba ≡ ≡ Eq. 5•25
b ya ∂N a
----------
∂y
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 law
of 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. 5•24, 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 by bx = {bxa, bya} in Eq.
5•25, which are bases in 4. The two spurious zero energy modes in the null space are constant solution mode
with nodal solution of sa = [1, 1, 1, 1] and hourglass mode with nodal solution of ha = [-1, 1, -1, 1]. The hour-
glass mode is illustrated in Figure 5•2. The two zero energy modes are orthogonal to bx
where we also denote x0 = x, and x1 = y. We notice that for isoparametric coordinate transformation xi = Na xia ,
we have the relation
1
T
0.5
0
-0.5 η
-1
1
0.5
.5
-0.5
-1
ξ
-1
-0.5
0
0.5
1
The constant nodal solution sa is considered “proper”, since a constant temperature field produces no heat flux is
as expected, while the hourglass mode ha has gradient far from zero (see Figure 5•2) 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 that
is very economical to compute as
The first term on the right hand side, ke(1-point) is standard stiffness matrix computed with only one Gaussian
integration point. The second term ke(hourglass) is to be constructed with the trial hourglass mode Ψa. The general
form of the trial hourglass mode, Ψa , in 4 is span by the four bases [bxa, bya, sa, ha] as
From last part of Eq. 5•31, no component of Ψa is in sa, so in Eq. 5•29 a2 = 0, and we have this equation re-writ-
ten as
Substituting Eq. 5•32 into Ψa xa = 0 in the first part of Eq. 5•31, and using bxa xa = 1, and bya xa = 0 as indicated
in Eq. 5•27, we have
a0 = - h a x a Eq. 5•33
Similarly, substituting Eq. 5•32 into Ψa ya = 0 in the second part of Eq. 5•31, and using bya ya = 1, and bxa ya = 0
as in Eq. 5•27, we have
a1 = - h a y a Eq. 5•34
where Ψa is Ψa normalized to ||Ψa|| = 2, b = [bx, by]T, and J ≡ det ( ∂x ⁄ ∂ ξ ) . Program Listing 5•3 implements the
hourglass element for heat conduction (project “hourglass_heat” in project ˜ workspace file”fe.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 dynami c
finite element analysis”, Prentice-Hall, Inc., Englewood Cliffs, New Jersey, and references therein.
#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; bottom B.C. = 0oC
the_gh_array[node_order(row_node_no*(row_node_no-1)+i)](0) = top B.C. = 30oC
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); 1-point Gaussian integration for 2-D
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;
ke(1-point) from irreducible formulation
C0 h(4, (double*)0); h[3] = 1.0; Ψa = ha - (ha xa) bxa - (ha ya) bya
C0 phi = h - Nx.quadrature_point_value(0)*((~xl)*h); Ψa is Ψa normalized to ||Ψa|| =2
double factor = 2.0/norm(phi); phi *= factor;
H0 b = Nx(0) & Nx(1);
b = [bx, by]T
double j = (double)(d(X).det().quadrature_point_value(0)); J ≡ det ( ∂x ⁄ ∂ ξ )
C0 K_hourglass = (k_*j*((~b)*b) | dv) /12.0 * (phi%phi); kJ ( b • b )
k e ( hourglass ) ≡ ----------------------- ( Ψ ⊗ Ψ )
stiff &= K_standard + K_hourglass; 12
}
Element_Formulation* Element_Formulation::type_list = 0; ke = ke(1-point) + ke(hourglass)
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 << uh << endl;
return 0;
}
Listing 5•3 One point Gauss integration stiffness matrix with hourglass stabilizer element (project:
“hourglass_heat” in project workspace file “fe.dsw”).
∫ ( Lδu ) σ dΩ – ∫ δu b dΩ – ∫ δuT h dΓ
T
δ (u) = T
Eq. 5•37
Ω Ω Γh
where the body force is denoted as b, the strain is defined as ε = Lu , and the differential operator L in matrix
form as
∂
------ 0
∂x
L ≡ 0 ----- ∂ Eq. 5•38
-
∂y
∂ ∂
------ ------
∂y ∂x
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 constitutive
equations and strain-displacement relations, separately. The interpolation functions Φ(x) in finite element
approximation of displacement field is taken as
where Φ ea ( x ) is interpolation functions, and û ea is nodal displacements. The subscript “e” denotes the element
level.
σ = D ε = D Lu Eq. 5•40
We also add stress field, σ, as additional variable in the Lagrangian functional such that
∫ δ σ T ( Lu – D –1 σ ) dΩ = 0 Eq. 5•41
Ω
Eq. 5•37 and Eq. 5•41 are the Euler-Lagrange equations corresponding to the Lagrangian functional.
( σ, u ) = --- ∫ σ T D –1 σ dΩ + ∫ u T ( L T σ + b ) dΩ – ∫ u T ( n σ – h ) dΓ
1
Eq. 5•42
2
Ω Ω Γh
σe ≡ Ψea ( x ) σ̂e
a
Eq. 5•43
By inspecting Eq. 5•37 and Eq. 5•41, 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 Ψea ( x ), in contrast to Φ ea ( x ) in Eq. 5•39, 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
1 1 1 1 1 1 1 1
[ ξ a, η a ] = – -------, – ------- , -------, – ------- , -------, ------- , – -------, ------- Eq. 5•44
3 3 3 3 3 3 3 3
1
Ψ ea ( x ) ≡ --- ( 1 + 3ξ a ξ ) ( 1 + 3η a η ) Eq. 5•45
4
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 of
Eq. 5•37 and Eq. 5•41, at element level, is
AC
T
σ̂ =
f1
Eq. 5•46
C 0 û f2
where
A = – ∫ Ψ ⊗ ( D Ψ ) dΩ
–1
Eq. 5•47
Ωe
C = ∫ B ⊗ Ψ dΩ Eq. 5•48
Ωe
f1 = – A ( n σ )
T
Γ eσ
–C u Γ eu
Eq. 5•49
f2 = ∫Φ b dΩ + ∫Φ ( n σ ) dΓ – C ( n σ ) Eq. 5•50
Γ eσ
Ωe Γ eσ
nσ ≥ nu Eq. 5•51
Two quadrilateral elements with four σ-nodes and eight u-nodes (Q 4/8)1 are used to compute the beam bending
problem 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. 5•51. The implemen-
tation of Eq. 5•8 to Eq. 5•12 is shown in Program Listing 5•4 (project “hellinger_reissner_variational_principle”
in project workspace file “fe.dsw”). They present no new difficulty from the Program Listing 5•1. 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.
#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; 1st element
xl[2][0] = 2.0*h_e_; xl[2][1] = 2.0*c_; xl[3][0] = 0.0; xl[3][1] = 2.0*c_; coordinates of four corner nodes
1 1
zai = - inv_sqrt3; eta = - inv_sqrt3; physcial coordinates at ( – -------, – ------- )
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]+ 3 3
(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);
1 1
zai = inv_sqrt3; eta = - inv_sqrt3; physcial coordinates at ( -------, – ------- )
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]+ 3 3
(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);
1 1
zai = inv_sqrt3; eta = inv_sqrt3; physcial coordinates at ( -------, ------- )
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]+ 3 3
(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);
1 1
zai = - inv_sqrt3; eta = inv_sqrt3; physcial coordinates at ( – -------, ------- )
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]+ 3 3
(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; 2nd element
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); node # 8-20 are geometrical nodes
v[0] = 1.0*h_e_; node = new Node(9, 2, v); node_array().add(node); (serendipity)
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);
Element_Formulation_Couple* ElasticQ84_Mixed_Formulation::make(
off-diagonal C-matrix definition
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;
Listing 5•4 Substructure solution for the Hellinger-Reissner variational principle for plane elasticity
(project: “hellinger_reissner_variational_formulation” in project workspace file “fe.dsw”).
Eq. 5•53 and Eq. 5•37 are the Euler-Lagange equations of the Lagrangian functional
( ε, σ, u ) = --- ∫ ε T D ε dΩ – ∫ σ T ( ε – Lu ) dΩ – ∫ uT b dΩ – ∫ uT h dΓ
1
Eq. 5•54
2
Ω Ω Ω Γh
The Lagrangian functional in Eq. 5•54 is known as the Hu-Washizu variational principle. The finite element
approximation to the strain field uses the interpolation functions Ξ(x) as
The matrix form, at element level, of Eq. 5•37 and Eq. 5•53 is
A CT 0 ε̂ f1
Eq. 5•56
C 0 ET σ̂ = f2
0 E 0 f3
û
where
A = ∫ Ξ ⊗ ( D Ξ ) dΩ Eq. 5•57
Ωe
E = ∫ B ⊗ Ψ dΩ Eq. 5•58
Ωe
C = – ∫ Ξ ⊗ Ψ dΩ Eq. 5•59
Ωe
f3 = ∫Φ b dΩ + ∫Φ ( n σ ) dΓ – E ( n σ ) Eq. 5•62
Γ eσ
Ωe Γ eσ
The Program Listing 5•5 implements Eq. 5•56 to Eq. 5•62 (project “hu_washizu_variational_principle” in
project 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. 5•59 to be symmetrical negative definitive.
Care should be taken, if Cholesky decomposition is used, which is applicable to a symmetrical positive defini-
tive matrix. The displacement (u) shape function Φ is an eight-nodes serendipity element. These choices satisfy
the condition in Eq. 5•63. 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. 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.
#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) { define Ωε, and Ωσ
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; elem # 0 nodal coordinates
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++)
1st Gauss point natural coordinates
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+ 1st Gauss point physical coordinates
(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;
2nd Gauss point natural coordinates
for(int j = 0; j < 2; j++) 2nd Gauss point physical coordinates
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; 3rd Gauss point natural coordinates
for(int j = 0; j < 2; j++) 3rd Gauss point physical coordinates
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; 4th Gauss point natural coordinates
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]+
4th Gauss point physical coordinates
(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_;
elem # 1 nodal coordinates
zai = - inv_sqrt3; eta = - inv_sqrt3; 1st Gauss point natural coordinates
for(int j = 0; j < 2; j++) 1st Gauss point physical coordinates
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; 2nd Gauss point natural coordinates
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]+
2nd Gauss point physical coordinates
(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++)
3rd Gauss point natural coordinates
v[j] = (1.0-zai)*(1.0-eta)/4.0*xl[0][j]+ (1.0+zai)*(1.0-eta)/4.0*xl[1][j]+ 3rd Gauss point physical coordinates
(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;
4th Gauss point natural coordinates
for(int j = 0; j < 2; j++) 4th Gauss point physical coordinates
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);
∫ Ξ ⊗ ( D Ξ ) dΩ
stiff &= MATRIX("int, int", 36, 36);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 12, 12, stiff, 24, 24);
A =
stiff_sub = ((~N_epsilon) * (D * N_epsilon)) | dv; Ωe
} else { K matrix; for iterative method to esti-
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), , Zai, Eta
mate initial u values
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE( "int, int, Quadrature", 8, 2, qp);
Listing 5•5 Substructure method for the three-field Hu-Washizu variational principle for plane elasticity
(project: “hu_wahsizu_variational_formulation” in project workspace file “fe.dsw”).
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. 5•64
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.
The tip-deflection solution for the bending problem is the same as the one solved in the higher-order patch test
case. They are both exact.
σ̂ ε̂
0 0
= = û 0 = 0 Eq. 5•67
The iterative procedure starts from using the stiffness matrix from the irreducible formulation as the conver-
gence acceleration matrix
where δ û = û n+1 - û n, therefore, the next iteration solution û n+1 can be obtained. The computation of û 1 from
û 0(=0) is the same as the solution from the standard irreducible formulation. rn is defined as the residual of the
third equation in Eq. 5•56 as
r n ≡ E T σ̂ – f 3
n
Eq. 5•70
the next iterative solutions for strain ε̂ n+1, and stress σ̂ n+1 are computed from
ε̂ σ̂ = D ε̂
n+1 n+1 n+1
= C T Eû n + 1, then Eq. 5•71
We test this iterative procedure by setting the Poisson ratio ν = 0.5-10-12, which is nearly incompressible. In
addition, the plane strain is assumed. The same project “hu_washizu_variational_principle” in project workspace
file “fe.dsw” with macro definitions “__TEST_NEARLY_INCOMPRESSIBLE_PLANE_STRAIN” and
“__TEST_AUGMENTED_LAGRANGIAN_ITERATIVE_METHOD” are set at the compile time. The initial
tip-deflection solution is the same as the one from irreducible formulation, which is expected not to be the final
answer due to the nearly incompressibility under plane strain condition. After several iterations the solution con-
verged and terminated with a energy norm smaller than 10-15 times its initial energy.
m • ε – ---- dΩ
p
∫ ( δp ) T K
Eq. 5•73
Ω
where δp is the variation of p. From Eq. 4•220 in Chapter 4, we have the element stiffness matrix
k = ∫ ε ( δu ) T σ ( u )dΩ = ∫ ε ( δu )T [ σd ( u ) + mp ( u ) ]dΩ
Ω Ω
∫ ε ( δu ) T µ D0 – --- m ⊗ m ε ( u ) + mp ( u ) dΩ
2
=
Eq. 5•74
3
Ω
where the variation of u is denoted as δu. Notice that the equilibrium equation is the equilibrium of internal
forces and external forces. The weak statement of the equilibrium equation gives
∫ ε ( δu ) T µ D 0 – --- m ⊗ m ε ( u ) + mp ( u ) dΩ =
2
3 ∫ ( δu ) T b dΩ + ∫ ( δu ) T t dΓ Eq. 5•75
Ω Ω Γ
Substituting into Eq. 5•75 and Eq. 5•72 gives in matrix form at element level is
A C T û = f 1 Eq. 5•77
C V p̂ f2
where
2
A = ∫ BTµ D 0 – --- m ⊗ m BdΩ
3
Eq. 5•78
Ωe
Np ⊗ Np
V = – ∫ --------------------- dΩ Eq. 5•80
K
Ωe
f1 = ∫ NuT b dΩ + ∫ NuT t dΓ – Au Γ e
– CTp Γe
Eq. 5•81
Ωe Γe
f 2 = – Cu Γe
– Vp Γe
Eq. 5•82
The solution to substructuring of Eq. 5•77 is proceeded from its second equation, using symmetrical negative
definitiveness of V,
That is,
û = [ A – C T V –1 C ] – 1 [ f1 – C T V –1 f 2 ] Eq. 5•85
Therefore, we first solve û , and then substituting û back to Eq. 5•83 for recovering p̂ . Program Listing 5•6
(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.
A C T û = f 1 Eq. 5•86
C 0 p̂ f2
Due to the zero diagonals, the solution procedure is different from the nearly incompressible case; i.e., the inver-
sion of V in Eq. 5•83 to Eq. 5•85 is not permissible now. From first equation of Eq. 5•86, we have
CA –1 [ f 1 – C T p̂ ] = f2 ⇒ p̂ = [ CA –1 C T ] – 1 [ CA –1 f 1 – f2 ] Eq. 5•88
After p̂ is solved by the second part of Eq. 5•88, û can be recovered from second part of Eq. 5•87. The tip-
deflection is “-0.5625”. This incompressible formulation is computed with macro definition “__TEST_INCOM
PRESSIBLE_PLANE_STRAIN” set at the compile time for the same project
“incompressible_u_p_formulation” in project workspace file “fe.dsw”.
Displacement-Only Mixed Formulation: If pressure field is taken as discontinuous field, the pressure can be elim-
inated at the element level for both the nearly incompressible and incompressible cases, since no element shares
pressure node with the other element, and therefore no inter-element dependency. For example, in the nearly
incompressible case Eq. 5•85 can be written as
k e û e = f e Eq. 5•89
where the re-defined element stiffness matrix element force vector are
The Program Listing 5•7 implements the present u-only simplified mixed formulation (project “mixed_u_only”
in project workspace file “fe.dsw”). The element stiffness matrix of Q 4/9 mixed formulation is equivalent to that
of the selective reduced integration Lagrangian 9-node element (in page 406 of Chapter 4 when “ElasticQ9” ele-
ment with selective reduced integration is used. see Figure 5•3). This is known as the equivalence theorem in a
more general context.2 Notice that due to the ill-condition number in the nearly incompressible plain strain case,
the full-scale mixed solution and the displacement-only solution may differ numerically.
1. see p. 202-203 in Hughes, T.J.R., 1987, “The finite element method: linear static and dynamic finite element analysis”,
Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
2. see p. 221-223 in Hughes, T.J.R., 1987, “The finite element method: linear static and dynamic finite element analysis”,
Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
Figure 5•3 The equivalence of the selective reduced integration and the mixed formulation.
#include "include\fe.h"
static const double E_ = 1.e3;
static const double v_ = 0.5-1.e-12;
static const double K_ = E_/3.0/(1-2.0*v_);
static const double a_ = E_*(1-v_)/(1+v_)/(1-2*v_);
static const double Dv[3][3]= {{a_, a_*v_/(1-v_), 0.0 },
{a_*v_/(1-v_), a_, 0.0 },
{0.0, 0.0, a_*(1-2*v_)/2.0/(1-v_)} };
C0 D = MATRIX("int, int, const double*", 3, 3, Dv[0]);
static const double lambda_ = v_*E_/((1+v_)*(1-2*v_));
static const double mu_ = E_/(2*(1+v_));
EP::element_pattern EP::ep = EP::LAGRANGIAN_9_NODES;
Omega_h::Omega_h() {
int control_node_flag[4] = {1, 1, 1, 1};
double x[4][2] = {{0.0, 0.0}, {10.0, 0.0}, {10.0, 2.0}, {0.0, 2.0}};
block(this, 3, 5, 4, control_node_flag, x[0]);
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) {
__initialization(df, omega_h);
double f_ = 15.0;
for(int i = 0; i < row_node_no; i++) {
the_gh_array[node_order((i+1)*5-1)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order((i+1)*5-1)][0] = 0.0;
the_gh_array[node_order(5)](1)= gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(5)](1)= 0.0;
double h_ = 1.0;
the_gh_array[node_order(10)](0) = gh_on_Gamma_h::Nuemann;
the_gh_array[node_order(10)][0] = f_*(1.0/3.0)*h_;
the_gh_array[node_order(0)](0)= gh_on_Gamma_h::Nuemann;
the_gh_array[node_order(0)][0] = -f_*(1.0/3.0)*h_;
}
class ElasticQ9 : public Element_Formulation {
public:
ElasticQ9(Element_Type_Register a) : Element_Formulation(a) {}
Element_Formulation *make(int, Global_Discretization&);
ElasticQ9(int, Global_Discretization&);
};
Element_Formulation* ElasticQ9::make(int en, Global_Discretization& gd) {
return new ElasticQ9(en,gd);
}
ElasticQ9::ElasticQ9(int en, Global_Discretization& gd) : Element_Formulation(en, gd) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 9, 2, qp),
Zai, Eta;
9-nodes Lagrangian shape functions
Zai &= Z[0]; Eta &= Z[1];
N[0]=(1-Zai)*(1-Eta)/4;
N[1]=(1+Zai)*(1-Eta)/4; Step1: initial four corner nodes
N[2]=(1+Zai)*(1+Eta)/4;
N[3] =(1-Zai)*(1+Eta)/4;
N[8] = (1-Zai.pow(2))*(1-Eta.pow(2)); Step 2: add center nodes
N[0] -= N[8]/4; N[1] -= N[8]/4; Step 3:modification of four corner
N[2] -= N[8]/4; N[3] -= N[8]/4;
nodes
N[4] = ((1-Zai.pow(2))*(1-Eta)-N[8])/2;
N[5] = ((1-Eta.pow(2))*(1+Zai)-N[8])/2; due to the presence of the center node
N[6] = ((1-Zai.pow(2))*(1+Eta)-N[8])/2; Step 4:add four edge nodes and correct
N[7] = ((1-Eta.pow(2))*(1-Zai)-N[8])/2;
for the presence of the center node
∫ ( mNp ) T BdΩ
(n[0] | n[1] | n[2] | n[3] ) &
(Zero | Zero | Zero | Zero ) ); ce =
C0 c = ((~mN_p)*B) | dV; Ωe
stiff &= a-(~c)*v_inv*c;
}
Element_Formulation* Element_Formulation::type_list = 0; ke ≡ a e – ( c e ) T ( v e ) –1 c e
Element_Type_Register element_type_register_instance;
static ElasticQ9 elasticq9_instance(element_type_register_instance);
int main() {
int ndf = 2;
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()));
gd.u_h() = u;
gd.u_h() = gd.gh_on_gamma_h();
cout << gd.u_h() << endl;
return 0;
}
Listing 5•7 Displacement only mixed formulation with discontinuous pressure field (project:
“mixed_u_only” in project workspace file “fe.dsw”).
εv = m T ε = m T Lu Eq. 5•91
∂
------ 0
∂x
L = 0 ----- ∂ Eq. 5•92
-
∂y
∂ ∂
------ ------
∂y ∂x
Kε v – p = 0 Eq. 5•93
Weighted residual statements can be obtained by applying pressure variation δp to Eq. 5•91 and volumetric strain
variation δεv to Eq. 5•93 together with the weak statement (displacement variation δu) to the equilibrium equa-
tion (Eq. 5•75) we have
∫ ε ( δu ) T µ D 0 – --- m ⊗ m ε ( δu ) + mp ( u ) dΩ =
2
3 ∫ δu T b dΩ + ∫ δuT t dΓ Eq. 5•94
Ω Ω Γ
∫ δp [ εv – m T Lu ] dΩ = 0 Eq. 5•95
Ω
A CT 0 û f1
C 0 E T p̂ = f 2 Eq. 5•98
0 E H ε̂v f3
where
2
A = ∫ BT µ D 0 – --- m ⊗ m BdΩ
3
Eq. 5•99
Ωe
f1 = ∫ NuT b dΩ + ∫ NuT t dΓ – Au Γ e
– CTp Γe
Eq. 5•103
Ωe Γe
f 2 = – Cu Γe
–E T εv Eq. 5•104
Γe
f3 = – Ep Γe
– Hε v Eq. 5•105
Γe
In the process of solution, E-matrix will need to be invertible. If we take Np = Nv = Ψe(x), “-E” becomes
which is symmetrical positive definitive and the inversion of “-E” can be computed by Cholesky decomposition.
With such choice of Np = Nv, from the third equation of Eq. 5•98, we have
That is
û = [ A + C T ( E T H –1 E ) –1 C ] – 1 [ f1 + C T ( E T H –1 E ) –1 ( E T H –1 f3 – f 2 ) ] Eq. 5•110
After we obtain û , p̂ can be recovered from second part of Eq. 5•108. Then ε̂v is computed directly from second
equation of Eq. 5•98. The Program Listing 5•8 implements the u-p-εv three-field incompressible formulation
(project “incompressible_u_p_epsilon_v_formulation” in project workspace file “fe.dsw”).
If Ψe(x) is taken as discontinuous fields, the variables p and εv can be eliminated at the element level and f3 =
0 because no boundary conditions can be imposed for p and εv. Then, we withheld the subtraction of essential
displacement boundary conditions from the second equation in Eq. 5•98, therefore, f2 = 0. From the second equa-
tion we have
or
where
A ≡ A + C T E – 1 H ( E T ) –1 C = A + W T HW Eq. 5•115
Therefore a modified stiffness matrix A, based on the Hu-Washizu variational principle can be used to compute
the displacement field directly. The implementation of the A solution procedure is
#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; half element size
static const double h_e_ = L_/((double)row_segment_no);
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_)); plane stress modification
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) { define Ωu
if(i == 0) { double v[2]; Node *node; 1st row
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); 2nd row
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);
3rd row
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);
Serendipity 8-nodes element
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; define Ωp and Ωε
elem = new Omega_eh(1, 0, 0, 8, ena); omega_eh_array().add(elem); v
} else if(i == 1 || i == 2) { double inv_sqrt3 = 1.0/sqrt(3.0), v[2], xl[4][2], zai, eta; Node *node; elem # 0 nodal coordinates
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_;
1st Gauss point natural coordinates
zai = - inv_sqrt3; eta = - inv_sqrt3;
for(int j = 0; j < 2; j++) 1st Gauss point physical coordinates
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];
2nd Gauss point natural coordinates
node = new Node(0, 2, v); node_array().add(node);
zai = inv_sqrt3; eta = - inv_sqrt3; 2nd Gauss point physical coordinates
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); 3rd Gauss point natural coordinates
zai = inv_sqrt3; eta = inv_sqrt3; 3rd Gauss point physical coordinates
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); 4th Gauss point natural coordinates
zai = - inv_sqrt3; eta = inv_sqrt3;
4th Gauss point physical coordinates
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);
elem # 1 nodal coordinates
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_; 1st Gauss point natural coordinates
zai = - inv_sqrt3; eta = - inv_sqrt3;
This computation can be invoked by setting macro definition “__TEST_A_BAR_FORMULATION” at the com-
pile time for the project “incompressible_u_p_epsilon_v_formulation” in project workspace file “fe.dsw”.
B Method
Mixed formulation leads to complicated matrix substructuring problem. With the support of “fe.lib” it does
not seems to be too difficult. However, most finite element programs do not have the capability to deal with the
matrix substructuring problem. Engineering simplification need to be made, particularly if such simplification
leads to highly efficient programs. For example, the A formulation in the above simplifies the program to be
compatible with the standard irreducible formulation, if only the displacement field is to be solved. Furthermore,
we may wish to re-define, in place of the strain-displacement matrix (B-matrix), the B-matrix such that A is
expressed in the form conformable to the standard irreducible formulation1
∫B
T
A≡ DB dΩ Eq. 5•116
Ωe
2 00
D ≡ µ D 0 – --- m ⊗ m + K ( m ⊗ m ) where D 0 = 0 2 0
2
Eq. 5•117
3
0 01
This expression can be easily implemented with the aid of VectorSpace C++ Library. A more graphic expression
suitable for a lower-level implementation is
K + 2 – --- µ
2 2
K – --- µ 0
3 3
D≡ Eq. 5•118
K + 2 – --- µ 0
2 2
K – --- µ
3 3
0 0 µ
1. p. 345 in Zienkiewicz, O.C. and R.L. Taylor, 1989, “The finite element method”, 4th ed., vol. 1. McGraw-Hill, Inc., UK.
That is the deviatoric part of B is just the same as that of B, but its volumetric part, Bvol , needs to be consistent
with the u-p-εv mixed formulation. Bvol and Bdev are defined as
1 1 1
Bvol ≡ --- ( m ⊗ m )B = --- m ( m • B ) and B dev ≡ B – B vol = I – --- ( m ⊗ m ) B Eq. 5•120
3 3 3
Now, we make distinction of discrete approximation to the volumetric strain as ε vh ≡ ε v and the infinite dimen-
sional εv in continuum mechanics. The approximation in Eq. 5•97 can be more precisely written (with over-bar
indicates “average” for certain simplest approximation which will become evident later) as
and,
m • B = Ψe W Eq. 5•123
From the first part of Eq. 5•120, Bvol can be defined similarly to Bvol as
1 1
Bvol = --- m ( m • B ) = --- mΨ e W Eq. 5•124
3 3
1 1
B ≡ Bdev + B vol = I – --- ( m ⊗ m ) B + --- mΨ e W Eq. 5•125
3 3
Eq. 5•125 can look quite formidable, a step-by-step algorithm for the B formula can be given as1
∂N ∂N
B1 = -------, and B2 = ------- Eq. 5•126
∂x ∂y
˜
and define B as
1. see p.233-236 in Hughes, T.J.R., 1987, “The finite element method: linear static and dynamic finite element analysis”,
Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
and
B 5 B6
B = B 4 B7 Eq. 5•128
B 2 B1
where
˜
B1 – B 1
B 4 ≡ ------------------ Eq. 5•129
3
B 5 ≡ B 1 + B4 Eq. 5•130
B2 – B 2
B 6 ≡ ------------------ Eq. 5•131
3
B 7 ≡ B 2 + B6 Eq. 5•132
It is easily verifiable that Eq. 5•126 to Eq. 5•132 is equivalent to Eq. 5•125. The algorithm given above, Eq.
5•128 to Eq. 5•132, involves only simple arithmatics. The Program Listing 5•9 implements the B formulation in
this section. Due to the importance of this formulation, the post-processing to compute reactions, stresses, strains
are also included. The details of the post-processing have been discussed in Chapter 4.
We note by passing that from Eq. 5•124 and for the case of bilinear element with piece-wise constant pres-
sure and volumetric strain; i.e., Ψe(x) = 1, we have
∫ ( mΨe ) ⊗ B dΩ ∫ Bvol dΩ
1 1 Ωe Ωe
B vol = --- mΨ e W = --- mΨ e ------------------------------------------- = ------------------------
- Eq. 5•133
3 3
∫ e e
[ Ψ ⊗ Ψ ]dΩ ∫ dΩ
Ωe Ωe
The last term shows that the Bvol is the “mean dilatation of B” over the element domain Ωe.1 This special case
adds another perspective to our understanding of Eq. 5•119 that the definition of B ≡ Bdev + B vol is through the
modification of its volumetric part Bvol, which is the mean of Bvol over the element domain, according to Eq.
5•133. By inspecting this equation, Bvol can also be interpreted as the least squares smoothing of Bvol over the
element domain. Therefore, B is considered an assumed-strain method as oppose to the assumed-displacement
1. see p. 235 in Hughes, T.J.R., 1987, “The finite element method: linear static and dynamic finite element analysis”, Pren-
tice-Hall, Inc., Englewood Cliffs, New Jersey, and the reference therein by Nagtegaal, Parks and Rice.
#include "include\fe.h"
static const int row_node_no = 5; static const int col_node_no = 3;
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.5-1.e-12;
static const double lambda_ = v_*E_/((1+v_)*(1-2*v_));
static const double mu_ = E_/(2*(1+v_)); static const double K_ = E_/3.0/(1-2.0*v_);
Omega_h::Omega_h() {
double v[2]; Node *node; define Ωu
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
1st row
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);
2nd row
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);
3rd row
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; Serendipity 8-nodes element
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::gh_on_Gamma_h( int df, Omega_h& omega_h) { boundary conditions
__initialization(df, omega_h);
the_gh_array[node_order(4)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(4)][0] = 0.0;
the_gh_array[node_order(7)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(7)][0] = 0.0;
the_gh_array[node_order(12)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(12)][0] = 0.0;
the_gh_array[node_order(7)](1) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(7)][1] = 0.0;
the_gh_array[node_order(8)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(8)][0] = -5.0;
the_gh_array[node_order(0)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(0)][0] = 5.0;
}
static int ndf = 2;
static Omega_h oh;
static gh_on_Gamma_h gh(ndf, oh);
static U_h uh(ndf, oh);
static Global_Discretization gd(oh, gh, uh);
class Elastic_B_bar_Q84 : public Element_Formulation {
public:
Elastic_B_bar_Q84(Element_Type_Register a) : Element_Formulation(a) {}
Element_Formulation *make(int, Global_Discretization&);
Elastic_B_bar_Q84(int, Global_Discretization&);
};
Element_Formulation* Elastic_B_bar_Q84::make(int en, Global_Discretization& gd) {
return new Elastic_B_bar_Q84(en,gd);
}
∫B
T
} else stiff &= ((~B_bar)*D*B_bar)|dv; K≡ DB dΩ
}
Element_Formulation* Element_Formulation::type_list = 0; Ωe
Element_Type_Register element_type_register_instance;
D ≡ µ D 0 – --- m ⊗ m + K ( m ⊗ m )
2
static Elastic_B_bar_Q84
elastic_B_bar_Q84_instance(element_type_register_instance);
3
int main() {
where
Matrix_Representation mr(gd);
mr.assembly();
20 0
C0 u = ((C0)(mr.rhs())) / ((C0)(mr.lhs()));
gd.u_h() = u; D0 = 0 2 0
gd.u_h() = gd.gh_on_gamma_h(); 00 1
cout << gd.u_h() << endl;
#if defined(__TEST_POST_PROCESSING)
Matrix_Representation::Assembly_Switch = Matrix_Representation::REACTION; post-processing
mr.assembly(FALSE);
cout << "reaction:" << endl << (mr.global_nodal_value()) << endl;
Matrix_Representation::Assembly_Switch = Matrix_Representation::STRAIN;
mr.assembly(FALSE);
Matrix_Representation::Assembly_Switch = Matrix_Representation::NODAL_STRAIN;
mr.assembly(FALSE);
cout << "nodal strains:" << endl << (mr.global_nodal_value()) << endl;
Matrix_Representation::Assembly_Switch = Matrix_Representation::STRESS;
mr.assembly(FALSE);
Matrix_Representation::Assembly_Switch = Matrix_Representation::NODAL_STRESS;
mr.assembly(FALSE);
cout << "nodal stresses:" << endl << (mr.global_nodal_value()) << endl;
#endif
return 0;
}
Listing 5•9 B matrix formulation for plane elasticity (project: “b_bar_formulation” in project workspace
file “fe.dsw”).
Non-conforming Element
In Chapter 4 Figure 4•42 eight bilinear 4-node elements and two Lagrangian 9-node elements are used to
compute beam bending problem. The tip-deflection solution (see TABLE 4•3. in page 405) with bilinear 4-node
elements (2 × 2 integration) is only 60 % of the exact solution, while it is 98% accurate for the Lagrangian 9-node
elements. The bilinear 4-node element exhibits shear locking and dilatation locking both due to the interpolation
failure to represent x2 and y2 (see aliasing analysis discussed in page 397 and page 406). Therefore these two
quadratic displacement modes are added back (1) to improve the bending behavior, and (2) to overcome the
incompressible limit of the 4-node element. This is the Wilson’s nonconforming element.
where node number “0, 1, 2 , 3” corresponding to four nodes of the element. α̂ e , with a = 4, 5, are known as
a
“nodeless variables” or “generalized displacements”, which is independent from the other element. Since α̂ e are
a
independent from the other elements, they can be eliminated at the element level. The element stiffness matrix is
of the form corresponding to variables a = [u0, u1, u2, u3, α4, α5]T as
T
k uu k αu û f
= Eq. 5•136
k αu k αα α̂ 0
α̂ – 1 k û
= – k αα αu Eq. 5•137
kû ≡ [ k uu – k αu
T k – 1 k ]û = f
αα αu Eq. 5•138
However, it is found that Wilson’s non-conforming element only works for rectangular or parallelogram element.
The addition of two quadratic shape functions in Eq. 5•134 make the interpolation polynomial not complete up to
the second-order. Therefore, the spatial isotropy is lost; the element is not invariant with respect to an arbitrary
coordinate axes rotation. The integration of B-matrix components corresponding to the nodeless variables are
∂y
– ξ ------ 0
1 1 N 4, x 0 1 1 ∂η
∂x
B4 dΩ = ∫∫ 0 N 4, y J dξ dη = 2 ∫ ∫ 0 ξ ------ dξd
∂η
Eq. 5•139
–1 –1 N 4, y N 4, x –1 –1
∂x ∂y
ξ ------ – ξ ------
∂η ∂η
∂y
η ------ 0
1 1 N 5, x 0 1 1 ∂ξ
∂x
∫ B 5 dΩ = ∫∫ 0 N 5, y J dξ dη = 2 ∫ ∫ 0 – η ------ dξ dη
∂ξ
Eq. 5•140
Ωe –1 – 1 N 5, y N 5, x –1 –1
∂x ∂y
– η ------ η ------
∂ξ ∂ξ
where we have use the relation N,x = N,ξ ξ,x, and the inversion of a 2 × 2 matrix
–1
∂ξ ∂ξ ∂x ∂x ∂y ∂x
------ ------ ------ ------ ------ ------
∂x ∂y ∂ξ ∂η 1 ∂η – ∂η
= = --
- Eq. 5•141
∂η ∂η ∂y ∂y J ∂y ∂x
------ ------ ------ ------ – ------ ------
∂x ∂y ∂ξ ∂η ∂ξ ∂ξ
For rectangular and parallelogram elements, the derivatives in Eq. 5•139 and Eq. 5•140 are constants through
out element domain. The integration of B4 and B5 over ξ and η = [-1, 1] are zero when the derivatives are con-
stant throught out the element domain, since B4 and B5, as defined in Eq. 5•139 and Eq. 5•140, become odd
functions of ξ and η. For element geometry other than rectangular or parallelogram, we can improve the behav-
ior of the non-conforming element. This can be achieved by evaluating the derivatives and the Jacobian for B4
and B5 only at the center [ξ0, η0] of the element. Such element has the improved behavior for element geometry
that are not rectangular or parallelogram (Taylor’s non-conforming element). Recall that the 8 bilinear 4-node
elements in the higher-order patch test (page 422 in Chapter 4) produces tip deflection of “-0.656467”, which is
significantly less than the exact solution of “-0.75”. Program Listing 5•10 implements the non-conforming ele-
ment discussed in this section. The Taylor’s non-conforming element can be invoked by setting macro definition
“__TEST_TAYLOR” at the compile time. The distortion of vertical element boundaries can be set by the macro
definition “__TEST_DISTORTION”. The results of eight non-conforming elements in the same problem in the
higher-order patch test are listed in the TABLE5• 1.
Without geometrical distortion both Wilson’s and Taylor’s non-conforming elements produce exact solution.
That is they both provide solution superior than the standard bilinear element. When the geometrical distortion
#include "include\fe.h"
static const double L_ = 10.0; static const double c_ = 1.0; static const double h_e_ = L_/4.0;
static const double E_ = 1.e3; static const double v_ = 0.3;
#if defined(__TEST_DISTORTION)
static const double e_ = h_e_/2.0;
#else
static const double e_ = 0.0;
#endif
Omega_h::Omega_h() {
double v[2]; Node *node; define Ωu
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
1st row
v[0] = h_e_-e_; node = new Node(1, 2, v); node_array().add(node);
v[0] = 2.0*h_e_-2.0*e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 3.0*h_e_-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);
2nd row
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);
3rd row
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_+e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 2.0*h_e_+2.0*e_; node = new Node(12, 2, v); node_array().add(node);
v[0] = 3.0*h_e_+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); 4-nodes element
int ena[4]; Omega_eh *elem;
ena[0] = 0; ena[1] = 1; ena[2] = 6; ena[3] = 5;
elem = new Omega_eh(0, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 1; ena[1] = 2; ena[2] = 7; ena[3] = 6;
elem = new Omega_eh(1, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 3; ena[2] = 8; ena[3] = 7;
elem = new Omega_eh(2, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 3; ena[1] = 4; ena[2] = 9; ena[3] = 8;
elem = new Omega_eh(3, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 5; ena[1] = 6; ena[2] = 11; ena[3] = 10;
elem = new Omega_eh(4, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 6; ena[1] = 7; ena[2] = 12; ena[3] = 11;
elem = new Omega_eh(5, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 7; ena[1] = 8; ena[2] = 13; ena[3] = 12;
elem = new Omega_eh(6, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 8; ena[1] = 9; ena[2] = 14; ena[3] = 13;
elem = new Omega_eh(7, 0, 0, 4, ena); omega_eh_array().add(elem);
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) {
__initialization(df, omega_h); boundary conditions
the_gh_array[node_order(4)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(4)][0] = 0.0;
the_gh_array[node_order(9)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(9)][0] = 0.0;
the_gh_array[node_order(14)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(14)][0] = 0.0;
the_gh_array[node_order(9)](1) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(9)][1] = 0.0;
the_gh_array[node_order(10)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(10)][0] = -5.0;
the_gh_array[node_order(0)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(0)][0] = 5.0;
}
Element_Formulation* Element_Formulation::type_list = 0;
Element_Type_Register element_type_register_instance;
static Elastic_Nonconforming_Q4
elastic_nonconforming_q4_instance(element_type_register_instance);
int main() {
Matrix_Representation mr(gd);
mr.assembly();
C0 u = ((C0)(mr.rhs())) / ((C0)(mr.lhs()));
gd.u_h() = u;
gd.u_h() = gd.gh_on_gamma_h();
cout << gd.u_h() << endl;
return 0;
}
Listing 5•10 Nonconforming element for plane elasticity (project: “nonconforming_element” in project
workspace file “fe.dsw”).
The element stiffness matrix is of size 8 × 8 for bilinear 4-node element (i.e., {ndf × nen} × {ndf × nen}). There are
three independent relations provided by three equations of stress-strain relations. Therefore, the one point Gauss
integration produces ke(1-point) of rank 3, which is clearly rank deficient. The correct rank number for ke should
be 5, which is from the full-rank subtracts the three rigid-body-motions (8-3=5). Therefore, two trial hourglass
modes (expanded by Ψ to both u and v), corresponding to the x-hourglass and y-hourglass modes (see Figure
4•50d& e in Chapter 4), are used to define ke(hourglass) as
EJ ( b ⊗ b )
k e ( hourglass ) ≡ -------------------------- ⊗ ( Ψ ⊗ Ψ ) Eq. 5•143
12
where E is the Young’s modulus. We can view Eq. 5•36 for heat conduction as the 1-ndf degenerated version of
Eq. 5•143 (by using κ ( b • b ) , a scalar, in place of E ( b ⊗ b ), which is a 2 × 2 matrix).The hourglass element is
implemented in project “hourglass_element” in project workspace file “fe.dsw” and is shown in the Program
Listing 5•11.
We test the performance of the hourglass element by considering the same problem solved by project
“higher_order_patch_test”. The formulation of 1-point integration stiffness is the same as the stiffness matrix
computed with macro definition “__TEST_B_MATRIX_FORMULATION” set at compile time for project
“higher_order_patch_test”. The hourglass element takes only 0.5 second to assemble the global stiffness matrix
comparing to 4.5 seconds for the standard 2 × 2 integration with project “higher_order_patch_test” (on an obso-
lete 166 MHz PC). However, the tip deflection is -0.82 instead of -0.75 (exact), which is not very accurate.
#include "include\fe.h"
static const double L_ = 10.0; static const double c_ = 1.0; static const double h_e_ = L_/4.0;
static const double E_ = 1.e3; static const double v_ = 0.3;
#if defined(__TEST_DISTORTION)
static const double e_ = h_e_/2.0;
#else
static const double e_ = 0.0;
#endif
Omega_h::Omega_h() {
double v[2]; Node *node; define Ωu
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
1st row
v[0] = h_e_-e_; node = new Node(1, 2, v); node_array().add(node);
v[0] = 2.0*h_e_-2.0*e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 3.0*h_e_-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);
2nd row
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);
3rd row
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_+e_; node = new Node(11, 2, v); node_array().add(node);
v[0] = 2.0*h_e_+2.0*e_; node = new Node(12, 2, v); node_array().add(node);
v[0] = 3.0*h_e_+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); 4-nodes element
int ena[4]; Omega_eh *elem;
ena[0] = 0; ena[1] = 1; ena[2] = 6; ena[3] = 5;
elem = new Omega_eh(0, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 1; ena[1] = 2; ena[2] = 7; ena[3] = 6;
elem = new Omega_eh(1, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 3; ena[2] = 8; ena[3] = 7;
elem = new Omega_eh(2, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 3; ena[1] = 4; ena[2] = 9; ena[3] = 8;
elem = new Omega_eh(3, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 5; ena[1] = 6; ena[2] = 11; ena[3] = 10;
elem = new Omega_eh(4, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 6; ena[1] = 7; ena[2] = 12; ena[3] = 11;
elem = new Omega_eh(5, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 7; ena[1] = 8; ena[2] = 13; ena[3] = 12;
elem = new Omega_eh(6, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 8; ena[1] = 9; ena[2] = 14; ena[3] = 13;
elem = new Omega_eh(7, 0, 0, 4, ena); omega_eh_array().add(elem);
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) {
__initialization(df, omega_h); boundary conditions
the_gh_array[node_order(4)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(4)][0] = 0.0;
the_gh_array[node_order(9)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(9)][0] = 0.0;
the_gh_array[node_order(14)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(14)][0] = 0.0;
the_gh_array[node_order(9)](1) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(9)][1] = 0.0;
the_gh_array[node_order(10)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(10)][0] = -5.0;
the_gh_array[node_order(0)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(0)][0] = 5.0;
}
Listing 5•11 Hourglass element for plane elasticity (project: “hourglass_element” in project workspace file
“fe.dsw”).
t0 = - t1 = λ Eq. 5•144
Irreducible Subdomains
The Euler-Lagrange equations applied on each of the two subdomains are
Γ0
Ω0
σ0 , u0 t = nσ (Cauchy’s formula)
n
t1
x0
ΓI tn = t • n
t0
Ω1 tt = t-tn
σ1 , u1
Γ1
Figure 5•4 Traction contact condition in the internal discontinuous surface ΓI. tn
is the normal component of t, and tt is its tangential component.
1. see p. 242 in Malvern, L.E., 1969, “Introduction to the mechanics of a continuous medium”, Prentice-Hall, Inc., Engle-
wood Cliffs, New Jersey.
∫ δ λ T ( u1 – u0 ) dΓ Eq. 5•146
ΓI
The matrix form of Eq. 5•145 and Eq. 5•146 after finite element approximation is1
K 0 Q 0T 0 û 0 f0
Q 0 0 Q1 λ̂ = fI Eq. 5•147
0 Q 1T K 1 û 1 f1
where for i = 0, 1
Q i = ( – 1 ) i ∫ N λT N u dΓ Eq. 5•149
i
ΓI
fi = ∫ NuT b dΩ + ∫ NuT h i dΓ
i i
Eq. 5•150
Ωi Γi
In the spirit of the B-method, all internal fields are eliminated at the element level through static condensation
to make a displacement-only formulation that resembles the standard irreducible formulation. In the present case,
the displacement û in Eq. 5•147 can be eliminated, leave only with boundary forces λ̂, provided that the stiff-
ness matrices Ki are all invertible. However, that would require each subdomain be specified so that the rigid-
body-motions are precluded. Therefore, the singularity of the stiffness matrices is avoided. The difficulty in
removing rigid-body-motions for each subdomain limits the practical use of the hybrid method in the present
form.
The Program Listing 5•12 implements the hybrid irreducible domains formulation. The test problem for the
higher-order patch test is now illustrated in Figure 5•5. As stated earlier special difficulty arises that the subdo-
main “0” is not fully constrained that the rigid-body modes can be prevented. The solution procedure is pro-
ceeded as the followings. First the static condensation can still be applied to the subdomain “1”, since its is
constrained sufficiently to suppress the rigid body motions. From third equation of Eq. 5•147, since K1 is not sin-
gular we can have
1. see p.375 in Zienkiewicz, O.C. and R.L. Taylor, 1989, “The finite element method”, 4th ed., vol. 1. McGraw-Hill, Inc.,
UK.
Q 0 û 0 + Q 1 K 1– 1 [ f 1 – Q 1T λ̂ ] = fI Eq. 5•152
Therefore,
After û 0 is obtained, λ̂ is computed from Eq. 5•153, then û 1 is computed from Eq. 5•151. The solution of this
computation shows that the tip-deflection is 0.75 (exact), and the horizontal traction λx on top and bottom of the
interface element has the magnitude of “15”, which is also exact.
Γ0 Γ1
15
Ωh0 Ωh 1
-15
ΓI
E =103, ν = 0.3
Figure 5•5 Bean bending problem for the hybrid irreducible domains formulation.
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
#include "include\global_discretization_gamma_h_n.h"
static const double L_ = 10.0;
static const double c_ = 1.0;
static const double h_e_ = L_/((double)4.0);
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]; define Ωh0
Node *node;
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
1st row
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); 2nd row
v[0] = 0.0; v[1] = 1.0*c_; node = new Node(3, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(4, 2, v); node_array().add(node);
v[0] = 0.0; v[1] = 2.0*c_; node = new Node(5, 2, v); node_array().add(node);
v[0] = h_e_; node = new Node(6, 2, v); node_array().add(node); 3rd row
v[0] = 2.0*h_e_; node = new Node(7, 2, v); node_array().add(node);
int ena[8]; Omega_eh *elem;
ena[0] = 0; ena[1] = 2; ena[2] = 7; ena[3] = 5; 4-nodes element
ena[4] = 1; ena[5] = 4; ena[6] = 6; ena[7] = 3;
elem = new Omega_eh(0, 0, 0, 8, ena);
omega_eh_array().add(elem);
} else if(i == 1) { define Ωh1
double v[2];
Node *node;
v[0] = 2.0*h_e_; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[0] = 3.0*h_e_; node = new Node(1, 2, v); node_array().add(node);
v[0] = 4.0*h_e_; node = new Node(2, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; v[1] = 1.0*c_; 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] = 2.0*h_e_; v[1] = 2.0*c_; node = new Node(5, 2, v); node_array().add(node);
v[0] = 3.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);
int ena[8]; Omega_eh *elem;
ena[0] = 0; ena[1] = 2; ena[2] = 7; ena[3] = 5;
ena[4] = 1; ena[5] = 4; ena[6] = 6; ena[7] = 3;
elem = new Omega_eh(0, 0, 0, 8, ena);
omega_eh_array().add(elem);
} else if(i == 2) { define ΓI; interface line elements
double v[2];
Node *node;
v[0] = 2.0*h_e_; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[1] = 1.0*c_; node = new Node(1, 2, v); node_array().add(node);
v[1] = 2.0*c_; node = new Node(2, 2, v); node_array().add(node);
int ena[3]; Omega_eh *elem; ena[0] = 0; ena[1] = 1; ena[2] = 2;
elem = new Omega_eh(0, 0, 0, 3, ena);
omega_eh_array().add(elem);
}
}
∫ BiT Di Bi dΩ
wy*~wy*U[1][1] )
| dv2 ); Ki =
stiff &= stiff_vol + stiff_dev; Ωi
}
û 1 = K 1–1 [ f 1 – Q 1T λ̂ ]
gd_interface.u_h() = gd_interface.gh_on_gamma_h();
cout << "inteface traction:" << endl << gd_interface.u_h();
gd_0.u_h() = u_0;
gd_0.u_h() = gd_0.gh_on_gamma_h();
cout << "first domain displacement:" << endl << gd_0.u_h();
gd_1.u_h() = u_1;
gd_1.u_h() = gd_1.gh_on_gamma_h();
cout << "second domain displacement:" << endl << gd_1.u_h();
return 0;
}
Listing 5•12 Hybrid irreducible subdomains for plane elasticity (project: “hybrid_irreducible_subdomain”
in project workspace file “fe.dsw”).
where i = 0, 1. An alternative form of the Hellinger-Reissner variational principle can be used to develop highly
efficient and accurate element. The Pian-Sumihara element can be easily implemented with the assumed-stress
field as1
a 22 ( ξ – ξ 0 ) a 02 ( η – η 0 )
Nσ ≡ b 22 ( ξ – ξ 0 ) b 02 ( η – η 0 ) Eq. 5•157
a2 b2 ( ξ – ξ0 ) a0 b0 ( η – η0 )
where
3 3 3 3 3 3
a0 ≡ ∑ xa ξa, a1 ≡ ∑ x a ξa ηa, a 2 ≡ ∑ xa ηa, b0 ≡ ∑ y a ξa, b1 ≡ ∑ ya ξa ηa, b2 ≡ ∑ ya ηa Eq. 5•158
a=0 a=0 a=0 a=0 a=0 a=0
{xa, ya}T(a = 0, ..., 3) are nodal coordinate, {ξa, ηa}T = {{-1,-1}, {1,-1},{1,1},{-1,1}}, and
J1 J2 a 0 b 2 – a2 b 0 a0 b1 – a1 b0 a1 b2 – a2 b1
ξ 0 ≡ --------, η 0 ≡ --------, with J 0 ≡ ----------------------------, J 1 ≡ ---------------------------- , J 2 ≡ ---------------------------- Eq. 5•159
3J 0 3J 0 16 16 16
where ke(1-point) is again the 1-point Gaussian integration on stiffness matrix from standard irreducible formula-
tion, and ke(stabilizer) is defined as
1. see p.282-285 in Zienkiewicz, O.C. and R.L. Taylor, 1989, “The finite element method”, 4th ed., vol. 1. McGraw-Hill,
Inc., UK.
∫ Nσ D –1 Nσ dΩ, ∫ N σ B dΩ
T T
A= and C = Eq. 5•162
Ωe Ωe
The Program Listing 5•12 implements the Pian-Sumihara element. For the test case in “higher-order patch test”
in nearly incompressible plane strain condition (with ν = 0.5 - 10-12), the tip-deflection of the Pian-Sumihara
element is “-0.566027”, which is comparable to the tip-deflection “-0.5625” in project
“incompressible_u_p_formulation” (with ν = 0.5 & plane strain). For element distortion test1, as shown in Fig-
ure 5•6, the Pian-Sumihara element produces tip-deflection that is 80% of that of the element without distortion,
which is far better than bilinear 4-node element. The Pian-Sumihara element is praised as the most efficient and
accurate four-noded element to date.
0.5
10
1. see p.387 in Zienkiewicz, O.C. and R.L. Taylor, 1989, “The finite element method”, 4th ed., vol. 1. McGraw-Hill, Inc.,
UK.
#include "include\fe.h"
static const double L_ = 10.0; static const double c_ = 2.0; static const double h_e_ = L_/2.0;
#if defined(__TEST_HIGHER_ORDER_PATCH_TEST)
static const double E_ = 1000.0;
static const double v_ = 0.5-1.e-12;
#else
static const double E_ = 1500.0; static const double v_ = 0.25;
#endif
#if defined(__TEST_DISTORTION)
static const double e_ = h_e_/10.0;
#else
static const double e_ = 0.0;
#endif
EP::element_pattern EP::ep = EP::QUADRILATERALS_4_NODES;
Omega_h::Omega_h() {
#if defined(__TEST_HIGHER_ORDER_PATCH_TEST) eight 4-nodes quadrilaterals
double x[4][2] = {{0.0, 0.0}, {10.0, 0.0}, {10.0, 2.0}, {0.0, 2.0}};
int control_node_flag[4] = {1, 1, 1, 1}, col_node_no = 5, row_node_no = 3;
block(this, row_node_no, col_node_no, 4, control_node_flag, x[0]);
#else
double v[2]; Node *node; two 4-nodes quadrilaterals
v[0] = 0.0; v[1] = 0.0; node = new Node(0, 2, v); node_array().add(node);
v[0] = h_e_-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] = 0.0; v[1] = c_; node = new Node(3, 2, v); node_array().add(node);
v[0] = h_e_+e_; node = new Node(4, 2, v); node_array().add(node);
v[0] = 2.0*h_e_; node = new Node(5, 2, v); node_array().add(node);
int ena[4]; Omega_eh *elem; ena[0] = 0; ena[1] = 1; ena[2] = 4; ena[3] = 3;
elem = new Omega_eh(0, 0, 0, 4, ena); omega_eh_array().add(elem);
ena[0] = 1; ena[1] = 2; ena[2] = 5; ena[3] = 4;
elem = new Omega_eh(1, 0, 0, 4, ena); omega_eh_array().add(elem);
#endif
}
gh_on_Gamma_h::gh_on_Gamma_h(int df, Omega_h& omega_h) {
__initialization(df, omega_h);
#if defined(__TEST_HIGHER_ORDER_PATCH_TEST) test case from p. 301 “Load 2”
int col_node_no = 5, row_node_no = 3; Zienkiewicz & Taylor vol.1
for(int i = 0; i < row_node_no; i++) {
the_gh_array[node_order((i+1)*col_node_no-1)](0) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order((i+1)*col_node_no-1)][0] = 0.0;
}
the_gh_array[node_order(col_node_no*((row_node_no+1)/2)-1)](1) =
gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(col_node_no*((row_node_no+1)/2)-1)][1] = 0.0;
double h_ = 1.0, f_ = 15.0;
the_gh_array[node_order(2*col_node_no)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(2*col_node_no)][0] = -f_*(1.0/3.0)*h_;
the_gh_array[node_order(0)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(0)][0] = f_*(1.0/3.0)*h_;
#else
the_gh_array[node_order(2)](0) = the_gh_array[node_order(5)](0) =
test case B.C. #3 from p. 386 , distorted
the_gh_array[node_order(2)](1) = gh_on_Gamma_h::Dirichlet; element configuration in p. 387 of
the_gh_array[node_order(3)](0) = gh_on_Gamma_h::Neumann; Zienkiewicz & Taylor vol.1
the_gh_array[node_order(3)][0] = 1000.0;
the_gh_array[node_order(0)](0) = gh_on_Gamma_h::Neumann;
the_gh_array[node_order(0)][0] = -1000.0;
#endif
}
H1 x = n*xl;
H0 nx = d(n) * d(x).inverse();
J dv2(d(x).det());
int main() {
int ndf = 2;
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()));
gd.u_h() = u;
gd.u_h() = gd.gh_on_gamma_h();
cout << gd.u_h();
return 0;
}
Listing 5•13 Hybrid Pian-Sumihara element for plane elasticity (project: “hybrid_pian_sumihara” in
project workspace file “fe.dsw”).
∂w
γx θx -------
∂x
γ = = – + = ( – θ ) + ∇w Eq. 5•163
γy θy ∂w
-------
∂y
In Reissner-Mindlin plate theory, the “fiber” is assumed to remain in plane, but it is not assumed to keep perpen-
dicular to the mid-surface as in thin plate theory. That is the transverse shear, γ, is not assumed to be zero. The
bending moment constitutive equations from Eq. 4•251 in Chapter 4 is
M = DL θ Eq. 5•164
The shear force relations to the bending moments and vertical loads from Eq. 4•254 in Chapter 4 are
First, M can be eliminated by substituting Eq. 5•164 into first part of Eq. 5•165 as
L T DL θ + S = 0 Eq. 5•166
Then, the constitutive equation for shear force and transverse shear strain is S = αγ (Eq. 4•253 in Chapter 4)
where α is the shear rigidity. Therefore,
--- + θ – ∇w = 0
S
Eq. 5•167
α
from the definition of the transverse shear strain γ ≡ ( – θ ) + ∇w in Eq. 5•163. Eq. 5•167 can be re-arranged as S
= α ( – θ + ∇w ) . Then, this is used to eliminate the shear force S in Eq. 5•166 as
L T DL θ – α ( θ – ∇w ) = 0 Eq. 5•168
∇ T [ α ( θ – ∇w ) ] = q Eq. 5•169
and
Integrating by parts to first term of Eq. 5•171 and to the left-hand-side terms of Eq. 5•172 and apply Green’s the-
orem
∫ ( ( LNθ ) T DLNθ + NθT αNθ ) dΩ θ̂ – ∫ NθT α∇Nw dΩŵ = ∫ NθT MΓ dΓ Eq. 5•173
Ω Ω Γ
and
or in matrix form
T ŵ
K s K bs fw
= Eq. 5•175
K bs K b θ̂ fθ
where
T
K s K bs Ks T
K bs 0 0
= + ≡ KS + KB Eq. 5•181
K bs K b K bs K b ( α ) 0 Kb ( D )
The matrix KS involves components that enforce the shear constraints, and KB is the part that has only to do
with the bending energy. This stiffness splitting is useful for selective reduced integration, in which the reduced
integration is applied to all the submatrices in the shear constraint part, KS, to avoid shear locking.
The Program Listing 5•14 implements the “heterosis element” illustrated in Figure 5•7. The deflection
degree of freedom, w, uses eight-node serendipity shape function, and the rotation degrees of freedom, θ = [θx ,
θy]T, use Lagrangian 9-node shape function. All terms except the bending stiffness submatrix Kb(D) (or KB stiff-
ness matrix) use the reduced (2 × 2) integration. We solve the same test problem in the thin plate section. The
maximum deflection is 222358 at center, which is comparing to the exact solution of the thin-plate theory of
226800.
:w
:θ
Figure 5•7 Heterosis element for irreducible thick plate formulation with Serendipity shape
function for deflection (w) and Lagrangian shape function for rotation (θ). The bending stiffness
submatrix Kb(D) is fully integrated with 3 × 3 integration. All other terms, that involve shear
constraints, are selective reduced integrated (2 × 2).
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) { Heterosis element
if(i == 0) { int row_segment_no = 2, count=0;
Node *node; double v[2], h = 1.0/((double)(row_segment_no)); Ωw; 8-node serendipity element
for(int j = 0; j < row_segment_no; j++) {
v[1] = ((double)j)*h;
for(int k = 0; k < (2*row_segment_no+1); k++) {
v[0] = ((double)k)*h/2; node = new Node(count++, 2, v); the_node_array.add(node);
}
v[1] += h/2.0;
for(int k = 0; k < row_segment_no+1; k++) {
v[0] = ((double)k)*h; node = new Node(count++, 2, v); the_node_array.add(node);
}
}
v[1] = 1.0;
for(int j = 0; j < (2*row_segment_no+1); j++) {
v[0] = ((double)j)*h/2.0; node = new Node(count++, 2, v); the_node_array.add(node);
}
int ena[8]; Omega_eh *elem; count = 0;
for(int j = 0; j < row_segment_no; j++)
for(int k = 0; k < row_segment_no; k++) {
int first_node = j*(3*row_segment_no+2)+k*2;
ena[0] = first_node; ena[1] = ena[0]+2; ena[2] = ena[1]+(3*row_segment_no+2);
ena[3] = ena[2]-2; ena[4] = ena[0]+1;
ena[5] = (j+1)*(2*row_segment_no+1)+j*(row_segment_no+1)+k+1;
ena[6] = ena[3]+1; ena[7] = ena[5]-1;
elem = new Omega_eh(count++, 0, 0, 8, ena); the_omega_eh_array.add(elem);
}
} else if(i == 1) { Ωθ; Lagrangian 9-node element
int row_segment_no = 2;
int count = 0; Node *node; double v[2], h = 1.0/((double)(row_segment_no));
for(int j = 0; j < row_segment_no; j++) {
v[1] = ((double)j)*h;
for(int k = 0; k < (2*row_segment_no+1); k++) {
v[0] = ((double)k)*h/2; node = new Node(count++, 2, v); the_node_array.add(node);
}
v[1] += h/2.0;
for(int k = 0; k < (2*row_segment_no+1); k++) {
v[0] = ((double)k)*h/2; node = new Node(count++, 2, v); the_node_array.add(node);
}
}
v[1] = 1.0;
for(int j = 0; j < (2*row_segment_no+1); j++) {
v[0] = ((double)j)*h/2.0; node = new Node(count++, 2, v); the_node_array.add(node);
}
int ena[9]; Omega_eh *elem; count = 0;
for(int j = 0; j < row_segment_no; j++) for(int k = 0; k < row_segment_no; k++) {
int row_node_no = 2*row_segment_no+1, first_node = j*2*row_node_no+k*2;
ena[0] = first_node; ena[1] = ena[0]+2; ena[2] = ena[1]+2*row_node_no;
ena[3] = ena[2]-2; ena[4] = ena[0]+1; ena[5] = ena[1]+row_node_no;
ena[6] = ena[2]-1; ena[7] = ena[0]+row_node_no; ena[8] = ena[7] +1;
elem = new Omega_eh(count++, 0, 0, 9, ena); the_omega_eh_array.add(elem);
}
}
}
θ
Global_Discretization w_gd(oh_w, w_gh, w_h, w_type);
const int theta_ndf = 2;
Omega_h_i oh_theta(1);
gh_on_Gamma_h_i theta_gh(1, theta_ndf, oh_theta);
U_h theta_h(theta_ndf, oh_theta);
Global_Discretization theta_gd(oh_theta, theta_gh, theta_h, theta_type);
Global_Discretization_Couple gdc(theta_gd, w_gd); θ-w
Matrix_Representation mr_w(w_gd);
Matrix_Representation mr_theta(theta_gd);
Matrix_Representation_Couple mrc(gdc, 0, &(mr_theta.rhs()), &(mr_w.rhs()), &mr_w);
mr_w.assembly();
mr_theta.assembly();
mrc.assembly();
C0 Ks = ((C0)(mr_w.lhs())), f_w = ((C0)(mr_w.rhs())), Ks , and fw
Kbs = ((C0)(mrc.lhs())), Kbs
Kb = ((C0)(mr_theta.lhs())), f_theta = ((C0)(mr_theta.rhs()));
Kb, and fθ
Cholesky dKs(Ks);
C0 Ks_inv = dKs.inverse(),
KbsKs_invKbst = Kbs*Ks_inv*(~Kbs),
K = Kb-KbsKs_invKbst,
f = f_theta-Kbs*(dKs*f_w);
θ̂=(Kb-Kbs(Ks)-1KbsT)-1
LU dK(K); (fθ-Kbs(Ks)-1fw)
C0 theta = dK*f,
w = dKs*(f_w-(~Kbs)*theta);
ŵ = (Ks)-1(fw-KbsTθ̂ )
w_h = w; w_h = w_gd.gh_on_gamma_h();
cout << "deflection w:" << endl << w_h << endl;
theta_h = theta; theta_h = theta_gd.gh_on_gamma_h();
cout << "rotation (theta_x, theta_y):" << endl;
for(int i = 0; i < theta_h.total_node_no(); i++) cout << theta_h[i] << endl;
return 0;
}
Listing 5•14 Heterosis element for θ-w irreducible thick plate formulation (project:
“irreducible_thick_plate” in project workspace file “fe.dsw”).
L T DL θ + S = 0 Eq. 5•183
--- + θ – ∇w = 0
S
Eq. 5•184
α
Three variables in Eq. 5•183 to Eq. 5•185 [θ, S, w]T are approximated as
θ = N θ θ̂ , S = N S S and w = Nw ŵ
ˆ
Eq. 5•186
Integrating by parts on the first term of Eq. 5•187 and the first term of Eq. 5•189, then apply Green’s theorem,
and simply change sign of Eq. 5•188 yield
∫ ( ∇Nw )T NS dΩŜ = – ∫ Nw ∫ w Γ
T q dΩ + N T S dΓ Eq. 5•192
Ω Ω Γ
Kb C T 0 θ̂ fθ
C H E T Sˆ = 0 Eq. 5•193
0 E 0 ŵ fw
H = – ∫ N ST --- N S dΩ
1
α
Eq. 5•196
Ω
The condition for non-singular matrices parallel to that for the three-fields Hu-Washizu variational principle in
Eq. 5•63 is
By inspecting Eq. 5•194 to Eq. 5•199, the first derivatives of θ and w exist. Therefore, C0-continuity need to be
satisfied for these two fields. S-field is taken as discontinuous, which has the potential advantage of being elim-
inated at the element level.1 The Program Listing 5•15 implements Heterosis element with θ-S-w mixed formu-
lation. The S-field is 4-node element by taking the four nodes at the 2 × 2 integration points. The results of the
mixed formulation is the same as the one with selective reduced integration on the shear constraint terms. In
plane elasticity, the equivalence theorem, in the previous chapter, was applied to (1) the selective reduced inte-
gration on the pressure constraint for the irreducible formulation, and (2) the pressure node taking on the Gauss
integration points for the mixed u-p formulation. Now, the equivalence theorem is applied to, the thick plate the-
ory, for (1) the θ-w irreducible formulation with the selective reduced integration on the shear constraint terms,
and (2) the θ-S-w mixed formulation where S-field is 4-node element with four nodes at the 2 × 2 integration
points. This equivalence theorem is illustrated in Figure 5•8.
The Program Listing 5•15 implement the mixed thick plate formulation (θ-S-w) for heterosis element. The
deflection is exactly the same as those obtained from the irreducible formulation.
1. p. 75 in Zienkiewicz, O.C. and R.L. Taylor, 1991, “The finite element method”, 4th ed., vol. 2. McGraw-Hill, Inc., UK.
Figure 5•8 The equivalence of selective reduced integration of the shear constraint
terms of the irreducible formulation and mixed formulation with shear force nodes at
Gauss integration points. Both formulation use the heterosis element which uses
serendipity element for w and Lagrangian element for θ.
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) { Heterosis element; see Hughes[1987]
Ωθ; 9-node Lagrangian element
if(i == 0) {
int row_segment_no = 2;
int count = 0; Node *node; double v[2], h = 1.0/((double)(row_segment_no));
for(int j = 0; j < row_segment_no; j++) {
v[1] = ((double)j)*h;
for(int k = 0; k < (2*row_segment_no+1); k++) {
v[0] = ((double)k)*h/2; node = new Node(count++, 2, v); the_node_array.add(node);
}
v[1] += h/2.0;
for(int k = 0; k < (2*row_segment_no+1); k++) {
v[0] = ((double)k)*h/2; node = new Node(count++, 2, v); the_node_array.add(node);
}
}
v[1] = 1.0;
for(int j = 0; j < (2*row_segment_no+1); j++) {
v[0] = ((double)j)*h/2.0; node = new Node(count++, 2, v); the_node_array.add(node);
}
int ena[9]; Omega_eh *elem; count = 0;
for(int j = 0; j < row_segment_no; j++) for(int k = 0; k < row_segment_no; k++) {
int row_node_no = 2*row_segment_no+1, first_node = j*2*row_node_no+k*2;
ena[0] = first_node; ena[1] = ena[0]+2; ena[2] = ena[1]+2*row_node_no;
ena[3] = ena[2]-2; ena[4]=ena[0]+1;ena[5]=ena[1]+row_node_no;
ena[6]=ena[2]-1;ena[7]=ena[0]+row_node_no; ena[8] = ena[7] +1;
elem = new Omega_eh(count++, 0, 0, 9, ena); the_omega_eh_array.add(elem);
Kb matrix; θ-field
if(gd.type() == theta_type) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), Zai, Eta, 3x3 Gauss integration for bending
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 9, 2, qp);
Zai &= Z[0]; Eta &= Z[1];
Lagrangian shape functions for θ dof
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;
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, nsd, Nx), Wx, Wy, B;
Wx &= W_x[0][0]; Wy &= W_x[0][1];
B &= (~Wx || C0(0.0)) &
(C0(0.0) || ~Wy ) & Kb = ∫ ( LNθ ) T DLNθ dΩ
(~Wy || ~Wx ); Ω
stiff &= (~B)*(D*B) | dV;
} else if(gd.type() == S_type) {
H matrix; S-field
Quadrature qp(2, 4);
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.0-Zai)*(1.0-Eta)/4.0; N[1] = (1.0+Zai)*(1.0-Eta)/4.0; bilinear corner node shape function for
N[2] = (1.0+Zai)*(1.0+Eta)/4.0; N[3] = (1.0-Zai)*(1.0+Eta)/4.0; coordinate transformation
C0 x = MATRIX("int, int, C0&, int, int", 4, 2, xl, 4, 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), n0, n1, n2, n3, 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; S-shape functions:
n0 &= n[0]; n1 &= n[1]; n2 &= n[2]; n3 &= n[3]; bilinear four Gauss point nodes
H0 N_S = (( n0 | zero | n1 | zero | n2 | zero | n3 | zero ) &
(zero | n0 | zero | n1 | zero | n2 | zero | n3 ));
stiff &= MATRIX("int, int", 16, 16);
H = – ∫ N ST --- N S dΩ
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 8, 8, stiff, 0, 0);
1
stiff_sub = -( ((~N_S) * N_S) | dv)/alpha_; α
Ω
}
}
Element_Formulation_Couple* Plate_Heterosis::make(
int en, Global_Discretization_Couple& gdc) { return new Plate_Heterosis(en,gdc); }
Plate_Heterosis::Plate_Heterosis(int en, Global_Discretization_Couple& gdc) :
Element_Formulation_Couple(en, gdc) {
if(gdc.type() == S_theta_type) { C matrix; S-θ couple
Quadrature qp(2, 9);
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]; bilinear corner node shape function for
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;
coordinate transformation
C0 x = MATRIX("int, int, C0&, int, int", 4, 2, xl, 4, 0);
H1 X = N*x;
J dv(d(X).det());
θ-shape functions:
nt0, nt1, nt2, nt3, nt4, nt5, nt6, nt7, nt8;
nt[0] = (1-zai)*(1-eta)/4; nt[1] = (1+zai)*(1-eta)/4;
nt[2] = (1+zai)*(1+eta)/4; nt[3] = (1-zai)*(1+eta)/4; Lagrangian shape function
nt[8] = (1-zai.pow(2))*(1-eta.pow(2));
nt[0] -= nt[8]/4; nt[1] -= nt[8]/4; nt[2] -= nt[8]/4; nt[3] -= nt[8]/4;
nt[4] = ((1-zai.pow(2))*(1-eta)-nt[8])/2; nt[5] = ((1-eta.pow(2))*(1+zai)-nt[8])/2;
nt[6] = ((1-zai.pow(2))*(1+eta)-nt[8])/2; nt[7] = ((1-eta.pow(2))*(1-zai)-nt[8])/2;
nt[0] -= (nt[4]+nt[7])/2; nt[1] -= (nt[4]+nt[5])/2;
nt[2] -= (nt[5]+nt[6])/2; nt[3] -= (nt[6]+nt[7])/2;
nt0 &= nt[0]; nt1 &= nt[1]; nt2 &= nt[2]; nt3 &= nt[3]; nt4 &= nt[4];
nt5 &= nt[5]; nt6 &= nt[6]; nt7 &= nt[7]; nt8 &= nt[8];
H0 N_theta=((nt0|zero|nt1|zero|nt2|zero|nt3|zero|nt4|zero|nt5|zero|nt6|zero|nt7|zero|nt8|zero)& Nθ
(zero|nt0|zero|nt1|zero|nt2|zero|nt3|zero|nt4|zero|nt5|zero|nt6|zero|nt7|zero|nt8));
stiff &= MATRIX("int, int", 16, 18);
C0 stiff_sub = MATRIX("int, int, C0&, int, int", 8, 18, stiff, 0, 0); C = – ∫ N ST N θ dΩ
stiff_sub = -( ((~N_S) * N_theta) | dv);
Ω
} else if(gdc.type() == w_S_type) {
Quadrature qp(2, 9);
H1 Z(2, (double*)0, qp), , Zai, Eta E matrix; w-S couple
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 8, 2, qp); w shape function:
Zai &= Z[0]; Eta &= Z[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (1+Zai)*(1-Eta)/4; serendipity shape functions
N[2] = (1+Zai)*(1+Eta)/4; N[3] = (1-Zai)*(1+Eta)/4;
N[4] = (1-Zai.pow(2))*(1-Eta)/2; N[5] = (1-Eta.pow(2))*(1+Zai)/2;
N[6] = (1-Zai.pow(2))*(1+Eta)/2; N[7] = (1-Eta.pow(2))*(1-Zai)/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;
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/*nsd*/, Nx), Wx, Wy, grad_W;
Wx &= W_x[0][0]; Wy &= W_x[0][1];
grad_W &= (~Wx) & ∇w
(~Wy);
double sqrt3 = sqrt(3.0);
C0 zero(0.0);
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4, qp), n0, n1, n2, n3, zai, eta;
zai &= ((H0)Z)[0]; eta &= ((H0)Z)[1]; S-shape functions:
n[0] = (1.0-sqrt3*zai)*(1.0-sqrt3*eta)/4.0; n[1] = (1.0+sqrt3*zai)*(1.0-sqrt3*eta)/4.0; bilinear four Gauss point nodes
n[2] = (1.0+sqrt3*zai)*(1.0+sqrt3*eta)/4.0; n[3] = (1.0-sqrt3*zai)*(1.0+sqrt3*eta)/4.0;
n0 &= ((H0)n)[0]; n1 &= ((H0)n)[1]; n2 &= ((H0)n)[2]; n3 &= ((H0)n)[3];
H0 n_S = (n0|zero|n1|zero|n2|zero|n3|zero) & NS
(zero|n0|zero|n1|zero|n2|zero|n3);
stiff &=MATRIX("int, int", 8, 16);
C0 stiff_sub=MATRIX("int, int, C0&, int, int", 8, 8, stiff, 0, 0); E = ∫ ( ∇Nw )T NS dΩ
stiff_sub = ( (~grad_W) * n_S) | dv; Ω
double f_0 = 1.0;
force &= (((H0)N)*f_0) | dv;
} fw = ∫ NwT q dΩ
} Ω
Element_Formulation* Element_Formulation::type_list = 0;
static Element_Type_Register element_type_register_instance;
static Plate_Heterosis plate_heterosis_instance(element_type_register_instance);
θ
const int theta_ndf = 2;
Omega_h_i oh_theta(0);
gh_on_Gamma_h_i theta_gh(0, theta_ndf, oh_theta);
U_h theta_h(theta_ndf, oh_theta);
Global_Discretization theta_gd(oh_theta, theta_gh, theta_h, theta_type);
const int S_ndf = 2; S
Omega_h_i oh_S(1);
gh_on_Gamma_h_i S_gh(1, S_ndf, oh_S);
U_h S_h(S_ndf, oh_S);
Global_Discretization S_gd(oh_S, S_gh, S_h, S_type);
const int w_ndf = 1; w
Omega_h_i oh_w(2);
gh_on_Gamma_h_i w_gh(2, w_ndf, oh_w);
U_h w_h(w_ndf, oh_w);
Global_Discretization w_gd(oh_w, w_gh, w_h); S-θ
Global_Discretization_Couple gdc_S_theta(S_gd, theta_gd, S_theta_type);
w−S
Global_Discretization_Couple gdc_w_S(w_gd, S_gd, w_S_type);
Matrix_Representation mr_theta(theta_gd); Matrix_Representation mr_S(S_gd);
Matrix_Representation_Couple mrcE(gdc_w_S,0, 0,&(mr_S.rhs()),&mr_S);
Matrix_Representation_Couple mrcC(gdc_S_theta,0,
&(mr_S.rhs()),&(mr_theta.rhs()), &mr_theta);
mr_theta.assembly();
mr_S.assembly();
mrcC.assembly();
Kb ,
mrcE.assembly();
C0 K = ((C0)(mr_theta.lhs())), H,
H = ((C0)(mr_S.lhs())), C,
C = ((C0)(mrcC.lhs())),
fθ
f_theta = ((C0)(mr_theta.rhs())),
E = ((C0)(mrcE.lhs())), E
f_S = ((C0)(mr_S.rhs())), fS
f_w = ((C0)(mrcE.rhs()));
fw
Cholesky dK(K);
C0 K_inv = dK.inverse(),
CK_inv = C*K_inv,
A = H-CK_inv*(~C);
Cholesky dnA(-A);
C0 A_inv = -(dnA.inverse()),
EA_inv = E*A_inv, ŵ =
EA_invEt = EA_inv*(~E);
(EA-1ET)-1(EA-1fS - EA-1CKb-1fθ−fw)
Cholesky dnEA_invEt(-EA_invEt); ˆ
C0 w = -(dnEA_invEt*( E*-(dnA*f_S) - E*-(dnA*(C*(dK*f_theta))) -f_w) ), S = A-1(fS−ET ŵ −CKb-1fθ)
S = -(dnA*(f_S-(~E)*w-C*(dK*f_theta))),
theta = dK*(f_theta-(~C)*S);
theta_h = theta;
θ̂ = Kb-1(fθ-CT Sˆ )
theta_h = theta_gd.gh_on_gamma_h();
cout << "rotation (theta_x, theta_y):" << endl;
for(int i = 0; i < theta_h.total_node_no(); i++) cout << theta_h[i] << endl;
S_h = S;
S_h = S_gd.gh_on_gamma_h();
cout <<"shear force S:" << endl << S_h << endl;
w_h = w;
w_h = w_gd.gh_on_gamma_h();
cout << "deflection w:" << endl << w_h << endl;
return 0; }
Listing 5•15 Heterosis element for θ-S-w mixed thick plate formulation (project: “mixed_thick_plate” in
project workspace file “fe.dsw”).
S = α [ ∇w – θ ] Eq. 5•201
For a rectangular plate with edges parallel to x and y axis (Figure 5•9a), these constraints, on the mid-side nodes
of an element boundaries, can be easily computed from bilinear four-node shape functions for both θ and w as 1
w 1 – w 0 θx + θ x
0 1
ˆ4
S x = α ------------------- – ------------------
a 2
w2 – w 1 θy + θy
1 2
ˆ5
S y = α ------------------- – ------------------
b 2
w2 – w 3 θx + θx
2 3
ˆ6
S x = α ------------------- – ------------------
a 2
w 3 – w0 θy + θy
3 0
ˆ7
S y = α ------------------- – ------------------ Eq. 5•202
b 2
3 6
2
NS
x
4 = (1−η)/2
b 7 5
NS 5 = (1+ξ)/2
y
1
0 4 NS 6 = (1+η)/2
x
a
: θ and w : Sx : Sy
NS
y
7 = (1−ξ)/2
(a)
(b)
Figure 5•9 Discrete Reissner-Mindlin method for rectangular element with bilinear four-node
shape functions for both θ and w, and four shear constraints enforced on the element boundaries.
1. p.87-88 in Zienkiewicz, O.C., and R.L. Taylor, 1991, “ The finite element method: solid and fluid mechanics, dynamics,
and non-linearity”, 4-th eds., McGraw-Hill Inc., UK.
S = α [ Q w ŵ – Q θ θ̂ ]
ˆ
Eq. 5•203
where
–1 1 –1 –1
------ --- 0 0 ------ 0 ------ 0 0 0 0 0
a a 2 2
1 –1 –1 –1
0 --- ------ 0 0 0 0 ------ 0 ------ 0 0
b b 2 2
Qw = , Qθ = Eq. 5•204
1 –1 –1 –1
0 0 --- ------ 0 0 0 0 ------ 0 ------ 0
a a 2 2
1 –1 –1 –1
--- 0 0 ------ 0 ------ 0 0 0 0 0 ------
b b 2 2
S =NS Sˆ with NS shape functions for these four mid-side nodes are shown in Figure 5•9(b). The matrix form of
the problem becomes
T
K ww K wθ ŵ fw
= Eq. 5•205
K wθ K θθ θ̂ fθ
where
fw and fθ are the same as those defined in the irreducible formulation. The Program Listing 5•16 implements the
discrete Reissner-Mindlin formulation in the above. The center deflection for this bilinear four-node element
with discrete shear constraints is 325634, which is greater than the analytical solution for the thin-plate theory of
226800.
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
EP::element_pattern EP::ep = EP::QUADRILATERALS_4_NODES; Ωθ & Ωw; bilinear 4-node element
static int row_node_no = 9; static int col_node_no = row_node_no;
Omega_h_i::Omega_h_i(int i) : Omega_h(0) {
if(i == 0 || i == 1) {
double x[4][2] = {{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}};
int control_node_flag[4] = {1, 1, 1, 1};
block(this, row_node_no, col_node_no, 4, control_node_flag, x[0]);
}
}
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);
boundary conditions
if(i == 0) {
for(int j = 0; j < row_node_no; j++) {
for(int k = 0; k < df; k++) {
the_gh_array[node_order((j+1)*row_node_no-1)](k) =
the_gh_array[node_order(row_node_no*(row_node_no-1)+j)](k) =
gh_on_Gamma_h::Dirichlet;
}
the_gh_array[node_order(j)](1) = gh_on_Gamma_h::Dirichlet;
the_gh_array[node_order(j*row_node_no)](0) = gh_on_Gamma_h::Dirichlet;
}
} else if(i == 1) {
for(int j = 0; j < 9; j++) {
the_gh_array[node_order((j+1)*row_node_no-1)](0) =
the_gh_array[node_order(row_node_no*(row_node_no-1)+j)](0) =
gh_on_Gamma_h::Dirichlet;
}
}
}
static Global_Discretization *w_type = new Global_Discretization;
static Global_Discretization *theta_type = new Global_Discretization;
class Plate_Discrete_Reissner_Mindlin : public Element_Formulation_Couple {
public:
Plate_Discrete_Reissner_Mindlin(Element_Type_Register a) :
Element_Formulation_Couple(a) {}
Element_Formulation *make(int, Global_Discretization&);
Plate_Discrete_Reissner_Mindlin(int, Global_Discretization&);
Element_Formulation_Couple *make(int, Global_Discretization_Couple&);
Plate_Discrete_Reissner_Mindlin(int, Global_Discretization_Couple&);
};
Element_Formulation* Plate_Discrete_Reissner_Mindlin::make( int en,
Global_Discretization& gd) { return new Plate_Discrete_Reissner_Mindlin(en,gd); }
static const double E_ = 1.0; static const double v_ = 0.25;
static const double t_ = 0.01;
static const double D_ = E_ * pow(t_,3) / (12.0*(1-pow(v_,2)));
static const double Dv[3][3] = { 1 ν 0
{D_, D_*v_, 0.0 }, Et 3 ν 1 0
{D_*v_, D_, 0.0 }, D = -------------------------
{0.0, 0.0, D_*(1-v_)/2.0} 12 ( 1 – ν 2 ) 1–ν
0 0 ------------
}; 2
C0 D = MATRIX("int, int, const double*", 3, 3, Dv[0]);
static const double mu_ = E_/(2*(1+v_));
static const double alpha_ = (5.0/6.0)*mu_*t_;
}
stiff &= ( ( ((~Q_w)*n)*((~n)*Q_w) ) | dv )/alpha_; K ww = ∫ ( NS Qw )T αNS Qw dΩ
} Ω
Element_Formulation_Couple* Plate_Discrete_Reissner_Mindlin::make(int en,
Global_Discretization_Couple& gdc) {
return new Plate_Discrete_Reissner_Mindlin(en,gdc);
}
Plate_Discrete_Reissner_Mindlin::Plate_Discrete_Reissner_Mindlin(int en,
Global_Discretization_Couple& gdc) : Element_Formulation_Couple(en, gdc) {
Quadrature qp(2, 4);
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.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;
H1 X = N*xl; J dv(d(X).det()); S-shape functions:
H0 n = INTEGRABLE_VECTOR("int, Quadrature", 4, qp), zai, eta; NS
zai = ((H0)Z)[0]; eta &= ((H0)Z)[1];
n[0] = (1-eta)/2.0; n[1] = (1+zai)/2.0; n[2] = (1+eta)/2.0; n[3] = (1-zai)/2.0;
t0 = n σ0 Eq. 5•209
where n is the outward unit surface normal at the point x0 on subdomain Ω0. Since the outward unit surface nor-
mal at the point x1 on subdomain Ω1 is opposite in direction to n. We also have
t1 = (- n) σ1 Eq. 5•210
Because we assumed the contact is frictionless, only the normal component of the tractions, t 0 • n = – t 1 • n ≡ λ ,
on the contact surface are required to be in equilibrium according to Newton’s third law of motion. The contact
conditions on contact surface Γc is2
0
g ≡ [ u1 – u 0 ] • n + g = 0 ⇒ t0 • n = – t1 • n < 0
0
g ≡ [ u1 – u 0 ] • n + g > 0 ⇒ t 0 • n = –t 1 • n = 0 Eq. 5•211
where “g” is the “gap” between the two bodies, and “g0” is the initial gap. In constraint optimization (see Eq.
2•14 in Chapter 2), Eq. 5•211 can be concisely written as the Kuhn-Tucker condition
g λ = 0, λ ≤ 0, g ≥ 0 Eq. 5•212
We note that λ, the normal component of the tractions, also plays the role of the Lagrange multipliers in the con-
text of constraint optimization problem. The geometry of contact element is shown in Figure 5•10. The node
number “8”, with coordinates x11, is projected to its opposite boundary on x0. The segment length proportional
parameter α is computed from
1. see p. 63 in Fung Y.C., 1965, “Foundations of solid mechanics”, Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
2. Simo, J.C. Wriggers, P., and R.L.Taylor, 1985, “A perturbed Lagrangian formulation for the finite element solution of
contact problem”, Computer Methods in Applied Mechanics and Engineering, vol. 50, p. 163-180, Elsevier Science Publish-
ers, North-Holland.
9x1
nodes
6 Ω1 x11 1
projected x10
7
nodes
n0 8
y2
contact element n1
1 numbers 0 5
1 2 4 y1
3 4x 1
unit surface 3 0
normal 1 x00 x00 5
2
Ωi domains 0
Ω0 αl
l = ||x01-x00||
Figure 5•10 Contact element geometry. Six contact line elements are formed
through projection of real nodes onto the boundary of the opposite boundaries.
( x 10 – x 00 ) • ( x 01 – x 00 )
α = -------------------------------------------------- Eq. 5•213
x 01 – x 00
and the coordinates of the projected point x00, and displacement on the projected node u0 can be linearly interpo-
lated from the level rule as
0
x 0 = ( 1 – α )x 00 + αx 01, and u 0 = ( 1 – α )u 00 + αu 01 Eq. 5•214
For the contact element number “5” in Figure 5•10 we recognize that, on Ω0, the node numbers “3”, “4”, in glo-
bal node numbering, are involved in the element. The contact element node on Ω0 associated with the current
element number “5” has the coordinates of {x00, x01}. The displacement associated with these two nodes is
denoted as u = [u00, u01]T which is related to the displacement of “real” nodes (global node numbers “3” and “4”,
0 1
and redefined as local element node number “0” and “1”) û = [ û 0 , û0 ]T by the same level rule as
0 0
u0 ( 1 – α 0 )n 0 α0 n0 û 0
u= = = cû Eq. 5•215
u0
1 α1 n1 ( 1 – α 1 )n 1 û 1
0
where α0 for node number “3” is computed from Eq. 5•213, and α1= 0 (consistent with Eq. 5•213) for node num-
ber “4” which is not a projected node. The initial gap, g0, and the tangent vector, s, along boundary Γ34 are
0 ( x 01 – x 00 )
g = x 10 – x 0 , s = ---------------------
- Eq. 5•216
x 01 – x 00
The outward unit surface normal vector, n0, is defined from rotating the tangent vector 90o counter-clockwise
π π
cos --- sin --- s
2 2 x
n0 = Rs = = [sy, -sx]T Eq. 5•217
π π sy
– sin --- cos ---
2 2
The Lagrangian functional to the contact problem is (with domain index i = 0, 1)
The Euler-Lagrange equations are obtained by taking the directional derivatives of Lagrangian functional with
respect to ui and λ, then, set to zero.
∫ δ λT { [ u2 – u1 ] • n + g 0 } dΓ = 0 Eq. 5•220
Γc
The first three terms in Eq. 5•219 are the same as the standard irreducible formulation. The last term in Eq.
5•219 and Eq. 5•220 are needed for the contact formulation. The Lagrangian multiplier and the displacement (on
the contact elements) are approximated as linear line element from their nodal values (with “hat”)
where N ua ≡ N a c ; i.e., the projected displacement u of contact nodes is related to u of global nodes by Eq. 5•215.
The off-diagonal element stiffness submatrices in the mixed formulation of Eq. 5•219 and Eq. 5•220 are
Eq. 5•222 adds nothing new from mixed formulation point of view. What is new to the program is we need to
feed the information, at the element level, on the corresponding λ and u on domain Ω0 and Ω1 that are associ-
ated with the particular contact segment.
1 int ndf = 2;
2 Omega_h_i elastic_foundation_oh(0); // elastic foundation; Ω elastic foundation
3 gh_on_Gamma_h_i elastic_foundation_gh(0, ndf, elastic_foundation_oh);
4 U_h u_0(ndf, elastic_foundation_oh); // uelastic foundation
5 Global_Discretization *elastic_foundation_type = new Global_Discretization();
6 Global_Discretization
7 elastic_foundation_gd(elastic_foundation_oh, elastic_foundation_gh, u_0,
8 elastic_foundation_type);
9 Gamma_h_i // potential contact segment; Γelastic founcation
10 elastic_foundation_gamma_h(0, elastic_foundation_oh);
11 Global_Discretization_Gamma_h_i
12 elastic_foundation_gamma_h_gd(0, elastic_foundation_gd, elastic_foundation_type,
13 elastic_foundation_gamma_h);
where line 9 defines the potential contact surface for the elastic foundation with a new class Gamma_h_i for Γi .
The Gamma_h_i class does not have variables of its own. The Global_Discretization of this class,
Global_Discretization_Gamma_h_i, uses the variable u_0 instantiated for the Ωi. The following lines define the
rigid punch (the upper part) in a similar manner.
B.C.
rigid punch problem v = -2
(a)
8 9 10 11 E = 1.e10
(B.C for the next section ν = 0.5
on rigid sled problem 4 5 6 7
4 u = 0.2 t)
0 1 2 3
14 15 16 17 18 19 20
7 8 9 10 11 12 13
20
E = 1.e5
ν = 0.5
0 1 2 3 4 5 6
60
15 0 16 1 17 2 18 3 19 4
Ωelastic foundation
Γelastic foundation
Figure 5•11 Frictionless contact problem with rigid punch (or sled) on top an elastic foundation.
1 Global_Discretization_Couple *interface_elastic_foundation_gamma_h_type
2 = new Global_Discretization_Couple();
3 Global_Discretization_Couple // {Γc-Γelastic founcation}
4 interface_elastic_foundation_gdc(interface_gd, elastic_foundation_gamma_h_gd,
5 interface_elastic_foundation_gamma_h_type);
6 Global_Discretization_Couple *interface_rigid_punch_gamma_h_type
7 = new Global_Discretization_Couple();
8 Global_Discretization_Couple // {Γc-Γrigid punch}
9 interface_rigid_punch_gdc(interface_gd, rigid_punch_gamma_h_gd,
10 interface_rigid_punch_gamma_h_type);
The contact element domain (Ωeh)c is defined as a new C++ class “Contact_Omega_eh” derived from class of
element domain Ωeh as
The public inheritance relationship makes the class of contact element domain inherits what is available in the
class of element domain. In addition, the derived class is equipped with new private data which define what
boundary elements on the surrounding bodies are associated with the contact element domain. For contact ele-
ment number 3 in Figure 5•11b, the associated elements to the domain from the lower body is the boundary ele-
ment number 2, and from the upper body is the boundary element number 1. A contact element domain for
contact element number 3 is defined inside the constructor of class Omega_h_i as (see also Eq. 5•12)
Ω1
1
α11 = 0
α10=1/2
n1
3 4
n0 3
α01 =1/2
α00 = 0 2
Ω0
Figure 5•12 Details of the contact element number “3”.
1 int ena[2];
2 ena[0] = 3; ena[1] = 4;
3 Omega_eh *elem = new Omega_eh(3, 0, 0, 2, ena); // store standard element information
4 int aen[2]; // associated element number array
5 aen[0] = 2; aen[1] = 1;
6 double pp[4], nv[4]; // projection parameters and unit normals
7 pp[0] = 0.0; pp[1] = 0.5; pp[2] = 0.5; pp[3] = 0.0; // α00, α01 (lower), and α10, α11 (upper)
8 nv[0] = 0.0; nv[1] = -1.0; // n0 = [n0x, n0y]T
9 nv[2] = 0.0; nv[3] = 1.0; // n1 = [n1x, n1y]T
10 Contact_Omega_eh *c_elem = new Contact_Omega_eh(aen, pp, nv, elem); // contact element
11 omega_eh_array().add(c_elem); // element array
The associated element number array supplies the element numbers of the lower and the upper boundary associ-
ated with the contact element number “3”. The element number for the lower boundary is “2”, and the upper ele-
ment number for the upper boundary is “1”. That is, in line 5,
aen[0] = 2; aen[1] = 1;
This information is needed for the contact element, so the contact element will know which real nodes are asso-
ciated with the contact element. The projection parameters, α00 and α01, for the lower boundary nodes are store
in pp[0] and pp[1]. The first node on the lower boundary associated with the contact element number 3 is the ele-
ment number 17 which is a real node α00 = 0. The second node is a projection node in the middle of element
number 17 and 18. Therefore, the projection parameter α01 = 0.5. Alternatively, we can use Eq. 5•213 to com-
pute the value of α when the geometrical condition becomes more complicated. α10 and α11 for the upper
boundary can be computed similarly. The first node again lies in the middle of node number “1” and node num-
ber “2” of the upper boundary. The projection parameter α10 = 0.5. The second node on the upper boundary is a
real node number “2” of the upper boundary and we have α11 = 0. We write in line 7
Figure 5•13 Rigid punch on elastic foundation. The punch has been pushed down 2
unit.
#include "include\fe.h"
#include "include\omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
#include "include\global_discretization_gamma_h_n.h"
class Contact_Omega_eh : public Omega_eh {
int the_associate_element[2]; defininig class of a contact element
double the_projection_parameter[4]; domain
double the_normal_vector[4];
public:
Contact_Omega_eh(int* ae, double* pp, double* nv, Omega_eh& oh) : Omega_eh(oh) {
for(int i = 0; i < 2; i++) the_associate_element[i] = ae[i];
for(int i = 0; i < 4; i++) the_projection_parameter[i] = pp[i];
for(int i = 0; i < 4; i++) the_normal_vector[i] = nv[i];
}
int* associate_element() { return the_associate_element; }
double* projection_parameter() { return the_projection_parameter; }
double* normal_vector() { return the_normal_vector; }
};
static const double E_[2] = {1.e5, 1.e10}; Young’s moduli
static const double v_ = (0.5-1.e-12); Poisson ratios
static const double lambda_[2] = { v_*E_[0]/((1+v_)*(1-2*v_)),
v_*E_[1]/((1+v_)*(1-2*v_))};
static const double mu_[2] = {E_[0]/(2*(1+v_)), shear moduli
E_[1]/(2*(1+v_))};
static const double lambda_bar[2] = {2*lambda_[0]*mu_[0]/(lambda_[0]+2*mu_[0]),
2*lambda_[1]*mu_[1]/(lambda_[1]+2*mu_[1])}; λ
Omega_h_i::Omega_h_i(int i) : Omega_h(0){
if(i == 0) { elastic foundation; Ωelastic founcation
double v[2]; Node *node;
v[0] = -30.0; v[1] = -20.0; node = new Node(0, 2, v); node_array().add(node); define nodes
v[0] = -16.0; node = new Node(1, 2, v); node_array().add(node);
v[0] = -8.0; node = new Node(2, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(3, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(4, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(5, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(6, 2, v); node_array().add(node);
v[0] = -30.0; v[1] = -8.0; node = new Node(7, 2, v); node_array().add(node);
v[0] = -16.0; node = new Node(8, 2, v); node_array().add(node);
v[0] = -8.0; node = new Node(9, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(10, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(11, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(12, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(13, 2, v); node_array().add(node);
v[0] = -30.0; v[1] = 0.0; node = new Node(14, 2, v); node_array().add(node);
v[0] = -16.0; node = new Node(15, 2, v); node_array().add(node);
v[0] = -8.0; node = neww Node(16, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(17, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(18, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(19, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(20, 2, v); node_array().add(node);
int ena[4]; Omega_eh *elem;
ena[0] = 0; ena[1] = 1; ena[2] = 8; ena[3] = 7; define elements
elem = new Omega_eh(0, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 1; ena[1] = 2; ena[2] = 9; ena[3] = 8;
elem = new Omega_eh(1, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 3; ena[2] = 10; ena[3] = 9;
elem = new Omega_eh(2, 0, 1, 4, ena); omega_eh_array().add(elem);
Contact node# 0 1 2 3 4 5 6
Γelastic founcation 0 -1 1 -1 2 -1 3
Γrigid sled -1 16 -1 17 -1 18 -1
TABLE5• 2. Contact node number table.
What is not shown in the present example is, if for a particular contact node number both cells contain the
default value “-1” it means that there is a detachment segment along the contact surface. This situation occurred
either there is no node project onto certain segments or the projection form a gap that is beyond a pre-defined
tolerance value. If both cell contains no default values, that is the case when the node on one side are projected
to the node on the other side within a tolerance distance. The contact searching algorithm is to (1) construct
TABLE5• 2. automatically, then (2) use this table to define contact nodes and contact elements. The second part
is straight forward, since we have the manual input experience gained from the rigid punch problem in the previ-
ous section. We focus on the first part. The basic idea is to scan through the contact surface Γc to find a leading
node from either side of the potential contact boundaries Γi . The leading node is the first node encountered that
is successful projected to the opposite boundary segment. For example, if we are now in the middle of the pro-
cess at the contact node number 2, the next leading node that can be successfully project to the opposing Γi is
node number 17 on the Γelastic foundation. Successive leading nodes are filled in to the rows that they are corre-
sponding to, and leave the opposite row with the default value (-1) which indicates a projected node. Inspecting
on yet another example in Figure 5•10, we find that the leading node is not necessary always alternating on rows
in their appearance on the contact searching number table as in TABLE5• 2. In general, they may appear consec-
Then the projection of a node onto its opposite target segment is successful, on condition that the gap as com-
puted from Eq. 5•211 between the current node and the projected node is within a tolerance value. In a special
condition, when α is very close to 0 or 1 and the distance between the projected node and the ends of the target
segment is small, we have a node-on-node projection situation. These functions are implemented in the same file
“contact_searching.cpp” under its “geometrical utilities” section.
The contact searching algorithm should be invoked upon every iteration. The Q matrix will be changed
accordingly. The rigid sled is push from left to the right for 8 steps with incremental displacement of ∆v = 0.2;
i.e., vt = ∆v t ( where t = 0, 8). The Program implements the frictionless sled on elastic foundation problem. The
Program Listing 5•18 implements the frictionless rigid punch problem. The solution of this problem is shown in
Figure 5•14.
t=2
t=5
t=8
#include "vs.h"
#include "fe.h"
#include "omega_h_n.h"
Matrix_Representation_Couple::assembly_switch
Matrix_Representation_Couple::Assembly_Switch = Matrix_Representation_Couple::ALL;
#include "global_discretization_gamma_h_n.h"
#include "contact_searching.h"
static const double E_[2] = {1.e5, 1.e10}; static const double v_ = (0.5-1.e-12); Young’s moduli
static const double lambda_[2] = {v_*E_[0]/((1+v_)*(1-2*v_)), v_*E_[1]/((1+v_)*(1-2*v_))}; Poisson ratios
static const double mu_[2] = {E_[0]/(2*(1+v_)), E_[1]/(2*(1+v_))}; shear moduli
static const double lambda_bar[2] =
{2*lambda_[0]*mu_[0]/(lambda_[0]+2*mu_[0]),2*lambda_[1]*mu_[1]/(lambda_[1]+2*mu_[1])}; λ
Omega_h_i::Omega_h_i(int i) : Omega_h(0){
the_index = i;
if(i == 0) {
double v[2]; Node *node; elastic foundation; Ωelastic founcation
v[0] = -30.0; v[1] = -20.0; node = new Node(0, 2, v); node_array().add(node); define nodes
v[0] = -16.0; node = new Node(1, 2, v); node_array().add(node);
v[0] = -8.0; node = new Node(2, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(3, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(4, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(5, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(6, 2, v); node_array().add(node);
v[0] = -30.0; v[1] = -8.0; node = new Node(7, 2, v); node_array().add(node);
v[0] = -16.0; node = new Node(8, 2, v); node_array().add(node);
v[0] = -8.0; node = new Node(9, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(10, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(11, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(12, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(13, 2, v); node_array().add(node);
v[0] = -30.0; v[1] = 0.0; node = new Node(14, 2, v); node_array().add(node);
v[0] = -16.0; node = new Node(15, 2, v); node_array().add(node);
v[0] = -8.0; node = new Node(16, 2, v); node_array().add(node);
v[0] = 0.0; node = new Node(17, 2, v); node_array().add(node);
v[0] = 8.0; node = new Node(18, 2, v); node_array().add(node);
v[0] = 16.0; node = new Node(19, 2, v); node_array().add(node);
v[0] = 30.0; node = new Node(20, 2, v); node_array().add(node);
int ena[4]; Omega_eh *elem; define elements
ena[0] = 0; ena[1] = 1; ena[2] = 8; ena[3] = 7;
elem = new Omega_eh(0, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 1; ena[1] = 2; ena[2] = 9; ena[3] = 8;
elem = new Omega_eh(1, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 2; ena[1] = 3; ena[2] = 10; ena[3] = 9;
elem = new Omega_eh(2, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 3; ena[1] = 4; ena[2] = 11; ena[3] = 10;
elem = new Omega_eh(3, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 4; ena[1] = 5; ena[2] = 12; ena[3] = 11;
elem = new Omega_eh(4, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 5; ena[1] = 6; ena[2] = 13; ena[3] = 12;
elem = new Omega_eh(5, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 7; ena[1] = 8; ena[2] = 15; ena[3] = 14;
elem = new Omega_eh(6, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 8; ena[1] = 9; ena[2] = 16; ena[3] = 15;
elem = new Omega_eh(7, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 9; ena[1] = 10; ena[2] = 17; ena[3] = 16;
elem = new Omega_eh(8, 0, 1, 4, ena); omega_eh_array().add(elem);
ena[0] = 10; ena[1] = 11; ena[2] = 18; ena[3] = 17;
elem = new Omega_eh(9, 0, 1, 4, ena); omega_eh_array().add(elem);
∫ NλT Nu
( zero | N_bar_0[1] | zero | N_bar_1[1] );
if(gdc.type() == interface_elastic_foundation_gamma_h_type) Q = dΓ ; where N ≡ Nc
u
stiff &= -(((~N_lambda)*N_u_bar)|d_l); Γc
else stiff &= (((~N_lambda)*N_u_bar)|d_l); Q0 {Γc-Γelastic founcation}
}
} Q1 {Γc-Γrigid punch}
Element_Formulation* Element_Formulation::type_list = 0;
Element_Type_Register element_type_register_instance;
static Elastic_Contact_Q4 elastic_contact_q4_instance(element_type_register_instance);
#include "\vs\ex\fe\contact_frictionless_sled_on_elastic_foundation\omega_h_n.cpp"
int main() {
C0 K_0, Q_0, K_1, Q_1, f_0, f_i, f_1, lambda, u_0, u_1;
interface_oh.contact_searching_algorithm(interface_oh, elastic_foundation_gamma_h_gd,
rigid_sled_gamma_h_gd, lambda_h, interface_gh, 0.05);
Matrix_Representation mr_K_0(elastic_foundation_gd);
Matrix_Representation mr_K_1(rigid_sled_gd);
Matrix_Representation_Couple mrc_Q_0(interface_elastic_foundation_gdc, 0, 0,
&(mr_K_0.rhs()) );
Matrix_Representation_Couple mrc_Q_1(interface_rigid_sled_gdc, 0, &(mrc_Q_0.rhs()),
&(mr_K_1.rhs()) );
for(int i = 0; i < 9; i++) {
mr_K_0.assembly(); K_0 &= (C0)(mr_K_0.lhs()); K0
mr_K_1.assembly(); K_1 &= (C0)(mr_K_1.lhs()); K1
mrc_Q_0.assembly(); Q_0 &= (C0)(mrc_Q_0.lhs()); Q0
mrc_Q_1.assembly(); Q_1 &= (C0)(mrc_Q_1.lhs());
f_0 &= (C0)(mr_K_0.rhs()); f_1 &= (C0)(mr_K_1.rhs()); f_i &= (C0)(mrc_Q_0.rhs()); Q1
Cholesky dK0(K_0); Cholesky dK1(K_1); f0, f1, fi
C0 K0_inv = dK0.inverse(); C0 QK_inv_0 = Q_0*K0_inv; C0 QKQ_0 = QK_inv_0*(~Q_0); K0-1, Q0 K0-1 Q0T
C0 K1_inv = dK1.inverse(); C0 QK_inv_1 = Q_1*K1_inv; C0 QKQ_1 = QK_inv_1*(~Q_1);
Cholesky mdQKQ(QKQ_0+QKQ_1, 1.e-12); K1-1, Q1 K1-1 Q1T
lambda &= mdQKQ * (QK_inv_0*f_0+QK_inv_1*f_1-f_i); (Q0 K0-1 Q0T + K1-1, Q1 K1-1 Q1T)-1
u_0 &= dK0*(f_0-(~Q_0)*lambda); u_1 &= dK1*(f_1-(~Q_1)*lambda); λ̂=(Q0 K0-1 Q0T + K1-1, Q1 K1-1 Q1T)-1
lambda_h = lambda; lambda_h = interface_gd.gh_on_gamma_h();
u_0_h = u_0; u_0_h = elastic_foundation_gd.gh_on_gamma_h(); (Q0 K0-1 f0 + Q1K1-1 f1 - fi)
u_1_h = u_1; u_1_h = rigid_sled_gd.gh_on_gamma_h(); û 0 = K0-1 (f0 - Q0Tλ̂)
cout << "contact forces:" << endl << lambda_h << "elastic foundation displacement:" << û 1 = K1-1 (f1 - Q1Tλ̂)
endl << u_0_h << "rigid sled displacement:" << endl << u_1_h;
if(i < 8) {
for(int j = 8; j < 12; j++) {
int node_order = rigid_sled_gd.gh_on_gamma_h().node_order(j);
rigid_sled_gd.gh_on_gamma_h().gh_array()[node_order][0] = ((double)(i+1));
}
cout << "step " << i << " :" << endl;
rigid_sled_gd.u_h() = rigid_sled_gd.gh_on_gamma_h();
interface_oh.contact_searching_algorithm(interface_oh, elastic_foundation_gamma_h_gd,
rigid_sled_gamma_h_gd, lambda_h, interface_gh,
mr_K_0, mr_K_1, mrc_Q_0, mrc_Q_1, 0.05);
}
}
return 0;
}
∂R
R ( û i + 1 ) = R ( û i + δ û i ) ≅ R ( û i ) + ------- δ û i = 0
∂û û i Eq. 5•224
where û i+1 = û i + δ û i. The solution of the non-linear problem is obtained by setting the residual vector to van-
ish; i.e., find the root for the equation R(ui+1) = 0. Notice that the approximation step in Eq. 5•224 is done by the
Taylor expansion up to the first-order. From this approximated equation, the incremental displacement δui is the
solution of the simultaneous linear algebraic equations
∂R – 1
δ û i = – ------- R ( û i ) ≡ K –T1 R ( û i ) Eq. 5•225
∂û û i
∂R
where K T ≡ –-------
∂û is the tangent stiffness matrix.
û
i
1. Simo and Taylor, 1985, “Consistent tangent operators for rate-independent elastoplasticity” in Computer
Methods in Applied Mechanics and Engineering, v. 48, p.101-118
2. Chapter 7 in Zienkiewicz and Taylor, 1991, “The finite element method”, 4th ed. v. 2, McGraw-Hill, UK.
Hence, the tangent stiffness matrix KT in Eq. 5•225 is obtained by taking the derivatives of R in Eq. 5•226 with
respect to the solution u as
∂R ∂σ T
-------
∂û
= –∑ ∫Ω BT ------
∂û
- B dΩ = – ∑ ∫Ω B DT B dΩ ≡ – K T Eq. 5•227
û i
e e ûi e e
where, DT ≡ ∂ Ψ ⁄ ∂ ε is the tangent moduli, with the Cauchy stress σ ≡ ∂Ψ ⁄ ∂ε and where Ψ is the free energy
2 2
function. With KT defined, the incremental displacement δui is readily obtained by solving δ û i = KT–1 R ( ûi ) .
Note that the tangent moduli is the second derivatives with respect to free energy function. The minimization is
–1
with respect to free energy Ψ, and the equation δ û i = KT R ( û i ) is equivalent to the Newton’s Formula for opti-
mization of a function f(x) as δx = - df / d 2f (obtained from second-order Taylor expansion), with x += δx for
solution update.
Incremental Loading Loop: At the outer incremental loop, enclosed in the “for” statement, the incremental load-
ing is added to the boundary at the beginning of each time step; i.e., at the first iteration (i = 0), δu0 is set to the
incremental boundary condition δu0 of the time step. This quantity is then given to the element level for the com-
putation of the residual (R). The residual is to be modified by the reaction caused by the incremental boundary
condition as R -= KTδu0.
For the stress-strain relation in plasticity, which is path-dependent, we also need to introduce total incremen-
tal displacement ∆ û = ∑ δ û (with k = 0,1, 2, ..., i). ∆ui is the “total increment”; the summation of all incre-
i k
mental displacement from the first iteration up to the current iteration within the current time step. This quantity
is updated at the global level in the “main()” function, and is referred to in the element level.
Global Newton-Raphson Iteration: The inner loop is the global Newton-Raphson iteration inside the do-while
control statement. The heart of the algorithm is the member function “Matrix_Representation::assembly()” which
performs three heavy-duty steps to be coded in the Element_Formulation. These three steps are (1) apply exter-
nal load (Fext in Eq. 5•226) and subtract the internal force divergence term as in Eq. 5•226. The details of these
three steps in the element level is in Section 5.3.2.
Listing 5•19 Incremental loading algorithm and the global Newton-Raphson iteration of the non-linear
problem
Theory of Elastoplasticity
Following the development in Simo and Taylor[1985]3 for the infinitesimal case, the deviatoric stress (s) and
deviatoric strain (e) tensors are defined as
with second-order unit tensor, 1, and the trace operator, tr( ). The von Mises yield criterion is
f ( ξ, α, κ ) ≡ ξ – 2- κ ( e p ) ≤ 0 , Eq. 5•229
3
∫
t
2
ep = -
3
d p ( τ ) dτ , Eq. 5•230
0
with ξ = s – α . where α is the back stress for the kinematic hardening. The kinematic hardening function κ(e p),
depends on plastic strain ep, is for the isotropic hardening, where dp is the plastic strain rate. The consistency
condition, or the normality rule, in the theory of plasticity requires that stress remains on the yield surface during
the plastic deformation. This is equivalent to assuming maximum plastic dissipation for a quasi-equilibrium pro-
cess in the context of irreversible thermodynamics. From the consistency condition, we get the deviatoric stress-
strain rate constitutive equation as
1
γ ≡ d p = -----------------------------
κ' + H’α
Eq. 5•232
1 + 3µ -------------------
µ is the shear modulus. n̂ = ξ TRn + 1 ⁄ ξ nTR+ 1 , where superscript “TR” denotes the trial elastic state. The primes
in κ and Hα denotes the first-derivative with respect to ep. The so-called continuum elastoplastic tangent moduli
·
ae p for the constitutive law σ = a : ε· in rate form is thus obtained as
ep
elastic predictor
sTRn+1
plastic corrector
sn sn+1
Yield Surface
where sn is obtained from stored data of the last time step, and superscript “TR” denotes the trial elastic state. We
also have
ξnTR+ 1 = s n + 1 – α n , and n̂ =
TR
ξ TR n + 1 ⁄ ξnTR+ 1 Eq. 5•235
where back stress αn is also obtained from stored data of the last time step.
Plastic-Corrector: The consistency condition requires the state of stress remains on yield surface during plastic
deformation. This leads to
φ ( γ ∆t ) ≡ – 2-3 κ ( e np + 1 ) + ξnTR+ 1 – 2µ γ ∆t + 2- ∆H α = 0 ,
3
Eq. 5•236
where the last two terms 2µγ∆t is the magnitude of plastic relaxation stress and 2 ⁄ 3 ∆Hα is the magnitude of
translation on “π-plane” of yield surface due to kinematic hardening with the “π-plane” proportional length-fac-
tor 2 ⁄ 3 considered. ep is integrated as
Define λ = γ∆t, the local Newton-Raphson iteration to enforce the consistency condition provides the Newton’s
formula for numerical root-finding on Eq. 5•236 as
the back stress and deviatoric stress are integrated for updating history data according to
αn + 1 = αn + -2 ∆H α ( enp + 1 ) n̂ , and s n + 1 =
3
αn + 1 + -2 κ ( enp + 1 ) n̂
3
Eq. 5•239
where,
[ κ n + 1 + ∆H α ] 1
β ≡ 2-3 -----------------------------------
- , and γ ≡ -------------------------------------------
[ κ' + H’ ]
- – (1 – β) = γ – (1 – β)
ξ TR
n+1 α n+1
Eq. 5•242
1 + ----------------------------------
3µ
We can check this formula by investigating that whether in the limit of infinitesimal incremental loading step,
the consistent tangent moduli does degenerate to the continuum tangent moduli; i.e., to have β = 1 , thus
γ = γ – ( 1 – β ) = γ . This follows immediately from the definitions of β and γ in Eq. 5•242.
where sn is obtained from history data. In order to get the trial deviatoric stress, we first need to compute the ele-
ment total incremental displacement (∆ û e = ∆ û +∆u, free plus fixed degree of freedom), and then total incre-
mental deviatoric strain (∆e = Bdev ∆ û e). Then, we can get to the 2µ∆e term in the elastic predictor (Eq. 5•243).
Note that Bdev is the deviatoric part of the B matrix. This trial state of elastic deviatoric stress (sTRn+1) may or
may not shoot out of the yield surface. This is inspected by checking the yield radius (R) against the norm of
ξTRn+1, where ξTRn+1 = sTRn+1 - αn. The back stress αn is obtained from the history data. If the norm of ξTRn+1 is
smaller than or equal to R, the state of stress remains inside the yield surface in the elastic state, we have sn+1 =
sTRn+1. Otherwise, the constraint is violated. The state of the stress is outside the yield surface and the plastic-cor-
rector follows.
The plastic-corrector is to return to the state of stress back to the yield surface—the consistency condition;
i.e., to satisfy φ ( λ ) ≡ – 2-3 κ ( e np + 1 ) + ξnTR+ 1 – 2 µλ + 2- ∆H α = 0 (with λ = γ∆t) in Eq. 5•236. With the Vector-
3
Space C++ Library, root-finding is very simple. Just declare C1 type variables and function for this equation. The
Newton iteration is furnished by the formula δ λ = – φ ( λ ) ⁄ d φ ( λ ) , with the solution updated by λ += δλ. The
C++ codes parallel the mathematical expression exactly. After we obtain the converged result form the local
Newton iteration, one can update s, α, and ep according to Eq. 5•237 and Eq. 5•239.
The consistent tangent moduli (Eq. 5•241) is readily obtained with all these parameters available. The
Cauchy stress is computed with averaged volumetric strain εv = Bvol û e = tr(ε)1, and then plug the volumetric
strain into the second term in the right-hand-side of Eq. 5•240. The rest of the Program Listing 5•20is the (tan-
gent) stiffness, and the residual. The stiffness is computed as defined in
T ep
∫B a B dΩ
Ωe
with B in place of the B for the B-formulation. The residual only needed to be computed for the non-linear prob-
lem, where we need to subtract the internal stress divergence term out of the “force” vector as
∫ B σ dΩ
T
Ωe
The implementation of the radial return mapping method is shown is Program Listing 5•20.
εv = Bvol û e = tr(ε)1
for(int i = 0; i < nen; i++)
eps_v += B_bar_vol_q(i*ndf)*ul[i*ndf] + B_bar_vol_q(i*ndf+1)*ul[i*ndf+1];
eps_v *= 3.0; σn+1 = sn+1 + K Ttr(ε) 1
stiffness += ∫ B a B dΩ
sigma_q = s_q + K_*eps_v; ep
}
stiff &= ((~B_bar)*Dt*B_bar)|dv; Ωe
∫ B σ dΩ
T
force &= -((~B_bar)*sigma)|dv; force -=
} Ωe
Listing 5•21 Radial return mapping alogrithm for the elastoplastic element.
δu = 0.01m
18 m
5m
5m
Figure 5•16 Perforated strip under uniaxial extension.
5.3.4 Perforated Strip under Uni-axial Extension
A benchmark test problem for elastoplasticity is shown in Figure 5•16. For the experimental results see Theo-
caris and Marketos[1964]1. The geometry and its boundary conditions are described below. Only a quadrant of
the problem is modeled due to the symmetry of the problem. Plain strain is assumed. The material properties are
Young’s Modulus E = 70 MPa, Poisson ratio ν = 0.2. The isotropic hardening law is given specifically as
where, Y0 = Y∞ = 0.243 MPa, ι = 0.1. No kinematic hardening is assumed, for simplicity. This test problem will
also be used in the two implementations of the finite deformation elastoplasticity in Section 5.4 for comparison.
The project “elastoplasticity” in project workspace file “fe.dsw” implements the example problem in this sec-
tion and the algorithm discussed in the last section. The yield ratio contours of the perforated strip after 10 incre-
mental loading steps are shown in Figure 5•17. The plastic zone is developed in area where the highest intensity
of the maximum shear values are expected. This zone runs about 45 o upwards from point A, forming a plastic
enclave. This direction is mostly parallel to the point-wise maximum shear directions inside this zone.
For the non-linear problem at hand, the iterative process requires the “matrix assembly” and “solution phase”
been processed many times, comparing to a linear problem where this process is only go thourgh once. There-
fore, the computing time becomes a concern for us. However, the computing time is very sensitive to the size of
the problem. We use “n” to represent the size of a problem, which may stand for total node/element number of a
problem. The element formulation in the assembly process is linearly proportional to “n”. We denote this linear
dependency as O(n). The memory space required for storing global stiffness matrix is proportional to n2 or
3.50
3.00
2.50
2.00
1.50
1.00
0.75
0.50
0.25
A 0.00
Figure 5•17 Contours of yield ratio (normalized to initial yield value) after
accumulating 10 incremental steps (δu = 0.01 m; total streching ~0.56%).
denote as O(n2), while the matrix solution problem is known to be a process of O(n3). As the size of the problem
increases, obviously the matrix solution process will become very costly. Therefore, optimization methods,
introduced in Chapter 2, that alleviates matrix solution process will be most desirable when the problem size
becomes large. We discuss (1) the conjugate gradient method that completely avoids the need for inverting a
matrix, and (2) the quasi-Newton BFGS method that only inverting matrix once in a while. A word of caution is
as you have seen in Chapter 2, the classical Newton method is the most powerful one that has quadratic conver-
gence rate. Use of these other methods may slow down the convergence rate substantially. The trade-off is then
many more iterations are needed to get to the same level convergence, when the second-order information (the
inverse of Hessian in this case is the decomposition of the global stiffness matrix) is to be avoid either partially
or completely.
1
Π ( u ) = --- u T Ku – u T f Eq. 5•245
2
where K is the global stiffness matrix and f is the global force vector and we drop the “hat” sign for the nodal
solution as u for simplicity. For the conjugate gradient method the initial search direction is taken as the negative
gradient as
where Du is the directional derivatives, and r0 is the residual. The the solution u, for the next iteration, is updated
along the search direction p as
The that minimized the objective functional for this quadratic programming case can be shown as1
g kT p k
α k = – -----------------
- Eq. 5•248
p kT Kp k
The next search direction is so chosen that it is orthogonal to the set of previously chosen search directions as
g kT + 1 Kp k
p k + 1 = – g k + 1 + β k p k, where β k = -----------------------
- Eq. 5•249
p kT Kp k
and gk+1 is g evaluated at uk+1. In Chapter 2, the conjugate gradient method is introduced with line search
method that no Hessian (global stiffness matrix) is required. In that case, the convergence will be extremely slow.
For finite element method, not assembling the global stiffness matrix gives some advantage that the required
memory space grow as O(n2) as discussed earlier. However, if the memory is not of very much concern, the vital
second-order information (the Hessian), will help convergence by a lot. The decision to assemble the global stiff-
ness matrix also depends on the fact that computation to form element stiffness matrix is un-avoidable. In order
to compute the residual according to Eq. 5•246, the element stiffness ke must be computed anyway. Since ele-
ment stiffness matrices are computed, assembly of the global stiffness matrix provides vital second-order infor-
mation which facilitates the convergence of the conjugate gradient method. Eq. 5•246 to Eq. 5•249 are
implemented for each incremental loading step, with its index “i”, as
1. see p.244 in Luenberger, D.G., 1984, “Linear and nonlinear programming”, 2nd eds., Addison-Wesley Publishing Com-
pany, Inc., Reading, Massachusetts.
The global stiffness matrix is assembled in this algorithm, but no matrix solution, by direct method, is performed.
The convergence rate compared to the classical Newton-Raphson method is still very very slow. The implemen-
tation of the conjugate gradient method for quadratic programming case can be activated by setting the macro
definition “__TEST_CONJUGATE_GRADIENT_METHOD” in project “elastoplasticity” of project workspace
file “fe.dsw”.
q i • ( B i q i ) p i ⊗ p i p i ⊗ ( B i q i ) + ( B i q i ) ⊗ p i
B iBFGS = B i + 1 + --------------------------- ------------------ – ---------------------------------------------------------------- Eq. 5•250
+1
qi • pi pi • pi qi • pi
For size of B as “n”, step 1 to step 2 can be repeated every “m” times (m < n). This m-iteration loop can be
repeated many times until all the convergence criteria are met. This additional outer loop is known as the partial
quasi-newton method, which aids the convergent rate of a numerical iterative process as opposed to theoretical
one that the convergence is guaranteed in “n” steps. The implementation of the BFGS method is as the follow-
ings
With the aids of the inverse of Hessian, B, the convergence rate shows dramatic improvement. When the size of
the matrix is increased, saving time in inverting the global stiffness matrix, a O(n3) process, will become more
and more critical. This implementation can be activated by setting marco definition “__TEST_QUASI_
NEWTON_BFGS_METHOD” in project “elastoplasticity” of workspace file “fe.dsw”.
Strain Measures
We first check the effect of finite rotation on the infinitesimal strain. A rigid body rotation can be expressed
as an orthogonal transformation, with θ as the rotation angle,
1 2
--- θ + O ( θ 4 ) 0
cos θ – 1
ε ≡ 1--2- ( ∇ u + ∇ T u ) = 1--2- ( R + R T – 2 I ) = 0
≅
2
Eq. 5•252
0 cos θ – 1 1 2
0 --- θ + O ( θ 4 )
2
The last approximation step is the Taylor expansion of the cos θ. Therefore, finite rotation, a rigid body motion,
would excite unwanted strain in the order of θ2 (in radian). In many practical engineering applications we are
Stress Rates
In small deformation problems, the Cauchy stress is used in the formulation. Unfortunately, the Cauchy
stress rate is not objective. Consider again applying a rigid body rotation to a body, where no stress should be
excited. Since the stress is a second order tensor, it transforms with the rotation tensor according to the transfor-
mation rule
σ’ = R σ RT Eq. 5•253
· 1 T
W ≡ R = --- ( ∇ u· – ∇ u· ) Eq. 5•254
2
Note that W is skew symmetric, so WT = -W. For two coordinates with x = X initially, and therefore R = I initially,
taking time derivative with respect to Eq. 5•253, (then evaluated at x = X, and R = I)
σ· ’ = W σ + W σ = Wσ – σW
T
Eq. 5•255
If σ ≠ 0 , σ· will not vanish. However, no stress rate is expected to be excited. Therefore, σ· is the spurious
’ ’
stress rate that needs to be corrected. The Jaumann stress rate takes out of this spurious stress rate and is defined
as
σ̃ = σ· – W σ + σ W Eq. 5•256
σ̃ is also known as the co-rotational stress rate. For a more formal treatment of the objective stress rate see stan-
dard text.1
The Jaumann stress rate is said to be objective only with respect to isomorphism. Isomorphism means that
the transformation is a one-to-one mapping with inverse of the transformation defined. We are also interested in
diffeomorphism. Diffeomorphism is a transformation that further requires the derivatives of the transformation is
also one-to-one mapping with inverse. There are many other objective stress rates historically. They are either
objective with respect to isomorphism or diffeomorphism.2 Rates which are objective with respect to diffeomor-
phism are called covariance. Therefore, the covariance requirement demands that a physical quantity invariant
under arbitrary Cn transformation. The covariance let us leap forward to the essence of modern Einstein’s rela-
Material Moduli
We restrict our discussion on the constitutive law to what is relevant to the strain measure and the stress rate
issues developed above. First of all, lets note the material moduli is a fourth-order tensor. A transformation apply
to a fourth-order tensor is similar to that of Eq. 5•253 for the second-order tensor, only the spurious term gener-
ated will be twice as ugly as what is in Eq. 5•255. Disregarding what those ugly spurious terms really are, it is
suffice to say that the material moduli so derived is not invariance with respect to a rigid body motion. This has
certain impact on material moduli of anisotropic materials. For isotropic materials, the constitutive law are
required to be written, by choosing its independent parameters, to be invariant with respect to rotation. It is not so
fortunately for the anisotropic materials. It becomes our responsibility to make it objective by subtracting corre-
sponding spurious terms similar to what was done in Eq. 5•256. The argument above for anisotropic material
moduli is therefore completely parallel that for stress rate. Secondly, we already know the Cauchy stress rate is
not objective (the spurious stress σ · ≠ 0 in Eq. 5•255 occurs). When we construct the constitutive equation in
’
stress-strain rate form, we could expect that the constitutive equation should be defined using the objective stress
rates only; i.e., not to use the Cauchy stress rate. Then, if it is more convenient for computation, the objective
stress rates can then be expressed in terms of the Cauchy stress rate with its corresponding spurious terms. When
the objective stress rate is used, the problem occurred in the material moduli here resolves automatically.
φ
φ(X) = x
WX
X Tφ WX
Kinematics
A simple body is an open set in n. Define its containing space as = n. A C1 configuration is repre-
sented by a mapping φ: → , see Figure 5•18. A tangent space to the set at point X is denoted as TX . The
tangent space is the vector space n considered as vectors with base point X. Similarly the tangent space to is
Tx . A tangent vector WX = (X, W) ∈ T X, with X denoting its base point. A tangent map of φ is defined as T
φ: TX → Tx . T φ(X, W) = (φ(X), Dφ(X) • W) where “Dφ(X) • W” denotes the derivative of φ(X) at X in the
direction of W. Then, T φ • WX is called “push-forward” of W by φ. The push-forward is also denoted as φ*.
Deformation Gradient
The tangent of φ is denoted F, the deformation gradient of φ; i.e., F = T φ. Let {XA} and {xa} denote coordi-
nate system on and , respectively. The matrix F with respect to the coordinate bases EA(X) and ea(x) is given
by F = FaA ea ⊗ EA (= GRAD φ(X) ≡ ∇ ⊗ φ(X), where the operator ⊗ denotes the tensor product)
a ∂φ a ∂x a
F A ( X ) = ---------- ( X ) , note that d x a = ---------- dX A Eq. 5•257
∂X A ∂X A
where dxa and dXA are the infinitesimal position vectors, which are the tangent vectors in and . From Eq.
5•257, dxa = F • dXA (= T φ • dXA = φ* dXA) is the “push-forward” of dXA by φ. The Jacobian is, J = det F.
The restriction that J > 0 is the impenetrability of matter, in that the local invertibility of F is required. Therefore,
the relative orientation of the line elements is preserved under deformation.
Metric tensor on is defined as gab(x) = <ea , eb>x , and metric tensor on is defined as GAB(X) = <EA ,
EB>X , where < , > is the inner product in n. The transpose of F is defined as
A
( F T ( x ) )a = g ab ( x ) F Bb ( X ) G AB ( X ) Eq. 5•258
Note that the deformation gradient F is a two-point tensor which can be considered as a tensor with “two legs”;
one on and the other on . Therefore, the question of whether F is symmetric is irrelevant!
Since F with two different “legs” can not be symmetrical, we want to find ways to define “symmetrized”
quantities from it; i.e., somehow, get the off-diagonal components to have same value and “leg”. Therefore, the
d x 2 – d X 2 = d X • ( FT F – G ) • d X = d X • ( C – G ) • d X
Eq. 5•259
2E
The Lagrangian (material, or Green) strain tensor E is defined as 2E = (C - G), (where G = I, in the Cartesian
Coordinates, where I is the identity on TX ). Similarly,
d x 2 – d X 2 = d X • ( g – ( FF T ) –1 ) • d X = d X • ( g – b –1 ) • d X Eq. 5•260
2e
The Eulerian (spatial) strain tensor e is defined as 2e = (g - b-1), (where g = i, where i is the identity on Tx ).
3
S = ∑ λi ( pi ⊗ pi )
i=1
Eq. 5•261
This leads to det(Q - I) = 0, indicating there exists a unit vector p such that
Q p = p = QT p Eq. 5•263
The orthogonal tensor Q can be expressed as the following equation (for derivation see P. Chadwick[1976]1)
1. see p. 37 in Chadwick, P., 1976, “Continuum mechanics, concise theory and problems”, John Wiley & Sons,
New York.
λ1 p x x’
λ3
q
p2
p1 λ2
r
Figure 5•19 Stretches and Rotation for the Polar Decomposition
One recognizes, in Eq. 5•264, (q cosθ-r sinθ)q+(q sinθ+r cosθ)r is a rotation about p-axis on (q, r)-plane. Fig-
ure 5•19 illustrates both the interpretation of S as stretches λ1, λ2, λ3, and Q as rotation around p-axis.
Recall C and b are symmetric and positive definite. Define U = C , and V = b , where U and V are the
right stretch tensor and the left stretch tensor, respectively. U and V have common eigenvalues λ i. The eigen-
vectors pi of U and the eigenvectors qi of V are called the referential stretch axis and the current stretch axis,
respectively.
pi
Right Polar
λi
qi
Stretch by U Rotate by R
Decomposition
pi
Left Polar
qi λi
Rotate by R Stretch by V
ε 1
= e + --- Θ g
3
Eq. 5•265
where infinitesimal strain tensor ε ≡ ( ∇ u + ∇T u ) ⁄ 2 , and the mean dilatation Θ ≅ J ≡ ∇•u . This kinematic split
is important for kinematic constraint for the incompressible materials, and is useful in the context of J2 plasticity.
In finite deformation this additive split is substituted by a multiplicative split.
F = J 1 / 3 F̂ Eq. 5•266
where “^”, denotes the volume-preserving part. Therefore, the corresponding right Cauchy-Green tensor is
T
Ĉ = J – 2 / 3 C = F̂ F̂ Eq. 5•267
The infinitesimal version of the additive split (Eq. 5•265) can be understood as linearization of the multiplicative
split (Eq. 5•267) about φ = I as the followings. Let denotes the set of all configuration φ. A tangent vector to
at φ0 ∈ is a vector field u covering φ0. The variation εu, where ε ∈ , is the infinitesimal deformation imposed
on the finite deformation φ0, or writes εu = δ φ0, the variation of the configuration. Considering an incremental
motion φ0ε = φ0 + εu • φ0, the deformation gradient with infinitesimal increment Fε is
The linearization of the volume-preserving right Cauchy Green tensor Ĉ in Eq. 5•267 gives “2e”, , where e,
unfortunately an overloaded symbol, is the infinitesimal deviatoric strain tensor. The derivation is explained in
the followings. The derivatives of the Jacobian, and the right Cauchy-Green tensor evaluated at ε = 0 are:
d d
det ( F ε ) = det ( F ) tr ( ∇u ) , and Cε = F T ( ∇ u + ∇T u ) F Eq. 5•269
dε ε=0
dε ε=0
εu
φ0
εu
φ0( )
Figure 5•21 Infinitesimal deformation imposed on finite deformation
∂
L v t = φ ∂ t φ∗t Eq. 5•270
*
where φ* is the “pull-back” by φ, defined as action taken by tangent map T φ-1. In words, the procedure of taking
the Lie derivatives is:
(3) “push-forward” the result of the time derivative to the current configuration using F.
This objective spatial rate is sometimes called a convected time derivative. It is the change of a spatial object rel-
ative to the flow of the spatial velocity field. Therefore, it is naturally objective. As we have mention earlier, the
objective flux (rate) defined by the Lie derivatives is objective with respect to diffeomorphisms and is called
covariant. A covariant rate transforms tensorially independent of any preferred coordinate system.
Strain rates are essential in defining constitutive laws in rate-form, for example, viscosity and plasticity. The
covariant nature derived from the Lie derivatives plays an important role. Following results of the Lie deriva-
tives on spatial tensors, g and b, are important.
We discuss the derivation in words, with two additional pull-back identities φ*(g) = C and φ*(b) = G [see Mars-
den and Hughes]1. In the first part of this equation, the Lie derivative of spatial metric tensor g gives two times
T
the spatial rate of deformation tensor d ( ≡ ( ∇ u· + ∇ u· ) ⁄ 2 ). The result follows immediately from the definition
of the Lie derivative per se. The first step is: “pull-back” of g is C the right Cauchy-Green tensor; i.e., φ*(g) = C.
Then the second step is: taking the time derivative on C yields 2D by definition; i.e., 2D ≡ ∂C ⁄ ∂t , where D is
the material rate of deformation tensor. The third step is: “push-forward” of D is the spatial rate of deformation
tensor d; i.e., φ*(D) = d. The second part of Eq. 5•271 shows the left Cauchy-Green tensor b is “dragged” by the
flow v. Again, following the procedure defined in the Lie derivatives, in the first step, the “pull-back” of b is the
material metric tensor G; i.e., φ*(b) = G. In the second step, the material metric tensor G is constant with respect
to time, and will be zero upon taking time derivative. In the third step, “push-forward” of zero gives zero. Eq.
5•271 is useful for developing the constitutive law in rate form.
Piola Transformation: Let y be a vector field on , and Y a vector field on . The Piola Transform of y to Y is
given by
This stress definition gives simple form of equations of motion. However, the first Piola-Kirchhoff stress tensor
is not symmetrical. Recall mixed upper-lower case indices means that the first Piola-Kirchhoff stress is a two-
point tensor with “two legs”. This disadvantage of first Piola-Kirchhoff stress tensor leads to the definition of
second Piola-Kirchhoff stress tensor. The second Piola-Kirchhoff stress tensor S is defined as pulling the “first
leg” of P back by φ as
Both τ and σ are defined only in spatial configuration. We observe the difference of them is a scalar factor of J,
the Jacobian. The reason for this proliferation of stresses (τ and σ) in the same configuration is whether one is
performing the Piola transformation with J factor considered, or merely pull-back and push-forward the tensor
objects between spatial and material configurations.
In this section, we mentioned one of the disadvantage of the Cauchy stress in describing the Green elastic
material. The other dismay of the Cauchy stress is the rate of the Cauchy stress is not objective (while the rate of
another symmetric stress tensor, the second Piola-Kirchhoff stress tensor S is objective). Therefore, the Cauchy
stress rate will not be suitable for defining constitutive laws formulated in rate form, e.g., viscosity and plasticity.
The subject of objective rates has been very controversial. All the “objective rates” of second-order tensors, for
examples the Oldroyd rate, Truesdell rate, and Jaumann rate are in fact either (1) the Lie derivatives of the
Cauchy stress tensor σab, or (2) the Lie derivative of the Cauchy stress’s associate tensors (σab, σab, σab), or
(3) certain linear combinations of the Lie derivatives of the associate Cauchy stresses.
Constitutive Equations
In the context of elastoplasticity for this workbook, we restrict ourselves on isotropic material in hyperelas-
ticity and associative flow law in the classical J2 plasticity (see e.g., Fung [1965]1, or Malvern [1969]2 for intro-
duction). We focus on the consequence of finite deformation on such a constitutive law.
For pure elasticity (isothermal), Ψ—the free energy, and E—the internal energy coincide (Ψ = E). We also
postulate that the constitutive equation can be expressed in differential operator which is defined in “local”
points to represent the whole material; i.e., the axiom of locality. Taking covariance of energy balance as an
other axiom, one can deduce
∂E ∂F
ρRef ------- = P: ------- Eq. 5•276
∂t ∂t
This is, the change in internal energy (the left-hand side) equals the “mechanical power” (the right-hand side).
Therefore, the constitutive equation, in material configuration expressed by the first Piola-Kirchhoff stress ten-
sor, should have the form of
∂Ψ
P = ρRef g# -------- Eq. 5•277
∂F
1. Fung, Y.C., 1965, “Foundations of solid mechanics” Prentice-Hall, Inc., Englewood Cliffs, New Jersey.
2. Malvern, L.E., 1969, “Introduction to the mechanics of a continuous medium” Prentice-Hall, Inc., Englewood
Cliffs, New Jersey.
∂Ψ
S = 2 ρRef -------- Eq. 5•278
∂C
Recall the “push-forward” of C is g. Having the Piola transformation in mind, Eq. 5•278 is equivalent to consti-
tutive equations written in the Cauchy stress σ, and the Kirchhoff stress τ defined in spatial configuration as the
follows
Ψ ∂Ψ
σ (= J-1 τ) = 2 ρ ∂-------
- ⇒ τ = 2 ρRef -------- Eq. 5•279
∂g ∂g
This is the Doyle-Erickson formula. For the dependence of free energy Ψ on g, one can feel more comfortable by
directly considering spatial setting as the followings. Changes of spatial metric tensor on from g to say g'
affect the accelerations of particles. Thus, the internal energy E must depend on the metric tensor g; i.e., for the
free energy Ψ to depend on g.
The elasticity tensor or the elasticities A is a fourth-order tensor on , and is defined as
∂S ABCD ∂S AB ∂2 Ψ
A = ------- , i.e., A = -------------- = 2 ρ Ref ----------------------------- Eq. 5•280
∂C ∂C CD ∂C AB ∂C CD
the symmetry of the elasticity tensor AABCD = ACDAB implies the cross partial differentiation of Ψ are equal
∂2 Ψ ∂2Ψ
----------------------------- = ----------------------------- Eq. 5•281
∂C AB ∂C CD ∂CCD ∂C AB
This is the condition for the existence of the free energy Ψ as a potential function from calculus; i.e., also the
condition to define hyperelasticity.
We have concluded that the free energy Ψ depends on φ and F only through C. Recall that C is a symmetric
tensor, which can be brought to diagonal form by orthogonal transformation. For regular φ we have seen, a posi-
tive definite symmetric tensor in this case C, admits spectral representation (Eq. 5•261). The free energy Ψ must
be a function only of the eigenvalues of C; that is, Ψ depends only on the principles stretches of U. However,
instead of using eigenvalues, the three invariants of C, where I(C) = tr (C), II(C) = det C tr C-1, and III(C) = det
C = J2, is also convenient to use. The same is true for the free energy Ψ expressed in spatial configuration with
the left Cauchy-Green tensor b, used in the next section.
Elasticity
Recall the kinematic split into deviatoric and spheric parts, the volume-preserving right Cauchy-Green ten-
T
sor is, therefore, defined as Ĉ = J –2 / 3 C = F̂ F̂ . The volume-preserving left Cauchy-Green tensor is defined
similarly as b̂ = J –2 / 3 b = F̂F̂ . The idea is to express the free energy Ψ as function of three invariant of b; i.e.,
T
Ib, IIb, and IIIb. For an isotropic material with uncoupled volumetric and deviatoric responses, the stored energy
ˆ
function has the form of Ψ = Ψ ( b̂ ) + U ( J ) . A special case in invariants of b is
1
Ψ = --- µ ( Îb – 3 ) + U ( J ) Eq. 5•282
2
where Î b = J-2/3 Ib, (where Ib ≡ b : g), and that J = IIIb1/2. Two identities are useful for the following deriva-
tions: Lv(IIIb) = Lv(J2) = 2 IIIb g# : d, and Lv(Ib) = Lv(b# : g) = 2 b# : d. Recall the Doyle-Erickson formula
(Eq. 5•279) as the Kirchhoff stress in relation to the free energy Ψ is
Ψ
τ = 2 ρRef ∂-------
- ⇒ τ = J p g# + µ dev b̂ , Eq. 5•283
∂g
∂τ
where p = dU/dJ. The spatial elasticity tensor a ≡ 2 ------ becomes,
∂g
2 1
a = J 2 U’’( J )( g ⊗ g ) + Jp ( g ⊗ g – 2I )+ --- µ Î b I – --- ( g ⊗ g ) – ( devb̂ ⊗ g – g ⊗ devb̂ ) Eq. 5•284
3 3
2 1
a dev ≡ --- µ ˆI b I – --- ( g ⊗ g ) – ( devb̂ ⊗ g – g ⊗ devb̂ ) Eq. 5•285
3 3
For example, a possible case of U, satisfying polyconvex condition, is U(J) = K/2 (J2-1). U’ = dU/dJ = p = KJ =
K (1+ ∫ dV/V) = K (1+logV), U’’ = d2U/d2J = K = V ( ∂p ⁄ ∂V ) T , with the last identity derived from p =
K(1+logV), where K is then identified as the bulk modulus. Eq. 5•284 is symmetrical as required in hyperelas-
ticity shown in Eq. 5•281.
We observe that in the above extremely simplified case of finite elasticity, the elasticity tensor a is a strong
non-linear function of deformation (expressed in J and b) and metric tensor (g), even though the bulk modulus K
and the shear modulus µ have been naively assumed as constant with respect to deformation and thermal effect.
This non-linearity is required if the constitutive equation is to be covariant, and is to be consistent with the sim-
1. J.C. Simo, 1988, “A Framework for Finite Strain Elastoplasticity Based on Maximum Plastic Dissipation and the Multi-
plicative Decompositions: Part I. Continuum Formulation.” Computer Methods in Applied Mechanics and Engineering, vol.
66, p. 199-219. “Part II. Computational Aspects.”, vol. 68, p.1-31.
We have come to a long way to define the elastoplasticity in the finite deformation range. However, the com-
plicated mathematical expression in Eq. 5•284 is only to implement the simplest ideas of “objectivity” and
“restorable elastic energy”. The algebraic structures in the infinitesimal deformation simply does not carry over
to the finite deformation. The idiosyncrasy in finite deformation range, if not respected, will lead only to absur-
dity!
where E is the finite Lagrangian strain tensor, and D is the strain rate tensor. The constitutive equation for such
additive decomposition is usually cast in a rate-form. However, the notion of hyperelasticity is not consistent
with a rate expression. The incremental objective algorithm, historically, is developed to ensure the frame-indif-
ference nature of the path-dependent stress-strain integration scheme, and hyperelasticity is achieved through
algorithmic approximation. The semantics of the Eq. 5•286 implies that the elastic and plastic deformations
occurred simultaneously. De and Dp are unknown to be solved simultaneously. An additional (stronger) assump-
tion, on top of the formal additive decomposition, will help us resolve the elastic and plastic parts of deformation
separately. This additional assumption is that the elastic and plastic deformation occur in succession. The defor-
mation gradient, occurring in two consecutive steps, is naturally expressed as a multiplicative decomposition
(Lee decomposition).
F = F e Fp Eq. 5•287
The superscript “e” indicates elastic part, and “p” indicates the plastic part. The tensor (Fe)-1, therefore, is the
deformation gradient which responses to the elastically released stress. The released intermediate configuration
is thus introduced. In multiplicative decomposition, one is able to compute elastic response exactly (by mere
function evaluation as opposed to algorithmic approximation in the incremental objective algorithm). This addi-
tional assumption of multiplicative decomposition is also justifiable from scientific point of view. It has been
argued from two perspectives. Firstly, from theoretical development of how elastic deformation of a crystalline
material is lead to dislocation (i.e., plasticity as the macroscopic manifestation of crystal structural dislocation).
Secondly, electron-microscope study that demonstrates how this micro-mechanism can occur.
rian strain (ep), we observe that (be)-1 plays the role of the plastic metric tensor gp. That is, for the elastic Eule-
rian strain ee, the elastic Finger deformation tensor (be)-1 is the deformation from the “identity” g, while for the
e –1
∂ Ψ ( g, ( b ) , F ) ∂2Ψ ∂2Ψ
τp = 2 ρRef Lv( ------------------------------------------ ) = - 2 ρ Ref -------------------------
e –1
Lv e – 1- L v ( ( b ) ) + -------------- L v ( F ) Eq. 5•288
∂g ∂g∂(b ) ∂ g ∂F
such that
e –1
∂ 2 Ψ ( g, ( b ) , F )
Lv τ p
= - 4 ρ Ref --------------------------------------------
e –1 - : dp Eq. 5•289
∂g∂(b )
e –1
Recall Lv(g) = 2d, and Lv(F) is zero, since φ*F = I. Note that L v ( ( b ) ) = L v ( g p ) = 2dp, the spatial rate of
plastic deformation tensor, where d is the symmetrical part of the velocity gradient.
e –1
∂ 2 Ψ ( g, ( b ) , F )
Lv τ = - J
p -2 / 3 e –1
e –1 - : L v ( ( b ) ) ],
dev [ 2ρRef-------------------------------------------- Eq. 5•290
∂g∂(b )
e –1
φ ( g, ( b ) , q, F ) ≤ 0 Eq. 5•291
e –1
∂ Ψ ( g, ( b ) , F )
γ φ ( g, ( b ) , q, F )
p e –1 · e –1
≡ ------------------------------------------
e –1 : Lv ( ( b ) ) + Eq. 5•292
∂( b )
· ·
where γ is the plastic consistency parameter. γ is also the Lagrangian multiplier in constrained optimization.
The minimization condition of the Lagrangian functional is the Euler-Lagrange equations (with virtual variation
of g )
∂
------ p = 0, Eq. 5•293
∂g
and the Kuhn-Tucker condition, the celebrated trio in inequality constrained optimization is
· e –1 · e –1
γ ≥ 0 , φ ( g, ( b ) , q, F ) ≤ 0 , and γ φ ( g, ( b ) , q, F ) = 0 Eq. 5•294
the Euler-Lagrange equation Eq. 5•292 gives the definition of the plastic relaxation stress as
∂φ
Lv τp = γ· 2 J dev ------
–2 / 3
Eq. 5•295
∂g
This is the plastic flow law basing on Hill’s principle of maximum plastic dissipation as derived in Simo[1988]1.
For a specific case of isotropic-kinematic hardening J2 plasticity with uncoupled hyperelasticity, the problem
is defined as
· ξ 1
µ J –2 / 3 dev [ L v b e ] = – 2µγ n̂ , where n̂ ≡ -------- , µ ≡ --- µ J –2 / 3 tr [ b e ] , and tr [ L v b e ] = 0 Eq. 5•299
ξ 3
1. J.C. Simo, 1988, “A Framework for Finite Strain Elastoplasticity Based on Maximum Plastic Dissipation and the Multipli-
cative Decompositions: Part I. Continuum Formulation.” Computer Methods in Applied Mechanics and Engineering, vol. 66,
p. 199-219. “Part II. Computational Aspects.”, vol. 68, p.1-31.
· 2·
κ ( e p ) = κ0 + β h’e p , where e p = --- γ Eq. 5•300
3
· h'
J – 2 / 3 dev [ L v α ] ≡ 2 µγ ------- ( 1 – β ) n̂ , where µ ≡ µ – J –2 / 3 tr [ α ] , and tr [ L v α ] = 0 Eq. 5•301
3µ
µ ≡ µ – --- tr [ F u α ( F u ) ]
1 1 ˆ ˆ T
µ ≡ --- µ tr [ b̂ ne +TR
1 ], Eq. 5•302
3 3
1 2
TR
a dev n+1 ≡ 2 µ I – --- ( g ⊗ g ) – --- ( s TR ⊗ g + g ⊗ s TR ) Eq. 5•303
3 3
≡ 2 µ I – --- ( g ⊗ g ) – --- ( ξ TR ⊗ g + g ⊗ ξ TR )
TR 1 2
h dev n+1 Eq. 5•304
3 3
2 µγ n + 1 1 h’ κ’ , h’
- + ------- δ ≡ f 2µ – ----- 1 + ------ – 1 --- γ n + 1 , δ ≡ 2
f0 ≡ ------------------- 1 4
ξn + 1
TR
-, f 1 ≡ ----- – f 0
δ0
, δ ≡ 1 + ------
0 3µ 3µ 1 1 δ0 3µ 3 2 ξnTR+ 1 f 1 Eq. 5•305
The deviatoric part of the consistent tangent moduli Eq. 5•285 is modified accordingly with superscript “s”
denote symmetrized
ep
a dev n+1 ≡ a dev
TR
n+1
TR
– f 0 h dev n+1 – δ1 ( n̂ ⊗ n̂ ) – δ 2 ( n̂ ⊗ dev [ n̂ 2 ] ) s Eq. 5•306
1. J.C. Simo, 1988, “A Framework for Finite Strain Elastoplasticity Based on Maximum Plastic Dissipation and the Multi-
plicative Decompositions: Part I. Continuum Formulation.” Computer Methods in Applied Mechanics and Engineering, vol.
66, p. 199-219. “Part II. Computational Aspects.”, vol. 68, p.1-31.
2. J.C. Simo, R.L. Taylor, and K.S. Pister, 1985, “Variational and Projection Methods for the Volume Constraint in Finite
Deformation Elasto-Plasticity”, Computer Methods in Applied Mechanics and Engineering, vol. 51, p. 177-208.
Proceed as in the linear case for the Hu-Washizu variational principle, the Euler-Lagrange equations are a set of
simultaneous equations and is reduced to displacement field only formulation. Linearization with respect to vari-
ations at tn+1, we obtain the tangent stiffness as (η is the variation about φn+1)
1 T
--- ∇ η :a: ∇ u = ∇ T η : [ σ ∇ u ] + ∇ T η : [ p ( 1 ⊗ 1 – 2I ) + a dev
ep ] :∇ u Eq. 5•308
J
The first term in the right-hand-side is the geometrical stiffness. The second term, which depends on the material
moduli, can be cast in the B-matrix formulation with an averaged volumetric term as
∫ B T [ adev
ep
n+1 ( Θ ) N’ N’]vol ( φ n + 1 )
– 2pI ] B dV + [ U’’
T
Eq. 5•309
Ωe
U(Θ) is the volumetric part of the free energy function, where Θ is the element mean dilatation, and N’ is the
averaged derivatives of shape function over the element.
sTRn+1
elastic predictor
plastic corrector
sn+1 elastic predictor sTRn+1
plastic corrector
sn sn sn+1
Yield Surface Yield Surface
3. J.C. Simo, 1988, “A Framework for Finite Strain Elastoplasticity Based on Maximum Plastic Dissipation and the Multipli-
cative Decompositions: Part I. Continuum Formulation.” Computer Methods in Applied Mechanics and Engineering, vol. 66,
p. 199-219. “Part II. Computational Aspects.”, vol. 68, p.1-31.
In the closest-point projection method, the integration is done at φn then push-forward by Fu (the incremental
deformation gradient) to the current configuration φn+1. The push-forward of the intermediate configuration and
its internal plastic variables at the finite deformation range makes the algorithm not only incremental objective,
but covariant.
Computationally, the stress inversion step of cutting-plane method is the trade-off for the push-forward step
in the closest-point projection method. The algorithm for the closest-point-projection is aesthetically more satis-
fying but requires the introduction of the advanced covariant concept.
Deformation Gradient from Shape Derivatives at φn+1 and the Mean Dilatational Approximation : The shape
derivative code (see Program Listing 5•22) is different from the infinitesimal case that it is evaluated at x = φn+1,
in place of X = φ0. The spatial metric tensor g = i (spatial identity), instantaneously coincide with a Cartesian
coordinates system. Recall x = X + u,
The lower case “grad”, in convention, denotes derivatives with respect to spatial coordinates x. Post-multiply by
F-1, we have
We first compute F-1 from grad u. The inverse of F-1 gives the deformation gradient, F. And evaluate the Jaco-
bian from the determinant of the deformation gradient as J = det(F). Remember for the following computation
all the available quantities are center around x = φn+1.
The mean dilatation Θ is
where the current volume is v = ∫ d v , and the initial volume is V = ∫ ------ , both integration are done at the cur-
dv
φ ( Ωe ) φ ( Ωe ) J
rent configuration φn+1.
Listing 5•22 Deformation gradient and mean dilatation approximation evaluated from configuration at x
= φn+1.
K
U ( Θ ) = ---- ( log Θ ) 2 Eq. 5•313
2
where K is the bulk modulus. p = U' = dU / dΘ, and U'' will be used in the calculation of tangent stiffness.
Again with VectorSpace C++ Library the evaluation of these derivatives is quite simple. We just need to declare
U and Θ to be a function and an independent variable, respectively, of C2 class. Alternatively, with such simple
equation, you might want to do the differentiation by hand, and code the result directly. In addition, because
pow(int) function only takes integer exponent, J2/3 is expressible as functions of exp() and log() by the equation
J2/3 = elog(J)2/3.
The update procedure for implementation 1 is to map the history data {Θn, pn, Jn, Fn, σn, (Fp)-1n, epn, αn} at
tn to {Θn+1, pn+1, Jn+1, Fn+1, σn+1, (Fp)-1n+1, epn+1, αn+1} at tn+1. We omit the programming details, since the
implementation to construct object-oriented private data members is completely parallel to that of the infinitesi-
mal case.
Elastic-Predictor and Plastic-Corrector: The elastic predictor (see Program Listing 5•23) assumes that the trial
plastic deformation gradient at tn+1 is Fnp +TR 1 ≡ F n ; i.e., no new plastic flow occurs. Therefore, the internal plas-
p
tic variables remain unchanged. Although the configuration has changed from φn to φn+1, push forward of zero
(no change of internal plastic variables) is zero. Then, the trial elastic deformation gradient at the current config-
p –1
1 ≡ F n + 1 ( F n ) . The deviatoric part of the Kirchhoff stress is calculated from the constitutive
uration is F ne +TR
equation, which has already been chosen to be covariant, as
Listing 5•23 Elsatic predictor assume no plastic flow occurs. The deviatoric Kirchhoff stress s, in engi-
neering convention, is evaluated from the consititutive law
Intermediate Configuration: We mentioned that the covariance of this stress-strain path integration algorithm
follows directly from the covariance of the constitutive law. We did not mention how do we get the (Fpn)-1 in the
above algorithm to furnish the covariance requirement.
We first describe a tactic change on stress inversion algorithm, from Simo et al[1985]1, adopted in the imple-
mentation of this workbook. At the initial step of the incremental loading step (Fp0)-1 can be assumed to be an
identity matrix, for no deformation has occurred. The tensor (Fp0)-1 remains unchanged during the same time
1. J.C. Simo, R.L. Taylor, and K.S. Pister, 1985, “Variational and Projection Methods for the Volume Constraint in Finite
Deformation Elasto-Plasticity”, Computer Methods in Applied Mechanics and Engineering, vol. 51, p. 177-208.
(a) get the Kirchhoff stress from the Jacobian and the Cauchy stress— τ n = J σ n from Eq. 5•275.
(b) compute dev ( b̂ ne ) from the deviatoric part of the constitutive law— dev ( b̂ ne ) = --- dev ( τn ) from Eq. 5•296.
1
µ
(c) compute b̂ ne from its deviatoric part dev ( b̂ne ) and requiring det ( b̂ne ) = 1.
(d) compute the elastic left-Cauchy-Green tensor from the elastic volume-preserving left-Cauchy-Green tensor—
b ne = J – 2 / 3 b̂ ne by definition.
(e) compute the left-stretch tensor ( Vne ) from the left-Cauchy-Green tensor ( bne )— Vne = b ne .
(f) set Fne = V ne , this is valid for isotropic case, and compute F pn = F n (F en)-1 from the multiplicative decompo-
sition (Eq. 5•287). Then, (F pn)-1 can be obtained.
Except for sub-steps (c) and (e), the other sub-steps are straight forward without explanation. The essence of
sub-step (c), for those who familiar with solid mechanics, is similar to the calculation of principle deviatoric
stress from a deviatoric stress. See C.Y. Fung[1965, p. 80]1, or L.E. Malvern[1969, p. 91]2.
Kinematic split of the elastic volume-preserving left-Cauchy-Green tensor b̂ ne is
1
b̂ ne = dev ( b̂ ne ) + Ξ , where Ξ = --- tr ( b̂ ne ) . Eq. 5•315
3
The objective of the problem at hand is to compute the spherical part Ξ , then adds to the given deviatoric part,
requiring that det ( b̂ ne ) = 1 —add trace to a unimodular deviatoric tensor. Assuming plain strain, we define
if(new_time_flag) { τn = Jσn
H0 dev_b_hat_n_e = INTEGRABLE_MATRIX("int, int, Quadrature", 3, 3, qp),
dev ( τ n ) = τ n – 1--3- tr ( τn )
dev_tau_n = INTEGRABLE_MATRIX("int, int, Quadrature", 3, 3, qp),
tau_n = J_n*sigma_n, tr_tau_n = tau_n[0]+tau_n[1]+tau_n[2];
dev_tau_n[0][0] = tau_n[0] - (1.0/3.0)*tr_tau_n; dev_tau_n[1][1] = tau_n[1]-(1.0/3.0)*tr_tau_n;
dev ( b̂ ne ) = --- dev ( τ n )
dev_tau_n[2][2] = tau_n[2] - (1.0/3.0)*tr_tau_n; dev_tau_n[0][1] = dev_tau_n[1][0] = tau_n[3]; 1
dev_b_hat_n_e = dev_tau_n / mu_; µ
H0 bp = dev_b_hat_n_e, theta_0(qp),
J2 = (bp[0][0].pow(2)+bp[1][1].pow(2)+bp[2][2].pow(2))/2.0 + bp[0][1].pow(2);
#if defined(__NUMERICAL_ROOT_FINDING)
for(int i = 0; i < qp.no_of_quadrature_point(); i++) { 1
C0 J2_q = J2.quadrature_point_value(i), theta_0_q = theta_0.quadrature_point_value(i), J 2 ≡ --- [ ( b’11 ) 2 + ( b’22 ) 2 + ( b’33 ) 2 ]
2
bp_q=bp.quadrature_point_value(i), J3_prime = (J2_q-bp_q[2][2].pow(2))*bp_q[2][2] + 1.0;
int MAX_ITERATION_NO = 50, count = 0; double EPSILON = 1.e-6;
+ ( b’12 ) 2 + ( b’13 ) 2 + ( b’23 ) 2
C1 X(1.0), f; C0 d_X(0.0);
do { J’3 = J 3 – I 3
f &= X.pow(3) - J2_q*X - J3_prime; d_X = -((C0)f)/d(f); ((C0)X) += d_X;
} while((double)norm(d_X) > EPSILON && ++count < MAX_ITERATION_NO);
if(count == MAX_ITERATION_NO) ofs << f ( Ξ ) = Ξ 3 – J 2 Ξ – J’3
"Warning: No convergence achieved for solution of a cubic algebraic equation!" << endl;
f
theta_0_q = ((C0)X); d Ξ = – ----- , and updating by Ξ += d Ξ
} df
#else
for(int i = 0; i < qp.no_of_quadrature_point(); i++) { Closed-form solution
C0 J2_q = J2.quadrature_point_value(i), theta_0_q = theta_0.quadrature_point_value(i);
if((double)J2_q < 1.e-6) theta_0_q = 1.0;
else {
C0 bp_q=bp.quadrature_point_value(i), Octahedral deviatoric tensor
J3_prime=(J2_q-bp_q[2][2].pow(2))*bp_q[2][2]+1.0,
2J
bp_oct = sqrt((2.0/3.0)*J2_q), temp = (-J2_q/3.0).pow(3)+(J3_prime/2.0).pow(2);
b oct = -------2-
if((double)temp > 0.0) { 3
double a1, a2,
arg1=(double)(J3_prime/2.0+sqrt(temp)),arg2=(double)(J3_prime/2.0-sqrt(temp)); marginal conditions
if(fabs(arg1) < 1.e-6)a1=0.0; else a1=((arg1>=0.0) ? 1.0 : -1.0) * exp(logl(fabs(arg1))/3.0);
if(fabs(arg2) < 1.e-6)a2=0.0; else a2=((arg2>=0.0) ? 1.0 : -1.0) * exp(logl(fabs(arg2))/3.0);
theta_0_q = a1 + a2; J’3 3 3 / 2 2 J’3
} else { cos 3α = ------ ---- = ----------------
-
C0 cos_3alpha=J3_prime * sqrt(2.0) / bp_oct.pow(3), alpha = acos(cos_3alpha)/3.0; 2 J 2 3
b oct
theta_0_q = sqrt(2.0) * bp_oct * cos(alpha);
}
} J
} Ξ = 2 ----2- cos α
#endif
3
{
H0 b_hat_n_e = dev_b_hat_n_e + theta_0 * I_33; b̂ ne = dev ( b̂ ne ) + Ξ
H0 b_n_e = J_two_third * b_hat_n_e;
H0 V_n_e = INTEGRABLE_MATRIX("int, int, Quadrature", 2, 2, qp);
H0 I_b = b_n_e[0][0]+b_n_e[1][1],
1
I_b =b_n_e[0][0]*b_n_e[1][1]-b_n_e[0][1]*b_n_e[1][0]; V = ----------------------------------- ( b + IIb I )
V_n_e[0][0] = (b_n_e[0][0]+sqrt(II_b)) / sqrt(I_b+2.0*sqrt(II_b)); ( I b + 2 II b )
V_n_e[1][1] = (b_n_e[1][1]+sqrt(II_b)) / sqrt(I_b+2.0*sqrt(II_b));
V_n_e[0][1] = b_n_e[0][1] / sqrt(I_b+2.0*sqrt(II_b));
V_n_e[1][0] = b_n_e[1][0] / sqrt(I_b+2.0*sqrt(II_b));
H0 F_n_e = V_n_e;
F_p_inv_n = F_n_e * F_n.inverse();
F ne = V ne , F pn = F n (F en)-1, (F pn)-1
}
Following standard procedure for finding principle values, it can be shown that the principle deviations b’ of Eq.
5•316 satisfy
Numerical root-finding procedure can be applied to second part of Eq. 5•317. This is turned on by a macro defi-
nition “__NUMERICAL_ROOT_FINDING”. With the aid of the VectorSpace C++ Library this numerical pro-
cedure is straight forward without any explanation (see Chapter 2 for introduction). However, a closed-form
expression for this cubic algebraic equation is even more desirable. Considering that the last two equations are
almost identical. The solution for b’ can be use for solution of Ξ if one defines J' 3 = J 3 – I3 ; i.e., J'3 is used in
place of J3 in the formula for solving b’ . According to Malvern p. 922., the solution of the cubic algebraic equa-
tion is obtained by substituting
J Eq. 5•318
Ξ = 2 ----2- cos α
3
J 3
2 ----- [ 4 cos3 α – 3 cos α ] = J’3 ,
2
3 Eq. 5•319
The octahedral b (boct, the counterpart of the octahedral shear stress τo in C.Y. Fung1) does not really need to be
introduced, if one use the first identity only (as in L.E. Malvern, p.922). We can first invert for α from Eq. 5•321
e
then get to Ξ by Eq. 5•318. After solving for the value of Ξ , b̂ n is obtained from Eq. 5•315.
The sub-step (e) is the steps that one usually uses to compute numerical values of polar decomposition from a
deformation gradient tensor. We only need the middle step, for b = FFT is already available, and after we get V
where Iv = tr V, and IIv = det V. The solution of this equation can be shown as
1
V = ----------------------------------- ( b + II b I ) Eq. 5•323
( I b + 2 II b )
Consistent Tangent Moduli, Tangent Stiffness and Residual: The consistent tangent moduli (Eq. 5•284 with
deviatoric part Eq. 5•285 modified by Eq. 5•302-Eq. 5•306) is having without the push-forward and set g = i
(since the current configuration is described in an instantaneous Cartesian coordinates). The implementation is
transparent (see Program Listing 5•25). Some nuisance in the code is caused by the use of engineering conven-
tion of the deviatoric Kirchhoff stress (s) as a vector instead of its counterpart dev τ as a matrix. Naturally, Vec-
torSpace C++ Library, designed for general purpose numerical computation, does not have specific operators
defined for s. Therefore, we throw the VectorSpace C++ Library out of the window, s need to be computed com-
ponent by component just as you would do in C or Fortran. A better implementation will be to use object-ori-
ented method to extend a new derived class for this “engineering 1-D matrix”.
...
C0 n2(4, (double*)0);
n̂ 2
n2[0] = n[0]*n[0]+n[3]*n[3]; n2[1] = n[3]*n[3]+n[1]*n[1];
n2[2] = n[2]*n[2]; n2[3] = n[3]*(n[0]+n[1]); tr( n̂ 2 )
C0 trn2 = n2[0]+n2[1]+n2[2];
C0 dev_n2(4, (double*)0); dev_n2 = n2;
for(int i = 0; i < 3; i++) dev_n2[i] -= trn2/3.0;
dev( n̂ 2 ) = n̂ 2 - 1/3 tr( n̂ 2 )
C0 mu_2bar = mu_bar_q - (alpha_n_q[0]+alpha_n_q[1]+alpha_n_q[2])/3.0,
2µγ n + 1
µ ≡ µ – --- tr ( α )
f_0 = 2.0*mu_bar_q*lambda_q / ZAI_norm_q, 1
f0 ≡ ------------------
-
delta_0 = (1.0+d_H_alpha/3.0/mu_+d(KAPA)/3.0/mu_2bar),
f_1 = (1.0/delta_0-f_0),
3 , ξn + 1 ,
TR
delta_1 = f_1*2.0*mu_2bar -
(1.0/delta_0*(1.0+d_H_alpha/3.0/mu_)-1.0)*(4.0/3.0)*lambda_q, 1 h’ κ’
f 1 ≡ ----- – f 0 δ0 ≡ 1 + ------ + ------
delta_2 = 2.0*ZAI_norm_q*f_1; δ0 , 3µ
C0 TR_h_dev = 2.0 * mu_2bar * (I_mu - (One%One)/3.0) - 3µ
(2.0/3.0)*(ZAI_q%One+One%ZAI_q);
a_dev_q = TR_a_dev_q - f_0 * TR_h_dev - delta_1*(n%n) -
δ 1 ≡ f1 2µ – ----- 1 + ------ – 1 --- γ n + 1
(delta_2/2.0)*(n%dev_n2+dev_n2%n); 1 h’ 4
} else { δ0 3µ 3
a_dev_q = TR_a_dev_q;
ofs << " Elastic state: element # " << en << ", quadrature point # " << i
}
<< ", yield ratio: " << yield_ratio_q << endl;
δ2 ≡ 2 ξnTR+ 1 f1
sigma_q = s_q/J_q + p*One;
1
} TR
a dev n+1 ≡ 2µ I – --- ( g ⊗ g ) –
. . . 3
2 TR
– --- ( s ⊗ g + g ⊗ s TR )
3
1
TR
h dev n+1 ≡ 2µ I – --- ( g ⊗ g )
. . . 3
– --- ( ξ ⊗ g + g ⊗ ξ TR )
2 TR
3
. . .
ep
a dev n+1 ≡ a nTR
+ 1 – f 0 h n + 1 – δ 1 ( n̂ ⊗ n̂ )
TR
– δ 2 ( n̂ ⊗ dev [ n̂ 2 ] ) s
∇Tη : [ σ ∇u ]
C0 e = BASIS("int", ndf),
E = BASIS("int", nen),
U = (e%e)*(E%E);
H0 fact = wx*(sigma[0]*~wx+sigma[3]*~wy) + wy*(sigma[3]*~wx+sigma[1]*~wy);
stiff_geometrical &= (+(fact*U[0][0]+ fact*U[1][1])) |dv; ∫ B T [ a dev
ep – 2pI ]B dv
} φ ( Ωe ) n+1
{
C0 dN_bar = (( (~wx) || (~wy) ) | dv) / vol; T
stiff_material &= ( ((~B) * (a_dev/j + p*((One%One) - 2.0*I_mu)) * B) | dv ) + [ U’’( Θ ) N’ N’]vol [ φ n + 1 ]
+ dd(U) * theta * ((~dN_bar)*dN_bar) * vol;
}
stiff &= stiff_geometrical + stiff_material; ∫ B T σ dv
force &= -((~B)*sigma)|dv; φ ( Ωe )
Incremental Covariant Algorithm: Step 2-Step 5 These steps include computing the elastic-predictor, the plas-
tic-corrector, the radial return mapping algorithm, and the consistent tangent moduli. They are the same as in the
ˆ
Implementation 1, except we need to push-forward b̂ n and αn by F u in the elastic-predictor and the radial
e
αnTR+ 1 ≡ dev [ Fˆ u αn ( Fˆ u )
T ˆ ˆ T
] , and b̂ nTR
+ 1 ≡ F u b̂ n ( F u ) Eq. 5•324
ˆ T
µ ≡ µ – --- tr [ F u α n ( F u ) ]
1 ˆ
Eq. 5•325
3
1. J.C. Simo, 1988, “A Framework for Finite Strain Elastoplasticity Based on Maximum Plastic Dissipation and the Multi-
plicative Decompositions: Part I. Continuum Formulation.” Computer Methods in Applied Mechanics and Engineering, vol.
66, p. 199-219. “Part II. Computational Aspects.”, vol. 68, p.1-31.
This definition of µ is also used in the consistent tangent moduli. The radial return mapping also include updat-
ing history data
2
e np + 1 = e np + --- γ n + 1 Eq. 5•326
3
αn + 1 = α TR n + 1 + -----
h’
3µ
- 2µγ n + 1 n̂ n + 1 Eq. 5•327
The spatial metric tensor g is now in place of 1 in “Implementation 1” used in implementation 1. The present
implementation is straight forward except, again, minor nuisance caused by engineering convention that is not
supported by VectorSpace C++ Library.
2µγ
1 – --------- tr [ b̂ n + 1 ] n̂ n + 1
b̂ ne + 1 = b̂ ne +TR e TR
Eq. 5•329
3µ
The finite deformation formulation for the implementation 1 for cutting-plane method is implemented in
project “finite_elastoplasticity” and the implementation 2 for closet-point-projection method is implemented in
project “covariant_finite_elasticity”. Both projects are in project file “fe.dsw”. Figure 5•24 shows the strip with
circular whole under 0.33 % (6 incremental steps) and 0.56 % (10 incremental steps) vertical stretching Figure
5•24a and b, respectively. At 0.33% stretching the deformation mode is similar to the infinitesimal case up to
0.56 % stretching (Figure 5•24c). At 0.56 % stretching the high yield ratio area is confined to the bottom edge of
the model. This is the “necking” process developed. After 1/10 (180 incremental steps) vertical stretching is
shown in Figure 5•25a. Necking is developed into a clear stage.
Line Search: The time consuming nonlinear iterative algorithm becomes clearly a problem. 180 incremental
step, say with average of five iteration for each incremental step means that we will have computation time that
is about a thousand times that of a linear problem. The problem is even more serious if we consider to stretch the
strip with circular hole problem up to 1/3 as shown in Figure 5•25b. That will need about four thousand times
that of a linear problem. A lot of computing time will be required. One immediate solution is to increase incre-
mental loading 10 times by using δu = 0.1 instead of δu = 0.01 for each incremental loading step. However, with
such magnitude of incremental loading, the nonlinear iteration fails to converge even for the first time step. As
we recalled from Chapter 2 the classic Newton method is powerful that its convergent rate is quadratic. How-
ever, the Newton method often leads to wild search path and may easily fail to converge. Therefore, a line search
method with golden section can be use to regulate the search path of the Newton method (see page 125 in Chap-
ter 2). This is implemented as the follows
1 Matrix_Representation::Assembly_Switch = Matrix_Representation::ALL;
2 mr.assembly();
3 new_time_flag = FALSE; // flag to turn off Step 3 of the finite deformation procedure, after first iteration
4 C0 p = ((C0)(mr.rhs())) / ((C0)(mr.lhs()));
5 energy = fabs( (double)(p * ((C0)(mr.rhs())) ) );
6 if(count == 1) { // first iteration only
7 for(int j = 86; j <= 92; j++) {
8 gh[j][1] += d_gh[j][1];
b_e_hat_q[0][0] = TR_b_e_hat_q[0][0]-mu_2bar_gamma/(3.0*mu_)*tr(TR_b_e_hat_q)*n[0];
b_e_hat_q[1][1] = TR_b_e_hat_q[1][1] - mu_2bar_gamma/(3.0*mu_)*tr(TR_b_e_hat_q)*n[1];
b_e_hat_q[2][2] = TR_b_e_hat_q[2][2] - mu_2bar_gamma/(3.0*mu_)*tr(TR_b_e_hat_q)*n[2];
2µγ
1 – --------- tr [ b̂ n + 1 ] n̂ n + 1
b̂ ne + 1 = b̂ ne +TR
b_e_hat_q[0][1] = b_e_hat_q[1][0] = e TR
TR_b_e_hat_q[0][1] - mu_2bar_gamma/(3.0*mu_)*tr(TR_b_e_hat_q)*n[3]; 3µ
3.50 & up
3.00
2.50
2.00
1.50
1.00
0.75
0.50
Figure 5•25 The further development of the “necking” of the strip with (a) 1/10
vertical stretching, and (b) 1/3 vertical stretching.