RELAZIONI, GRUPPI E CAMPI

annuncio pubblicitario
Coefficienti della serie di Fourier
1. Introduzione
1
2. Esempio
1
3. Algoritmo risolutivo
2
4. Due esecuzioni del programma
3
4.1. Funzione dispari
4.2. Funzione oscillante
4
6
5. Codice dell’unità principale
7
6. Codice del modulo
9
1. Introduzione. Data una funzione
1.1)
f : [ L, L]  R
si dimostra che sotto alcune ipotesi di regolarità della stessa, allora la successione di funzioni
trigonometriche
1.2)
a0  
 kx 
 kx  
   a k cos
  bk sin 
 
2 k 1 
 L 
 L 
converge totalmente verso la funzione f in [ L, L] ; i coefficienti in 1.2 si ottengono dalle seguenti
integrazioni
1.3)
ak 
1
 kx 
f  x  cos
dx

L L
 L 
1.4)
bk 
1
 kx 
f  x sin 
dx

L L
 L 
L
L
per k  1,2,3...
2. Esempio. Si consideri la funzione
2.1)
f  x, x  [3,3]
e si vogliano calcolare diciamo i primi 7 coefficienti dello sviluppo 1.2. Si osserva intanto che
essendo la 1.5 una funzione dispari, ed essendo il coseno una funzione pari, segue che anche gli
integrandi delle 1.3 sono funzioni dispari; quindi il valore dei coefficienti 1.3 è nullo. Ci restano
quindi da calcolare i primi 3 coefficienti 1.4, per i quali si ha
1
3
3
3
3
1
1
1  
 x 
 x 
 x  
 x  
b1   x sin  dx    xd cos     x cos     cos dx  
3 3
 3
  
 3
3
 3   3 3  3  

1
3
 6
 3 cos   3 cos    sin    sin      1.9


 
1
1
 2x 
b2   x sin 
dx  
3 3
2
 3 
3

1
 2x 
3 xd cos 3    2
3
3
3


2

x


 2x  
  x cos


cos


dx 


 
3
3



 

3
3

1 
3
sin 2   sin  2    6  0.95
 3 cos2   3 cos 2  
2 
2
2

3


 x cosx 33   cosx dx  


3


1 
1
 2
   3 cos3   3 cos 3   sin 3   sin  3    0.63
3 

 
1
1
 3x 
b3   x sin 
dx  
3 3
3
 3 
3
1
1
 4x 
b4   x sin 
dx  
3 3
3
 3 
3

3
1
3 xd cosx    3
1
 4x 
3 xd cos 3    4
3
3
3


4

x


 4x  
  x cos


cos

dx 



3
3



 

3
3

1 
1
sin 4   sin  4   6  0.47
 3 cos4   3 cos 4  
4 
4
 4
Quindi abbiamo ottenuto lo sviluppo
2.2)
 x 
 2x 
 3x 
 4x 
b1 sin    b2 sin 
  b3 sin 
  b4 sin 

 3
 3 
 3 
 3 
essendo i coefficienti dati da
2.4)
6

b1    1.9

b   6  0.95
 2
2

b  2  0.63
 3 

6
b4 
 0.47
4

3. Algoritmo risolutivo. Il programma in Fortran qui discusso è costituito dai seguenti elementi:
 il programma principale fourier_main il quale si occupa di chiedere all’utente di inserire la
funzione da sviluppare, di utilizzare le subroutine di modulo e di stampare sullo schermo i
coefficienti calcolati;
2
 il modulo fourier_mod il quale contiene una stima del pi greco e le dimensioni degli array,
oltre alle seguenti subroutine:
 coeff_coseno che si occupa di calcolare i coefficienti del coseno;
 coef_seno che si occupa di calcolare i coefficienti del seno;
 diagramma che plotta le funzioni inviate (quella da sviluppare, e quella
sviluppata).
Si precisa che i coefficienti sono calcolati integrando col metodo numerico di Cavalieri_Simpson. Il
diagramma di flusso complessivo del programma è il seguente:
Inizio
L’unità chiamante fourier_main chiede



il semiperiodo
i valori della funzione nei nodi
il numero di coefficienti da calcolare
invoca diagramma per disegnare la
funzione da sviluppare in serie
diagramma
invoca coeff_coseno per calcolare i
coefficienti delle funzioni coseno
coeff_coseno
invoca coeff_seno per calcolare i
coefficienti delle funzioni seno
coeff_seno
calcola lo sviluppo in serie mettendolo in un array in funzione della ascissa
diagramma
invoca diagramma per disegnare lo
sviluppo in serie
scrive sullo schermo i valori dei coefficienti di Fourier calcolati
fine
4. Due esecuzioni del programma. Vediamo ora come si comporta il programma in due diverse
esecuzioni; nel primo caso inserisco la funzione sviluppata nel paragrafo 2, così a poter confrontare
i coefficienti forniti dal programma con quelli calcolati analiticamente, nel secondo caso inserisco
una funzione oscillante con tratti rettilinei.
3
4.1. Funzione dispari. Fornisco al programma i valori della funzione 2.1 e chiedo di calcolare 13
coefficienti, ottenendo i seguenti valori, che riporto direttamente dal Prompt:
I coefficenti del coseno sono
a 0 = 1.9272168E-8
a 1 = -6.548746E-7
a 2 = 7.616324E-7
a 3 = -6.594555E-7
a 4 = 8.252311E-7
a 5 = -5.588875E-7
a 6 = 4.1913088E-7
I coefficenti del seno sono
b 1 = 1.9098659
b 2 = -0.9549813
b 3 = 0.63679826
b 4 = -0.47789773
b 5 = 0.38284233
b 6 = -0.31986767
4
Si può osservare che quelli del coseno, pur essendo la funzione dispari, non sono nulli; ma sono
comunque piccolissimi; questo naturalmente è dovuto alla integrazione numerica; che in genere
fornisce valori non nulli anche per integrali che sono analiticamente pari a zero. Buona invece la
concordanza con i coefficienti del seno calcolati in 2.4.
Il grafico della funzione da sviluppare è anch’esso fornito dal codice ed è riportato sopra. Quello
dello sviluppo in serie di Fourier di 13 funzioni sinusoidali è invece riportato qui sotto.
Si possono notare i raccordi ai due estremi i quali sono legati alla struttura della serie di Fourier, che
perviene alla costruzione di una funzione continua su tutto R, di periodo 2L.
5
4.2. Funzione oscillante. Fornisco al programma i valori di una funzione che oscilli tra -3 e 3,
descrivendo una spezzata. La funzione non è pari, né dispari, dunque si prevedono coefficienti del
coseno e del seno in generale non nulli. Il grafico della funzione da sviluppare è sopra. I coefficienti
di Fourier che ottengo, che prendo direttamente dal Prompt, sono i seguenti
I coefficenti del coseno sono
a 0 = 10.
a 1 = 6.521652E-7
a 2 = -0.0000017741673
a 3 = -0.000003436954
a 4 = 0.000003346504
a 5 = -0.0000026000405
a 6 = 0.000002361434
I coefficenti del seno sono
b 1 = -0.39804778
b 2 = 1.8445204
b 3 = 2.2338054
b 4 = -0.820715
b 5 = 0.51045585
b 6 = -0.34598902
Ed ecco il grafico dello sviluppo in serie di Fourier, di 13 addendi:
6
5. Il codice della unità principale. Riporto lo script del main program.
PROGRAM fourier_main
USE fourier_mod
USE DISLIN
!sezione dichiarativa
IMPLICIT NONE
INTEGER::k
INTEGER::i,j
REAL::L
REAL::ak,bk
REAL::h
INTEGER::m
REAL:: somma
!il numero dei coefficenti del seno
!indici di ciclo
!semiperiodo della funzione
!i coefficienti k-mi
!la distanza fra i nodi
!il numero totale di coefficenti
REAL,DIMENSION(n+1)::x !ascissa
REAL,DIMENSION(n)::f !i valori della funzione in corrispondenza dei nodi
REAL,DIMENSION(0:100)::a !i coefficienti del coseno
REAL,DIMENSION(1:100)::b !i coefficienti del seno
REAL,DIMENSION(p)::x_f !ascissa della funzione sviluppata
REAL,DIMENSION(p)::f_f !funzione sviluppata
CHARACTER(len=28):: titolo
!titolo dei grafici
CHARACTER(len=20):: chiusura
!serve per chiudere il programma
!sezione esecutiva
WRITE(*,*) "La funzione da sviluppare in serie di Fourier"
WRITE(*,*) "si intende definita in [-L,L] con periodo 2L."
WRITE(*,*) " "
WRITE(*,*) "Indica il semiperiodo L della funzione."
WRITE(*,*) " "
READ(*,*) L
h = (2*L)/(n-1) !calcola il passo
x(1)= -L
!valore dell'ascissa del primo nodo
!inizializza la funzione
ciclo_f: DO i=1,n,1
WRITE(*,*) "Inserisci il valore della funzione in", x(i)
READ (*,*) f(i)
x(i+1) = x(i) + h
END DO ciclo_f
titolo = "funzione da sviluppare
"
CALL diagramma (f,n,titolo,L)
!disegna la funzione in [-L,L]
WRITE(*,*) " "
WRITE(*,*) "Indica il numero di coefficienti della serie di Fourier da calcolare."
WRITE(*,*) "Si precisa che e' richiesto un numero dispari."
WRITE(*,*) " "
7
READ(*,*) m
k = (m-1)/2
!inizializza m
!calcola k
!calcolo i coefficienti del coseno
ciclo_cos: DO i=0,k,1
CALL coeff_coseno (i,L,f,ak)
a(i)=ak
END DO ciclo_cos
!calcolo i coefficieinti del seno
ciclo_sen: DO i=1,k,1
CALL coeff_seno (i,L,f,bk)
b(i)=bk
END DO ciclo_sen
!scrive sullo schermo i coefficienti del coseno
WRITE(*,*) " "
WRITE(*,*) "I coefficenti del coseno sono"
ciclo_write_cos: DO i=0,k,1
WRITE(*,*) " "
WRITE(*,*) "a",i,"=",a(i)
WRITE(*,*) " "
END DO ciclo_write_cos
!scrive sullo schermo i coefficienti del seno
WRITE(*,*) " "
WRITE(*,*) "I coefficenti del seno sono"
ciclo_write_sin: DO i=1,k,1
WRITE(*,*) " "
WRITE(*,*) "b",i,"=",b(i)
WRITE(*,*) " "
END DO ciclo_write_sin
!calcola la funzione sviluppata in serie di fourier
x_f(1)=-L
ciclo_fourier: DO i=1,p,1
somma = 0
ciclo_interno: DO j=1,k,1
somma = somma + a(j)*cos(REAL(j)*pi*(x_f(i)/L)) + b(j)*sin(REAL(j)*pi*(x_f(i)/L))
END DO ciclo_interno
f_f(i) = (a(0)/2) + somma
x_f(i+1)= x_f(i)+((2*L)/(p-1))
END DO ciclo_fourier
titolo = "sviluppo in serie di Fourier"
CALL diagramma (f_f,p,titolo,L)
!disegna lo sviluppo di fourier in [-L,L]
!scrive sullo schermo i coefficenti dello sviluppo della funzione in serie di Fourier
WRITE(*,*) " "
WRITE(*,*) "I coefficienti trovati si intendono relativi allo sviluppo:"
WRITE(*,*) " "
8
WRITE(*,*) "f(x)= a0/2 + sommatoria in k (ak*cos(k*pi*x/L) + bk*sin(k*p*x/L)) da 1 a", m
WRITE(*,*) " "
!operazioni di chiusura
WRITE(*,*)"Premi un tasto per chiudere il programma. In questo caso la finestra del prompt"
WRITE(*,*)"si chiudera' e perderai tutti i dati."
READ(*,*) chiusura
STOP
END PROGRAM fourier_main
6. Il codice del modulo. Riporto lo script del modulo.
MODULE fourier_mod
!sezione dichiarativa
IMPLICIT NONE
REAL, PARAMETER:: pi=3.1415927 !una approssimazione del pi greco
INTEGER,PARAMETER::n=41
!il numero di nodi
INTEGER,PARAMETER::p=100
!il numero di punti in cui calcola lo sviluppo
CONTAINS
!-------------------------------------------------------SUBROUTINE coeff_coseno (k,L,f,ak)
!integra la funzione inviata con il metodo di Cavalieri
!(detto anche della parabola)
IMPLICIT NONE
!dichiaro gli argomenti fittizi
REAL,INTENT(IN),DIMENSION (n)::f
INTEGER,INTENT (IN)::k
REAL,INTENT (IN)::L
REAL,INTENT(OUT)::ak
!dichiaro le variabili locali
INTEGER::i !indice del ciclo
REAL::h !passo
REAL, DIMENSION (n):: primitiva
REAL, DIMENSION (n):: integrando
REAL, DIMENSION (n+1):: x
!sezione esecutiva
!calcola la distanza fra i nodi
h = (2.*L)/REAL(n-1)
!calcola la funzione integranda
x(1)=-L
9
ciclo_integranda: DO i=1,n,1
integrando(i)=f(i)*COS((REAL(k)/L)*pi*x(i))
x(i+1)=x(i)+h
END DO ciclo_integranda
primitiva(1)= 0 !inizializza il primo valore
!calcolo la primitiva (elementi dispari dell'array)
ciclo_integra: DO i=1,n-2,2
primitiva(i+2) = primitiva(i) + ( (integrando(i+2) + (integrando(i+1)*4) + integrando(i))*(h/3.) )
END DO ciclo_integra
!calcolo il coefficiente ak
ak = primitiva(n)/L
RETURN
END SUBROUTINE coeff_coseno
!-------------------------------------------------------SUBROUTINE coeff_seno (k,L,f,bk)
!integra la funzione inviata con il metodo di Cavalieri
!(detto anche della parabola)
IMPLICIT NONE
!dichiaro gli argomenti fittizi
REAL,INTENT(IN),DIMENSION (n)::f
INTEGER,INTENT (IN)::k
REAL,INTENT (IN)::L
REAL,INTENT(OUT)::bk
!dichiaro le variabili locali
INTEGER::i !indice del ciclo
REAL::h !passo
REAL, DIMENSION (n):: primitiva
REAL, DIMENSION (n):: integrando
REAL, DIMENSION (n):: x
!sezione esecutiva
!calcola la distanza fra i nodi
h = 2*L/(n-1)
!calcola la funzione integranda
x(1)=-L
ciclo_ascissa: DO i=1,n-1,1
x(i+1)=x(i)+h
10
END DO ciclo_ascissa
ciclo_integranda: DO i=1,n,1
integrando(i)=f(i)*SIN((REAL(k)/L)*pi*x(i))
END DO ciclo_integranda
primitiva(1)= 0 !inizializza il primo valore
!calcolo la primitiva (elementi dispari dell'array)
ciclo_integra: DO i=1,n-2,2
primitiva(i+2) = primitiva(i) + ( (integrando(i+2) + (integrando(i+1)*4) + integrando(i))*(h/3.) )
END DO ciclo_integra
!calcolo il coefficiente bk
bk = primitiva(n)/L
RETURN
END SUBROUTINE coeff_seno
!------------------------------------------------------SUBROUTINE diagramma (f,int,titolo,L)
!traccia il diagramma della f
IMPLICIT NONE
!dichiaro gli argomenti fittizi
REAL,INTENT(IN),DIMENSION (int)::f !da plottare
INTEGER, INTENT(IN)::int
CHARACTER(len=28), INTENT(IN)::titolo
REAL,INTENT(IN)::L
!dichiaro le variabili locali
INTEGER::j,i !indici di ciclo
REAL ::h !passo
REAL ::max !valore massimo della funzione
REAL ::min !valore minimo della funzione
REAL, DIMENSION (int):: x !contiene i valori delle ascisse
!sezione esecutiva
h=2*L/(int-1)
!inizializzo l'array delle ascisse
x(1)=-L
ciclo_ascisse: DO i=2,int,1
x(i)=x(i-1)+h
11
END DO ciclo_ascisse
!inizializzo l'array della funzione da plottare
CALL METAFL ('bmp') !indico il formato dell'output
CALL SCRMOD ('revers') !scritta nera su fondo bianco
CALL DISINI
CALL TEXMOD ('ON') !chiedo di poter scrivere le formule in maniera grafica
CALL PAGERA !traccio un bordo per il piano xy
CALL DUPLX !font a doppio spessore
CALL AXSPOS (450,1800) !coordinate angolo basso sinistra
CALL AXSLEN (2200,1500)!lunghezza dei due assi in pixel
CALL NAME ('x','x') !nome delle ascisse
CALL NAME ('y','y') !nome delle ordinate
CALL TITLIN (titolo,1) !prima riga del titolo
max=MAXVAL(f) !il massimo della funzione
min=MINVAL(f) !il minimo valore della funzione
CALL GRAF (-L,L,-L,5*h,min,max,min,max/5)
CALL TITLE !stampa il titolo di cui sopra
CALL CURVE (x,f,int) !plotto la funzione
CALL DASH !tratteggio per gli assi coordinati
CALL XAXGIT !traccio la retta y=0
CALL YAxGIT !traccio la retta x=0
CALL DISFIN
RETURN
END SUBROUTINE diagramma
!-------------------------------------------------------END MODULE fourier_mod
12
Scarica