structure Sim_{{group.name}} = struct {% if (trace) %} val trace = true {% else %} val trace = false {% endif %} fun putStrLn out str = (TextIO.output (out, str); TextIO.output (out, "\n")) fun putStr out str = (TextIO.output (out, str)) fun showBoolean b = (if b then "1" else "0") fun showReal n = let open StringCvt open Real in (if n < 0.0 then "-" else "") ^ (fmt (FIX (SOME 12)) (abs n)) end fun timing (action) = let val timer = Timer.startCPUTimer () val result = action () val times = Timer.checkCPUTimer timer in (result, Time.+ (#usr times, #sys times)) end structure TEventPriority = struct type priority = real fun compare (x,y) = Real.compare (x,y) type item = real * (int * int * real) fun priority (x : item) = (#1(x)) end structure TEQ = TEventQueue (structure P = TEventPriority type value = (int * int * real) fun value (x : P.item) = (#2(x))) val DQ = TEQ.empty exception Index exception Shape fun dimVals [m,n] = (m,n) | dimVals _ = raise Shape fun writeProjection S prefix = ListPair.app (fn (W,p) => let val out = TextIO.openOut (prefix ^ "." ^ (Int.toString p) ^ ".prj.dat") val (m,n) = dimVals (BitSparseMatrix.shape W) in Loop.app (0, n, fn (i) => let val sl = BitSparseMatrix.slice (W,1,i) val lst = BitSparseMatrix.sliceFoldi (fn (j,x,lst) => j::lst) [] sl in List.app (fn (j) => putStrLn out ( (Int.toString i) ^ " " ^ (Int.toString j))) lst end); TextIO.flushOut out; TextIO.closeOut out end) (S, List.tabulate (List.length S, fn(i) => i)) fun writeLog Plabels (spike_filepath,state_prefix,ext_prefix,event_prefix) (statelog,spikelog) = let open {{group.name}} val _ = case state_prefix of SOME prefix => ListPair.app (fn (label,lst) => let val state_out = TextIO.openAppend (prefix ^ "." ^ label ^ ".dat") in List.app (fn (i,nstate) => putStrLn state_out (Int.toString (i) ^ ", " ^ (showReal (state_indep nstate)) ^ ", " ^ (showRealArray (state_y nstate)))) (List.rev lst); TextIO.flushOut state_out; TextIO.closeOut state_out end) (Plabels,statelog) | NONE => () val _ = case ext_prefix of SOME prefix => ListPair.app (fn (label,lst) => let val ext_out = TextIO.openAppend (prefix ^ "." ^ label ^ ".dat") in List.app (fn (i,nstate) => putStrLn ext_out (Int.toString (i) ^ ", " ^ (showReal (state_indep nstate)) ^ ", " ^ (showRealArray (state_ext nstate)) ^ ", " ^ (showRealArray (state_extev nstate)))) (List.rev lst); TextIO.flushOut ext_out; TextIO.closeOut ext_out end) (Plabels,statelog) | NONE => () val _ = case event_prefix of SOME prefix => ListPair.app (fn (label,lst) => let val event_out = TextIO.openAppend (prefix ^ "." ^ label ^ ".dat") in List.app (fn (i,nstate) => putStrLn event_out (Int.toString (i) ^ ", " ^ (showReal (state_indep nstate)) ^ ", " ^ (showRealArray (state_event nstate)))) (List.rev lst); TextIO.flushOut event_out; TextIO.closeOut event_out end) (Plabels,statelog) | NONE => () val _ = let val spike_out = TextIO.openAppend spike_filepath in ({{group.name}}.SEQ.nextEventsApp (fn (t,i) => putStrLn spike_out ((showReal t) ^ " " ^ (Int.toString i)), spikelog)); TextIO.flushOut spike_out; TextIO.closeOut spike_out end in () end fun start (N, S, D, DQ, Pn, Plabels, global_h, initial_vector, frun, ftime, fspikes, finfo, tstop, logperiod, rs_vector, rszt_vector, (spikeout_filepath,stateout_prefix,extout_prefix,eventout_prefix), (statesample,extsample,evsample)) = let {% if CheckBounds %} val sub = Real64Array.sub val isub = IntArray.sub val update = Real64Array.update {% else %} val sub = Unsafe.Real64Array.sub val isub = Unsafe.IntArray.sub val update = Unsafe.Real64Array.update {% endif %} val frun' = frun (statesample,extsample,evsample) val writeLog' = writeLog Plabels (spikeout_filepath,stateout_prefix,extout_prefix,eventout_prefix) fun enqueueSpikes (spike_i, S, D, DQ) = {{group.name}}.SEQ.PQ.foldl (fn ((t,i),dq) => ((*putStrLn TextIO.stdOut ("enqueuing spike for gid " ^ (Int.toString i) ^ " at time " ^ (showReal t));*) #2(ListPair.foldl (fn (del,W,(port,dq)) => let val sl = BitSparseMatrix.slice (W,1,i) in (port+1, BitSparseMatrix.sliceFoldi (fn (j,x,dq) => let val tev = Real.+ (t,del) in TEQ.addEvent ((tev, (j,port,1.0)), dq) end) dq sl) end) (0,dq) (D,S)) )) DQ spike_i fun netrun (t_n,n,DQ,state_vector,spikelog,statelog,tlog) = let val t_i = (Real.fromInt n) * (!global_h) val _ = if trace then (putStrLn TextIO.stdOut ("netrun: global_h = " ^ (showReal (!global_h)) ^ " t_n = " ^ (showReal t_n) ^ " t_i = " ^ (showReal t_i))) else () val (I,DQ') = TEQ.nextEventsFold (fn (t,_) => Real.<=(t,t_i), fn (t,(i,port,w),I) => let val _ = if trace then putStrLn TextIO.stdOut ("netrun: event at t = " ^ (showReal t) ^ " i = " ^ (Int.toString i) ^ " port = " ^ (Int.toString port) ^ " w = " ^ (showReal w)) else () val im = IntMap.find (I, i) val im = case im of SOME m => IntMap.unionWith (op @) (m,IntMap.singleton(port,[(t,w)])) | NONE => IntMap.singleton (port,[(t,w)]) in IntMap.insert (I,i,im) end, IntMap.empty, DQ) val (state_vector_i, spikes_i, statelog_i) = frun' (I, t_i, state_vector, rs_vector, rszt_vector) val (all_spike_i, log_spike_i) = fspikes spikes_i val _ = finfo state_vector_i val DQ'' = enqueueSpikes (all_spike_i, S, D, DQ') val spikelog' = {{group.name}}.SEQ.merge (log_spike_i, spikelog) val _ = if t_i >= tlog orelse t_i >= tstop then (writeLog' (if List.null statelog then statelog_i else ListPair.map (op @) (statelog_i, statelog), spikelog')) else () val (tlog',statelog',spikelog') = if t_i >= tlog orelse t_i >= tstop then (t_n + logperiod, [], {{group.name}}.SEQ.empty) else (tlog, if List.null statelog then statelog_i else ListPair.map (op @) (statelog_i, statelog), spikelog') in if t_i >= tstop then state_vector_i else netrun (t_i, Int.+(n,1), DQ'', state_vector_i, spikelog', statelog', tlog') end in netrun (0.0,1,DQ,initial_vector,{{group.name}}.SEQ.empty,[],0.0) end exception Exit of OS.Process.status fun exitError (prog, msg) = let val _ = TextIO.output(TextIO.stdErr, prog ^ ": " ^ msg ^ "\n") in raise Exit OS.Process.failure end fun exitHelp prog = let val _ = TextIO.output(TextIO.stdOut, (Options.usage prog) ^ "\n") in raise Exit OS.Process.success end fun main (name,args) = let open {{group.name}} fun finfo (_) = () val optStatus = ref NONE val (opts, _) = (Options.getopt optStatus) args val _ = (case !optStatus of SOME msg => exitError (CommandLine.name(), msg) | NONE => ()) val {is_help, is_time, is_timestep, is_abstol, is_reltol, is_logperiod, is_statesample, is_extsample, is_evsample, is_spikerecord, is_prjrecord, is_spikeout, is_stateprefix, is_extprefix, is_eventprefix, is_prjprefix, is_cell_randomseeds, is_prj_randomseeds } = Options.getstate (opts) val _ = if is_help then exitHelp (CommandLine.name()) else () val _ = case (is_statesample, is_extsample, is_evsample, is_spikerecord) of (NONE, NONE, NONE, NONE) => (putStrLn TextIO.stdErr ("No options for state sampling or event recording have been specified;"); putStrLn TextIO.stdErr ("State traces and spike event times will not be recorded.")) | (_, _, _, _) => () val _ = case is_abstol of SOME v => (if v > 0.0 then (D.abstol := (SOME v)) else ()) | NONE => () val _ = case is_reltol of SOME v => (if v > 0.0 then (D.reltol := (SOME v)) else ()) | NONE => () val _ = case is_timestep of SOME dt => (global_h := (Real.min(dt, minDelay))) | NONE => (global_h := (Real.min(!global_h, minDelay))) val tstop = case is_time of SOME t => t | NONE => 150.0 val logperiod = case is_logperiod of SOME t => t | NONE => 100.0 val statesample = case is_statesample of SOME n => n | NONE => 0 val extsample = case is_extsample of SOME n => n | NONE => 0 val evsample = case is_evsample of SOME n => n | NONE => 0 val spikelog = case is_spikerecord of SOME n => fspikeidxs n | NONE => [] val spikeout_filepath = case is_spikeout of SOME s => s | NONE => label ^ ".dat" val stateout_prefix = if statesample>0 then (case is_stateprefix of SOME s => SOME s | NONE => SOME (label ^ "_state")) else NONE val extout_prefix = if extsample>0 then (case is_extprefix of SOME s => SOME s | NONE => SOME (label ^ "_ext")) else NONE val eventout_prefix = if evsample>0 then (case is_eventprefix of SOME s => SOME s | NONE => SOME (label ^ "_event")) else NONE val prjout_prefix = case is_prjprefix of SOME s => s | NONE => label in (let val _ = putStrLn TextIO.stdOut ("global time step is " ^ (showReal (!global_h))) val _ = case !D.abstol of SOME tol => putStrLn TextIO.stdOut ("absolute error tolerance is " ^ (showReal (tol))) | NONE => () val _ = case !D.reltol of SOME tol => putStrLn TextIO.stdOut ("relative error tolerance is " ^ (showReal (tol))) | NONE => () val _ = putStrLn TextIO.stdOut ("constructing projections...") val (S,t) = timing fprojection val _ = putStrLn TextIO.stdOut ("projections took " ^ (Time.toString t) ^ " s") val _ = if is_prjrecord then writeProjection S prjout_prefix else () val _ = (case is_spikerecord of SOME s => let val spike_out = TextIO.openOut spikeout_filepath in List.app (fn (s) => putStrLn spike_out ("# " ^ s)) ([ label ]); TextIO.closeOut spike_out end | NONE => (); case stateout_prefix of SOME prefix => List.app (fn(label) => let val state_out = TextIO.openOut (prefix ^ "." ^ label ^ ".dat") in TextIO.closeOut state_out end) Plabels | NONE => (); case extout_prefix of SOME prefix => List.app (fn(label) => let val ext_out = TextIO.openOut (prefix ^ "." ^ label ^ ".dat") in TextIO.closeOut ext_out end) Plabels | NONE => (); case eventout_prefix of SOME prefix => List.app (fn(label) => let val event_out = TextIO.openOut (prefix ^ "." ^ label ^ ".dat") in TextIO.closeOut event_out end) Plabels | NONE => () ) val _ = case is_prj_randomseeds of NONE => () | SOME lst => if (List.length lst)=C then update_projection_rs lst else exitError (CommandLine.name(), "list of projection random seeds does not match number of projections") val cell_rs_seeds = case is_cell_randomseeds of NONE => NONE | SOME lst => if (List.length lst)=P then SOME lst else exitError (CommandLine.name(), "list of cell random seeds does not match number of populations") val rs_vector = make_rs_vector (cell_rs_seeds) val _ = D.maxstep := (!global_h) val _ = if minDelay <= 0.0 then raise Fail "minimum delay is zero" else () val _ = putStrLn TextIO.stdOut ("starting simulation...") val (_,t) = timing (fn () => start (N, S, D, DQ, Pn, Plabels, global_h, initial, frun, ftime, fspikes spikelog, finfo, tstop, logperiod, rs_vector, rszt_vector, (spikeout_filepath, stateout_prefix, extout_prefix, eventout_prefix), (statesample, extsample, evsample))) in putStrLn TextIO.stdOut ("simulation took " ^ (Time.toString t) ^ " s") end) end end val _ = let val name = CommandLine.name() val args = CommandLine.arguments() val env = Posix.ProcEnv.environ() in Sim_{{group.name}}.main (name, args) end