#!/usr/bin/perl -w
use PDL;
use PDL::NiceSlice;
use PDL::RungeKutta;
#use PDL::Graphics::PGPLOT::Window;

#$win1 = PDL::Graphics::PGPLOT::Window->new( Device      => "/xserve",
#                                            WindowWidth => 6);

$n0=50;             # initial number of steps per average Larmor period
$Bmax=1.e-9;
$pi=3.14159265358979;
$m =  9.10938188e-31;  # electron mass
$q = -1.602176462e-19; # electron charge


$rv0=pdl(0,0,0,1.e5,2.e5,0); # initial position and velocity
$t0  = 0;	# begining os integration
$Tl  = 2*$pi*$m/(abs($q)*$Bmax);    # Larmor period
$dt0 = $Tl/($n0-1);                 # initial time step
$t1  = 20*$Tl;   # end of integration
$eps= 1.e-6; # error
$verbose=1;

@esargs=($m,$q,\&field,$t0,$t1); # arguments for error-scale function

($evt,$evrv,$evd,$i,$j)=
rkevolve($t0,$rv0,$dt0,\&difeq,$t1,$eps,\&ersceval,\@esargs,$verbose);

wcols $evrv((0),),$evrv((1),),$evrv((2),),$evrv((3),),$evrv((4),),$evrv((5),),'test.dat';
#$win1->line($evrv((0),),$evrv((1),),{COLOR=>'red'});

sub difeq {         # motion law
  my ($t,$y)= @_;
  my $yd=zeroes(6);  # y=(R,V)
  $yd(:2).=$y(3:);                                            # R'=V
  $yd(3:).=$q/$m*crossp($y(3:),field($y(:2),$t,$t0,$t1));     # V'=q(BxV)/m
  return $yd;
}

sub ersceval {      #error-scale evaluation
  my ($t,$rv,$m,$q,$fld,$t0,$t1) = @_;
  my $es=ones(6);
  my $B=&$fld($rv(0:2),$t,$t0,$t1);
  $es(:2).=abs($m*sumover($rv(3:1) x $B)/($q*sumover($B**2))); # Larmor radius
  $es(3:).=sqrt(sumover($rv(3:)**2)); # module of velocity
  return $es;
}

sub field {
  my ($r,$t,$t0,$T) = @_;
  $scale=($t-$t0)/$T*1.e-9;
  my $B = pdl(0,0,1)*$scale;
  return $B;
}