Variational Inequality
We present, a classical example of variational inequality.
Let us denote \(\mathcal{C} = \{ u\in H^1_0(\Omega), u \le g \}\)
The problem is:
where \(f\) and \(g\) are given function.
The solution is a projection on the convex \(\mathcal{C}\) of \(f^\star\) for the scalar product \(((v,w)) = \int_\Omega \nabla v . \nabla w\) of \(H^1_0(\Omega)\) where \(f^\star\) is solution of:
The projection on a convex satisfy clearly \(\forall v \in \mathcal{C}, \quad (( u -v , u - \tilde{f} )) \leq 0\), and after expanding, we get the classical inequality:
We can also rewrite the problem as a saddle point problem:
Find \(\lambda, u\) such that:
where \(((u-g)^+ = max(0,u-g)\).
This saddle point problem is equivalent to find \(u, \lambda\) such that:
The primal-dual active set algorithm to solve the previous problem is:
k=0, and choose \(\lambda_0\) belong \(H^{-1}(\Omega)\)
Loop on \(k = 0, .....\)
set \(\mathcal{I}_{k} = \{ x \in \Omega / \lambda_{k} + c * ( u_{k+1} - g) \leq 0 \}\)
\(V_{g,k+1} = \{ v\in H^1_0(\Omega) / v = g\) on \({I}_{k} \}\),
\(V_{0,k+1} = \{ v\in H^1_0(\Omega) / v = 0\) on \({I}_{k} \}\),
Find \(u_{k+1} \in V_{g,k+1}\) and \(\lambda_{k+1} \in H^{-1}(\Omega)\) such that
\[\left\{\begin{array}{cc} \displaystyle \int_\Omega \nabla u_{k+1}. \nabla v_{k+1} \,d\omega = \int_\Omega f v_{k+1} , &\forall v_{k+1} \in V_{0,k+1} \cr \displaystyle <\lambda_{k+1},v> = \int_\Omega \nabla u_{k+1}. \nabla v - f v \,d\omega & \end{array}\right.\]where \(<,>\) is the duality bracket between \(H^{1}_0(\Omega)\) and \(H^{-1}(\Omega)\), and \(c\) is a penalty constant (large enough).
You can find all the mathematics about this algorithm in [ITO2003] [HINTERMULLER2002].
Now how to do that in FreeFEM? The full example is:
Tip
Variational inequality
1load "medit"
2
3// Parameters
4real eps = 1e-5;
5real c = 1000; //penalty parameter of the algoritm
6real tgv = 1e30; //a huge value for exact penalization
7func f = 1; //right hand side function
8func fd = 0; //Dirichlet boundary condition function
9
10// Mesh
11mesh Th = square(20, 20);
12
13// Fespace
14fespace Vh(Th, P1);
15int n = Vh.ndof; //number of degree of freedom
16Vh uh, uhp; //u^n+1 and u^n
17Vh Ik; //to define the set where the containt is reached.
18Vh g = 0.05; //discret function g
19Vh lambda = 0;
20
21// Problem
22varf a (uh, vh)
23 = int2d(Th)(
24 dx(uh)*dx(vh)
25 + dy(uh)*dy(vh)
26 )
27 - int2d(Th)(
28 f*vh
29 )
30 + on(1, 2, 3, 4, uh=fd)
31 ;
32
33//the mass Matrix construction
34varf vM (uh, vh) = int2d(Th)(uh*vh);
35
36//two versions of the matrix of the problem
37matrix A = a(Vh, Vh, tgv=tgv, solver=CG); //one changing
38matrix AA = a(Vh, Vh, solver=CG); //one for computing residual
39
40matrix M = vM(Vh, Vh); //to do a fast computing of L^2 norm : sqrt(u'*(w=M*u))
41
42real[int] Aiin(n);
43real[int] Aii = A.diag; //get the diagonal of the matrix
44real[int] rhs = a(0, Vh, tgv=tgv);
45
46// Initialization
47Ik = 0;
48uhp = -tgv;
49
50// Loop
51for(int iter = 0; iter < 100; ++iter){
52 // Update
53 real[int] b = rhs; //get a copy of the Right hand side
54 real[int] Ak(n); //the complementary of Ik ( !Ik = (Ik-1))
55 Ak = 1.; Ak -= Ik[];
56 //adding new locking condition on b and on the diagonal if (Ik ==1 )
57 b = Ik[] .* g[]; b *= tgv; b -= Ak .* rhs;
58 Aiin = Ik[] * tgv; Aiin += Ak .* Aii; //set Aii= tgv i in Ik
59 A.diag = Aiin; //set the matrix diagonal
60 set(A, solver=CG); //important to change preconditioning for solving
61
62 // Solve
63 uh[] = A^-1* b; //solve the problem with more locking condition
64
65 // Residual
66 lambda[] = AA * uh[]; //compute the residual (fast with matrix)
67 lambda[] += rhs; //remark rhs = -\int f v
68
69 Ik = (lambda + c*( g- uh)) < 0.; //the new locking value
70
71 // Plot
72 plot(Ik, wait=true, cmm=" lock set ", value=true, fill=true);
73 plot(uh, wait=true, cmm="uh");
74
75 // Error
76 //trick to compute L^2 norm of the variation (fast method)
77 real[int] diff(n), Mdiff(n);
78 diff = uh[] - uhp[];
79 Mdiff = M*diff;
80 real err = sqrt(Mdiff'*diff);
81 cout << "|| u_{k=1} - u_{k} ||_2 = " << err << endl;
82
83 // Stop test
84 if(err < eps) break;
85
86 // Update
87 uhp[] = uh[];
88}
89
90// Plot
91medit("uh", Th, uh);
Note
As you can see on this example, some vector, or matrix operator are not implemented so a way is to skip the expression and we use operator +=
, -=
to merge the result.