#!/bin/sh  ##this line is just to activate prettyprinters
# Copyright (c) 2012 Josh Berryman, University of Luxembourg,
# Pfaffenwaldring 27, 70569 Stuttgart, Germany; all rights
# reserved unless otherwise stated.
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA


#
# get_rc_aggregation
# ---------------------
#
# Get an rc value based on cluster sizes
#
#############################################################
proc get_rc_aggregation { r_contact n_part } {

    ##get the size of the largest cluster
    set lastId [expr int($n_part - 1)]
    set agreturn [analyze aggregation $r_contact 0 $lastId]
    set rc [lindex $agreturn 1]

    puts "Set RC: $rc"

    return $rc

}

#
# save_snapshot
# ---------------------
#
# example for writing a snapshot: keep this
# to the minimum information needed to regenerate your system state
# e.g., if particle charge never changes then hardcode it
# rather than writing and re-loading.
#############################################################
proc save_snapshot {f_out} {
    blockfile $f_out write variable box_l
    blockfile $f_out write particles {pos v}
}

 
#
# load_snapshot
# ---------------------
#
# read in data comparable to whatever is generated 
# by "save_snapshot"
#############################################################
proc load_snapshot {fn} {
  
    # open the FIFO or file: shouldn't matter which.
    set f_in [open "$fn" "r"]
 
    # read all parameters which were stored by save_snapshot
    while { [blockfile $f_in read auto] != "eof" } {}
    close $f_in
}
 
#
# init_basic
# ---------------------
#
# set up everything in the system apart from crds, vels 
# and box 
#############################################################
proc init_basic { } {

  set n_part   868

  ##dummies 
  set box_l     10.7437
  setmd box_l $box_l $box_l $box_l

  # Interaction parameters (Lennard Jones)
  set lj1_eps     1.0
  set lj1_sig     1.0
  set lj1_cut     4.0 
  set lj1_shift   [calc_lj_shift $lj1_sig $lj1_cut]
  set r_contact   [expr $lj1_sig * 1.0]
  inter 0 0 lennard-jones $lj1_eps $lj1_sig $lj1_cut $lj1_shift 0

  # set up system with dummy state
  for {set i 0} { $i < $n_part } {incr i} {
      part $i pos 0.0 0.0 0.0 type 0
  }
  
  # define the (trivial) topology
  for {set i 0} { $i < $n_part} {incr i} {
    set topo_chain 0
    lappend topo_chain [expr $i]
    lappend topo $topo_chain
  }
  eval analyze set $topo
  analyze set "topo_part_sync"

  # Integration parameters
  setmd time_step 0.01
  setmd skin      0.4
  thermostat langevin 1.0 1.0

  return $n_part

}

 
#
# init_A
# ---------------------
#
# generate a random system and equilibrate such that the
# RC is less than value A
#############################################################
proc init_A {} {
   puts "JOBSCRIPT: WARNING, CALLED STUB"
   puts "JOBSCRIPT: YOU ARE PROBABLY HERE BECAUSE NO initial_config.dat WAS FOUND"
   puts "JOBSCRIPT: EITHER MAKE AN initial_config.dat, CHANGE THE PATH, OR"
   puts "JOBSCRIPT: FILL OUT THIS FUNCTION TO MAKE A RANDOM START STATE."
}

###Debug flag: set 1 to turn on extra output. (Not threadsafe).
set debug 0
set max_steps 0

#default arguments:
set COORDS_TO_FILE 0

#parse arguments
foreach {option value} $argv {
  switch -glob -- $option {
    -tmpdir             {set TMP_DIR $value }
    -initial_config     {set INITIAL_CONFIG $value }
    -in_fifoname        {set IN_FIFONAME $value }
    -coords_to_file     {set COORDS_TO_FILE $value }
    -back_fifoname      {set OUTPUT_CONFIG $value }
    -metadata_fifoname  {set OUTPUT_METADATA $value }
    -halt_steps         {set HALT_STEPS $value }
    -check_rc_every     {set CHECK_RC_EVERY $value }
    -halt_rc_lower      {set HALT_RC_LOWER $value }
    -halt_rc_upper      {set HALT_RC_UPPER $value }
    -seed               {set SEED $value }
    -current_lambda     {set CURRENT_LAMBDA $value }
    -rp_id              {set RP_ID $value }
    -A                  {set HALT_RC_LOWER $value }
    -B                  {set borderB $value }
    -last_rc            {set last_rc $value }
    -next_interface     {set HALT_RC_UPPER $value }
    -clientname         {set clientname $value }
    -timestamp          {set timestamp $value }
    -act_lambda         {set act_lambda $value }
    -uuid               {set uuid $value }
    -max_steps          {set max_steps $value }
    -jobtype            {set jobtype $value }
    default             {puts "Additional not-used parameter $option with value $value"}
  }
}

set stop_at_b 0
if { $CHECK_RC_EVERY != 0 } {
   set stop_at_b 1
}

set warnCount 0
set warnMax  10
set tcl_precision 6
  
# definition for rc calc
set r_contact 1.0

# basic setup


#############################################################
#  Parameters                                               #
#############################################################


t_random seed $SEED


#############################################################
#  Setup System                                             #
#############################################################

if {$INITIAL_CONFIG == "None" && $IN_FIFONAME == "None"} {
    puts "JOBSCRIPT: self-generating an initial state with equilibration."
    init_A  
} elseif {$INITIAL_CONFIG == "None"} {
    set n_part [ init_basic ] 
    puts "JOBSCRIPT: Loading snapshot from fifo: ${IN_FIFONAME}."
    # get snap
    load_snapshot "${IN_FIFONAME}"
} else {
    set n_part [ init_basic ] 
    #get snap from file
    puts "JOBSCRIPT: Loading snapshot from file: ${INITIAL_CONFIG}."
    load_snapshot "${INITIAL_CONFIG}"
}


if { $debug == 1 } {
        set debugF [open "espresso_debug.vtf" "w"]
        writevsf $debugF
        writevcf $debugF
}

#############################################################
#      Integration                                          #
#############################################################
set rclast [get_rc_aggregation $r_contact $n_part]
set rc      $rclast

if { $CHECK_RC_EVERY != 0 } {
        set int_step $CHECK_RC_EVERY
} else {
        set int_step $HALT_STEPS
}
set i 0
set in_progress 1
set step_abort 0

while { $in_progress } {

        integrate $int_step
        set i [expr ($i + $int_step)]

        if { ($max_steps > 0) && ($i >= $max_steps)} {
            set in_progress 0
            set step_abort 1
        }

        ##REACTION COORDINATE: CALCULATE HERE      
        if { $CHECK_RC_EVERY > 0 } {
                set rclast $rc
                set rc    [get_rc_aggregation $r_contact $n_part]
            
                if { $debug == 1 } {
                    puts "rc: $rc"
                    writevcf $debugF
                }
                if { $rc >= $HALT_RC_UPPER } {
                            if { $rclast < $HALT_RC_UPPER }  {
                                    break
                            }
                } elseif { $rc >= $HALT_RC_LOWER && $rclast < $HALT_RC_LOWER } {
                            break
                } elseif { $rc <= $HALT_RC_LOWER && $rclast > $HALT_RC_LOWER } {
                            break
                }
        }
      
        if { $HALT_STEPS > 0 && $i >= $HALT_STEPS } {

             ##REACTION COORDINATE: CALCULATE HERE
             set rclast $rc
             set rc    [get_rc_aggregation $r_contact $n_part]
             break

        }

 ###This close-brackets signifies end of simulation
}
puts "MD: Quitting: rc $rc , rclast $rclast, steps $i, haltsteps $HALT_STEPS."

#############################################################
puts "MD: opening output pipe $OUTPUT_CONFIG"
set output_channel [open $OUTPUT_CONFIG {WRONLY}]
#fconfigure $output_channel -blocking 1

if { $COORDS_TO_FILE == 0 } {
    ##write out the final coords
    save_snapshot $output_channel
    flush $output_channel
    close $output_channel   
} else {

    set output_coords_file [open $COORDS_TO_FILE {WRONLY CREAT TRUNC}]
    
    ##write out the final coords
    save_snapshot $output_coords_file
    close $output_coords_file
    
    ##just write the filename to pipe
    puts  $output_channel "$COORDS_TO_FILE"
    flush $output_channel
    close $output_channel   
}


puts "MD: opening output RC data $OUTPUT_METADATA"
set output_metadata_channel [open $OUTPUT_METADATA {WRONLY}]
set t [setmd time]
puts $output_metadata_channel [format "{\"rc\": %.4f, \"steps\": %i, \"time\": %.4f}" $rc $i $t]
puts "MD: sent: "
puts [format "{\"rc\": %.4f, \"steps\": %i, \"time\": %.4f}" $rc $i $t]
flush $output_metadata_channel
close $output_metadata_channel  
    

puts "\n Simulation Finished \n"
exit


