You are on page 1of 96

CHAPTER

Three

Variational Methods
Using H0, H1, and H2 Type
Objects

In functional analysis, H0 (= L2 = W0,2), H1 (=W1,2), and H2 (= W2,2) are Sobolev spaces. They are also Hilbert spaces that has the inner product defined. For the users of VectorSpace C++ Library, it is sufficient to know
H0, H1, and H2 type objects are integrable objects (among them H1 and H2 type objects are also differentiable
objects). The applications such as those in variational methods can be easily implemented with H0, H1, and H2
type objects. C++ programs using VectorSpace C++ Library in this chapter are projects contained in project
workspace file Hn.dsw under directory vs\ex\Hn.

3.1 H0 Type Objects


We first look at various integration methods and then inferred from these integration methods the data
abstraction of an integrable object.

3.1.1 Quadrature
Numerical integration is also known as quadrature, which means the process of finding a square equal in area
to a given area. The trapezoidal rule and the Simpsons rule are the most fundalmental ones that are introduced in
calculus1. For a one dimensional function f(x), the trapezoidal rule and Simpsons rule evaluate the areas of the

1. For example, p. 602-609, in T.M. Apostol, 1969, Calculus, 2nd eds., vol. 2, Blaisdell Publishing Company, Waltham,
Mass.

Workbook of Applications in VectorSpace C++ Library 165

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


Trapezoidal rule

Simpsons rule
f(x)
quadratic interpolation

linear interpolation

x0 h = x1 - x0

f(x)

x1

x0

x1

x2

Figure 31 Approximation by two linear interpolation functions (left-hand-side), and by one


quadratic interpolation function (right-hand-side), where h = xi+1 - xi is the size of one segment.
approximated linear and quadratic interpolation functions, respectively. Formula of the approximated linear and
quadratic interpolation functions are
x1

x f ( x )dx

Trapezoidal rule:

Simpsons rule:

1
1
= h --- f ( x 0 ) + --- f ( x 1 ) + O ( h 3 f)
2
2

1
4
1
f ( x )dx = h --- f ( x 0 ) + --- f ( x 1 ) + --- f ( x 2 ) + O ( h 5 f ( 4 ) )
3
3
3
0

x2

Eq. 31

where O( ) indicates order of errors as a function of size h and derivatives of f(x). The two methods are illustrated in Figure 31 . Formula without the necessity of evaluating the function at the end-points (open-type
formula) exists; e.g.,
x5

x f ( x )dx
0

55
5
5
55
= h ------ f ( x 1 ) + ------ f ( x 2 ) + ------ f ( x 3 ) + ------ f ( x 4 ) + O ( h 5 f ( 4 ) )
24
24
24
24

Eq. 32

We notice that f(x0) and f(x5) are not in Eq. 32. So, if a singularity of f(x) presents at any such end-points it can
be avoided. Repeatedly using the trapezoidal rule or Simpsons rule of Eq. 31 in many smaller segments yields
the extended-type formula
Extended trapezoidal rule:
( x N x 0 ) 3 f
1
1
-----------------------------
--f
(
x
)dx
h
f
(
x
)
+
f
(
x
)
+
f
(
x
)
+

+
f
(
x
)
+
f
(
x
)
O
=
+
1
2
N1
x 0
(N + 1)2
2 0
2 N
xN

Extended Simpsons rule:


xN

1
4
2
4
2
1
1
4
f ( x )dx = h --- f ( x 0 ) + --- f ( x 1 ) + --- f ( x 2 ) + --- f ( x 3 ) + + --- f ( x N 2 ) + --- f ( x N 1 ) + --- f ( x N ) + O --------------------4-
(N + 1)
3
3
3
3
3
3
3

Eq. 33
166

Workbook of Applications in VectorSpace C++ Library

H0 Type Objects
The above formula are all expressible as
N

hci f ( xi )

Eq. 34

i=0

where ci is an array of coefficients in Eq. 31, Eq. 32, and Eq. 33. They all use equally spaced intervals (h = x i+1
- xi), and f(xi) are evaluated at positions xi = x0 + i h. For example, an integration problem
2

( x 2 2x + 1 ) dx

Eq. 35

using extended Simpsons rule can be written in C++ with VectorSpace C++ Library as (see project:
extended_simpson)
// QUADRATURE: EXTENDED SIMPSONS RULE
const int N = 11;
// number of integration segments
double c[N] = {1.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, // ci
2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0,
2.0/3.0, 4.0/3.0, 1.0/3.0},
X[2] = {1.0, 2.0},
// starting and end points
h = (X[1]-X[0])/N;
// size of one segment
Quadrature qp(c, X[0], X[1], N);
// domain [a, b], 11 integration points
// THE INTEGRATION
2
H0 x(qp);
( x 2 2x + 1 ) dx = 1/3
C0 area = (x.pow(2) - 2 * x + 1) | J(h);
// 1
cout << area << endl;
// 0.333334
The class Quadrature takes arguments of (1) array of coefficients, (2) starting and end points, and (3) number
of integration points. VectorSpace C++ Library uses integration operator H0::operator | (const J&), where
another new class J, the Jacobian, may take the size of an integration segment as its arguments. The reason of
using class J is to be compatible with more complicated integration domain and will become more evident
later. For now, in view of Eq. 34, we define referential coordinate (with domain [0, 1]) for every integration
segment. Hence, the length of each referential integration segment is || = 1. The actual integration segement
domain [xi, xi+1] is mapped with a linear coordinate transformation rule x = x() = (1-) xi + xi+1. The Jacobain
for the segement is J = dx/d = (xi+1-xi) / || = h, the length of the segment per se. For various quadrature rules
discussed in the above only the values of the coefficient array need to be defined differently.
Higher order approximation can be obtained, in general, with greater number of function evaluations, which,
unfortunately, increases the computational cost. The significant computational improvement can be achieved if
we can reduce the number of function evaluations while maintain higher order approximation. The idea of Gaussian quadrature is to choose not only the values of ci but also the locations for the function evaluation (i.e., the
integration point coordinates). Therefore, we have two times the degree of freedom to improve the order of
approximation. For example, we seek a two-point integration rule to exactly integrate a general cubic polynominal. Let
Workbook of Applications in VectorSpace C++ Library

167

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


f() = 0 + 1 + 22 + 33

Eq. 36

where i are the coefficients for the cubic function f(). First we normalize the integration domain to [-1, 1], and
assume that the integration points are spaced symmetrically and weighted equally. Therefore, W 0 = W1 and 0 =
-1. Integration of Eq. 36 at the interval of [-1, 1] gives

f ( ) d = 2 0 + 2--- 2
3

Eq. 37

The two-point Gaussian quadrature wieghting coefficients Wi at integration points i gives (with i = 0, 1)

f ( ) d W0f(0) + W1f(1) =W0(f(1) + f(1)) = 2W0 ( 0 + 2 12)

Eq. 38

From the right-hand-sides of both Eq. 37 and Eq. 36, we have


2
2 0 + --- 2 = 2W0 ( 0 + 2 12)
3

Eq. 39

For arbitary values of 0 and 2 Eq. 39 must always hold. Therefore, we obtain weightings W0 = W1 = 1, and
integration point coordinates 0 = - 1 = -1 / 3 . Tabulated values of Wi and i with more integration points can
be found in Stroud and Secrest1. Gaussian integration can be applied to integral domains other than the normalized interval [-1, 1]. For example, for an actual integration domain of [1, 2], we can define a linear interpolation
function f(x) = f(), with the natural coordinate (Gaussian integration domain in [-1, 1]), as
1
1
f() = --- (1-) f(x0) + --- (1+) f(x1)
2

Eq. 310

where we can check f(1) = f(x0) and f(1) = f(x1). We can also define a similar linear coordinate transformation
1
1
x() = --- (1-) x0 + --- (1+) x1
2

Eq. 311

We note that the forms of the interpolation function and the coordinate transformation do not have to be the same
as they are in this example. Again, we can check at the starting point x(1) = x0, and at the end point x(1) = x1.
Then, without loss of generality for a multi-dimensional case, we write

f ( x ) dx

f ( x )det x
------ d = f ( x )J d
Wi f ( xi )Ji

i=0

1. A.H. Stroud and D. Secrest, 1966, Gaussian quadrature formulas, Prentice-Hall, Englewood Cliffs, N.J.

168

Workbook of Applications in VectorSpace C++ Library

Eq. 312

H0 Type Objects
where is the integration domain, and is the normalized integration domain. Define J = x/ as the Jacobian matrix, and J = det J =det ( x/ ) is the Jacobian. In an one-dimensional case, if the coordinate transformation rule x() is chosen to be linear such as Eq. 310, Ji = dx/d = (x1-x0)/2 equal the same constant.
Comparing Eq. 312 with Eq. 34, we find that (1) the constant Ji is in place of segment size h, (2) the
wieghting coefficients Wi is in place of the coefficients ci and (3) the integration point coordinates in Eq. 312 is
now taking from tabulated numbers instead of simply computed from a equally spaced formula of xi = x0 + i h.
The integration problem in Eq. 35,

1( x 1 ) 2 dx
2

using Gauss quadrature, can be re-written in C++ with VectorSpace C++ Library as (project:
linear_coordinate_transformation)
double X[2] = {1.0, 2.0};
Quadrature qp(1, 2);
H0 z(qp),
x = (1-z) /2*X[0] + (1+z)/2 * X[1];
J omega((X[1]-X[0])/2);
C0 area = (x-1).pow(2) | omega;
cout << area << endl;

// integration domain [1, 2]


// one dimension, 2 integration points
// natural coordinate
// x() = (1/2)(1-) x0 + (1/2)(1+) x1
// J = dx/d = (x1-x0)/2
// Eq. 35; analytical value = 1/3
// 0.333334

The Gaussian quadrature is the default integration method in VectorSpace C++ Library, because of its higher
order approximation. Database for both the weighting coefficients and integration points of the Gaussian quadrature are hidden from end-users. The users, however, need to input number of dimensions and number of integration points in the constructor of class Quadrature. In the present example, since the coordinate transformation is
linear the Jacobian is constant everywhere along the integral line; i.e., J = (x1-x0)/2, where 2 is the length of the
integration domain, since the natural coordinate is defined in the interval of [-1, 1]. The result of the integration is 0.333334. A quadratic coordinate tranformation case is presented later. We note that the restriction of constant values for the Jacobian can be relaxed when we introduce H1 type later.
We have seen various integration methods, and we have inferred the basic elements in object-oriented modeling of an integrable class. Now we are ready to deduce the data abstraction for constructing classes in H0 type.
H0 type objects are generalization of C0 type objects with integration capability. As in C0 type objects, H0 type
objects are subdivided into primary objects and utility objects. The primary objects include Integrable_Scalar,
Integrable_Vector, and Integrable_Matrix. These objects deserve detailed description. For the utility objects,
Integrable_Subvector and Integrable_Submatrix, it is suffice to say that they are mostly comformable to their C0
counterparts.

3.1.2 Integrable_Scalar
An Integrable_Scalar, H0::H0(const Quadrature&), contains a reference to a Quadrature class instance,
and a pointer array of C0 *u. The dual abstraction, discussed on page 97, is also used to model the high-level

Workbook of Applications in VectorSpace C++ Library

169

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

mathematics and to encapsulate the details of low-level memory management. The pointer array of C0, u, is
referring to double *v.

Integrable_Scalar Object

Quadrature Point Values

x
C0* of Scalaru
TABLE 3.1 Dual abstraction of an Integrable_Scalar.

Physical Memory

double*v

Constructors
Two examples of using variable dedicated constructor for H0 type Integrable_Scalar have been shown on
page 167 and page 169 for Simpsons rule and Gaussian quadrature, respectively. We show a few more non-trivial examples, in the followings. Consider a diffusion problem, e.g., heat conduction or chemical diffusion, in the
form of a differential equation1
2

d u
--------2 = f ( x ) , with 0 < x < 1, u ( 0 ) = , u ( 1 ) =
dx

Eq. 313

where f(x) is the source term. The solution to Eq. 313 can be expressed in integral form as
1

u( x) =

g ( x, )f ( )d + ( 1 x ) + x

Eq. 314

where g(x, ) is Greens function. The physical interpretation of the Greens function is that g(x, ) is the temperature (or concentration) sampling at x when a unit concentrated point source is located at . Therefore, g(x, )
satisfies Eq. 313; i.e., with g(x, ) in place of u(x) in the differential equation. We also require, at the location x
= , g(x, ) to be continuous. And the net flux of the infinitesimal control line segment at x = equals to the
source intensity; i.e., g(+, ) - g(-, ) = -1, which is also known as the jump condition. From the above conditions, the Greens function can be solved as
x ( 1 ), 0 < x <
g ( x, ) =
( 1 x ), < x < 1

Eq. 315

Therefore, Eq. 314 can be re-written as


x

u ( x ) = ( 1 x ) f ( )d+ x ( 1 )f ( )d + ( 1 x ) + x
0

1. p. 42 in I. Stakgold, 1979, Greens function and boundary value problems, John Wiley & Sons, New York.

170

Workbook of Applications in VectorSpace C++ Library

Eq. 316

H0 Type Objects
where at interval [0, x] of the integration domain < x, so the second line of Eq. 315 is applicable, and at the
interval [x, 1] of the integration domain, x < , the first line of Eq. 315 is applicable .
For a specific case with source distribution as f(x) = sin (x), and homogeneous boundary conditions = =
0, we can compute ten point values of the solution u(x) at interval of h = 0.1. Program Listing 31 implemented
the solution using Eq. 316. The analytical solution corresponding to this source distribution is u = - (1/ 2)
sin(x), which is used to compare with the computed result of the integral equation. They only differs after the
sixth digit after the decimal point ( see TABLE 3.2.)
#include include/vs.h
int main() {
double const PI = 3.141592654;
double const alpha = 0.0; double const beta = 0.0;
double x = 0.0,
w[11] = {1.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 1.0/3.0};
for(int i = 0; i < 11; i++) {
Quadrature q1(w, 0.0, x, 11), q2(w, x, 1.0, 11);
H0 z1(q1), z2(q2),
f_1 = sin(PI*z1), f_2 = sin(PI*z2);
C0 integ_1, integ_2;
if(i !=0) integ_1 &= (1-x)*( (z1*f_1) | J(x/10.0); else integ_1 &= C0(0.0);
if(i !=10) integ_2 &= x*( ((1-z2)*f_2) | J((1-x)/10.0); else integ_2 &= C0(0.0);
double u = (double)(integ_1+integ_2) + (1-x)*alpha+x*beta;
cout << u( << x << ): << u << endl;
if(i != 10) x += 0.1;
}
return 0;
}

==0
extended Simpsons rule

f(x) = sin x
x

( 1 x ) f ( )d + x ( 1 )f ( )d

with boundary terms (1-x) + x

Listing 31 Solving diffusion problem using integral expression (project: green_diffusion_equation).

- (1/ 2) sin(x)

Program Listing 31

0.0

0.000000

0.000000

0.1

0.031310

0.031311

0.2

0.059555

0.059555

0.3

0.081971

0.081970

0.4

0.096362

0.096361

0.5

0.101321

0.101320

0.6

0.096362

0.096361

0.7

0.081971

0.081970

0.8

0.059555

0.059555

TABLE 3.2. Comparison of analytical solution and the


result computed from integral expression Eq. 316.

Workbook of Applications in VectorSpace C++ Library

171

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


x

- (1/ 2) sin(x)

Program Listing 31

0.9

0.031310

0.031311

1.0

0.000000

0.000000

TABLE 3.2. Comparison of analytical solution and the


result computed from integral expression Eq. 316.
For heat conduction or chemical diffusion problem as shown in Eq. 313, the thermal diffusivity (or the diffusion coefficient) can be a function of positions (x). We may have a slightly different problem as
d
du
------ k ( x ) ------ = f ( x ), 0 < x < 1 ;u ( 0 ) = 0, u( 1 ) = 0
dx
dx

Eq. 317

The solution can be expressed in integral form as


u( x ) =

g ( x, )f ( )d

Eq. 318

The Greens function should satisfy Eq. 317 and should be continuous at x = . The jump condition is
k()[g(+,)-g(-, )] = -1. These conditions lead to the Greens function for this problem as

g ( x, ) =

- dy,
--------k(y)

0<x<

Eq. 319

- dy,
--------k(y)

<x<1

Substituting Eq. 319 into Eq. 318, with the case of k(x) = (1+x), and f(x) = x, gives
u(x) =

ln ( 1 + )f ( )d + ln ( 1 + x ) f ( )d
0

Eq. 320

The exact solution for this case is


uexact = -x2/4 +x/2

Eq. 321

Program Listing 32 implements Eq. 320, which are codes from the Program Listing 31 with only very slight
modifications. The results of Program Listing 32 are listed in TABLE 3.2. for comparison with the analytical
solution. Only last three points in the interval of [0.8, 1.0] has 1.e-6 in error. We emphasize that Eq. 316 and Eq.
320 are much more complicated than that of the corresponding analytical solutions. However, analytical solutions are only possible when the given f(x) and k(x) happen to give an analytical solvable differential equations,
while the Greens function method is quite general for less restricted forms of f(x) and k(x). This concludes the
example for the Integrable_Scalar object of H0 type.
172

Workbook of Applications in VectorSpace C++ Library

H0 Type Objects
#include include/vs.h
int main() {
double x = 0.0,
w[11] = {1.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 1.0/3.0};
for(int i = 0; i < 11; i++) {
Quadrature q1(w, 0.0, x, 11), q2(w, x, 1.0, 11);
H0 z1(q1), z2(q2);
C0 integ_1, integ_2;
if(i !=0) integ_1 &= ( (z1*log(1+z1)) | J(x/10.0); else integ_1 &= C0(0.0);
if(i !=10) integ_2 &= log(1+x)*( z2 | J((1-x)/10.0); else integ_2 &= C0(0.0);
double u = (double)(integ_1+integ_2) ;
cout << u( << x << ): << u << endl;
if(i != 10) x += 0.1;
}
return 0;
}

extended Simpsons rule

f(x) = x, k(x) = 1+x


x

ln ( 1 + )f ( )d + ln ( 1 + x ) f ( )d
0

Listing 32 Solving diffusion problem with k(x) = 1+x and f(x) = x using integral expression (traget:
green_diffusion_variable_conductivity).

-x2/4 +x/2

Program Listing 32

0.0

0.000000

0.000000

0.1

0.047500

0.047500

0.2

0.090000

0.090000

0.3

0.127500

0.127500

0.4

0.160000

0.160000

0.5

0.187500

0.187500

0.6

0.210000

0.210000

0.7

0.227500

0.227500

0.8

0.240000

0.240001

0.9

0.247500

0.247501

1.0

0.250000

0.250001

TABLE 3.3. Comparison of analytical solution and the


result computed from integral expression Eq. 320.

Workbook of Applications in VectorSpace C++ Library

173

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

The constant strings used for the virtual constructors (for example, using macro definition H0 x =
INTEGRABLE_SCALAR(const char*, ...)) and the autonomous virtual constructor (for example, using H0 x
= H0(const char*, ...)) are shown in the following box.

virtual constructor string

VectorSpace C++ library definition

priority

by reference
H0&
H0 type Integrable_Scalar object
1
H0*
a pointer to H0 type Integrable_Scalar object
2
double*, const Quadrature&, int, int
3
double pointer, Quadrature, m_row_size, m_col_size
by value
const Quadrature&
const H0&
const H0*

Quadrature
H0 type Integrable_Scalar object
pointer to H0 type Integrable_Scalar object

4
5
6

Strings in H0 virtual constructor for Integrable_Scalar object.

Operators and Functions


The most important operator for the Integrable_Scalar object is the integration operator. The integration
operator is H0::operator | (const J&) that takes a Jacobian class J(const H0&) or J(const double&) as its
argument. We notice that unless we have H1 type object capability we can not do the differentiation of the coordinate transformation x() to construct the Jacobian class, such as J(d(x)), where x is an H1 object, and d(x)
returns an H0 object that contains the derivative information of the x. For the time being, as long as the coordinate transformation x() is chosen to be linear we can use J(const double& J) to define the corresponding constant Jacobian easily, where the single argument is a reference to a const double, and its value is J = (xend point xstarting point)/2, as shown in the above example.
The rest of the operators and functions are listed in the following box. They are mostly comformable to the
operators and functions of the Scalar object. Promotion of C0 type to H0 type object by binary operators is a
common practice just as in standard C++ language. For example,
H0 x;
C0 y;
H0 z1 = x+y;
H0 z2 = y+z;

// invoke H0::operator +(const C0&);


// invoke H0s friend operator +(const C0&, const H0&)

The second operator invoked, operator +(const C0&, const H0&) is a binary operator which is declared a
friend function (operator) to H0 class. These operators, needed for the promotion operation, are not listed in the
box for simplicity.

174

Workbook of Applications in VectorSpace C++ Library

H0 Type Objects
operator or function

VectorSpace C++ library definition

remark

symbolic operators
H0& operator &= ( )
H0& operator = ( )
H0 operator & ( ) const
H0 operator && () const
H0 operator | ( ) const
H0 operator || () const

assignment by reference
assignment by value
column concatenation
one-by-one column concatenation
row concatenation
one-by-one row concatenation

arithmatic operators
H0 operator + ( ) const
H0 operator - ( ) const
H0 operator + (const H0&) const
H0 operator - (const H0&) const
H0 operator * (const H0&) const
H0 operator / (const H0&) const
H0& operator += (const H0&)
H0& operator -= (const H0&)
H0& operator *= (const H0&)
H0& operator /= (const H0&)

positive
negative
addition
subtraction
multiplication
multiplication
replacement addition
replacement subtraction
replacement multiplication
replacement division

unary
unary

logic operators
int operator == (const H0&) const
int operator != (const H0&) const
int operator >= (const H0&) const
int operator <= (const H0&) const
int operator > (const H0&) const
int operator < (const H0&) const

equal
not equal
greater or equal
less or equal
greater
less

TRUE == 1
FALSE == 0

functions
H0 pow(int) const
H0 sqrt(const C0&) const
H0 exp(const C0&) const
H0 log(const C0&) const
H0 sin(const C0&) const
H0 cos(const C0&) const

power
square root
exponent
log
sin
cos

Partial listing of H0 type Integrable_Scalar class arithmetic operators, logic operators and functions.

Workbook of Applications in VectorSpace C++ Library

175

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

3.1.3 Integrable_Vector
Constructors
A dedicated constructor of an Integrable_Vector, H0::H0(int, double*, const Quadrature&), contains a reference to a Quadrature instance, and a pointer array of C0 *u. The dual abstraction is used. The pointer array
of C0, u, is referring to a double *v.

Integrable_Vector Object

Quadrature Point Values

x
C0* of Vectoru
TABLE 3.4. Dual abstraction of an Integrable_Vector.

Physical Memory

double*v

Following is an example of an array of quadratic interpolation functions N constructed as an H0 type


Integrable_Vector object. The access of each element of the Integrable_Vector is done by the selector,
H0::operator [](int) (see project: quadratic_coordinate_transformation).

double f(double x) { return (x-1)*(x-1); }


Quadrature qp(1, 2);
H0 z(qp),
N(3, (double*)0, qp);
N[0] = (z-1)*z/2.0;
N[1] = (1-z.pow(2));
N[2] = (z+1)*z/2.0;
H0 y = N[0]*f(1.0)+N[1]*f(1.5)+N[2]*f(2.0);
C0 area = y | J(0.5);
cout << area << endl;

//
// 1-dimension, 2-points Gaussian
// natural coordinates
// Integrable_Vector object of H0 type
// N0 = (-1)/2
// N1= 1-2
// N2 = (+1)/2
// y = Nifi
// H0::operator | (const J&)
// 1/3

In this case the quadratic coordinate transformation rule is implicitly chosen as


1
1
x() = --- (-1) x0 + (1-2) x1 + --- (+1) x2
2

Eq. 322

We mentioned in previous section on the subject of Integrable_Scalar that since we have not yet introduced H1
type objects, we need a linear coordinate transformation to have constant values of the Jacobian throughout the
integration domain. We can make Eq. 322 consistent with a linear coordinate transformation rule by enforcing
x1 = (x0+x2)/2
i.e., x1 has to be the middle point of the segment. Substituting this relation into Eq. 322 to eliminate x1 yields
1
1
x() = --- (1-) x0 + --- (1+) x2
2

176

Workbook of Applications in VectorSpace C++ Library

H0 Type Objects

f(x2) = 3
f(x3) = 2
f(x1) = 2

f(x0) = 1

x2 = (1,1)

x3 = (0,1)

x1 = (1,0)
x0 = (0,0)
Figure 32 Integration of a plane surface with a square integration domain.

which is exactly the linear coordinate transformation rule of Eq. 311. Therefore, we have J = (2-1)/2 = 0.5 as
used in the above example.
We show an example of a 2-D problem using Gaussian quadrature. Again, without H1 type objects for differentiation operation, we restrict the integration domain to be a square or a rhombic region in order to have constant Jacobian everywhere. In this example, a set of bilinear interpolation functions are used
1
1
1
1
f(, ) = --- (1)(1) f(x0) + --- (1+)(1) f(x1) + --- (1+)(1+) f(x2) + --- (1)(1+) f(x3)
4

Eq. 323

Assuming a plane as shown in , f(x0) = 1, f(x1) = 2, f(x2) = 2, and f(x3) = 3, where x0 = (0, 0), x1 = (1, 0),x2 = (1,
1), and x3 = (0, 1). The constant Jacobian of the problem is J = 1/4, where the area of the referential domain
1 1 and 1 1 , is 4. (in project: integration_2d).
double f[4] = {1.0, 2.0, 2.0, 3.0};
// f(xi)
Quadrature qp(2, 4);
// 2-D, and 2x2 (= 4) integration points
H0 z(2, (double*)0, qp), zai, eta;
// natural coordinates
zai &= z[0], eta &= z[1];
// alias of elements in the Integrable_Vector
C0 volume = ((1-zai)*(1-eta)/4 *f[0]
// f ( , ) d

+ (1+zai)*(1-eta)/4*f[1]
+(1+zai)*(1+eta)/4*f[2]
+(1-zai)*(1+eta)/4*f[3]) | J(0.25);
cout << volume << endl;
// 2.0

Workbook of Applications in VectorSpace C++ Library

177

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

The constant strings used for the virtual constructors (for example, using macro definition in H0 x =
INTEGRABLE_VECTOR(const char*, ...)) and the autonomous virtual constructor (for example, using H0 x
= H0(const char*, ...)) are shown in the following box.
virtual constructor string
by reference
H0&
H0*
int, double*, const Quadrature&,
int, int
by value
int, const Quadrature&
const H0*
int, H0&, int, const Quadrature

VectorSpace C++ library definition

priority

H0 type Integrable_Vector
a pointer to H0 type Integrable_Vector
length, double* != 0, Quadrature
m_row_size, m_col_size

length, Quadrature
H0*
length, H0, starting index, Quadrature
(the only one for reference Integrable_Vector)

Strings in H0 virtual constructor for H0 type Integrable_Vector class.

Operators and Functions


In the above example the integration operator is applied on Integrable_Scalar objects of H0 type, which are
components of an Integrable_Vector object of H0 type. The integration operator can be applied to an H0 type
Integrable_Vector object directly. However, the return value of the integration operator in this case is a Vector of
C0 type instead of a Scalar of C0 type. The rest of the operators and functions are listed in the following box.
They are mostly conformable to the operators and functions of the Vector objects of C0 type.

178

Workbook of Applications in VectorSpace C++ Library

H0 Type Objects
operator or function

VectorSpace C++

remark

symbolic operators
H0& operator &= ( )
H0& operator = ( )
H0& operator [] (int)
H0 operator & ( ) const
H0 operator && () const
H0 operator | ( ) const
H0 operator || ( ) const

assignment by reference
assignment by value
selector
column concatenation
one-by-one column concatenation
row concatenation
one-by-one row concatenation

arithmetic operators
H0 operator ~ ( ) const
H0 operator + ( ) const
H0 operator - ( ) const
H0 operator + (const H0&) const
H0 operator - (const H0&) const
H0 operator * (const H0&) const
H0 operator %(const H0&) const
H0 operator / (const H0&) const
H0& operator += (const H0&)
H0& operator -= (const H0&)
H0& operator *= (const H0&)
H0& operator /= (const H0&)

transposed (into a row vector)


return matrix
positive (primary casting)
unary
negative
unary
addition
subtraction
multiplication by a scalar; scalar productof two vectors
tensor product of two vectors
division (by a scalar or a matrix only)
replacement addition
replacement subtraction
replacement multiplication (by a scalar only)
replacement division (by a scalar only)

logic operators
int operator == (const H0&) const
int operator != (const H0&) const
int operator >= (const H0&) const
int operator <= (const H0&) const
int operator > (const H0&) const
int operator < (const H0&) const

equal
not equal
greater or equal
less or equal
greater
less

return scalar

return matrix
return matrix

TRUE == 1
FALSE == 0

functions
int length() const
double norm(int = 2) const
double norm(const char*) const
H0 pow(int) const
H0 sqrt(const H0&) const
H0 exp(const H0&) const
H0 log(const H0&) const
H0 sin(const H0&) const
H0 cos(const H0&) const

length of the Integrable_Vector


1-norm or 2-norm
infinite-norm takes strings infinity, or maximum
power (applied to each element of the Integrable_Vector)
square root(applied to each element of the Integrable_Vector)
exponent (applied to each element of the Integrable_Vector)
log (applied to each element of the Integrable_Vector)
sin (applied to each element of the Integrable_Vector)
cos (applied to each element of the Integrable_Vector)
Partial listing of Integrable_Vector object arithmatic operators, logic operators and functions.
Workbook of Applications in VectorSpace C++ Library

179

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

3.1.4 Integrable_Matrix
Constructors
A dedicated constructor of an Integrable_Matrix, H0::H0(int, int, double*, const Quadrature&), contains a
reference to a Quadrature instance, and a pointer array of C0 *u (pointer to C0 type Matrix object). The dual
abstraction is also used. The pointer array of C0, u, is referring to a double *v.

Integrable_Matrix Object

Quadrature Point Values

x
C0* of Matrixu
TABLE 3.5. Dual abstraction of an Integrable_Matrix.

Physical Memory

double*v

A simple example of an Integrable_Matrix is the consistent mass matrix; e.g., M in Eq. 3217 on
page 258, generated from the tensor product operation (using % in VectorSpace C++ Library ) of two
Integrable_Vector objects of H0 type. Integrable_Matrix is often encountered in variational calculus to be introduced later in this Chapter.
The constant strings used for the virtual constructors (for example, using macro definition in H0 x =
INTEGRABLE_MATRIX(const char*, ...)) and the autonomous virtual constructor (for example, using H0 x
= H0(const char*, ...)) are shown in the following box.

virtual constructor string


by reference
H0&
H0*
int, int, double*,
const Quadrature&, int, int
by value
int, int, double*,
const Quadrature&, int, int
int, int, const Quadrature&
int, int, const double*,
const Quadrature&, int, int
int, int, H0&, int, int,
const Quadrature&

VectorSpace C++ library definition

priority

H0 type Matrix
a pointer to H0 type Matrix
row-length, column-length, double* != 0,
memory-row-length, memory-column-length

row-length, column-length, double* = 0,


memory-row-length, memory-column-length
row-length, column-length
row-length, column-length, double*,
memory-row-length, memory-column-length
row-length, column-length, H0&,
starting row-index, starting column-index
(the only one for reference Integrable_Matrix)

Strings in H0 virtual constructor for H0 type Integrable_Matrix class.

180

Workbook of Applications in VectorSpace C++ Library

10

11
12
13
14

H0 Type Objects
operator or function

VectorSpace C++ library definition

remark

functions
H0 pow(int) const
H0 sqrt(const H0&) const
H0 exp(const H0&) const
H0 log(const H0&) const
H0 sin(const H0&) const
H0 cos(const H0&) const

power (applied to each element of the Matrix)


square root (applied to each element of the Matrix)
exponent (applied to each element of the Matrix)
log (applied to each element of the Matrix))
sin (applied to each element of the Matrix)
cos (applied to each element of the Matrix

matrix algebra fucntions


int rank() const
H0 identity() const
H0 cond() const
H0 inverse() const
H0 det() const

rank of a Matrix
identity Matrix
condition number of a Matrix
inverse of a Matrix
determinant of a Matrix

Partial listing of H0 type Integrable_Matrix class arithmetic operators, logic operators and functions.

Operators and Functions


The operators and functions are listed in the above box. They are mostly conformable to the operators and
functions of the Matrix object of C0 type.

3.1.5 Utility Integrable ObjectsIntegrable_Subvector and Integrable_Submatrix


The Integrable_Subvector and the Integrable_Submatrix objects of H0 type are straight-forward extensions
from the Subvector and Submatrix objects of C0 type. However, it is not necessary to have Integrable_Basis
object of H0 type. We can simply use primary integrable objects in Sections 3.1.2 to 3.1.4 with the Basis object
of C0 type to make Integrable_Subvector or Integrable_Submatrix objects. In Fourth-order Differential Equation on page 205, many examples of alternative but equivalent approaches of using different utility integrable
objects are shown. With these flexible utility integrable objects, the C++ code of the mathematical implementations can be made to look much closer to the mathematical expressions we find in the mathematics literature.

Workbook of Applications in VectorSpace C++ Library

181

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


operator or function

VectorSpace C++ library definition

symbolic operators
H0& operator &= ( )
H0& operator = ( )
H0& operator [ ] (int)
H0& operator( )(int)
H0& operator ( )(int, int)
H0 operator & ( ) const
H0 operator && () const
H0 operator | ( ) const
H0 operator || ( ) const

assignment by reference
assignment by value
row selector
column selector
element selector
column concatenation
one-by-one column concatenation
row concatenation
one-by-one row concatenation

arithmetic operators
H0 operator + ( ) const
H0 operator - ( ) const
H0 operator + (const C0&) const
H0 operator - (const C0&) const
H0 operator * (const C0&) const
H0 operator / (const C0&) const
H0& operator += (const C0&)
H0& operator -= (const C0&)
H0& operator *= (const C0&)
H0& operator /= (const C0&)

positive (primary casting)


unary
negative
unary
addition
subtraction
multiplication
division (by Integrable_Scalar or Integrable_Matrix only)
replacement addition
replacement subtraction
replacement multiplication (by an Integrable_Scalar only)
replacement division (by an Integrable_Scalar only)

matrix algebra operators


H0 operator ~ ( ) const
H0 operator !( ) const

transpose
matrix decomposition

logic operators
int operator == (const H0&) const
int operator != (const H0&) const
int operator >= (const H0&) const
int operator <= (const H0&) const
int operator > (const H0&) const
int operator < (const H0&) const

equal
not equal
greater or equal
less or equal
greater
less

functions
int row_length() const
int col_length() const
H0 norm(in) const
H0 norm(const char*) const

row-length of the Integrable_Matrix


column-length of the Integrable_Matrix
1 (maximum column-sum)-norm or 2 (spectral)- norm
infinity(max row-sum),Forbenisu(Forbenius-norm)

Partial listing of H0 type Integrable_Matrix class arithmetic operators, logic operators and functions.

182

remark

Workbook of Applications in VectorSpace C++ Library

TRUE == 1
FALSE == 0

H1 Type and H2 Type Objects


3.2

H1 Type and H2 Type Objects

We can consider H1 and H2 types as natural extensions of C1 and C2 types. That is the high-level data
abstraction in the dual abstraction of H1 and H2 type object is a pointer array to C1 and C2 type objects (i.e.,
C1*, or C2*), and the length of the pointer array equals the number of quadrature points. The low-level data
abstraction is pointers to double (double*) to represent the memory space of the base point, tangent, and tangent
of tangent, in which the values of all quadrature points are connected together in a continuous memory space for
efficient memory management. A cross-relation of the dual abstraction is shown in Figure 33. The high-level
entities, in this case, three conceptually separate C1 type objects have their sub-entities (base points and tangents), share the continuous memory spaces.
mathematical abstraction
C1( tangent bundle)*u

physical memory space


double *v, *dv
quadrature
point # 1

base
point
C1 *u;

tangent

quadrature
point # 2
quadrature
point # 3
double * v

double* dv
quadrature
point # 1

quadrature
u[0] point # 1

quadrature
point # 2

quadrature
u[1] point # 2

u[2] quadrature
point # 3

quadrature
point # 3
(assume spatial dimension = 3)

Figure 33 Cross relation by dual representation of an H1 type object.

3.2.1

Integrable_Tangent_Bundle / Integrable_Vector_of_Tangent_Bundle

Integrable_Tangent_Bundle and Integrable_Vector_of_Tangent_Bundle are two H1 type objects that are the
integrable extension of Tangent_Bundle and Vector_of_Tangent_Bundle objects of C1 type.

Constructors
The dedicated constructors for an Integrable_Tangent_Bundle are

Workbook of Applications in VectorSpace C++ Library

183

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


H1::H1(const Quadrature&)
H1::H1(double* v, const Quadrature&)
H1::H1(double* v, int spatial_dimension, const Quadrature&)

The dedicated constructor for an Integrable_Vector_of_Tangent_Bundle is


H1::H1(int vector_size, double* v, const Quadrature&)
For the dedicated constructor, the size of the vector equals the number of the spatial dimension.
The constant strings used for the virtual constructors and autonomous virtual constructor are listed in the
following two boxes. The macro defintions used for the virtual constructors of the Integrable_Tangent_Bundle
and the Integrable_Vector_of_Tangent_Bundle are
H1 x = INTEGRABLE_TANGENT_BUNDLE(const char*, ...);
H1 x = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(const char*, ...);
respectively. And, H1 x = H1(const char*, ...) is used for autonomous virtual constructors.

virtual constructor string

VectorSpace C++ library definition

by reference
H1&
H1 type Matrix
H1*
a pointer to H1 type Matrix
double*, double*, Quadrature
v, dv,
double*, double*, int, Quadraturev, dv, spatial dimension,
by value
Quadrature,
int, Quadrature
memory-row-length, memory-column-length
const double&, const double&, v, dv, (for spatial dimension = 1 only)
const Quadrature&
const double*, const double*,
v, dv,
int, Quadrature&
spatial dimension
const H0&, const H0&
base point, tangent
const H0*, const H0*
base point, tangent
const H1&
Integrable_Tangent_Bundle
const H1*
Integrable_Tangent_Bundle*
Strings in H1 virtual constructor for H1 type Integrable_Tangent_Bundle class.

184

Workbook of Applications in VectorSpace C++ Library

priority

1
2
7
8
3
4
5
6
9
10
11
12

H1 Type and H2 Type Objects


virtual constructor string

VectorSpace C++ library definition

by reference
H1&
H1*
int, int, double*, double*,
Quadrature, int, int
by value
int, int, Quadrature,
const H0&, const H0&
const H0*, const H0*
int, const H1*
const H1&
const H1*

priority

H1 type Matrix

a pointer to H1 type Matrix

vector size, spatial dimension, v, dv,


14
quadrature, memory row size, and column size
vector size, spatial dimension
base point , tangent
base point, tangent
vector size, Integrable_Tangent_Bundle*
Integrable_Vector_of_Tangent_Bundle
Integrable_Vector_of_Tangent_Bundle*

13

15

Strings in H1 virtual constructor for H1 type Integrable_Vector_of_Tangent_Bundle class.

1-D Integration: We seek the integration of the example shown on page 176. That is
x2

x3
( x 1 ) 2 dx = x x 2 + ----3-
x0

x2

Eq. 324
x0

The same quadratic coordinate tranformation rule


1
1
x() = --- (-1) x0 + (1-2) x1 + --- (+1) x2
2

is used, and recall from Eq. 312 the 1-D version is

x
f ( x ) dx f ( x ) ------ d = f ( x )J d W i f ( x i )J i

i=0

On page 176 we restrict ourselves to have equal-spaced points of x0, x1, and x2, in order to have a constant Jacobian throughout the integration domain. Now Jacobian of the coordinate tranformation rule in this case is an
Integrable_Scalar of H0 type
dx ( )
J = -------------d

Eq. 325

This numerical integration problem can be coded with VectorSpace C++ Library as (project: integration_1d)
double x[3] = {1.0, 1.5, 3.0};
Quadrature qp(1,3);

// x=[1, 3], analytical value form Eq. 324 is 8/3

Workbook of Applications in VectorSpace C++ Library

185

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


H1 zai(qp),
X = -(1-zai)*zai/2.0 * x[0]
+(1-zai)*(1+zai) * x[1]
+zai*(1+zai)/2.0 * x[2];
C0 v = (((H0)X)-1).pow(2) | J(d(X));
cout << v << endl;

// Integrable_Tangent_Bundle

( x 1 ) 2 dx

//
// 2.66667,

2
= 2 --3

Now the restriction of requring the three nodes to be equally spaced is lifted. The Jacobian is simply J(d(X)) as
in the above program.
Line Integration in 2-D: Consider an example of line integration on a two-dimensional space. We first look at
the arc length method in calculus. We seek the length of a circle in the first quadrant (see the right-hand-side of
Figure 34)
x2 + y 2 = 1
The value of the ordinate y can be considered as a function of x as
f( x) y =

1 x2

Eq. 326

The arc length, s, of a function f(x) is (see the middle of Figure 34)
s ( x i ) 2 + f ( x i + 1 ) f ( x i ) 2

Eq. 327

by applying pythagorean law. For differentiable function f(x) at the limit of x 0 we have the arc-length
method formula
s =

1 + f ( x )2 dx

Eq. 328

y = f(x)

y
arc length = s
r

x 2 + y 2 = r2

f(xi+1)-f(xi)
x
x
Figure 34 Use arcs to approximate the length of a curve.

186

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


An alternative approach is found in finite element method, which is also adopted by boundary element
method. A point in a curved element is represented by a position vector r ={x, y}T as shown in Figure 35. We
use quadratic interpolation functions for coordinate transformation of the position vector, r, with three nodal
coordinates (x0, y0), (x1, y1), and (x2, y2).
1
1
x() = --- (-1) x0 + (1-2) x1 + --- (+1) x2
2

1
1
y() = --- (-1) y0 + (1-2) y1 + --- (+1) y2
2

Eq. 329

where is the parameter for the coordinate transformation of x and y coordinates. An infinitesimal length of the
curve dr can be obtained as (see Figure 35)
2

dr =

dx + dy d
d
d

Eq. 330

again, by applying pythagorean law. The integrand in Eq. 330 is


2

dx + dy
d
d

= dr
d

J
2

Eq. 331

That is the Euclidean norm of Jacobian of the coordinate transformation rule. Therefore, we have
Eq. 332

dr = J 2 d

This integration formula is simply written consistent with the coordinate transformation method.
Program Listing 33 implements the arc length method with Eq. 326 and Eq. 328, and the coordinate transformation method with Eq. 329 and Eq. 330. The program computes the line integration using arc length
method, if the macro definition __ARC_LENGTH is defined at the compile time. Otherwise, the default

dr

r
dy
y

r
dx
x

Figure 35 Derivatives of the position vector r = {x, y}T .

Workbook of Applications in VectorSpace C++ Library

187

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

method is the coordinate transformation method.


The function sqrt() is only defined for C0 and H0 types but can be extended easily for H1 type by an ad
hoc implementation of a free function sqrt(), which takes an Integrable_of_Tangent_Bundle of H1 type argument. The virtual constructor of the Integrable_Tangent_Bundle uses macro definition as in
H1 sqrt(const H1& a) {
return INTEGRABLE_TANGENT_BUNDLE(
const H0&, const H0&, sqrt((H0)a), d(a)/2.0/sqrt((H0)a) );
}
.
#include "include\vs.h"
#define NODE_NO 5
#if defined(__ARC_LENGTH)
H1 sqrt(const H1& a) {
return INTEGRABLE_TANGENT_BUNDLE("const H0&, const H0&",
sqrt((H0)a), d(a)/2.0/sqrt((H0)a));
}
#endif
int main() {
const double r = 1.0; const double PI = 3.141592654;
double X[NODE_NO][2];
for(int i = 0; i < NODE_NO; i++) {
X[i][0] = r*cos(((double)(i+1))*PI/(2.0*(NODE_NO-1)));
#ifndef __ARC_LENGTH
X[i][1] = r*sin(((double)(i+1))*PI/(2.0*(NODE_NO-1)));
#endif
}
Quadrature qp(1, 4);
H1 zai(qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3, 1, qp),
x, y;
N[0] = -zai*(1-zai)/2; N[1] = (1+zai)*(1-zai); N[2] = zai*(1+zai)/2;
C0 length = 0.0;
for(int i = 0; i < (NODE_NO-1)/2; i++) {
x = N[0]*X[i+2][0]+N[1]*X[i+1][0]+N[2]*X[i][0];
#if defined(__ARC_LENGTH)
y = sqrt(pow(r,2)-x.pow(2));
length += (sqrt(1.0+(d(y)/d(x)).pow(2)) | J(d(x)));
#else
y = N[0]*X[i+2][1]+N[1]*X[i+1][1]+N[2]*X[i][1];
length += (sqrt(d(x).pow(2)+d(y).pow(2))) | J(1.0);
#endif
}
cout << length << endl;
return 0;
}

nodal coordinates (xi, yi)

1
N0() = --- (-1), N1()= (1-2)

2
1
N2()= --- (+1)
2

coordinate transformation rule


x()=Ni()xi , y()=Ni()yi
arc length method
s =

1 +f ( x )2 dx

integration of Jacobian of transformation rule


2

dr =

dx + dy d = J d
2
d
d

Listing 33 Line integration using the arc length method or the coordinate transformation method (project:
line_integration_2d).

188

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


The results of the computation are listed in TABLE 3.6. The analytical result for the length of a quadrant of a
circle with unit radius is 2(1)2/4 1.570796327. The accuracy of the arc length method seems to be far superior than that of the integration of the coordinate transformation method. For both methods, the smaller the line
segments for integration the better the accuracy.

Number
of Nodes

Arc Length

Coordinate
Transformation

1.57077

1.56245

1.57079

1.57020

1.57079

1.57068

1.57079

1.57076

TABLE 3.6. Line integration using 3 to 9 nodes.


Surface and Volume Integration in 3-D: Next we consider an example of integrating the volume and surface
area of a sphere with unit radius, numerically. The analytical value of the volume of a sphere is -34- r3
4.188790203 (with r = 1), and surface area of a unit sphere is 4r2 12.56637061 (with r=1). The nodal coordinates of any point on a unit sphere can be computed using spherical (polar) coordinates as
x0 = r sin cos , x1 = r sin sin , and z = r cos
where r is the radius of the sphere, (latitude) is the angle between the points to the Z-axis, and (colatitude) is
the angle obtained by first projecting the point on the x0-x1 plane, then, measuring the angle of the projected
point and the polar axis on the x0-x1 plane.
We use a 9-node Lagrangian element in Figure 37, which is common in finite element method. The case presented here, with the interpolation functions the same as the functions used for coordinate transformation, is
known as isoparametric element. The algorithm presented here, however, is applicable to 4 to 9 node element.
With this algorithm, any number of nodes from the fifth to the ninth can be added or omitted.
z

V =

z ( )dx
x

A =

z 2
z 2
1 + -------- + -------- dx
x 0
x 1

x1
x0
Figure 36 Spherical (polar) coordinates and formula for computing the volume and
surface area of one-eighth of a sphere with unit radius.
Workbook of Applications in VectorSpace C++ Library

189

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

x()
6

0
4

1
Figure 37 Coordinate transformation rule x(, ) of a 9-node Lagrangian element.

Step 1: Define interpolation functions Ni for four corner nodes (i = 0, 1, 2, 3) with


N0(, ) = 1--4- (1-)(1-), N1(, ) = 1--4- (1+)(1-)
N2(, ) = 1--4- (1+)(1+), N3(, )= 1--4- (1-)(1+)

Eq. 333

Step 2: If no center node, skip Step 2.


(1) add the center node by
N8(, ) = (1-2) (1-2)

Eq. 334

Then, (2) modify four corner nodes due to the presence of the center node
N0 -= N8/4, N1 -= N8/4, N2 -= N8/4, N3 -= N8/4,

Eq. 335

Step 3: For each of the four edge nodes (i = 4, 5, 6, 7), do the following. If the edge node is present,
(1) add the edge node according to the corresponding interpolation function
N4(, ) = (1-2)(1-) - N8/2, N5(, ) = (1-2)(1+) - N8/2
N6(, ) = (1-2)(1+) - N8/2, N7(, ) = (1-2)(1-) - N8/2

Eq. 336

Then, (2) modify the four corner nodes according to the presence of the four edge nodes
N0 -= (N4+N7)/2, N1 -= (N4+N5)/2, N2 -= (N5+N6)/2, N3 -= (N6+N7)/2,

190

Workbook of Applications in VectorSpace C++ Library

Eq. 337

H1 Type and H2 Type Objects


3

6
2

1
5

1
2

4
1
0
Figure 38 Finite element discretization of a quarter of a circle.
The order of the node number (left-hand-side of Figure 37) and the interpolation functions defined in the above
are both accepted standard in finite element method. A quarter of a circle is taken as a whole element or subdivided into three quadrilateral elements as in Figure 38.
The coordinate tranformation rule for a nodal point x = (x0, x1) is now
x ( , ) = N x

Eq. 338

where the components of vector N are the shape functions defined in Eq. 333 to Eq. 337, and x = (x0, x1) are
nodal coordinates. The interpolation function for the z-coordinates of a point on the surface of a sphere can be
expressed similarly as
z ( , ) = N z

Eq. 339

where z is the height of the spherical surface above a node. For geometrical entities that are simple enough, as in
this case with the unit sphere, their algebraic expression can be found in analytical geometry. Instead of Eq. 339,
the height of the unit sphere can be written as
z ( , ) =

1 ( x0 ) 2 ( x 1 ) 2

Eq. 340

The volume of one-eighth of a sphere can be obtained by


volume =

z ( )dx

Eq. 341

where is a vector = {, }T. Either, the isoparametric interpolation of Eq. 339 or analytical expression of Eq.
340 can be used in Eq. 341. A three dimensional surface area of a two dimensional integration domain has its
formula as a multiple dimensional generalization to that of the arc length method shown in Eq. 328.
surface area =

z 2
z 2
1 + -------- + -------- dx
x 0
x 1

Eq. 342

Workbook of Applications in VectorSpace C++ Library

191

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

where
z
-------x 0
dz
dz dx 1
------
= ------ ------
dx
d d
z
-------x 1

Eq. 343

The Program Listing 35 defines the element geometry as shown in Figure 38. The Program Listing 35 is
the C++ main() porgram implements integration formula for computing volume and surface area using Eq. 339
or Eq. 339. The macro definition __THREE_ELEMENTS, if defined, the program discretizes one-quarter of
a circular domain into three nine-nodes quadrilateral elements, otherwise, only one element is used. The macro
definition __ANALYTICAL_GEOMETRY, if defined, Eq. 340 is used in place of Eq. 339. The macro definition __SURFACE_AREA, if defined, compute the surface area instead of the volume. (Program Listing 35
and Program Listing 35 are in project: volume_and_surface_area)
The results of this computation are shown in TABLE 3.7. Three elements discretization does improve the
accuracy of the integration as compared to that of the one element discretization.

Volume

Surface Area

1 Element

3.99991

12.3264

3 Elements

4.17283

12.5465

Analytical

4.18879

12.5664

TABLE 3.7. Integration for Volume and Surface Area


Automatic Mesh Generation: We use, in the above, the example of evaluating the volume and the surface area
of an unit sphere because it has the advantage that the analytical solutions are available for checking the accuracy of the numerical integration. For simplicity, we stick to use this example in the following In a pratical application we might face problem with more complicated geometrical domain. Therefore, we need a more
sophisticated tool to deal with the geometrical complexity. We have used the coordinate transformation method
in finite element method to evaluate the integration. The finite element method is a powerful tool in part that it
deals with complicated geometry. Therefore, we use some of the most primitive finite element objects in Chapter
4, which provides us a systematic treatment to acomplish the refinement of the meshes. We use a function
block to automatically generate mesh with the interface as
void block(Omega_h* h, int -node-no, int -node-no,
int control-node-no, int* control-node-flag,
double* control-node-coordinates,
int first-node-no, int first-element-no)
The first argument h refers to the discretized global domain, where in mathematical convention is domain of
integration, and the superscript h denotes the discretization of the actual domain with a characteristic mesh
size of h. The block function generates nodes and elements for a set of control points (4 to 9 nodes). The

192

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


#include "include\vs.h"
double PI = 3.141592654, deg = PI/180.0, theta = 90.0, phi = 90.0;
void sphere(double* X, double& Z, double phi, double theta) {
X[0] = sin(phi*deg)*cos(theta*deg); X[1] = sin(phi*deg)*sin(theta*deg); Z = cos(phi*deg); }
void define_element() {
#if defined(__THREE_ELEMENTS)
const int ELEMENT_NO = 3;
double X[ELEMENT_NO][9][2], Z[ELEMENT_NO][9];
sphere(X[0][0], Z[0][0], 0.0, 0.0);
sphere(X[0][1], Z[0][1], 1.0/2.0*phi, 0.0);
sphere(X[0][2], Z[0][2], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[0][3], Z[0][3], 1.0/2.0*phi, theta);
sphere(X[0][4], Z[0][4], 1.0/4.0*phi, 0.0);
sphere(X[0][5], Z[0][5], 1.0/2.0*phi, 1.0/4.0*theta);
sphere(X[0][6], Z[0][6], 1.0/2.0*phi, 3.0/4.0*theta);
sphere(X[0][7], Z[0][7], 1.0/4.0*phi, theta);
sphere(X[0][8], Z[0][8], 1.0/4.0*phi, 1.0/2.0*theta);
sphere(X[1][0], Z[1][0], 1.0/2.0*phi, 0.0);
sphere(X[1][1], Z[1][1], phi, 0.0);
sphere(X[1][2], Z[1][2], phi, 1.0/2.0*theta);
sphere(X[1][3], Z[1][3], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[1][4], Z[1][4], 3.0/4.0*phi, 0.0);
sphere(X[1][5], Z[1][5], phi, 1.0/4.0*theta);
sphere(X[1][6],Z[1][6],3.0/4.0*phi,1.0/2.0*theta);
sphere(X[1][7],Z[1][7],1.0/2.0*phi,1.0/4.0*theta);
sphere(X[1][8],Z[1][8],3.0/4.0*phi,1.0/4.0*theta);
sphere(X[2][0], Z[2][0], 1.0/2.0*phi, theta);
sphere(X[2][1], Z[2][1], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[2][2], Z[2][2], phi, 1.0/2.0*theta);
sphere(X[2][3], Z[2][3], phi, theta);
sphere(X[2][4], Z[2][4], 1.0/2.0*phi, 3.0/4.0*theta);
sphere(X[2][5], Z[2][5], 3.0/4.0*phi, 1.0/2.0*theta);
sphere(X[2][6], Z[2][6], phi, 3.0/4.0*theta);
sphere(X[2][7], Z[2][7], 3.0/4.0*phi, theta);
sphere(X[2][8], Z[2][8], 3.0/4.0*phi, 3.0/4.0*theta);
#else
const int ELEMENT_NO = 1;
double X[ELEMENT_NO][9][2], Z[ELEMENT_NO][9];
sphere(X[0][0], Z[0][0], 0.0, 0.0);
sphere(X[0][1], Z[0][1], phi, 0.0);
sphere(X[0][2], Z[0][2], phi, 1.0/2.0*theta);
sphere(X[0][3], Z[0][3], phi, theta);
sphere(X[0][4], Z[0][4], 1.0/2.0*phi, 0.0);
sphere(X[0][5], Z[0][5], phi, 1.0/4.0*theta);
sphere(X[0][6], Z[0][6], phi, 3.0/4.0*theta);
sphere(X[0][7], Z[0][7], 1.0/2.0*phi, theta);
sphere(X[0][8], Z[0][8], 1.0/2.0*phi, 1.0/2.0*theta);
#endif
}

Three elements discretization

frist element

second element

third element

One element discretization

Listing 34 Element discretization of two dimensional integration domain for a sphere with unit radius.
control points use linear of quadratic interpolation functions to map a referential domain to a physical domain
(see Figure 37). The second and third argument -node-no and -node-no indicate the number of nodes
generated in each direction. The fourth argument control-node-no has values of 4 to 9. The following controlnode-flag uses either TRUE (=1) or FALSE (=0) to indicate if a node is to be used as a control node. The
pointer to double array is the nodal coordinates of the control nodes. This is followed by two integers to indicate
the first node number and the first element number to be generated. For example (see also Figure 39),

Workbook of Applications in VectorSpace C++ Library

193

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

1
2
3
4
5
6
7
8
9

void sphere(double* X, double phi, double theta);


EP::element_pattern EP::ep = EP::LAGRANGIAN_9_NODES;
Omega_h::Omega_h() {
// constructor for h
double X[9][2];
const double theta = 90.0; const double phi = 90.0;
int control_node_flag[9] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};
sphere(X[0], 0.0, 0.0);
sphere(X[1], 1.0/2.0*phi, 0.0);
sphere(X[2], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[3], 1.0/2.0*phi, theta);
block(this, 3, 3, 4, control_node_flag, X[0], 0, 0);
...
10 }
int main() {
define_element();
Quadrature qp(2, 9);
H1 ZAI(2, (double*)0, qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 9, 2, qp), Zai, Eta;
Zai &= ZAI[0]; Eta &= ZAI[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (1+Zai)*(1-Eta)/4;
N[2] = (1+Zai)*(1+Eta)/4; N[3] = (1-Zai)*(1+Eta)/4;
N[8] = (1-Zai.pow(2))*(1-Eta.pow(2));
N[0] -= N[8]/4; N[1] -= N[8]/4; N[2] -= N[8]/4; N[3] -= N[8]/4;
N[4] = ((1-Zai.pow(2))*(1-Eta)-N[8])/2; N[5] = ((1-Eta.pow(2))*(1+Zai)-N[8])/2;
N[6] = ((1-Zai.pow(2))*(1+Eta)-N[8])/2; N[7] = ((1-Eta.pow(2))*(1-Zai)-N[8])/2;
N[0] -= (N[4]+N[7])/2; N[1] -= (N[4]+N[5])/2;
N[2] -= (N[5]+N[6])/2; N[3] -= (N[6]+N[7])/2;
C0 vol(0.0), area(0.0);
for(int i = 0; i < ELEMENT_NO; i++) {
C0 X_(9, 2, X[i][0]);
H1 x = N*X_;
C0 Z_(9, Z[i]);
#if defined(__SURFACE_AREA)
H1 z = N*Z_;
H0 dz_dx = d(z) * d(x).inverse(),
da = sqrt((dz_dx[0]).pow(2)+(dz_dx[1]).pow(2)+1.0);
area += da | J(d(x).det());
}
cout << (8.0*90.0/theta*area) << endl;
#else
#if defined(__ANALYTICAL_GEOMETRY)
H0 z = sqrt(1-((H0)x[0]).pow(2)-((H0)x[1]).pow(2));
#else
H0 z = ((H0)N)*Z_;
#endif
vol += z | J(d(x).det());
}
cout << (8.0*90.0/theta*vol) << endl;
#endif
return 0;
}

4 to 9 nodes algorithm
Step 1: four corner nodes
Step 2: center nodes and modification
to four corner nodes
Step 3: four edge nodes and modifcation
to other nodes

coordinate transformation
x ( , ) = N x

1: Surface Area
interpolation z ( , ) = N z
area =

z 2
z 2
1 + -------- + -------- dx
x 0
x 1

2: Volume
z ( , ) =

1 ( x 0 ) 2 ( x1 ) 2

interpolation z ( , ) = N z
volume =

z ( )dx
x

Listing 35 Two dimensional integration domain for volume and surface area of a sphere with unit radius.
194

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


3

6
2
2
5

0
4
3

2
3

2
0

0
1
Figure 39 Use of block() function to generate elements and nodes
automatically. The control nodes are shwon as open squares.

The function sphere() is to generate Catesian coordinates on a circular domain (on x0-x1 plane, see Figure 36)
given the latitude and colatitude of a unit sphere. This generates a 9-nodes Lagrangian element with four corner nodes as control nodes (see element number 0 in Figure 39). The other two 9-nodes Lagrangian elements
labeled as element number 1 and element number 2 and can be constructed as .
1
2
3
4
5
6
7
8
9
10
11

sphere(X[0], 1.0/2.0*phi, 0.0);


sphere(X[1], phi, 0.0);
sphere(X[2], phi, 1.0/2.0*theta);
sphere(X[3], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[4], 3.0/4.0*phi, 0.0);
sphere(X[5], phi, 1.0/4.0*theta);
control_node_flag[4] = FALSE;
block(this, 3, 3, 6, control_node_flag, X[0], 9, 1);
sphere(X[0], 1.0/2.0*phi, theta);
sphere(X[1], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[2], phi, 1.0/2.0*theta);
sphere(X[3], phi, theta);
sphere(X[4], 1.0/2.0*phi, 3.0/4.0*theta); sphere(X[5], 3.0/4.0*phi, 1.0/2.0*theta);
sphere(X[6], phi, 3.0/4.0*theta);
control_node_flag[4] = control_node_flag[5] = FALSE;
block(this, 3, 3, 7, control_node_flag, X[0], 18, 2);

The control nodes ordering is the same as that shown in Figure 37. For the element number 1, the total number
of control nodes is 6, and the node number 4 is skipped by setting control_node_flag[4] = FALSE;. For the
element number 2, the total number of control nodes is 7, and both node number 4 and 5 are skipped by
setting control_node_flag[4] = control_node_flag[5] = FALSE;. In the main() program, the discretized domain
is declared as
Omega_h oh;
the geometrical information of nodes and elements can be accessed as

Workbook of Applications in VectorSpace C++ Library

195

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Omega_eh elem = oh(j);


Node nd = oh[i];
doube x = nd[0],
y = nd[1];

// j-th element he with operator()(int)


// i-th node with operator[](int)
// x-coordinates of i-th node using operator[](int)
// y-coordinates of i-th node using operator[](int)

Program Listing 36 is the program to generate three 9-nodes Lagragian elements. The geometrical information
on the nodes and elements are coded in the segment for the constructor of the discretized global domain
Omega_h::Omega_h(). The actual instance of the discretized global domain is declared inside the main() program. The project block_volume_integral can be used to generate either 9-nodes Lagragian elements or 4nodes quadrilateral elements. The 9 nodes Lagragian elements are generated when the macro definition
__LAGRANGAIN_9_NODES is defined at the compile time. 2, 4, and 8 subdivision for each side of the
block can be defined using macro definition __TWO_SEGMENTS and __FOUR_SEGMENTS for the first
two kinds of subdivision. The nodes and elements for these options are shown in Figure 310. The results of
refined computation are shown in TABLE 3.8.

12 elements

3 elements

48 elements
12 elements

192 elements

4-nodes Quadrilateral

48 elements

9-nodes Lagrangian element

Figure 310 Discretization of global domain into nodes and elements.

196

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


#include "include\vs.h"
#include "include\dynamic_array.h"
#include "include\omega_h.h"
#include "include\block.h"
static const double PI = 3.14159265359; static const double deg = PI/180.0;
void sphere(double* X, double phi, double theta) {
X[0] = sin(phi*deg)*cos(theta*deg); X[1] = sin(phi*deg)*sin(theta*deg); }
EP::element_pattern EP::ep = EP::LAGRANGIAN_9_NODES;
Omega_h::Omega_h() {
double X[9][2]; const double theta = 90.0; const double phi = 90.0;
int control_node_flag[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
sphere(X[0], 0.0, 0.0); sphere(X[1], 1.0/2.0*phi, 0.0);
sphere(X[2], 1.0/2.0*phi, 1.0/2.0*theta); sphere(X[3], 1.0/2.0*phi, theta);
block(this, 3, 3, 4, control_node_flag, X[0], 0, 0);
sphere(X[0], 1.0/2.0*phi, 0.0); sphere(X[1], phi, 0.0); sphere(X[2], phi, 1.0/2.0*theta);
sphere(X[3], 1.0/2.0*phi, 1.0/2.0*theta); sphere(X[4], 3.0/4.0*phi, 0.0);
sphere(X[5], phi, 1.0/4.0*theta); control_node_flag[4] = 0;
block(this, 3, 3, 6, control_node_flag, X[0], 9, 1);
sphere(X[0], 1.0/2.0*phi, theta); sphere(X[1], 1.0/2.0*phi, 1.0/2.0*theta);
sphere(X[2], phi, 1.0/2.0*theta); sphere(X[3], phi, theta);
sphere(X[4], 1.0/2.0*phi, 3.0/4.0*theta); sphere(X[5], 3.0/4.0*phi, 1.0/2.0*theta);
sphere(X[6], phi, 3.0/4.0*theta); control_node_flag[4] = control_node_flag[5] = 0;
block(this, 3, 3, 7, control_node_flag, X[0], 18, 2);
}
int main() {
Quadrature qp(2, 9);
H1 ZAI(2, (double*)0, qp),
N = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 9/*nen*/, 2/*nsd*/, qp), Zai, Eta;
Zai &= ZAI[0]; Eta &= ZAI[1];
N[0] = (1-Zai)*(1-Eta)/4; N[1] = (1+Zai)*(1-Eta)/4;
N[2] = (1+Zai)*(1+Eta)/4; N[3] = (1-Zai)*(1+Eta)/4;
N[8] = (1-Zai.pow(2))*(1-Eta.pow(2));
N[0] -= N[8]/4; N[1] -= N[8]/4; N[2] -= N[8]/4; N[3] -= N[8]/4;
N[4] = ((1-Zai.pow(2))*(1-Eta)-N[8])/2; N[5] = ((1-Eta.pow(2))*(1+Zai)-N[8])/2;
N[6] = ((1-Zai.pow(2))*(1+Eta)-N[8])/2; N[7] = ((1-Eta.pow(2))*(1-Zai)-N[8])/2;
N[0] -= (N[4]+N[7])/2; N[1] -= (N[4]+N[5])/2;
N[2] -= (N[5]+N[6])/2; N[3] -= (N[6]+N[7])/2;
Omega_h oh; C0 vol(0.0);
for(int i = 0; i < oh.total_element_no(); i++) {
Omega_eh& elem = oh(i);
double X[9][2];
for(int j = 0; j < 9; j++) {
int nn = elem[j];
Node& nd = oh[nn];
for(int k = 0; k < 2; k++) X[j][k] = nd[k];
}
C0 X_(9, 2, X[0]); H1 x = N*X_;
H0 z = sqrt(1-((H0)x[0]).pow(2)-((H0)x[1]).pow(2));
vol += z | J(d(x).det());
}
cout << (8.0*vol) << endl;
return 0;
}

9-nodes Lagrangian element

block # 0; 4 control nodes


block # 1; 5 control nodes

block # 2; 5 control nodes

4 to 9 nodes shape function


Step 1: four corner nodes
Step 2: center nodes and modification
to four corner nodes
Step 3: four edge nodes and modifcation
to other nodes
h
element he

x- and y- coordinates
x ( , ) = N x

Volume
z ( , ) =

1 ( x0 ) 2 ( x1 )2
interpolation z ( , ) = N z
volume = z ( )dx
x

Listing 36 Volume integration using block() function to generate nodes and elements automatically.

Workbook of Applications in VectorSpace C++ Library

197

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

No. of Elements

4-nodes Quadrilateral

9-nodes Lagragian

4.19694

12

4.17459

4.19144

4.18803

4.18958

48

TABLE 3.8. Volume integral of an unit sphere (analytical =


4/3 = 4.18879).
192

4.18092

3.2.2 Integrable_Tangent_of_Tangent_Bundle /Integrable_Vector_of_Tangent_of_Tangent_Bundle


Integrable_Tangent_of_Tangent_Bundle and Integrable_Vector_of_Tangent_of_Tangent_Bundle are two
objects of H2 type that are the integrable extension of Tangent_of_Tangent_Bundle and
Vector_of_Tangent_of_Tangent_Bundle of C2 type objects.

Constructors
The dedicated constructors for a Integrable_Tangent_Bundle are
H2::H2(const Quadrature&)
H2::H2(double* v, const Quadrature&)
H2::H2(double* v, int spatial_dimension, const Quadrature&)
The dedicated constructors for a Integrable_Vector_of_Tangent_of_Tangent_Bundle is
H2::H2(int vector_size, double* v, const Quadrature&)
For the dedicated constructor, the size of vector is equal to the number of spatial dimension.
The constant strings used for the virtual constructors and autonomous virtual constructor are listed in the
following two boxes. The macro defintions use for the virtual constructors of the
Integrable_Tangent_of_Tangent_Bundle and Integrable_Vector_of_Tangent_of_Tangent_Bundle are
H2 x = INTEGRABLE_TANGENT_OF_TANGENT_BUNDLE(const char*, ...);
H2 x = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(const char*, ...);
respectively. H2 x = H2(const char*, ...) is used for autonomous virtual constructors. There are not much different in the use of H2 type objects compared to that of the H1 type objects, The major difference is that the H2
type objects allow twice differentiable operation needed in some applications. In the next section on the variational methods, a lot of examples with H2 type are shown.

198

Workbook of Applications in VectorSpace C++ Library

H1 Type and H2 Type Objects


virtual constructor string
by reference
H2&
H2*
double*, double*, double*,
Quadrature
double*, double*, double*,
int, Quadrature
by value
Quadrature,
int, Quadrature
const double&, const double&,
const double&, Quadrature
const double*, const double*,
const double*, int, Quadrature&
const H0&, const H0&,
const H0&
const H0*, const H0*,
const H0*
const H2&
const H2*

VectorSpace C++ library definition

priority

H2 type Matrix
a pointer to H2 type Matrix
v, dv, ddv

1
2
7

v, dv, ddv,
spatial dimension

memory-row-length, memory-column-length
v, dv, (for spatial dimension = 1 only)
ddv
v, dv,
ddv, spatial dimension
base point, tangent,
tangent of tangent
base point, tangent,
tangent of tangent
Integrable_Tangent_of_Tangent_Bundle
Integrable_Tangent_of_Tangent_Bundle*
Strings in H2 virtual constructor for Integrable_Tangent _of_Tangent_Bundle object.

virtual constructor string

VectorSpace C++ library definition

3
4
5
6
9
10
11
12

priority

by reference
H2&
H2 type Matrix

H2*
a pointer to H2 type Matrix

int, int, double*, double*, double*,vector size, spatial dimension, v, dv, ddv
14
Quadrature, int, int
quadrature, memory row size, and column size
by value
int, int, Quadrature,
vector size, spatial dimension
13
const H0&, const H0&,
base point , tangent

const H0&
tangent of tangent
const H0*, const H0*,
base point, tangent

const H0*
tangent of tangent
int, const H2*
vector size, Integrable_Tangent_of_Tangent_Bundle* 15
const H2&
Integrable_Vector_of_Tangent_of_Tangent_Bundle
const H2*
Integrable_Vector_of_Tangent_of_Tangent_Bundle*
Strings in H2 virtual constructor for Integrable_Vector_of_Tangent_of_Tangent_Bundle object.

Workbook of Applications in VectorSpace C++ Library

199

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

3.3 Variational Methods


For a linear differential equation with homogeneous essential boundary condition,
Au = f

Eq. 344

where A is a self-adjoint linear operator. We can define a functional J(u) as


1
J(u) = --- a(u, u) - (u, f)

Eq. 345

where (u, f) is a linear functional and a(u, u) is a bilinear functional with a(u, u) (u, Au). For u0, a solution
corresponding to the minimum value of J; i.e., J(u0) J(u). We define u = u0 + , where is a small real number and is called the variation. The variation of J denoted as J can be defined with the directional derivatives
as
d

J(u)= ------ J ( u 0 + )
d

= 0

Eq. 346

Set J(u) = 0 for the minimization of J. Considering Eq. 346 equals zero is always true for the arbitary small
real number , the term in bracket must equal zero for u0 to give a stationary value of J. So, we have
d 1
2
------ --- a ( u 0, u 0 ) + a ( , u 0 ) + ----- a ( , ) ( u 0, f ) ( , f )

2
d 2

=0

= a ( , u 0 ) ( , f ) = 0

Eq. 347

That is,
a(, u0) = (, f)

Eq. 348

which is just the Eq. 344 multiplies by the variation . So it is equivalent to the Eq. 344. Therefore, the solution of the differential equation (strong form) of Eq. 344, is the solution of the minimization problem of Eq.
345, and is also the solution of the variational formulation (weak form) of Eq. 348.
Re-defining v = u0 + , and u = u0 in Eq. 348, we have (v, Au) = (v, f), And, the adjoint homogeneous
equation A*v = 0, therefore, (A*v, u) = (0, u).
(v, Au) - (A*v, u) = (v, f) - (0, u) = (v, f)

Eq. 349

The left-hand-side of Eq. 349 is (Au, v) - (u, A*v) = 0 for self-adjoint operator A. So, we have
(v, f) = 0

Eq. 350

Eq. 350 is the solvability condition. From linear algebra, orthogonal complement of the range space of A is the
null space of its adjoint A*, usually denoted as R(A) = N(A*). Since f R(A) and v N(A*), this leads directly
to the orthogonal relation (v, f) = 0.
200

Workbook of Applications in VectorSpace C++ Library

Variational Methods
3.3.1 Rayleigh-Ritz Method
For the Rayleigh-Ritz method we write the approximation of the variational formulation in Eq. 348 as
a(vN, uN) = (vN, f)

Eq. 351

where vN and uN is taken as


N1

u N = vN =

ci i

Eq. 352

i=0

The approximation basis functions i should give finite energy with respect to the bilinear form a(. , .), such that
derivatives corresponding to the operator A is integrable. Substituting Eq. 352 into Eq. 351 gives a system of
simultaneous equations
N1

ci

a ( i, j ) cj

= c i ( f, i ), where i = 0, 1, , N 1

Eq. 353

j=0

coefficients ci are present in both sides of the equation, so it can be dropped. Eq. 353 can be re-written in matrix
form as
Mc=b

Eq. 354

where Mij = a(i, j), and bi = (i, f). The solution vector c of Eq. 354 is the vector consists of coefficients ci in
Eq. 352. If i are chosen to be orthogonal basis functions, M is diagonal; i.e., Mij = 0 for i j.

Second-order Differential Equation


The first set of example problems is a second-order differential equation1
2

d u
dx

= cos x, where 0 < x < 1

Eq. 355

with different kinds of boundary conditions for each of the two problems:
1. Dirichlet boundary conditionsu(0) = u(1) = 0
2. Mixed boundary conditionsu(0) = 0, and u(1) = 0

1. p. 265-270 in J.N. Reddy, 1986, Applied functional analysis and variational methods in engineering, McGraw-Hill, Inc.

Workbook of Applications in VectorSpace C++ Library

201

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Dirichlet Boundary Conditions: For the first one with the Dirichlet boundary conditions u(0) = u(1) = 0 the
exact solution is
1
uexact(x) = -----2 ( cos x + 2x 1 )

Eq. 356

From Eq. 351 we have the weak form as


a(vN, uN) - (vN, f) =
1

d uN

vN d x2 + vN cos x dx =
0

dv N du N
du N
d x d x + v N cos x dx + v N d x
0

=
0

dv N du N
+ v N cos x dx = 0

dx

d x

Eq. 357

We have applied the integration by part on the term with the second order derivative and requring homogeneous
conditions, vN(0) = vN(1) = 0, on the boundary integral term
du N
vN
dx

= 0

Eq. 358

Therefore, we choose i in Eq. 352 as the set of orthogonal functions {sin [(i+1)x] | 0 i N 1 }. Notice
that this set of functions satisfies the requirement of vN(0) = vN(1) =0. Since the set is orthogonal, all off-diagonals of M matrix are zeros. We only consider the diagonal elements of M as
1

diag(M)i = a(i, i) =

d i d i
dx , and bi = i cos x
dx

dx

Eq. 359

The solution of the coefficient vector is simply ci = bi / diag(M)i , component by component without having to
solve a system of simultaneous equation. The Program Listing 37 implements the Eq. 359. After the ci are
solved for, the solution of the Dirichlet boundary value problem is obtained by plug in ci in Eq. 352.
In Figure 311, the exact solution in Eq. 356 is compared to the solution constructed using ci computed from
Program Listing 37. The approximated vairiational solution, in the form of Eq. 352 uN = cii, with N = 2 to N =
16 (even numbers only) are ploted in the left-hand-side. Only the case with N=2 has clear differences from the
exact solution, other solutions (N= 4-16) converge rapidly towards the exact solution. Figure 312 shows the
alternative approach discussed in page 170 with an integral equation using Green function as kernel for solution.
The results are computed by Program Listing 37, which is almost with a simple modification that f(x) = cos
x instead of f(x) = sin(x).

202

Workbook of Applications in VectorSpace C++ Library

Variational Methods
#include "include\vs.h"
#define PI 3.141592654
int main() {
const int n = 16;
double w[35] = {1.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 1.0/3.0};
Quadrature qp(w, 0.0, 1.0, 35);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", n, 1, qp);
for(int i = 0; i < n; i++) phi[i] = sin(((double)i+1.0)*PI*x);
H0 d_phi_2(n, (double*)0, qp);
for(int i = 0; i < n; i++) d_phi_2[i] = d(phi[i]).pow(2);
C0 M = d_phi_2 | J(1.0/34.0);
C0 b = ( ((H0)phi) * cos(PI*((H0)x)) ) | J(1.0/34.0);
C0 c(n, (double*)0);
for(int i = 0; i < n; i++) c[i] = b[i] / M[i];
for(int i = 0; i < n; i++) cout << c[i] << ", "; cout << endl;
return 0;
}

extended Simpsons rule

i = sin[(i+1)x], i = 0, N-1
1

diag(M)i = a(i, i) =
bi = i cos x
ci = bi / diag(M)i

d i d i
dx
dx

dx
0

Listing 37 Dirichlet boundary condition u(0) = u(1) = 0, for the differential equation - u = f (project:
dirichlet).
Exact = (cos x + 2x -1) /2

uN = cii , i = 0, ( = 216)

0.02
0.01
-0.01
-0.02

0.02
0.01
0.20.40.60.8 1

-0.01
-0.02

=2

0.20.40.60.8 1

Figure 311 The left-hand-side is the exact solution, and the right-hand-side is the solution
with N=2 to N = 16 Rayleigh-Ritz method.
Mixed Boundary Conditions: For the Mixed boundary conditions u(0) = u(1) = 0, the exact solution is
1
uexact(x) = -----2 ( cos x 1 )

Eq. 360

With this different set of boundary conditions the Eq. 357 to Eq. 359 still hold. However, i = {sin(ix) |
0 i N 1 } now is not complete with respect to x = 1, where u(1) = 0 always. We can add a new algebraic
function 0 = x (the simplest one) to fix this situation. That is the new set of becomes {x, sin(x), sin(2x),
sin(3x), ... }. Therefore, the Program Listing 37 only needs the slightest modification. The Program Listing 38
is a modified version for the mixed boundary conditions problem. Aternatively, since the solution of ci in Program Listing 37 is working out component by component for this problem (since we select a orthogonal set of
i), we can just compute one additional term c0 with 0 = x and add to the solution of the problem 1. Figure 313
Workbook of Applications in VectorSpace C++ Library

203

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


0.02

uexact = (cos x + 2x -1) /2

0.01

0.2

0.4

0.6

0.8

-0.01

-0.02

Figure 312 Point-values are solution of integral equation using Green function computed by Program
Listing 31 with a simple modification that f(x) = cos x.
shows that the solution up to N= 2 is already a good enough approximation to the exact solution for this
problem.
#include "include\vs.h"
#define PI 3.141592654
int main() {
const int n = 16;
double w[35] = {1.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0,
4.0/3.0, 2.0/3.0, 4.0/3.0, 2.0/3.0, 4.0/3.0, 1.0/3.0};
Quadrature qp(w, 0.0, 1.0, 35);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", n, 1, qp);
phi[0] = x;
for(int i = 1; i < n; i++) phi[i] = sin(((double)i+1)*PI*x);
H0 d_phi_2(n, (double*)0, qp);
for(int i = 0; i < n; i++) d_phi_2[i] = d(phi[i]).pow(2);
C0 M = d_phi_2 | J(1.0/34.0);
C0 b = ( ((H0)phi) * cos(PI*((H0)x)) ) | J(1.0/34.0);
C0 c(n, (double*)0);
for(int i = 0; i < n; i++) c[i] = b[i] / M[i];
for(int i = 0; i < n; i++) cout << c[i] << ", "; cout << endl;
return 0;
}

extended Simpsons rule

0 = x, i = sin[ix], i = 1, N-1

Listing 38 Mixed boundary condition u(0) = u(1) = 0, for the differential equation - u = f (project: mixed).
Dirichlet Boundary Conditions Revisited: We can use polynominals instead of trigonometric functions as the
basis functions, such as
i = x(i+1) (1-x).

Eq. 361

Notice that this choice of i satisfies the Dirichlet boundary conditions u(0) = u(1) = 0. However the is are not
orthogonal with each other and therefore Mij will not be a diagonal matrix. The solution of a system of simultaneous equations is required. We choose 0 i 3 ; i.e., N=4. Hence the highest order polynomial is fifth-order.
One modification to the Program Listing 37 is that we use Bodes integration rule which is a fifth-order approximation. The weights for the Bodes rule is
204

Workbook of Applications in VectorSpace C++ Library

Variational Methods

0.20.40.60.8 1

0.20.40.60.8 1
-0.05
-0.1
-0.15
-0.2

Exact = (cos x -1) /2

-0.05
-0.1
-0.15
-0.2

uN = cii , i = 0, ( = 216)

Figure 313 Exact solution (cos x -1) /2 comparing to solutions of N= 2-16 Rayleigh-Ritz method.
64 24 64 14
14 24 64 28 64 24 64 28
------, ------ , ------, ------, ------ , ------, ------, ------, , ------, ------, ------, -----45 45 45 45
45 45 45 45 45 45 45 45

Redefine i simply as phi[0] = x*(1-x); for(int i = 1; i < 4; i++) phi[i] = phi[i-1]*x; Program Listing 39 implements the polynomial approximation. Figure 314 shows the solutions of the polynomial approximations which
is almost the same as the eact solution visually.
#include "include\vs.h"
#define PI 3.141592654
int main() {
double w[17] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(w, 0.0, 1.0, 17);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 4, 1, qp);
phi[0] = x*(1-x); for(int i = 1; i < n; i++) phi[i] = phi[i-1]*x;
C0 M = ( d(phi)*(~d(phi)) ) | J(1.0/16.0);
C0 b = ( ((H0)phi) * cos(PI*((H0)x)) ) | J(1.0/16.0);
C0 c = b / M;
for(int i = 0; i < 4; i++) cout << c[i] << ", ";
return 0;
}

extended Bodes rule


i = x(i+1) (1-x), i = 0, N-1
1

Mij = a(i, j) =
bi = i cos x
ci = bi /Mij

d i d j
dx
dx

dx
0

Listing 39 Polynomial basis i = x(i+1) (1-x), i = 0, N-1 for the Dirichlet boundary condition u(0) = u(1) = 0,
for the differential equation - u = f (project: polynomial).

Fourth-order Differential Equation


Now we consider a second example problem which is a fourth-order differentail equation which is apllicable
for transverse deflection of a beam in the subject of mehanics of materials1. Denote the transverse deflection of

1. p.188-190, and p. 351-353 in J.M.Gere, and S.P. Timoshenko, 1984, Mechanics of materials, 2nd ed., Wadsworth, Inc.,
Belmont, California.

Workbook of Applications in VectorSpace C++ Library

205

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

0.02

0.01

0.2

0.4

0.6

0.8

-0.01

-0.02

Figure 314 Solution of Dirichlet boundary problem using polynomial basis functions.
the beam as w (see Figure 315). From balance of force, the transverse loading (f) is equal to the derivative of
shear force (V) as
dV/dx =- f

Eq. 362

and the shear force is equal to the derivative of bending moment (M) as
dM/dx =- V

Eq. 363

Therefore,
2

dM
= f
dx2

Eq. 364

The curvature (d2w/dx2) of the beam is related to the bending moment and the flexure rigidity of the beam as

w
f(x)

x
M

L
Figure 315 Transverse deflection of a beam.
206

Workbook of Applications in VectorSpace C++ Library

Variational Methods
2

dw
M
= --------2EI
dx2

Eq. 365

where EI is the flexural rigidity. Substituting M in Eq. 365 into Eq. 364 gives
2

2
d d w
EI
= f, where 0 < x < L
d x d x2

Eq. 366

For the current problem, Eq. 366 is subject to boundary conditions


2

w( 0 ) =

dw
dw
d d w
( 0 ) = 0, EI 2 ( L ) = M, V ( L ) =
EI
(L) = 0
dx
d
x d x2
dx

Eq. 367

The exact solution for this problem is


2M + fL 2
fL
f
w ( x ) = ---------------------- x 2 --------- x 3 + ------------ x 4
4EI
6EI
24EI

Eq. 368

Four weak formulations can be used for this problem1


1. Irreducible formulation,
2. Lagrange multiplier formulation,
3. Penalty function formulation, and
4. Mixed formulation
1. Irreducible Formulation: The irreducible formulation has the highest order of differential equation. We first
need to transform the end bending moment boundary condition into a homogeneous one by change of variable as
u = w - w0, where w0 = Mx2 / 2EI
The problem posed by Eq. 366 and Eq. 367 becomes
2

2
d d u
EI
= f, where 0 < x < L
dx dx2

Eq. 369

with the homogeneous boundary conditions of

1. From examples in p. 156-158, and p. 275-280 in J.N. Reddy, 1986, Applied functional analysis and variational methods
in engineering, McGraw-Hill, Inc.

Workbook of Applications in VectorSpace C++ Library

207

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


2

u(0) =

du
d d u
du
( 0 ) = EI 2 ( L ) =
EI
(L) = 0
d
x dx2
dx
dx

Eq. 370

The Lagrangian functional corresponding to this is


L

J(u) =

EI d u
------
fu dx
2 d x2

Eq. 371

Using u = v, where is a small real number, and setting J(u) =0 gives


L

J ( u ) =

2
d u
d v d u
d
EI
( u ) 2 uf dx = EI 2 2 vf dx = 0
2
d
x
dx

dx dx

Eq. 372

The second identity is obtained from applying integration by parts twice and considering that all boundary conditions are homogeneous. Dropping , for which is arbitary, we can define an approximated system of equations
with left-hand-side and right-hand-side as
L

a(vN, uN) =

d v N d u N
EI 2 2 dx , and (vN, f) =
dx dx

[ vN

f ] dx

Eq. 373

respectively. The approximation basis functions are taken as i = {x i+2}, i = 0,1, ..., N-1. Program Listing 310
implements Eq. 373, with N= 2, 3. The case with N= 3 actually produces the coefficients of the exact solution
in Eq. 368. Figure 316 shows N=2 is almost identical to the exact solution visually.
0.6
0.5
0.4

Exact = (N=3) ~ (N=2)


0.3
0.2
0.1
0.2

0.4

0.6

0.8

Figure 316 Irreducible formulation for transeverse deflection of a beam with N=2, 3.
2. Lagrange Multiplier Formulation: We refer to Chapter 2, Eq. 211 in page 118 for an introduction on the
Lagrangian functional in the Lagrange multiplier method for the constrained optimization problem. We now
define the constraint equation as the variable of the negative slope
=

208

dw
dx

Workbook of Applications in VectorSpace C++ Library

Eq. 374

Variational Methods
#include "include\vs.h"
int main() {
double L_ = 1.0, E_ = 1.0, I_ = 1.0, f_ = 1.0, M_ = 1.0;
for(int N = 2; N < 4; N++) {
double w[17] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(w, 0.0, L_, 17);
H2 x((double*)0, qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
"int, int, Quadrature", N/*vector size*/, 1/*spatial dim.*/, qp);
for(int i = 0; i < N; i++) phi[i] = x.pow(i+2);
H0 d2_phi = INTEGRABLE_VECTOR("int, Quadrature", N, qp);
for(int i = 0; i < N; i++) d2_phi[i] = dd(phi)(i)[0][0];
C0 M = ( E_* I_* (d2_phi%d2_phi) ) | J(L_/16.0);
C0 b = ( ( ((H0)phi) * f_ ) | J(L_/16.0) )+ M_bc;
C0 c = b / M;
for(int i = 0; i < N; i++) cout << c[i] << endl;
}
return 0;
}

extended Bodes rule


i = x(i+2), i = 0, N-1
L

Mij =

d i d j
EI 2 2 dx
dx dx

bi =

[ i

f ] dx

ci = bi /Mij
N = 2: ci={0.20833,-0.0833333}T,
N = 3: ci={0.25, -0.166667, 0.041667}T

Listing 310 Transverse deflection of a beam using irreducible formulation. i = x(i+2) , i = 0, N-1 (project:
irreducible_formulation).
Substituting Eq. 374 into Eq. 371 and considering the boundary term yields
L

J ( , w ) =

EI d 2
----- fw dx + ( M )
2 dx

Eq. 375
L

Using the Lagrangian multiplier with the constraint equation (Eq. 374), we can define the Lagrangian functional l(, w, ) as
L

l ( , w, ) =

EI d 2
dw
----- f w + + dx + ( M )
2 dx
dx

Eq. 376
L

subject to boundary condition that (0) = w(0) = 0. The Euler-Lagrange equations can be obtained by setting
l(, w, ) = 0 as

Workbook of Applications in VectorSpace C++ Library

209

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


L

l ( , w, ) =

d d
EI ---------+ ( ) dx + ( M )
dx d x

0
L

- w
---------dx
dw

+
L

f dx +

0
L

+ d x dx
dw

Eq. 377

=0
The Lagrange multiplier in this case has physical interpretation of the shear force.
2

d d w
=
EI

dx d x2

Eq. 378

Therefore, the exact solution for and can be obtained by differentiating the exact solution for w(x) in Eq.
368 as
f
fL 2 ------- ( 2M + fL 2 )
- 3
x + ------- ( x ) = -----------------------------2EI x 6EI x ,
2EI

= f(L x )

Eq. 379

The approximation basis functions for each approximated variable are taken as
N wN N = c i i c iw iw c i i

Eq. 377 can be re-written in matrix form as


L

d i d j
- ---------- dx
EI
--------dx dx

i j dx

c j

0
L

i j dx

djw
i ---------- dx
dx

( i M )
L

d iw
- dx c jw =
--------dx j

iw f dx

c j

Eq. 380

Therefore, the matrix and vectors in Eq. 380 can be labeled to be comformed with M c = b (Eq. 354). We
first consider a one-parameter approximation with

210

Workbook of Applications in VectorSpace C++ Library

Variational Methods
0 0w 0 = x x 1

Eq. 381

then, a two-parameters approximation with


0 1 0w 1w 0 1 = x x 2 x x 2 1 x

Eq. 382

Eq. 380 with Eq. 381 or Eq. 382 offers a first non-trivial matrix formulation in this workbook and it deserves
us to look into the various ways, that VectorSpace C++ Library supports, to implment these equations. Program
Listing 311 implements the one-parameter approixmation.
#include "include\vs.h"
int main() {
double L_ = 1.0, E_ = 1.0, I_ = 1.0, f_ = 1.0, M_ = 1.0, weight[2] = {0.5, 0.5};
Quadrature qp(weight, 0.0, L_, 2);
H1 x(qp), psi = x, w = x;
double lambda = 1.0;
H0 m = INTEGRABLE_MATRIX("int, int, Quadrature", 3, 3, qp);
m[0][0] = (E_*I_)*d(psi)*d(psi);
m[0][2] = m[2][0] = ((H0)psi)*lambda;
m[1][2] = m[2][1] = d(w)*lambda;
m[0][1] = m[1][0] = m[1][1] = m[2][2] = 0.0;
C0 M = m | J(L_),
b(3, (double*)0);
b[0] = -L_*M_; b[1] = ( ((H0)w)*f_ ) | J(L_); b[2] = 0.0;
C0 c = b / M;
for(int i = 0; i < 3; i++) cout << c[i] << ", "; cout << endl;
return 0;
}

Trapezoidal rule weightings {0.5, 0.5}T


0 0w 0 = x x 1
L

M00=

d 0 d 0
EI ---------- ---------- dx
dx dx

0
L

M02 =M20 =

0 0 dx

M12 =M21 =

L d w
0
--------- dx
dx 0
0

b=

ML 0w fdx 0

Listing 311 On-parameter approximation in Lagrange multiplier method for beam bending problem
(project: lagrange_multiplier).
For one-parameter approximation matrix M is only 3 3, which is not too complicated. It can be accessed
with plain C or Fortran semantics using the selector []. Two alternative approaches are available in VectorSpace C++ Library. First we can build M just as it is written in matrix form using concatenation operator | and
& such as
C0 M = ( ( (E_*I_*(d(psi)*d(psi)))| null
| (((H0)psi)*lambda) )&
( null
| null
| (d(w)*lambda)
)&
( (((H0)psi)*lambda)
| (d(w)*lambda) | null
) ) | J(L_),
b = ( C0(-L_*M_) &
( (((H0)w)*f_) | J(L_) ) &
C0(0.0) );

Workbook of Applications in VectorSpace C++ Library

211

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

The expression is to mimic directly the image of the right-hand-side matrix and the left-hand-side vector of Eq.
380. Or, we can use basis expression closer to linear algebra as
C0 e(3),
M = ( (E_*I_*(d(psi)*d(psi)))
0.0
(((H0)psi)*lambda)
0.0*(e[1]%e[0])+ 0.0
(d(w)*lambda)
(((H0)psi)*lambda)
(d(w)*lambda)
0.0
) | J(L_),
b = (-L_*M_)
((((H0)w)*f_) | J(L_))
0.0

*(e[0]%e[0])+
*(e[0]%e[1])+
*(e[0]%e[2])+
*(e[1]%e[1])+
*(e[1]%e[2])+
*(e[2]%e[0])+
*(e[2]%e[1])+
*(e[2]%e[2])
*e[0] +
*e[1] +
*e[2];

This code simulates the image of


d 0 d 0
- ---------- dx ( e 0 e 0 ) +
EI
--------dx dx
L

M=

0 ( e 0 e 1 ) + 0 0 dx ( e 0 e 2 ) +

0
L

d iw
dx

0 ( e 1 e 1 ) + ---------- j dx ( e 1 e 2 ) +

0 ( e1 e0 ) +

0
L

0 0 dx ( e 2 e0 ) +
0

d 0w
0 ---------- dx ( e 2
dx

e1 ) +

0 ( e2 e2 )

and,
L

b=

( 0 M )

e 0 + 0w f dx e 1 + 0 e 2
0

The results of one-parameter approximation are shown in Figure 317. There is room for improvements obviously.
Program Listing 312 implements the two-parameter approximation.

-0.2
-0.4
-0.6
-0.8
-1
-1.2

0.2 0.4 0.6 0.8

exact

0.6
0.5
0.4
0.3
0.2
0.1

exact

0.8
0.6
0.4

exact
0.2 0.4 0.6 0.8

0.2
1

0.2 0.4 0.6 0.8

Figure 317 Comparison of one-parameter solution to the exact solution.


212

Workbook of Applications in VectorSpace C++ Library

Variational Methods
T

= w , = x x2 , w = x x2 , = 1 x
T

Eq. 383

For more than one-parameter approximation, the complexities for the formulation increase dramatically. Submatrix/Subvector become an important tool to deal with the complexities. We used in Program Listing 312, the reference Integrable_Matrix mi j, where i, j = 0, 1, 2. Each mi j is a matrix of size 2x2.
#include "include\vs.h"
int main() {
double L_ = 1.0, E_ = 1.0, I_ = 1.0, f_ = 1.0, M_ = 1.0, weight[3] = {1.0/3.0, 4.0/3.0, 1.0/3.0};
Quadrature qp(weight, 0.0, L_, 3);
H1 x(qp),
psi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 2, 1, qp),
w
= INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 2, 1, qp),
lambda=INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature",2,1,qp);
psi[0] = x; psi[1] = x.pow(2);
w[0] = x; w[1]
= x.pow(2);
lambda[0] = 1.0; lambda[1] = x;
H0 m(6, 6, (double*)0, qp),
m00(2, 2, m, 0, 0, qp), m01(2, 2, m, 0, 2, qp), m02 (2, 2, m, 0, 4, qp),
m10(2, 2, m, 2, 0, qp), m11(2, 2, m, 2, 2, qp), m12(2, 2, m, 2, 4, qp),
m20(2, 2, m, 4, 0, qp), m21(2, 2, m, 4, 2, qp), m22(2, 2, m, 4, 4, qp);
m00 = (E_*I_)*d(psi)*(~d(psi)); m01 = 0.0;
m02 = ((H0)psi)%((H0)lambda);
m10 = 0.0;
m11 = 0.0;
m12 = d(w)(0)%((H0)lambda);
m20 = ((H0)lambda)%((H0)psi); m21 = ((H0)lambda)%d(w)(0); m22 = 0.0;
C0 M = m | J(L_/2);
H0 f(6, (double*)0, qp), f0(2, f, 0, qp), f1(2, f, 2, qp), f2(2, f, 4, qp);
f1 = (((H0)w)*f_); f0 = f2 = 0.0;
C0 b = f | J(L_/2);
b[0] = -M_*L_;b[1] = -M_*pow(L_, 2);
C0 c = b / M;
for(int i = 0; i < 6; i++) cout << c[i] << ", "; cout << endl;
return 0;
}

Simpsons rule {1/3,4/3,1/3}T


0 1 0w 1w 0 1 = x x 2 x x 2 1 x
L

M00=

d d
EI --------- --------- dx
dx
dx

0
L

ML

02

= dx

dx ,

M20

0
L

d w

-dx
M12= ---------- dx , M21= --------dx
dx
0

b=

( M ( L ) ) w fdx 0

Listing 312 Two-parameters approximation in Lagrange multiplier method for beam bending problem
(project: lagrange_multiplier).
Three alternative implementions of the two-parameter approximation in VectorSpace C++ Library are possible. First, concatenation operators can be used to patch smaller matrices and vectors into a larger one, such as
H0 null = INTEGRABLE_MATRIX("int, int, Quadrature", 2, 2, qp); null = 0.0;
C0 M =(( (E_*I_*(d(psi)*(~d(psi)))) |
null
| (((H0)psi)%((H0)lambda)) )&
(
null
|
null
| (d(w)(0)%((H0)lambda)) )&
( (((H0)lambda)%((H0)psi)) | (((H0)lambda)%d(w)(0)) |
null
)
) | J(L_/2);
C0 M_delta_psi(2, (double*)0), zero(2, (double*)0);
M_delta_psi[0] = -M_*L_; M_delta_psi[1] = -M_*L_*L_; zero = 0.0;
C0 b = ( M_delta_psi & ( (((H0)w)*f_) | J(L_/2)) & zero);

Workbook of Applications in VectorSpace C++ Library

213

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

This code is hardly different from the one-parameter version, although each term is now an Integrable_Matrix
instead of an Integrable_Scalar. Secondly, the two-parameter approximation for the linear algebra version can be
written as
C0 e(2), E(3),
M =+( ((E_*I_)*(d(psi)*(~d(psi)))) *((e%e)*(E[0]%E[0]))+
0.0
*((e%e)*(E[0]%E[1]))+
(((H0)psi)%((H0)lambda)) *((e%e)*(E[0]%E[2]))+
0.0
*((e%e)*(E[1]%E[0]))+
0.0
*((e%e)*(E[1]%E[1]))+
(d(w)(0)%((H0)lambda))
*((e%e)*(E[1]%E[2]))+
(((H0)lambda)%((H0)psi))
*((e%e)*(E[2]%E[0]))+
(((H00)lambda)%d(w)(0))
*((e%e)*(E[2]%E[1]))+
0.0
*((e%e)*(E[2]%E[2]))
) | J(L_/2);
C0 M_delta_psi(2, (double*)0); M_delta_psi[0] = -M_*L_; M_delta_psi[1] = -M_*L_*L_;
C0 b = +( M_delta_psi
*(e*E[0]) +
( (((H0)w)*f_) | J(L_/2) )
*(e*E[1]) +
0.0
*(e*E[2]) );
The expressions for using Integrable_Submatrix or Integrable_Subvector in two-parameter case are very close to
those of the one-parameter approximation case. The fact that they are now matrix of size 2x2 and vector of size
2x1 instead of a scalar component (comparing to one-parameter case discussed on page 212) is handled by projecting these matrices and vectors to ((e%e)*(E[i]%E[j])) or (e*E[i]) ) according to basis expression introduced in Section 1.1.6. We call your attention to the last operations in the construction of both M and b.
They use unary + operator. This is the primary casting which down casts Subvectors and Submatrices into
Vectors and Matrices, respectively.
Basis expression generates Integrable_Subvector and Integrable_Submatrix. Third, a complementary expression using the objects of Integrable_Subvector and Integrable_Submatrix directly is
H0 m(6, 6, (double*)0, qp),
ms(2, 2, m);
ms(0,0) = E_*I_*(d(psi)*(~d(psi))); ms(0,1) = 0.0;
ms(0,2) = ((H0)psi)%((H0)lambda);
ms(1,0) = 0.0;
ms(1,1) = 0.0;
ms(1,2) = d(w)(0)%((H0)lambda);
ms(2,0) = ((H0)lambda)%((H0)psi); ms(2,1) = ((H0)lambda)%d(w)(0); ms(2,2) = 0.0;
H0 f(6, (double*)0, qp), fs(2, f);
fs(1) = (((H0)w)*f_); fs(0) = fs(2) = 0.0;
C0 M = m | J(L_/2),
b = f | J(L_/2);
b[0] = -M_*L_; b[1] = -M_*pow(L_, 2);
The results of two-parameter approximation are shown in Figure 318. Compared with Figure 317 the approximations for and w are almost equal to the exact solution, and the approximation for is identical to the exact
solution.

214

Workbook of Applications in VectorSpace C++ Library

Variational Methods

0.6
-0.2 0.20.40.60.8 1 0.5
0.4
-0.4
0.3
-0.6
0.2
-0.8 exact ~~ approx.
0.1
-1

1
0.8
0.6
0.4
0.2

exact ~
~ approx.

0.20.40.60.8 1

exact = approx.

0.20.40.60.8 1

Figure 318 Two-parameter approximation using Lagrange multiplier formulation for the beam
bending problem.

3. Penalty Function Formulation: We refer to Chapter 2, Eq. 261 on page 153 for the basics of the penalty
method. Taking J(, w) in Eq. 375 with a quadratic penalty term, we have
L

J p ( , w ) =

dw 2

+ --- + dx
2
dx

EI d 2
----- fw dx + ( M )
2 dx

Eq. 384

where is the penalty parameter. Setting Jp = 0,


L

- ------- wf dx + ( M )
EI --------
dx dx

dw
dw
+ + ----------- + ------- dx = 0

dx
dx

d d

Eq. 385

Using approximation basis functions as in the Rayleigh-Ritz method this equation can be written in matrix form
as
L

d i d j
d jw
EI -------- dx ----------------
+
dx dx i j
i dx- dx
0
L

d iw
---------- j dx
dx

0
L

d iw d jw

---------- ---------- dx
dx dx

M i

c j
=
c jw

iw fdx

Eq. 386

Workbook of Applications in VectorSpace C++ Library

215

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

We label Eq. 386 as Mc = b. We may choose approximation basis functions as


2
w
= i i , where i = x, and iw = x x
T

Eq. 387

Program Listing 313 implements the penalty function formulation as in Eq. 386 and approximation basis
functions as in Eq. 387.
#include "include\vs.h"
int main() {
double L_ = 1.0, E_ = 1.0, I_ = 1.0, f_ = 1.0, M_ = 1.0,
rho = 1.0, weight[3] = {1.0/3.0, 4.0/3.0, 1.0/3.0};
Quadrature qp(weight, 0.0, L_, 3);
C0 c, delta_c, c_cache(3, (double*)0);
do {
H1 x(qp), psi = x,
w = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature",
2, 1, qp);
w[0] = x; w[1] = x.pow(2);
H0 m = INTEGRABLE_MATRIX("int, int, Quadrature", 3, 3, qp);
m[0][0] = E_*I_*d(psi)*d(psi)+rho*((H0)psi)*((H0)psi);
m[0][1] = m[1][0] = rho*((H0)psi)*d(w[0]);
m[0][2] = m[2][0] = rho*((H0)psi)*d(w[1]);
m[1][1] = rho*d(w[0])*d(w[0]); m[1][2] = rho*d(w[0])*d(w[1]);
m[2][1] = rho*d(w[1])*d(w[0]); m[2][2] = rho*d(w[1])*d(w[1]);
C0 M = m | J(L_/2.0);
C0b(3, (double*)0);
b[0] = -M_*L_; b[1] = (((H0)w[0])*f_) | J(L_/2.0); b[2] = (((H0)w[1])*f_) | J(L_/2.0);
c &= b / M;
delta_c &= c_cache - c;
c_cache = c;
rho *= 5.0;
} while((double)norm(delta_c) > 1.e-6);
cout << c << endl;
return 0;
}

= x, and w = x x
L

M00=

2 T

d 0 d 0
EI ---------- ---------- dx
dx dx

0
L
w
w
0 d 1 dx ,
[M01, M02] = 0 d
--------- ---------0

M 10
M 20

dx

dx

d w

-------- dx
0 dx
=
d 1w

0 --------
dx

M11 M 12
M21 M 22

b=

d w d w
= ---------- ---------- dx
dx
dx
0

w w

( M 0 ( L ) ) 0 1 fdx

Listing 313 Penalty function formulation for beam bending problem (project: penalty_function).

Notice that the penalty functional Jp can be written in quadratic form Jp(c) = cTMc-cT b where M is a symmetrical positive definitive. Jp = 0 gives Mc = b. Therefore, the solution is c = b / M. Alternatively, we consider that Newtons method for the minimization of Jp(x) should be achieved in just one iteration for a quadratic
functional
c = - Jp,c / Jp,c c = b / M

Eq. 388

Applied Newtons formula gives the same result. Therefore, Eq. 386 can be used to replace the inner loop of the
Newtons iteration in Program Listing 220 for the penalty method in Chapter 2.

216

Workbook of Applications in VectorSpace C++ Library

Variational Methods
The results of the penalty function formulation are shown in Figure 319. Both the and w approximation
are significantly different from the exact solution, considering the exact solution for y is spanned by [x, x2, x3] (in
Eq. 379), and the exact solution for w is spanned by [x2, x3, x4] (in Eq. 368).

0.2 0.4 0.6 0.8


-0.2
-0.4
-0.6
-0.8
-1

exact

0.6
0.5
0.4
0.3
0.2
0.1

exact

0.2 0.4 0.6 0.8

Figure 319 Penalty formulation for beam bending problem.

4. Mixed Formulation: The irreducible formulation is based on a fourth-order differential equation (Eq. 366),
which is obtained from substituting M in Eq. 365 into Eq. 364. The mixed formulation is based on the two separated equations, Eq. 364 and Eq. 365, directly. That is
2

M
dM
dw
= ---------, and
= f
2EI
dx2
d x2

Eq. 389

These equations are subject to the boundary conditions of w(0) = 0, and M(L) = M. The Lagrangian functional
corresponding to the above equations is
L

J M ( w, M ) =

M2
dw dM + ------- d x d x 2EI- + fw dx

Eq. 390

Setting JM = 0, we can obtain Euler-Lagrange equations as


L

- -------- + wf dx
---------
dx dx
0
L

dw dM

( M )M

= 0

- ------- + ------------------ dx
---------dx dx
EI
dM dw

= 0

Eq. 391

Workbook of Applications in VectorSpace C++ Library

217

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Using Eq. 365, the exact solution for the bending moment M can be obtained by differentiating Eq. 368 as
Mexact(x) = (f/2) (x-L)2 +M
The approximated solutions for w and M, which satisfies the boundary condtions w(0) = 0 and M(L) = M, are
taken as
w c 0w x + c 1w x 2, and M M + c 0M ( L x ) + c 1M ( L x ) 2

Substituting w and M in Eq. 391, we can write Eq. 391 in matrix form as
L

d w d M
- ---------- dx
--------dx
dx
cw

d w

dx
- ---------- dx -------------------- --------dx
dx
EI
0

0
L

d M

w fdx

cM

Eq. 392

MM

------------ dx
EI

where w = [x, x2], and M = [(L-x), (L-x)2]. The second term in the right-hand-side vector has the bending
moment boundary condition M(L) = M, which is shifted to the right-hand-side of Eq. 392 from the second term
in the second equation of the left-hand-side of Eq. 391. Program Listing 314 implements Eq. 392. The results
of the mixed formulation are shown in Figure 320.

#include "include\vs.h"
int main() {
double L_ = 1.0, E_ = 1.0, I_ = 1.0, f_ = 1.0, M_ = 1.0,
weight[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(weight, 0.0, L_, 5.0);
H1 x(qp),
w = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 2, 1, qp),
M = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE("int, int, Quadrature", 2, 1, qp);
w[0] = x;
w[1] = x.pow(2);
M[0] = x-L_; M[1] = (x-L_).pow(2);
C0 e(2), E(2),
m =+( 0.0
*((e%e)*(E[0]%E[0])) +
(d(w)*(~d(M)))
*((e%e)*(E[0]%E[1]))+
(d(M)*(~d(w)))
*((e%e)*(E[1]%E[0])) +
( ((H0)M)*(~((H0)M))/(E_*I_) )*((e%e)*(E[1]%E[1])) ) | J(L_/4),
b = +( ( (-(H0)w)*f_ )
*(e*E[0])+
( (-(H0)M)*(M_/(E_*I_)) )
*(e*E[1]) ) | J(L_/4);
c = b / m;
cout << c << endl;
return 0;
}

M01 =

d w

d M

d M

d w

- ---------- dx
--------dx
dx
0
L

M10 =

- ---------- dx
--------dx
dx
0
L

M11 =

dx
--------------------EI
M

w fdx

b=

0
L M
M

------------ dx
EI
0

Listing 314 Mixed formulation for beam bending problem (project: mixed_formulation).

218

Workbook of Applications in VectorSpace C++ Library

Variational Methods

0.6
0.5
0.4
0.3
0.2
0.1

1.5
1.4
1.3
1.2
1.1

exact ~~ approx.

0.2 0.4 0.6 0.8 1

exact = approx.

0.2 0.4 0.6 0.8 1

Figure 320 Approximated transeverse deflection w and bending moment M using mixed
formulation for the beam bending problem.

Green Function Solution: We now re-visit the solution by integral equation using Green function to solve the
same fourth-order differential equation and boundary conditions posed in Eq. 365 and Eq. 366. For simplicity
we set all material constant as 1 and this simplifies the problem to have a Green function that satisfies
4

dg
= ( x ), 0 < x, < 1 ;g ( 0, ) = g( 0, ) = g( 1, ) = 0, g( 1, ) = 1
dx4

Eq. 393

where ( . ) is the Dirac delta function. The jump condition of the shear force (V) due to the concentrated load at
is
V(+)-V(-) = -1
That results in the jump condition
solving the Green function is

g( + , ) g( , ) = 1

. Therefore, the equation and conditions for

1.

dg
= 0, 0 < x < , < x < 1
dx4

2. ( 0, ) = g( 0, ) = g( 1, ) = 0, g( 1, ) = 1
3. g, g, g continuous at x = ; g( + , ) g( , ) = 1

Workbook of Applications in VectorSpace C++ Library

219

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

From conditions 1. and 2. we can determine that the Green function is of the form
For x < , g1= Ax2 + B x3 (from g4 = 0 and g ( 0, ) = g( 0, ) = 0 )
For x > , g2 =a + b (1-x) + c (1-x)2 (from g4 = 0 and g( 1, ) = 0 )
We can determine c = 1/2 by using g( 1, ) = 1 . Applying the jump condition g( + , ) g( , ) = 1 on x
= we have
g1= Ax2 - (1/6) x3 , and g2 =a + b (1-x) + (1/2)(1-x)2
That is B = -1/6. Consequently, the continuity of g at gives A = (1+)/2, and the continuity of g gives b = - 1
2/2. Then, the continuity of g gives a = 1/2 +(1/2) 2 (1/6) 3. Therefore,
g1= ((1+)/2) x2 - (1/6) x3; for x <
g2 = (1/2 +(1/2) 2 (1/6) 3) - (1+2/2) (1-x) + (1/2) (1-x)2; for x >

Eq. 394

Program Listing 315 implements the Green function defined in Eq. 394, the transverse loading f(x) is taken as
a constant 1.0. The results of eleven-points values are shown in Figure 321 for compared with the exact solution.

#include "include/vs.h"
int main() {
double x = 0.0,
wt[17] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0 64.0/45.0, 24.0/45.0,
64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 14.0/45.0};
for(int i = 0; i < 11; i++) {
Quadrature q1(wt, 0.0, x, 17), q2(wt, x, 1.0, 17);
double c = 1.0/2.0, B = -1.0/6.0;
H0 z1(q1), z2(q2);
H0 A = (1.0 + z2) / 2.0,
a = 1.0/2.0+1.0/2.0*z1.pow(2)-1.0/6.0*z1.pow(3),
b = -1.0 - 1.0/2.0*z1.pow(2),
integrand1 = a + b*(1.0-x)+ c*pow((1.0-x), 2),
integrand2 = A*pow(x, 2) + B*pow(x, 3);
C0 integal_1, integal_2;
if(i != 0) integal_1 &= integrand1 | J(x / 16.0); else integal_1 &= C0(0.0);
if(i != 10) integal_2 &= integrand2 | J((1.0-x) / 16.0); else integal_2 &= C0(0.0);
double w = (double) (integal_1 + integal_2);
cout << "w(" << x << "): " << w << endl;
if(i != 10) x += 0.1;
}
return 0;
}

f(x) = 1, a constant
c = 1/2, B = - 1/6
A = (1+)/2
a = 1/2 +(1/2)2 (1/6)3
b = - 1 2/2
g2 =a + b (1-x) + c (1-x)2 (where <x)
g1= Ax2 + B x3 (where >x)
x

w(x) =

g2 d +
0

g 1 d

Listing 315 Integral equation solution using Green function for beam bending problem (project:
green_function).
220

Workbook of Applications in VectorSpace C++ Library

Variational Methods
0.6
0.5
0.4

0.3
0.2
0.1
0.2

0.4

0.6

0.8

Figure 321 Point-values are integral equation solution using the Green function compared
with the curve of the exact solution.

Workbook of Applications in VectorSpace C++ Library

221

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Poisson Equation
The two sub-sections on second-order differential equation and the fourth-order differential equation discussed above are ordinary differential equations with only one dimension. We now deal with the Poisson equation which is a partial differetial equation with dimensions greater than one.
Consider the Poisson equation defined in an unit square region with homogenous essential or natural boundary conditions
2 u = f

Eq. 395

Denote the square region as and its boundary as . Multiply the left-hand-side with the variation v and integrate over the square region .
v 2 udV =

[ ( vu ) v u ]dV

v udV vu nds

v udV

Eq. 396

The first identity uses the integration by parts and the second identity uses divergence theorem of Gauss, where
n is the surface unit normal vector. For homogeneous boundary conditions the boundary integral term vanishes.
We investigate three sets of boundary conditions
1. Dirichlet boundary conditions: u = 0 on all sides,
2. Neumann boundary conditions: u n = 0 on all sides,
3. Mixed boundary conditions: u = 0 on x0 = 1 and x1 = 1; u n = 0 on x0 = 0 and x1 = 0.
The matrix form for the Eq. 396 in this particular 2-D settings can be re-written as
11

Mij

i j i j
= -------- -------- + -------- -------- dx 0 dx 1, b i =
x 0 x 0 x 1 x 1
00

11

i fdx 0 dx1

Eq. 397

00

where bi is the right-hand-side vector.


Dirichlet Boundary Conditions : the basis functions to satisfy these conditions are
i = mn = sin((m+1)x0) sin((n+1)x1) ; m, n = 0, 2, ..., N-1, and i = m N + n.

Eq. 398

Program Listing 316 implements Eq. 397 with basis functions in Eq. 398, where N = 3 and f = 1. Notice that
the 2-D integration are obtained by forming a 2-D array of weightings. The Jacobian of this problem is constant
throughout the whole integration domain. Figure 322 shows the results obtained from Program Listing 316.

222

Workbook of Applications in VectorSpace C++ Library

Variational Methods
#include "include\vs.h"
#define PI 3.141597
int main() {
double f_0 = 1.0, weight[5][5],
bode[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++) weight[i][j] = bode[i] * bode[j];
Quadrature qp(weight[0], 0.0, 1.0, 5, 0.0, 1.0, 5);
J d_a(pow( (1.0/4.0), 2.0));
H1 x(2, (double*)0, qp), phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature",9, 2, qp);
for(int m = 0; m < 3; m++)
for(int n = 0; n < 3; n++) phi[m*3+n] = sin((m+1.0)*PI*x[0])*sin((n+1.0)*PI*x[1]);
H0 M_diag(9, (double*)0, qp);
for(int i = 0; i < 9; i++)
M_diag[i] = d(phi[i]).pow(2);
C0 M = M_diag | d_a,
b = ( ((H0)phi) * f_0 ) | d_a,
c(9, (double*)0);
for(int i = 0; i < 9; i++) c[i] = b[i] / M[i];
cout << c << endl;
return 0;
}

2-D weightings
2-D Jacobian
i = mn = sin(mx0) sin(nx1)
m, n = 0, 2, ..., N-1, and i = m N + n
11

M ii =

i i

i i

- -------- + -------- -------- dx dx


------x 0 x 0 x 1 x 1 0 1

00
11

bi =

i fdx0 dx1
00

Listing 316 The Poisson equation with the Dirichlet boundary conditions (project: poisson_dirichlet).

0.06
6
1

0.04
04

0.8

0.02
02

0.6

0
0
0.2

0.4
0.4
0.2

0.6
0.8
10

Figure 322 Solution of Poisson equation with homogeneous Dirichlet boundary conditions.

Neumann Boundary Conditions : the basis functions are


i = mn = cos(mx0) cos(nx1) ; m, n = 0, 1, 2, ..., N-1, and i = m N + n

Eq. 399

For this Neumann boundary condition to be solvable, f can not be a non-zero constant. On physical ground if we
consider the Poisson equation to be for the heat conduction problem, the homogeneous Neumann boundary conditions mean that the square region is to be insulated from its surroundings. The temperature in the region will
Workbook of Applications in VectorSpace C++ Library

223

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

increase with time, since the internal source f is added to the region. For a steady state solution to be possible
with totally insulated condition, we conclude that the N(A*) of the Laplace operator consists of constant functions (with the homogeneous Neuman boundary conditions.) Therefore, the solvability condition, from Eq. 350,
requires the orthogonal relation which has the internal source to equal the internal sink; i.e.,

f dV

Eq. 3100

= 0

In this case, we choose f = cos x which satisfies Eq. 3100. For the computation we only need to replace the
definition for i (N = 2) and the source term f = cos x.
Mixed Boundary Conditions : We choose approximation basis functions to be algebraic polynomials of the
form
i = (1-x02+i) (1-x12+i); i = 0, 1, 2, ..., N-1

Eq. 3101

We choose N = 2 and f = 1. The results of the Neumann boundary conditions and the mixed boundary conditions
are shown in Figure 323.
Mixed boundary conditions, with f = 1.0
Neumann boundary conditions, with f = cos x

0.3
3

0.1
1
0.05
5
0
-0.05
05
-0.1
.1
0

1
0.8

0.8

0.1
.1

0.6
0.2

0.2
2

0.4

0.6

0
0
0.2

0.4
0.4

0.4
0.2

0.6

0.2

0.6
0.8

0.8
10

10

Figure 323 Solutions of the Poisson equation with the Neumann and mixed boundary conditions.

Green Function Method : The Green function for Eq. 395 with the Dirichlet boundary condtions is1

g ( x, y ;, ) =

sin ( n ) sin ( nx ) { cosh ( n ( 1 ( y + ) ) ) cosh ( n ( 1


-------------------------------n sinh ( n )

y ))}

Eq. 3102

n=1

1. Problem 9.3.9 in p. 147 of G.F. Carrier, and C.E. Pearson, 1988, Partial Differential Equations: Theory and technique
2nd eds., Academic Press Inc., San Diego, CA.

224

Workbook of Applications in VectorSpace C++ Library

Variational Methods
Program Listing 317 (project: green_poisson) is the code for Poisson equations with the Dirichlet boundary
conditions using the Green function (Eq. 3102). The computation approximates the infinite series only up to n =
8. The results of this approximation are shown in Figure 324.
#include "include\vs.h"
#define PI 3.141597
H0 cosh(const H0& a) { return (exp(a)+exp(-a))/2.0; }
int main() {
const double f_0 = -1.0,
bode[17] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0,
64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0,
64.0/45.0, 14.0/45.0}, weight[17][17];
for(int i = 0; i < 17; i++)
for(int j = 0; j < 17; j++) weight[i][j] = bode[i] * bode[j];
Quadrature qp(weight[0], 0.0, 1.0, 17, 0.0, 1.0, 17);
J d_a(pow( (1.0/16.0), 2.0));
double x0, x1;
H0 z(2, (double*)0, qp), integrand(qp), zai, eta; zai &= z[0]; eta &= z[1];
for(int i = 0; i < 11; i++) {
for(int j = 0; j < 11; j++) {
x0 = 0.1 * j; x1 = 0.1 * i;
integrand = 0.0;
for(int n = 1; n <= 8; n++) {
integrand += (f_0/(n*PI*sinh(n*PI))*sin(n*PI*x0)*sin(n*PI*zai)*
(cosh(n*PI*(1.0-x1-eta))-cosh(n*PI*(1.0-sqrt((x1-eta)*(x1-eta))))));
}
C0 integal = integrand | d_a;
cout << "u(" << x0 << ", " << x1 << ") = " << ((double)integal) << ", ";
}
cout << endl;
}
return 0;
}

2-D weightings
2-D Jacobian

g ( x, y ;, ) =

sin ( n ) sin ( nx )

--------------------------------------------n sinh ( n )
n=1

{ cosh ( n ( 1 ( y + ) ) ) cosh ( n ( 1 y ) ) }

Listing 317 The Green function method on the Poisson equation with the Dirichlet boundary conditions.

0.06
6

1.0
1.

0.04
04
0.02
02
0
0.0

-1

0.5

0.5

1 -1
Figure 324 Eight-term (n=8) Green function method for the Poisson equation with the Dirichlet
boundary conditions.

1.0
1
0 0.0

Workbook of Applications in VectorSpace C++ Library

225

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

3.3.2 Weighted-Residual Method


For a linear differential equation Au = f, with a self-adjoint operator A, the approximated solution uN is
u u N = + c i i

Eq. 3103

where is set to the essential boundary conditions of u, and i is homogenous on the boundaries. Define the
residual RN of the approximated solution as
Eq. 3104

R N = Au N f

The residual can be distributed in an over-all manner through-out the whole domain, and then set the integrated
value to be zero, such as
( w, R N ) =

wRN d

= 0

Eq. 3105

where w is the weighting function. Different ways of defining the weighting function lead to different types of
approximation methods. The general class of methods in the form of Eq. 3105 is known as the weighted-residual methods.

Point-Collocation Method
The weighting function of the point-collocation method can be expressed using the Dirac delta function that
is
w = (x-)

Eq. 3106

For a function f(x), we have

( x )f ( x ) dx

= f( )

Eq. 3107

Therefore, substituting Eq. 3106 into Eq. 3105 gives RN() = 0. What we have to do is simply pick a number of
collocation points i , evaluate their corresponding residuals, and obtain a system of equations by setting these
residual equations to zero.
Considering the example1
2

du
+ u + x = 0,
dx2

0<x<1

Eq. 3108

1. p. 14 and on in C.A. Brebbia, J.C.F. Telles, and L.C. Wrobel, 1984, Boundary element techniques: Theory and applications in engineering, Springer-Verlag, Berlin, Germany.

226

Workbook of Applications in VectorSpace C++ Library

Variational Methods
subject to boundary conditions u(0) = u(1) = 0. The exact solution to this problem is
sin ( x )
u exact = --------------- x
sin ( 1 )

Eq. 3109

Two term approixmation basis functions which satisfy this homogenous boundary condition can be taken from
Eq. 361 in page 204,
0 = x (1-x), and 1 = x2 (1-x)
That is u2 = c0 0 + c1 1. Two collocation points are necessary for solving the two unkown coefficients, and they
are taken at 0 = 1/4 and 1 = 3/4. These two points generate two residual equations in matrix form as

d2 1 ( 0 )
d 2 0 ( 0 )
---------------------- + 0 ( 0 ) --------------------- + 1 ( 0 )
c0
0
dx 2
dx 2
=
2
2
c1
1
d 1 ( 1 )
d 0 ( 1 )
--------------------- + 0 ( 1 ) --------------------- + 1 ( 1 )
2
2
dx
dx

Eq. 3110

We can also write Eq. 3110 as M c = - b. This two-point collocation problem is simple enough to be solved by
hand, or you can code it with VectorSpace C++ Library, which has the advantage that it can be extended to higher
number of basis functions and collocation points, and the matrix solution procedure becomes inevitable (see
project: point_collocation)
double x[2] = {0.25, 0.75};
// 0 = 1/4, 1 = 3/4
C0 M(2, 2, (double*)0), b(2, x);
for(int i = 0; i < 2; i++) {
C2 z(x[i]),
phi = VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(int, int, 2, 1);
phi[0] = z*(1-z); phi[1] = z.pow(2)*(1-z);
// 0 = x (1-x), 1 = x2 (1-x)
M[i] = (+dd(phi))(0)+((C0)phi);
// d2/dx2 +
}
C0 c = -b / M;
cout << c << endl;
// c = {0.189841, 0.172043}T
For a Vector_of_Tangent_of_Tangent_Bundle object with spatial dimension = 1, we need a forced degeneration
operation for its Hessain, (+dd(phi))(0). The first operation has the primary casting operator + casting a
Nominal_Submatrix to a Matrix, and then a column selector ( ) makes this Matrix into a Vector. The approximated two-point-collocation solution is u2 = 0.189841 x (1-x) + 0.172043 x2 (1-x). This result is plotted against
the exact solution uexact = sin(x)/sin(1) -x in Figure 325. There are no significant differences among the two
from the left-hand-side of Figure 325.

Workbook of Applications in VectorSpace C++ Library

227

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Solution - Exact
0.07
0.06
0.2

0.05
0.04

-0.0002

0.03

-0.0004

0.4

0.6

0.8

0.02
-0.0006

0.01
0.2

0.4

0.6

0.8

-0.0008

Figure 325 Two-points collocation solution and error comparing to the exact solution.

We can investigate further on the relationships of the point-collocation method and the finite difference
method. Considering the domain (cell) has three equally spaced points xi-1, xi, and xi+1, the approximating
function u correspoinding to these three points are given as ui-1, ui, and ui+1. The value of u in between two consequtive points can be interpolated with a set of quadratic interpolation functions as
u = ui-1 1 + ui 2 + ui+1 3

Eq. 3111

1 = (-1)/2, 2 = (1-) (1+), and 3 = (1+)/2, where -1 < < 1

Eq. 3112

where

Considering the cell length = 2h for the three equally spaced points, we have a constant Jacobian for the coordinate transformation rule through-out the whole cell as d/dx = 1/h. With a point-collocation on = 0, the first
derivative of u with respect to x is
du/ dx = (du/ d) (d/dx) = [(-1/2)ui-1 + 2ui + (+1/2)ui+1] 1--h

=0

1
= ------ (ui+1-ui-1)
2h

Eq. 3113

Notice that the point-collocation is taken at = 0. Eq. 3113 is the central difference formula. We can check that
point-collocation at = -1/2 and = 1/2 will yield the backward difference and the forward difference formula,
respectively. The second derivative of u can be derived accordingly as
1
h

d2u/ dx2 = (d2u/ d2) (d/dx)2 =----2- (ui-1-2 ui + ui+1)

Eq. 3114

This finite difference formula for the second derivative is independent of ; i.e., the position of collocation point.

228

Workbook of Applications in VectorSpace C++ Library

Variational Methods
Subdomain-Collocation Method
The weighting function for the subdomain-collocation method is taken as a step function defined, for example, as

1, 1 < x < 2
w =
0, 1 < x < 1 or 2 < x < 1

Eq. 3115

where x, 1, and 2 can be all defined in the interval of (-1, 1). For a function f(x), we have
2

wf ( x )dx

f ( x )dx

Eq. 3116

That is the domain of integration is now restricted to the subdomain bounded by [1, 2]. Substituting the weighting function of Eq. 3115 in the weighted-residual statement of Eq. 3105 gives
2

RN ( x )dx

Eq. 3117

= 0

The subdomain-collocation method evaluates a number of subdomains bounded by different sets of [1, 2] in
Eq. 3117, for solving the coefficient vector c.
Considering the same example in the point-collocation case with the same basis functions and two subdomains 1 = (-1, 0), and 2 = (0, 1), we then have

d2 0
----------- + 0 dx
dx 2

d 2 1
- + 1 dx
---------dx 2
c0
1

d2 0
----------- + 0 dx
dx 2

c1
d 2 1
----------- + 1 dx
2
dx

xdx
=

Eq. 3118

xdx
2

The code which implements Eq. 3118 with VectorSpace C++ Library is (project: subdomain_collocation)
double x[2][2] = {{-1.0, 0.0}, {0.0, 1.0}},
// 1 =(-1,0), 2 = (0, 1)
w[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0}; // Bodes integration rule
C0 M(2, 2, (double*)0), b(2, (double*)0);
for(int i = 0; i < 2; i++) {
Quadrature qp(w, x[i][0], x[i][1], 5);
// Quadrautre in subdomain i
J d_l((x[i][1]-x[i][0])/4.0);
Workbook of Applications in VectorSpace C++ Library

229

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


H2 z(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
int, int, Quadrature, 2, 1, qp);
phi[0] = z*(1-z); phi[1] = z.pow(2)*(1-z);
// 0 = x (1-x), 1 = x2 (1-x)
M[i] = (+dd(phi))(0)+((H0)phi) | d_l;
// d2/dx2 +
b[i] = - ((H0)z) | d_l;
}
C0 c = b / M;
cout << c << endl;

// c = {0.181818, 0.181818}T

The coefficient vector is not substantially different from that of the point-collocation case. The results are shown
in Figure 326.
Error
0.07

0.00025

0.06

0.2
0.05

0.4

0.6

0.8

-0.00025

0.04

-0.0005

0.03

-0.00075
-0.001

0.02

-0.00125
0.01

-0.0015
0.2

0.4

0.6

0.8

Figure 326 Solution of subdomain collocation and error compared with the exact
solution.
We note that the first derivative of u with respect to x collocated in the interval of (-1/2, 1/2) is
1
--2

1
--2

du

d x dx
1
--2

d d x dx
du

1 1
1
= --- --- ( 1 )u i 1 + ( 1 ) ( 1 + )u i + --- ( 1 + )u i + 1
h 2
2

1
--2

1
--2
1
--2

1
= ------ (ui+1-ui-1) Eq. 3119
2h

This gives the central difference formula. Similarly, subdomains [-1, 0] and [0, -1] give backward difference and
forward difference formula, respectively.

Method of Moment
In statistics, the idea of using moments to descirbe a distribution is taken from mechanics. The expectation of
a distribution can be considered as the center of the gravity. The variance is the second power of distances of the
data with respect to this center of gravity. Skewness and kurtosis are defined as the third and fourth power of
the distances, respectively.
For the weighted-residual method, we can choose the weighting function in Eq. 3105 to be the various
power of coordinate variable x, such as

230

Workbook of Applications in VectorSpace C++ Library

Variational Methods
wi = xi, i = 0, 1, 2, ....

Eq. 3120

That is the residuals (or errors) are distributed through-out the domain with various moments of x. We notice that
the weighting function for the weighted residual method in general is not necessarily required to satisfy the
homogeneous boundary conditions.
Consider the example in the point-collocation and subdomain collocation with the approximation basis function 0 = x (1-x), and 1 = x2 (1-x). We use first two weighting moments w 0 = 1 and w1 = x. This gives
d2
----------0- + dx
dx 2 0

d2
----------1- + dx
dx 2 1

c0

d2
----------0- + dx
x
dx 2 0

c
d2
----------1- + dx 1
x
dx 2 1

xdx
=

Eq. 3121

x 2 dx

The code which implements Eq. 3121 with VectorSpace C++ Library is (project: method_of_moment)
double w[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0}; // Bodes integration rule
C0 M(2, 2, (double*)0), b(2, (double*)0);
Quadrature qp(w, 0.0, 1.0, 5);
J d_l(1.0/4.0);
for(int i = 0; i < 2; i++) {
H2 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
int, int, Quadrature, 2, 1, qp);
phi[0] = x*(1-x); phi[1] = x.pow(2)*(1-x);
// 0 = x (1-x), 1 = x2 (1-x)
M[i] = (((H0)x).pow(i)*(+dd(phi))(0)+((H0)phi)) | d_l; // d2/dx2 +
b[i] = - ((H0)x).pow(i+1) | d_l;
}
C0 c = b / M;
cout << c << endl;
// c = {0.166667, 0.212121}T
The results of this implementation are shown in Figure 327.
Error

0.07
0.001

0.06
0.05

0.2

0.04
0.03

0.4

0.6

0.8

-0.001

0.02
-0.002

0.01
0.2

0.4

0.6

0.8

Figure 327 Method of moment solution and its error.


Workbook of Applications in VectorSpace C++ Library

231

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Galerkin Method: Bubnov-Galerkin / Petrov-Galerkin Methods and Weak Formulation


We have chosen the weighting functions to be a Dirac delta function in point-collocation, a step function in
subdomain collocation, and a set of power of coordinate x for the method of moment. In Galerkin method the
weighting functions are simply the same as the approximation basis functions.That is
wi = i = x(i+1) (1-x), i = 0, 1, 2, ...

Eq. 3122

Consider the same example we solved starting from the point-collocation method in the above. We have
d2 j

- + j dx
i --------
dx 2

c j = i xdx

Eq. 3123

For two term approximation (i = 0, 1), the matrix form can be written as

d2 0

d 2 1

- + 0 dx 0 ----------- + 1 dx
0 ---------
dx 2

dx 2

d2

0
1 --------- dx 2

+ 0 dx

d2

1
1 --------- dx 2

+ 1 dx

c0
c1

0 xdx
=

Eq. 3124

1 xdx

The code implements Eq. 3124 with VectorSpace C++ Library as (project: galerkin_method)
double w[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0}; // Bodes integration rule
C0 M(2, 2, (double*)0), b(2, (double*)0);
Quadrature qp(w, 0.0, 1.0, 5);
J d_l(1.0/4.0);
for(int i = 0; i < 2; i++) {
H2 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
int, int, Quadrature, 2, 1, qp);
phi[0] = x*(1-x); phi[1] = x.pow(2)*(1-x);
// 0 = x (1-x), 1 = x2 (1-x)
M[i] = (((H0)phi)[i]*(+dd(phi))(0)+((H0)phi)) | d_l;
// d2/dx2 +
b[i] = - (((H0)phi)[i]*((H0)x)) | d_l;
}
C0 c = b / M;
cout << c << endl;
// c = {0.166667, 0.212121}T
The results of the above implementation are shown in Figure 327. Notice that although we choose the weighting functions equal to the approximation basis functions; i.e., wi = i , the left-hand-side matrix M is still not
symmetrical. This is because the operator A(u) = (d2 u/ dx2 + u) is not self-adjoint. .
232

Workbook of Applications in VectorSpace C++ Library

Variational Methods
0.08

0.14

Error

0.12

0.06
0.1
0.08

0.04

0.06

0.02

0.04
0.02

0.2
0.2

0.4

0.6

0.8

0.4

0.6

0.8

Figure 328 Galerkin method solution and its error.


For a positive definite operator A = (T*) T, where T* is the self-adjoint of T (i.e., T*=T), the Galerkin method
with homogeneous boundary conditions gives
(Ai, j) = (Ti, Tj) = a(i, j)

Eq. 3125

= ( i, A j )

Eq. 3126

where a( . , . ) is a bilinear form which is symmetrical. Therefore, A is self-adjoint ( Eq. 3126), and the resultant
weak formulation with the Galerkin weighting is symmetrical (Eq. 3125). In the case of the self-adjoint operator, the Galerkin method with wi = i is also known as the Bubnov-Galerkin method. When wi i , it is known
as the Petrov-Galerkin method
A second example is the eigenvalue problem of a circular membrance of radius a given by1
2u = u

Eq. 3127

with homogeneous essential boundary conditions. This axisymmetric problem can be reduced to a 1-D problem
in polar coordinate r as
1d
du
--- r
= u
r d r d r

Eq. 3128

The approximation basis functions which satisfy the homogeneous boundary conditions are
r
i = cos ( 2 i + 1 ) ------, i = 0, 1, 2, , N 1
2a

Eq. 3129

For the Galerkin method with wi = i, we have

1. p. 292 in J.N. Reddy, 1986, Applied functional analysis and variational methods in engineering, McGraw-Hill, Inc.

Workbook of Applications in VectorSpace C++ Library

233

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


a

1 d dj
i --r- d r r d r ( 2rdr )cj =
0

i j ( 2rdr )cj

Eq. 3130

Therefore,
2

a d
a

d j
j r

rdr c
c
dr
=

i 2
idr
i j j
dr j
0

Eq. 3131

We have a generalized eigenvalue problem of the form


Ax = B x

Eq. 3132

We solve Eq. 3131 for N = 2 and a = 1. First, we notice that the off-diagonals of A is analytically identical since
the Laplace operator is self-adjoint. However, numerically, the off-diagonals of A can be slightly different due to
errors from numerical integration. We can either ignore such differences or symmetrize A numerically by defining As = (A+AT)/2. Now we can solve the generalized eigenvalue problem by using the inverse of B as
B -1Asx = x

Eq. 3133

However, (B -1As) will not be symmetrical. We can not use a symmetrical eigenvalue solver for this problem.
Therefore, we first use Cholesky decomposition for the symmetrical matrix B = LLT. The symmetry of the lefthand-side can now be preserved by pre-multipling L -1 and post-multipling (L-1)T on Eq. 3132 to give
(L -1) As ((L-1)T) x = x

Eq. 3134

Program Listing 318 implements the Galerkin method with Laplace operator in Eq. 3131, and using Eq. 3134
to solve the symmetric eigenvalue problem.
The results are shown in Figure 329. The surface graphs represent the modes from eigenvectors as a function of vi j j, where vi is the i-th eigenvector. The frequencies i are computed from eigenvalues i as
i =

234

Workbook of Applications in VectorSpace C++ Library

Variational Methods
#include "include\vs.h"
#define PI 3.141592654
int main() {
double a_= 1.0,
weight[25] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0,
64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(weight, 0.0, a_, 25);
J d_r(a_/24.0);
H2 r((double*)0, qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3, 1, qp);
phi[0] = cos((PI/2.0/a_)*r); phi[1] = cos((3.0*PI/2.0/a_)*r); phi[2] = cos(5.0*PI/2.0/a_*r);
H0 d2_phi = INTEGRABLE_VECTOR("int, Quadrature", 3, qp);
for(int i = 0; i < 3; i++) d2_phi[i] = dd(phi)(i)[0][0];
C0 A = -( ( d(phi)(0)%((H0)phi) + d2_phi%((H0)phi)*((H0)r) ) | d_r ),
B = ( ((H0)phi)%((H0)phi) * ((H0)r) ) | d_r;
C0 L = MATRIX("int, int", 3, 3);
Cholesky Ch(B);
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
if(i >= j) L[i][j] = Ch.rep_ptr()[0][i*(1+i)/2+j];
else L[i][j] = 0.0;
C0 L_inv = L.inverse(),
C = L_inv*((A+~A)/2.0*(~L_inv)),
lambda = Eigen(C).Eigenvalues(),
v = Eigen(C).Eigenvectors();
cout << lambda << endl;
cout << v << endl;
return 0;
}

radius a = 1
extended Bodes integration rule

r
i = cos ( 2 i + 1 ) ------, i = 0, 1, 2
2a
2

d j
d j
A= i r i 2 dr
d
r
dr

0
a

B=

i j rdr
0

Cholesky decomposition
Lower triangular matrix
(L -1) As ((L-1)T) x = x
= {5.78529, 30.4889, 75.0492}T
v0 ={0.999174, 0.398374, -0.008019}T
v1 ={0.0396508,-0.998966,-0.022225}T
v2={0.00889577,-0.0218887,0.99972}T

Listing 318 Galerkin method for the eigenvalue problem of a circular membrance (project:
circular_membrance).

0 =2.40526

1 = 5.52168

2 = 8.66309

2
1

0.5

-1
-2
-1

0.5

-1
-2
-1

-0.5

-0.5

1 -1

0
-0.5

0
0.5

0.5

0.5

1
0.5

-1
-2
-1
-0.5

-0.5

-0.5

1
0

1 -1

1 -1

Figure 329 Three frequency and mode pairs of the circular membrance eigenvalue problem.

Workbook of Applications in VectorSpace C++ Library

235

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

A third example is a non-linear differential equation 1


2

du
du 2
u 2 + = 1,
d x
dx

0 < x < 1, with u' ( 0 ) = 0, and u ( 1 ) =

Eq. 3135

The exact solution to this problem is


u exact ( x ) =

1 + x2

Eq. 3136

This problem can be transformed to one that has homogeneous boundary conditions by setting u = v+ 2 such
that
2

(v + 2)

d v dv 2
+
= 1,
d x 2 d x

0 < x < 1, with

v' ( 0 ) = 0, v ( 1 ) = 0

Eq. 3137

This is equivalent to
dv
d
(v + 2)
dx
dx

= 1,

0 < x < 1, with

v' ( 0 ) = 0, v ( 1 ) = 0

Eq. 3138

Therefore, the residuals of the problem is


R ( vN ) =

dv N
d
( vN + 2)
1
dx
dx

Eq. 3139

The weighted residuals method with Galerkin weightings, wN = ci i , and approximation basis functions, vN = cj
j , gives
1

dv N
d

I ( c ) = c i i R ( v N ) dx = c i i
( vN + 2)
1 dx = 0
dx
dx

Eq. 3140

where ci are arbitary constants and will eventually be dropped from Eq. 3140, and cj is the only unknown vector
of the non-linear problem. Integrating by part on the first term gives the weak formulation
1

I ( c ) = ci ( vN + 2 )

d i dv N
i dx = 0
dx dx

Eq. 3141

An iterative algorithm needs to be employed for this non-linear problem

1. p. 294 in J.N. Reddy, 1986, Applied functional analysis and variational methods in engineering, McGraw-Hill, Inc.

236

Workbook of Applications in VectorSpace C++ Library

Variational Methods
I ( c jk + 1 ) = I ( c jk + cjk ) I ( cjk ) +

I
c

c jk = 0

Eq. 3142

cjk

where cjk+1 = cjk + cjk. The approximation in this equation is the Taylor expansion to the first-order derivatives.
That is the increment of the solution cjk can be solved by

c jk =

I
c

I ( c jk ) = [ IT ] 1 I ( c jk )

Eq. 3143

d i dv N d j

+
( v + 2 ) dx

dx jdx
dx N

Eq. 3144

where IT the tangent of I(c) can be defined as


I
IT =
c

ci

= ci
0

Program Listing 319 implements the three-parameters approximation of the weak formulation I(c) (Eq. 3141)
and its tangent IT (Eq. 3144), then, uses the iterative alogrithm (Eq. 3143; i.e., Newtons method) to solve for
the increment of the Ritz coefficients c. The preprocessing macro __PETROV_GALERKIN, if defined at
compile time, the corresponding code segment implements the Petrov-Galerkin method with the approximation
basis functions for weighting as
2i + 1
i = cos -------------- , i = 0, 1, 2
2

Eq. 3145

Otherwise, the Bubnov-Galerkin method is assumed and i = i. The approximated solution is


2

u = wN + 2 = c0 ( 1 x ) + c 1 ( 1 x ) + c2 ( 1 x 3 ) + 2

Eq. 3146

The results of the computation are shown in Figure 330. The data speak for themselve without the need for any
elaboration.

Workbook of Applications in VectorSpace C++ Library

237

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

#include "include\vs.h"
#define EPSILON 1.e-12
int main() {
double weight[13] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0,
14.0/45.0};
Quadrature qp(weight, 0.0, 1.0, 13);
J d_l(1.0/12.0);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3, 1, qp);
phi[0] = 1.0-x; phi[1] = 1.0-x.pow(2); phi[2] = 1.0-x.pow(3);
#if defined(__PETROV_GALERKIN)
#define PI 3.141592654
H1 psi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3, 1, qp);
psi[0] = cos(PI/2.0*x); psi[1] = cos(3.0*PI/2.0*x); psi[2] = cos(5.0*PI/2.0*x);
#else
H1 psi;
psi &= phi;
#endif
C0 c(3,(double*)0), delta_c(3,(double*)0);
do {
H1 v = c * phi;
C0 I = ( d(psi)(0) * ( ((H0)v)+sqrt(2.0) ) * d(v)[0] + ((H0)psi) ) | d_l,
I_t = ( d(psi)(0) % (((H0)phi) * d(v)[0] + d(phi)(0) * ( ((H0)v)+sqrt(2.0) ) ) ) | d_l;
delta_c = - I / I_t;
c += delta_c;
cout << c << ", " << norm(delta_c) << endl;
} while((double)norm(delta_c ) > EPSILON);
cout << c << endl;
return 0;
}

extended Bodes integration rule

i = (1-xi+1), i = 0, 1, 2
Petrov-Galerkin method
(2 i + 1)
i = cos ---------------------- , i = 0, 1, 2
2

Bubnov-Galerkin method
i = i
1

I=

0
1

IT=

( vN + 2 )

d i dv N
i dx
dx dx

d i dv N dj

+
( v + 2 ) dx

dx jdx
dx N

c = - I / IT , and ck+1 = ck + ck
Bubnov: c = {0.00539687, -0.547092,
0.127479}T, Petrov: c = {0.00884522, 0.554076, 0.131396}T .

Listing 319 Galerkin method for a non-linear differential equation (project: nonlinear_galerkin).

1.4

u exact ( x ) =

1 + x2

0.0006

1.3

0.0004

1.2

0.0002

Petrov-Galerkin

Bubnov-Galerkin
Errors
1.1

0.2

0.2

0.4

0.6

0.8

0.4

0.6

-0.0002

Figure 330 Solution of non-linear differential equation using Bubnov-Galerkin


and Petrov-Galerkinmethods.

238

Workbook of Applications in VectorSpace C++ Library

0.8

Variational Methods
Least Squares Method
The basic idea of the least squares method is introduced in Eq. 126 of Chapter 1 on page 35. The minimization of the squares of the residual norm is
R N 22
R N
= 0
------------------ = 2 RN, ---------
c
c

Eq. 3147

The factor 2 can be dropped since the equation equals zero. Comparing Eq. 3147 with the weighted-residual
statement ( R N, w ) = 0 it shows that the least squares method is a special case of the weighted-residual method
with the weighting function w as
R N
w = ---------c

Eq. 3148

For a non-linear problem, we define


R N
I
I ( c ) = R N, ---------- , and I T =

c
c

ci

RN R N
2 RN

= ----------, ---------- + R N, ------------ c c


c 2

Eq. 3149

For the non-linear problem in the last section,


2

RN = ( vN + 2 )

d vN
dx2

dv N 2
1
+
dx

Eq. 3150

and the first derivatives of RN is


2

dv
R N
d dv N
d
---------- = N +
(v + 2) + 2
dxdx
c
d x2
dx2 N

Eq. 3151

The second derivatives is


2

2 RN
d d
d d
------------- =
+
+2
dx dx
c 2
dx2 dx2

Eq. 3152

Program Listing 320 implements Eq. 3149 to Eq. 3152, with three-parameter approximation. Considering that
the exact solution of the problem is an even function we assume the approximation basis functions are 0 = (1x2), 1 = (1-x4), and 2 = (1-x6). This set of approximation basis functions are as accurate as if we had used sixparameter approximation with continuous power of algebraic functions. The errors of this computation are
shown in Figure 331. Before we proceed any further, we notice that the combination of the concept of subdomain collocation method and weak formulation with Galerkin method provides the foundations of the finite element method which we will discuss in details in Chapter 4 and Chapter 5.
Workbook of Applications in VectorSpace C++ Library

239

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

#include "include\vs.h"
#define EPSILON 1.e-12
int main() {
double weight[13] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0,
14.0/45.0};
Quadrature qp(weight, 0.0, 1.0, 13);
J d_l(1.0/12.0);
H2 x((double*)0, qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 3, 1, qp);
phi[0] = 1.0-x.pow(2); phi[1] = 1.0-x.pow(4); phi[2] = 1.0-x.pow(6);
H0 d2_phi = INTEGRABLE_VECTOR("int, Quadrature", 3, qp);
for(int i = 0; i < 3; i++) d2_phi[i] = dd(phi)(i)[0][0];
C0 c(3, (double*)0), delta_c(3, (double*)0);
do {
H2 w = c * phi;
H0 R = d(w)[0].pow(2)+(((H0)w)+sqrt(2.0))*dd(w)[0][0]-1.0,
dR = 2.0*d(phi)(0)*d(w)[0]+((H0)phi)*dd(w)[0][0]+d2_phi*(((H0)w)+sqrt(2.0)),
ddR = 2.0*(d(phi)(0)%d(phi)(0))+((H0)phi)%d2_phi+d2_phi%((H0)phi);
C0 I = ( dR*R ) | d_l,
I_t = ( dR%dR+ddR*R ) | d_l;
delta_c = -I /I_t;
c += delta_c;
cout << c << ", " << norm(delta_c) << endl;
} while((double)norm(delta_c ) > EPSILON);
cout << c << endl;
return 0;
}

extended Bodes integration rule


0 = (1-x2), 1 = (1-x4), and 2 = (1-x6)
2

RN = ( vN + 2 )
2

R
c

N
I = R N, ----------

2R

N
N
N
IT= ----------, ---------- + R N, ------------c c
c 2

c = - I / IT , and ck+1 = ck + ck
c= {-0.491866, 0.0970614, -0.018541}T

0.0006

Error
0.0004

0.0002

0.6

0.8

Figure 331 The errors of the nonlinear least squares method.

240

Workbook of Applications in VectorSpace C++ Library

2 RN
d d
d d
------------- =
+
+2
dx dx
c 2
dx2 dx2

0.0008

0.4

dx2

dv N 2
1
+
dx

d vN d
R N
d dv N
---------- =
+ 2 ( vN + 2 ) + 2
2
c
dxdx
dx
dx

Listing 320 Least squares method for a non-linear differential equation (project:
nonlinear_least_squares).

0.2

d vN

Variational Methods
3.3.3 Boundary Solution Methods
Consider the residual of the Poisson equation as in Eq. 395; i.e., R N = 2 u + f , in the context of the
weighted-residual statement,
( R N, w ) =

RN w d

( 2 u + f )w d

= 0

Eq. 3153

If we integrate by part once, and apply Greens theorem to transform the volume integral to the surface integral
as

u w + f w d

( n u )w d

Eq. 3154

when the approximation basis functions for u and w are the same the first term in the left-hand-side of Eq. 3154
is equivalent to the corresponding term in the Bubnov-Galerkin method for a self-adjoint operator (weak formulation) discussed in Eq. 3125. When the right-hand-side of Eq. 3154 is included in the variational statment, Eq.
3154 is also equivalent to the corresponding term in the Rayleigh-Ritz method in Eq. 353. Taking Eq. 3154
and integrating by parts once more, and applying Greens theorem to transform volume integral to surface integral,again, we have

( ( 2 w )u + fw ) d

( n w )u d ( n u )w d

Eq. 3155

An alternative view to the weighted-residual derivation from Eq. 3153 is possible. By setting f = - 2 u , we identify, directly, Eq. 3154 as Greens first identity, and Eq. 3155 as Greens second identity.1

Trefftz Method
In Trefftz method, both u and w in Eq. 3155 are taken as harmonic functions. By definition, harmonic founctions satisfy the Laplace operator
2 u = 2w = 0

Eq. 3156

(i.e., f = 0). We obtain the boundary integral equation as

( n w )u d

( n u )w d

Eq. 3157

Considering the Poisson equation2

1. p. 450 in L.E. Malvern, 1969, Introduction to the mechanics of a continuous medium, Prentice-Hall, Englewood Cliffs,
N.J.
2. p. 38 in C.A. Brebbia, J.C.F. Telles, and L.C. Wrobel, 1984, Boundary element Techniques: Theory and applications in
engineering, Springer-Verlag, Berlin, Germany.

Workbook of Applications in VectorSpace C++ Library

241

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


2 u = f

Eq. 3158

with u = 0 at x = 1 , and y = 1 . It can be transformed into a Laplace equation with


f
4

u = --- (x2+y2) + v

Eq. 3159

where v is approximated by a subset of algebraic harmonic basis functions


H0 = 1.0,
H1 = (x2-y2).
H2 = (x4 - 6x2y2 + y4),
H3 = (x6-15x4y2+15x2y4-y6),
H4 = (x8 - 28 x6y2 + 70 x4y4 -28 x2y6 + y8),
... etc.,
with v = ci i and v v = (x2+y2) f /4, at the boundaries x = 1 , and y = 1 . Then, v is taken in place of u and
w in Eq. 3157. For this problem q ( n u ) = 0 ; i.e., total flux vanish on the boundaries, the right-handside of Eq. 3157 equals zero. Considering the symmetry of the problem, we only need to compute the boundary
at x = 1, and 0 < y < 1.
1

v
v
----x

dy =
x=1

v
----x
0

dy

Eq. 3160

x=1

Substituting v = ci i into Eq. 3160, we have


1

i
- i
-----
x
0

dy c =
x=1

- v
dy
-----x
x=1

Eq. 3161

Eq. 3161 can be re-written in matrix form as M c = b where


1

M =

i
- i
-----
x
0

dy,

and b =

x=1

- v
dy
-----x x = 1

Eq. 3162

Due to the symmetry of the problem with respect to x and y, only H0, H2 and H4 out of the list of algebraic harmonic functions will be taken. In view of the problem at hand, H0 = 1.0 can not be in i, because the x-derivatives in the matrix M and vector b are both zero. We can remedy this by taking only
1 = H2 = (x4 - 6x2y2 + y4) and 2 = H4 = (x8 - 28 x6y2 + 70 x4y4 -28 x2y6 + y8)

242

Workbook of Applications in VectorSpace C++ Library

Eq. 3163

Variational Methods
v = c1 1 + c2 2 with u = -v + v + c0 where v = (x2+y2) f /4. Without the solution for a constant term, the boundary integral equation is indetermined up to the constant value c0. After we obtain c1 and c2, c0 can be computed
by requiring
1

u dy

( v + c1 1 + c2 2 + c0 ) x = 1 dy

= 0 =

Eq. 3164

considering u = 0 at this boundary. That is


1

c0 = ( v + c1 1 + c 2 2 )

x=1

Eq. 3165

dy

Program Listing 321 implements Eq. 3162 with basis functions Eq. 3163 and integrating constant c0 computed from Eq. 3165. Alternatively we can use transcendental harmonic functions symmetrized with respect to x
and y as
1 = cos(x/2) cosh(y/2) + cos(y/2) cosh(x/2), and
2 = cos(3x/2) cosh(3y/2) + cos(3y/2) cosh(3x/2)
The macro definition __TRANSCENDENTAL, if defined at compile time, turns on the corresponding code
segments.
The first quadrant solution of this problem is shown in Figure 332, which is directly comparable to the solution of the same problem shown in the right-hand side of Figure 323. Transcendental harmonic functions give
almost identical results.

u = -v -0.0453175 H2+0.0013438 H4+0.29469

0.3
3
1

0.2
2

0.8

0.1
.1
0
0

0.6
0.2

0.4

0.4

0.2

0.6
0.8
10

Figure 332 The first quadrant solution of the Poisson equation using the Trefftz method.

Workbook of Applications in VectorSpace C++ Library

243

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

#include "include\vs.h"int main() {


const double f_ = 1.0; const double PI = 3.141592654;
double weight[13] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(weight, 0.0, 1.0, 13);
J d_l(1.0/12.0);
H1 X = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 2, 2, qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 2, 2, qp),
x, y; x &= X[0]; y &= X[1];
((H0)x) = 1.0; d(y) = 0.0;
H0 v_bar = f_/4.0 *(((H0)x).pow(2)+((H0)y).pow(2));
#if defined(__TRANSCENDENTAL)
H1 cosh(const H1& a) { return (exp(a)+exp(-a))/2.0; }
phi[0] = cos(PI/2.0*x)*cosh(PI/2.0*y) + cos(PI/2.0*y)*cosh(PI/2.0*x);
phi[1] = cos(3.0*PI/2.0*x)*cosh(3.0*PI/2.0*y) + cos(3.0*PI/2.0*y)*cosh(3.0*PI/2.0*x);
#else
phi[0] = x.pow(4) - 6.0*x.pow(2)*y.pow(2) + y.pow(4);
phi[1] = x.pow(8) -28.0*x.pow(6)*y.pow(2)+70.0*x.pow(4)*y.pow(4)
-28.0*x.pow(2)*y.pow(6)+y.pow(8);
#endif
H0 dphi_dx = d(phi)(0);
C0 M = dphi_dx % ((H0)phi) | d_l,
b = dphi_dx * v_bar | d_l;
C0 c = b / M;
cout << c << endl;
C0 c_0 = -((- v_bar + ((H0)phi)*c) | d_l);
cout << c_0 << endl;
return 0;
}

extended Bodes integration rule

x evaluated at 1
v = f (x2+y2) /4
1, and 2
1

M =

- i
dy
-----
x
x=1
0

b =

- v
dy
-----x x = 1
0

c0 = ( v + c1 1 + c2 2 )

algebraic: c0 = 0.29469
c= {-0.0453175, 0.0013438}T
transcendental: c0 = 0.496296
c= {-0.10095, 0.00014436}T

Listing 321 Solution of Poisson equation with Trefftz method (project: trefftz_method).

244

Workbook of Applications in VectorSpace C++ Library

x=1

dy

Variational Methods
Boundary Element Method
If we consider the Poisson equation and set f = - 2 u , Eq. 3155 becomes the Greens second identity

( ( 2 w )u ( 2 u ) w ) d

( n w )ud ( n u )w d

Eq. 3166

In the case of heat conduction, we use temperature T in place of u; therefore, we have the heat flow q =
n u = u n , the weighting function w is taken as the fundamental solution (Greens function) T* in the
boundary element method, which satisfies
( x, )
2 T ( x, ) = -------------------k

Eq. 3167

where (x, ) is the Dirac delta function with x as the sampling point, as the point source location, and k is the
conductivity. In two-dimensional case, the solution is
1
T ( x, ) = ---------- ln ( r )
2k

Eq. 3168

where k is the conductivity and r is the distance between x and ; i.e., r ( x, ) = ( x0 0 ) 2 + ( x 1 1 ) 2 . We


have also taken the thickness of the medium as unity for simplicity. The heat flow q according to Fouriers law of
conduction is
1
q = k T = ----------2- [ ( x 0 0 )e 0 + ( x 1 1 )e 1 ]
2r

Eq. 3169

For simplicity, we deal with problems without internal heat source; i.e., f = 0. When f 0 , domain integral is
required. From programming point of view, the advantage of the boundary element method begins to make concession to the finite element method. Substituting Eq. 3168 and Eq. 3169 into Eq. 3166, we have

( x, )
-------------------- T d ( 0 )T d =
k

n q

- T d ( n q )T d
-------------k

Eq. 3170

This can be proved to be


c T() =

( n q )T d ( n q )T d

Eq. 3171

where c = 1 if is inside , c = 0 if is outside , and c = 1/2 if is on a smooth boundary . The boundary integral equation for the boundary element method is obtained by discretizing the boundary to boundary elements
as
Workbook of Applications in VectorSpace C++ Library

245

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


c T( ) =

( n q ) e T ( x, ) d T e ( n q ( x, )) d
e

Eq. 3172

where T and q can be either a variable or a specified boundary condition. For the matrix form representation of
Eq. 3172, we reserve T and q as the unknown and T and q as corresponding boundary conditions, and denote
G ij =

T ( x, i ) d,

and H ij =

( n q ( x, i ) ) d,

ij

with H ij = H ij -----2

Eq. 3173

Therefore the matrix form of Eq. 3172 is

H ij G ij

Tj
qj

Eq. 3174

= H ij Tj + G ij q j

This can be re-written as A x = b. Two singular integrations in Eq. 3174 occur, when the source location is
right on the element under consideration; i.e., all diagonal terms on the left-hand-side. For an element with constant shape function, it can be proved that 1

H ii =

(n q ) d = 0,

and G ii =

2
ln --- + 1
h

T d= --------2k

Eq. 3175

where h is the size of the constant element with one variable node on the middle of the element. After the variables T and q are solved from Eq. 3174. The interior temperature at any location can be recovered using Eq.
3172, by setting c = 1. The interior heat flux can also be recovered by applying Fouriers law of conduction and
Eq. 3172 (c = 1). We have a response gradient boundary integral equation as

T ( x, )
(n q ( x, ))
T ( )
q ( ) = k -------------- = k ( n q ) e ----------------------- d T e ------------------------------------- d

Eq. 3176

where
( xi i )
( x i i )
1
r
T ( x, )
r
----------------------- = ---------- r 1 ------- = ------------------, sin ce ------- = ----------------------2k i
i
r
i
2kr 2

Eq. 3177

and
1. p. 69 in C.A. Brebbia, J.C.F. Telles, and L.C. Wrobel, 1984, Boundary element Techniques: Theory and applications in
engineering, Springer-Verlag, Berlin, Germany.

246

Workbook of Applications in VectorSpace C++ Library

Variational Methods

1
( n q ( x, ) )
r
------------------------------------- = --------------- r 2 ( n e i ) 2r 3 ----- ( ( x ) n )

i
2kr 2

2 ( xi i ) ( ( x ) n )
1
-
= --------------2- n i + ----------------------------------------------------2kr
r2

Eq. 3178

We consider a trivial example which solution is self-evident for checking our implementation of this method.
We investigate conduction of heat on a squre region -1 < x < 1, and -1 < y < 1. The upper and lower boundaries
are insulated from its sorrounding by setting qy = 0, the left boundary has T = 0, and the right boundary has T =
100. Because of the steady state condition 2 T = 0 , the gradient on the x direction is constant. This leads to a
linear temperature distribution and constant heat flux on x direction. On y direction, temperature distribution is
uniform and heat flux is zero. Program Listing 322 to Program Listing 326 implement Eq. 3174 to solve for
the variables T and q on the boundaries, then, use Eq. 3172 and Eq. 3176 to recover the interior temperature
and heat flux. We discritize each side of the square region into eight equal length constant elements. Program
Listing 322 is the main() program of the boundary element method.
#include "include\vs.h"
static const double PI = 3.141592654;
static C0 A(32, 32, (double*)0);
static C0 f(32, (double*)0);
static C0 H(32, 16, A, 0, 0);
static C0 mG(32, 16, A, 0, 16);
double w[9] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0,
64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0},
x[8][2] = {{-1.0, -0.75}, {-0.75, -0.5}, {-0.5, -0.25}, {-0.25, -0.0}, {0.0, 0.25}, {0.25, 0.5},
{0.5, 0.75}, {0.75, 1.0}},
y[8][2] = {{-1.0, -0.75}, {-0.75, -0.5}, {-0.5, -0.25}, {-0.25, -0.0}, {0.0, 0.25}, {0.25, 0.5},
{0.5, 0.75}, {0.75, 1.0}},
zai[8] = {-0.875, -0.625, -0.375, -0.125, 0.125, 0.375, 0.625, 0.875},
eta[8] = {-0.875, -0.625, -0.375, -0.125, 0.125, 0.375, 0.625, 0.875};
void LHS_0_15();
void LHS_16_31();
void RHS();
void T_recovery(const C0&, const C0&, const C0&);
void q_recovery(const C0&, const C0&, const C0&, const C0&);
int main() {
LHS_0_15();
LHS_16_31();
RHS();
C0 Y = f / A,
T_gamma(16, Y, 0), q_gamma(16, Y, 16),
T(8, 8, (double*)0), q_x(8, 8, (double*)0), q_y(8, 8, (double*)0);
cout << T_gamma << endl;
cout << q_gamma << endl;
T_recovery(T_gamma, q_gamma, T);
cout << T << endl;
q_recovery(T_gamma, q_gamma, q_x, q_y);
cout << q_x << endl;
cout << q_y << endl;
return 0;
}

extended Bodes integration rule


element end points coordinates

element variable node coordinates

row 0-15 of A
row 16-31 of A
b
Solve boundary integral equations

interior temperature recovery


interior heat flux recovery

Listing 322 The main program of the boundary element method (project: boundary_element_method).

Workbook of Applications in VectorSpace C++ Library

247

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

void LHS_0_15() {
for(int i = 0; i < 16; i++) H[i][i] = -1.0/2.0;
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
Quadrature qp(w, x[j][0], x[j][1], 9);
J d_l(0.25/8.0);
H0 X(qp),
R_pow_2 = 4+(X-zai[i]).pow(2);
H[i][j+8] = H[i+8][j] = 1.0/(PI*R_pow_2) | d_l;
}
}
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
Quadrature qp(w, y[j][0], y[j][1], 9);
J d_l(0.25/8.0);
H0 Y(qp),
R0 = sqrt(pow(1.0-zai[i], 2)+(Y-1).pow(2)),
R1 = sqrt(pow(1.0+zai[i], 2)+(Y-1).pow(2)),
R2 = sqrt(pow(1.0-zai[i], 2)+(Y+1).pow(2)),
R3 = sqrt(pow(1.0+zai[i], 2)+(Y+1).pow(2));
mG[i][j] = 1.0/(2.0*PI)*log(R0) | d_l;
mG[i][j+8] = 1.0/(2.0*PI)*log(R1) | d_l;
mG[i+8][j] = 1.0/(2.0*PI)*log(R2) | d_l; mG[i+8][j+8] = 1.0/(2.0*PI)*log(R3) | d_l;
}
}
}

Hii (diagonal) is -1/2

H ij =

- d
------r 2

ln ( r )

- d
----------2k

G ij =

Listing 323 Function LHS_0_15() (project: boundary_element_method).


Program Listing 323 implements the first 16 rows of matrix A corresponding to source position i on the 8
upper boundary elements and 8 lower boundary elements. From Eq. 3173 the diagonal elements of Hij are first
assigned -1/2. For this particular case, if source position i is located at any element of the upper boundary, the
integration of Hij for all upper boundary elements (with second index j) become signular and their values are
zero according to Eq. 3175. This is also true for sources position at lower boundary elements, which makes all
lower boundary element integrals zero. For source position i at upper boundary and integral on the lower
boundary elements (with index j), and vice versa, we have

H ij =

(n q ( x, i )) d

( x 1 1 )

d
--------------------2r 2

- d
---------2r 2

- d
------r 2

Eq. 3179

The -Gij terms in the first 16 rows of matrix A corresponding to the 8 upper boundary elements and 8 lower
boundary elements are simply
G ij = T ( x, i ) d =
j

248

ln ( r ( x, i ) )

d
--------------------------2k

Workbook of Applications in VectorSpace C++ Library

Eq. 3180

Variational Methods
void LHS_16_31() {
double mG_diag = 0.125 / PI * (log(0.125)-1.0);
for(int i = 0; i < 16; i++) mG[i+16][i] = mG_diag;
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
Quadrature qp(w, y[j][0], y[j][1], 9);
J d_l(0.25/8.0);
H0 Y(qp);
if(i != j) {
if(i<j) mG[i+16][j] = mG[i+24][j+8] = 1.0/(2.0*PI) * log(Y-eta[i]) | d_l;
else mG[i+16][j] = mG[i+24][j+8] = 1.0/(2.0*PI) * log(eta[i]-Y) | d_l;
}
}
}
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++) {
Quadrature qp(w, y[j][0], y[j][1], 9);
J d_l(0.25/8.0);
H0 Y(qp),
R = sqrt(4+(Y-eta[i]).pow(2));
mG[i+16][j+8] = mG[i+24][j] = 1.0/(2.0*PI) * log(R) | d_l;
}
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++) {
Quadrature qp(w, x[j][0], x[j][1], 9);
J d_l(0.25/8.0);
H0 X(qp),
R0_2 = pow(1-eta[i], 2) +(X-1).pow(2),
R1_2 = pow(1+eta[i], 2) +(X-1).pow(2),
R2_2 = pow(1-eta[i], 2) +(X+1).pow(2),
R3_2 = pow(1+eta[i], 2) +(X+1).pow(2);
H[i+16][j] = (1.0-eta[i])/(2.0*PI*R0_2) | d_l;
H[i+16][j+8] = (1.0+eta[i])/(2.0*PI*R1_2) | d_l;
H[i+24][j] = (1.0-eta[i])/(2.0*PI*R2_2) | d_l;
H[i+24][j+8] = (1.0+eta[i])/(2.0*PI*R3_2) | d_l;
}
}

h
2
G ii = ---------- ln --- + 1
2k h

G ij =

ln ( r )

- d
----------2k

H ij =

( n e 1 ) ( x1 1 )

- d
---------------------------------------2r 2

Listing 324 Function LHS_16_31() (project: boundary_element_method).


Similarly, Program Listing 324 implements the last 16 rows of matrix A corresponding to source position i
on 8 right boundary elements and 8 left boundary elements. Now the singular integration corresponds to diagonals of -Gij terms in the last 16 rows of matrix A. According to Eq. 3175, that is
2
h
G ii = T d = ---------- ln --- + 1
2k h

Eq. 3181

Otherwise, -Gij use the definition in Eq. 3180. For the terms of Hij

H ij =

( n q ( x , i ) ) d

( n e 1 ) ( x1 1 )

- d
---------------------------------------2r 2

Eq. 3182

Workbook of Applications in VectorSpace C++ Library

249

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

void RHS() {
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
Quadrature qp(w, y[j][0], y[j][1], 9);
J d_l(0.25/8.0);
H0 Y(qp),
R0_2 = pow(1-zai[i], 2)+(Y-1).pow(2),
R1_2 = pow(1-zai[i], 2)+(Y+1).pow(2);
f[i] += (-100.0*(1-zai[i]))/(2.0*PI*R0_2) | d_l;
f[i+8] += (-100.0*(1-zai[i]))/(2.0*PI*R1_2) | d_l;
}
}
for(int i = 16; i < 24; i++) f[i] = 100.0 / 2.0;
for(int i = 24; i < 32; i++) {
for(int j = 0; j < 8; j++) {
Quadrature qp(w, y[j][0], y[j][1], 9);
J d_l(0.25/8.0);
H0 Y(qp), R_pow_2 = 4+(Y-eta[i-24]).pow(2);
f[i] += - 100.0 / (PI*R_pow_2) | d_l;
}
}
}

100 ( 1 0 )
- d
b i = --------- -----------------2
r2
j

bi = 100/2

100 1
b i = --------- ---2- d
r
j

Listing 325 Function RHS() (project: boundary_element_method).


where both coordinate x1 and the inner product of surface normal and coordinate basis n e 1 can have the value
of either 1 or -1.
Program Listing 325 implements the right-hand-side vector of Eq. 3174. Since only Tj corresponding to
right boundary elements are not zero (i.e., T16 ~ T23 = 100, all other T = 0 and all q = 0), we only need to consider right-hand-side values of -Hij Tj with index j running from 16 to 23, i.e., 16th to 23rd columns of H. For
source position on upper and lower boundary elements (i = 0~15), we have
( n e0 ) ( x0 0 )
100 ( 1 0 )

- d = --------- ------------------ d
b i = H ij T j = 100 ( n q ( x, i ) ) d = 100 ---------------------------------------2
2
2r
r2
j

Eq. 3183

For source position on left boundary elements, singular integrals occur. Therefore, bi = -c Tj, where c = -1/2;
i.e., bi = 100/2 = 50, for i = 16~23. For source position on right boundary elements (i = 24~31), we have
( n e0 ) ( x0 0 )
100 1

- d = --------- ---- d
b i = H ij T j = 100 (n q ( x, i )) d = 100 --------------------------------------- r2
2r 2
j

Eq. 3184

Program Listing 326 for interior temperature and interior heat flux recovery is a straight forward implementation of Eq. 3172 and Eq. 3176.
The results of this simple problem are trivial. It is suffice to say that close to boundaries the accuracy deteriorates fast, since we have a lot of ln(r), 1/r, 1/r 2 ... etc. in the equations. This phenomenon is known as hypersingularity of the boundary integral equation. These complex functions are very chanlleging for numerical
integration. Special integration rules for these functions are common practice in boundary element method.
250

Workbook of Applications in VectorSpace C++ Library

Variational Methods
void T_recovery(const C0& T_gamma, const C0& q_gamma, const C0& T) {
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++) {
for(int k = 0; k < 8; k++) {
Quadrature qpx(w, x[k][0], x[k][1], 9);
J d_l(0.25/8.0);
H0 X(qpx),
R0_2 = pow((1-eta[i]), 2) + (X-zai[j]).pow(2),
R1_2 = pow((1+eta[i]), 2) + (X-zai[j]).pow(2);
T[i][j] += T_gamma[k] /(2.0*PI)*(1-eta[i])/R0_2 | d_l;
T[i][j] += T_gamma[k+8] /(2.0*PI)*(1+eta[i])/R1_2 | d_l;
Quadrature qpy(w, y[k][0], y[k][1], 9);
H0 Y(qpy),
R2_2 = pow((1-zai[j]), 2) + (Y-eta[i]).pow(2),
R3_2 = pow((zai[j]+1), 2) + (Y-eta[i]).pow(2);
T[i][j] += 100.0 / (2.0*PI)*(1-zai[j])/R2_2 | d_l;
T[i][j] += q_gamma[k] / (2.0*PI)*log(sqrt(R2_2)) | d_l;
T[i][j] += q_gamma[k+8] / (2.0*PI)*log(sqrt(R3_2)) | d_l;
}
}
}
void q_recovery(const C0& T_gamma, const C0& q_gamma,
const C0& q_x, const C0& q_y) {
double nx, ny;
nx = 1.0;
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++) {
for(int k = 0; k < 8; k++) {
Quadrature qpx(w, x[k][0], x[k][1], 9);
J d_l(0.25/8.0);
H0 X(qpx),
R0_2 = pow((1-eta[i]), 2) + (X-zai[j]).pow(2),
R1_2 = pow((1+eta[i]), 2) + (X-zai[j]).pow(2);
ny = 1.0;
q_x[i][j] -= (ny*T_gamma[k] /(2.0*PI*R0_2)*(2.0*(X-zai[j])*(1-eta[i])/R0_2)) | d_l;
q_y[i][j] -= (ny*T_gamma[k] /(2.0*PI*R0_2)*
(2.0*(1-eta[i])*(1-eta[i])/R0_2-1.0)) | d_l;
ny = -1.0;
q_x[i][j] -= (ny*T_gamma[k+8] /(2.0*PI*R1_2)*
(2.0*(X-zai[j])*(-1-eta[i])/R1_2)) | d_l;
q_y[i][j] -= (ny*T_gamma[k+8] /(2.0*PI*R1_2)*
(2.0*(-1-eta[i])*(-1-eta[i])/R1_2-1.0)) | d_l;
Quadrature qpy(w, y[k][0], y[k][1], 9);
H0 Y(qpy),
R2_2 = pow((1-zai[j]), 2) + (Y-eta[i]).pow(2),
R3_2 = pow((zai[j]+1), 2) + (Y-eta[i]).pow(2);
q_x[i][j] -= (nx*100.0 / (2.0*PI*R2_2)*(2.0*(1-zai[j])*(1-zai[j])/R2_2 - 1.0)) | d_l;
q_y[i][j] -= (nx*100.0 / (2.0*PI*R2_2)*(2.0*(Y-eta[i])*(1-zai[j])/R2_2 )) | d_l;
q_x[i][j] += (q_gamma[k] / (2.0*PI*R2_2)*(1-zai[j])) | d_l;
q_y[i][j] += (q_gamma[k] / (2.0*PI*R2_2)*(Y-eta[i])) | d_l;
q_x[i][j] += (q_gamma[k+8] / (2.0*PI*R3_2)*(-1-zai[j])) | d_l;
q_y[i][j] += (q_gamma[k+8] / (2.0*PI*R3_2)*(Y-eta[i])) | d_l;
}
}
}

T() =

( n q ) e T ( x, ) d
e

T e ( n q ( x, ) ) d
e

where
1
q = ----------2- [ ( x 0 0 )e 0 + ( x 1 1 )e 1 ]
2r
1
T ( x, )= ---------- ln ( r )
2k

T ( x, )
q ( ) = k ( n q ) e ----------------------- d

( n q ( x, ) )
+ k T e ------------------------------------- d

where
T ( x, ) ( x i i )
----------------------- = ------------------ i
2kr 2

and
(n q ( x, ))
------------------------------------- =
i
2 ( xi i ) ( ( x ) n )
1
--------------- n i + -----------------------------------------------------
2
2kr
r2

Listing 326 Function T_recovery() and q_recovery() (project: boundary_element_method).


Workbook of Applications in VectorSpace C++ Library

251

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

3.3.4 Transient ProblemsInitial Value Problem


In this section, the weighted residual method (Section 3.3.2) is applied to time domain of (1) heat conduction, and (2) structural dynamics. Heat conduction (a parabolic equation) is of the form
Ca + Ka + f = 0

Eq. 3185

where C is the heat capacitiy matrix, K is the conductivity matrix, and f is heat source vector. The variable a is
the temperature and a is the time derivative of temperature. Structural dynamics (a hyperbolic equation) is of
the form
Ma + Ka + f = 0

Eq. 3186

where M is the consistent mass matrix, K is the stiffness matrix, and f is the force vector. The variable a is the
displacement and the second time derivative of the displacement, a gives the acceleration.

Parabolic Equation
Considering a time interval tn to tn+1, and t = tn+1 - tn. At this time interval, (= t - tn) can be normalized by
t as a referential coordinate = / t, with 0 < < 1. The variable a at time tn and tn+1 is denoted as an and an+1,
respectively. A linear interpolation function, the trapezoidal rule for time integration, is used to approximate a in
the time interval tn to tn+1 as1

a a ( ) = ( 1 )a n + a n + 1 = a n + ( a n + 1 a n ) = a n + ----- ( a n + 1 a n )
t

Eq. 3187

Now, the residual of Eq. 3185 is distributed through-out the time domain (tn, tn+1) by a weighted-residual statement similar to Eq. 3105 as
t

WR d
0

W ( Ca ( ) + Ka ( ) + f ) d

= 0

Eq. 3188

A parameter is defined as

= W d

t W d

Eq. 3189

Eq. 3188 devided by t W d gives


0

1. We follow Chapter 10 in Zienkiewicz and Taylor, 1991, The finite element method, 4th eds. vol. 2, McGraw-Hill Book
Company, UK.

252

Workbook of Applications in VectorSpace C++ Library

Variational Methods
( an + 1 a n )

d
C ( a ( ) ) + K [ a n + ( a n + 1 a n ) ] + [ f n + ( f n + 1 f n ) ] = 0, where a ( ) = a ( ) = ----------------------------t
d

Eq. 3190

Note that similar interpolation of force vector f is taken as that for the variable a. Re-arranging in order to solve
for the unknown an+1, we have
( C + tK )a n + 1 = ( C t ( 1 )K )a n f

Eq. 3191

f = f + ( f
n
n + 1 fn )

Eq. 3192

where

Eq. 3191 is a time recurrence formula with which the solutions of consequtive time steps can be calculated.
From the results of Eq. 3113 and Eq. 3114, we have, in the context of the point-collocation method, the values
of = 0, 1, 0.5 corresponding to the backward difference, forward difference, and central difference, respectively.
Consider an initial value problem1
u 2 u
----- -------- = 0, 0 < x < 1
t x 2

Eq. 3193

u
u ( 0, t ) = 0, ------ ( 1, t ) = 0, and u ( x, 0 ) = 1
x

Eq. 3194

the boundary and initial conditions are

The exact solution to this problem is

u exact ( x, t ) = 2

n=0

e n t sin n x
( 2n + 1 )
-----------------------------, n = -----------------------n
2
2

Eq. 3195

Making (1) a weighted-residual statement, and (2) integration by part on the spatial derivative term of Eq. 3193,
we have the weak form with Bubnov-Galerkin weighting v w = u as
1

v 2 v
0 = v ----- --------2 dx =
t x
0

v v v
v
+ ------ ------ dx v ------
v ---- x
t x x
0

=
0

v v

+ ------ ------ dx
v ----t x x

Eq. 3196

1. p. 323-324 in J.N. Reddy, 1986, Applied functional analysis and variational methods in engineering, McGraw-Hill, Inc.

Workbook of Applications in VectorSpace C++ Library

253

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

This is the equation of the form of Eq. 3185; i.e., Ca + Ka + f = 0 , where f = 0. Two term approximation for v is
v(x, t) = c0(t) 0(x) + c1(t) 1(x)

Eq. 3197

where we take 0(x) = x, and 1(x) = x2. Now the matrices in Eq. 3185 can be identified as
1

0
1

0
1

0
1

0
1

0 0

- --------- dx --------0- --------1- dx
------- x x
x x

0 0 dx 0 1 dx
C =

, and K =

1 0

Eq. 3198
1 1

1 0 dx 1 1 dx

- --------- dx --------- --------- dx


------- x x
x x

The initial condition u(x, 0) = 1, is approximated by a Bubnov-Galerkin weighted-residual statement as


1

v [ v ( x, 0 ) 1 ] dx

= 0 =

[ ( c ( 0 ) ) ] dx

Eq. 3199

or in matrix form,
1

0 0 dx 0 1 dx
0
1

0
1

1 0 dx 1 1 dx
0

0 dx

c0 ( 0 )
=
c1 ( 0 )

0
1

Eq. 3200

1 dx
0

Therefore, the results are c0(0) = 4 and c1(0) = -10/3. This serves as the initial condition in place of Eq. 3200 for
the basis function approximation in Eq. 3197. Although Eq. 3200 is simple enough to be solved by hand, we
can easily implement Eq. 3200 with VectorSpace C++ Library.
Program Listing 327 first implements the approximated initial condition with Eq. 3200, and then, uses the
definitions of C and K in Eq. 3198 to solve for the time recurrence formula provided by Eq. 3191. In this
implementation, the time step t = 0.05, and = 0.5 is used for the central difference method. Note that for the
initial condition approximation the highest order polynomial is the fifth-order. We use Bodes integration rule for
the accuracy of the initial condition approximation. For the time recurrence formula the highest order polynomial for integration is only up to second order, so Simpsons rule will be sufficient.
The results of the computation are shown in Figure 333. A large error occurs at time zero, since the initial
condition is only approximated through Eq. 3199.

254

Workbook of Applications in VectorSpace C++ Library

Variational Methods
#include "include\vs.h"
int main() {
C0 c_t_n(2, (double*)0), c_t_n1(2, (double*)0);
{
double weight[5] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(weight, 0.0, 1.0, 5);
J d_l(1.0/4.0);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 2, 1, qp);
phi[0] = x; phi[1] = x.pow(2);
C0 C = (((H0)phi)%((H0)phi))|d_l,
b = ((H0)phi)|d_l;
c_t_n = b / C;
}
double weight[3] = {1.0/3.0, 4.0/3.0, 1.0/3.0};
Quadrature qp(weight, 0.0, 1.0, 3);
J d_l(1.0/2.0);
H1 x(qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 2, 1, qp);
phi[0] = x; phi[1] = x.pow(2);
C0 C = (((H0)phi)%((H0)phi))|d_l,
K = (d(phi)(0)%d(phi)(0))|d_l;
double theta_ = 0.5, dt_ = 0.05;
C0 LHS = C + theta_ * dt_ * K,
RHS = C - (1.0 - theta_) * dt_ * K;
C0 d_LHS = !LHS;
for(int i = 0; i < 30; i++) {
c_t_n1 = d_LHS*(RHS*c_t_n);
double iptr;
if(modf( ((double)(i+1))/2.0, &iptr)==0) cout << c_t_n1 << endl;
c_t_n = c_t_n1;
}
return 0;
}

0(x) = x, and 1(x) = x2


initial condition approximation
Bodes integration rule

0 0 dx 0 1 dx
0
1

0
1

1 0 dx 1 1 dx
0

0 dx

c0 ( 0 )

c1 ( 0 )

0
1

1 dx
0

c(t=0) = {4, -10/3}T


1

C =

dx
0
1

K =

- ------ dx
----x x
0

( C + tK )a n + 1=( C t ( 1 )K )a n

Listing 327 Parabolic equation (project: parabolic_equation).

Hyperbolic Equation
We consider a more general second order differential equation (hyperbolic-parabolic equation) such as
Ma + Ca + Ka + f = 0

Eq. 3201

where M is the mass matrix, C is the viscous damping, K is the stiffness, and f is the forcing terms. In structural
dynamics, a is the displacement, a is the velocity, and a is the acceleration. When C = 0, Eq. 3201 reduces to
the hyperbolic case. For Eq. 3201, we use a time recurrence formula in which given a n, a n , and an at time tn,
we seek solutions of a n + 1, a n + 1, and an + 1 at time tn+1. Similar to Eq. 3187, we use a linear interpolation function with a natural coordinate = / t, where 0 < < 1, to approximate the acceleration as

Workbook of Applications in VectorSpace C++ Library

255

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

Exact Solution t=0.0

0.8

x = 1.0
0.8

t=0.2

0.6

t=0.4

0.6

x = 1.0

0.4

0.4

t=0.6
t=0.8
t=1.0
t=1.2
t=1.4

0.2

Numerical Solution at x = 0.5 & 1.0

x = 0.5

0.2

0.4

0.6

0.8

0.2

x = 0.5

0.2

0.4

0.6

0.8

1.2

1.4

t
x
Figure 333 The left-hand-side is the exact solution computed from Eq. 3195. The results of
numerical solution on x = 0.5 and 1.0 are shown.

a a ( ) = ( 1 )an + an + 1 = an + ( an + 1 an ) = an + ----- ( an + 1 an )
t

Eq. 3202

For the displacement a and the velocity a , we can approximate them with Taylor series approximation to the
second order of t for an+1 as
t 2
a n + 1 a n + ta n + -------- [ ( 1 2 )an + 2an + 1 ]
2

Eq. 3203

or, to the first order of t for a n + 1 as,


a n + 1 a n + t [ ( 1 )a n + an + 1 ]

Eq. 3204

The two parameters and are choosen independently. Notice that Eq. 3204 is an expression only up to the
first order of t. Therefore, we restrict our choice of = 1/2 to keep the order of accuracy up to O(t2). Two
choices of are popular. For the so-called constant average acceleration = 2 = 1/2, the weighting functions
W() for acceleration terms in Eq. 3203 and Eq. 3204 are the same. In the context of point-collocation the
value 1/2 corresponds to central difference method. This value is also equivalent to collocation with a constant
weighting function throught out the time interval tn to tn+1; i.e., W() = 1, such that from the definition in Eq.
3189, we get
t

= 2 = W d

256

2
t W d = ----- ( t )
2

Workbook of Applications in VectorSpace C++ Library

t
0

1
= --2

Eq. 3205

Variational Methods
Similarly, for the so-called linear acceleration, = 1/2 is to keep the second order accuracy, but now set = 1/6.
That is we use W() = 1 for Eq. 3204, while we take a linear weighting function W() = (1) = (1 / t) for
Eq. 3203, so
t

2 = W d

2
2 3
t W d = ----- ----- -----
2 3 2

1
0

1
= --3

Eq. 3206

Now, we work out the formula for the Newmark method for the hyperbolic-parablic equation. From Eq.
3203, we have
1
t 2
an + 1 = --------- a n + 1 a n ta n -------- ( 1 2 )an
2
t

Eq. 3207

Substituting this into Eq. 3204, we have


t 2

a n + 1 = a n + t ( 1 )an + --------- a n + 1 a n ta n -------- ( 1 2 )an

t
2

Eq. 3208

Since a n, a n , and an at time tn are all given values, the three unknowns a n + 1, a n + 1, and an + 1 at time tn+1 can be
substituted into Eq. 3201 as
Man + 1 + Ca n + 1 + Ka n + 1 + fn + 1 = 0

Eq. 3209

where a n + 1 , and an + 1 are expressed in Eq. 3207 and Eq. 3208, and the only unknown is a n + 1 in Eq. 3209.
Re-arranging Eq. 3209, we have1

Kan + 1 = Rn + 1

Eq. 3210

K = K + a 0 M + a 1 C, and R n + 1 = f n + 1 + ( a 0 a n + a 2 a n + a 3 an )M + ( a 1 a n + a 4 a n + a 5 an )C

Eq. 3211

where,

a n + 1 is solved from Eq. 3210, then, a n + 1 , and an + 1 are calculated from re-arranged Eq. 3207 and Eq. 3208

as
an + 1 = a 0 ( a n + 1 a n ) a 2 a n a 3 an
a
= a + a a + a a
n+1

6 n

7 n+1

Eq. 3212

The so-called Newmark coefficients ai in Eq. 3211 and Eq. 3212 are
1. p. 323 in K Bathe, and E.L. Wilson, 1976, Numerical method in finite element analysis, Prentice-Hall, New Jersey.

Workbook of Applications in VectorSpace C++ Library

257

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects

1
1

t
1
a 0 = -----------2, a 1 = ---------, a 2 = ---------, a 3 = ------ 1, a 4 = --- 1, a 5 = ----- --- 2 , a 6 = t ( 1 ), a 7 = t
t
t
2
2

Eq. 3213

Consider a hyperbolic equation for beam vibration


2 w
4 w
---------- = ---------4-, 0 < x < 1, t > 0
2
x
t

Eq. 3214

where w(x, t) is the deflection of the beam , boundary conditions are


w ( 0, t )
w ( 1, t )
w ( 0, t ) = w ( 1, t ) = -------------------- = -------------------- = 0
x
x

Eq. 3215

and initial conditions are


w ( x, 0 )
t

w(x, 0) = sin(x)-x(1-x), and --------------------- = 0

Eq. 3216

Two approximation basis functions are taken as


0 = 1-cos(2x),

1 = 1-cos(4x)

for w2 = c0(t) 0(x) + c1(t) 1(x), with C = 0 and f = 0 in Eq. 3201, M and K can be identified as
1

M =

( ) dx, and K =
0

d d
d x2 d x2 dx

Eq. 3217

The coefficients for the initial condition in Eq. 3216 is approximated by weighted-residual method
1

W [ w2 ( x, 0 ) sin ( x ) + x ( 1 x ) ] dx

= 0

Eq. 3218

With Bubnov-Galerkin weighting W(x, t) = w2(x, t) = c0(t) 0(x) + c1(t) 1(x) , Eq. 3218 becomes
1

( ) dx
0

c(0) =

[ sin ( x ) x ( 1 x ) ] dx

Eq. 3219

Therefore, the intial condition coefficient vector c(0) can be obtained.


Program Listing 328 implements Newmark method (Eq. 3211 to Eq. 3213) with constant average acceleration = 1/2, = 1/4, and t = 0.01. The initial condition coefficients are approximated by Eq. 3219.
The results of the computation are shown in Figure 334.

258

Workbook of Applications in VectorSpace C++ Library

Variational Methods
#include "include\vs.h"
#define PI 3.141592654
int main()
{
double weight[33] = {14.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0,
28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0,
28.0/45.0, 64.0/45.0, 24.0/45.0, 64.0/45.0, 28.0/45.0, 64.0/45.0,
24.0/45.0, 64.0/45.0, 14.0/45.0};
Quadrature qp(weight, 0.0, 1.0, 33);
J d_l(1.0/32.0);
H2 x((double*)0, qp),
phi = INTEGRABLE_VECTOR_OF_TANGENT_OF_TANGENT_BUNDLE(
"int, int, Quadrature", 2, 1, qp);
phi[0] = 1.0-cos(2.0*PI*x); phi[1] = 1.0-cos(4.0*PI*x);
H0 d2_phi = INTEGRABLE_VECTOR("int, Quadrature", 2, qp);
for(int i = 0; i < 2; i++) d2_phi[i] = dd(phi)(i)[0][0];
C0 mass = (((H0)phi)%((H0)phi))|d_l,
stiff = (d2_phi%d2_phi)|d_l;
double gamma_ = 0.5, beta_ = 0.25, dt_ = 0.01, a[8];
C0 c_old(2, (double*)0), c_new(2, (double*)0), dc_old(2, (double*)0),
dc_new(2, (double*)0), ddc_old(2, (double*)0), ddc_new(2, (double*)0);
a[0] = 1.0/(beta_*pow(dt_,2)); a[1] = gamma_/(beta_*dt_); a[2] = 1.0/(beta_*dt_);
a[3] = 1.0/(2.0*beta_)-1.0; a[4] = gamma_/beta_-1.0; a[5] = dt_/2.0*(gamma_/beta_-2.0);
a[6] = dt_*(1.0-gamma_);
a[7] = gamma_*dt_;
H0 w_0 = sin(PI*((H0)x))-PI*((H0)x)*(1.0-((H0)x));
c_old = ( ( ((H0)phi)*w_0 )|d_l ) / ( ( ((H0)phi)%((H0)phi) )|d_l );
C0 LHS = stiff + a[0]*mass,
d_LHS = !LHS;
for(int i = 0; i < 28; i++) {
C0 RHS = mass * (a[0]*c_old + a[2] * dc_old + a[3] * ddc_old);
c_new = d_LHS*RHS;
double iptr;
if(modf( ((double)(i+1))/2.0, &iptr)==0) cout << "t= " << ((i+1)*dt_) << ", u(0.5) = " <<
(c_new[0]*(1.0-cos(PI))+c_new[1]*(1.0-cos(2.0*PI))) << endl;
ddc_new = a[0]*(c_new - c_old)-a[2]*dc_old-a[3]*ddc_old;
dc_new = dc_old + a[6]*ddc_old + a[7]*ddc_new;
c_old = c_new; dc_old = dc_new; ddc_old = ddc_new;
}
return 0;
}

extended Bodes integration rule

1 = 1-cos 2x, 2 = 1-cos 4x


1

( ) dx

M =

0
1

d d
K = 2 2 dx
dx
dx
0

initial condition approximation


by Eq. 3219

K = K + a0 M

R n + 1 = ( a 0 a n + a 2 a n + a 3 an )M

an + 1 = a 0 ( a n + 1 a n ) a 2 a n a 3 an
a
= a + a a + a a
n+1

6 n

7 n+1

update ( . )n = ( . )n+1

Listing 328 Hyperbolic equation using Newmark method with constant average acceleration (project:
hyperbolic_equation).

Workbook of Applications in VectorSpace C++ Library

259

Chapter

3 Variational Methods Using H0, H1, and H2 Type Objects


t=0.02

0.2

t=0.28
t=0.26

0.2

t=0.04
t=0.24

0.1

0.1

t=0.08

t=0.22

w
w

0.2

-0.1

0.4

0.6
t=0.08
t=0.10

0.8

0.2
-0.1

t=0.14
Figure 334

260

0.6
t=0.20
t=0.18

t=0.12

-0.2

0.4

-0.2

Hperbolic equation using Newmark method.

Workbook of Applications in VectorSpace C++ Library

t=0.16

0.8

You might also like