structure Sim_{{group.name}} = struct 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 val h = ref 0.1 structure TEventPriority = struct type priority = int (* Given a delay (positive real number), compute the priority given a time step *) fun delayPriority (delay) = Real.round (Real./ (delay, (!h))) (* Given a priority and a time step, computes the corresponding delay *) fun priorityDelay (priority,h) = Real.* (Real.fromInt priority, (!h)) fun compare (x,y) = Int.compare (x,y) type item = real * (int * (real IntMap.map)) fun priority (x : item) = delayPriority (#1(x)) end structure TEQ = FixTEventQueue (structure P = TEventPriority type value = (int * (real IntMap.map)) 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 printProjectionSummary S k = List.app (fn (W) => let val (m,n) = dimVals (SparseMatrix.shape W) in Loop.app (0, n, fn (i) => let val sl = SparseMatrix.slice (W,k,i) val sln = SparseMatrix.sliceFoldi (fn (j,x,n) => n+1) 0 sl val slsum = SparseMatrix.sliceFoldi (fn (j,x,ax) => Real.+(ax,x)) 0.0 sl in putStrLn TextIO.stdOut ("column " ^ (Int.toString i) ^ ": n = " ^ (Int.toString sln) ^ ": mean = " ^ (Real.toString (Real./(slsum, (Real.fromInt sln))))) end) end) S fun start (N, S, D, DQ, Pn, initial_vector, frun, ftime, fspikes, finfo, tstop, out) = let val sub = Unsafe.Real64Array.sub val isub = Unsafe.IntArray.sub val update = Unsafe.Real64Array.update fun netrun (DQ,state_vector) = let val t = ftime state_vector val prio = TEventPriority.delayPriority (t) val (I,DQ') = TEQ.nextEventsFold (fn (prio',_) => prio' <= prio, fn (prio,(port,w),ax) => let val t = TEventPriority.priorityDelay (prio, h) in IntMap.insert (ax,port,(t,w)) end, IntMap.empty, DQ) val (state_vector_i, spikes_i) = frun (!h) I state_vector val t_i = ftime state_vector_i val (spike_i, log_spike_i) = fspikes spikes_i val _ = finfo (state_vector_i, out) val W'' = if (List.null spike_i) then NONE else SOME (List.map (fn (W) => let val T = Real64Array.array (N, 0.0) in (List.app (fn (lst) => List.app (fn (i,nv) => let val sl = SparseMatrix.slice (W,1,i) in SparseMatrix.sliceAppi (fn (j,x) => update (T,j,Real.+ (Real.* (nv,x), sub(T,j)))) sl end) lst) spike_i; Real64Array.foldli (fn (i,v,m) => if not (Real.==(v, 0.0)) then IntMap.insert(m,i,v) else m) IntMap.empty T) end) S) val _ = if not (List.null log_spike_i) then (putStr out ((showReal t_i) ^ " "); List.app (fn(lst) => List.app (fn x => (TextIO.output(out, " " ^ (Int.toString x)))) (List.map (fn (i,n) => (i+1)) lst)) log_spike_i; TextIO.output(out, "\n")) else (putStrLn out ("# " ^ (showReal t_i))) val DQ'' = case W'' of SOME W => let val DW: (real list * (real IntMap.map) list) = (D,W) in (#2(ListPair.foldl (fn(del: real,w: real IntMap.map,(port,dq)) => let val tev = Real.+ (t_i,del) in (port+1, TEQ.addEvent ((tev, (port,w)), dq)) end) (0, DQ') DW)) end | NONE => DQ' in if t_i > tstop then (putStrLn out "# All done!"; state_vector_i) else netrun (DQ'',state_vector_i) end in netrun (DQ,initial_vector) 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 (_,out) = () 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_tol, is_statesample, is_extsample, is_evsample, is_spikerecord} = Options.getstate (opts) val _ = if is_help then exitHelp (CommandLine.name()) else () val _ = case is_timestep of SOME dt => (h := dt) | NONE => () val tstop = case is_time of SOME t => t | NONE => 150.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 => [] in (let val _ = putStrLn TextIO.stdOut ("starting fprojection...") val (S,t) = timing fprojection val _ = putStrLn TextIO.stdOut ("fprojection took " ^ (Time.toString t) ^ " s") val out = TextIO.openOut (label ^ ".dat") {% for pop in dict (group.populations) %} val _ = (if statesample > 0 then ({{pop.name}}_state_out := TextIO.openOut ("{{pop.name}}_state.dat")) else (); if extsample > 0 then ({{pop.name}}_ext_out := TextIO.openOut ("{{pop.name}}_ext.dat")) else (); if evsample > 0 then ({{pop.name}}_event_out := TextIO.openOut ("{{pop.name}}_event.dat")) else ()) {% endfor %} in List.app (fn (s) => putStrLn out ("# " ^ s)) ([ label ]); let val _ = putStrLn TextIO.stdOut ("starting simulation...") val (_,t) = timing (fn () => start (N, S, D, DQ, Pn, initial, frun (statesample,extsample,evsample), ftime, fspikes spikelog, finfo, tstop, out)) in putStrLn TextIO.stdOut ("simulation took " ^ (Time.toString t) ^ " s") end; TextIO.flushOut (out); TextIO.closeOut (out); {% for pop in dict (group.populations) %} if statesample > 0 then (TextIO.flushOut (!{{pop.name}}_state_out); TextIO.closeOut (!{{pop.name}}_state_out)) else (); if extsample > 0 then (TextIO.flushOut (!{{pop.name}}_ext_out); TextIO.closeOut (!{{pop.name}}_ext_out)) else (); if evsample > 0 then (TextIO.flushOut (!{{pop.name}}_event_out); TextIO.closeOut (!{{pop.name}}_event_out)) else (); {% endfor %} () 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