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; } } }