using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStability.Assemblers;
using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces;
using Deltares.DamEngine.Calculators.Properties;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.Results;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.DamMacroStability.Calculator;
namespace Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStability
{
public class DamMacroStabilityKernelWrapper : IKernelWrapper
{
private const string DamMacroStabilityFolder = @".\KernelWrappers\DamMacroStability";
private const string DGeoStabilityExe = "DGeoStability.exe";
///
/// Prepares the specified dam kernel input.
///
/// The dam kernel input.
///
public PrepareResult Prepare(DamKernelInput damKernelInput, out IKernelDataInput kernelDataInput)
{
// TODO: this is just fake data
const string testFolder = @"..\..\Deltares.DamEngine.Calculators.Tests\Files\MacroStability";
// Relative paths in ini file do not work yet in DGeoStability 16.2. This is fixed in 18.1.
var absoluteFolder = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), testFolder));
var stiFileName = Path.Combine(absoluteFolder, "test.sti");
kernelDataInput = new DamMacroStabilityInput()
{
DGeoStabilityExePath = Path.Combine(DamMacroStabilityFolder, DGeoStabilityExe),
DGeoStabilityInputFileName = stiFileName
};
return PrepareResult.Successful;
}
///
/// Validates the specified kernel data input.
///
/// The kernel data input.
/// The return messages.
///
public int Validate(IKernelDataInput kernelDataInput, out List messages)
{
var calculator = StabilityCalculator(kernelDataInput);
//ToDo zant calculator has no Validate.
// List kernelMessages = calculator.Validate();
messages = new List();
// foreach (string stringMessage in kernelMessages)
// {
// messages.Add(new LogMessage() { Message = stringMessage, MessageType = LogMessageType.Error });
// }
return messages.Count;
}
///
/// Executes the kernel.
///
/// The kernel data input.
/// The return messages.
///
public IKernelDataOutput Execute(IKernelDataInput kernelDataInput, out List messages)
{
var damMacroStabilityOutput = new DamMacroStabilityOutput();
messages = new List();
// ToDo zant Question: write sti file in prepare or in execute?
// Write xml file
XDocument xmlDocument = CreateMstabDamXmlDocument();
// Use xml file to create sti file
CreateStiFile(xmlDocument);
// start calculation
var calculator = StabilityCalculator(kernelDataInput);
calculator.Calculate();
// get results
var results = calculator.GetResults();
if (results.Count > 0)
{
var zone1 = new DamMacroStabilityOutput.ResultsSingleZone();
zone1.SafetyFactor = results[0].Zone1.SafetyFactor;
zone1.CircleSurfacePointLeftXCoordinate = results[0].Zone1.CircleSurfacePointLeftXCoordinate;
zone1.CircleSurfacePointRightXCoordinate = results[0].Zone1.CircleSurfacePointRightXCoordinate;
zone1.EntryPointXCoordinate = results[0].Zone1.EntryPointXCoordinate;
zone1.ExitPointXCoordinate = results[0].Zone1.ExitPointXCoordinate;
damMacroStabilityOutput.Zone1 = zone1;
if (results[0].Zone2 != null)
{
var zone2 = new DamMacroStabilityOutput.ResultsSingleZone();
zone2.SafetyFactor = results[0].Zone1.SafetyFactor;
zone2.CircleSurfacePointLeftXCoordinate = results[0].Zone1.CircleSurfacePointLeftXCoordinate;
zone2.CircleSurfacePointRightXCoordinate = results[0].Zone1.CircleSurfacePointRightXCoordinate;
zone2.EntryPointXCoordinate = results[0].Zone1.EntryPointXCoordinate;
zone2.ExitPointXCoordinate = results[0].Zone1.ExitPointXCoordinate;
damMacroStabilityOutput.Zone2 = zone2;
}
}
return damMacroStabilityOutput;
}
internal XDocument CreateMstabDamXmlDocument()
{
// ToDo zant Fake data
// var stabilityProjectFilename = "testproject";
// var scenario = new DesignScenario();
// var soilProfile = new SoilProfile1D();
// var soilGeometry2DName = "testgeom2D";
// var riverLevel = 1.1;
// var mstabDesignEmbankment = new MStabDesignEmbankment();
// var surfaceLine = new SurfaceLine2();
// var trafficLoad = 2.2;
// var requiredSafetyFactor = 1.2;
// List errorMessages;
//
// XDocument TestmstabXml = MStabXmlDoc.CreateMStabXmlDoc(stabilityProjectFilename, scenario, soilProfile, soilGeometry2DName,
// riverLevel, mstabDesignEmbankment, surfaceLine, trafficLoad, requiredSafetyFactor, out errorMessages);
// TestmstabXml.Save(stabilityProjectFilename + ".xml");
// ToDo zant_xml tmp use predefined xml doc until CreateMstabDamXmlDocument is fully implemented
const string testFolder = @"..\..\Deltares.DamEngine.Calculators.Tests\Files\MacroStability";
var xmlFileName = Path.Combine(testFolder, "test.xml");
var stiFileName = Path.Combine(testFolder, "test.sti");
var geometryFileName = Path.Combine(testFolder, "DWP_1.sti");
var soilDbName = Path.Combine(testFolder, "DAM Tutorial Design0.soilmaterials.mdb");
XDocument mstabXml = XDocument.Load(xmlFileName);
XElement inputElement = (from element in mstabXml.Root.Descendants()
where element.Name.LocalName == DamMStabAssembler.XmlElementNameInput
select element).Single();
XAttribute mstabFileName = inputElement.Attribute(DamMStabAssembler.XmlAttributeMStabFileName);
Debug.Assert(mstabFileName != null, "mstabFileName != null");
mstabFileName.Value = stiFileName;
// modify name of Soil DB Name
XAttribute dbName = inputElement.Attribute(DamMStabAssembler.XmlAttributeSoilDBName);
Debug.Assert(dbName != null, "dbName != null");
dbName.Value = soilDbName;
// modify name of geometry input file
XElement geometryOptionsElement = (from element in inputElement.Descendants()
where element.Name.LocalName == DamMStabAssembler.XmlElementGeometryCreationOptions
select element).Single();
XAttribute geomFileName = geometryOptionsElement.Attribute(DamMStabAssembler.XmlAttributeSoilGeometry2DFilename);
Debug.Assert(geomFileName != null, "geomFileName != null");
geomFileName.Value = geometryFileName;
return mstabXml;
}
internal void CreateStiFile(XDocument xmlDocument)
{
DGSMStabDAMInterface mstabDamDll = new DGSMStabDAMInterface();
var result = mstabDamDll.CreateProjectFile(xmlDocument.ToString());
if (result > 0)
{
string errorMessage = mstabDamDll.ErrorMessage();
throw new MacroStabilityException(errorMessage);
}
}
internal static StabilityCalculator StabilityCalculator(IKernelDataInput kernelDataInput)
{
DamMacroStabilityInput damMacroStabilityInput = kernelDataInput as DamMacroStabilityInput;
if (damMacroStabilityInput == null)
{
throw new NoNullAllowedException(Resources.DamMacroStabilityKernelWrapper_StabilityCalculator_NoInputObjectDefinedForMacroStability);
}
var calculator = new StabilityCalculator
{
ProjectName = damMacroStabilityInput.DGeoStabilityInputFileName,
DGeoStabilityExePath = damMacroStabilityInput.DGeoStabilityExePath
};
return calculator;
}
///
/// Fills the design results with the kernel output.
///
/// The dam kernel input.
/// The .
/// The kernel data output.
/// The design result.
///
public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, out DesignResult designResult)
{
DamMacroStabilityOutput damPipingOutput = kernelDataOutput as DamMacroStabilityOutput;
if (damPipingOutput == null)
{
throw new NoNullAllowedException(Resources.DamMacroStabilityKernelWrapper_PostProcess_NoOutputObjectDefinedForSellmeijer4Forces);
}
// TODO: this is just fake data
string id = "id";
string soilProfile2DName = "soilProfile2DName";
var d = new DamFailureMechanismeCalculationSpecification();
var s = new DesignScenario();
s.Location = new Location();
var p = new SoilProfile1D();
designResult = new DesignResult(d, s, p, soilProfile2DName, AnalysisType.NoAdaption);
var stabilityDesignResults = new StabilityDesignResults();
stabilityDesignResults.Zone1SafetyFactor = damPipingOutput.Zone1.SafetyFactor;
stabilityDesignResults.LocalZone1EntryPointX = damPipingOutput.Zone1.EntryPointXCoordinate;
stabilityDesignResults.LocalZone1ExitPointX = damPipingOutput.Zone1.ExitPointXCoordinate;
stabilityDesignResults.SafetyFactor = stabilityDesignResults.Zone1SafetyFactor;
if (damPipingOutput.Zone2 != null)
{
var zone2 = (DamMacroStabilityOutput.ResultsSingleZone) damPipingOutput.Zone2;
stabilityDesignResults.Zone2SafetyFactor = zone2.SafetyFactor;
stabilityDesignResults.LocalZone2EntryPointX = zone2.EntryPointXCoordinate;
stabilityDesignResults.LocalZone2ExitPointX = zone2.ExitPointXCoordinate;
stabilityDesignResults.SafetyFactor = Math.Min(damPipingOutput.Zone1.SafetyFactor, zone2.SafetyFactor);
}
designResult.StabilityDesignResults = stabilityDesignResults;
}
}
}