//-----------------------------------------------------------------------
//
// Copyright (c) 2009 Deltares. All rights reserved.
//
// B. Faassen
// barry.faassen@deltares.nl
// 19-5-2008
// n.a.
//-----------------------------------------------------------------------
using System.Collections.Generic;
using System.Threading;
using Deltares.Geometry;
using Deltares.Geotechnics;
using Deltares.Geotechnics.IO.Importers;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Standard;
using Deltares.Standard.Language;
namespace Deltares.Dam.Data
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
public struct MStabResults
{
public MStabResultsSingleZone zone1;
public MStabResultsSingleZone? zone2;
public string CalculationName;
public string CalculationSubDir;
public int IterationNumber;
public void Init()
{
zone1 = new MStabResultsSingleZone();
zone1.Init();
zone2 = new MStabResultsSingleZone();
zone2.Value.Init();
}
}
public struct MStabResultsSingleZone
{
public double safetyFactor;
public double circleSurfacePointLeftXCoordinate;
public double circleSurfacePointRightXCoordinate;
public double entryPointXCoordinate;
public double exitPointXCoordinate;
public double beta;
public void Init()
{
safetyFactor = 0.0;
circleSurfacePointLeftXCoordinate = 0.0;
circleSurfacePointRightXCoordinate = 0.0;
entryPointXCoordinate = 0.0;
exitPointXCoordinate = 0.0;
beta = 0.0;
}
}
public struct NonWaterRetainingObjectResults
{
public string NwoId;
public double LocationXrdStart;
public double LocationYrdStart;
public double LocationZrdStart;
public double LocationXrdEnd;
public double LocationYrdEnd;
public double LocationZrdEnd;
public MStabResults MStabResults;
public SurfaceLine2 AdaptedSurfaceLine;
public SoilGeometryProbability SoilProfileProbability;
public void Init()
{
NwoId = "";
MStabResults = new MStabResults();
MStabResults.Init();
LocationXrdStart = 0.0;
LocationYrdStart = 0.0;
LocationZrdStart = 0.0;
LocationXrdEnd = 0.0;
LocationYrdEnd = 0.0;
LocationZrdEnd = 0.0;
AdaptedSurfaceLine = null;
}
}
///
/// Defines the service agent which is responsible for delegating calls
/// to the MStab calculation kernel or services
///
public class StabilityServiceAgent : IDisposable
{
private DGSMStabDAMInterface mstabDamDll;
private DGSDAMSlopeWInterface slopeWDamDll;
public StabilityServiceAgent()
{
mstabDamDll = new DGSMStabDAMInterface();
slopeWDamDll = new DGSDAMSlopeWInterface();
MStabExePath = Properties.Settings.Default.MStabExePath;
SlopeWExePath = Properties.Settings.Default.SlopeWExePath;
}
#region Native Members
///
/// Constant to the dll file can only be a constant!
///
#endregion
#region Wrapper Methods
public string MStabExePath { get; set; }
public string SlopeWExePath { get; set; }
public ProgramType ProgramType { get; set; }
///
/// Get DLL version
///
///
public string GetDllVersion()
{
if (ProgramType == ProgramType.SlopeW)
{
return slopeWDamDll.GetDllVersion();
}
else
{
return mstabDamDll.GetDllVersion();
}
}
///
/// Create MStab project file
///
///
public void CreateProjectFile(string inputXmlString)
{
lock (typeof (StabilityServiceAgent))
{
var result = 0;
if (ProgramType == ProgramType.SlopeW)
{
result = slopeWDamDll.CreateProjectFile(inputXmlString);
if (result > 0)
{
string errorMessage = slopeWDamDll.ErrorMessage();
throw new StabilityServiceAgentException(errorMessage);
}
}
else
{
result = mstabDamDll.CreateProjectFile(inputXmlString);
if (result > 0)
{
string errorMessage = mstabDamDll.ErrorMessage();
throw new StabilityServiceAgentException(errorMessage);
}
}
}
}
///
/// Create Soilprofile for location X in geometry-2d
///
///
///
public void ConvertGeometry2DTo1D(string inputXML, ref StringBuilder outputXML)
{
const int defaultBufferSize = 10000;
int bufferSize = defaultBufferSize;
outputXML = new StringBuilder(bufferSize);
int returnCode = mstabDamDll.Geometry2DTo1DConversion(inputXML, outputXML, ref bufferSize);
if (returnCode == DgsStandardDllInterface.DllErrorOutputBufferTooSmall)
{
outputXML = new StringBuilder(bufferSize);
returnCode = mstabDamDll.Geometry2DTo1DConversion(inputXML, outputXML, ref bufferSize);
}
if (returnCode != DgsStandardDllInterface.DllErrorNone)
throw new StabilityServiceAgentException(mstabDamDll.ErrorMessage());
}
///
/// Create Geometry2DData object from geometry2D file
///
///
///
public void CreateGeometry2DDataFromGeometry2D(string inputXML, ref StringBuilder outputXML)
{
const int defaultBufferSize = 10000;
int bufferSize = defaultBufferSize;
outputXML = new StringBuilder(bufferSize);
int returnCode = mstabDamDll.CreateGeometry2DDataFromGeometry2D(inputXML, outputXML, ref bufferSize);
if (returnCode == DgsStandardDllInterface.DllErrorOutputBufferTooSmall)
{
outputXML = new StringBuilder(bufferSize);
returnCode = mstabDamDll.CreateGeometry2DDataFromGeometry2D(inputXML, outputXML, ref bufferSize);
}
if (returnCode != DgsStandardDllInterface.DllErrorNone)
throw new StabilityServiceAgentException(mstabDamDll.ErrorMessage());
}
///
/// Calculate piping length
///
///
///
public double CalculatePipingLength(PolyLine headLine)
{
int pointCount = headLine.Points.Count;
var headLinePoints = new DGSMStabDAMInterface.LegacyCoordinate[pointCount];
double[] pointCoordinates = new double[pointCount * 2];
for (int pointIndex = 0; pointIndex < pointCount; pointIndex++)
{
headLinePoints[pointIndex].x = headLine.Points[pointIndex].X;
headLinePoints[pointIndex].z = headLine.Points[pointIndex].Z;
pointCoordinates[pointIndex * 2] = headLine.Points[pointIndex].X;
pointCoordinates[pointIndex * 2 + 1] = headLine.Points[pointIndex].Z;
}
return mstabDamDll.PipingLengthCalculation(pointCount, ref headLinePoints);
}
///
/// Calculate MStab projects in specified directory
///
///
public void CalculateMStabDirectory(string directoryPath)
{
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(directoryPath, StringResourceNames.ProjectFileNameNullOrEmpty);
ThrowHelper.ThrowIfDirectoryNotExist(directoryPath, StringResourceNames.ProjectFileNotExist);
ThrowHelper.ThrowIfFileNotExist(MStabExePath, StringResourceNames.MStabExecutableFileNameNotFound);
try
{
// Compute the project files
ProcessInputfFile(directoryPath);
}
catch (ArgumentNullException argumentNullException)
{
throw new StabilityServiceAgentException(argumentNullException.Message, argumentNullException);
}
catch (FileNotFoundException outputFileNotFoundException)
{
throw new StabilityServiceAgentException(outputFileNotFoundException.Message, outputFileNotFoundException);
}
}
///
/// Calculate MStab project
///
///
public void CalculateMStabProject(string projectFilePath)
{
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(projectFilePath, StringResourceNames.ProjectFileNameNullOrEmpty);
ThrowHelper.ThrowIfFileNotExist(projectFilePath, StringResourceNames.ProjectFileNotExist);
ThrowHelper.ThrowIfFileNotExist(MStabExePath, StringResourceNames.MStabExecutableFileNameNotFound);
try
{
// Compute the project files
ProcessInputfFile(projectFilePath);
}
catch (ArgumentNullException argumentNullException)
{
throw new StabilityServiceAgentException(argumentNullException.Message, argumentNullException);
}
catch (FileNotFoundException outputFileNotFoundException)
{
throw new StabilityServiceAgentException(outputFileNotFoundException.Message, outputFileNotFoundException);
}
}
///
/// Calculate SlopeW project
///
///
public void CalculateSlopeWProject(string projectFilePath)
{
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(projectFilePath, StringResourceNames.ProjectFileNameNullOrEmpty);
ThrowHelper.ThrowIfFileNotExist(projectFilePath, StringResourceNames.ProjectFileNotExist);
ThrowHelper.ThrowIfFileNotExist(SlopeWExePath, StringResourceNames.SlopeWExecutableFileNameNotFound);
try
{
// Compute the project files
ProcessInputfFile(projectFilePath);
}
catch (ArgumentNullException argumentNullException)
{
throw new StabilityServiceAgentException(argumentNullException.Message, argumentNullException);
}
catch (FileNotFoundException outputFileNotFoundException)
{
throw new StabilityServiceAgentException(outputFileNotFoundException.Message, outputFileNotFoundException);
}
}
///
/// Extracts the relevant calculation results from the outputfile of MStab
///
/// The project file to process
/// The MStab calculation results
public MStabResults ExtractStabilityResults(string projectFileName)
{
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(projectFileName, StringResourceNames.ProjectFileNameNullOrEmpty);
ThrowHelper.ThrowIfFileNotExist(projectFileName, StringResourceNames.ProjectFileNotExist);
try
{
if (ProgramType == ProgramType.SlopeW)
{
string outputFile = GetSlopeWOutputFileName(projectFileName);
return ParseSlopeWResultsFromOutputFile(outputFile);
}
else
{
string outputFile = Path.Combine(Path.GetDirectoryName(projectFileName), GetOutputFileName(projectFileName));
return ParseMStabResultsFromOutputFile(outputFile);
}
}
catch (ArgumentNullException argumentNullException)
{
string message = LocalizationManager.GetTranslatedText(this.GetType(), "CouldNotExtractSafetyFactor");
throw new StabilityServiceAgentException(message, argumentNullException);
}
catch (FileNotFoundException outputFileNotFoundException)
{
string message = LocalizationManager.GetTranslatedText(this.GetType(), "CouldNotExtractSafetyFactor");
string outputFile = Path.Combine(Path.GetDirectoryName(projectFileName), GetOutputFileName(projectFileName));
string[] errorMessages = ParseMStabErrorFile(outputFile);
if (errorMessages.Length > 0)
{
message = errorMessages[0];
}
throw new StabilityServiceAgentException(message, outputFileNotFoundException);
}
}
///
/// Extract the beta-value from dumpfile of MStab
///
///
///
public double ExtractBeta(string projectFileName)
{
ThrowHelper.ThrowIfStringArgumentNullOrEmpty(projectFileName, StringResourceNames.ProjectFileNameNullOrEmpty);
ThrowHelper.ThrowIfFileNotExist(projectFileName, StringResourceNames.ProjectFileNotExist);
string outputFile = Path.Combine(Path.GetDirectoryName(projectFileName), GetOutputFileName(projectFileName));
try
{
return ParseBetaFromOutputFile(outputFile);
}
catch (ArgumentNullException argumentNullException)
{
throw new StabilityServiceAgentException(argumentNullException.Message, argumentNullException);
}
catch (FileNotFoundException outputFileNotFoundException)
{
throw new StabilityServiceAgentException(outputFileNotFoundException.Message, outputFileNotFoundException);
}
}
#endregion
#region Helper Methods
private string CreateMStabIniFile(string inputFileName)
{
string filename = Path.GetTempFileName();
filename = Path.ChangeExtension(filename, "ini");
string defaultIniFilename = Path.Combine(Path.GetDirectoryName(MStabExePath), "DGeoStability.ini");
string newIniContent = "[D-Geo Stability batch processing]";
var isDirectoryBatchCalculation = Directory.Exists(inputFileName);
if (isDirectoryBatchCalculation)
{
newIniContent += System.Environment.NewLine + "Path=" + inputFileName;
newIniContent += System.Environment.NewLine + "Filespec=*.sti";
}
else
{
newIniContent += System.Environment.NewLine + "InputFileName=" + inputFileName;
}
newIniContent += System.Environment.NewLine + "Plot Critical Circle=1";
newIniContent += System.Environment.NewLine + "PlotWMF=1";
newIniContent += System.Environment.NewLine + "PlotJPeg=1";
if (File.Exists(defaultIniFilename))
{
string iniContent = File.ReadAllText(defaultIniFilename);
newIniContent += System.Environment.NewLine + System.Environment.NewLine + iniContent;
};
File.WriteAllText(filename, newIniContent);
return filename;
}
///
/// Processes the input file using the working folder
///
/// The folder or file name; for MStab: if a filename is specified then the file will be calculated; if a foldername is specified, all the stability files in the folder will be calculated. For SlopeW only filename is allowed
private void ProcessInputfFile(string folderOrFileName)
{
const string quote = "\"";
var argument = "";
var programpath = "";
string mStabIniFilename = "";
if (ProgramType == ProgramType.SlopeW)
{
programpath = SlopeWExePath;
argument = " /s /x " + quote + folderOrFileName + quote + " " + quote + Path.GetFileNameWithoutExtension(folderOrFileName) + quote;
}
else
{
programpath = MStabExePath;
mStabIniFilename = CreateMStabIniFile(folderOrFileName);
argument = string.Format("/b \"{0}\"", mStabIniFilename);
// For debugging and calling with commandline options i.s.o. inifile
//string filename = Path.GetTempFileName();
//File.WriteAllText(filename, programpath);
//File.WriteAllText(filename, argument);
//File.AppendAllText(filename, mStabIniFilename);
//argument = string.Format("/B /PlotJPeg /Plot \"{0}\"", folderOrFileName); // note: use the folder name only for running MStab in batch mode
//File.AppendAllText(filename, argument);
}
var process = new Process
{
StartInfo =
{
FileName = programpath,
Arguments = argument,
UseShellExecute = false
}
};
Parallel.KillOnAbort(process);
process.Start();
try
{
process.WaitForExit();
}
catch (ThreadInterruptedException)
{
// thread was killed by user action to stop calculation
}
finally
{
if (File.Exists(mStabIniFilename))
{
File.Delete(mStabIniFilename);
}
}
}
///
/// Creates a random working folder by using a GUID
///
/// The generated folder name
private static string CreateTempDirName()
{
return string.Format("{0}\\{1}", Path.GetTempPath(), Guid.NewGuid().ToString().Replace('-', '0'));
}
///
/// Gets the stripped file name with the correct extension extracted from the input file name
///
/// The file name with path
/// The project file name without path and correct extension
private static string GetOutputFileName(string projectFileName)
{
return GetStrippedFileNameWithoutExtension(projectFileName) + ".std";
}
///
/// Gets the filename with the correct extension and the proper path for the outputfile for SlopeW
///
/// The file name with path
/// The project file name with extended path and correct extension
private static string GetSlopeWOutputFileName(string projectFileName)
{
string outputFile = Path.GetDirectoryName(projectFileName);
outputFile = Path.Combine(outputFile, Path.GetFileNameWithoutExtension(projectFileName));
outputFile = Path.Combine(outputFile, "001");
outputFile = Path.Combine(outputFile, Path.GetFileNameWithoutExtension(projectFileName));
string outputFileTest = outputFile + ".optfrc";
if (!File.Exists(outputFileTest))
{
outputFileTest = outputFile + ".frc01";
}
if (!File.Exists(outputFileTest))
{
outputFileTest = "";
}
return outputFileTest;
}
///
/// Gets the stripped file name without a path
///
/// The file name
/// The project file name without path and correct extension
private static string GetInputFileName(string projectFileName)
{
return GetStrippedFileNameWithoutExtension(projectFileName) + ".sti";
}
///
/// Gets the stripped file name without path and extension
///
/// The file name to strip
/// The file name
private static string GetStrippedFileNameWithoutExtension(string fileName)
{
return fileName.Substring(fileName.LastIndexOf("\\") + 1).Split('.')[0];
}
///
/// Gets the constructed file name with folder
///
/// The name of the file
/// The name of the folder
/// The full file path
private static string GetFileName(string fileName, string folderName)
{
return string.Format("{0}\\{1}", folderName, fileName);
}
///
/// Parses the safety factor from the output file
///
/// The file to parse
/// The safety factor
private static MStabResults ParseMStabResultsFromOutputFile(string outputFile)
{
if (!File.Exists(outputFile))
throw new FileNotFoundException("No valid calculation performed");
var fileContent = StabilityServiceFileParser.GetFileContents(outputFile);
return StabilityServiceFileParser.GetMStabResults(fileContent);
}
///
/// Parses the error messages from the error file
///
/// The file to parse
/// The error messages
private string[] ParseMStabErrorFile(string outputFile)
{
string errorFile = outputFile.Replace(".std", ".err");
if (File.Exists(errorFile))
{
List messages = new List();
bool content = false;
foreach (string line in File.ReadAllLines(outputFile))
{
if (line.StartsWith("**********"))
{
content = !content;
}
else if (content)
{
messages.Add(line);
}
}
return messages.ToArray();
}
else
{
return new string[0];
}
}
///
/// Parses the safety factor from the output file
///
/// The file to parse
/// The safety factor
private static MStabResults ParseSlopeWResultsFromOutputFile(string outputFile)
{
if (!File.Exists(outputFile))
throw new FileNotFoundException("No valid calculation performed");
var fileContent = StabilityServiceFileParser.GetFileContents(outputFile);
return StabilityServiceFileParser.GetSlopeWResults(fileContent);
}
private static double ParseBetaFromOutputFile(string outputFile)
{
if (!File.Exists(outputFile))
throw new FileNotFoundException("No valid calculation performed");
var fileContent = StabilityServiceFileParser.GetFileContents(outputFile);
return StabilityServiceFileParser.GetBeta(fileContent);
}
#endregion
#region IDispose Members
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// No need to call the finalizer since we've now cleaned
// up the unmanaged memory
GC.SuppressFinalize(this);
}
}
// This finalizer is called when Garbage collection occurs, but only if
// the IDisposable.Dispose method wasn't already called.
~StabilityServiceAgent()
{
Dispose(false);
}
#endregion
}
}