diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..a91e2e5b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +[*.vb] +tab_width = 4 +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true + +# IDE1006: Naming Styles +dotnet_diagnostic.IDE1006.severity = none diff --git a/BlueM.Opt.sln b/BlueM.Opt.sln index 9e744783..b3ea9321 100644 --- a/BlueM.Opt.sln +++ b/BlueM.Opt.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.6.11806.211 stable +VisualStudioVersion = 18.6.11806.211 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlueM.Opt.Algos", "BlueM.Opt.Algos", "{44D440EE-4641-44A1-B177-2DD0FDD6FB75}" EndProject @@ -38,6 +38,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlueM.Opt.Tests", "BlueM.Op EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BlueM.Opt.Tests", "BlueM.Opt\Tests\BlueM.Opt.Tests\BlueM.Opt.Tests.vbproj", "{BBDDC177-F059-4139-9A0E-C4B7D03F2786}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5A9D3221-E48E-4A26-9F13-090359144136}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 diff --git a/BlueM.Opt/Apps/BlueM.Opt.Apps.vbproj b/BlueM.Opt/Apps/BlueM.Opt.Apps.vbproj index dca74993..ebf6ea6b 100644 --- a/BlueM.Opt/Apps/BlueM.Opt.Apps.vbproj +++ b/BlueM.Opt/Apps/BlueM.Opt.Apps.vbproj @@ -117,9 +117,20 @@ + + + + TALSIM5_Dialog.vb + + + Form + + + Always + @@ -128,6 +139,9 @@ My.Resources Designer + + TALSIM5_Dialog.vb + @@ -192,6 +206,9 @@ + + 10.0.8 + 4.2023.4.18 diff --git a/BlueM.Opt/Apps/Sim.vb b/BlueM.Opt/Apps/Sim.vb index 12ad8920..4f6affc4 100644 --- a/BlueM.Opt/Apps/Sim.vb +++ b/BlueM.Opt/Apps/Sim.vb @@ -534,7 +534,7 @@ Public MustInherit Class Sim 'ModellParameter aus OptParametern errechnen '******************************************* - Private Sub OptParameter_to_ModellParameter() + Protected Sub OptParameter_to_ModellParameter() Dim i As Integer Dim j As Integer @@ -555,7 +555,7 @@ Public MustInherit Class Sim 'Die ModellParameter in die Eingabedateien des SimModells schreiben '****************************************************************** - Public Sub Write_ModellParameter() + Public Overridable Sub Write_ModellParameter() Dim WertStr As String Dim AnzZeichen, AnzNachkomma As Short diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM.vb b/BlueM.Opt/Apps/TALSIM/TALSIM.vb index 0518e887..21524a63 100644 --- a/BlueM.Opt/Apps/TALSIM/TALSIM.vb +++ b/BlueM.Opt/Apps/TALSIM/TALSIM.vb @@ -30,12 +30,12 @@ Public Class Talsim #Region "Eigenschaften" - Private exe_path As String + Private ReadOnly exe_path As String ''' ''' List of result file extensions to use (e.g. "WEL", "KTR.WEL", "CHLO.WEL", "WBL", etc.) ''' - Private resultFiles As List(Of String) + Private ReadOnly resultFiles As List(Of String) '**** Multithreading **** Dim MyTalsimThreads() As TalsimThread @@ -264,8 +264,9 @@ Public Class Talsim Folder = getThreadWorkDir(Thread_ID) MyTalsimThreads(Thread_ID) = New TalsimThread(Thread_ID, Child_ID, Folder, Datensatz) - MyThreads(Thread_ID) = New Thread(AddressOf MyTalsimThreads(Thread_ID).launchSim) - MyThreads(Thread_ID).IsBackground = True + MyThreads(Thread_ID) = New Thread(AddressOf MyTalsimThreads(Thread_ID).launchSim) With { + .IsBackground = True + } MyThreads(Thread_ID).Start() launchSim = True @@ -325,12 +326,13 @@ Public Class Talsim Dim errfile As String = IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & ".err") Dim simendfile As String = IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & ".SIMEND") Dim proc As Process - Dim startInfo As New ProcessStartInfo() - startInfo.FileName = Me.exe_path - startInfo.Arguments = runfilename - startInfo.UseShellExecute = True - startInfo.WindowStyle = ProcessWindowStyle.Hidden - startInfo.WorkingDirectory = IO.Path.GetDirectoryName(Me.exe_path) + Dim startInfo As New ProcessStartInfo With { + .FileName = Me.exe_path, + .Arguments = runfilename, + .UseShellExecute = True, + .WindowStyle = ProcessWindowStyle.Hidden, + .WorkingDirectory = IO.Path.GetDirectoryName(Me.exe_path) + } 'start proc = Process.Start(startInfo) 'DEBUG: write to log diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM5.vb b/BlueM.Opt/Apps/TALSIM/TALSIM5.vb new file mode 100644 index 00000000..6acbb0fe --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/TALSIM5.vb @@ -0,0 +1,488 @@ +'BlueM.Opt +'Copyright (C) BlueM Dev Group +'Website: +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU General Public License for more details. +' +'You should have received a copy of the GNU General Public License +'along with this program. If not, see . +' +Imports System.Threading +Imports System.Windows.Forms +Imports BlueM.Opt.Common +Imports Microsoft.Data.Sqlite + +''' +''' Class TALSIM5 for carrying out simulations using TALSIM5 (same simulation executable but different dataset format than TALSIM4) +''' +''' +Public Class Talsim5 + Inherits Sim + + Private ReadOnly exe_path As String + Private scenarioId As Integer + Private simulationId As Integer + Private timeseriesPath As String + + ''' + ''' List of result file extensions to use (e.g. "WEL", "KTR.WEL", "CHLO.WEL", "WBL", etc.) + ''' + Private ReadOnly resultFiles As List(Of String) + + '**** Multithreading **** + Dim MyTalsimThreads() As Talsim5Thread + Dim MyThreads() As Thread + + ''' + ''' Class to represent a scenario in a TALSIM5 database + ''' + Friend Class Scenario + Public Id As Integer + Public Name As String + Public Overrides Function ToString() As String + Return $"{Id}: {Name}" + End Function + End Class + + ''' + ''' Class to represent a simulation in a Talsim5 database + ''' + Friend Class Simulation + Public Id As Integer + Public Name As String + Public Overrides Function ToString() As String + Return $"{Id}: {Name}" + End Function + End Class + + ''' + ''' Alle Dateiendungen (ohne Punkt), die in einem Datensatz vorkommen können + ''' + ''' Die erste Dateiendung in dieser Collection repräsentiert den Datensatz (wird z.B. als Filter für OpenFile-Dialoge verwendet) + Public Overrides ReadOnly Property DatensatzDateiendungen() As Collections.Specialized.StringCollection + Get + Dim exts As New Collections.Specialized.StringCollection() + + exts.AddRange(New String() {"DB", "SCE", "QAB", "UPD", "VAR", "OPF", "ZIE", "PRO", "RFD", "ABZ"}) + + Return exts + + End Get + End Property + + ''' + ''' Ob die Anwendung Multithreading unterstützt + ''' + ''' True + Public Overrides ReadOnly Property MultithreadingSupported As Boolean = True + + ''' + ''' Path to the database file (in the current working directory) + ''' + ''' + Private ReadOnly Property DBFile As String + Get + Return IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & ".db") + End Get + End Property + + 'Konstruktor + '*********** + Public Sub New() + + Call MyBase.New() + + 'Daten belegen + '------------- + Me.resultFiles = New List(Of String) + + 'Pfad zu talsimw64.exe bestimmen + '------------------------------- + 'attempt to get exe_path from UserSettings + exe_path = My.Settings.TALSIM_path + + If (Not IO.File.Exists(exe_path)) Then + 'use default location instead + exe_path = IO.Path.Combine(System.Windows.Forms.Application.StartupPath(), "TALSIM\talsimw64.exe") + If My.Settings.TALSIM_path.Trim() <> "" Then + MsgBox($"UserSetting for TALSIM_path {My.Settings.TALSIM_path} was not found.{eol}Using default {exe_path} instead.", MsgBoxStyle.Information) + End If + End If + + If (Not IO.File.Exists(exe_path)) Then + Throw New Exception(exe_path & " not found!") + End If + + End Sub + + ''' + ''' TALSIM Simulationen vorbereiten + ''' + Public Overrides Sub prepareSimulation() + + Call MyBase.prepareSimulation() + + 'Thread-Objekte instanzieren + Talsim5Thread.exe_path = Me.exe_path + ReDim MyTalsimThreads(n_Threads - 1) + For i = 0 To n_Threads - 1 + MyTalsimThreads(i) = New Talsim5Thread(i, -1, "Folder", Datensatz, Me.scenarioId, Me.simulationId, Me.timeseriesPath) + MyTalsimThreads(i).set_is_OK() + Next + ReDim MyThreads(n_Threads - 1) + + End Sub + + Public Overrides Sub setProblem(ByRef prob As BlueM.Opt.Common.Problem) + + Call MyBase.setProblem(prob) + + 'TALSIM-spezifische Weiterverarbeitung von ZielReihen: + Dim objective As Common.ObjectiveFunction + + 'Feststellen, welche WEL/WBL-Dateien in Zielfunktionen genutzt werden + For Each objective In Me.mProblem.List_ObjectiveFunctions + If Not IsNothing(objective.FileExtension) Then + Dim fileExtension As String = objective.FileExtension.ToUpper() + If Not Me.resultFiles.Contains(fileExtension) Then + Me.resultFiles.Add(fileExtension) + End If + End If + Next + + 'Feststellen, welche WEL/WBL-Dateien in Constraints genutzt werden + For Each constr As Constraintfunction In Me.mProblem.List_Constraintfunctions + Dim fileExtension As String = constr.Datei.ToUpper() + If Not Me.resultFiles.Contains(fileExtension) Then + Me.resultFiles.Add(fileExtension) + End If + Next + + End Sub + + ''' + ''' Simulationsparameter einlesen + ''' + Protected Overrides Sub Read_SimParameter() + + 'Show Talsim5 settings dialog + Dim dlg As New TALSIM5_Dialog(Me.DBFile) + If dlg.ShowDialog() <> DialogResult.OK Then + Throw New Exception("Talsim5 settings not set!") + End If + 'save settings from dialog + Me.scenarioId = dlg.SelectedScenario.Id + Me.simulationId = dlg.SelectedSimulation.Id + Me.timeseriesPath = dlg.TimeseriesPath + + 'read simulation start and end from database + Using connection As New SqliteConnection($"Data Source={Me.DBFile}") + connection.Open() + Using command As SqliteCommand = connection.CreateCommand() + command.CommandText = " + SELECT SimulationStart, SimulationEnd, TimeStep + FROM Simulation + WHERE Id = @SimulationId + " + command.Parameters.AddWithValue("@SimulationId", Me.simulationId) + Using reader As SqliteDataReader = command.ExecuteReader() + While reader.Read() + Me.SimStart = reader.GetDateTime(0) + Me.SimEnde = reader.GetDateTime(1) + 'TODO: what if we have a monthly timestep? + Me.SimDT = New TimeSpan(0, reader.GetInt32(2), 0) + End While + End Using + End Using + connection.Close() + End Using + + End Sub + + ''' + ''' Gibt zurück ob ein beliebiger Thread beendet ist und gibt die ID diesen freien Threads zurück + ''' + ''' + ''' + ''' + Protected Overrides Function ThreadFree(ByRef Thread_ID As Integer) As Boolean + ThreadFree = False + + For Each Thr_C As Talsim5Thread In MyTalsimThreads + If Thr_C.Sim_Is_OK = True And Thr_C.get_Child_ID = -1 Then + ThreadFree = True + Thread_ID = Thr_C.get_Thread_ID + Exit For + End If + Next + + End Function + + ''' + ''' Carry out a multithreaded simulation + ''' + ''' + ''' + ''' + ''' starts a new thread and gives it the Child_ID + Protected Overrides Function launchSim(ByVal Thread_ID As Integer, ByVal Child_ID As Integer) As Boolean + + launchSim = False + Dim Folder As String + + Folder = getThreadWorkDir(Thread_ID) + MyTalsimThreads(Thread_ID) = New Talsim5Thread(Thread_ID, Child_ID, Folder, Datensatz, Me.scenarioId, Me.simulationId, Me.timeseriesPath) + MyThreads(Thread_ID) = New Thread(AddressOf MyTalsimThreads(Thread_ID).launchSim) With { + .IsBackground = True + } + MyThreads(Thread_ID).Start() + launchSim = True + + Return launchSim + + End Function + + ''' + ''' Carry out a simulation (single-threaded) + ''' + ''' + ''' + Protected Overrides Function launchSim() As Boolean + + Dim filestr As IO.FileStream + Dim strread As IO.StreamReader + Dim simOK As Boolean + Dim isFinished As Boolean + + Try + + 'write the required settings into a new run file + 'this is done for every simulation because the workdir may change + Dim runfile As String = IO.Path.Combine(IO.Path.GetDirectoryName(exe_path), "talsim5.run") + If (Not IO.File.Exists(runfile)) Then + Throw New Exception(runfile & " not found!") + End If + Dim line As String + 'read the template run file + filestr = New IO.FileStream(runfile, IO.FileMode.Open, IO.FileAccess.Read) + strread = New IO.StreamReader(filestr, System.Text.Encoding.GetEncoding("iso8859-1")) + Dim lines As New Collections.Generic.List(Of String) + Do + line = strread.ReadLine() + lines.Add(line) + Loop Until strread.Peek = -1 + strread.Close() + filestr.Close() + + 'write a new run file + Dim runfilename As String = MyBase.Datensatz & ".run" + runfile = IO.Path.Combine(IO.Path.GetDirectoryName(Me.exe_path), runfilename) + Dim strwrite As New IO.StreamWriter(runfile, False, System.Text.Encoding.GetEncoding("iso8859-1")) + For Each line In lines + If line.StartsWith("Path=") Then + line = "Path=" & MyBase.WorkDir_Current + ElseIf line.StartsWith("System=") Then + line = "System=" & MyBase.Datensatz + ElseIf line.StartsWith("DBFile=") Then + line = "DBFile=" & Me.DBFile + ElseIf line.StartsWith("ZrePath=") Then + line = "ZrePath=" & Me.timeseriesPath & "\" + ElseIf line.StartsWith("ScenarioId=") Then + line = "ScenarioId=" & Me.scenarioId.ToString() + ElseIf line.StartsWith("SimulationId=") Then + line = "SimulationId=" & Me.simulationId.ToString() + End If + strwrite.WriteLine(line) + Next + strwrite.Close() + + 'TALSIM starten + Dim errfile As String = IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & ".err") + Dim simendfile As String = IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & ".SIMEND") + Dim proc As Process + Dim startInfo As New ProcessStartInfo With { + .FileName = Me.exe_path, + .Arguments = runfilename, + .UseShellExecute = True, + .WindowStyle = ProcessWindowStyle.Hidden, + .WorkingDirectory = IO.Path.GetDirectoryName(Me.exe_path) + } + 'start + proc = Process.Start(startInfo) + 'DEBUG: write to log + 'BlueM.Opt.Common.Log.AddMessage(startInfo.FileName & " " & startInfo.Arguments) + 'wait until finished + Do + isFinished = proc.WaitForExit(100) + System.Windows.Forms.Application.DoEvents() + Loop Until isFinished + 'close the process + proc.Close() + + 'if .ERR file exists, simulation finished with errors + If IO.File.Exists(errfile) Then + 'read err-file + Dim errmsg As String = "TALSIM simulation ended with errors:" + filestr = New IO.FileStream(errfile, IO.FileMode.Open, IO.FileAccess.Read) + strread = New IO.StreamReader(filestr, System.Text.Encoding.GetEncoding("iso8859-1")) + Do + line = strread.ReadLine() + errmsg &= BlueM.Opt.Common.eol & line + Loop Until strread.Peek = -1 + strread.Close() + filestr.Close() + + Throw New Exception(errmsg) + End If + + 'if .SIMEND does not exist, simulation aborted prematurely + If Not IO.File.Exists(simendfile) Then + Throw New Exception("TALSIM simulation aborted prematurely!") + End If + + 'Simulation erfolgreich + simOK = True + + Catch ex As Exception + + 'Simulationsfehler aufgetreten + Common.Log.AddMessage(Common.Log.levels.error, ex.Message) + + 'Simulation nicht erfolgreich + simOK = False + + Finally + + 'nothing to do + + End Try + + Return simOK + + End Function + + ''' + ''' Prüft ob das aktuelle Child mit der ID die oben übergeben wurde fertig ist + ''' Gibt die Thread ID zurück um zum auswerten in das Arbeitsverzeichnis zu wechseln + ''' + ''' + ''' + ''' + ''' + ''' + Protected Overrides Function ThreadReady(ByRef Thread_ID As Integer, ByRef SimIsOK As Boolean, ByVal Child_ID As Integer) As Boolean + ThreadReady = False + + For Each Thr_C As Talsim5Thread In MyTalsimThreads + If Thr_C.launch_Ready = True And Thr_C.get_Child_ID = Child_ID Then + ThreadReady = True + SimIsOK = Thr_C.Sim_Is_OK + Thread_ID = Thr_C.get_Thread_ID + MyThreads(Thread_ID).Join() + MyTalsimThreads(Thread_ID) = New Talsim5Thread(Thread_ID, -1, "Folder", Datensatz, Me.scenarioId, Me.simulationId, Me.timeseriesPath) + MyTalsimThreads(Thread_ID).set_is_OK() + End If + Next + + End Function + + ''' + ''' Update model parameters in database + ''' + Public Overrides Sub Write_ModellParameter() + + 'ModellParameter aus OptParametern kalkulieren() + Call MyBase.OptParameter_to_ModellParameter() + + Try + Using connection As New SqliteConnection($"Data Source={Me.DBFile}") + connection.Open() + Dim i As Integer = 0 + Using transaction As SqliteTransaction = connection.BeginTransaction() + For Each modParam As Struct_ModellParameter In Me.mProblem.List_ModellParameter + Try + Using command As SqliteCommand = connection.CreateCommand() + command.CommandText = $" + UPDATE {modParam.DBTable} + SET {modParam.DBField} = @Value + WHERE Id = @Id + " + command.Parameters.AddWithValue("@Value", Me.Akt.ModPara(i)) + command.Parameters.AddWithValue("@Id", modParam.DBId) + Dim nrows As Integer = command.ExecuteNonQuery() + If nrows = 0 Then + Throw New Exception($"No row with Id {modParam.DBId} found in table {modParam.DBTable} for updating model parameter '{modParam.Bezeichnung}'!") + End If + i += 1 + End Using + Catch ex As Exception + Throw New Exception($"Error while updating model parameter '{modParam.Bezeichnung}' in database: {ex.Message}", ex) + End Try + Next + transaction.Commit() + End Using + connection.Close() + End Using + Catch ex As Exception + Throw New Exception($"Error while updating model parameters in database: {ex.Message}", ex) + End Try + + End Sub + + ''' + ''' Simulationsergebnis lesen + ''' + ''' + Protected Overrides Sub SIM_Ergebnis_Lesen() + + 'Altes Simulationsergebnis löschen + Me.SimResult.Clear() + + 'Collect required result files and series + 'TODO: das braucht eigentlich nicht nach jeder Simulation nochmal neu getan zu werden + Dim seriesMap As New Dictionary(Of String, List(Of String)) '{file: [series]} + For Each fileExtension As String In Me.resultFiles + seriesMap.Add(fileExtension, New List(Of String)) + Next + For Each objfunc As ObjectiveFunction In Me.mProblem.List_ObjectiveFunctions + If objfunc.GetObjType = ObjectiveFunction.ObjectiveType.Series Or + objfunc.GetObjType = ObjectiveFunction.ObjectiveType.ValueFromSeries Then + If Not seriesMap(objfunc.FileExtension.ToUpper()).Contains(objfunc.SimResultName) Then + seriesMap(objfunc.FileExtension.ToUpper()).Add(objfunc.SimResultName) + End If + End If + Next + For Each constr As Constraintfunction In Me.mProblem.List_Constraintfunctions + If Not seriesMap(constr.Datei.ToUpper()).Contains(constr.SimGr) Then + seriesMap(constr.Datei.ToUpper()).Add(constr.SimGr) + End If + Next + + 'Read result series from file + For Each fileExtension As String In Me.resultFiles + + 'get a file instance + Dim fileInstance As Wave.TimeSeriesFile = Wave.TimeSeriesFile.getInstance(IO.Path.Combine(Me.WorkDir_Current, Me.Datensatz & "." & fileExtension)) + 'select required series for import + For Each series As String In seriesMap(fileExtension) + fileInstance.selectSeries(series) + Next + 'read the file + fileInstance.readFile() + 'add time series to SimResults + For Each ts As Wave.TimeSeries In fileInstance.TimeSeries.Values + Me.SimResult.Series.Add(ts.Title, ts) + Next + Next + + End Sub + + End Class \ No newline at end of file diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM5Thread.vb b/BlueM.Opt/Apps/TALSIM/TALSIM5Thread.vb new file mode 100644 index 00000000..e93a9f89 --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/TALSIM5Thread.vb @@ -0,0 +1,223 @@ +'BlueM.Opt +'Copyright (C) BlueM Dev Group +'Website: +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU General Public License for more details. +' +'You should have received a copy of the GNU General Public License +'along with this program. If not, see . +' +''' +''' Klasse beinhaltet alle Infomationen für einen Simulationslauf im Thread +''' +''' +Public Class Talsim5Thread + + Private ReadOnly Thread_ID As Integer + Private ReadOnly Child_ID As Integer + Private ReadOnly WorkFolder As String + Private ReadOnly DS_Name As String + Private ReadOnly ScenarioId As Integer + Private ReadOnly SimulationId As Integer + Private ReadOnly TimeseriesPath As String + Private SimIsOK As Boolean + Private launchReady As Boolean + Public Shared exe_path As String + + ''' + ''' Path to the database file (in the thread's working directory) + ''' + ''' + Private ReadOnly Property DBFile As String + Get + Return IO.Path.Combine(Me.WorkFolder, Me.DS_Name & ".db") + End Get + End Property + + Public Sub New(_Thread_ID As Integer, _Child_ID As Integer, _WorkFolder As String, _DS_Name As String, scenarioId As Integer, simulationId As Integer, timeseriesPath As String) + Me.Thread_ID = _Thread_ID + Me.Child_ID = _Child_ID + Me.WorkFolder = _WorkFolder + Me.DS_Name = _DS_Name + Me.ScenarioId = scenarioId + Me.SimulationId = simulationId + Me.TimeseriesPath = timeseriesPath + End Sub + + ''' + ''' Die Funktion startet die Simulation mit dem entsprechendem WorkingDir + ''' + ''' + Public Sub launchSim() + + Dim filestr As IO.FileStream + Dim strread As IO.StreamReader + + Me.SimIsOK = False + Dim isFinished As Boolean + Me.launchReady = False + + 'Priority + System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Normal + + Try + 'write the required settings into a new run file + 'this is done for every simulation because otherwise we would have to keep track of runfiles and thread IDs separately + Dim runfile As String = IO.Path.Combine(IO.Path.GetDirectoryName(exe_path), "talsim5.run") + If (Not IO.File.Exists(runfile)) Then + Throw New Exception(runfile & " not found!") + End If + Dim line As String + 'read the template run file + filestr = New IO.FileStream(runfile, IO.FileMode.Open, IO.FileAccess.Read) + strread = New IO.StreamReader(filestr, System.Text.Encoding.GetEncoding("iso8859-1")) + Dim lines As New Collections.Generic.List(Of String) + Do + line = strread.ReadLine() + lines.Add(line) + Loop Until strread.Peek = -1 + strread.Close() + filestr.Close() + + 'write a new run file + Dim runfilename As String = $"{Me.DS_Name}_{Me.Thread_ID}.run" + runfile = IO.Path.Combine(IO.Path.GetDirectoryName(Talsim5Thread.exe_path), runfilename) + Dim strwrite As New IO.StreamWriter(runfile, False, System.Text.Encoding.GetEncoding("iso8859-1")) + For Each line In lines + If line.StartsWith("Path=") Then + line = "Path=" & Me.WorkFolder + ElseIf line.StartsWith("System=") Then + line = "System=" & Me.DS_Name + ElseIf line.StartsWith("DBFile=") Then + line = "DBFile=" & Me.dbfile + ElseIf line.StartsWith("ZrePath=") Then + line = "ZrePath=" & Me.TimeseriesPath & "\" + ElseIf line.StartsWith("ScenarioId=") Then + line = "ScenarioId=" & Me.scenarioId.ToString() + ElseIf line.StartsWith("SimulationId=") Then + line = "SimulationId=" & Me.simulationId.ToString() + End If + strwrite.WriteLine(line) + Next + strwrite.Close() + + 'TALSIM starten + Dim errfile As String = IO.Path.Combine(Me.WorkFolder, Me.DS_Name & ".err") + Dim errmsg As String + Dim simendfile As String = IO.Path.Combine(Me.WorkFolder, Me.DS_Name & ".SIMEND") + Dim proc As Process + Dim startInfo As New ProcessStartInfo With { + .FileName = Talsim5Thread.exe_path, + .Arguments = runfilename, + .UseShellExecute = True, + .WindowStyle = ProcessWindowStyle.Hidden, + .WorkingDirectory = IO.Path.GetDirectoryName(Talsim5Thread.exe_path) + } + + 'Carry out up to 5 simulation attempts, because TALSIM sometimes blocks access to the time series files in multithreading mode + Dim n_attempts As Integer = 5 + For i_attempt As Integer = 1 To n_attempts + + errmsg = "" + Me.SimIsOK = False + + 'start + proc = Process.Start(startInfo) + 'DEBUG: write to log + 'BlueM.Opt.Common.Log.AddMessage($"Thread {Me.Thread_ID}: {startInfo.FileName} {startInfo.Arguments}") + 'wait until finished + Do + isFinished = proc.WaitForExit(100) + System.Windows.Forms.Application.DoEvents() + Loop Until isFinished + 'close the process + proc.Close() + + 'Simulation erfolgreich? + If Not IO.File.Exists(errfile) And IO.File.Exists(simendfile) Then + Me.SimIsOK = True + Exit For + End If + + 'if .ERR file exists, simulation finished with errors + If IO.File.Exists(errfile) Then + 'read err-file + errmsg = $"Thread {Me.Thread_ID}: TALSIM simulation ended with errors:" + filestr = New IO.FileStream(errfile, IO.FileMode.Open, IO.FileAccess.Read) + strread = New IO.StreamReader(filestr, System.Text.Encoding.GetEncoding("iso8859-1")) + Do + line = strread.ReadLine() + errmsg &= BlueM.Opt.Common.eol & line + Loop Until strread.Peek = -1 + strread.Close() + filestr.Close() + End If + + 'if .SIMEND does not exist, simulation aborted prematurely + If Not IO.File.Exists(simendfile) Then + errmsg = $"Thread {Me.Thread_ID}: TALSIM simulation aborted prematurely!" + End If + + 'Log error message + Common.Log.AddMessage(Common.Log.levels.error, errmsg) + + If i_attempt < n_attempts Then + Common.Log.AddMessage(Common.Log.levels.error, $"Thread {Me.Thread_ID}: TALSIM simulation attempt {i_attempt} was unsuccessful, trying again...") + System.Threading.Thread.Sleep(100) + Else + Common.Log.AddMessage(Common.Log.levels.error, $"Thread {Me.Thread_ID}: TALSIM simulation attempt {i_attempt} was unsuccessful, parameter set will be discarded!") + End If + + Next + + Catch ex As Exception + + 'Simulationsfehler aufgetreten + Common.Log.AddMessage(Common.Log.levels.error, ex.Message) + + 'Simulation nicht erfolgreich + Me.SimIsOK = False + + Finally + + 'ready for next sim + Me.launchReady = True + + End Try + + End Sub + + Public Function Sim_Is_OK() As Boolean + + Sim_Is_OK = Me.SimIsOK + End Function + + Public Function launch_Ready() As Boolean + + launch_Ready = Me.launchReady + End Function + + Public Sub set_is_OK() + + Me.SimIsOK = True + End Sub + + Public Function get_Thread_ID() As Integer + + get_Thread_ID = Me.Thread_ID + End Function + + Public Function get_Child_ID() As Integer + + get_Child_ID = Me.Child_ID + End Function + +End Class \ No newline at end of file diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.Designer.vb b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.Designer.vb new file mode 100644 index 00000000..f2c7c296 --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.Designer.vb @@ -0,0 +1,205 @@ + _ +Partial Class TALSIM5_Dialog + Inherits System.Windows.Forms.Form + + 'Form overrides dispose to clean up the component list. + _ + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + + 'Required by the Windows Form Designer + Private components As System.ComponentModel.IContainer + + 'NOTE: The following procedure is required by the Windows Form Designer + 'It can be modified using the Windows Form Designer. + 'Do not modify it using the code editor. + _ + Private Sub InitializeComponent() + Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(TALSIM5_Dialog)) + Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel() + Me.OK_Button = New System.Windows.Forms.Button() + Me.Cancel_Button = New System.Windows.Forms.Button() + Me.Label_DBPath = New System.Windows.Forms.Label() + Me.Label2 = New System.Windows.Forms.Label() + Me.Label3 = New System.Windows.Forms.Label() + Me.Label4 = New System.Windows.Forms.Label() + Me.Label5 = New System.Windows.Forms.Label() + Me.ComboBox_Scenario = New System.Windows.Forms.ComboBox() + Me.ComboBox_Simulation = New System.Windows.Forms.ComboBox() + Me.TextBox_TimeseriesPath = New System.Windows.Forms.TextBox() + Me.Button_BrowseFolder = New System.Windows.Forms.Button() + Me.FolderBrowserDialog1 = New System.Windows.Forms.FolderBrowserDialog() + Me.TableLayoutPanel1.SuspendLayout() + Me.SuspendLayout() + ' + 'TableLayoutPanel1 + ' + Me.TableLayoutPanel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.TableLayoutPanel1.ColumnCount = 2 + Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + Me.TableLayoutPanel1.Controls.Add(Me.OK_Button, 0, 0) + Me.TableLayoutPanel1.Controls.Add(Me.Cancel_Button, 1, 0) + Me.TableLayoutPanel1.Location = New System.Drawing.Point(172, 119) + Me.TableLayoutPanel1.Name = "TableLayoutPanel1" + Me.TableLayoutPanel1.RowCount = 1 + Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!)) + Me.TableLayoutPanel1.Size = New System.Drawing.Size(146, 29) + Me.TableLayoutPanel1.TabIndex = 0 + ' + 'OK_Button + ' + Me.OK_Button.Anchor = System.Windows.Forms.AnchorStyles.None + Me.OK_Button.Location = New System.Drawing.Point(3, 3) + Me.OK_Button.Name = "OK_Button" + Me.OK_Button.Size = New System.Drawing.Size(67, 23) + Me.OK_Button.TabIndex = 0 + Me.OK_Button.Text = "OK" + ' + 'Cancel_Button + ' + Me.Cancel_Button.Anchor = System.Windows.Forms.AnchorStyles.None + Me.Cancel_Button.DialogResult = System.Windows.Forms.DialogResult.Cancel + Me.Cancel_Button.Location = New System.Drawing.Point(76, 3) + Me.Cancel_Button.Name = "Cancel_Button" + Me.Cancel_Button.Size = New System.Drawing.Size(67, 23) + Me.Cancel_Button.TabIndex = 1 + Me.Cancel_Button.Text = "Cancel" + ' + 'Label1 + ' + Me.Label_DBPath.AutoSize = True + Me.Label_DBPath.Location = New System.Drawing.Point(12, 9) + Me.Label_DBPath.Name = "Label1" + Me.Label_DBPath.Size = New System.Drawing.Size(56, 13) + Me.Label_DBPath.TabIndex = 1 + Me.Label_DBPath.Text = "Database:" + ' + 'Label2 + ' + Me.Label2.AutoSize = True + Me.Label2.Location = New System.Drawing.Point(12, 34) + Me.Label2.Name = "Label2" + Me.Label2.Size = New System.Drawing.Size(52, 13) + Me.Label2.TabIndex = 2 + Me.Label2.Text = "Scenario:" + ' + 'Label3 + ' + Me.Label3.AutoSize = True + Me.Label3.Location = New System.Drawing.Point(13, 61) + Me.Label3.Name = "Label3" + Me.Label3.Size = New System.Drawing.Size(58, 13) + Me.Label3.TabIndex = 3 + Me.Label3.Text = "Simulation:" + ' + 'Label4 + ' + Me.Label4.AutoSize = True + Me.Label4.Location = New System.Drawing.Point(13, 90) + Me.Label4.Name = "Label4" + Me.Label4.Size = New System.Drawing.Size(89, 13) + Me.Label4.TabIndex = 4 + Me.Label4.Text = "Timeseries folder:" + ' + 'Label5 + ' + Me.Label5.AutoSize = True + Me.Label5.Location = New System.Drawing.Point(114, 9) + Me.Label5.Name = "Label5" + Me.Label5.Size = New System.Drawing.Size(74, 13) + Me.Label5.TabIndex = 5 + Me.Label5.Text = "pathDatabase" + ' + 'ComboBox_Scenario + ' + Me.ComboBox_Scenario.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ + Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.ComboBox_Scenario.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList + Me.ComboBox_Scenario.FormattingEnabled = True + Me.ComboBox_Scenario.Location = New System.Drawing.Point(117, 31) + Me.ComboBox_Scenario.Name = "ComboBox_Scenario" + Me.ComboBox_Scenario.Size = New System.Drawing.Size(201, 21) + Me.ComboBox_Scenario.TabIndex = 6 + ' + 'ComboBox_Simulation + ' + Me.ComboBox_Simulation.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ + Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.ComboBox_Simulation.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList + Me.ComboBox_Simulation.FormattingEnabled = True + Me.ComboBox_Simulation.Location = New System.Drawing.Point(117, 58) + Me.ComboBox_Simulation.Name = "ComboBox_Simulation" + Me.ComboBox_Simulation.Size = New System.Drawing.Size(201, 21) + Me.ComboBox_Simulation.TabIndex = 7 + ' + 'TextBox_TimeseriesPath + ' + Me.TextBox_TimeseriesPath.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ + Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.TextBox_TimeseriesPath.Location = New System.Drawing.Point(117, 87) + Me.TextBox_TimeseriesPath.Name = "TextBox_TimeseriesPath" + Me.TextBox_TimeseriesPath.Size = New System.Drawing.Size(165, 20) + Me.TextBox_TimeseriesPath.TabIndex = 8 + ' + 'Button1 + ' + Me.Button_BrowseFolder.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) + Me.Button_BrowseFolder.Location = New System.Drawing.Point(288, 85) + Me.Button_BrowseFolder.Name = "Button1" + Me.Button_BrowseFolder.Size = New System.Drawing.Size(30, 23) + Me.Button_BrowseFolder.TabIndex = 9 + Me.Button_BrowseFolder.Text = "..." + Me.Button_BrowseFolder.UseVisualStyleBackColor = True + ' + 'TALSIM5_Dialog + ' + Me.AcceptButton = Me.OK_Button + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.CancelButton = Me.Cancel_Button + Me.ClientSize = New System.Drawing.Size(330, 160) + Me.Controls.Add(Me.Button_BrowseFolder) + Me.Controls.Add(Me.TextBox_TimeseriesPath) + Me.Controls.Add(Me.ComboBox_Simulation) + Me.Controls.Add(Me.ComboBox_Scenario) + Me.Controls.Add(Me.Label5) + Me.Controls.Add(Me.Label4) + Me.Controls.Add(Me.Label3) + Me.Controls.Add(Me.Label2) + Me.Controls.Add(Me.Label_DBPath) + Me.Controls.Add(Me.TableLayoutPanel1) + Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) + Me.MaximizeBox = False + Me.MinimizeBox = False + Me.Name = "TALSIM5_Dialog" + Me.ShowInTaskbar = False + Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent + Me.Text = "Talsim5 settings" + Me.TableLayoutPanel1.ResumeLayout(False) + Me.ResumeLayout(False) + Me.PerformLayout() + + End Sub + Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel + Friend WithEvents OK_Button As System.Windows.Forms.Button + Friend WithEvents Cancel_Button As System.Windows.Forms.Button + Friend WithEvents Label_DBPath As Windows.Forms.Label + Friend WithEvents Label2 As Windows.Forms.Label + Friend WithEvents Label3 As Windows.Forms.Label + Friend WithEvents Label4 As Windows.Forms.Label + Friend WithEvents Label5 As Windows.Forms.Label + Friend WithEvents ComboBox_Scenario As Windows.Forms.ComboBox + Friend WithEvents ComboBox_Simulation As Windows.Forms.ComboBox + Friend WithEvents TextBox_TimeseriesPath As Windows.Forms.TextBox + Friend WithEvents Button_BrowseFolder As Windows.Forms.Button + Friend WithEvents FolderBrowserDialog1 As Windows.Forms.FolderBrowserDialog +End Class diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.resx b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.resx new file mode 100644 index 00000000..80dc2770 --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDg4Njb29vv2dnZ79oaGhjAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAhYWFKYGBgQ6QkJACl5eX6svLy//BwcH/cnJy6nFxcQJycnIOZGRkKQAA + AAAAAAAAAAAAAAAAAAAAAAAAl5eXm4WFhf17e3vnjIyMGZiYmOfW1tb/09PT/3l5eedxcXEZbm5u52Rk + ZP1fX1+bAAAAAAAAAAAAAAAAtbW1e8nJyf/l5eX/t7e3/5iYmPSampr+0NDQ/8/Pz/+EhIT+hISE9Li4 + uP/b29v/lZWV/2hoaHsAAAAAAAAAALy8vH23t7f+3t7e/9HR0f/W1tb/29vb/9TU1P/T09P/19fX/9LS + 0v/Kysr/1tbW/4SEhP5+fn59AAAAAAAAAAAAAAAAvb29hdHR0f/Ozs7/0dHR/9PT0/+7u7v/uLi4/87O + zv/Ly8v/xMTE/7u7u/+AgICFAAAAAAAAAAC1tbXNo6Oj47Kysu7Z2dn/0tLS/9fX1/+wsLDGq6urRKen + p0Sjo6PGzc3N/8nJyf/IyMj/enp67m9vb+NpaWnNzMzM/ejo6P/c3Nz/0tLS/9jY2P/BwcH/pqamRAAA + AAAAAAAAqKioRLm5uf/Pz8//xcXF/83Nzf/c3Nz/eHh4/dDQ0P3u7u7/39/f/9XV1f/Y2Nj/t7e3/5mZ + mUQAAAAAAAAAAK2trUS8vLz/0NDQ/8jIyP/S0tL/5OTk/4KCgv3T09PN0NDQ487Ozu7h4eH/2NjY/8rK + yv+Xl5fGjY2NRJOTk0Sjo6PG0NDQ/8/Pz//Y2Nj/oaGh7pubm+OYmJjNAAAAAAAAAADR0dGF3d3d/9fX + 1//U1NT/yMjI/66urv+zs7P/z8/P/9LS0v/Ozs7/xcXF/56enoUAAAAAAAAAAAAAAADV1dV90NDQ/uTk + 5P/d3d3/4eHh/+Pj4//f39//3t7e/+Li4v/b29v/1tbW/9PT0/+Pj4/+h4eHfQAAAAAAAAAA2trae+Pj + 4//x8fH/4+Pj/8/Pz/TLy8v+39/f/97e3v/AwMD+vb299NbW1v/t7e3/xsbG/5+fn3sAAAAAAAAAAAAA + AADb29ub2NjY/dXV1efS0tIZzs7O5+Xl5f/l5eX/wsLC58HBwRm9vb3nuLi4/bS0tJsAAAAAAAAAAAAA + AAAAAAAAAAAAANvb2ynZ2dkO1tbWAtPT0+rr6+v/6urq/7y8vOrExMQCwcHBDr6+vikAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADW1tZj0tLSv9HR0b/MzMxjAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA/n8AAPw/AADEIwAAwAMAAMADAADAAwAAAYAAAAPAAAADwAAAAYAAAMADAADAAwAAwAMAAMQj + ///8P////n///w== + + + \ No newline at end of file diff --git a/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.vb b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.vb new file mode 100644 index 00000000..c85a228f --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/TALSIM5_Dialog.vb @@ -0,0 +1,180 @@ +'BlueM.Opt +'Copyright (C) BlueM Dev Group +'Website: +' +'This program is free software: you can redistribute it and/or modify +'it under the terms of the GNU General Public License as published by +'the Free Software Foundation, either version 3 of the License, or +'(at your option) any later version. +' +'This program is distributed in the hope that it will be useful, +'but WITHOUT ANY WARRANTY; without even the implied warranty of +'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +'GNU General Public License for more details. +' +'You should have received a copy of the GNU General Public License +'along with this program. If not, see . +' +Imports Microsoft.Data.Sqlite +Imports System.Windows.Forms + +Friend Class TALSIM5_Dialog + + Private dbPath As String + + ''' + ''' Selected scenario in the dialog, or null if no scenario is selected + ''' + ''' + Friend ReadOnly Property SelectedScenario As Talsim5.Scenario + Get + Try + Return CType(ComboBox_Scenario.SelectedItem, Talsim5.Scenario) + Catch + Return Nothing + End Try + End Get + End Property + + ''' + ''' Selected simulation in the dialog, or null if no simulation is selected + ''' + ''' + Friend ReadOnly Property SelectedSimulation As Talsim5.Simulation + Get + Try + Return CType(ComboBox_Simulation.SelectedItem, Talsim5.Simulation) + Catch + Return Nothing + End Try + End Get + End Property + + ''' + ''' Selected timeseries path in the dialog + ''' + ''' + Friend ReadOnly Property TimeseriesPath As String + Get + Return Me.TextBox_TimeseriesPath.Text.Trim() + End Get + End Property + + ''' + ''' Create a new instance of the dialog with the given database path. + ''' The dialog will read the scenarios and simulations from the database and show them in the corresponding combo boxes. + ''' + ''' Path to the database + Public Sub New(dbPath As String) + ' Dieser Aufruf ist für den Designer erforderlich. + InitializeComponent() + ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu. + Me.dbPath = dbPath + + 'show database path + Me.Label_DBPath.Text = dbPath + + 'read scenarios from database + Dim scenarios As New List(Of Talsim5.Scenario) + Using connection As New SQLiteConnection($"Data Source={dbPath}") + connection.Open() + Using command As SQLiteCommand = connection.CreateCommand() + command.CommandText = " + SELECT Id, Name + FROM Scenario + ORDER BY id + " + Using reader As SQLiteDataReader = command.ExecuteReader() + While reader.Read() + Dim id As Integer = reader.GetInt32(0) + Dim name As String = reader.GetString(1) + Dim scenario As New Talsim5.Scenario() With { + .Id = id, + .Name = name + } + scenarios.Add(scenario) + End While + End Using + End Using + connection.Close() + End Using + + Me.ComboBox_Scenario.Items.AddRange(scenarios.ToArray()) + Me.ComboBox_Scenario.SelectedIndex = 0 + + End Sub + + Private Sub ComboBox_Scenario_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox_Scenario.SelectedIndexChanged + 'read simulations of currently selected scenario from database + Dim simulations As New List(Of Talsim5.Simulation) + Using connection As New SQLiteConnection($"Data Source={dbPath}") + connection.Open() + Using command As SQLiteCommand = connection.CreateCommand() + command.CommandText = " + SELECT Id, Description + FROM Simulation + WHERE ScenarioId = @ScenarioId + ORDER BY id + " + command.Parameters.AddWithValue("@ScenarioId", Me.SelectedScenario.Id) + Using reader As SQLiteDataReader = command.ExecuteReader() + While reader.Read() + Dim id As Integer = reader.GetInt32(0) + Dim name As String = reader.GetString(1) + Dim simulation As New Talsim5.Simulation() With { + .Id = id, + .Name = name + } + simulations.Add(simulation) + End While + End Using + End Using + connection.Close() + End Using + + Me.ComboBox_Simulation.Items.Clear() + Me.ComboBox_Simulation.Items.AddRange(simulations.ToArray()) + Me.ComboBox_Simulation.SelectedIndex = 0 + + If simulations.Count = 0 Then + MessageBox.Show("The selected scenario does not contain any simulations!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + End If + + End Sub + + Private Sub Button_BrowseFolder_Click(sender As Object, e As EventArgs) Handles Button_BrowseFolder.Click + If Me.TimeseriesPath <> "" Then + Me.FolderBrowserDialog1.SelectedPath = Me.TimeseriesPath + End If + If Me.FolderBrowserDialog1.ShowDialog() <> DialogResult.OK Then + Return + End If + Me.TextBox_TimeseriesPath.Text = Me.FolderBrowserDialog1.SelectedPath + End Sub + + Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click + If Me.SelectedScenario Is Nothing Then + MessageBox.Show("Please select a scenario!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + Return + End If + If Me.SelectedSimulation Is Nothing Then + MessageBox.Show("Please select a simulation!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + Return + End If + If Me.TimeseriesPath = "" Then + MessageBox.Show("Please select a timeseries path!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + Return + ElseIf Not IO.Directory.Exists(Me.TimeseriesPath) Then + MessageBox.Show("The selected timeseries path does not exist!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) + Return + End If + Me.DialogResult = System.Windows.Forms.DialogResult.OK + Me.Close() + End Sub + + Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel_Button.Click + Me.DialogResult = System.Windows.Forms.DialogResult.Cancel + Me.Close() + End Sub + +End Class diff --git a/BlueM.Opt/Apps/TALSIM/TALSIMThread.vb b/BlueM.Opt/Apps/TALSIM/TALSIMThread.vb index 67d9dd5d..ea2c1441 100644 --- a/BlueM.Opt/Apps/TALSIM/TALSIMThread.vb +++ b/BlueM.Opt/Apps/TALSIM/TALSIMThread.vb @@ -21,10 +21,10 @@ ''' Public Class TalsimThread - Private Thread_ID As Integer - Private Child_ID As Integer - Private WorkFolder As String - Private DS_Name As String + Private ReadOnly Thread_ID As Integer + Private ReadOnly Child_ID As Integer + Private ReadOnly WorkFolder As String + Private ReadOnly DS_Name As String Private SimIsOK As Boolean Private launchReady As Boolean Public Shared exe_path As String @@ -92,12 +92,13 @@ Public Class TalsimThread Dim errmsg As String Dim simendfile As String = IO.Path.Combine(Me.WorkFolder, Me.DS_Name & ".SIMEND") Dim proc As Process - Dim startInfo As New ProcessStartInfo() - startInfo.FileName = TalsimThread.exe_path - startInfo.Arguments = runfilename - startInfo.UseShellExecute = True - startInfo.WindowStyle = ProcessWindowStyle.Hidden - startInfo.WorkingDirectory = IO.Path.GetDirectoryName(TalsimThread.exe_path) + Dim startInfo As New ProcessStartInfo With { + .FileName = TalsimThread.exe_path, + .Arguments = runfilename, + .UseShellExecute = True, + .WindowStyle = ProcessWindowStyle.Hidden, + .WorkingDirectory = IO.Path.GetDirectoryName(TalsimThread.exe_path) + } 'Carry out up to 5 simulation attempts, because TALSIM sometimes blocks access to the time series files in multithreading mode Dim n_attempts As Integer = 5 diff --git a/BlueM.Opt/Apps/TALSIM/talsim5.run b/BlueM.Opt/Apps/TALSIM/talsim5.run new file mode 100644 index 00000000..1d2c2ea4 --- /dev/null +++ b/BlueM.Opt/Apps/TALSIM/talsim5.run @@ -0,0 +1,10 @@ +[TALSIM] +Path= +System= +DBFile= +ZrePath= +ScenarioId= +SimulationId= +VariationId=0 +Language=en +Debug=1 diff --git a/BlueM.Opt/Common/Constants.vb b/BlueM.Opt/Common/Constants.vb index 939db40a..f4af5ad1 100644 --- a/BlueM.Opt/Common/Constants.vb +++ b/BlueM.Opt/Common/Constants.vb @@ -38,6 +38,7 @@ Public Module Constants Public Const ANW_SMUSI As String = "SMUSI" Public Const ANW_SWMM As String = "SWMM" Public Const ANW_TALSIM As String = "TALSIM" + Public Const ANW_TALSIM5 As String = "TALSIM5" Public Const ANW_TESTPROBLEMS As String = "Testproblems" Public Const ANW_TSP As String = "Traveling Salesman" diff --git a/BlueM.Opt/Common/Modellparameter.vb b/BlueM.Opt/Common/Modellparameter.vb index 81195a85..d699b1e9 100644 --- a/BlueM.Opt/Common/Modellparameter.vb +++ b/BlueM.Opt/Common/Modellparameter.vb @@ -59,6 +59,34 @@ Public Structure Struct_ModellParameter ''' ''' ModellParameter = OptimierungsParameter * Faktor Public Faktor As Double + + ''' + ''' Name of the table in the database, in which the parameter is defined + ''' + Public ReadOnly Property DBTable As String + Get + Return Me.Datei + End Get + End Property + + ''' + ''' Name of the field of the table, in which the parameter is defined + ''' + Public ReadOnly Property DBField As String + Get + Return Me.Element + End Get + End Property + + ''' + ''' Id of the row to update + ''' + Public ReadOnly Property DBId As Integer + Get + Return Me.ZeileNr + End Get + End Property + ''' ''' Klont einen Modellparameter ''' diff --git a/BlueM.Opt/Common/Problem.vb b/BlueM.Opt/Common/Problem.vb index 4aadaa59..23afa629 100644 --- a/BlueM.Opt/Common/Problem.vb +++ b/BlueM.Opt/Common/Problem.vb @@ -403,8 +403,8 @@ Public Class Problem .Datei = array(4).Trim() .Element = array(5).Trim() .ZeileNr = Convert.ToInt16(array(6).Trim()) - .SpVon = Convert.ToInt16(array(7).Trim()) - .SpBis = Convert.ToInt16(array(8).Trim()) + .SpVon = If(array(7).Trim() <> "", Convert.ToInt16(array(7).Trim()), 0) + .SpBis = If(array(8).Trim() <> "", Convert.ToInt16(array(8).Trim()), 0) .Faktor = Convert.ToDouble(array(9).Trim(), Common.Provider.FortranProvider) End With i += 1 diff --git a/BlueM.Opt/Main/BLUEM.OPT_RELEASE-NOTES.txt b/BlueM.Opt/Main/BLUEM.OPT_RELEASE-NOTES.txt index 60808da0..26795c22 100644 --- a/BlueM.Opt/Main/BLUEM.OPT_RELEASE-NOTES.txt +++ b/BlueM.Opt/Main/BLUEM.OPT_RELEASE-NOTES.txt @@ -2,8 +2,12 @@ BlueM.Opt Release Notes =============================================================== -Version X.X.X +Version 2.6.0 ------------- +NEW: +* Added support for Talsim datasets in Talsim5 database format (select `TALSIM5` as the app) + +CHANGED: * Updated Talsim.Engine to v4.1.22 * Updated BlueM.Wave to v2.17.0 diff --git a/BlueM.Opt/Main/Form1.vb b/BlueM.Opt/Main/Form1.vb index 7118c176..afc46a26 100644 --- a/BlueM.Opt/Main/Form1.vb +++ b/BlueM.Opt/Main/Form1.vb @@ -145,7 +145,7 @@ Partial Public Class Form1 '--------- 'Liste der Anwendungen in ComboBox schreiben und Anfangseinstellung wählen Me.ComboBox_Anwendung.Items.Clear() - Me.ComboBox_Anwendung.Items.AddRange(New Object() {"", ANW_BLUEM, ANW_SWMM, ANW_TALSIM, ANW_TESTPROBLEMS, ANW_TSP}) 'ANW_SMUSI entfernt (#184) + Me.ComboBox_Anwendung.Items.AddRange(New Object() {"", ANW_BLUEM, ANW_SWMM, ANW_TALSIM, ANW_TALSIM5, ANW_TESTPROBLEMS, ANW_TSP}) 'ANW_SMUSI entfernt (#184) Me.ComboBox_Anwendung.SelectedIndex = 0 'Datensatz @@ -431,6 +431,13 @@ Partial Public Class Form1 Sim1 = New BlueM.Opt.Apps.Talsim() + Case ANW_TALSIM5 'Anwendung TALSIM5 + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + 'Objekt der Klasse Talsim5 initialisieren + Sim1 = New BlueM.Opt.Apps.Talsim5() + + Case ANW_SWMM 'Anwendung SWMM 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -904,7 +911,7 @@ Partial Public Class Form1 '================= Select Case Me.Anwendung - Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM + Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM, ANW_TALSIM5 'Bei allen Sim-Anwendungen '----------------------------------------------------- @@ -1037,7 +1044,7 @@ Partial Public Class Form1 Select Case Anwendung - Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM + Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM, ANW_TALSIM5 'Sim-Anwendungen 'Save settings to file @@ -1272,7 +1279,7 @@ Partial Public Class Form1 Call Testprobleme1.DiagInitialise(Me.Hauptdiagramm1) - Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM + Case ANW_BLUEM, ANW_SMUSI, ANW_SWMM, ANW_TALSIM, ANW_TALSIM5 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Select Case Me.mProblem.Method diff --git a/BlueM.Opt/Main/My Project/AssemblyInfo.vb b/BlueM.Opt/Main/My Project/AssemblyInfo.vb index 1a1bb5c1..753416fd 100644 --- a/BlueM.Opt/Main/My Project/AssemblyInfo.vb +++ b/BlueM.Opt/Main/My Project/AssemblyInfo.vb @@ -12,9 +12,9 @@ Imports BlueM.Opt.Common.Constants + & "* Talsim (https://www.talsim.de/)")> @@ -32,6 +32,6 @@ Imports BlueM.Opt.Common.Constants ' mit '*' verwenden. Siehe unten - +