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π.