// Copyright (C) Stichting Deltares 2017. All rights reserved.
//
// This file is part of the DAM Engine.
//
// The DAM Engine is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Deltares.DamEngine.Calculators.Dikes_Assessment_Regional;
using Deltares.DamEngine.Calculators.Stability;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.RWScenarios;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Data.Standard.Language;
using Deltares.DamEngine.Data.Standard.Logging;
namespace Deltares.DamEngine.Calculators
{
public class DamRunner
{
private readonly DamProjectData damProjectData;
private readonly string directory = "";
private int maxCalculationCores = 255;
private DateTime startTimeCalculation;
public DamRunner(DamProjectData damProjectData, string projectFileName)
{
this.damProjectData = damProjectData;
directory = Path.GetDirectoryName(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"); ##Bka: most probably unwanted, replace with other mechanism
}
else if (result == CalculationResult.Succeeded)
{
string openingMessage = LocalizationManager.GetTranslatedText(this, "CalculationFinished");
// LocalizedMessageBox.ShowTranslatedText(openingMessage + paragraphSepatator + timeMessage + paragraphSepatator + output); ##Bka: most probably unwanted, replace with other mechanism
}
else if ((result == CalculationResult.RunFailed) || (result == CalculationResult.UnexpectedError))
{
string openingMessage = LocalizationManager.GetTranslatedText(this, "CalculationFailed");
//LocalizedMessageBox.ShowTranslatedText(openingMessage + paragraphSepatator + output); ##Bka: most probably unwanted, replace with other mechanism
}
}
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 ##Bka: most probably unwanted, replace with other mechanism
{
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, DamProjectData.ProjectWorkingPath); //##Bka!? or damCalculation.ProjectDataDirectory
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); ##Bka
calculationResult = rwScenariosCalculation.Run();
//DataEventPublisher.DataListModified(LogManager.Messages);
}
catch (Exception)
{
calculationResult = CalculationResult.UnexpectedError;
}
string results = "";
rwScenariosCalculation.GetResults(ref results);
//evaluationJob.XML = results; ##Bka
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 = DamProjectData.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; }
}
}
}