E-school di Arrigo
Amadori
Calcolo numerico
Atomo di idrogeno
soluzione esatta non relativistica
Le formule utilizzate dal programma sono riportate in tutti i testi di meccanica quantistica. Nel grafico che si ottiene, maggiore è la probabilità per l'elettrone, più acceso è il colore rosso.
Sorgenti PHP :
atomoidrogeno.php
<html>
<head>
<title>Atomo di idrogeno</title>
</head>
<body>
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
// parametri in input
//
// $n = numero quantico principale
// $l = numero quantico azimutale
// $m = numero quantico magnetico
// $ampl = amplificazione probabilità
// $lar = larghezza immgine in pixel
// $alt = altezza immagine in pixel
// $xa = inizio dominio x
// $xb = fine dominio x
// $ya = inizio dominio y
// $yb = fine dominio y
//
// parametri in output
//
// crea l'immagine PNG e ne visualizza il link
//
// inserisce tutti gli include (funzioni esterne)
if (is_integer(strpos($SERVER_SOFTWARE, "Win")))
{
include("..\Routines\sgn.php");
include("..\Routines\polLaguerreGeneral.php");
include("..\Routines\polLegendreAssocIncompl.php");
include("..\Routines\fattoriale.php");
include("..\Routines\coeffBinom.php");
include("..\Routines\potBinom.php");
include("..\Routines\derivPolin.php");
include("..\Routines\daVbAPow.php");
include("..\Routines\polSimbVett.php");
include("..\Routines\polVettSimb.php");
}
else
{
include("../Routines/sgn.php");
include("../Routines/polLaguerreGeneral.php");
include("../Routines/polLegendreAssocIncompl.php");
include("../Routines/fattoriale.php");
include("../Routines/coeffBinom.php");
include("../Routines/potBinom.php");
include("../Routines/derivPolin.php");
include("../Routines/daVbAPow.php");
include("../Routines/polSimbVett.php");
include("../Routines/polVettSimb.php");
}
// controlli vari
if ($n <= 0)
{
echo "Attenzione !!! Deve essere n > 0 !!!" . "<p>";
return;
}
if ($l < 0 Or $l > $n - 1)
{
echo "Attenzione !!! Deve essere 0 <= l <= n - 1 !!!" . "<p>";
return;
}
if ($m < -$l Or $m > $l)
{
echo "Attenzione !!! Deve essere -l <= m <= l !!!" . "<p>";
return;
}
// parametri di scala
$dx = ($xb - $xa) / ($lar - 1); // intervallo di scomposizione asse x
$dy = ($yb - $ya) / ($alt - 1); // intervallo di scomposizione asse y
// disegno frame con coordinate
$im = ImageCreate ($lar + 100, $alt + 100);
$bianco = ImageColorAllocate ($im, 255, 255, 255);
$nero = ImageColorAllocate ($im, 0, 0, 0);
$rosso = ImageColorAllocate ($im, 255, 0, 0);
$verde = ImageColorAllocate ($im, 0, 255, 0);
$blu = ImageColorAllocate ($im, 0, 0, 255);
Imageline ($im, 0, 0, $lar, 0, $nero);
Imageline ($im, 0, $alt, $lar, $alt, $nero);
Imageline ($im, 0, 0, 0, $alt, $nero);
Imageline ($im, $lar, 0, $lar, $alt, $nero);
ImageString ($im, 1, 0, $alt + 10, $xa . " (x)", $nero);
ImageString ($im, 1, $lar, $alt + 10, $xb, $nero);
ImageString ($im, 1, $lar + 10, $alt, $ya . " (y)", $nero);
ImageString ($im, 1, $lar + 10, 0, $yb, $nero);
ImageString ($im, 2, 0, $alt + 30, "numero quantico principale n = " . $n, $nero);
ImageString ($im, 2, 0, $alt + 50, "numero quantico azimutale l = " . $l, $nero);
ImageString ($im, 2, 0, $alt + 70, "numero quantico magnetico m = " . $m, $nero);
if ($xa < 0) // disegna asse y se dentro intervallo
{
Imageline ($im, abs($xa) / $dx, 0, abs($xa) / $dx, $alt, $nero);
ImageString ($im, 1, abs($xa) / $dx, $alt + 10, "0", $nero);
}
if ($ya < 0) // disegna asse x se dentro intervallo
{
Imageline ($im, 0, $alt - abs($ya) / $dy, $lar, $alt - abs($ya) / $dy, $nero);
ImageString ($im, 1, $lar + 10, $alt - abs($ya) / $dy, "0", $nero);
}
// determina polinomi
$polLeg = polLegendreAssocIncompl($m, $l);
// mette le parentesi
$polinomio = $polLeg;
$polinomio = str_replace("*u^", "*(u)^", $polinomio);
do
{
$contr = 0;
for ($i = 1; $i <= strlen($polinomio); $i++)
{
$c1 = substr($polinomio, $i - 1, 1);
$c2 = substr($polinomio, $i, 1);
if ($c1 == "^" and $c2 <> "(")
{
$contr = 1;
$esp = "";
for ($j = $i + 1; $j <= strlen($polinomio); $j++)
{
$c = substr($polinomio, $j - 1, 1);
If ($c == "+" or $c == "-")
{
break;
}
$esp = $esp . $c;
}
$polinomio = substr($polinomio, 0, $i) . "(" . $esp . ")" . substr($polinomio, $j - 1);
}
}
if ($contr == 0)
{
break;
}
} while(TRUE);
// da ^ a pow
$polinomio = daVbAPow($polinomio);
$polLeg = $polinomio;
//echo "leg " . $polLeg . "<p>";
$polLag = polLaguerreGeneral(2 * $l + 1, $n + $l);
// mette le parentesi
$polinomio = $polLag;
$polinomio = str_replace("*u^", "*(u)^", $polinomio);
do
{
$contr = 0;
for ($i = 1; $i <= strlen($polinomio); $i++)
{
$c1 = substr($polinomio, $i - 1, 1);
$c2 = substr($polinomio, $i, 1);
if ($c1 == "^" and $c2 <> "(")
{
$contr = 1;
$esp = "";
for ($j = $i + 1; $j <= strlen($polinomio); $j++)
{
$c = substr($polinomio, $j - 1, 1);
If ($c == "+" or $c == "-")
{
break;
}
$esp = $esp . $c;
}
$polinomio = substr($polinomio, 0, $i) . "(" . $esp . ")" . substr($polinomio, $j - 1);
}
}
if ($contr == 0)
{
break;
}
} while(TRUE);
// da ^ a pow
$polinomio = daVbAPow($polinomio);
$polLag = $polinomio;
//echo "lag " . $polLag . "<p>";
// definizione colori
for ($i = 0; $i <= 255; $i++)
{
$colore[$i] = ImageColorAllocate ($im, $i, 0, 0);
}
// calcolo e disegno densità di probabilità
$nn = 0;
$nnn = 0;
$probmax = -999999999;
$probmin = 999999999;
for ($i = 0; $i <= $lar; $i++)
{
for ($j = 0; $j <= $alt; $j++)
{
$x = $xa + $i * $dx;
$y = $ya + $j * $dy;
$r = sqrt($x * $x + $y * $y);
if ($y == 0)
{
$teta = pi() / 2;
}
else
{
$teta = atan($x / $y);
}
if ($teta < 0)
{
$teta = pi() + $teta;
}
$f = $polLeg;
$f = str_replace("u", '$x1', $f);
$x1 = cos($teta);
eval("\$ff = @($f);");
$valLeg = $ff * pow(sin($teta), abs($m));
$f = $polLag;
$f = str_replace("u", '$x1', $f);
$x1 = 2 * $r / $n;
eval("\$ff = @($f);");
$valLag = $ff;
$densprob = 1 / (2 * pi());
$densprob = $densprob * ((2 * $l + 1) * fattoriale($l - abs($m))) / (2 * fattoriale($l + abs($m)));
$densprob = $densprob * pow($valLeg, 2);
$densprob = $densprob * (4 / pow($n, 4)) * fattoriale($n - $l - 1) / pow(fattoriale($n + $l), 3);
$densprob = $densprob * exp(-2 * $r / $n) * pow(2 * $r / $n, 2 * $l);
$densprob = $densprob * pow($valLag, 2);
if ($densprob < $probmin)
{
$probmin = $densprob;
}
if ($densprob > $probmax)
{
$probmax = $densprob;
}
$dp[$i][$j] = $densprob;
}
}
for ($i = 0; $i <= $lar; $i++)
{
for ($j = 0; $j <= $alt; $j++)
{
//$gradorosso = intval(255 * pow($ampl * $dp[$i][$j], 1 / $linear));
$gradorosso = intval(255 * pow(($dp[$i][$j] - $probmin) / ($probmax - $probmin),1/$ampl));
$rcolore = $colore[$gradorosso];
if ($gradorosso <= 0)
{
$rcolore = $nero;
}
if ($gradorosso > 255)
{
$rcolore = $bianco;
}
imageline ($im, $i, $j, $i, $j, $rcolore);
}
}
//echo "nnn " . $nnn . "<p>";
//echo "probab. min e max : " . $probmin . " " . $probmax . "<p>";
// disegna immagine
$nomefile = $REMOTE_ADDR;
$nomefile = "grafico" . str_replace(".", "-", $nomefile). ".png";
ImagePng ($im, $nomefile);
echo " <p>";
echo " <p>";
echo " <p>";
echo " <p>";
echo "<a href='$nomefile'>Visualizza il grafico</a>";
</script>
</body>
</html>
sgn.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function sgn($x)
{
// funzione sgn
// x = variabile indipendente
if ($x > 0)
{
return +1;
}
if ($x == 0)
{
return 0;
}
if ($x < 0)
{
return -1;
}
} // fine sgn()
</script>
polLaguerreGeneral.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function polLaguerreGeneral($m, $n)
{
// determina il polinomio di Laguerre generalizzato di grado m su n
// Lm,n(x)=Am,n(x)*Bm,n(x)
// Am,n = (-1)^m*(n!/(n-m)!)*exp(x)*x^(-m)
// Bm,n = der(n-m)(exp(-x)*x^n) (dove der(k) sta per derivata kappesima)
// utilizzando la formula di ricorrenza per determinare Bm,n :
// der(0) --> exp(-x)*x^n
// der(1) --> exp(-x)*(n*x^(n-1)-x^n)
// der(2) --> exp(-x)*(n*(n-1)*x^(n-2)-2*n*x^(n-1)+x^n)
// der(3) --> exp(-x)*(n*(n-1)*(n-2)*x^(n-3)-3*n*(n-1)*x^(n-2)+3*n*x(n-1)+x^n)
// ... ... ... ... ... ...
// la funzione ritorna il polinomio in forma simbolica (variabile indip. = u)
$rf = "";
// test di validità
if ($m < 0)
{
echo "(polLaguerreGeneral)Attenzione !!! deve essere m >= 0 !!!" . "<p>";
return;
}
if ($m > $n)
{
echo "(polLaguerreGeneral)Attenzione !!! deve essere m <= n !!!" . "<p>";
return;
}
$der = $n - $m;
if ($der == 0)
{
$i = pow(-1, $m) * fattoriale($n);
If ($i > 0)
{
$i = "+" . $i;
}
$rf = $i . "*u^0";
return $rf;
}
for ($i = 1; $i <= $der; $i++)
{
$coeff[$i] = 1;
for ($j = 0; $j <= $der - $i; $j++)
{
$coeff[$i] = $coeff[$i] * ($n - $j);
}
}
$coeff[$der + 1] = 1;
for ($i = 1; $i <= $der + 1; $i++)
{
$coeff[$i] = $coeff[$i] * coeffBinom($der, $i - 1) * pow(-1, $i + 1);
$coeff[$i] = $coeff[$i] * pow(-1, $m) * (fattoriale($n) / fattoriale($n - $m));
if ($coeff[$i] >= 0)
{
$coeff[$i] = "+" . abs($coeff[$i]);
}
else
{
$coeff[$i] = "-" . abs($coeff[$i]);
}
}
$rf = "";
for ($i = 0; $i <= $n - $m; $i++)
{
$rf = $rf . $coeff[$i + 1] . "*u^" . $i;
}
return $rf;
} // fine polLaguerreGeneral()
</script>
polLegendreAssocIncompl.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function polLegendreAssocIncompl($m, $n)
{
// determina il polinomio di Legendre associato di grado m su n (formula incompleta)
// Pm,n(x)=Am,n(x)*Bm,n(x)
// Am,n = (1/((2^n)*n!)
// Bm,n = der(n+m)((x^2-1)^n) (dove der(k) sta per derivata kappesima)
// utilizzando la formula di derivazione formale del polinomio
// la funzione ritorna il polinomio in forma simbolica (variabile indip. = u)
$rf = "";
// test di validità
$mm = $m;
if ($m < 0)
{
$m = -$m;
}
if ($n < 0)
{
echo "(polLegendreAssocIncompl)Attenzione !!! deve essere n >= 0 !!!" . "<p>";
return;
}
if ($m > $n)
{
echo "(polLegendreAssocIncompl)Attenzione !!! deve essere m <= n !!!" . "<p>";
return;
}
$der = $n + $m;
if ($der == 0)
{
$rf = "+1*u^0";
return $rf;
}
$fisso = 1 / (pow(2, $n) * fattoriale($n));
$coeff = potBinom("u^2", "-1", $n);
$rf = "";
for ($k = 0; $k <= $n; $k++)
{
if (pow(-1, $k + 1) > 0)
{
$segno = "+";
}
else
{
$segno = "-";
}
if ($segno == "+" and pow(-1, $mm) > 0)
{
$segno = "+";
}
elseif ($segno == "+" and pow(-1, $mm) < 0)
{
$segno = "-";
}
elseif ($segno == "-" and pow(-1, $mm) > 0)
{
$segno = "-";
}
elseif ($segno == "-" and pow(-1, $mm) < 0)
{
$segno = "+";
}
$rf = $rf . ($coeff[$k] * $fisso) . "*u^" . (2 * $n - 2 * $k) . $segno;
}
$rf = substr($rf, 0, strlen($rf) - 1);
for ($i = 1; $i <= $der; $i++)
{
$rf = derivPolin($rf);
}
return $rf;
} // fine polLegendreAssocIncompl()
</script>
fattoriale.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function fattoriale($n)
{
// calcolo del fattoriale n!
// n = valore in input di cui calcolare il fattoriale
// fornisce in output il fattoriale di n = n!
If ($n == 0)
{
$fatt = 1;
return $fatt;
}
If ($n < 0)
{
echo "Attenzione !!! Valore negativo, impossibile procedere !!! <p>";
return NULL;
}
If (intval($n) <> $n)
{
echo "Attenzione !!! Valore non intero, impossibile procedere !!! <p>";
return NULL;
}
$fatt = 1;
For ($i = 1; $i <= $n; $i++)
{
$fatt = $fatt * $i;
}
return $fatt;
} // fine fattoriale()
</script>
coeffBinom.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function coeffBinom($n, $k)
{
// calcolo coefficiente binominiale (n,k)
// in input n e k
// in output il coeff. binominiale
$coeff = fattoriale($n) / (fattoriale($k) * fattoriale($n - $k));
return $coeff;
} // fine coeffBinom()
</script>
potBinom.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function potBinom($momom1, $monom2, $n)
{
// calcola la potenza di un binomio
// monom1 = primo monomio
// monom2 = secondo monomio
// n = esponente
// ritorna i coefficienti ed il risultato simbolico nella forma :
// coeff(0) = (n,0)
// coeff(1) = (n,1)
// coeff(2) = (n,2)
// " " "
// coeff(n) = (n,n)
// coeff(n+1) = forma simbolica del risultato
$coeff[0] = "";
If ($n < 0)
{
echo "(potBinom) Attenzione !!! Esponente negativo, impossibile procedere !!!" . "<p>";
return;
}
If (intval($n) <> $n)
{
echo "(potBinom) Attenzione !!! Esponente non intero, impossibile procedere !!!" . "<p>";
return;
}
For ($i = 0; $i <= $n; $i++)
{
$coeff[$i] = coeffBinom($n, $i);
}
$coeff[$n + 1] = "";
$rf = "";
For ($i = 0; $i <= $n; $i++)
{
$rr = $coeff[$i];
If ($coeff[$i] >= 0)
{
$rr = "+" . $rr;
}
$rf = $rf . $rr . "*" . "(" . $momom1 . ")" . "^" . ($n - $i) . "*" . "(" . $monom2 . ")" . "^" . $i;
}
$coeff[$n + 1] = $rf;
return $coeff;
} // fine potBinom()
</script>
derivPolin.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function derivPolin($polinomio)
{
// derivata prima di un polinomio
// polinomio = polinomio da derivare in forma simbolica
// in output viene fornita la derivata in forma simbolica
//
// forma simbolica di un polinomio :
//
// a0*u^0+a1*u^1+a2*u^2+....
// (Attenzione !!! questa forma è vincolante !!!)
// (Attenzione !!! i coefficienti a0, a1, ... devono essere numerici !!!)
// ( " possono aversi più monomi dello stesso grado !!!)
$polin = polSimbVett($polinomio);
$grado = 0;
$i = 0;
Do
{
If ($polin[$i] === "")
{
break;
}
$grado = $i;
$i = $i + 1;
} while(TRUE);
For ($i = 0; $i <= $grado - 1; $i++)
{
$deriv[$i] = 0;
}
$deriv[$grado] = "";
For ($i = 1; $i <= $grado; $i++)
{
$deriv[$i - 1] = $polin[$i] * $i;
}
$rf = polVettSimb($deriv);
return $rf;
} // fine derivPolin()
</script>
daVbAPow.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function daVbAPow($f)
{
// trasforma la funzione potenza ()^() di Visual Basic nell'analoga Pow() di PHP
// f = stringa contenente la funzione
$rf = $f;
// esce nel caso che la funzione non contenga ^
if (!is_integer(strpos($rf, "^")))
{
return $rf;
}
// iterazione
$contr = 0;
do
{
$contr = 0;
for ($i = 1; $i <= strlen($rf); $i++)
{
if (strpos($rf, "^", $i - 1) === $i - 1)
{
$base = "";
$esp = "";
$ini = 0;
$fin = 0;
$par = 0;
for ($j = $i - 1; $j >= 0; $j--)
{
$c = substr($rf, $j - 1, 1);
if ($c == "(")
{
$par = $par + 1;
}
if ($c == ")")
{
$par = $par - 1;
}
$base = $base . $c;
if ($par == 0)
{
$ini = $j;
break;
}
}
$par = 0;
for ($j = $i + 1; $j <= strlen($rf); $j++)
{
$c = substr($rf, $j - 1, 1);
if ($c == "(")
{
$par = $par + 1;
}
if ($c == ")")
{
$par = $par - 1;
}
$esp = $esp . $c;
if ($par == 0)
{
$fin = $j;
break;
}
}
$contr = 1;
$base = strrev($base);
$base = substr($base,1, strlen($base) - 2);
eval("\$ff = @($esp);");
$esp = $ff;
$rf = substr($rf, 0, $ini - 1) . "pow(" . $base . "," . $esp . ")" . substr($rf, $fin);
break;
}
}
if ($contr == 0)
{
break;
}
} while(TRUE);
// ritorna risultato
return $rf;
} // fine daVAPow()
</script>
polSimbVett.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function polSimbVett($polinomio)
{
// trasforma un polinomio dalla forma simbolica alla forma vettoriale
//
// polinomio = stringa che contiene il polinomio in forma simbolica
// +a0*u^0+a1*u^1+a2*u^2+....
// (Attenzione !!! questa forma è vincolante !!!)
// ( " !!! i coefficienti a0, a1, ... devono essere numerici !!!)
// ( " !!! possono aversi più monomi dello stesso grado !!!)
// ( " !!! l'ordine dei monomi è arbitrario !!!)
// ( " !!! i coefficienti non devono essere mai in
// ( forma scientifica E
// polin() = rappresentazione vettoriale del vettore
// polin(0) = coeff. grado 0
// polin(1) = coeff. grado 1
// polin(2) = coeff. grado 2
// " " "
// polin(n) = coeff. grado n
// polin(n+1) = ""
$rf = $polinomio;
// calcolo grado del polinomio
$grado = 0;
For ($i = 1; $i <= strlen($rf); $i++)
{
$c = substr($rf, $i - 1, 1);
If ($c == "^")
{
$rrf = "";
For ($j = $i + 1; $j <= strlen($rf); $j++)
{
$cc = substr($rf, $j - 1, 1);
If ($cc == "+" Or $cc == "-")
{
break;
}
$rrf = $rrf . $cc;
}
If (strval($rrf) > $grado)
{
$grado = strval($rrf);
}
}
}
// setta vettore
For ($i = 0; $i <= $grado; $i++)
{
$polin[$i] = 0;
}
$polin[$grado + 1] = "";
For ($i = 1; $i <= strlen($rf); $i++)
{
$c = substr($rf, $i - 1, 1);
If ($c == "^")
{
$espon = "";
For ($j = $i + 1; $j <= strlen($rf); $j++)
{
$cc = substr($rf, $j - 1, 1);
If ($cc == "+" Or $cc == "-")
{
break;
}
$espon = $espon . $cc;
}
$coeff = "";
For ($j = $i - 3; $j >= 1; $j--)
{
$cc = substr($rf, $j - 1, 1);
$coeff = $coeff . $cc;
If ($cc == "+" Or $cc == "-")
{
if (substr($rf, $j - 2, 1) <> "E")
{
break;
}
}
}
$coeff = strrev($coeff);
eval("\$ff = @($coeff);");
$polin[strval($espon)] = $polin[strval($espon)] + $ff;
}
}
return $polin;
} // fine polSimbVett()
</script>
polVettSimb.php
<script language="php">
error_reporting (E_ALL ^ E_NOTICE);
function polVettSimb($polin)
{
// trasforma un polinomio dalla forma vettoriale alla forma simbolica
//
// polinomio = stringa che contiene il polinomio in forma simbolica
// +a0*u^0+a1*u^1+a2*u^2+....
// polin() = rappresentazione vettoriale del vettore
// polin(0) = coeff. grado 0
// polin(1) = coeff. grado 1
// polin(2) = coeff. grado 2
// " " "
// polin(n) = coeff. grado n
// polin(n+1) = ""
$rf = "";
$i = 0;
Do
{
If ($polin[$i] === "")
{
break;
}
$rr = $polin[$i];
If ($polin[$i] >= 0)
{
$rr = "+" . $rr;
}
$rf = $rr . "*u^" . $i . $rf;
$i = $i + 1;
} while(TRUE);
$polinomio = $rf;
return $polinomio;
} // fine polVettSimb()
</script>