Quantenmechanik/ Boson-Fermion

Identische Teilchen

Bearbeiten

Ein System aus mehreren Teilchen hat quantenmechanisch nicht etwa mehrere Wellenfunktionen, sondern eine gemeinsame im Tensorprodukt der Einteilchen-Hilbert-Räume. Nur wenn für Teilchen A bei x und B bei y keine Wechselwirkung   im Hamilton-Operator auftritt, ist ein Separations-Ansatz   erfolgreich. Allgemein gibt es Linearkombinationen von solchen Produkten, also verschränkte Teilchen:  

Teilchen wie Protonen, Elektronen oder ganze Atome haben nicht das geringste Merkmal, mit dem man sie individuell verfolgen kann. Gleiche Teilchen sind ununterscheidbar. Sie haben keine Pfade wie in der klassischen Physik. Sind Teilchen A und B identisch wie die zwei Elektronen des Helium-Atoms, dann stellt sich schon ohne Wechselwirkung eine Frage.

Die Wellen   und   sind degeneriert, es könnte also sein, dass ein ganzes Kontinuum von Funktionen

 

die selbe Physik beschreibt. Der Permutations-Operator   hätte dann keine definierten Eigenwerte?

Oder aber P hat eine einfache Darstellung,  , das heißt die Zweiteilchen-Funktion ist entweder symmetrisch oder antisymmetrisch beim Vertausch der Koordinaten, also mit Eigenwert 1 oder -1 zu P. Auf jeden Fall hätte P einen Eigenwert auf dem Einheitskreis, so dass die observablen Betragsquadrate invariant sind beim Paarvertausch?

Die Antwort der Natur ist kategorisch und wurde von Pauli formuliert. Die Mehrteilchen-Zustände N identischer Teilchen mit halbzahligem Spin, wie der Elektronen, haben als Darstellung der Permutationsgruppe den Faktor -1 bei Paarvertauschung. Teilchen mit dieser Antisymmetrie sind Fermionen. Teilchen mit ganzzahligem Spin, die Bosonen, haben den P-Eigenwert 1, sie haben also vertauschungs-invariante N-Teilchen-Zustände.

Unmittelbare Konsequenz ist das Pauli-Verbot: keine zwei Fermionen passen auf den selben Quantenzustand:  . Mittelbare Konsequenz ist der Aufbau der Atome der Kernladung Z in Schalen. Die Elektronen füllen nacheinander die aufsteigende Reihe der Energie-Niveaus, die bei der Berechnung eines Elektrons im Coulomb-Potenzial herauskommen.

Die Ursache des Spin-Statistik-Prinzips ist in der relativistischen Quantenfeldtheorie zu suchen. Die identischen Teilchen sind alle die elementaren Anregungen des selben Quantenfeldes. Der Spin ergibt sich aus einer Klassifizierung der Darstellungen der Lorentz-Gruppe. Die Vielteilchen-Zustände sollen einen Hilbert-Raum aufspannen (positives Skalarprodukt) und einen stabilen Grundzustand haben (beschränktes Spektrum der Energie). Nur die experimentell untermauerte Korrespondenz von Spin und Vertauschungs-Symmetrie ist dann widerspruchsfrei möglich.

Statistik

Bearbeiten

Angenommen, es gebe   Plätze oder Einzelniveaus für einzelne Teilchen. Jedem Teilchen gehöre ein Vektorraum der Dimension I mit einer Basis von Einteilchen-Zuständen  .

Naiv besteht ein Basissystem der Zustände von   verfolgbaren Teilchen aus allen Abbildungen  . Es gibt   Vektoren in der Basis des gewöhnlichen Tensorproduktes  . Sie beschreibt das System:

  erzeugt  .

Die Dimension ist die Zahl der linear unabhängigen Zuständsvektoren.

Mit Fermionen sind für jedes i nur zwei Besetzungen erlaubt, 0 oder 1. Falls  , sind die unabhängigen Zustände die Menge aller Teilmengen der Größe N, insgesamt   Zustände. Soviel Möglichkeiten gibt es, N Plätze aus den I verfügbaren auszuwählen. Der Vektorraum des Systems wird aufgespannt von allen total antisymmetrischen Tensorprodukten, ist also ein Teilraum  , definiert wie folgt.

Sei   die Gruppe aller N! Permutationen von  . Die Gruppe hat zwei elementare Homomorphismen zu den ganzen Zahlen,

  • den trivialen,   und
  • das Permutations-Vorzeichen   genau dann wenn
p aus einer ungeraden Zahl von Nachbar-Vertauschungen gebaut ist, 1 sonst.

Alle Paarvertauschungen, nicht nur die Transpositionen von Nachbarn, haben negatives  . Eine beliebige Permutation kann in ein Produkt aus Zyklen zerlegt werden. Ein Zyklus der Größe   hat das Vorzeichen  .

Der Antisymmetrie-Operator A auf   ist die lineare Fortsetzung von:

 

Der Vektorraum des Fermionsystems ist die Bildmenge  . A ist eine Projektion,  . Als Projektion hat A die Tendenz, Vektoren zu "verkürzen" und erhält daher nicht die Normen.

In der Ortsdarstellung geht die Vielteilchen-Welle aus Produkten hervor. Man wende den Operator A an auf  .

 

Eine für orthogonale Produkte norm-erhaltende Variante hat folgende Form:

 .

Diese Schreibweise einer N-Fermion-Wellenfunktion ist bekannt under dem Namen Slater-Determinante. Alle beteiligten Einteilchen-Wellen müssen linear unabhängig sein, damit sie nicht verschwindet. Die Slater-Determinanten eines Einteilchen-Orthonormalsystems bilden ein Vielteilchen-Orthonormalsystem.

Die Argumente   können allgemeiner Tupel sein aus Ortskoordinaten, Spin-Indizes und anderen Quantenzahlen. Bei N Elektronen können eventuell nur die Spin-Faktoren der Wellenfunktion antisymmetrisch sein; dann werden die Orts-Faktoren symmetrisch für die geforderte totale Antisymmetrie. Alle möglichen Kombinationen der Symmetrien mit Tupeln können mit der Darstellungstheorie der Permutationsgruppen (Young-Tableaus etc) klassifiziert werden.

Bei Bosonen darf man N "Ziehungen mit Zurücklegen" aus den I Einzelniveaus machen, was der Zahl von Möglichkeiten   entspricht.

Die immer wieder erquickliche Umformulierung beweist diese Kombinatorik:

Die N Kugeln sollen auf I Fächer   verteilt werden. Die Fächer kriegen (I-1) Trennwände, so dass jede Verteilung genau einer Folge aus (N+I-1) Dingen entspricht, entweder Kugel oder Wand. Gesucht ist die Zahl aller Möglichkeiten, die (I-1) Wände zu setzen. Das ergibt  .

Der Boson-Vektorraum ist der Unterraum der total symmetrischen Tensorprodukte in  , er ist die Bildmenge des Symmetrierung-Operators S. Operator   ist definiert wie folgt (linear zu erweitern):

 

Auch der Operator S ist eine Projektion. Eine norm-erhaltende Version für Produkte orthogonaler Funktionen wäre:  .

Der Grundzustand mit vielen Bosonen ist der, wo alle auf dem selben niedrigsten Energie-Niveau hocken: Bose-Einstein-Kondensation. Er hat mehr Gewicht bei insgesamt   im Vergleich zu den   klassisch markierbaren möglichen Zustands-Dimensionen.

Die Multi-Fermion- und Multi-Boson-Zustände liegen in Eigenräumen zum Eigenwert 1 der Operatoren A bzw. S. Der Hamilton-Operator und alle Operatoren von Observablen sollten diesen Zustandsraum nicht verlassen können und sollten mit allen Permutations-Operatoren von Teilchenpaaren (Transpositionen) kommutieren. Es ist auch nicht möglich, dass ein System aus gleichen Teilchen sein Verhalten dynamisch ändert, von Symmetrie zu Antisymmetrie oder zurück.

(In der spekulativen Physik gibt es Super-Symmetrien mit Operatoren, die Bosonen und Fermionen ineinander umwandeln! Bisher wurde nichts dergleichen in der Natur gefunden.)

Auf der direkten Summe aller Boson-Vektorräume zu allen Teilchenzahlen

 

gibt es ein Produkt. Es wird auf Monomen von Produktzuständen von N bzw. M Teilchen als   definiert, bilinear fortzusetzen auf alle Polynome. Das Produkt ist assoziativ und kommutativ; der Boson-Raum ist damit eine Kommutative Algebra. Die erste Dimension von komplexen Zahlen wird hinzugenommen und ist physikalisch der Zustand des Vakuums, das null Teilchen enthält. Damit hat die Algebra ein Einselement.

Auf der direkten Summe der Fermion-Vektorräume zu allen Teilchenzahlen

 

ist das entsprechende Produkt auf Monomen von N bzw. M Teilchen als   definiert, bilinear fortzusetzen auf alle Polynome. Das Produkt ist assoziativ und alternierend. Der Fermion-Raum ist damit eine Grassmann-Algebra. Die Vertauschung funktioniert mit der Vorzeichenregel:

 .

Zwei Monome mit ungeraden Einteilchen-Faktoren antikommutieren, alle anderen Paare kommutieren.

Die beiden Algebren haben einen Grad bei Monomen, die Zahl der elementaren Faktoren (wie bei gewöhnlichen Polynomen der Homogenitäts-Grad). Sie werden graduierte Algebren genannt. Der Grad ist additiv bei Multiplikation von homogenen Elementen. Viele Operatoren auf den Algebren variieren den Grad um 0,+1,-1 Einheit. Manche agieren auf Produkten mit einer Leibniz-Regel, ähnlich zur Ableitung vom Produkt zweier Funktionen; sie heißen dann Derivationen bzw. Anti-Derivationen.

Exponential-Verteilung

Bearbeiten

In den einfachsten klassischen Modellen der statistischen Mechanik sind die Energie-Zustände der Teilchen exponentiell verteilt. Die relative Häufigkeit der Teilchen mit Energie  .

Quantenmechanisch gibt es weit weniger 'Freiheitsgrade', wie schon aus der Abzählung der Basen hervorging. Pauli verbietet den Fermionen die Doppelbelegung eines Niveaus, und auch bei Bosonen zählen gleiche Partikelbelegungen der Niveaus nur als ein einziger Zustand.

Ein Multi-Boson-Zustand ist eine Folge   ganzer Zahlen; seine Häufigkeit ist  . Interessant ist die relative Häufigkeit von Niveau  , wofür der Erwartungswert von   aus der Verteilung   zu berechnen ist.

 

Faktoren   können aus allen   gestrichen werden. Es bleibt mit  :

 .
 
 

Ein Multi-Fermion-Zustand ist eine Folge   die nur aus den Werten 0 und 1 besteht. Die Wahrscheinlichkeit für ein Teilchen auf dem Niveau i wird dann ganz analog mit Summen über {0,1} statt   :

 

??? Normierung? Diese Verteilung wird nahezu Null für E_i weit oberhalb der thermischen Energie k_BT=1/\beta, nahezu konstant für Energien weit darunter? negative?

Zusammenfassung

  • Klassische Verteilung  .
  • Fermi-Dirac-Verteilung  
  • Bose-Einstein-Verteilung  

Periodensystem

Bearbeiten
 
Radiale Dichte der Elektronenladung von Edelgas-Atomen. Zeigt den Aufbau des Elektronensystems in Schalen

Nach dem Pauli-Prinzip bauen sich die Atome um einen Kern der Ladung Z auf. In erster Näherung belegt das erste Elektron das niedrigste Energieniveau von den Lösungen im Coulomb-Potenzial. Die weiteren Elektronen belegen höhere Plätze. Sie sehen ein verformtes Potenzial wegen der Abschirmung des Kerns durch alle anderen Elektronenwolken.

Die einfachste Näherung wäre, für alle Z Elektronen das selbe mittlere radiale Potenzial   einzusetzen. Der vereinfachte Hamilton-Operator wäre

 .

Die Wellenfunktionen kämen aus einer Basis der Slater-Determinanten von wasserstoff-ähnlichen Lösungen.

Mit besseren Methoden und Computer-Hilfe konnte die Wellenmechanik nach Schrödinger und Pauli die Grundzustände aller Atome des Periodensystems naturgetreu berechnen. Die Entartung aller (n,l) zu gleichem n wird durch das kollektive Potenzial aufgehoben. Die Reihenfolge, in der die Paare (n,l) das höchste belegte Niveau stellen, konnte genau bestätigt werden.

Die folgende Tabelle zeigt die Ordnung der Niveaus mit Hauptquantenzahl 1-6 und Drehimpuls 0-3 (spdf), wie sie mit steigender Energie gefüllt werden. Bei gegebener Hauptquantenzahl haben die Drehimpulse s,p,d,f, zusammen mit den Paaren vom Elektronenspin, je 2,6,10,14 Zustände mit fast gleicher Energie. Jede Reihe beginnt mit einem Alkali-Atom und endet mit einem Edelgas. Vor dem Edelgas steht jeweils ein Halogen. Das Edelgas mit seiner stabilen Elektronenschale ist chemisch inert. Das Alkalimetall gibt reaktionsfreudig sein vereinzeltes Elektron ab. Genauso begierig nimmt das Halogen ein Elektron auf, um die Edelgaskonfiguration zu erreichen. Die theoretische und numerische Chemie ist nichts anderes als angewandte Quantenmechanik.

Niveaus Anzahl Elemente
1s 2 H He
2s 2p 2+6 Li ... F Ne
3s 3p 2+6 Na ... Cl Ar
4s 3d 4p 2+10+6 K ... Br Kr
5s 4d 5p 2+10+6 Rb ... I Xe
6s 4f 5d 6p 2+14+10+6 Cs ... At Rn

Die Konfigurationen der Elektronen der Alkalimetalle Natrium und Kalium und des Halogen-Atoms Chlor sehen schematisch aus wie folgt.

 
Konfiguration Na
 
Konfiguration Cl
 
Konfiguration K

Thomas-Fermi-Modell

Bearbeiten

Dies ist ein vereinfachtes Modell für das kollektive Zentralpotenzial V(r), das von den Elektronen um einen Kern der Ladung Z gefühlt wird. Gefordert:

  • Asymptotisch für  
  • Für  
  •   (Elektron-Dichte im Grundzustand)
  •  

V ist am Zentrum von der Kernladung bestimmt und anderswo von der Ladungsdichte der gesamten Z Elektron-Wellen-Faktoren. Diese stecken in einer Slater-Determinante, die den Grundzustand annähert.

Nun kommt eine halb-klassische Idee hinzu: die Dichte von gebundenen Quantenzuständen im Phasenraum. In der WKB-Näherung sind die Energie-Niveaus des eindimensionalen Modells gequantelt nach der Regel:

 .

Die Ebene der Punkte   heißt der Phasenraum, seine allgemeine Version für N Freiheitsgrade hat die Dimension 2N.

Mit   kann die Quantelung so beschrieben werden: Das klassische System im Potenzialtopf oszilliert zwischen zwei Umkehrpunkten   und beschreibt geschlossene Kurven im Phasenraum  . Zuerst mit   für x von a bis b, dann zurück mit   für x von b nach a. Das Integral über eine Runde ist die umrundete Fläche in der  -Ebene.

 .

Einer Stufe der Energie E entspricht ein Zuwachs von "Volumen im Phasenraum"   vom Wert h. In drei Dimensionen wächst der Phasenraum um den Wert   zwischen Energieniveaus. Die Quantenmechanik schreibt also den gebundenen Fermionen wegen des Pauli-Verbots vor, mit einer konstanten Packungsdichte   den Phasenraum aufzufüllen, angefangen mit dem niedrigsten Energie-Niveau. Der Faktor 2 zählt die 2 Dimensionen des Spins.

Nach dem Thomas-Fermi-Modell sind die Energiezustände im 6-dimensionalen Phasenraum   lokalisiert mit der Dichte   falls die Energie   kleiner ist als das maximal besetzte Niveau  . Man darf   festlegen, denn eine Verschiebung ändert nicht das Verhalten von   am Nullpunkt. Der Faktor 2 berücksichtigt die zwei Spin-Richtungen der Elektronen. Die Elektronendichte im Raum:

 
 .

Die Dichte   hängt also von   ab und ist positiv wenn  , Null sonst. Es gilt also diese Differenzialgleichung für  :

 .

Es werden   durch dimensionslose Variablen   ersetzt:

 
  mit dem Grenzwert   wegen  .

Damit:   im Gebiet  .
Die Differenzialgleichung für u lautet in der Kugel wo   positiv ist:

 .

Wann kommt die erste Nullstelle   von u(x)? Ausgerechnet wird dazu eine Normierung von u, die daraus folgt dass   sich zu Z summiert:

 .

Daraus folgt   an der Nullstelle. Das weist darauf hin, dass   bei Unendlich liegt.   ist also zu lösen mit den zwei Randbedingungen  . Ein Skript im Anhang integriert die Gleichung numerisch und macht den Graphen als SVG-Datei.

Aus der Funktion u() folgen die radialen Potenziale   und Ladungsdichten  , die unter der Annahme   großer Atome angenähert beschreiben, wie dicht die Elektronen sich drängeln dürfen. Man definiert einen Atomradius   als die Kugel, in der der Bruchteil   der Elektronenladung ist. Typischerweise  , also die Kugel für alle bis auf ein Elektron. Gleichung:  . Mit dimensionslosem  , ergibt sich X als numerische Lösung von  . Ergebnis: R variiert recht langsam mit steigendem Z. Der Phasenraum wird schneller in der Impuls- als in der Orts-Dimension aufgeblasen.

Das Skript integriert numerisch die Gleichung   mit der Probeschuss-Technik wie folgt, ohne Anspruch auf hohe Präzision:

  • Intervall   wird in 100 gleiche Schritte d=0.01 geteilt.

Der typische Rechenschritt bestimmt   aus  

  • Intervall   wird als geometrische Folge in 1% große Schritte geteilt.

Hier ist u zur Funktion   umgeschrieben und die Rechenschritte sind die Differenz-Version von  .
Es wird   festgesetzt und   mit Dichotomie variiert, bis am Ende   herauskommt, von Rundungsfehlern abgesehen. Die SVG-Grafik zeigt die Funktion mit logarithmischer x-Achse.

Anhang: Skript

Bearbeiten

Skript fürs Thomas-Fermi-Modell. Schreibt eine Datei thomferm.svg.

'''
Thomas-Fermi potential model.
solve x(f")^2 = f^3 on interval [0,inf), f(0)=1, f(1)=0
implemented direct shoot algorithm with log section:
f(x)=F(y); y=log(x); x=exp(y); f'=F'/x; f"= F"/x^2-F'/x^2=(F"-F')/(xx)
F"-F'= xx sqrt(F^3/x)= (F*x)^(3/2) = (F*exp(y))^(3/2)= z
(F(2)+F(0)-2F(1))/(dd)-(F(2)-F(0)/(2d) = z
(1-d/2)F(2)/dd = z + (2F(1)-F(0))/dd - F(0)/(2d) 
(1-d/2)F(2)= ddz+ 2F(1)- (1+d/2) F(0)
'''

from math import sqrt,exp,log
def div(p,q) : return int(p/q)

###### plot

class svgdump :
  def plotbegin(sd, w,h,f) : # args: width height zoomfactor
    W=str(w); H=str(h); u=''; fw=str(f*w); fh=str(f*h)
    s=( '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'+
     '<!DOCTYPE svg>\n'+
     '<svg xmlns="http://www.w3.org/2000/svg"\n'+
     '  xmlns:xlink="http://www.w3.org/1999/xlink"\n'+
     '  width="'+W+'" height="'+H+'" viewBox="0 0 '+fw+' '+fh+'">\n')
    return s

  def plotend(sd) : return '</svg>\n'
  def move(sd,x,y) : return 'M'+str(x)+','+str(y)
  def line(sd,x,y) : return 'L'+str(x)+','+str(y)
      
  def labl(sd,s,x,y, size=14,fill='#000') :
    f=' font-family="Arial"'
    t='<tspan x="'+str(x)+'" y="'+str(y)+'">'+s+'</tspan>'; fsz= str(size)
    return ('<text fill="'+fill+'"'+f+' font-size="'+fsz+'px">'+t+'</text>\n')

  def path(sd,w,s,lc='#000') : # path w=with lc=linecolor
    t='<path fill="none" stroke="'+lc+'" stroke-width="'+str(w)+'" '
    t+= ' stroke-linecap="round" ' 
    return t + 'd="\n'+s+'" />\n'

# end class svgdump

def aprx(x) : # 3-digit approximation
  y= (-x) if(x<0) else x; z= int(1e3*y+1e-3); z= (-z) if (x<0) else z
  return z/1000.0

def curve(sd,scale,xy, fill='#000', width=1) :
  (xs,fx,xmin, ys,fy,ymin) = scale; s=''; n= div(len(xy),2) 
  for i in range(n) : 
    x= aprx(xmin+fx*(xy[2*i]-xs)); y= aprx(ymin+fy*(xy[2*i+1]-ys))
    s+= sd.move(x,y) if(i==0) else sd.line(x,y)
  return sd.path(width,s,lc=fill)

def label(sd,scale,txt,tx,ty) : # tx,ty plot coordinates not pixels
  (xs,fx,xmin, ys,fy,ymin) = scale 
  x= aprx(xmin+fx*(tx-xs)); y= aprx(ymin+fy*(ty-ys))
  return sd.labl(txt,x,y)

###########

def shootlog(y,f,i,k) : # x=exp(y) version
  d=y[i]-y[i-1]; z=f[i]; j=i; p=1.0-0.5*d; q=1.0+0.5*d
  while (j<k) and (z>=0) and (z<10) : # stop if out of bounds
    t=exp(y[j])*z;  z=sqrt(t*t*t)
    u= d*d* z + 2*f[j]-q*f[j-1]
    f[j+1]= u/p; y[j+1]=y[j]+d; j+=1; z=f[j]
  return j,z  # print(str(f[j+1]))

def shootlin(x,f,i,k) : # i=1, f[0] and f[1] known, x[0]=0, x[1]=d.
  d=x[i]-x[i-1]; j=i; z=f[j]
  while (j<k) and (z>=0) and (z<10) :
    u= d*d* sqrt(z*z*z/x[j])
    f[j+1]= u+2*z-f[j-1]; x[j+1]=x[j]+d; j+=1; z=f[j]
  return j,z    # print(str(f[j+1]))

def logplot(fn,x,f,y,g) : # log x axis, y axis 0 to 1.
  txt=['Function y\"= sqrt(y^3/x), y(0)=1.',
    'xscale log 0.01...100','yscale 0...1']
  n=len(x); m=len(y); ok=(g[1]==f[n-1]); k=0; xy=[0.0]*(2*n+2*m)
  if not ok : print('logplot no join'); exit()
  for i in range(1,n) : xy[k]=log(x[i]);xy[k+1]=f[i]; k+=2
  for i in range(2,m) : xy[k]=y[i]; xy[k+1]=g[i]; k+=2
  xmin=log(0.01); xmax=log(100); ymin=0; ymax=1.0; xy=xy[:k]
  xyf=[ xmin,ymin, xmax,ymin, xmax,ymax, xmin,ymax, xmin,ymin ] # frame
  xg=[1,2,4,6,8]; fg=[0.01,0.1,1,10,100]; z=0; 
  lbl=['0.01','0.1','1','10','100']
  for i in range(len(fg)) :
    for k in range(len(xg)) :
      f=fg[i]; g=f*xg[k]; h=log(g)
      if (i==0)and(k==0) : xp=xmin; z=0
      elif (h<=xmax)and(z==0) : xyf += [xp,ymin,h,ymin,h,ymax];xp=h; z=1
      elif (h<=xmax)and(z==1) : xyf += [xp,ymax,h,ymax,h,ymin];xp=h; z=0
  xys=[xyf,xy]
  xs,fx,xpix= xmin, 750/(xmax-xmin),25 # scale user units, min in pixels
  ys,fy,ypix= ymin,-550/(ymax-ymin),575 ; scale=(xs,fx,xpix, ys,fy,ypix)
  colo=['#777','#000','#00a','#077','#0a0','#770','#a00']
  sd=svgdump(); buf=sd.plotbegin(800,600,1); i=0; dy=(ymax-ymin)/20.0
  for j in range(len(txt)) :
    buf += label(sd,scale, txt[j], (xmin+xmax)*0.5,ymax-dy-j*dy)
  for j in range(len(lbl)) :
    buf += label(sd,scale, lbl[j], log(fg[j]),ymax)
  for t in xys : buf += curve(sd,scale, t, fill=colo[i%7]); i +=1
  g=open(fn+'.svg','w'); g.write(buf+sd.plotend()); g.close()

def shooter() : # dichotomic shots to solve equation
  # adjust f[1] to hit target
  # logscale y,g(y) after initial x,f(x) linear section 
  n=50; n1=n+1; x=[0]*n1; f=[0]*n1; x[0]=0;x[1]=0.01; f[0]=1; fhi=1; flo=0.5
  m=300; m1=m+1; y=[0]*m1; g=[0]*m1; logsection=True
  targ=1e-8; ff=0.5*(fhi+flo); f[1]=ff; zhi=10; zlo=-1; 
  i=0; busy=True;zbefore=1
  while busy and (i<100) :
    j,z= shootlin(x,f,1,n); print(str([f[1],j,z]))
    if logsection and (z>0)and(z<1) :
      g[0]=f[j-1]; g[1]=f[j]; y[0]=log(x[j-1]); y[1]=log(x[j])
      k,z= shootlog(y,g,1,m); xmax=exp(y[k]); print('log: '+str([xmax,k,z]))
    if z>targ : fhi=ff;zhi=z 
    else : flo=ff;zlo=z
    ff=0.5*(fhi+flo);
    if (zlo>0)and(zlo<zhi)and(zhi<1) : ff= flo+(targ-zlo)*(fhi-flo)/(zhi-zlo)
    f[1]=ff; i+=1; busy= (abs(z-zbefore)>1e-8); zbefore=z
  print('Done at i='+str(i))
  logplot('thomferm', x,f,y,g)
  atomradius('bla', x,f,y,g)

def atomradius(fn,x,f,y,g) : # solve x(a): u(x)-xu'(x)=a where a=0.01..0.1
  # u-xu'= u[i]-xx[i]*(u[i+1]-u[i-1])/(xx[i+1]-xx[i-1])
  n=len(x); m=len(y); k=0; xx=[0.0]*(n+m);u=[0.0]*(n+m); v=[0.0]*(n+m)
  for i in range(1,n) : xx[k]=x[i];u[k+1]=f[i]; k+=1
  for i in range(2,m) : xx[k]=exp(y[i]); u[k+1]=g[i]; k+=1
  vmax,jmax,vmin,jmin= -1e6,0,1e6,0
  for j in range(1,k-1) :
    v[j]= u[j]-xx[j]*(u[j+1]-u[j-1])/(xx[j+1]-xx[j-1])
    if v[j]>vmax: vmax,jmax= v[j],j
    if v[j]<vmin: vmin,jmin= v[j],j
  if False : #debug
    print('v='+str([v[1],v[50],v[100],v[k-2]]))
    print('vmax,xmax='+str([vmax,xx[jmax]]))
    print('vmin,xmin='+str([vmin,xx[jmin]]))
  print('Percent electron charge; Radius of ball')
  for p in range(1,21) : # p=percentage
    a=0.01*p ; j=jmax
    while v[j]>a : j+=1
    xa=xx[j-1];xb=xx[j]; va=v[j-1];vb=v[j]
    xp=xa+(a-va)*(xb-xa)/(vb-va); print('p,xp='+str([100-p,xp]))  

### following stuff not working

def geterror(f,y,err, n) :
  d=1.0/n
  for i in range(1,n) :
    x=y[i]; z=1.0-x; a=f[i]; f3=a*a*a
    f1=(f[i+1]-f[i-1])/(2.0*d); f2=(f[i+1]+f[i-1]-2*f[i])/(d*d)
    b=f2-2*z*f1; c=x*z*z*b*b; err[i]= f3-c

def shootstep(y,f,i,n) : # get f[i+1] for zero error.
  d=1.0/n; x=y[i]; z=1.0-x; a=f[i]; f3=a*a*a;
  # init bracket problem minimum find
  def err(i,ff) :
    f1=(ff-f[i-1])/(2.0*d); f2=(ff+f[i-1]-2*f[i])/(d*d)
    b=f2-2*z*f1; c=x*z*z*b*b; return f3-c
  # shoot is initialized with f[0] and f[1], the first slope
  def bugsweep(i,fh,eh) : # nearly degen pair of zeroes!
    df=1e-2; fmin=fh;emin=1e9
    for k in range(25) :
      ff=fh+(k-10)*df; ef=err(i,ff);
      fmin,emin = (ff,ef) if (abs(ef)<emin) else (fmin,emin)
      print('bug k,ff,ef='+str([k-10,ff,ef]))
    df=1e-3; fs=fmin; ok=False; fl=fmin;el=emin
    for k in range(25) :
      ff=fs+(k-10)*df; ef=err(i,ff)
      print('bug2 k,ff,ef='+str([k-10,ff,ef]))
      if (not ok) and ((ef*eh)<0) : ok=True; fl=ff;el=ef
    return fl,el
  #
  def descent(i,fh) :
    # search for bracket for f[i+1], fh<0 search a point >0
    eps=0.001; df= max(abs(eps*fh),eps); fl=fh-df; j=0; nf=0
    eh= err(i,fh); el=err(i,fl); found=(el*eh)<0; q=el/eh
    if (not found) and (q>1) : df=-df; fl=fh-df; el=err(i,fl)
    #print('i,eh,el,fh,fl='+str([i, eh,el, fh,fl]))
    while (j<100)and(not found) :
      q=el/eh
      #if q>1 : df=-0.5*df; fl -= df; nf+=1; print('flip j,eh,el='+str([j,eh,el]))
      if q>0.9 : df= 4*df; fl -=df
      elif q>0.5 : df= 2*df; fl -=df
      else : fl -= df
      el=err(i,fl); found=(el*eh)<0; j= 100 if (nf>4) else (j+1)
    if not found : fx,ex= bugsweep(i,fh,eh); 
    # print('i,j,eh,el,fh,fl='+str([i,j, eh,el, fh,fl]))
    return fl,el,j
  #
  fh=a; eh= err(i,fh); ok=True; k=0
  fl,el,j =descent(i,fh)
  while (k<20)and(ok) : # this part working, slow convergence
    if (eh*el)>=0 : ok=False;print('shoot exit i,k='+str(i)+','+str(k))
    ff= (fh*el-fl*eh) / (el-eh); ef=err(i,ff)
    if ef*eh>0 : fh=ff; eh=ef
    else : fl=ff; el=ef
    k +=1
  if ok : f[i+1]=ff; print('i,j,k, ff,ef='+str([i,j,k,ff,ef]))
  return ok

def smooth(x) :
  n=len(x); n1=n-1; y=[0]*n
  for i in range(1,n1) : y[i]=(2.0*x[i]+x[i-1]+x[i+1])/4.0
  return y

# def downerr(y,f,g,y,ef,eg, n) :
# tweak f[i],g[i] so that err at [i-1] doesnt worsen 

def explore(n) :
  d=1.0/n;n1=n+1; f=[0]*(n+1); g=[0]*n1; y=[0]*n1; f[0]=1; f[n]=0; 
  for i in range(n+1) : f[i]= 1.0-d*i; y[i]=d*i; g[i]=f[i] - 0.7*y[i]*f[i]
  print('start end', str([f[0],g[0],f[n],g[n]]))
  errf=[0]*n1; errg=[0]*n1; h=[0]*n1; errh=[0]*n1; h[0]=1
  geterror(f,y,errf, n); ef=smooth(errf); ef=errf
  geterror(g,y,errg, n); eg=smooth(errg); eg=errg
  for i in range(1,n) : h[i]=(f[i]*eg[i]-g[i]*ef[i]) / (eg[i]-ef[i])
  for i in range(1,n) : h[i]=(f[i]+g[i])/2.0
  geterror(h,y,errh,n) # secant fails, with eg,ef worse than average
  #for i in range(1,n) :
  #  print(str([i,errf[i],errg[i],errh[i]]))
  for i in range(1,n) : ok= shootstep(y,g,i,n)

# explore(20)
shooter()