// Copyright (C) Stichting Deltares 2018. 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.Data; using System.IO; using System.Xml.Linq; using Deltares.DamEngine.Calculators.KernelWrappers.Common; using Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStabilityCommon; 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.Calculation; using Deltares.DamEngine.Data.Standard.Logging; using Deltares.DamMacroStability.Calculator; namespace Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStabilityInwards { public class DamMacroStabilityInwardsKernelWrapper : IKernelWrapper { /// /// Gets or sets the failure mechanisme paramaters for mstab. /// /// /// The failure mechanisme paramaters mstab. /// public FailureMechanismParametersMStab FailureMechanismParametersMStab { get; set; } /// /// Prepares the specified dam kernel input. /// /// The dam kernel input. /// The number of the current iteration. /// The kernel data input. /// The kernel data output /// /// Result of the prepare /// public PrepareResult Prepare(DamKernelInput damKernelInput, int iterationIndex, out IKernelDataInput kernelDataInput, out IKernelDataOutput kernelDataOutput) { var damMacroStabilityOutput = new DamMacroStabilityOutput() { StabilityOutputItems = new List(), CalculationResult = CalculationResult.NoRun }; kernelDataOutput = damMacroStabilityOutput; // Make sure the gridposition is Right. FailureMechanismParametersMStab.MStabParameters.GridPosition = MStabGridPosition.Right; if (damKernelInput.SubSoilScenario.SegmentFailureMechanismType == FailureMechanismSystemType.StabilityInside) { var model = FailureMechanismParametersMStab.MStabParameters.Model; if (model == MStabModelType.BishopUpliftVan) { // if current model is BishopUpliftVan then set to Bishop for proper name/path for inputfile model = MStabModelType.Bishop; } FailureMechanismParametersMStab.DGeoStabilityExePath = @".\KernelWrappers\DamMacroStabilityCommon\DGeoStability.exe"; if (string.IsNullOrEmpty(damKernelInput.WorkingDir)) { FailureMechanismParametersMStab.ProjectWorkingPath = Directory.GetCurrentDirectory(); } else { FailureMechanismParametersMStab.ProjectWorkingPath = damKernelInput.WorkingDir; } damKernelInput.SubSoilScenario.StiFileName = Path.Combine(damKernelInput.Location.StabilityOptions.MapForSoilGeometries2D, damKernelInput.SubSoilScenario.StiFileName); var damMacroStabilityInput = new DamMacroStabilityInput() { DGeoStabilityExePath = FailureMechanismParametersMStab.DGeoStabilityExePath, DGeoStabilityInputFileName = DamMacroStabilityUtils.GetStabilityInputFileName( damKernelInput, iterationIndex, model, FailureMechanismParametersMStab.ProjectWorkingPath), FailureMechanismParametersMStab = FailureMechanismParametersMStab }; // Check the model to see what is to be calculted and how many calculations are required switch (FailureMechanismParametersMStab.MStabParameters.Model) { case MStabModelType.Bishop: case MStabModelType.UpliftVan: { // prepare the requested calc break; } case MStabModelType.BishopUpliftVan: { // see if uplift is required // if so, both upliftvan and bishop are to be prepared, calculated and worst case is to be determined damMacroStabilityInput.DGeoStabilityInputFileNameSecondModel = DamMacroStabilityUtils.GetStabilityInputFileName(damKernelInput, iterationIndex, MStabModelType.UpliftVan, FailureMechanismParametersMStab.ProjectWorkingPath); // if not, only Bishop calculation so leave SecondModel empty. break; } default: { //model not implemented error break; } } kernelDataInput = damMacroStabilityInput; // Write xml file XDocument xmlDocument = CreateMstabDamXmlDocument(damKernelInput, damMacroStabilityInput); // Use xml file to create sti file CreateStiFile(xmlDocument); return PrepareResult.Successful; } kernelDataInput = null; return PrepareResult.NotRelevant; } /// /// Validates the specified kernel data input. /// /// The kernel data input. /// The kernel data output. /// The return messages. /// /// Number of errors that prevent a calculation /// public int Validate(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, 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 kernel data output. /// The return messages. public void Execute(IKernelDataInput kernelDataInput, IKernelDataOutput kernelDataOutput, out List messages) { DamMacroStabilityOutput damMacroStabilityOutput = (DamMacroStabilityOutput) kernelDataOutput; messages = new List(); var input = (DamMacroStabilityInput)kernelDataInput; // When there are two calculations to be performed (BishopUpliftVan), make sure the first one is Bishop if (!string.IsNullOrEmpty(input.DGeoStabilityInputFileNameSecondModel)) { input.FailureMechanismParametersMStab.MStabParameters.Model = MStabModelType.Bishop; } // start (first) calculation var stabilityOutputItem = ExcecuteCalculation(kernelDataInput); if (stabilityOutputItem != null) { damMacroStabilityOutput.StabilityOutputItems.Add(stabilityOutputItem); } // now check if second calculation for BishopUpliftVan is needed, if so perform it. if (!string.IsNullOrEmpty(input.DGeoStabilityInputFileNameSecondModel)) { var inputFileName = input.DGeoStabilityInputFileName; // set proper name and model input.DGeoStabilityInputFileName = input.DGeoStabilityInputFileNameSecondModel; input.FailureMechanismParametersMStab.MStabParameters.Model = MStabModelType.UpliftVan; try { var stabilityOutputItemSecondModel = ExcecuteCalculation(kernelDataInput); if (stabilityOutputItemSecondModel != null) { damMacroStabilityOutput.StabilityOutputItems.Add(stabilityOutputItemSecondModel); } } finally { // reset name and model input.DGeoStabilityInputFileName = inputFileName; input.FailureMechanismParametersMStab.MStabParameters.Model = MStabModelType.BishopUpliftVan; } } } private static DamMacroStabilityOutputItem ExcecuteCalculation(IKernelDataInput kernelDataInput) { var calculator = StabilityCalculator(kernelDataInput); calculator.Calculate(); // get (first) results var results = calculator.GetResults(); if (results.Count > 0) { var stabilityOutputItem = new DamMacroStabilityOutputItem(); var zone1 = new DamMacroStabilityOutputItem.ResultsSingleZone { SafetyFactor = results[0].Zone1.SafetyFactor, CircleSurfacePointLeftXCoordinate = results[0].Zone1.CircleSurfacePointLeftXCoordinate, CircleSurfacePointRightXCoordinate = results[0].Zone1.CircleSurfacePointRightXCoordinate, EntryPointXCoordinate = results[0].Zone1.EntryPointXCoordinate, ExitPointXCoordinate = results[0].Zone1.ExitPointXCoordinate }; stabilityOutputItem.Zone1Results = zone1; if (results[0].Zone2 != null) { var zone2 = new DamMacroStabilityOutputItem.ResultsSingleZone { SafetyFactor = results[0].Zone1.SafetyFactor, CircleSurfacePointLeftXCoordinate = results[0].Zone1.CircleSurfacePointLeftXCoordinate, CircleSurfacePointRightXCoordinate = results[0].Zone1.CircleSurfacePointRightXCoordinate, EntryPointXCoordinate = results[0].Zone1.EntryPointXCoordinate, ExitPointXCoordinate = results[0].Zone1.ExitPointXCoordinate }; stabilityOutputItem.Zone2Results = zone2; } return stabilityOutputItem; } return null; } internal XDocument CreateMstabDamXmlDocument(DamKernelInput damKernelInput, DamMacroStabilityInput kernelDataInput) { var stabilityProjectFilename = kernelDataInput.DGeoStabilityInputFileName; var scenario = damKernelInput.DesignScenario; var subSoilScenario = damKernelInput.SubSoilScenario; var requiredSafetyFactor = scenario.RequiredSafetyFactorStabilityInnerSlope?? scenario.Location.ModelFactors.RequiredSafetyFactorStabilityInnerSlope; if (requiredSafetyFactor == null) { throw new MacroStabilityException("Required safety factor must be specified"); } List errorMessages; XDocument mstabXml = MStabXmlDoc.CreateMStabXmlDoc(stabilityProjectFilename, scenario, subSoilScenario, null, requiredSafetyFactor.Value, kernelDataInput.FailureMechanismParametersMStab, out errorMessages); mstabXml.Save(stabilityProjectFilename + ".xml"); 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 kernel data output. /// The result message. /// The design results. /// public void PostProcess(DamKernelInput damKernelInput, IKernelDataOutput kernelDataOutput, string resultMessage, out List designResults) { DamMacroStabilityOutput damMacroStabilityOutput = kernelDataOutput as DamMacroStabilityOutput; if (damMacroStabilityOutput == null) { throw new NoNullAllowedException(Resources.DamMacroStabilityKernelWrapper_PostProcess_NoOutputObjectDefinedForMacroStability); } // TODO: this is just fake data string soilProfile2DName = "soilProfile2DName"; var d = new DamFailureMechanismeCalculationSpecification(); var s = new DesignScenario { Location = new Location() }; var p = new SoilProfile1D(); designResults = new List(); var designResult = new DesignResult(d, s, p, soilProfile2DName, AnalysisType.NoAdaption); if (damMacroStabilityOutput.StabilityOutputItems.Count > 0) { var damMacroStabilityOutputItem = damMacroStabilityOutput.StabilityOutputItems[0]; if (damMacroStabilityOutputItem != null) { FillDesignResult(damMacroStabilityOutputItem, designResult); designResults.Add(designResult); } } if (damMacroStabilityOutput.StabilityOutputItems.Count > 1) { // Todo this next line is still fake! designResult = new DesignResult(d, s, p, soilProfile2DName, AnalysisType.NoAdaption); var damMacroStabilityOutputItem = damMacroStabilityOutput.StabilityOutputItems[1]; if (damMacroStabilityOutputItem != null) { FillDesignResult(damMacroStabilityOutputItem, designResult); } designResults.Add(designResult); //Todo combine results from bishop/upliftvan and add these too? check in old Dam. // Bka: Old Dam shows both bishop, upliftvan and combined result. So this should // add decisive result as well. } } private static void FillDesignResult(DamMacroStabilityOutputItem damMacroStabilityOutputItem, DesignResult designResult) { var stabilityDesignResults = new StabilityDesignResults { Zone1SafetyFactor = damMacroStabilityOutputItem.Zone1Results.SafetyFactor, LocalZone1EntryPointX = damMacroStabilityOutputItem.Zone1Results.EntryPointXCoordinate, LocalZone1ExitPointX = damMacroStabilityOutputItem.Zone1Results.ExitPointXCoordinate }; stabilityDesignResults.SafetyFactor = stabilityDesignResults.Zone1SafetyFactor; if (damMacroStabilityOutputItem.Zone2Results != null) { var zone2 = (DamMacroStabilityOutputItem.ResultsSingleZone) damMacroStabilityOutputItem.Zone2Results; stabilityDesignResults.Zone2SafetyFactor = zone2.SafetyFactor; stabilityDesignResults.LocalZone2EntryPointX = zone2.EntryPointXCoordinate; stabilityDesignResults.LocalZone2ExitPointX = zone2.ExitPointXCoordinate; stabilityDesignResults.SafetyFactor = Math.Min(damMacroStabilityOutputItem.Zone1Results.SafetyFactor, zone2.SafetyFactor); } designResult.StabilityDesignResults = stabilityDesignResults; } } }