diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 255 |
1 files changed, 131 insertions, 124 deletions
@@ -2,157 +2,164 @@ package main import ( "fmt" - g "github.com/AllenDang/giu" "image" - "image/draw" - _ "image/jpeg" "os" -) + "sync" -const ( - gasConstant = 8.314472 - airMolarMass = 0.0289647 // kg/mol + "github.com/faiface/mainthread" + "volute/gui" + "volute/gui/widget" + "volute/gui/win" ) -var ( - defaultDisplacement = 2 * Litre - defaultSpeed int32 = 2000 - defaultVE int32 = 80 - defaultTemperature = Temperature{25, Celcius} -) - -var ( - defaultManufacturer = "borgwarner" - defaultSeries = "efr" - defaultModel = "6258" -) - -// Number of data points on the compressor map. -var numPoints = 1 - -var ( - displacement = defaultDisplacement - volumeUnitIndex int32 - - // Angular crankshaft speed in RPM. - speed = []int32{defaultSpeed} +const ( + WIDTH = 800 + HEIGHT = 600 - volumetricEfficiency = []int32{defaultVE} + POINTS = 6 - intakeAirTemperature = []Temperature{defaultTemperature} - temperatureUnitIndex int32 + R = 8314.3 // gas constant + M = 28.962 // molar mass of air - manifoldPressure = []Pressure{AtmosphericPressure()} - pressureUnitIndex int32 + WIDEST_LABEL = "mass flow (kg/min)" ) -var pressureRatio []float32 +func run() { + wg := new(sync.WaitGroup) + defer wg.Wait() -func pressureRatioAt(point int) float32 { - u := Pascal - m := manifoldPressure[point] / u - a := AtmosphericPressure() / u - return float32(m / a) -} -func init() { - pressureRatio = append(pressureRatio, pressureRatioAt(0)) -} - -var ( - massFlowRateAir []MassFlowRate - massFlowRateUnitIndex int32 -) + focus := widget.NewFocus([]int{1, POINTS, POINTS, POINTS, POINTS}) + defer focus.Close() -func massFlowRateAt(point int) MassFlowRate { - rpm := float32(speed[point]) - disp := float32(displacement / CubicMetre) - ve := float32(volumetricEfficiency[point]) / 100.0 - cubicMetresPerMin := (rpm / 2.0) * disp * ve + displacementChan := make(chan uint) + displacementBroadcast := NewBroadcast(displacementChan) + defer displacementBroadcast.Wait() - iat, err := intakeAirTemperature[point].AsUnit(Kelvin) - Check(err) - pres := manifoldPressure[point] / Pascal - molsPerMin := (float32(pres) * cubicMetresPerMin) / (gasConstant * iat) + var ( + rpmChan [POINTS]chan uint + veChan [POINTS]chan uint + imapChan [POINTS]chan uint + actChan [POINTS]chan uint - kgPerMin := molsPerMin * airMolarMass + flowChan [POINTS]chan float64 + ) + makeChans(rpmChan[:], veChan[:], imapChan[:], actChan[:]) + makeChans(flowChan[:]) - mfr := MassFlowRate(kgPerMin/60.0) * KilogramsPerSecond - return mfr -} -func init() { - massFlowRateAir = append(massFlowRateAir, massFlowRateAt(0)) -} + w, err := win.New(win.Title("volute"), win.Size(WIDTH, HEIGHT)) + if err != nil { + fmt.Println("error creating window:", err) + os.Exit(1) + } + mux, env := gui.NewMux(w) + defer close(env.Draw()) + + spawnWidgets( + displacementChan, + rpmChan, veChan, imapChan, actChan, + flowChan, + &focus, + mux, + wg, + ) -var ( - compressorImage *image.RGBA - compressorTexture *g.Texture - selectedCompressor Compressor -) + imChan := make(chan image.Image) + defer close(imChan) + wg.Add(1) + go widget.Image( + imChan, + image.Rect(0, 200, 100, 300), + mux.MakeEnv(), + wg, + ) -func init() { - manufacturer := defaultManufacturer - series := defaultSeries - model := defaultModel - c, ok := Compressors[manufacturer][series][model] - if !ok { - fmt.Printf("compressor.Compressors()[\"%s\"][\"%s\"][\"%s\"] does not exist.\n", - manufacturer, series, model, + for i := 0; i < POINTS; i++ { + wg.Add(1) + go calculateFlow( + flowChan[i], + displacementBroadcast.AddDestination(), + rpmChan[i], veChan[i], actChan[i], imapChan[i], + wg, ) - os.Exit(1) } - setCompressor(c) + focus.Focus(true) + eventLoop(env, &focus) } -func main() { - wnd := g.NewMasterWindow("volute", 400, 200, 0) - - go updateCompImg() - m := <-updatedCompImg - g.EnqueueNewTextureFromRgba(m, func(tex *g.Texture) { - compressorTexture = tex - }) - - wnd.Run(loop) +func eventLoop(env gui.Env, focus *widget.Focus) { + for event := range env.Events() { + switch event := event.(type) { + case win.WiClose: + return + case win.KbType: + switch event.Rune { + case 'q': + return + case 'h': + focus.Left() + case 'j': + focus.Down() + case 'k': + focus.Up() + case 'l': + focus.Right() + } + } + } } -func setCompressor(c Compressor) { - f, err := os.Open(c.FileName) - Check(err) - defer f.Close() - - j, _, err := image.Decode(f) - Check(err) +func makeChans[T any](chanss ...[]chan T) { + for i := range chanss { + for j := range chanss[i] { + chanss[i][j] = make(chan T) + } + } +} - b := j.Bounds() - m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) - draw.Draw(m, m.Bounds(), j, b.Min, draw.Src) +func calculateFlow( + flow chan<- float64, + displacementChan, rpmChan, veChan, actChan, imapChan <-chan uint, + wg *sync.WaitGroup, +) { + defer wg.Done() + defer close(flow) + + var ( + displacement Volume + rpm uint + ve uint + act Temperature + imap Pressure + + v uint + ok bool + ) - selectedCompressor = c - compressorImage = m + for { + select { + case v, ok = <-displacementChan: + displacement = Volume(v) * CubicCentimetre + case rpm, ok = <-rpmChan: + case ve, ok = <-veChan: + case v, ok = <-actChan: + act = Temperature{float64(v), Celcius} + case v, ok = <-imapChan: + imap = Pressure(v) * Millibar + } + if !ok { + return + } + flow <- massFlow(displacement, rpm, ve, act, imap) + } +} - go updateCompImg() +func massFlow(displacement Volume, rpm, ve uint, act Temperature, imap Pressure) float64 { + density := (M / R) * float64(imap/Pascal) / act.AsUnit(Kelvin) // kg/m3 + volumeFlow := float64(displacement/CubicMetre) * float64(rpm/2) * (float64(ve) / 100.0) // m3/min + return density * volumeFlow } -func loop() { - g.SingleWindow().Layout( - displacementRow(), - g.Table(). - Size(g.Auto, 190). - Rows( - speedRow(), - volumetricEfficiencyRow(), - intakeAirTemperatureRow(), - manifoldPressureRow(), - pressureRatioRow(), - massFlowRateRow(), - duplicateDeleteRow(), - ). - Columns( - columns()..., - ). - Flags(g.TableFlagsSizingFixedFit), - selectCompressor(), - g.Custom(compressorWidget), - ) +func main() { + mainthread.Run(run) } |