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.01 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 printProjectionSummary S k = List.app (fn (W) => let val (m,n) = dimVals (BitSparseMatrix.shape W) in Loop.app (0, n, fn (i) => let val sl = BitSparseMatrix.slice (W,k,i) val sln = BitSparseMatrix.sliceFoldi (fn (j,x,n) => n+1) 0 sl in putStrLn TextIO.stdOut ("column " ^ (Int.toString i) ^ ": n = " ^ (Int.toString sln)) end) end) S fun start (N, S, D, DQ, Pn, initial_vector, frun, fspikes, finfo, tstop, out) = let val sub = Unsafe.Real64Array.sub val isub = Unsafe.IntArray.sub val update = Unsafe.Real64Array.update fun enqueueSpikes (spike_i, S, D, DQ) = {{group.name}}.SEQ.PQ.foldl (fn ((t,i),dq) => (#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 (DQ,t,state_vector) = let val tn = t+(!h) val t_i = case TEQ.findMin DQ of SOME (t,_) => Real.min(t, tn) | NONE => tn val (I,DQ') = TEQ.nextEventsFold (fn (t,_) => Real.<=(t,t_i), fn (t,(i,port,w),I) => let val im = IntMap.find (I, i) val im = case im of SOME m => IntMap.insert (m,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) = frun (t_i,I) state_vector val (ext_spike_i, log_spike_i) = fspikes spikes_i val _ = finfo (state_vector_i, out) val DQ'' = enqueueSpikes (ext_spike_i, S, D, DQ') val DQ''' = enqueueSpikes (log_spike_i, S, D, DQ'') val _ = if not ({{group.name}}.SEQ.isEmpty log_spike_i) then ({{group.name}}.SEQ.nextEventsApp (fn (t,i) => putStrLn out ((showReal t) ^ " " ^ (Int.toString (i + 1))), log_spike_i)) else (putStrLn out ("# " ^ (showReal t_i))) in if t_i > tstop then (putStrLn out "# All done!"; state_vector_i) else netrun (DQ''',t_i,state_vector_i) end in netrun (DQ,0.0,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_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_timestep of SOME dt => (h := dt) | NONE => () val tstop = case is_time of SOME t => t | NONE => 150.0 val _ = case is_tol of SOME tol => ({{group.name}}.D.tol := tol) | NONE => () 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 ("constructing projections...") val (S,t) = timing fprojection val _ = putStrLn TextIO.stdOut ("projections 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), 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