8. Razvejitve
Iz Računalniška orodja v fiziki 2008 - 2009
m (Zaščita strani "8. Razvejitve" ([edit=sysop] (indefinite) [move=sysop] (indefinite))) |
|||
Vrstica 1: | Vrstica 1: | ||
- | Računalnik je prislovično hiter, vesten in neumoren delavec, le bister ni kaj dosti. Stori natanko samo tisto, kar smo mu v programu naročili. Da se izognemo naročanju vedno enakih korakov, imajo programski jeziki ukaze, ki omogočajo ponavljanja – zanke. Skoraj v vsaki nalogi doslej smo uporabili tako zanko (for i:= 1 to n do). | + | Računalnik je prislovično hiter, vesten in neumoren delavec, le bister ni kaj dosti. Stori natanko samo tisto, kar smo mu v programu naročili. Da se izognemo naročanju vedno enakih korakov, imajo programski jeziki ukaze, ki omogočajo ponavljanja – zanke. Skoraj v vsaki nalogi doslej smo uporabili tako zanko (<tt>for i:= 1 to n do</tt>). |
- | Gibkost programiranja pa zagotavljajo predvsem razvejitveni ukazi, ko je nadaljnji potek računanja odvisen od izpolnitve kontrolnega pogoja (if '''pogoj''' then do ... else do'' ...''). Posebna vrsta zelo gibkih razvejitev so klici podprogramov in funkcij. S temi orodji bomo skicirali zgradbo programa za risanje dvodimenzionalnih grafov, t. j. upodabljanje funkcij z(x,y). | + | Gibkost programiranja pa zagotavljajo predvsem razvejitveni ukazi, ko je nadaljnji potek računanja odvisen od izpolnitve kontrolnega pogoja (<tt>if '''pogoj''' then do ... else do'' ...''</tt>). Posebna vrsta zelo gibkih razvejitev so klici podprogramov in funkcij. S temi orodji bomo skicirali zgradbo programa za risanje dvodimenzionalnih grafov, t. j. upodabljanje funkcij <math>z(x,y)</math>. |
- | + | Naj bo funkcija podana s tabelo <tt>z[i,j]</tt>, <tt>i = 1, ..., nx</tt>, <tt>j = 1, ..., ny</tt>, pri čemer sta koordinati točke <math>(i,j)</math> na zaslonu <tt>ix = x0 + i*dx</tt>, <tt>jy = y0 + j*dy</tt>. Na znani način poiščemo zgornjo in spodnjo mejo, <tt>zmin</tt> in <tt>zmax</tt>. Recimo, da bi v sliki radi ločili (približno) 10 razredov vrednosti spremenljivke <math>z</math>. Najpreprostejša upodobitev je kar s senčenjem ali z barvo. | |
- | function barva(i, j: integer): integer; | + | <tt> |
- | + | function barva(i, j: integer): integer; | |
- | var zz: real; | + | var zz: real; |
- | + | begin | |
- | begin | + | zz := 0.25*(z[i,j] + z[i+1,j] + z[i,j+1] + z[i+1,j+1]); |
- | + | barva := trunc(10.0*(zz - zmin)/(zmax - zmin)) | |
- | + | end; | |
- | + | </tt> | |
- | barva:= trunc(10.0*(zz-zmin)/(zmax-zmin)) | + | |
- | + | ||
- | end; | + | |
Narišemo pa: | Narišemo pa: | ||
- | for i:= 1 to nx-1 do | + | <tt> |
+ | for i := 1 to nx-1 do | ||
+ | for j := 1 to ny-1 do | ||
+ | rectangle(x0 + i*dx, y0 + j*dy, x0 + i*dx + dx, y0 + j*dy + dy, barva(i,j)) | ||
+ | </tt> | ||
- | + | Lepša je slika z izohipsami. Spet si bomo izbrali ~10 vrednosti za izohipse med <tt>zmin</tt> in <tt>zmax</tt>. Izohipso pri vrednosti <tt>z0</tt> narišemo tako, da pregledamo vse pravokotniške celice po vrsti, kot tečeta indeksa <tt>i</tt> in <tt>j</tt> njihovega spodnjega levega oglišča, ali vsebujejo vrednosti <tt>z0</tt>. Najprej pregledamo, kje na vsakem od robov celice je vrednost <tt>z0</tt>. Če vrednosti ni na tem robu, vrne funkcija vrednost <tt>-1</tt>, sicer pa najde točko na robu z linearno interpolacijo. | |
- | + | <tt> | |
- | + | function nicla(i1, j1, i2, j2: integer; z0: real): real | |
- | + | var z1, z2: real; | |
- | + | begin | |
- | function nicla(i1,j1,i2,j2:integer;z0:real):real | + | z1 := z[i1,j1]; |
- | + | z2 := z[i2,j2]; | |
- | var z1,z2:real; | + | if ((z0 - z1)*(z0 - z2)) then do nicla := (z0 - z1)/(z2 - z1) else do nicla := -1 |
- | + | end; | |
- | begin | + | </tt> |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | end; | + | |
Zdaj pogledamo po vrsti robove celice in si beležimo, na kolikih od njih je vrednost z0. Možno je, da dobimo 2 točki ali 4. Ustrezno temu potegnemo en ali dva odseka izohipse. | Zdaj pogledamo po vrsti robove celice in si beležimo, na kolikih od njih je vrednost z0. Možno je, da dobimo 2 točki ali 4. Ustrezno temu potegnemo en ali dva odseka izohipse. | ||
- | procedure celica(i,j:integer;z0:real) | + | <tt> |
- | + | procedure celica(i,j: integer; z0: real) | |
- | var m:integer; p:real; | + | var m: integer; p: real; xx, yy: array[1..4] of integer; |
- | + | begin | |
- | + | m := 1; | |
- | + | p := nicla(i, j, i+1, j, z0); | |
- | begin | + | if p > 0 then begin |
- | + | xx[m] := x0 + (i + p)*dx; | |
- | m:=1; p:= nicla(i,j,i+1,j,z0); | + | yy[m] := y0 + j*dy; |
- | + | inc(m) | |
- | + | end; | |
- | + | p := nicla(i+1, j, i+1, j+1, z0); | |
- | + | if p > 0 then begin | |
- | + | xx[m] := x0 + (i + 1)*dx; | |
- | end; | + | yy[m] := y0 + (j + p)*dy; |
- | + | inc(m) | |
- | p:= nicla(i+1,j,i+1,j+1,z0); | + | end; |
- | + | p := nicla(i+1, j+1, i, j+1, z0); | |
- | if p>0 then | + | if p>0 then begin |
- | + | xx[m] := x0 + (i + 1 - p)*dx; | |
- | + | yy[m] := y0 + (j + 1)*dy; | |
- | + | inc(m) | |
- | end; | + | end; |
- | + | p := nicla(i, j+1, i, j, z0); | |
- | p:=nicla(i+1, j+1,i,j+1,z0); | + | if p > 0 then begin |
- | + | xx[m] := x0 + i*dx; | |
- | if p>0 then | + | yy[m] := y0 + (j + 1 - p)*dy; |
- | + | end; | |
- | + | if m > 1 then plotline(xx[1], yy[1], xx[2], yy[2]); | |
- | + | if m = 4 then plotline(xx[3], yy[3], xx[4], yy[4] | |
- | end; | + | end; |
- | + | </tt> | |
- | p:=nicla(i,j+1,i,j,z0); | + | |
- | + | ||
- | if p>0 then | + | |
- | + | ||
- | + | ||
- | + | ||
- | end; | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | end; | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | V glavnem programu napravimo zanko po vseh vrednostih <tt>z0</tt>, za katere želimo narisati izohipse, in seveda dvojno zanko po vseh celicah: | |
- | + | ||
- | + | ||
- | + | <tt> | |
+ | for i := 1 to nx-1 do | ||
+ | for j := 1 to ny-1 do | ||
+ | celica(i, j, z0); | ||
+ | </tt> | ||
- | + | Notranje izohipse bodo nekoliko oglate, zunanje pa dokaj dobre. Nekaj malega bi lahko izboljšali z uporabo odsekov višjega reda (n.pr. paraboličnih lokov), predvsem pa pomaga, če je tabela funkcijskih vrednosti <tt>z[i,j]</tt> dovolj gosta. | |
- | + | == Naloge: == | |
- | Izberi primerno območje za spremenljivki | + | # Za 28 absorpcijskih spektrov robu K železa v datoteki "Fe_rob_0_27.xmu" nariši dvodimenzionalni graf, kjer je ena os energija fotona, druga pa čas v teku polnjenja in praznenja. Prikaži z barvo in izohipsami. |
+ | # Prikaži temperaturno polje v prečnem prerezu dimnika, kjer je temperatura vročih plinov 200 <sup>0</sup>C, na zunanji steni pa je 0 <sup>0</sup>C, iz podatkov v datoteki "Dimnik.dat". V datoteki je območje temperatur normirano na interval [0, 1], podane so v mreži 24 x 24 točk. Napravi grafa z barvno lestvico in z risanjem izoterm. | ||
+ | # Napravi graf izoterm <math>T(p,V)</math> za Van der Waalsov plin z enačbo stanja <math>(p+a/V^2)(V-b)=RT</math>, ki jo najprej predelamo v brezdimenzijsko obliko, tako da vse tri spremenljivke <math>p</math>, <math>V</math> in <math>T</math> normiramo na njihove vrednosti v kritični točki in se enačba v novih spremenljivkah <math>\Pi</math>, <math>\Phi</math> in <math>\Theta</math> glasi <math>(\Pi+3/\Phi^2)(3\Phi-1)=8\Theta</math>. Izberi primerno območje za spremenljivki <math>\Pi</math> in <math>\Phi</math> in si pripravi tabelo funkcije za risanje. |
Redakcija: 10:00, 5. maj 2009
Računalnik je prislovično hiter, vesten in neumoren delavec, le bister ni kaj dosti. Stori natanko samo tisto, kar smo mu v programu naročili. Da se izognemo naročanju vedno enakih korakov, imajo programski jeziki ukaze, ki omogočajo ponavljanja – zanke. Skoraj v vsaki nalogi doslej smo uporabili tako zanko (for i:= 1 to n do).
Gibkost programiranja pa zagotavljajo predvsem razvejitveni ukazi, ko je nadaljnji potek računanja odvisen od izpolnitve kontrolnega pogoja (if pogoj then do ... else do ...). Posebna vrsta zelo gibkih razvejitev so klici podprogramov in funkcij. S temi orodji bomo skicirali zgradbo programa za risanje dvodimenzionalnih grafov, t. j. upodabljanje funkcij z(x,y).
Naj bo funkcija podana s tabelo z[i,j], i = 1, ..., nx, j = 1, ..., ny, pri čemer sta koordinati točke (i,j) na zaslonu ix = x0 + i*dx, jy = y0 + j*dy. Na znani način poiščemo zgornjo in spodnjo mejo, zmin in zmax. Recimo, da bi v sliki radi ločili (približno) 10 razredov vrednosti spremenljivke z. Najpreprostejša upodobitev je kar s senčenjem ali z barvo.
function barva(i, j: integer): integer; var zz: real; begin zz := 0.25*(z[i,j] + z[i+1,j] + z[i,j+1] + z[i+1,j+1]); barva := trunc(10.0*(zz - zmin)/(zmax - zmin)) end;
Narišemo pa:
for i := 1 to nx-1 do for j := 1 to ny-1 do rectangle(x0 + i*dx, y0 + j*dy, x0 + i*dx + dx, y0 + j*dy + dy, barva(i,j))
Lepša je slika z izohipsami. Spet si bomo izbrali ~10 vrednosti za izohipse med zmin in zmax. Izohipso pri vrednosti z0 narišemo tako, da pregledamo vse pravokotniške celice po vrsti, kot tečeta indeksa i in j njihovega spodnjega levega oglišča, ali vsebujejo vrednosti z0. Najprej pregledamo, kje na vsakem od robov celice je vrednost z0. Če vrednosti ni na tem robu, vrne funkcija vrednost -1, sicer pa najde točko na robu z linearno interpolacijo.
function nicla(i1, j1, i2, j2: integer; z0: real): real var z1, z2: real; begin z1 := z[i1,j1]; z2 := z[i2,j2]; if ((z0 - z1)*(z0 - z2)) then do nicla := (z0 - z1)/(z2 - z1) else do nicla := -1 end;
Zdaj pogledamo po vrsti robove celice in si beležimo, na kolikih od njih je vrednost z0. Možno je, da dobimo 2 točki ali 4. Ustrezno temu potegnemo en ali dva odseka izohipse.
procedure celica(i,j: integer; z0: real) var m: integer; p: real; xx, yy: array[1..4] of integer; begin m := 1; p := nicla(i, j, i+1, j, z0); if p > 0 then begin xx[m] := x0 + (i + p)*dx; yy[m] := y0 + j*dy; inc(m) end; p := nicla(i+1, j, i+1, j+1, z0); if p > 0 then begin xx[m] := x0 + (i + 1)*dx; yy[m] := y0 + (j + p)*dy; inc(m) end; p := nicla(i+1, j+1, i, j+1, z0); if p>0 then begin xx[m] := x0 + (i + 1 - p)*dx; yy[m] := y0 + (j + 1)*dy; inc(m) end; p := nicla(i, j+1, i, j, z0); if p > 0 then begin xx[m] := x0 + i*dx; yy[m] := y0 + (j + 1 - p)*dy; end; if m > 1 then plotline(xx[1], yy[1], xx[2], yy[2]); if m = 4 then plotline(xx[3], yy[3], xx[4], yy[4] end;
V glavnem programu napravimo zanko po vseh vrednostih z0, za katere želimo narisati izohipse, in seveda dvojno zanko po vseh celicah:
for i := 1 to nx-1 do for j := 1 to ny-1 do celica(i, j, z0);
Notranje izohipse bodo nekoliko oglate, zunanje pa dokaj dobre. Nekaj malega bi lahko izboljšali z uporabo odsekov višjega reda (n.pr. paraboličnih lokov), predvsem pa pomaga, če je tabela funkcijskih vrednosti z[i,j] dovolj gosta.
Naloge:
- Za 28 absorpcijskih spektrov robu K železa v datoteki "Fe_rob_0_27.xmu" nariši dvodimenzionalni graf, kjer je ena os energija fotona, druga pa čas v teku polnjenja in praznenja. Prikaži z barvo in izohipsami.
- Prikaži temperaturno polje v prečnem prerezu dimnika, kjer je temperatura vročih plinov 200 0C, na zunanji steni pa je 0 0C, iz podatkov v datoteki "Dimnik.dat". V datoteki je območje temperatur normirano na interval [0, 1], podane so v mreži 24 x 24 točk. Napravi grafa z barvno lestvico in z risanjem izoterm.
- Napravi graf izoterm T(p,V) za Van der Waalsov plin z enačbo stanja (p + a / V2)(V − b) = RT, ki jo najprej predelamo v brezdimenzijsko obliko, tako da vse tri spremenljivke p, V in T normiramo na njihove vrednosti v kritični točki in se enačba v novih spremenljivkah Π, Φ in Θ glasi (Π + 3 / Φ2)(3Φ − 1) = 8Θ. Izberi primerno območje za spremenljivki Π in Φ in si pripravi tabelo funkcije za risanje.