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. 


 parametri dell'elettrone :

 numero quantico principale n = (n > 0)
 numero quantico azimutale  l = (0 <= l <= n - 1)
 numero quantico magnetico  m = (-l <= m <= l)

 amplificazione colore :

 ampl = (amplifica i valori di bassa probabilità)


 parametri di scala :

 lar = alt = (larghezza ed altezza immagine in pixel)
 xa =    xb = (estremi semiasse x positivo)
 ya =    yb = (estremi semiasse y positivo)

 esempi già elaborati : 

n l m n l m n l m n l m n l m
1 0 0 2 0 0 3 0 0 ...   ...   ... ...   ...   ...
  2 1 0 ...   ...   ... ...   ...   ... 5 2 0
  2 1 1 3 1 0 ...   ...   ... ...   ...   ...
  2 1 -1 3 1 1 ...   ...   ... ...   ...   ...
     ...   ...   ... ...   ...   ... ...   ...   ...


 


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 "&nbsp;<p>";
echo "&nbsp;<p>";
echo "&nbsp;<p>";
echo "&nbsp;<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>