SOLUTION DU TP1 1 Code Scilab

Transcription

SOLUTION DU TP1 1 Code Scilab
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) =
if i ∼= n & j ∼= n
p1 = p ; p2 = p1 + 1 ; p3 = p1 + n ; p4 =
e = e + 1 ; lnods(1,e) = p1 ; lnods(2,e)
e = e + 1 ; lnods(1,e) = p4 ; lnods(2,e)
end
end
end
x(j) ;
p2 + n ;
= p2 ; lnods(3,e) = p3 ;
= p3 ; lnods(3,e) = p2 ;
// 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
v( :,2) = [x(1,1) - x(1,3) ; x(2,1) - x(2,3)] ; // vecteur
v( :,3) = [x(1,2) - x(1,1) ; x(2,2) - x(2,1)] ; // vecteur
:
arete oppose au noeud 1
arete oppose au noeud 2
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π.