/*

  Microcanonical Molecular Dynamics

  Narejeno po F77 programu
  microcanonical molecular dynamics
  1.0 Dieter W. Heermann 1985

  Vhodni parametri so:
  npart  - število delcev (mora biti večkratnik števila 4)
  side   - dolžina stranice kocke v sigma enotah
  den    - reducirana gostota
  tref   - reducirana temperatura
  rcoff  - odrez (cutoff) potenciala v sigma enotah
  h      - osnovni časovni korak
  irep   - popravi hitrost vsak irep-ti časovni korak
  istop  - kje prenehaj popravljati hitrost
  timemx - število integracijskih korakov

*/
function molecular_dynamics ($npart, $den, $side, $tref, $rcoff, $h, $irep, $istop=0, $timemx, $koliko, $md) {

  // -------------------------------------------
  // najava spremenljivk
  // -------------------------------------------

  // sile
  $fx = array();
  $fy = array();
  $fz = array();

  // položaji
  $x = array();
  $y = array();
  $z = array();

  // hitrosti
  $vh = array();

  // za izpis podatkov
  $podatki = array();

  // preveri, da ni preveč korakov (max 2500)
  if ($timemx > 2500) $timemx = 2500;

  // popravi število delcev, da je deljivo s 4
  $npart = $npart - ($npart % 4);
  if ($npart < 4) $npart = 4;


 if($md) {  
  echo "-- Microcanonical Molecular Dynamics --\n\n";
  echo "Število delcev je: ".$npart."\n";
  echo "Velikost stranice kocke je: ".$side."\n";
  echo "Odrez LJ potenciala je: ".$rcoff."\n";
  echo "Število korakov je: ".$timemx."\n";
  echo "Osnovni časovni korak je: ".$h."\n";
  echo "Popravim hitrosti vsak ".$irep."-ti korak\n";
  echo "Preneham popravljat po ".$istop." korakih\n";
 }
 else {
  echo "-- Brownian Dynamics --\n\n";
  echo "Število delcev je: ".$npart."\n";
  echo "Velikost stranice kocke je: ".$side."\n";
  echo "Odrez LJ potenciala je: ".$rcoff."\n";
  echo "Število korakov je: ".$timemx."\n";
  echo "Osnovni časovni korak je: ".$h."\n";
  echo "Popravim hitrosti vsak ".$irep."-ti korak\n";
 }


  // -------------------------------------------
  // nastavi parametre
  // -------------------------------------------

  $a      = $side / 4.0;
  $sideh  = $side * 0.5;
  $hsq    = $h*$h;
  $hsq2   = $hsq * 0.5; // zakaj ne $hsq/2.0 ?
  $rcoffs = $rcoff * $rcoff;
  $tscale = 16.0 / (1.0 * $npart - 1.0);
  $vaver  = 1.13 * sqrt($tref / 24.0);

  $n3     = 3 * $npart;
  $iof1   = $npart;     // odmik za for zanke
  $iof2   = 2 * $npart; // odmik za for zanke


  // -------------------------------------------
  // nastavi začetno konfiguracijo
  // -------------------------------------------

  // postavi atome v kocki
  $ijk = 0;
  for ($lg = 0; $lg <= 3; $lg++) { //za $lg 0 do 3
    for ($i = 0; $i <= 3; $i++) {
      for ($j = 0; $j <= 3; $j++) {
	for ($k = 0; $k <= 3; $k++) {
	  $ijk++;
	  if ($lg < 2) {
	    $x[$ijk] = $i * $a + $lg * $a * 0.5; // $lg je tukaj 0, 1
	    $y[$ijk] = $j * $a + $lg * $a * 0.5; // $lg je tukaj 0, 1
	    $z[$ijk] = $k * $a;
	  }
	  else {
	    $x[$ijk] = $i * $a + (3 - $lg) * $a * 0.5; // $lg izraz je tukaj 1, 0
	    $y[$ijk] = $j * $a + ($lg - 2) * $a * 0.5; // $lg izraz je tukaj 0, 1
	    $z[$ijk] = $k * $a + $a * 0.5;
	  }
	} //$k
      } //$j
    } //$i
  } //$lg


  // določi hitrosti, porazdeljene normalno
  $vh = mxwell($n3, $h, $tref);

  // počisti sile
  for ($i = 1; $i <= $npart; $i++) {
    $fx[$i] = 0.0; // popravi polje $f na 0 (mogoče bi to naredil direkt)
    $fy[$i] = 0.0;
    $fz[$i] = 0.0;
  }

  // -------------------------------------------
  // Začni dejansko molekularno dinamiko
  //
  // Enačbe gibanja so integrirane z uporabo "sumarne oblike".
  // Vsak irep-ti korak so hitrosti popravljene, da dajo določeno reducirano temperaturo (tref)
  // -------------------------------------------

  echo "\n\n- Začnem računat MD -\n";

  for ($clock = 1; $clock <= $timemx; $clock++) {
    
    // napreduj položaj za en osnovni časovni korak
    for ($i = 1; $i <= $npart; $i++) {
      $x[$i] = $x[$i] + $vh[$i]       + $fx[$i];
      $y[$i] = $y[$i] + $vh[$i+$iof2] + $fy[$i];
      $z[$i] = $z[$i] + $vh[$i+$iof3] + $fz[$i];
    }

    // dodaj perodične mejne pogoje (da delci "krožijo" v škatli)
    for ($i = 1; $i <= $npart; $i++) {
      if ($x[$i] < 0)     $x[$i] = $x[$i] + $side;
      if ($x[$i] > $side) $x[$i] = $x[$i] - $side;

      if ($y[$i] < 0)     $y[$i] = $y[$i] + $side;
      if ($y[$i] > $side) $y[$i] = $y[$i] - $side;

      if ($z[$i] < 0)     $z[$i] = $z[$i] + $side;
      if ($z[$i] > $side) $z[$i] = $z[$i] - $side;
    }

    // izračunaj delne hitrosti
    for ($i = 1; $i <= $npart; $i++) {
      $vh[$i]       = $vh[$i]       + $fx[$i];
      $vh[$i+$iof1] = $vh[$i+$iof1] + $fy[$i];
      $vh[$i+$iof2] = $vh[$i+$iof2] + $fz[$i];
    }



    // ta del izračuna sile na delcih ...

    $vir  = 0.0;
    $epot = 0.0;
    for ($i = 1; $i <= $npart; $i++) {
      $fx[$i] = 0.0; // popravi polje $f na 0 (mogoče bi to naredil direkt)
      $fy[$i] = 0.0;
      $fz[$i] = 0.0;
    }

    for ($i = 1; $i <= $npart; $i++) {
      $xi = $x[$i];
      $yi = $y[$i];
      $zi = $z[$i];
      for ($j = $i+1; $j < $npart; $j++) {
	$xx = $xi - $x[$j];
	$yy = $yi - $y[$j];
	$zz = $zi - $z[$j];
	
	if ($xx < $sideh*-1) $xx = $xx + $side;
	if ($xx > $sideh)    $xx = $xx - $side;

	if ($yy < $sideh*-1) $yy = $yy + $side;
	if ($yy > $sideh)    $yy = $yy - $side;

	if ($zz < $sideh*-1) $zz = $zz + $side;
	if ($zz > $sideh)    $zz = $zz - $side;

	$rd = $xx * $xx + $yy * $yy + $zz * $zz;
	if ($rd > $rcoffs) break 2; // pojdi ven iz obeh for loopov
      
	$epot = $epot + pow($rd, (-6.0)) - pow($rd, (-3.0));
	$r148 = pow($rd, (-7.0)) - 0.5 * pow($rd, (-4.0));
	$vir  = $vir - $rd * $r148;

	$kx     = $xx * $r148;
	$fx[$i] = $fx[$i] + $kx;
	$fx[$j] = $fx[$j] - $kx;

	$ky     = $yy * $r148;
	$fy[$i] = $fy[$i] + $ky;
	$fy[$j] = $fy[$j] - $ky;

	$kz     = $zz * $r148;
	$fz[$i] = $fz[$i] + $kz;
	$fz[$j] = $fz[$j] - $kz;

      } //$i
    } //$j

    for ($i = 1; $i <= $npart; $i++) {
      $fx[$i] = $fx[$i] * $hsq2;
      $fy[$i] = $fy[$i] * $hsq2;
      $fz[$i] = $fz[$i] * $hsq2;
    }
    
    // ... konec računanja sil na delcih



    // izračunaj hitrosti
    for ($i = 1; $i <= $npart; $i++) {
      $vh[$i]       = $vh[$i]       + $fx[$i];
      $vh[$i+$iof1] = $vh[$i+$iof1] + $fy[$i];
      $vh[$i+$iof2] = $vh[$i+$iof2] + $fz[$i];
    }

    // izračunaj kinetično energijo
    $ekin = 0.0;
    for ($i = 1; $i <= $n3; $i++) {
      $ekin = $ekin + $vh[$i] * $vh[$i];
    }
    $ekin = $ekin / $hsq;


    // izračunaj povprečno hitrost
    $vel   = 0.0;
    $count = 0.0;
    for ($i = 1; $i <= $npart; $i++) {
      $vx = $vh[$i]       * $vh[$i];
      $vy = $vh[$i+$iof1] * $vh[$i+$iof1];
      $vz = $vh[$i+$iof2] * $vh[$i+$iof2];

      $sq = sqrt($vx + $vy + $vz);
      $sqt = $sq / $h;

      if ($sqt > $vaver) $count = $count + 1;
      $vel = $vel + $sq;

    }// $i
    $vel = $vel / $h;


    // izberi tip simulacije
    if ($md) {    

    if ($clock < $istop) { 
      // normaliziraj hitrosti da dobiš nakazano referenčno temperaturo
      if (($clock % $irep) == 0) {
	echo "\n Korak ".$clock."\n";
	echo "Popravljam hitrosti ...\n";
	$ts = $tscale * $ekin;
	echo "Temperatura pred spremembo je ".$ts."\n";
	$sc = $tref / $ts;
	$sc = sqrt($sc);
	echo "Faktor spremembe je ".$sc."\n";
	for ($i = 1; $i <= $n3; $i++) {
	  $vh[$i] = $vh[$i] * $sc;
	}
	$ekin = $tref / $tscale; // to je zmeraj enako
      } 
    } // if clock

    }
    // simulacija je BD
    else {

    // normaliziraj hitrosti da dobiš nakazano referenčno temperaturo
    if (($clock % $irep) == 0) {
      echo " Korak ".$clock."\n";
      echo "Zamenjam hitrosti ...\n";
      $vh = mxwell($n3, $h, $tref);
      $ekin = $tref / $tscale;
    }

    }
    
    // izračunaj razne količine
    if (($clock % $koliko) == 0) {
      $ek   = 24.0 * $ekin;
      $epot = 4.0 * $epot;
      $etot = $ek + $epot;
      $temp = $tscale * $ekin;
      $pres = $den * 16.0 * ($ekin - $vir) / $npart;
      $vel  = $vel / $npart;
      //$rp   = ($count / $npart) * 100.0;
      
/*
	echo "korak ".$clock."\n";
	echo "kin. energija: ".$ek."\n";
	echo "pot. energija: ".$epot."\n";
	echo "tot. energjia: ".$etot."\n";
	echo "temperatura: ".$temp."\n";
	echo "pritisk: ".$pres."\n";
	echo "povp. hitrost: ".$vel."\n";
	//echo "rp: ".$rp."\n\n";
*/

	$ek_out = $ek_out. "[".$clock.", ".$ek."], ";
 	$epot_out = $epot_out. "[".$clock.", ".$epot."], ";
	$etot_out = $etot_out. "[".$clock.", ".$etot."], ";
	$temp_out = $temp_out. "[".$clock.", ".$temp."], ";
	$pres_out = $pres_out. "[".$clock.", ".$pres."], ";
	$vel_out = $vel_out. "[".$clock.", ".$vel."], ";

    }

  } //$clock

  $podatki["ek"] = $ek_out;
  $podatki["epot"] = $epot_out;
  $podatki["etot"] = $etot_out;
  $podatki["temp"] = $temp_out;
  $podatki["pres"] = $pres_out;
  $podatki["vel"] = $vel_out;

  return $podatki;

} //molecular_dynamics()