func main() { flag.Parse() if *doprof { f, err := os.Create(*fname + ".prof") if err != nil { log.Fatalf("error creating CPU-profiling file: %v\n", err) } defer f.Close() pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } log.SetFlags(0) log.SetPrefix("snfusion-gen: ") log.Printf("processing...\n") beg := time.Now() f, err := os.Create(*fname) if err != nil { log.Fatalf("error creating %s: %v\n", *fname, err) } defer f.Close() w := bufio.NewWriter(f) defer w.Flush() engine := sim.Engine{ NumIters: *nIters, NumCarbons: *nCarbons, Seed: *seed, } err = engine.Run(w) delta := time.Now().Sub(beg) log.Printf("processing... [done]: %v\n", delta) if err != nil { log.Fatalf("error running engine: %v\n", err) } }
func (c *client) run() { var err error dir, err := ioutil.TempDir("", "snfusion-web-") if err != nil { log.Printf("error creating temporary directory: %v\n", err) return } defer func() { c.srv.unregister <- c c.ws.Close() c.srv = nil os.RemoveAll(dir) }() type params struct { ID int `json:"id"` NumIters int `json:"num_iters"` NumCarbons float64 `json:"num_carbons"` Seed int64 `json:"seed"` } type genReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` Msg string `json:"msg"` Engine sim.Engine `json:"engine"` } type plotReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` SVG string `json:"svg"` } type zipReply struct { ID int `json:"id"` Stage string `json:"stage"` Err error `json:"err"` Href string `json:"href"` } for { param := params{ NumIters: 100000, NumCarbons: 60, Seed: 1234, } log.Printf("waiting for simulation parameters...\n") err = websocket.JSON.Receive(c.ws, ¶m) if err != nil { log.Printf("error rcv: %v\n", err) return } id := param.ID msgbuf := new(bytes.Buffer) msg := log.New(msgbuf, "snfusion-sim: ", 0) engine := sim.Engine{ NumIters: param.NumIters, NumCarbons: param.NumCarbons, Seed: param.Seed, } engine.SetLogger(msg) log.Printf("processing... %#v\n", engine) csvbuf := new(bytes.Buffer) errc := make(chan error) ticker := time.NewTicker(1 * time.Second) go func() { errc <- engine.Run(csvbuf) ticker.Stop() }() err = <-errc if err != nil { log.Printf("error: %v\n", err) _ = websocket.JSON.Send(c.ws, genReply{ ID: id, Err: err, Engine: engine, Stage: "gen-done", Msg: msgbuf.String(), }) return } err = websocket.JSON.Send(c.ws, genReply{ ID: id, Err: err, Engine: engine, Stage: "gen-done", Msg: msgbuf.String(), }) if err != nil { log.Printf("error sending data: %v\n", err) return } csvdata := make([]byte, len(csvbuf.Bytes())) copy(csvdata, csvbuf.Bytes()) log.Printf("running post-processing...\n") r := csv.NewReader(csvbuf) r.Comma = ';' r.Comment = '#' table := make([]plotter.XYs, len(engine.Population)) for i := range table { table[i] = make(plotter.XYs, engine.NumIters+1) } for ix := 0; ix < engine.NumIters+1; ix++ { var text []string text, err = r.Read() if err != nil { break } for i := range engine.Population { table[i][ix].X = float64(ix) table[i][ix].Y = float64(atoi(text[i])) } } if err == io.EOF { err = nil } if err != nil { log.Printf("error reading data: %v\n", err) return } p, err := plot.New() if err != nil { panic(err) } p.Title.Text = fmt.Sprintf( "Time evolution of nuclei C%v-O%v (seed=%d)", engine.NumCarbons, 100-engine.NumCarbons, engine.Seed, ) p.X.Label.Text = "Iteration number" p.Y.Label.Text = "Atomic mass of nuclei" for i, n := range engine.Population { line, err := plotter.NewLine(table[i]) if err != nil { log.Fatalf( "error adding data points for nucleus %v: %v\n", n, err, ) } line.LineStyle.Color = col(n) line.LineStyle.Width = vg.Points(1) p.Add(line) p.Legend.Add(label(n), line) } p.Add(plotter.NewGrid()) p.Legend.Top = true p.Legend.XOffs = -1 * vg.Centimeter figX := 25 * vg.Centimeter figY := figX / vg.Length(math.Phi) // Create a Canvas for writing SVG images. canvas := vgsvg.New(figX, figY) // Draw to the Canvas. p.Draw(draw.New(canvas)) outsvg := new(bytes.Buffer) _, err = canvas.WriteTo(outsvg) if err != nil { log.Printf("error svg: %v\n", err) return } err = websocket.JSON.Send(c.ws, plotReply{ ID: id, Err: err, SVG: outsvg.String(), Stage: "plot-done", }) if err != nil { log.Printf("error sending data: %v\n", err) return } pngcanvas := vgimg.PngCanvas{Canvas: vgimg.New(figX, figY)} p.Draw(draw.New(pngcanvas)) outpng := new(bytes.Buffer) _, err = pngcanvas.WriteTo(outpng) if err != nil { log.Printf("error png: %v\n", err) return } href := filepath.Join(dir, fmt.Sprintf("output-%d.zip", id)) zipf, err := os.Create(href) if err != nil { log.Printf("error creating zip file: %v\n", err) } defer zipf.Close() zipw := zip.NewWriter(zipf) defer zipw.Close() for _, file := range []struct { Name string Body []byte }{ {"output.csv", csvdata}, {"output.png", outpng.Bytes()}, } { ff, err := zipw.Create(file.Name) if err != nil { log.Printf("error creating zip content %v: %v\n", file.Name, err) return } _, err = ff.Write(file.Body) if err != nil { log.Printf("error writing zip content %v: %v\n", file.Name, err) return } } err = zipw.Close() if err != nil { log.Printf("error closing zip-writer: %v\n", err) return } err = zipf.Close() if err != nil { log.Printf("error closing zip-file: %v\n", err) return } err = websocket.JSON.Send(c.ws, zipReply{ ID: id, Err: err, Href: href, Stage: "zip-done", }) if err != nil { log.Printf("error sending zip: %v\n", err) return } log.Printf("saved report under %v\n", href) } }