<<

#05 ; Enkel algoritmik

>>

Äntligen kommer vi att räkna kulans gång i luften på riktigt, åtminstone skottets ungefärliga horisontala hastighet.

Vi behöver algoritmen för programmet. Jag skall använda notation som passar ihop med JavaScript. I JavaScript kommer vi att använda "tabeller" för resultat så att alla resultat är bevarade när luupen blir färdig. För klarhetens skull kommer jag att använda i pseudokoden för värden i tabeller notation typ tabell [ index ], alltså indexet i hakparentes, eftersom vanliga parentes används i allmänhet så mycket.

Den ballistiska koefficienten BC kommer att vara tills vidare en konstant. Om vi tänker att den fysikaliska BC:n är 1750 gånger mera än den ballistiska, kan vi skriva för det valda skottet från Lapua i pseudokod så här:

BC := 0,785 * 1750	// Fysikalisk BC för det valda skottet i kg/m2

Vi kan läsa tex. pseudokoden A := A + 1 som "variabeln A får ett nytt värde som är det gamla värdet på A plus 1". För klarhetens skull vill jag inte skriva det litet kortare A = A + 1 , fast det gör man allmänt. Alltså variablar till höger om likhetstecken är gamla värden och det är inte riktigt fråga om likheten här, utan det är en ny placering. Den förstnämnda variabeln får ett nytt värde och samtidigt dess gamla värde försvinner för evigt. Värdet på A skrevs över och det går inte att få det gamla värdet tillbaka.

Vi kommer att behöva en funktion som räknar kulans negativa acceleration för en given varierande hastighet. Runge-Kutta numerisk integration kommer att kalla funktionen när det behövs. Pseudokoden för funktionen som heter acc följer :

// Matematisk notation skulle vara : 
//   y'' = f ( x, y, y' )

FUNKTION acc ( t, s, v )
  // Faktiskt endast hastigheten v behövs, men för 
  // den matematiska fullständighetens skull har vi 
  // också tiden t och sträckan s som parametrar

  rho := 1,225	// Konstant luftens täthet kg/m3 

  
  acceleration := -rho * v2 / ( 2 * BC )
  // Använder det värde BC som har givits annorstädes

  RETURN acceleration
SLUT FUNKTION

För att starta Runge-Kutta ger vi följande värden för det ursprungliga läget

n := 0		// indexet i början är noll
s[0] := 0	// sträckan s är först 0m, matematiskt y0 = 0
t[0] := 0	// tiden t är först 0s, matematiskt x0 = 0
v[0] := 830	// kulans hastighet är först 830 m/s, matematiskt y'0 = 830

Vi väljer den konstanta längden för tidssteget Δt eller h. Till exempel 10 millisekunder eller 10/1000 sekunder skulle vara 0,01 sekunder.

h := 0,010	// tidssteget Δt är 0,01 sekunder, alltså 10 millisekunder

Nu kan vi starta luupen som utför den numeriska integrationen. Det här är Runge-Kutta -algoritmen andra grad i pseudokod. Vi kommer att bryta luupen när sträckan s[n] har vuxit tillräckligt stor, tex. mera än 300 meter. Programmet skall alltså repetera iterationen tills kulan har flugit långt nog. Först är det ju indexet n = 0 och det växer i varje varv så att programmet gör nya placeringar i tabeller och inte skriver över de gamla.

ITERATION tills sträckan som kulan flugit s[n] > 300, eller är stor nog

  // Runge-Kutta kallar funktionen acc fyra gånger för olika hastigheter
  // Värden på t och s varierar också men de har ingen betylse i detta fall
  // för man kan inte räkna kulans acceleration direkt från tiden eller sträckan

  k1 := h * acc ( t[n],       s[n],                         v[n] )
  k2 := h * acc ( t[n] + h/2, s[n] + v[n] * h/2,            v[n] + k1 / 2 )
  k3 := h * acc ( t[n] + h/2, s[n] + v[n] * h/2 + k1 * h/4, v[n] + k2 / 2 )
  k4 := h * acc ( t[n] + h,   s[n] + v[n] * h   + k2 * h/2, v[n] + k3 )

  // Nya resultat som gäller för tiden t[n+1] :

  s[n+1] := s[n] + h * v[n] + ( k1 + k2 + k3 ) / 6
  // Sträckan som kulan flugit, matematiskt  yn+1 = ...

  v[n+1] := v[n] + ( k1 + 2*k2 + 2*k3 + k4 ) / 6
  // Kulans nya fart, matematiskt  y'n+1 = ...

  t[n+1] := t[n] + h	
  // Tiden har nu vuxit med det konstanta steget Δt eller h
  // Matematiskt  xn+1 = xn + h

  // Vi förbereder oss för det nästa steget (i fall det blir ett)

  n := n + 1		// Indexet n växer

SLUT ITERATION

Då luupen slutar, har vi alla räknade resultat i tabeller t[], s[], v[] . Indexet n berättar hur många steg algoritmen behövde för att nå och överskrida det önskade avståndet. Det måste överskrida avståndets övre gräns litet för att vi skall kunna interpolera värdena precis vid gränsen. När alla värden är i globala tabeller, kan vi använda dom även efter luupen om det behövs och interpolationen kommer ju att behöva dem.

Tabellen t[] innehåller stegets tid i sekunder
Tabellen s[] innehåller sträckor i meter som kulan har flugit
Tabellen v[] innehåller kulans hastigheter i meter per sekund

Vi får alltså inte direkt hastigheter i jämna mellanrum av sträckan för tex. 100m, 200m, 300m osv, utan vi kommer att få resultat som sträckan och farten i jämna mellanrum av tidsteget Δt eller h som det heter i algoritmen.

t[n] ; stegets tid i sekunder
s[n] ; motsvarande sträcka som kulan har flugit, i meter
v[n] ; motsvarande kulans hastighet i m/s

Vårt kära lilla programm kommer att existera i sin egna fil.

Jag tror nog att faktiskt det är skottets BC som varierar, och inte relationen BCi_fysik / BCi_ballistik som jag ännu inte känner så bra, troligen den är en konstant vars värde (i G1-modellen) ligger någonstans mellan 1680 och 1820?

Det här är ännu ganska mycket experimentation för mig. Tidstegets längd i RK är inte så kritiskt. Man skall bära i minnet att man kan inte förbättra noggranheten oendligt genom att förkorta tidsteget. Ett mycket kort tidsteg betyder många varv iteration med "rundningsfel" som kan växa större än det fördel som ett kortare steg medför. Vi måste lära oss att leva med små fel.



Meny
Huvudsida (finska)