// Copyright (C) Stichting Deltares 2024. All rights reserved.
//
// This file is part of the application DAM - UI.
//
// DAM - UI is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU 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 Deltares.DamEngine.Io.XmlOutput;
using Deltares.Geometry;
using Deltares.Geotechnics.GeotechnicalGeometry;
using Deltares.Geotechnics.Soils;
using Deltares.Geotechnics.SurfaceLines;
using Deltares.Mathematics;
using Deltares.Standard;
using Deltares.Standard.EventPublisher;
using Deltares.Standard.Logging;
using SurfaceLine = Deltares.DamEngine.Io.XmlOutput.SurfaceLine;
namespace Deltares.Dam.Data.DamEngineIo;
///
/// Exception class for FillDamUiFromXmlOutput
///
public class FillDamUiFromXmlOutputException : Exception
{
public FillDamUiFromXmlOutputException(string message)
: base(message) {}
}
///
/// Class to support the conversion of XmlOutput (as provided by the Engine) to DamUI objects.
///
public class FillDamUiFromXmlOutput
{
///
/// Adds the output to dam project data.
/// Precondition is that dam project data is filled and contains all relevant data that is referred to in the Output.
///
/// The dam project data.
/// The output.
///
public static DamProjectData AddOutputToDamProjectData(DamProjectData damProjectData, Output output)
{
if (output?.Results?.CalculationResults != null)
{
DataEventPublisher.InvokeWithoutPublishingEvents(() => { CreateDesignResultsFromOutput(output, damProjectData); }
);
}
// Transfer calculation messages
if (output?.Results?.CalculationMessages != null)
{
damProjectData.CalculationMessages = new List();
for (var i = 0; i < output.Results.CalculationMessages.Length; i++)
{
Message validationResult = output.Results.CalculationMessages[i];
var logMessage = new LogMessage
{
MessageType = ConversionHelper.ConvertToMessageType(validationResult.MessageType),
Subject = null,
Message = validationResult.Message1
};
damProjectData.CalculationMessages.Add(logMessage);
}
}
// Transfer output time series
if (output != null && output.Results != null && output.Results.OperationalOutputTimeSeries != null)
{
damProjectData.OutputTimeSerieCollection = new TimeSerieCollection();
TransferOutputTimeSeries(output.Results.OperationalOutputTimeSeries, damProjectData.OutputTimeSerieCollection);
if (output.Results.OperationalStaticData is { StabilityModel: OperationalStaticDataStabilityModel.Bishop })
{
TransferOutputTimeSeries(output.Results.OperationalOutputTimeSeries, damProjectData.OutputTimeSerieCollection, TimeSerieParameters.BishopCircleCentreX.ToString());
TransferOutputTimeSeries(output.Results.OperationalOutputTimeSeries, damProjectData.OutputTimeSerieCollection, TimeSerieParameters.BishopCircleCentreZ.ToString());
TransferOutputTimeSeries(output.Results.OperationalOutputTimeSeries, damProjectData.OutputTimeSerieCollection, TimeSerieParameters.BishopCircleRadius.ToString());
}
}
damProjectData.TransferOutputTimeSerieToLocationJobs();
return damProjectData;
}
private static void TransferOutputTimeSeries(TimeSerieOutput[] outputTimeSeries, TimeSerieCollection outputTimeSerieCollection, string parameterId = "")
{
foreach (TimeSerieOutput outputTimeSerie in outputTimeSeries)
{
TimeSerie timeSerie = outputTimeSerieCollection.AddNewSeries(outputTimeSerie.LocationId);
timeSerie.ParameterId = parameterId == "" ? outputTimeSerie.ParameterId : parameterId;
timeSerie.ForecastDateTime = outputTimeSerie.ForecastDateTime;
timeSerie.StartDateTime = outputTimeSerie.StartDateTime;
timeSerie.EndDateTime = outputTimeSerie.EndDateTime;
timeSerie.MissVal = outputTimeSerie.MissVal;
timeSerie.Units = outputTimeSerie.Units;
for (var i = 0; i < outputTimeSerie.Entries.TimeSerieEntryOutput.Length; i++)
{
TimeSerieOutputEntriesTimeSerieEntryOutput entry = outputTimeSerie.Entries.TimeSerieEntryOutput[i];
var timeSerieEntry = new TimeSerieEntry
{
DateTime = entry.DateTime
};
if (parameterId == "")
{
timeSerieEntry.Value = entry.Value;
}
if (parameterId == TimeSerieParameters.BishopCircleCentreX.ToString())
{
timeSerieEntry.Value = entry.BishopCalculatedSlipPlane is { Center: not null } ? entry.BishopCalculatedSlipPlane.Center.X : double.NaN;
}
if (parameterId == TimeSerieParameters.BishopCircleCentreZ.ToString())
{
timeSerieEntry.Value = entry.BishopCalculatedSlipPlane is { Center: not null } ? entry.BishopCalculatedSlipPlane.Center.Z : double.NaN;
}
if (parameterId == TimeSerieParameters.BishopCircleRadius.ToString())
{
timeSerieEntry.Value = entry.BishopCalculatedSlipPlane?.Radius ?? double.NaN;
}
timeSerie.Entries.Add(timeSerieEntry);
}
}
}
private static void CreateDesignResultsFromOutput(Output output, DamProjectData damProjectData)
{
if (damProjectData.WaterBoard.Dikes[0] != null)
{
// Design results
damProjectData.DesignCalculations = new List();
for (var i = 0; i < output.Results.CalculationResults.Length; i++)
{
DesignResult designResult = output.Results.CalculationResults[i];
if (string.IsNullOrEmpty(designResult.BaseFileName))
{
designResult.BaseFileName = "Loc(" + designResult.LocationName + ")_Prof(" + designResult.ProfileName + ")_Scen(" + designResult.ScenarioName + ")";
}
var desResult = new CsvExportData(designResult.LocationName, designResult.ScenarioName)
{
DamFailureMechanismeCalculation = damProjectData.DamProjectCalculationSpecification.CurrentSpecification, // vanuit invoer
AnalysisType = DamProjectCalculationSpecification.SelectedAnalysisType, //is vanuit invoer
DikeName = damProjectData.WaterBoard.Dikes[0].Name, // is de enige voor nu
CalculationResult = ConversionHelper.ConvertToCalculationResult(designResult.CalculationResult),
BaseFileName = designResult.BaseFileName,
CalculationSubDir = designResult.CalculationSubDir,
ProfileName = designResult.ProfileName
};
desResult.CalculationResult = ConversionHelper.ConvertToCalculationResult(designResult.CalculationResult);
Scenario scenario = GetScenarioByName(damProjectData, designResult.LocationName, designResult.ScenarioName);
desResult.Scenario = scenario;
SoilProfile1D soilProfile = GetSoilProfileByName(damProjectData, designResult.ProfileName);
if (soilProfile == null)
{
desResult.SoilGeometry2DName = designResult.ProfileName;
}
else
{
desResult.SoilProfile = soilProfile;
}
if (designResult.PipingDesignResults != null)
{
CreateDesignResultsPipingOutput(designResult, desResult);
}
if (designResult.StabilityDesignResults != null)
{
CreateDesignResultsStabilityOutput(designResult, desResult);
}
int index = output.Results.CalculationResults.Where(y => y.LocationName == designResult.LocationName).ToList().IndexOf(designResult);
if (desResult.Scenario != null)
{
desResult.LocationScenarioCount = scenario.Location.Scenarios.Count;
desResult.ScenarioIndex = index;
desResult.Scenario.CalculationResult = desResult.CalculationResult;
desResult.Scenario.CalculationResults.Add(desResult);
}
damProjectData.DesignCalculations.Add(desResult);
}
}
}
private static void CreateDesignResultsPipingOutput(DesignResult designResult, CsvExportData desResult)
{
desResult.ResultMessage = designResult.PipingDesignResults.ResultMessage;
if (designResult.PipingDesignResults.RedesignedSurfaceLine != null)
{
desResult.RedesignedSurfaceLine2 = new SurfaceLine2();
SurfaceLine2 surfaceLine = ConvertXmlSurfaceLineToSurfaceLine2(designResult.PipingDesignResults.RedesignedSurfaceLine);
desResult.RedesignedSurfaceLine2 = surfaceLine;
}
if (designResult.PipingDesignResults.UpliftFactorSpecified)
{
desResult.UpliftFactor = designResult.PipingDesignResults.UpliftFactor;
}
if (designResult.PipingDesignResults.HeaveFactorSpecified)
{
desResult.HeaveFactor = designResult.PipingDesignResults.HeaveFactor;
}
if (designResult.PipingDesignResults.BlighFactorSpecified)
{
desResult.BlighPipingFactor = designResult.PipingDesignResults.BlighFactor;
}
if (designResult.PipingDesignResults.BlighHcriticalSpecified)
{
desResult.BlighHCritical = designResult.PipingDesignResults.BlighHcritical;
}
if (designResult.PipingDesignResults.Wti2017BackwardErosionFactorSpecified)
{
desResult.Wti2017BackwardErosionSafetyFactor = designResult.PipingDesignResults.Wti2017BackwardErosionFactor;
}
if (designResult.PipingDesignResults.Wti2017BackwardErosionHcriticalSpecified)
{
desResult.Wti2017BackwardErosionHcritical = designResult.PipingDesignResults.Wti2017BackwardErosionHcritical;
}
if (designResult.PipingDesignResults.Wti2017BackwardErosionDeltaPhiCSpecified)
{
desResult.Wti2017BackwardErosionDeltaPhiC = designResult.PipingDesignResults.Wti2017BackwardErosionDeltaPhiC;
}
if (designResult.PipingDesignResults.Wti2017BackwardErosionDeltaPhiReducedSpecified)
{
desResult.Wti2017BackwardErosionDeltaPhiReduced = designResult.PipingDesignResults.Wti2017BackwardErosionDeltaPhiReduced;
}
if (designResult.PipingDesignResults.Wti2017UpliftFactorSpecified)
{
desResult.Wti2017UpliftSafetyFactor = designResult.PipingDesignResults.Wti2017UpliftFactor;
}
if (designResult.PipingDesignResults.Wti2017UpliftHcriticalSpecified)
{
desResult.Wti2017UpliftHcritical = designResult.PipingDesignResults.Wti2017UpliftHcritical;
}
if (designResult.PipingDesignResults.Wti2017DeltaPhiCuSpecified)
{
desResult.Wti2017UpliftDeltaPhiC = designResult.PipingDesignResults.Wti2017DeltaPhiCu;
}
if (designResult.PipingDesignResults.Wti2017HeaveFactorSpecified)
{
desResult.Wti2017HeaveSafetyFactor = designResult.PipingDesignResults.Wti2017HeaveFactor;
}
if (designResult.PipingDesignResults.Wti2017HeaveHcriticalSpecified)
{
desResult.Wti2017HeaveHcritical = designResult.PipingDesignResults.Wti2017HeaveHcritical;
}
if (designResult.PipingDesignResults.Wti2017GradientSpecified)
{
desResult.Wti2017Gradient = designResult.PipingDesignResults.Wti2017Gradient;
}
if (designResult.PipingDesignResults.Wti2017FactorOverallSpecified)
{
desResult.Wti2017SafetyFactorOverall = designResult.PipingDesignResults.Wti2017FactorOverall;
}
if (designResult.PipingDesignResults.Wti2017HcriticalOverallSpecified)
{
desResult.Wti2017HcriticalOverall = designResult.PipingDesignResults.Wti2017HcriticalOverall;
}
if (designResult.PipingDesignResults.Wti2017EffectiveStressSpecified)
{
desResult.Wti2017EffectiveStress = designResult.PipingDesignResults.Wti2017EffectiveStress;
}
if (designResult.PipingDesignResults.Wti2017CCreepSpecified)
{
desResult.Wti2017CCreep = designResult.PipingDesignResults.Wti2017CCreep;
}
if (designResult.PipingDesignResults.ExitPointXSpecified)
{
desResult.LocalPipingExitPointX = designResult.PipingDesignResults.ExitPointX;
}
if (designResult.PipingDesignResults.UpliftSituation != null)
{
DamEngine.Io.XmlOutput.UpliftSituation uplift = designResult.PipingDesignResults.UpliftSituation;
desResult.IsUplift = uplift.IsUplift;
if (desResult.IsUplift.Value)
{
desResult.IsUplift = uplift.IsUplift;
desResult.Pl3MinUplift = uplift.Pl3MinUplift;
desResult.Pl3HeadAdjusted = uplift.Pl3HeadAdjusted;
desResult.Pl3LocalLocationXMinUplift = uplift.Pl3LocationXMinUplift;
desResult.Pl4MinUplift = uplift.Pl4MinUplift;
desResult.Pl4HeadAdjusted = uplift.Pl4HeadAdjusted;
desResult.Pl4LocalLocationXMinUplift = uplift.Pl4LocationXMinUplift;
}
else
{
ResetUpliftValues(desResult);
}
}
else
{
ResetUpliftValues(desResult);
}
if (string.IsNullOrEmpty(desResult.CalculationSubDir))
{
desResult.CalculationSubDir = Path.Combine("Piping", desResult.PipingModel.ToString());
}
if (string.IsNullOrEmpty(desResult.BaseFileName))
{
desResult.BaseFileName = "Loc(" + designResult.LocationName + ")_Prof(" + designResult.ProfileName + ")_Scen(" + designResult.ScenarioName + ")";
}
desResult.CreateResultsFileForSurfaceLineAndProfile(desResult.PipingResultFile);
}
private static Scenario GetScenarioByName(DamProjectData damProjectData, string locationName, string scenarioName)
{
List locations = damProjectData.Locations;
foreach (Location location in locations)
{
if (location.Name == locationName)
{
foreach (Scenario scenario in location.Scenarios)
{
if (scenario.LocationScenarioID == scenarioName)
{
return scenario;
}
}
}
}
return null;
}
private static SoilProfile1D GetSoilProfileByName(DamProjectData damProjectData, string profileName)
{
IList soilProfiles1D = damProjectData.WaterBoard.Dikes[0].SoilProfiles;
foreach (SoilProfile1D soilProfile1D in soilProfiles1D)
{
if (soilProfile1D.Name == profileName)
{
return soilProfile1D;
}
}
return null;
}
private static SurfaceLine2 ConvertXmlSurfaceLineToSurfaceLine2(SurfaceLine inputSurfaceLine)
{
var surfaceLine = new SurfaceLine2
{
Name = inputSurfaceLine.Name
};
surfaceLine.CharacteristicPoints.Geometry = surfaceLine.Geometry;
AddPointsToSurfaceLine(inputSurfaceLine, surfaceLine);
return surfaceLine;
}
private static void AddPointsToSurfaceLine(SurfaceLine inputSurfaceLine, SurfaceLine2 surfaceLine)
{
surfaceLine.Geometry = new LocalizedGeometryPointString();
for (var j = 0; j < inputSurfaceLine.Points.Length; j++)
{
SurfaceLinePoint inputPoint = inputSurfaceLine.Points[j];
var geometryPoint = new GeometryPoint
{
X = inputPoint.X,
Y = 0.0,
Z = inputPoint.Z
};
surfaceLine.AddCharacteristicPoint(geometryPoint, ConversionHelper.ConvertToDamPointType(inputPoint.PointType));
}
}
private static void CreateDesignResultsStabilityOutput(DesignResult designResult, CsvExportData desResult)
{
desResult.ResultMessage = designResult.StabilityDesignResults.ResultMessage;
if (designResult.StabilityDesignResults.RedesignedSurfaceLine != null)
{
SurfaceLine2 surfaceLine = ConvertXmlSurfaceLineToSurfaceLine2(designResult.StabilityDesignResults.RedesignedSurfaceLine);
desResult.RedesignedSurfaceLine2 = surfaceLine;
}
if (designResult.StabilityDesignResults.SafetyFactorSpecified)
{
desResult.StabilitySafetyFactor = designResult.StabilityDesignResults.SafetyFactor;
}
if (designResult.StabilityDesignResults.NumberOfIterationsSpecified)
{
desResult.NumberOfIterations = designResult.StabilityDesignResults.NumberOfIterations;
}
if (designResult.StabilityDesignResults.StabilityModelTypeSpecified)
{
desResult.StabilityModel = ConversionHelper.ConvertToStabilityModelType(designResult.StabilityDesignResults.StabilityModelType);
}
if (designResult.StabilityDesignResults.UpliftSituation != null)
{
CreateDesignUpliftSituationResults(designResult, desResult);
}
else
{
ResetUpliftValues(desResult);
}
if (designResult.StabilityDesignResults.SlipCircleDefinition != null)
{
CreateSlipPlaneDefinitionResults(designResult, desResult);
}
if (string.IsNullOrEmpty(desResult.CalculationSubDir) && (desResult.CalculationResult != CalculationResult.RunFailed) &&
(desResult.CalculationResult != CalculationResult.UnexpectedError))
{
throw new FillDamUiFromXmlOutputException(nameof(desResult.CalculationSubDir) + " is null or empty.");
}
if (string.IsNullOrEmpty(desResult.BaseFileName))
{
throw new FillDamUiFromXmlOutputException(nameof(desResult.BaseFileName) + " is null or empty.");
}
if ((desResult.CalculationResult != CalculationResult.RunFailed) &&
(desResult.CalculationResult != CalculationResult.UnexpectedError &&
designResult.StabilityDesignResults.StabilityModelType != DesignResultStabilityDesignResultsStabilityModelType.BishopUpliftVan))
{
desResult.CreateResultsFileForSurfaceLineAndProfile(desResult.GetDesignResultFile());
}
}
private static void CreateSlipPlaneDefinitionResults(DesignResult designResult, CsvExportData desResult)
{
bool isBishop = designResult.StabilityDesignResults.StabilityModelType == DesignResultStabilityDesignResultsStabilityModelType.Bishop;
bool isUpliftVan = designResult.StabilityDesignResults.StabilityModelType == DesignResultStabilityDesignResultsStabilityModelType.UpliftVan;
if (designResult.StabilityDesignResults.StabilityModelType == DesignResultStabilityDesignResultsStabilityModelType.BishopUpliftVan)
{
isBishop = designResult.StabilityDesignResults.SlipCircleDefinition is SlidingCircleMinimumSafetyCurveType;
isUpliftVan = designResult.StabilityDesignResults.SlipCircleDefinition is DualSlidingCircleMinimumSafetyCurveType;
}
if (isBishop)
{
var singleSlipCircleDefinition = (SlidingCircleMinimumSafetyCurveType) designResult.StabilityDesignResults.SlipCircleDefinition;
if (singleSlipCircleDefinition.Center != null)
{
desResult.ActiveCenterPointX = singleSlipCircleDefinition.Center.X;
desResult.ActiveCenterPointZ = singleSlipCircleDefinition.Center.Z;
desResult.ActiveCenterPointRadius = singleSlipCircleDefinition.Radius;
}
}
if (isUpliftVan)
{
var dualSlipCircleDefinition = (DualSlidingCircleMinimumSafetyCurveType) designResult.StabilityDesignResults.SlipCircleDefinition;
if (dualSlipCircleDefinition.ActiveCircleCenter != null)
{
desResult.ActiveCenterPointX = dualSlipCircleDefinition.ActiveCircleCenter.X;
desResult.ActiveCenterPointZ = dualSlipCircleDefinition.ActiveCircleCenter.Z;
desResult.ActiveCenterPointRadius = dualSlipCircleDefinition.ActiveCircleRadius;
}
if (dualSlipCircleDefinition.PassiveCircleCenter != null)
{
desResult.PassiveCenterPointX = dualSlipCircleDefinition.PassiveCircleCenter.X;
desResult.PassiveCenterPointZ = dualSlipCircleDefinition.PassiveCircleCenter.Z;
desResult.PassiveCenterPointRadius = dualSlipCircleDefinition.PassiveCircleRadius;
}
}
if (designResult.StabilityDesignResults.StabilityModelType is DesignResultStabilityDesignResultsStabilityModelType.Bishop
or DesignResultStabilityDesignResultsStabilityModelType.UpliftVan
or DesignResultStabilityDesignResultsStabilityModelType.BishopUpliftVan)
{
if (designResult.StabilityDesignResults.SlipCircleDefinition.Slices != null)
{
desResult.ResultSlices = new List();
foreach (MinimumSafetyCurveBaseTypeSlice slice in designResult.StabilityDesignResults.SlipCircleDefinition.Slices)
{
var resultSlice = new StabilityResultSlice
{
TopLeftPoint = new Point2D(slice.TopLeftPoint.X, slice.TopLeftPoint.Z),
TopRightPoint = new Point2D(slice.TopRightPoint.X, slice.TopRightPoint.Z),
BottomLeftPoint = new Point2D(slice.BottomLeftPoint.X, slice.BottomLeftPoint.Z),
BottomRightPoint = new Point2D(slice.BottomRightPoint.X, slice.BottomRightPoint.Z)
};
desResult.ResultSlices.Add(resultSlice);
}
}
}
}
private static void CreateDesignUpliftSituationResults(DesignResult designResult, CsvExportData desResult)
{
DamEngine.Io.XmlOutput.UpliftSituation uplift = designResult.StabilityDesignResults.UpliftSituation;
desResult.IsUplift = uplift.IsUplift;
if (desResult.IsUplift.Value)
{
desResult.Pl3MinUplift = uplift.Pl3MinUplift;
desResult.Pl3HeadAdjusted = uplift.Pl3HeadAdjusted;
desResult.Pl3LocalLocationXMinUplift = uplift.Pl3LocationXMinUplift;
desResult.Pl4MinUplift = uplift.Pl4MinUplift;
desResult.Pl4HeadAdjusted = uplift.Pl4HeadAdjusted;
desResult.Pl4LocalLocationXMinUplift = uplift.Pl4LocationXMinUplift;
}
else
{
ResetUpliftValues(desResult);
}
}
private static void ResetUpliftValues(CsvExportData desResult)
{
desResult.Pl3MinUplift = null;
desResult.Pl3HeadAdjusted = null;
desResult.Pl3LocalLocationXMinUplift = null;
desResult.Pl4MinUplift = null;
desResult.Pl4HeadAdjusted = null;
desResult.Pl4LocalLocationXMinUplift = null;
}
}