#!/usr/bin/perl use warnings; use strict; use Getopt::Long; GetOptions( "width=f" => \my $width, "acc=f" => \my $acc, "input=i" => \my $input, "coll=f" => \my $coll_prob, "emit=f" => \my $emission_energy, ); use constant ELECTRON_MASS => 1; use constant ELECTRON_CHARGE => 1; use constant TIME_PER_STEP => 0.1; use constant EPSILON_0 => 1; my $id = "franck-hertz-$width-$acc-$input-$coll_prob-$emission_energy"; my $sid = "franck-hertz-$width-$input-$coll_prob-$emission_energy"; { my @colls = (0) x $width; sub register_coll { use constant ROUNDER => 1; my $pos = shift; my $rounded = sprintf '%0.f', $pos / ROUNDER; $colls[ROUNDER*$rounded + $_]++ for 0..(ROUNDER - 1); } sub output_colls { open my $fh, ">", "$id-colls.txt" or die $!; print $fh "$_ $colls[$_]\n" for 0..$#colls; } } { my @kins = (0) x $acc; sub register_kin { use constant ROUNDER => 1; my $kin = shift; my $rounded = sprintf '%0.f', $kin / ROUNDER; $kins[ROUNDER*$rounded + $_]++ for 0..(ROUNDER - 1); } sub output_kins { { open my $fh, ">", "$id-kins.txt" or die $!; print $fh "$_ $kins[$_]\n" for 0..$#kins; } { use constant TRESHOLD => 8; my $sum = 0; $sum += $kins[$_] for TRESHOLD..$#kins; open my $fh, ">>", "$sid-diag.txt" or die $!; print $fh "$acc $sum\n"; } } } my @electrons = ({ x => 0, v => 0 }) x $input; my $step = 0; while(@electrons = grep { $_ } @electrons) { $step++; warn "$step...\n" if $step % 10 == 0; for my $e (@electrons) { next unless $e; my ($x, $v) = @$e{"x", "v"}; my $F = (EPSILON_0 * $acc / $width) / ELECTRON_CHARGE; my $a = $F / ELECTRON_MASS; $v += $a * TIME_PER_STEP; my $delta_x = $v * TIME_PER_STEP; $delta_x = $width - $x if $x + $delta_x > $width; $x += $delta_x; my $kin = 1/2 * ELECTRON_MASS * $v**2; if($coll_prob * $delta_x > rand) { #warn "kin: $kin\n"; if($kin >= $emission_energy) { $kin -= $emission_energy; $v = sqrt(2 * $kin / ELECTRON_MASS); register_coll($x); } else { # nichts } } if($x >= $width) { register_kin($kin); $e = undef; } else { $e = { x => $x, v => $v }; } } } output_colls(); output_kins();
Download