summaryrefslogtreecommitdiff
path: root/Plasmapropagation.lpr
diff options
context:
space:
mode:
Diffstat (limited to 'Plasmapropagation.lpr')
-rw-r--r--Plasmapropagation.lpr279
1 files changed, 279 insertions, 0 deletions
diff --git a/Plasmapropagation.lpr b/Plasmapropagation.lpr
new file mode 100644
index 0000000..52e1926
--- /dev/null
+++ b/Plasmapropagation.lpr
@@ -0,0 +1,279 @@
+program Plasmapropagation;
+
+{$mode objfpc}{$H+}
+
+uses
+ {$IFDEF UNIX}{$IFDEF UseCThreads}
+ cthreads,
+ {$ENDIF}{$ENDIF}
+ Classes, SysUtils, CustApp,
+ { you can add units after this }
+ math, Physikunit, crt;
+
+var ErrorCode: longint;
+
+type
+
+ { TPlasmapropagation }
+
+ TPlasmapropagation = class(TCustomApplication)
+ protected
+ procedure DoRun; override;
+ public
+ constructor Create(TheOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure WriteHelp; virtual;
+ end;
+
+function InputFeld(t: extended): extended;
+const a0 = 1;
+ omega = 2*pi*100;
+ tfwhm = 10 * 2*pi/omega;
+ tMitte = 3*tfwhm;
+begin
+(* result:=
+ a0 * Exp(-2*Ln(2)*sqr((t-tMitte)/tfwhm)) *
+ (omega*Cos(t*omega) + 4*Ln(2)*(tMitte - t)*Sin(t*omega)/sqr(tfwhm)); *)
+
+ result:=
+ a0 * Exp(-2*Ln(2)*sqr((t-tMitte)/tfwhm)) *
+ Sin(t*omega)
+end;
+
+function Anfangsdichte(x: extended): extended;
+const Profilbreite = 0.5;
+ Randbreite = 0.1;
+ offset = 0.0001;
+ Mitte = 0.75;
+begin
+ x:=abs(x-Mitte);
+ result:=1+offset;
+ if x<=Profilbreite then exit;
+ result:=0+offset;
+ if x>=Profilbreite+Randbreite then exit;
+ result:=sqr(sin((Profilbreite+Randbreite-x)*0.5*pi/Randbreite))+offset;
+end;
+
+{ TPlasmapropagation }
+
+procedure TPlasmapropagation.DoRun;
+var
+ ErrorMsg,s,t,u: String;
+ Breite,i,j: longint;
+ Gitter: TGitter;
+ deltaT,deltaX,start,
+ sT,sDT,sDX,Endzeit,
+ zeitDatei,zeitPhysik,
+ pDNMax: extended;
+ AusgabeDateien: array of TAusgabeDatei;
+ FI: TFeldInhalt;
+ Zeitverfahren: TZeitverfahren;
+ Abl: Boolean;
+ Prot: TProtokollant;
+ c: char;
+begin
+ // quick check parameters
+ start:=now;
+ s:='';
+ for Abl:=False to True do
+ for FI:=low(TFeldInhalt) to high(TFeldInhalt) do
+ if not (Abl and (FI in [fiP,fiPX,fiPY,fiPZ,fiGamma,fiiGamma])) then
+ s:=s+' '+Copy('d',1,Byte(Abl))+OptionNamen[FI]+':';
+ ErrorMsg:=CheckOptions('HB:Z:x:t:FEX:T:D:','Hilfe Breite: Zeit: Ortsschritt: Zeitschritt: Fortschrittsanzeige Euler Ortsspeicherschritt: Zeitspeicherschritt: Diffusionsterm:'+s);
+ if (ErrorMsg='') then begin
+ setlength(Ausgabedateien,0);
+ for Abl:=False to True do
+ for FI:=low(TFeldInhalt) to high(TFeldInhalt) do
+ if not (Abl and (FI in [fiGamma,fiP])) then
+ if HasOption(Copy('d',1,Byte(Abl))+OptionNamen[FI]) then begin
+ setlength(Ausgabedateien,length(Ausgabedateien)+1);
+ Ausgabedateien[length(Ausgabedateien)-1].Inhalt:=FI;
+ Ausgabedateien[length(Ausgabedateien)-1].Ableitung:=Abl;
+ AssignFile(Ausgabedateien[length(Ausgabedateien)-1].Datei,GetOptionValue(Copy('d',1,Byte(Abl))+OptionNamen[FI]));
+ end;
+ if length(Ausgabedateien)=0 then
+ ErrorMsg:='Du solltest irgendetwas abspeichern lassen! ('+AusgabeHilfe+')';
+ end;
+ if ErrorMsg<>'' then begin
+ ShowException(Exception.Create(ErrorMsg));
+ Terminate;
+ Exit;
+ end;
+
+ // parse parameters
+ if HasOption('H','Hilfe') then begin
+ WriteHelp;
+ Terminate;
+ Exit;
+ end;
+ if HasOption('Z','Zeit') then Endzeit:=strtofloat(GetOptionValue('Z','Zeit'))
+ else Endzeit:=100;
+ if HasOption('x','Ortsschritt') then deltaX:=strtofloat(GetOptionValue('x','Ortsschritt'))
+ else deltaX:=1e-2;
+ if HasOption('B','Breite') then Breite:=round(strtofloat(GetOptionValue('B','Breite'))/deltaX)
+ else Breite:=1000;
+ if HasOption('t','Zeitschritt') then deltaT:=strtofloat(GetOptionValue('t','Zeitschritt'))
+ else deltaT:=deltaX/10;
+ if HasOption('X','Ortsspeicherschritt') then begin
+ s:=GetOptionValue('X','Ortsspeicherschritt');
+ if pos('#',s)=0 then sDX:=strtofloat(s)
+ else sDX:=Breite*deltaX/strtofloat(rightstr(s,length(s)-1));
+ end
+ else sDX:=deltaX;
+ if HasOption('T','Zeitspeicherschritt') then begin
+ s:=GetOptionValue('T','Zeitspeicherschritt');
+ if pos('#',s)=0 then sDT:=strtofloat(s)
+ else sDT:=Endzeit/strtofloat(rightstr(s,length(s)-1));
+ end
+ else sDT:=sDX;
+ if HasOption('D','Diffusionsterm') then pDNMax:=strtofloat(GetOptionValue('D','Diffusionsterm'))
+ else pDNMax:=-1;
+ if HasOption('E','Euler') then Zeitverfahren:=zfEulerVorwaerts
+ else Zeitverfahren:=zfRungeKuttaVier;
+
+ { add your program here }
+
+ Prot:=TProtokollant.create('error');
+
+ Prot.schreibe('Simulationsbox');
+ Prot.schreibe(' '+inttostr(breite)+' Felder breit ('+floattostr(breite*deltaX)+' lambda)');
+ Prot.schreibe(' '+floattostr(Endzeit)+' T lang (etwa '+inttostr(round(Endzeit/deltaT))+' Schritte)');
+ Prot.schreibe(' '+floattostr(deltaT)+' Zeitschritt und '+floattostr(deltaX)+' Ortsschritt');
+ for i:=0 to length(Ausgabedateien)-1 do begin
+ Prot.schreibe('Mache Ausgabe '+Copy('d',1,Byte(Ausgabedateien[i].Ableitung))+Ausgabenamen[Ausgabedateien[i].Inhalt]+'.');
+ Rewrite(Ausgabedateien[i].Datei,1);
+ j:=0;
+ BlockWrite(Ausgabedateien[i].Datei,j,sizeof(longint));
+ j:=floor(Endzeit/sDT+1);
+ BlockWrite(Ausgabedateien[i].Datei,j,sizeof(longint));
+ end;
+ if pDNMax<0 then Prot.schreibe('Maximales px * dn/dx / n wird automatisch ermittelt.')
+ else Prot.schreibe('Maximales px * dn/dx / n: '+floattostr(pDNMax/deltaX)+'mc/dx');
+ s:='Iterationsverfahren: ';
+ case Zeitverfahren of
+ zfEulerVorwaerts: s:=s+'Euler-Vorwärts';
+ zfRungeKuttaVier: s:=s+'Runge-Kutta';
+ else s:=s+'unbekannt!?';
+ end{of case};
+ Prot.schreibe(s);
+
+ zeitDatei:=0;
+ zeitPhysik:=0;
+ sT:=-Min(deltaT,sDT)/2;
+ Gitter:=TGitter.create(Breite,deltaT,deltaX,pDNMax,@Anfangsdichte,Zeitverfahren,Prot);
+// Gitter.Al:=@InputFeld;
+ while Gitter.t<Endzeit do begin
+ if HasOption('F','Fortschrittsanzeige') then begin
+ if errorCode<2 then
+ s:=Gitter.gibErhaltungsgroessen;
+ if (floor(100*Gitter.t/Endzeit) < floor(100*(Gitter.t+deltaT)/Endzeit)) or keypressed then begin
+ if keypressed then c:=readkey
+ else c:=#0;
+ case c of
+ #27,'q': begin
+ errorCode:=3;
+ break;
+ end;
+ ' ': begin
+ writeln(' ... Pause (beliebige Taste drücken um fortzufahren) ...');
+ readkey;
+ writeln(' ... weiter geht''s ...');
+ end;
+ else begin
+ Prot.schreibe(inttostr(round(100*Gitter.t/Endzeit))+'% (t='+floattostr(Gitter.t)+'T)',true);
+ Prot.schreibe(timetostr(now-start)+' ('+floattostr(zeitPhysik/max(1e-11,zeitPhysik+zeitDatei))+')',true);
+ Prot.schreibe('ETA: '+timetostr((now-start)*(Endzeit-Gitter.t)/max(Gitter.t,deltaT)),true);
+ Prot.schreibe('aktueller Zeitschritt: '+floattostr(deltaT)+'T',true);
+ Prot.schreibe(s);
+ end;
+ end{of case};
+ end;
+ end;
+
+ zeitPhysik:=zeitPhysik-now;
+ if errorCode<2 then
+ Gitter.iteriereSchritt(deltaT);
+ zeitPhysik:=zeitPhysik+now;
+ zeitDatei:=zeitDatei-now;
+ while Gitter.t>=sT do begin
+ sT:=sT+sDT;
+ for j:=0 to length(Ausgabedateien)-1 do
+ Gitter.macheAusgabe(Ausgabedateien[j],sDX);
+ end;
+ zeitDatei:=zeitDatei+now;
+ end;
+
+ case errorCode of
+ 2: Prot.schreibe('Simulation wurde auf halbem Wege abgebrochen wegen Überlaufs.',true);
+ 3: Prot.schreibe('Simulation wurde auf halbem Wege abgebrochen wegen Benutzereingriffs.',true);
+ end{of case};
+
+ for i:=0 to length(Ausgabedateien)-1 do
+ CloseFile(Ausgabedateien[i].Datei);
+
+ Prot.schreibe('fertig!',true);
+ s:=timetostr(now-start);
+ t:=timetostr(zeitDatei);
+ u:=timetostr(zeitPhysik);
+ while length(s)<max(length(t),length(u)) do s:=' '+s;
+ while length(t)<max(length(s),length(u)) do t:=' '+t;
+ while length(u)<max(length(s),length(t)) do u:=' '+u;
+ Prot.schreibe('Das hat '+s+' gedauert,',true);
+ Prot.schreibe(' davon '+t+' für Dateizugriffe',true);
+ Prot.schreibe('und nur '+u+' für die eigentliche Physik!',true);
+
+ Gitter.Free;
+ Prot.Free;
+ // stop program loop
+ Terminate;
+ if errorCode=1 then errorCode:=0;
+end;
+
+constructor TPlasmapropagation.Create(TheOwner: TComponent);
+begin
+ inherited Create(TheOwner);
+ errorCode:=1;
+ StopOnException:=True;
+end;
+
+destructor TPlasmapropagation.Destroy;
+begin
+ inherited Destroy;
+end;
+
+procedure TPlasmapropagation.WriteHelp;
+begin
+ { add your help code here }
+ writeln('Verwendung:');
+ writeln(ExeName,' -HBZxtFEP '+AusgabeHilfe);
+ writeln(' -H/--Hilfe Hilfe anzeigen');
+ writeln(' -B/--Breite=x');
+ writeln(' Breite der Simulationsbox in Plasmawellenlängen');
+ writeln(' -Z/Zeit=x');
+ writeln(' Länge der Simulationsbox in Plasmaoszillationsperioden');
+ writeln(' -x/Ortsschritt=x');
+ writeln(' Ortsdiskretisierung in Plasmaoszillationsvakuumwellenlängen');
+ writeln(' -t/Zeitschritt=x');
+ writeln(' Zeitdiskretisierung in Plasmaoszillationsperioden');
+ writeln(' -X/Ortsspeicherschritt=x');
+ writeln(' Ortsdiskretisierung der gespeicherten Werte in Plasmaoszillationsvakuumwellenlängen');
+ writeln(' -T/Zeitspeicherschritt=x');
+ writeln(' Zeitdiskretisierung der gespeicherten Werte in Plasmaoszillationsperioden');
+ writeln(' -F/Fortschrittsanzeige');
+ writeln(' -E/Euler');
+ writeln(' verwende Eulerverfahren statt Runge-Kutta Stufe 4');
+ writeln(' -D/Diffusionsterm=x');
+ writeln(' p_x * dn/dx / n, bis zu dem numerische Stabilität gewähleistet ist.');
+ writeln(' Ein hoher Wert bringt in Verbindung mit einer schlechten Ortsauflösung unphysikalische Ergebnisse!');
+ writeln(' Ein negativer Wert sowie keine Angabe aktivieren die automatische Bestimmung. Das garantiert numerische Stabilität, führt jedoch möglicherweise unbemerkt zu unphysikalischen Ergebnissen.');
+end;
+
+var
+ Application: TPlasmapropagation;
+begin
+ Application:=TPlasmapropagation.Create(nil);
+ Application.Run;
+ Application.Free;
+ Halt(errorCode);
+end.
+