You are on page 1of 5

SOLUTION DU TP1

Master Ingénierie Mathématique


Université de Savoie
R. Hassani

On donne ici une version du code en langage Scilab et pour comparaison la version à l’aide de FreeFem++. On
propose, sous forme d’exercices, quelques adaptations possibles.

1 Code Scilab
// Premier programme d’Elements Finis (BBcamef)
//
// Resolution du probleme de Dirichlet :
// -Delta u = f dans Omega
// u = g sur Gamma
// avec Omega = ]0,1[x]0,1[, Gamma = la frontiere de [0,1]^2,
// u la fonction numerique cherchee et f et g deux fonctions quelconques.
//
// Les elements utilises sont des triangles a trois noeuds (elements P1).

clear

// On charge toutes les fonctions :


exec maillage.sce ;
exec rigidel.sce ;
exec assemblage.sce ;
exec dirichlet.sce ;
exec user func.sce ;

// Ouverture d’une boite de dialogue pour saisir les donnees


// Celles-ci sont :
// n = le nbr de noeuds dans [0,1]
// (le nbr de noeuds total est n^2)
// fuser = le second membre (chaine de caracteres)
// guser = le second membre de bord (chaine de caracteres)
//
message = ["n : " ;"f : " ;"g : "] ;
defaut = ["21" ;"2*(2*%pi)^2*sin(2*%pi*x)*cos(2*%pi*y)" ;...
"sin(2*%pi*x)*cos(2*%pi*y)"]
[ok,n,fuser,guser] = getvalue("BBcamef",message,...
list("vec",1,"str",-1,"str",-1),defaut)

// Creation du maillage
[coord,lnods,ldiri,npoin,nelem,ndiri] = maillage(n) ;

// Formation de la matrice et du second membre


A = sparse(zeros(npoin,npoin)) ; F = zeros(npoin,1) ;

for e = 1 :nelem
[Ae,Fe] = rigidel(lnods( :,e),coord,fuser) ;
[A,F] = assemblage(A,F,Ae,Fe,lnods( :,e)) ;
end

// Prise en compte des conditions aux limites (penalisation)


[A,F] = dirichlet(A,F,coord,ldiri,guser) ;

1
2

// Factorisation et resolution
[h,rk] = lufact(A) ; U = lusolve(h,F) ; ludel(h) ;

// Sortie graphique
figure(2) ; clf ;
x = coord(1,1 :n) ; ip = 0 ;
for i=1 :n
for j=1 :n
ip = ip + 1 ;
u(i,j) = U(ip) ;
end
end
plot3d(x,x,u,alpha=88,theta=40) ;

// Fin du programme

//
//**********************************************************************
//
function [coord,lnods,ldiri,npoin,nelem,ndiri] = maillage(n)

// Generation d’un maillage regulier du carre unite par des triangles


//
// n : nbr de points selon x et y
//
// coord : tableau contenant les coordonnees
// lnods : table de connectivite
// ldiri : liste des noeuds du bord
// npoin : nbr de noeuds
// nelem : nbr d’elements
// ndiri : nbr de noeuds sur le contour
//

h = 1 / (n-1) ; npoin = n^2 ; nelem = 2*(n-1)^2 ;


coord = zeros(2,npoin) ; lnods = zeros(3,nelem) ;

// Coordonnees et connectivites :
e = 0; p = 0;
x = 0 :h :1 ;
for j = 1 :n
for i = 1 :n
p = p + 1 ; coord(1,p) = x(i) ; coord(2,p) = x(j) ;
if i ∼= n & j ∼= n
p1 = p ; p2 = p1 + 1 ; p3 = p1 + n ; p4 = p2 + n ;
e = e + 1 ; lnods(1,e) = p1 ; lnods(2,e) = p2 ; lnods(3,e) = p3 ;
e = e + 1 ; lnods(1,e) = p4 ; lnods(2,e) = p3 ; lnods(3,e) = p2 ;
end
end
end

// Liste des noeuds de la frontiere :


ldiri = 1:n ; // bas
ldiri = [ldiri,n*(2:n-1)] ; // droite
ldiri = [ldiri,(n^2):-1:(n^2-n+1)] ; // haut
ldiri = [ldiri,n*(n-1:-1:2)-n+1] ; // gauche
ndiri = length(ldiri) ; // nbr total de noeuds de Dirichlet

// Dessin du maillage :
figure(1) ; clf ;
x=[] ; y=[] ;
for e = 1 :nelem
xe = coord(1,lnods( :,e)) ; ye = coord(2,lnods( :,e)) ;
x = [x,[xe,xe(1)]’] ; y = [y,[ye,ye(1)]’] ;
end
plot2d(0,0,rect=[0,0,1,1]) ; xpolys(x,y) ;

endfunction

//
//**********************************************************************
//
function [Ae,Fe] = rigidel(lnods,coord,fuser)
3

// Calcul de la matrice de rigidite elementaire et du


// vecteur elementaire pour un element P1
//
// Les coefficients de la matice elementaire :
//
// Ae ij = integrale (gradN i . gradN j)
//
// sont simples a calculer puisque les fonctions d’interpolation N i
// (i = 1, 2, 3) sont affines sur l’element (gradN i est constant) :
//
// Ae ij = s * gradN i . gradN j
//
// s etant l’aire du triangle
//
// Les composantes du vecteur elementaire :
//
// Fe i = integrale (N i * f)
//
// peuvent etre calculees de differentes facons suivant la fonction f
// (integration exacte, quadratures de Gauss ou autres ..). En particulier :
//
// * Si f est supposee constante sur l’element :
// fe i = (s / 3) * f
//
// * Si f ne l’est pas on peut toujours l’approcher par :
// fe i = (s / 3) * fm
// ou fm est soit la valeur au centre du triangle soit la valeur
// moyenne des 3 valeurs aux sommets : fm = (f(i) + f(j) + f(k))/3
// Dans ce dernier cas, la formule est d’ordre h.
//
// * Si f est affine sur l’element on peut aussi utiliser la formule :
// fe i = (s / 12) * (2*f(i) + f(j) + f(k))
// qui est exacte. Si f n’est pas affine on obtient une approximation
// d’ordre h^2.
//
// en entree :
// - coord : coordonnees des noeuds
// - lnods : table de connectivite de l’element
// - fuser : le nom d’une fonction (chaine de caractere)
//
// en sortie :
// - Ae : matrice de rigidite elementaire
// - Fe : vecteur elementaire

Ae = zeros(3,3) ; Fe = zeros(3,1) ;

// Coordonnees des noeuds de l’element et vecteurs aretes :


x = [coord(1,lnods( :)) ; coord(2,lnods( :))] ;
v( :,1) = [x(1,3) - x(1,2) ; x(2,3) - x(2,2)] ; // vecteur arete oppose au noeud 1
v( :,2) = [x(1,1) - x(1,3) ; x(2,1) - x(2,3)] ; // vecteur arete oppose au noeud 2
v( :,3) = [x(1,2) - x(1,1) ; x(2,2) - x(2,1)] ; // vecteur arete oppose au noeud 3

// Aire de l’element :
s = 0.5*(v(2,1)*v(1,3) - v(1,1)*v(2,3)) ;

if s <= 0
message = ["Erreur dans rigidel : element a surface negative ou nulle" ;" " ;
"Coordonnees des 3 sommets de l’’element :" ;
string(x( :,1)) ;string(x( :,2)) ;string(x( :,3))] ;
messagebox(message, "Error", "error")
end

// Calcul de la matrice elementaire :


Ae = 0.25 * v’*v / s ;

// Calcul des composantes du vecteur elementaire


c = s / 12 ; F = [f(x( :,1),fuser) ;f(x( :,2),fuser) ;f(x( :,3),fuser)] ;
Fe = c*(sum(F)*ones(3,1)+F) ;

endfunction
4

//
//**********************************************************************
//
function [A,F] = assemblage(A,F,Ae,Fe,lnods)

// 1) Assemblage de la matrice de rigidite elementaire, Ae,


// dans la matrice de rigidite globale, A :
//
// A(ip,jp) <-- A(ip,jp) + Ae(i,j)
//
// avec ip = lnods(i) et jp = lnods(j)
//
// lnods contenant les numeros des noeuds de l’element considere
//
// 2) Assemblage du vecteur elementaire, Fe, dans le vecteur
// second membre globale, F :
//
// F(ip) <-- F(ip) + Fe(i)
//
//

A(lnods,lnods) = A(lnods,lnods) + Ae ;
F(lnods) = F(lnods) + Fe ;

endfunction

//
//**********************************************************************
//
function [A,F] = dirichlet(A,F,coord,ldiri,guser)

// Prise en compte des conditions de Dirichlet u = g sur Gamma.


// La liste des no. des noeuds formant Gamma est donnee par ldiri.
//
// Methode du "terme diagonale dominant" (penalisation) :
//
// pour un noeud ip de Gamma on modifie :
// - le coefficient diagonal correspondant de la matrice de rigidite :
// A(ip,ip) <-- A(ip,ip) + C
// - la composante correspondante du second membre :
// F(ip) <-- C * g(x(ip),y(ip))
//
// ou C est une constante "tres grande"
//

C = max(max(A))*1e10 ;
for i = 1:length(ldiri)
ip = ldiri(i) ;
A(ip,ip) = A(ip,ip) + C ;
F(ip) = C*g([coord(1,ip) ;coord(2,ip)],guser) ;
end

endfunction

//
//**********************************************************************
//
function val = f(xy,fuser)
// Second membre du probleme de Poisson -Delta u = f
x = xy(1) ; y = xy(2) ; val = eval(fuser) ;
endfunction

//
//**********************************************************************
//
function val = g(xy,guser)
// Valeur de l’inconnue sur le bord
x = xy(1) ; y = xy(2) ; val = eval(guser) ;
endfunction
5

2 Code FreeFem++
// Definition du maillage :

mesh Th=square(20,20) ; // maillage de Omega (le carre unite)

// Espace elements finis :

fespace Vh(Th,P1) ; // approximation P1

// Declaration des variables :

Vh u,v ; // u et v sont donc Vh

// Les fonctions f et g :

func f = 2*pi)^2*sin(2*pi*x)*cos(2*pi*y) ;
func g = sin(2*pi*x)*cos(2*pi*y) ;

// Definition du probleme variationnel a resoudre :

problem Poisson (u,v) =


int2d(Th) (dx(u)*dx(v) + dy(u)*dy(v))
- int2d(Th) (f*v)
+ on (1,2,3,4, u=g) ;

// Resolution du probleme :

Poisson ;

// Affichage :

plot (u,wait=true) ;

Exemples
Ci-dessous la solution obtenue pour f (x, y) = 1 et g(x, y) = 0 puis pour f (x, y) = 2a2 sin ax cos ay et g(x, y) =
sin ax cos ay avec a = 2π.