Content

Teilchen Im Nanobereich



Die Überlegungen zur Technischen Realisierung des Programmes waren der erste Schritt des Designs.
Das Vorgehen zum Systemdesig erfolgte nach Rumbaugh.

Systemdesign

Aufteilung in Subsysteme

Objekte mit ähnlichen Eigenschaften und ähnlichen Funktionen weren zusammengefaßt. Objekte innerhalb eines Subsystems sind eng miteinander verbunden, die Subsysteme selbst sind lose gekoppelt und nur durch wenige definierte Schnittstellen verbunden.

Identifikation von Parallelverarbeitung

Zwei Objekte arbeiten dann parallel, wenn sie zur gleichen Zeit Events empfangen können, aber nicht zusammenarbeiten.
Im Programm Tina wäre es möglich Teile der Berechnung parallel zu gestalten, es wurde aber nicht vorgesehen.

Auswahl der Methode zur Datenverwaltung

Im Programm Tina wird zum Speichern der Versuchsdaten sowie für die zu ladenden ASCII-Files ein Filesystem benötigt.

Auswahl der Art der Software-Kontrolle

Da das Programm Tina objektorientiert, mit graphischer Benutzeroberfl&äuml;che und ohne Parallelverarbeitung ist, wird die Kontrolle event-gesteuert implementiert.

Objektdesign

Aus den Modellen der Analysephase wird das Objektmodell entwickelt.
Die Funktionen wurden aus den Prozessen des funktionalen Modells und den Events des dynamischen Modellsermittelt und den Klassen des Objektmodells zugeordnet.
In der weiteren Designphase wurde die Notwendigkeit der Klasse Complex entdeckt und implementiert. Daraus entstand das folgende Objektmodell:

Algorithmen

Am Ende Der Designphase wurden Algorithmen für die wesentlichen Teile der Anwendung Tina erstellt.

CVersuch::CVersuch()
{ maxfarben=1250;
for (int i=0;i<531;i++)
ASCII_File[i]=0;
maxvalueposFELD=0;
};

double CVersuch::maxvalueASCII()
{ double help=0;
for (int i=0;i<531;i++)
if (ASCII_File[i]>help)
(help=ASCII_File[i]);
return help;
}

void CVersuch::setdatetime(const char* date,const char* time)
{ strcpy(Datum,date);
strcpy(Uhrzeit,time);
}

void CVersuch::getdatetime(char* date, char* time)
{ strcpy(date,Datum);
strcpy(time,Uhrzeit);
}

CComplex CVersuch::alpha(double a,double b,double lambda,double epsumg,double efakt)
{
CComplex retval;
CComplex epsi=0.0;
double gamma,g2,g3,g4,dpf,hv;
gamma=a/b;
g2=gamma*gamma;
if (a < b)
{ epsi=epsab(a,b,lambda,efakt)/epsumg;
g3=sqrt(1.0-g2);
dpf=(0.5*log((1.0+g3)/(1.0-g3))/g3-1.0)/(g3*g3);
retval=0.33333333*b*b*b/(dpf+1.0/((epsi-1.0)*g2));
}
else
{ g3=g2-1.0;
g4=sqrt(g3);
hv=g4/gamma;
epsi=epsab(a,b,lambda,efakt)/epsumg;
dpf=1.0/g2-1.0/g3+atan(hv/sqrt(1.0-hv*hv))/(g4*g4*g4);
retval=0.66666667*b*b*b/(dpf+2.0/((epsi-1.0)*g2));
}
return retval;
}

CComplex CVersuch::eps(double lambda,double efakt)
//C Diese Funktion berechnet die komplexe Dielektrizitaetsfunktion von Silber
//C mittels Polynomfit. Werte nach Johnson & Christie (1972).
//C Gilt fuer 290 nm < lambda < 821 nm.

{ CComplex retval;
double eps1,eps2;
if (lambda<332.0)
{ eps1=-2.3905E-3*lambda*lambda+1.46101*lambda-2.22263E2;
eps2=1.13355E-3*lambda*lambda-0.786993*lambda+1.36539E2;
{ if (lambda>320.0)
eps2=eps2+(332.-lambda)/200.0;
}
}
else
{ eps1=-3.70839E-5*lambda*lambda-2.21316E-2*lambda+10.4863;
eps2=1.50032E-10* pow(lambda,4.0) -3.54302E-7* pow(lambda,3) +14.9751;
eps2=eps2+3.03927E-4*lambda*lambda-0.111437*lambda;
if (lambda<350.0)
{ eps2=eps2-(350.-lambda)/400.0;
eps1=eps1+(350.-lambda)/50.0;
}
}
retval=eps1+efakt*eps2*I;
return retval;
}

CComplex CVersuch::drude(double lambda,double tau)
{ CComplex retval;
//C Dielektrizitaetsfunktion von Silber nach d. Drude-Formel.
//C tau=Relaxationszeit
retval=lambda*lambda/(ONE+I*lambda/(1.88364E18*tau));
retval=ONE-5.2598E-5*retval;
return retval;
}

CComplex CVersuch::epsab(double a,double b,double lambda,double efakt)
// Korrektur d. Dielektrizitaetsfunktion nach Kreibig u. Fragstein (1969)
// (Verkuerzung der freien Weglaenge der Leitungselektronen)
// Fuer flache Sphaeroide; a,b = Halbachsen

{ CComplex retval,epsb;
double vfermi,tau,hv1,f,hv2,fwl,gamma;
vfermi=1.4E15;
tau=3.1E-14;
epsb=eps(lambda,efakt)-drude(lambda,tau);
gamma=b/a;
if (a < b)
{ //Prolate Inseln a kleiner b (Laenglich)
hv1=sqrt(gamma*gamma-1.0);
f=hv1/gamma;
hv2=atan(f/sqrt(1.0-f*f));
fwl=(2.0*gamma*gamma-1.0)/hv1-hv2-2.0*log(gamma)/(hv1*hv1*hv1);
fwl=fwl/(gamma*gamma*hv2+hv1);
fwl=4.0*b*fwl/3.0;
}
else
{ //Oblate Inseln a>b (flach)
hv1=sqrt(1.0-gamma*gamma);
f=hv1/gamma;
hv2=log(sqrt(f*f+1.0)+f);
fwl=(2.0*gamma*gamma-1.0)/hv1+hv2+2.0*log(gamma)/(hv1*hv1*hv1);
fwl=fwl/(gamma*gamma*hv2+hv1);
fwl=-4.0*b*fwl/3.0;
}
tau=1.0/(1.0/tau+vfermi/fwl);
retval=epsb+drude(lambda,tau);
return retval;
}

double CVersuch::vqabs(double a, double lambda)
// Die zu integrierende Funktion (Gauss-Dichte mal Extinktionsquerschnitt)
{ CComplex alphrd;
double k0,retval;
double b,v;
b=teil.getb();
v=a-teil.geta();
v=exp(-v*v/(2.0*teil.getSIGMA()*teil.getSIGMA()))/(sqrt(2.0*PI)*teil.getSIGMA());
alphrd=alpha(a,b,lambda,teil.getepsilon(),teil.getkorrekturfaktor());
k0=2.0*PI/lambda;
alphrd=alphrd/(ONE-I*2.0*k0*k0*k0*alphrd/3.0);
retval=v*8.0*PI*PI*alphrd.i/lambda;
return retval;
}

double CVersuch::simps(double a,double b, double n, double wert)
// Simpson-Verfahren.
// Integration der Funktion funk von a bis b.
// n = Zahl der Intervalle (gerade!).
{ double x,dx,x1,x2,retval;
dx=2.0*(b-a)/n;
retval=vqabs(a,wert)+vqabs(b,wert);
x1=a+dx/2.0;
for (x=x1;x<=b;x+=dx)
retval=retval+4.0*vqabs(x,wert);
x1=a+dx;
x2=b-dx/2.0;
for (x=x1;x<=x2;x+=dx)
retval=retval+2.0*vqabs(x,wert);
retval=retval*dx/6.0;
return retval;
}

// Feldverstaerkung in der Umgebung flacher Sphaeroide bei
// Anregung senkrecht zur Rotationsachse.

double CVersuch::ofeld(double a,double b,double lambda,double x,double y,double z,double epsumg,double
efakt) { double l, xi0, rl, srl, xi, hv, dxidx, dxidy, dxidz, q, ax, ay, az, retval;
CComplex m,v;

xi0=1.0/sqrt(a*a/(b*b)-1.0);
m=eps(lambda,efakt)/epsumg-ONE;
m=m/(m*(atan(1.0/xi0)-xi0/(xi0*xi0+1.0))+2.0/(xi0*(xi0*xi0+1.0)));
l=a*a-b*b;
rl =0.5*((x*x+y*y+z*z)/l-1.0);
srl =sqrt(rl*rl+z*z/l);
xi =sqrt(rl+srl);
hv =2.0*xi*l;
dxidx=(1.0+rl/srl)*x/hv;
dxidy=(1.0+rl/srl)*y/hv;
dxidz=(1.0+(rl+1.0)/srl)*z/hv;
q =2.0*x/((1.+xi*xi)*(1.0+xi*xi));
ax =atan(1.0/xi)-xi/(xi*xi+1.0)-q*dxidx;
ay =-q*dxidy;
az =-q*dxidz;
v=ONE-m*ax;
v=v*v+(ay*ay+az*az)*m*m;
retval=cabs(csqrt(v));
return retval;
}

// Resonanzwellenlaenge von Silbersphaeroiden:

double CVersuch::res(double a,double b)
{ double p, q, gamma, g2, g3, g4, hv, retval;
p=0.0221316/3.70839E-5;
q=10.4863;
gamma=a/b;
g2=gamma*gamma;
if (gamma > 1.0)
{
g3=g2-1.0;
g4=sqrt(g3);
hv=g4/gamma;
q=q-1.0+2.0/(1.0-g2/g3+g2*atan(hv/sqrt(1.0-hv*hv))/(g4*g4*g4));
}
else
{
g3=1.0-g2;
g4=sqrt(g3);
q=q-1.0+1.0/(g2*(0.5*log((1.0+g4)/(1.0-g4))/g4-1.0)/g3);
}
q=-q/3.70839E-5;
retval=-p/2.0+sqrt(p*p/4-q);
return retval;
}

double CVersuch::calculateFeldverstaerkung(double wert)
{ double value;
double avon,abis,fdicht;
CComplex c;
avon=teil.geta()-2.0*teil.getSIGMA();
abis=teil.geta()+2.0*teil.getSIGMA();
fdicht=1.0/(Gitterkonstante*Gitterkonstante);
// value=-log10(exp(-fdicht*simps(avon,abis,100.0,wert)));
value=-log10(exp(-fdicht*simps(avon,abis,2,wert)));
return value;
}

double CVersuch::calculateFeldverlauf(double x,double y,double z)
{ double value;
if ((pow(x,2)/pow(teil.geta(),2)+pow(y,2)/pow(teil.geta(),2)+pow(z,2)/pow(teil.getb(),2))<1.0)
return 0.0;
value=ofeld(teil.geta(),teil.getb(),res(teil.geta(),teil.getb()),x,y,z,teil.getepsilon(),teil.getkorrekturfaktor());
value=pow(value,2);
return value;
}

char* CVersuch::getUhrzeit()
{ return Uhrzeit;
}

char* CVersuch::getDatum()
{ return Datum;
}

double CVersuch::getgkonst()
{ return Gitterkonstante;
}

void CVersuch::setgkonst(double gk)
{ Gitterkonstante=gk;
}

void CVersuch::parameter_laden(const char* name)
{ ifstream datei;
char help;
datei.open(name);
datei>>Experimentnummer>>help;
datei>>Gitterkonstante>>help;
datei>>teil;
datei>>help;
datei>>licht;
datei>>help>>help;
datei>>Uhrzeit>>help>>help;
datei>>Datum>>help>>help;
datei.close();
Uhrzeit[8]=0;
Uhrzeit[8]=0;
};

void CVersuch::parameter_speichern(const char* name)
{ ofstream datei;
datei.open(name);
datei< datei< datei< datei< datei< datei< datei.close();
};

void CVersuch::setall(int expnr, float a, float b, float eps, float epsk, float psigma, double gitterk, char* materi,
float start, float ende, char* richtung, char* pricht)
{ Experimentnummer=expnr;
teil.seta(a);
teil.setb(b);
teil.setepsilon(eps);
teil.setkorrekturfaktor(epsk);
teil.setSIGMA(psigma);
Gitterkonstante=gitterk;
if (!(strcmp(materi,"Silber")))
teil.material.setmatbez(CMaterial::silber);
licht.setBereichStart(start);
licht.setBereichEnde(ende);
if (!(strcmp(richtung,"oben")))
licht.setRichtung(CLicht::oben);
if (!(strcmp(richtung,"seitlich")))
licht.setRichtung(CLicht::seitlich);
if (!(strcmp(pricht,"horizontal")))
licht.setPolarisationsrichtung(CLicht::horizontal);
if (!(strcmp(pricht,"vertikal")))
licht.setPolarisationsrichtung(CLicht::vertikal);
};

void CVersuch::lade_datei (char* name)
{ ifstream datei;
double help;
int position,lastposition=290;
datei.open(name);
// Try to use the MVCPP Exception Handling, but failed (possible error in MVCPP)
/*if (!datei.good())
{ AfxThrowFileException(CFileException::generic);
}
*/
while (!datei.eof())
{ datei >> help;
// There should be no error at this values, but the system will crash if there is one !
(help<290) ? (position=290) : (position=(int)help);
(help>821) ? (position=821) : (position=(int)help);
datei >> help;
for (;lastposition<=position;lastposition++)
ASCII_File[lastposition-290]=help;
}
datei.close();
for (;lastposition<=821;lastposition++)
ASCII_File[lastposition-290]=help;
}

void CVersuch::Feldverstaerkung (CDiagramme* Worksheet)
{ double step;
double xstart,xend,ystart,yend;
Worksheet->getranges(&xstart,&xend,&ystart,¥d);
if ((xstart==0) && (xend==0) && (ystart==0) && (yend==0))
{
xstart=licht.getBereichStart();
xend=licht.getBereichEnde();
ystart=-0.1;
yend=maxvalueASCII()+0.2;
if (yend==0.2)
{ if (maxvalueposFELD<280)
{ maxvalueFELD=0;
for (int i=290;i<=821;i++)

putvalueFELD(calculateFeldverstaerkung(i),i);
}
yend=maxvalueFELD+0.2;
}
Worksheet->setdiagrammaxes(xstart,xend,ystart,yend);
}
step=Worksheet->x_Schrittweite_holen();
Worksheet->drawdiagramm();
if (maxvalueASCII()>0.0001)
{ Worksheet->virtualmove(xstart,ASCII_File[((int)xstart)-290]);
for (int i=((int)(xstart));i<=((int)(xend));i++)
Worksheet->drawLine(i,ASCII_File[i-290],RGB(250,0,0),2);
}
Worksheet->virtualmove(xstart,calculateFeldverstaerkung(xstart));
for (double f=xstart;f<=xend;f+=step)
Worksheet->drawLine(f,calculateFeldverstaerkung(f),RGB(0,0,0),2);
}

void CVersuch::Feldverlauf_2D (CDiagramme* Worksheet,int flag)
{ double step,f;
double xstart,xend,ystart,yend;
Worksheet->getranges(&xstart,&xend,&ystart,¥d);
if ((xstart==0) && (xend==0) && (ystart==0) && (yend==0))
{ switch (flag)
{ case 0: xstart=teil.geta();
xend=teil.geta()*5;
ystart=-0.1;
yend=calculateFeldverlauf(teil.geta(),0,0);
break;
case 1: xstart=teil.geta();
xend=teil.geta()*5;
ystart=-0.1;
yend=calculateFeldverlauf(0,teil.geta(),0);
break;
case 2: xstart=teil.getb();
xend=teil.getb()*5;
ystart=-0.1;
yend=calculateFeldverlauf(0,0,teil.getb());
break;
}
Worksheet->setdiagrammaxes(xstart,xend,ystart,yend);
}
step=Worksheet->x_Schrittweite_holen();
Worksheet->drawdiagramm();
switch (flag)
{ case 0: Worksheet->virtualmove(xstart,calculateFeldverlauf(xstart,0,0));
for (f=xstart;f<=xend;f+=step)
Worksheet-
>drawLine(f,calculateFeldverlauf(f,0,0),RGB(0,0,255),2);
break;
case 1: Worksheet->virtualmove(xstart,calculateFeldverlauf(0,xstart,0));
for (f=xstart;f<=xend;f+=step)
Worksheet-
>drawLine(f,calculateFeldverlauf(0,f,0),RGB(0,0,255),2);
break;
case 2: Worksheet->virtualmove(xstart,calculateFeldverlauf(0,0,xstart));
for (f=xstart;f<=xend;f+=step)
Worksheet-
>drawLine(f,calculateFeldverlauf(0,0,f),RGB(0,0,255),2);
break;
}
}

void CVersuch::Feldverlauf_3D (CDiagramme* Worksheet,int flag)
{ double stepx,stepy,f,g;
double xstart,xend,ystart,yend;
Worksheet->getranges(&xstart,&xend,&ystart,¥d);
if ((xstart==0) && (xend==0) && (ystart==0) && (yend==0))
{ switch (flag)
{ case 0: xstart=-teil.geta()*3;
xend=teil.geta()*3;
ystart=-teil.geta()*3;
yend=teil.geta()*3;
break;
case 1: xstart=-teil.geta()*3;
xend=teil.geta()*3;
ystart=-teil.getb()*3;
yend=teil.getb()*3;
break;
case 2: xstart=-teil.geta()*3;
xend=teil.geta()*3;
ystart=-teil.getb()*3;
yend=teil.getb()*3;
break;
}
Worksheet->setdiagrammaxes(xstart,xend,ystart,yend);
}
Worksheet->setmaxfarben(maxfarben);
Worksheet->putfunctionvalue(calculateFeldverlauf(teil.geta(),0,0));
Worksheet->putfunctionvalue(calculateFeldverlauf(0,teil.geta(),0));
Worksheet->putfunctionvalue(calculateFeldverlauf(0,0,teil.geta()));
stepx=Worksheet->x_Schrittweite_holen();
stepy=Worksheet->y_Schrittweite_holen();
switch (flag)
{ case 0: for (f=ystart;f<=yend;f+=stepy)
for (g=xstart;g<=xend;g+=stepx)
Worksheet-
>drawPixel(g,f,calculateFeldverlauf(g,f,0));
break;
case 1: for (f=ystart;f<=yend;f+=stepy)
for (g=xstart;g<=xend;g+=stepx)
Worksheet-
>drawPixel(g,f,calculateFeldverlauf(g,0,f));
break;
case 2: for (f=ystart;f<=yend;f+=stepy)
for (g=xstart;g<=xend;g+=stepx)
Worksheet-
>drawPixel(g,f,calculateFeldverlauf(0,g,f));
break;
}
Worksheet->drawdiagramm(TRUE);
}

void CVersuch::setmaxfarben(int wert)
{ maxfarben=wert;
}

void CVersuch::putvalueFELD(double wert, int pos)
{ if (wert>maxvalueFELD)
{ maxvalueFELD=wert;
maxvalueposFELD=pos;
}
}

void CVersuch::autofitt()
{ double maxascii=maxvalueASCII();
double diff,olddiff;
double wert;
maxvalueFELD=0;
for (int i=290;i<=821;i++)
putvalueFELD(calculateFeldverstaerkung(i),i);
olddiff=32768;
for (double f=10.0;f>=0.0;f-=0.1)
{ teil.setkorrekturfaktor((float)(f));
wert=calculateFeldverstaerkung(maxvalueposFELD);
diff=abs(maxascii-wert);
if (diff<=olddiff)
olddiff=diff;
else
{ teil.setkorrekturfaktor((float)(f+0.2));
goto ende;
}
}
ende: ;
}