using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using Deltares.Dam.Data; using Deltares.Standard; using Deltares.Standard.EventPublisher; using Deltares.Standard.Forms.DExpress; using Deltares.Standard.Language; using Deltares.Standard.Logging; namespace Deltares.Dam.Forms { public class DamRunner { private readonly DamProjectData damProjectData; private readonly string directory = ""; private int maxCalculationCores = 255; private DateTime startTimeCalculation; public DamRunner(DamProject damProject) { damProjectData = damProject.DamProjectData; directory = Path.GetDirectoryName(damProject.ProjectFileName); } private delegate void ProcessResultDelegate(DamProjectData damProject, CalculationResult result, string output); private void ProcessResultLocal(DamProjectData damProject, CalculationResult result, string output) { damProjectData.UpdateCalculations(); damProjectData.UpdateSchematizationFactors(); TimeSpan elapsedTime = DateTime.Now - startTimeCalculation; string timeMessage = String.Format(LocalizationManager.GetTranslatedText(this, "CalculationTime"), elapsedTime.ToString(@"dd\.hh\:mm\:ss")); string paragraphSepatator = Environment.NewLine + Environment.NewLine; if (output.StartsWith("Thread was being aborted")) { LocalizedMessageBox.Show(this, "CalculationAborted"); } else if (result == CalculationResult.Succeeded) { string openingMessage = LocalizationManager.GetTranslatedText(this, "CalculationFinished"); LocalizedMessageBox.ShowTranslatedText(openingMessage + paragraphSepatator + timeMessage + paragraphSepatator + output); } else if ((result == CalculationResult.RunFailed) || (result == CalculationResult.UnexpectedError)) { string openingMessage = LocalizationManager.GetTranslatedText(this, "CalculationFailed"); LocalizedMessageBox.ShowTranslatedText(openingMessage + paragraphSepatator + output); } foreach (LocationJob locationJob in damProject.LocationJobs) { if (locationJob.Run.HasValue && locationJob.Run.Value) { DataEventPublisher.AfterChange(locationJob); } } DataEventPublisher.DataListModified(damProjectData.LocationJobs); DataEventPublisher.AfterChange(damProjectData); } private void ProcessResult(DamProjectData damProject, CalculationResult result, string output) { if (BindSupport.InvokeControl.InvokeRequired) { var d = new ProcessResultDelegate(ProcessResultLocal); BindSupport.InvokeControl.Invoke(d, new object[] { damProject, result, output }); } else { ProcessResultLocal(damProject, result, output); } } public void PerformCalculation(ProgressDelegate progressDelegate) { startTimeCalculation = DateTime.Now; try { switch (damProjectData.DamProjectType) { case DamProjectType.Calamity: { var damCalculation = new DamCalculation(); damCalculation.RegisterProgress(progressDelegate); damCalculation.RegisterSendMessage(HandleCalculationSendMessage); damCalculation.ProjectWorkingDirectory = ""; // Force default location for working directory damCalculation.ProjectDataDirectory = directory + Path.DirectorySeparatorChar; damCalculation.MStabExePath = StabilityCalculator.MStabExePath; damCalculation.MaxCalculationCores = MaxCalculationCores; damCalculation.CalculateDamProject(damProjectData); var output = FillOutputForMessage(damProjectData.LocationJobs); ProcessResult(damProjectData, CalculationResult.Succeeded, output); break; } case DamProjectType.Assessment: { var rwScenariosCalculation = new RWScenariosCalculation { SchematizationFactorData = damProjectData.SchematizationFactorData, MaxCalculationCores = MaxCalculationCores }; rwScenariosCalculation.RegisterProgress(progressDelegate); rwScenariosCalculation.RegisterSendMessage(HandleCalculationSendMessage); rwScenariosCalculation.MStabExePath = StabilityCalculator.MStabExePath; rwScenariosCalculation.PipingModelType = damProjectData.DamProjectCalculationSpecification.CurrentSpecification.PipingModelType; rwScenariosCalculation.MStabParameters = damProjectData.DamProjectCalculationSpecification.CurrentSpecification .FailureMechanismeParamatersMStab.MStabParameters; EvaluationJob evaluationJob = damProjectData.GetEvaluationJob(); RemoveLogMessages(evaluationJob); CalculationResult calculationResult; try { rwScenariosCalculation.Load(evaluationJob.XML); calculationResult = rwScenariosCalculation.Run(); DataEventPublisher.DataListModified(LogManager.Messages); } catch (Exception) { calculationResult = CalculationResult.UnexpectedError; } string results = ""; rwScenariosCalculation.GetResults(ref results); evaluationJob.XML = results; evaluationJob.AttachResults(damProjectData.LocationJobs); var output = FillOutputForMessage(damProjectData.LocationJobs); ProcessResult(damProjectData, calculationResult, output); break; } case DamProjectType.Design: { if (damProjectData.DamProjectCalculationSpecification.DamCalculationSpecifications.Count > 0) { List scenarios = CreateScenarioListForCalculation(); var damProjectCalculator = new DamProjectCalculator(damProjectData) { MaxCalculationCores = MaxCalculationCores, MStabProgramPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "DGeoStability.exe"), SlopeWProgramPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Slope2.exe"), ProjectDataDirectory = directory + Path.DirectorySeparatorChar, Progress = progressDelegate, CalculationBaseDirectory = DamProject.ProjectWorkingPath + @"\CalculationFiles\" }; damProjectCalculator.Calculate(damProjectData, scenarios); var output = FillOutputForMessage(damProjectData.LocationJobs); ProcessResult(damProjectData, CalculationResult.Succeeded, output); } } break; } } catch (Exception exception) { var sb = new StringBuilder(exception.Message); for (Exception innerException = exception.InnerException; innerException != null; innerException = innerException.InnerException) { sb.Append('\n'); sb.Append(innerException.Message); } ProcessResult(damProjectData, CalculationResult.RunFailed, sb.ToString()); } } private string FillOutputForMessage(IEnumerable locationJobs) { var res = ""; foreach (var locationJob in locationJobs) { if (locationJob.Result == JobResult.Failed) { var failedLocationCalculation = LocalizationManager.GetTranslatedText(GetType(), "failedLocationCalculationId"); res = res + String.Format(failedLocationCalculation, locationJob.Location.Name) + Environment.NewLine; } else { if (locationJob.Result != JobResult.NoRun && !locationJob.HasLocationResults && !locationJob.HasRWScenarioResults && !locationJob.HasScenarioResults) { var noResultsForLocation = LocalizationManager.GetTranslatedText(GetType(), "noResultsForLocationId"); res = res + String.Format(noResultsForLocation, locationJob.Location.Name) + Environment.NewLine; } } } return res; } /// /// Create a list of scenarios to be calculated /// /// List of the generated scenarios private List CreateScenarioListForCalculation() { var scenarios = new List(); // The locations of the scenarios can get out of sync after a calculation, so make sure they are in sync damProjectData.WaterBoard.UpdateLocationsForScenarios(); List selectedLocations = damProjectData.SelectedLocationJobs.Select(x => x.Location).ToList(); foreach (var location in selectedLocations) { scenarios.AddRange(location.Scenarios); } return scenarios; } private void RemoveLogMessages(EvaluationJob evaluationJob) { foreach (LogMessage logMessage in LogManager.Messages.ToArray()) { foreach (var location in evaluationJob.Locations) { if (logMessage.SubjectName.Equals(location.ToString())) { LogManager.Messages.Remove(logMessage); } } } DataEventPublisher.DataListModified(LogManager.Messages); } private void HandleCalculationSendMessage(LogMessage logMessage) { lock (LogManager.Messages) { LogManager.Messages.Add(logMessage); DataEventPublisher.DataListModified(LogManager.Messages); } } public int MaxCalculationCores { get { return maxCalculationCores; } set { maxCalculationCores = value; } } } }