FreeFEM Documentation on GitHub

stars - forks

Eigen value problems

This section depends on your installation of FreeFEM; you need to have compiled ARPACK. This tool is available in FreeFEM if the word eigenvalue appears in line Load:, like:

1-- FreeFem++ v*.** (date *** *** ** **:**:** CET ****)
2 file : ***.edp
3 Load: lg_fem lg_mesh eigenvalue

This tool is based on arpack++, the object-oriented version of ARPACK eigenvalue package [LEHOUCQ1998].

The function EigenValue computes the generalized eigenvalue of \(A u = \lambda B u\). The Shift-invert method is used by default, with sigma =\(\sigma\) the shift of the method.

The matrix \(OP\) is defined with \(A - \sigma B\).

The return value is the number of converged eigenvalues (can be greater than the number of requested eigenvalues nev=)

1int k = EigenValue(OP, B, nev=Nev, sigma=Sigma);

where the matrix \(OP= A - \sigma B\) with a solver and boundary condition, and the matrix \(B\).

There is also a functional interface:

1int k = EigenValue(n, FOP1, FB, nev=Nev, sigma=Sigma);

where \(n\) is the size of the problem, and the operators are now defined through functions, defining respectively the matrix product of \(OP^{-1}\) and \(B\), as in

1int n = OP1.n;
2func real[int] FOP1(real[int] & u){ real[int] Au = OP^-1*u; return Au; }
3func real[int] FB(real[int] & u){ real[int] Au = B*u; return Au; }

If you want finer control over the method employed in ARPACK, you can specify which mode ARPACK will work with (mode= , see ARPACK documentation [LEHOUCQ1998]). The operators necessary for the chosen mode can be passed through the optional parameters A=, A1=, B=, B1=, (see below).

You can also specify which subset of eigenvalues you want to compute (which=). The default value is which="LM", for eigenvalues with largest magnitude. "SM" is for smallest magnitude, "LA" for largest algebraic value, "SA" for smallest algebraic value, and "BE" for both ends of the spectrum.

Remark: For complex problems, you need to use the keyword complexEigenValue instead of EigenValue when passing operators through functions.


Boundary condition and Eigenvalue Problems

The locking (Dirichlet) boundary condition is make with exact penalization so we put 1e30=tgv on the diagonal term of the locked degree of freedom (see Finite element chapter). So take Dirichlet boundary condition just on \(A\) and not on \(B\) because we solve \(w=OP^{-1}*B*v\).

If you put locking (Dirichlet) boundary condition on \(B\) matrix (with key work on) you get small spurious modes \((10^{-30})\), due to boundary condition, but if you forget the locking boundary condition on \(B\) matrix (no keywork on) you get huge spurious \((10^{30})\) modes associated to these boundary conditons. We compute only small mode, so we get the good one in this case.


Laplace eigenvalue

In the first example, we compute the eigenvalues and the eigenvectors of the Dirichlet problem on square \(\Omega=]0,\pi[^2\).

The problem is to find: \(\lambda\), and \(\nabla u_{\lambda}\) in \(\mathbb{R}{\times} H^1_0(\Omega)\)

\[\int_\Omega \nabla u_{\lambda} \nabla v = \lambda \int_\Omega u v \quad \forall v \in H^1_0(\Omega)\]

The exact eigenvalues are \(\lambda_{n,m} =(n^2+m^2), (n,m)\in {\mathbb{N}_*}^2\) with the associated eigenvectors are \(u_{{m,n}}=\sin(nx)*\sin(my)\).

We use the generalized inverse shift mode of the arpack++ library, to find 20 eigenvalues and eigenvectors close to the shift value \(\sigma=20\).

 1// Parameters
 3real sigma = 20; //value of the shift
 4int nev = 20; //number of computed eigen value close to sigma
 6// Mesh
 7mesh Th = square(20, 20, [pi*x, pi*y]);
 9// Fespace
10fespace Vh(Th, P2);
11Vh u1, u2;
13// Problem
14// OP = A - sigma B ; // the shifted matrix
15varf op (u1, u2)
16    = int2d(Th)(
17          dx(u1)*dx(u2)
18        + dy(u1)*dy(u2)
19        - sigma* u1*u2
20    )
21    + on(1, 2, 3, 4, u1=0)
22    ;
24varf b ([u1], [u2]) = int2d(Th)(u1*u2); //no boundary condition
26matrix OP = op(Vh, Vh, solver=Crout, factorize=1); //crout solver because the matrix in not positive
27matrix B = b(Vh, Vh, solver=CG, eps=1e-20);
29// important remark:
30// the boundary condition is make with exact penalization:
31// we put 1e30=tgv on the diagonal term of the lock degree of freedom.
32// So take Dirichlet boundary condition just on $a$ variational form
33// and not on $b$ variational form.
34// because we solve $ w=OP^-1*B*v $
36// Solve
37real[int] ev(nev); //to store the nev eigenvalue
38Vh[int] eV(nev); //to store the nev eigenvector
40int k = EigenValue(OP, B, sym=true, sigma=sigma, value=ev, vector=eV,
41    tol=1e-10, maxit=0, ncv=0);
43// Display & Plot
44for (int i = 0; i < k; i++){
45    u1 = eV[i];
46    real gg = int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1));
47    real mm = int2d(Th)(u1*u1) ;
48    cout << "lambda[" << i << "] = " << ev[i] << ", err= " << int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1) - (ev[i])*u1*u1) << endl;
49    plot(eV[i], cmm="Eigen Vector "+i+" value ="+ev[i], wait=true, value=true);

The output of this example is:

 1lambda[0] = 5.0002, err= -1.46519e-11
 2lambda[1] = 8.00074, err= -4.05158e-11
 3lambda[2] = 10.0011, err= 2.84925e-12
 4lambda[3] = 10.0011, err= -7.25456e-12
 5lambda[4] = 13.002, err= -1.74257e-10
 6lambda[5] = 13.0039, err= 1.22554e-11
 7lambda[6] = 17.0046, err= -1.06274e-11
 8lambda[7] = 17.0048, err= 1.03883e-10
 9lambda[8] = 18.0083, err= -4.05497e-11
10lambda[9] = 20.0096, err= -2.21678e-13
11lambda[10] = 20.0096, err= -4.16212e-14
12lambda[11] = 25.014, err= -7.42931e-10
13lambda[12] = 25.0283, err= 6.77444e-10
14lambda[13] = 26.0159, err= 3.19864e-11
15lambda[14] = 26.0159, err= -4.9652e-12
16lambda[15] = 29.0258, err= -9.99573e-11
17lambda[16] = 29.0273, err= 1.38242e-10
18lambda[17] = 32.0449, err= 1.2522e-10
19lambda[18] = 34.049, err= 3.40213e-11
20lambda[19] = 34.0492, err= 2.41751e-10

Fig. 157 Isovalue of 11th eigenvector \(u_{4,3}-u_{3,4}\)


Fig. 158 Isovalue of 12th eigenvector \(u_{4,3}+u_{3,4}\)

Table of content