// Copyright (C) Stichting Deltares 2017. 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;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Deltares.DamEngine.Calculators.Uplift;
using Deltares.DamEngine.Data.Design;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
using Deltares.DamEngine.Data.General.TimeSeries;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard.Calculation;
using Deltares.DamEngine.Data.Standard.Logging;
using Deltares.DamEngine.Calculators.General;
using Deltares.DamEngine.Calculators.PlLinesCreator;
using Deltares.DamEngine.Calculators.Stability;
using Deltares.DamEngine.Data.General.Results;
using Parallel = Deltares.DamEngine.Calculators.General.Parallel;
namespace Deltares.DamEngine.Calculators
{
public class DamProjectCalculator
{
private readonly DamProjectData damProjectData;
private readonly Object lockObject = new object();
private int maxCalculationCores = 255;
private string slopeWProgramPath = "";
private string mStabProgramPath = "";
private string calculationBaseDirectory = "";
///
/// Constructor
///
///
public DamProjectCalculator(DamProjectData damProjectData)
{
this.damProjectData = damProjectData;
}
///
/// Base directory where the project is stored
/// Needed to find the 2d geometries
///
public string ProjectDataDirectory { get; set; }
public ProgressDelegate Progress { get; set; }
///
/// Properties
///
public string CalculationBaseDirectory
{
get
{
return calculationBaseDirectory;
}
set
{
calculationBaseDirectory = value;
}
}
public string MStabProgramPath
{
get
{
return mStabProgramPath;
}
set
{
mStabProgramPath = value;
}
}
public string SlopeWProgramPath
{
get
{
return slopeWProgramPath;
}
set
{
slopeWProgramPath = value;
}
}
public int MaxCalculationCores
{
get
{
return maxCalculationCores;
}
set
{
maxCalculationCores = value;
}
}
///
/// Validate if all parameters are available for calculation of project
///
public void ValidateGeneral()
{
// ToDo make this intelligent depending on the specification
ThrowHelper.ThrowWhenConditionIsTrue("No actual calculation specified.",
() => damProjectData.DamProjectCalculationSpecification.DamCalculationSpecifications.Count == 0);
}
///
/// Validate if all parameters are available for calculation of project
///
public void ValidateSpecification()
{
// ToDo make this intelligent depending on the specification
if (damProjectData.ProgramType == ProgramType.MStab)
{
ThrowHelper.ThrowIfFileNotExist(MStabProgramPath, StringResourceNames.MStabExecutableFileNameNotFound);
}
if (damProjectData.ProgramType == ProgramType.SlopeW)
{
ThrowHelper.ThrowIfFileNotExist(SlopeWProgramPath, StringResourceNames.SlopeWExecutableFileNameNotFound);
}
}
///
/// Perform the calculations
///
public List> Calculate(DamProjectData damProjectData, IList scenarios)
{
foreach (var scenario in scenarios)
{
if (damProjectData.Dike.Locations.Contains(scenario.Location))
{
damProjectData.Dike.UpdateLocation(scenario.Location);
break;
}
}
ValidateGeneral();
Parallel.Run((IList) scenarios, RunScenario, Progress, MaxCalculationCores);
var allCalculationResults = scenarios.Select(scenario => scenario.CalculationResults).ToList();
PostprocessForStabilityUpliftVanBishop(ref allCalculationResults);
this.damProjectData.UpdateDesignCalculations();
return allCalculationResults;
}
///
/// Determine where lowest uplift factor occurs and the value of that factor
///
///
///
///
///
///
///
///
public double? GetLowestUpliftFactor(SurfaceLine2 surfaceLine, SoilProfile1D soilProfile, string soilGeometry2DName, PLLines plLines, Location location)
{
var upliftLocationDeterminator = new UpliftLocationDeterminator()
{
SurfaceLine = surfaceLine,
SoilProfile = soilProfile,
SoilGeometry2DName = soilGeometry2DName,
//SoilBaseDB = location.SoilbaseDB,
SoilList = location.SoilList,
DikeEmbankmentMaterial = location.GetDikeEmbankmentSoil(),
PLLines = plLines,
XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin
};
UpliftLocationAndResult upliftLocationAndResult = upliftLocationDeterminator.GetLocationAtWithLowestUpliftFactor();
if (upliftLocationAndResult != null)
{
return upliftLocationAndResult.UpliftFactor;
}
return null;
}
///
/// Determines whether it is a combined stability bishop and liftvan calculation.
///
/// The calculation specification.
///
/// true if it is a stability bishop and liftvan calculation; otherwise, false.
///
private bool IsStabilityBishopLiftVanCalculation(DamFailureMechanismeCalculationSpecification calculationSpecification)
{
return ((calculationSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside) &&
((MStabModelType) calculationSpecification.CalculationModel == MStabModelType.BishopUpliftVan));
}
///
/// Calculate one scenario
///
///
private void RunScenario(object scenarioTask)
{
var scenario = (DesignScenario) scenarioTask;
var scenarioName = scenario.Location.Name;
Debug.WriteLine(String.Format("Start thread for location '{0}'", scenarioName));
Location oldLocation = null;
try
{
oldLocation = scenario.Location;
var scenarioId = scenario.LocationScenarioID;
Debug.WriteLine("Location '{0}', scenario '{1}'", scenarioName, scenarioId);
scenario.ClearResults();
scenario.ClearErrors();
CloneLocationOnScenario(scenario);
if (scenario.PlLineOffsetBelowDikeToeAtPolder.HasValue)
{
scenario.Location.PlLineOffsetBelowDikeToeAtPolder = scenario.PlLineOffsetBelowDikeToeAtPolder.Value;
}
if (scenario.PlLineOffsetBelowDikeTopAtPolder.HasValue)
{
scenario.Location.PlLineOffsetBelowDikeTopAtPolder = scenario.PlLineOffsetBelowDikeTopAtPolder.Value;
}
if (scenario.PlLineOffsetBelowDikeTopAtRiver.HasValue)
{
scenario.Location.PlLineOffsetBelowDikeTopAtRiver = scenario.PlLineOffsetBelowDikeTopAtRiver.Value;
}
if (scenario.PlLineOffsetBelowShoulderBaseInside.HasValue)
{
scenario.Location.PlLineOffsetBelowShoulderBaseInside = scenario.PlLineOffsetBelowShoulderBaseInside.Value;
}
if (scenario.PlLineOffsetBelowDikeCrestMiddle.HasValue)
{
scenario.Location.PlLineOffsetBelowDikeCrestMiddle = scenario.PlLineOffsetBelowDikeCrestMiddle;
}
if (scenario.PlLineOffsetFactorBelowShoulderCrest.HasValue)
{
scenario.Location.PlLineOffsetFactorBelowShoulderCrest = scenario.PlLineOffsetFactorBelowShoulderCrest;
}
if (scenario.UsePlLineOffsetBelowDikeCrestMiddle.HasValue)
{
scenario.Location.UsePlLineOffsetBelowDikeCrestMiddle = scenario.UsePlLineOffsetBelowDikeCrestMiddle;
}
if (scenario.UsePlLineOffsetFactorBelowShoulderCrest.HasValue)
{
scenario.Location.UsePlLineOffsetFactorBelowShoulderCrest = scenario.UsePlLineOffsetFactorBelowShoulderCrest;
}
if (scenario.HeadPl3.HasValue)
{
scenario.Location.HeadPl3 = scenario.HeadPl3.Value;
}
if (scenario.HeadPl4.HasValue)
{
scenario.Location.HeadPl4 = scenario.HeadPl4.Value;
}
var selectedKernelType = StabilityKernelType.DamClassic;
var damProjectCalculationSpecification = damProjectData.DamProjectCalculationSpecification;
var spec = damProjectCalculationSpecification.DamCalculationSpecifications.First();
if (spec != null)
{
selectedKernelType = spec.StabilityKernelType;
}
if (DetermineStabilityUpliftForScenarios(scenario, selectedKernelType))
{
// Save the results after each calculation, because these will be deleted in the next calculation
var calculationresults = new List();
foreach (var calculationSpecification in damProjectCalculationSpecification.DamCalculationSpecifications)
{
var selectedProbabilisticType = damProjectCalculationSpecification.SelectedProbabilisticType;
var analysisType = DamProjectCalculationSpecification.SelectedAnalysisType;
Debug.WriteLine("Location '{0}', scenario '{1}' 10", scenarioName, scenarioId);
ValidateSpecification();
if (IsStabilityBishopLiftVanCalculation(calculationSpecification))
{
Debug.WriteLine("Location '{0}', scenario '{1}' 11", scenarioName, scenarioId);
CalculateStabilityBishopUpliftvanForScenario(scenario, calculationSpecification, selectedProbabilisticType, analysisType);
}
else
{
Debug.WriteLine("Location '{0}', scenario '{1}' 15", scenarioName, scenarioId);
CalculateOneCalculationTypeForScenario(scenario, calculationSpecification, selectedProbabilisticType, analysisType);
}
Debug.WriteLine("Location '{0}', scenario '{1}' 20", scenarioName, scenarioId);
calculationresults.AddRange(scenario.CalculationResults);
}
// Assign the combined results to the scenario
scenario.CalculationResults.Clear();
scenario.CalculationResults.AddRange(calculationresults);
}
}
catch (Exception exception)
{
scenario.Errors.Add(exception.Message);
}
finally
{
if( oldLocation != null)
{
scenario.Location = oldLocation;
}
}
}
private void CloneLocationOnScenario(DesignScenario scenario)
{
lock (lockObject)
{
// // TODO missing clone method for Location. This is a dirty way of performing a clone.
// var locationUsedInCalculation = new XmlSerializer().SerializeToString(scenario.Location);
// var location = new XmlDeserializer().XmlDeserializeFromString(locationUsedInCalculation);
// scenario.Location = location; ##Bka replace with object copier.
}
}
///
/// Calculates combined stability bishop and upliftvan for scenario.
///
/// The scenario.
/// The calculation specification.
/// Type of the probabilistic.
/// Type of the analysis.
private void CalculateStabilityBishopUpliftvanForScenario(DesignScenario scenario, DamFailureMechanismeCalculationSpecification calculationSpecification, ProbabilisticType probabilisticType, AnalysisType analysisType)
{
var bishopCalculationSpecification = new DamFailureMechanismeCalculationSpecification();
bishopCalculationSpecification.Assign(calculationSpecification);
bishopCalculationSpecification.CalculationModel = MStabModelType.Bishop;
var liftvanCalculationSpecification = new DamFailureMechanismeCalculationSpecification();
liftvanCalculationSpecification.Assign(calculationSpecification);
liftvanCalculationSpecification.CalculationModel = MStabModelType.UpliftVan;
// Make sure check on uplift is performed before doing UpliftVan calculation
liftvanCalculationSpecification.FailureMechanismeParamatersMStab.IsStabilityCheckOnUplift = true;
// First perform calculate Bishop
CalculateOneCalculationTypeForScenario(scenario, bishopCalculationSpecification, probabilisticType, analysisType);
// Save the results, because these will be deleted in the next calculation
var calculationresults = new List();
calculationresults.AddRange(scenario.CalculationResults);
// Now run LiftVan calculation
CalculateOneCalculationTypeForScenario(scenario, liftvanCalculationSpecification, probabilisticType, analysisType);
// Combine Bishop and Liftvan results and assign them to the scenario
calculationresults.AddRange(scenario.CalculationResults);
scenario.CalculationResults.Clear();
scenario.CalculationResults.AddRange(calculationresults);
}
///
/// Calculates one calculation type for scenario.
///
/// The scenario.
/// The dam failure mechanisme calculation specification.
/// Type of the probabilistic.
/// Type of the analysis.
private void CalculateOneCalculationTypeForScenario(
DesignScenario scenario,
DamFailureMechanismeCalculationSpecification damFailureMechanismeCalculationSpecification,
ProbabilisticType probabilisticType,
AnalysisType analysisType)
{
var dike = damProjectData.Dike;
var damProjectCalculatorLogBuilder = new DamProjectCalculatorCsvExportDataBuilder
(
dike,
scenario,
damFailureMechanismeCalculationSpecification,
analysisType,
probabilisticType
);
scenario.ClearResults();
scenario.ClearErrors();
var damFailureMechanismeCalculator = new DamFailureMechanismeCalculator(
damProjectData.ProgramType,
damFailureMechanismeCalculationSpecification,
MStabProgramPath,
SlopeWProgramPath,
dike.MapForSoilGeometries2D,
probabilisticType);
damFailureMechanismeCalculator.CalculationBaseDirectory = CalculationBaseDirectory;
if (analysisType == AnalysisType.AdaptNWO)
{
damFailureMechanismeCalculator.NonWaterRetainingObject = dike.NonWaterRetainingObjects[0];
}
if (damFailureMechanismeCalculationSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside ||
damFailureMechanismeCalculationSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityOutside)
{
StabilityCalculator.ModelSubDirectory = damFailureMechanismeCalculationSpecification.FailureMechanismeParamatersMStab.MStabParameters.Model.ToString();
}
try
{
damFailureMechanismeCalculator.Calculate(analysisType, scenario);
foreach (var error in scenario.Errors)
{
var logMessage = new LogMessage(LogMessageType.Error, null, error);
damFailureMechanismeCalculator.ErrorMessages.Add(logMessage);
}
foreach (var errorMessage in damFailureMechanismeCalculator.ErrorMessages)
{
//LogManager.Messages.Add(errorMessage);##Bka
}
var recordIndex = 0;
var firstNwoSoilProfileProbability = true;
var validSoilProfileProbabilities = DamFailureMechanismeCalculator.SelectProbabilitiesForFailureMechanism(
damFailureMechanismeCalculationSpecification.FailureMechanismSystemType, scenario.Location.Segment.SoilProfileProbabilities);
foreach (var soilProfileProbability in validSoilProfileProbabilities)
{
if (analysisType == AnalysisType.AdaptNWO)
{
if (firstNwoSoilProfileProbability)
{
// for NWO, only add results for every first soilProfileProbability as the others are already part of the nwo results.
foreach (var nwoResult in scenario.NwoResults)
{
var resultMessage = scenario.GetResultMessage(
nwoResult.SoilProfileProbability.SoilProfile,
nwoResult.SoilProfileProbability.SoilGeometry2DName);
// The error message can contain "," and ";" and should therefor be surrounded with double quotes, so it will be read correctly as a scv file
damProjectCalculatorLogBuilder.Append(
@"""",
++recordIndex,
" - ",
resultMessage,
" - ",
nwoResult.NwoId,
" - ",
nwoResult.LocationXrdStart,
" - ",
nwoResult.MStabResults.CalculationName,
@""""
);
scenario.CalculationResults.Add(damProjectCalculatorLogBuilder.Build(nwoResult.SoilProfileProbability, scenario.NwoResults.IndexOf(nwoResult)));
scenario.CalculationResult = CalculationResult.Succeeded;
}
foreach (var error in scenario.Errors)
{
damProjectCalculatorLogBuilder.Append(error);
scenario.CalculationResults.Add(damProjectCalculatorLogBuilder.Build(soilProfileProbability));
scenario.CalculationResult = CalculationResult.Succeeded;
}
firstNwoSoilProfileProbability = false;
}
else
{
if (scenario.CalculationResult != CalculationResult.NoRun)
{
// The error message can contain "," and ";" and should therefor be surrounded with double quotes, so it will be read correctly as a csv file
string resultMessage = scenario.GetResultMessage(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
damProjectCalculatorLogBuilder.Append(
@"""",
++recordIndex,
" - ",
resultMessage,
@""""
);
scenario.CalculationResults.Add(damProjectCalculatorLogBuilder.Build(soilProfileProbability));
}
scenario.CalculationResult = CalculationResult.Succeeded;
}
}
else
{
// The error message can contain "," and ";" and should therefor be surrounded with double quotes, so it will be read correctly as a scv file
var resultMessage = scenario.GetResultMessage(
soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName);
damProjectCalculatorLogBuilder.Append(
@"""",
++recordIndex,
" - ",
resultMessage,
@""""
);
scenario.CalculationResults.Add(damProjectCalculatorLogBuilder.Build(soilProfileProbability, damFailureMechanismeCalculationSpecification.StabilityKernelType));
scenario.CalculationResult = CalculationResult.Succeeded;
}
}
}
catch (Exception exception)
{
damProjectCalculatorLogBuilder.Append("Error: ", exception.Message);
var innerException = exception.InnerException;
while (innerException != null)
{
damProjectCalculatorLogBuilder.Append(": ", innerException.Message);
innerException = innerException.InnerException;
}
foreach (var error in scenario.Errors)
{
var logMessage = new LogMessage(LogMessageType.Error, null, error);
//LogManager.Messages.Add(logMessage);##Bka
}
foreach (var errorMessage in damFailureMechanismeCalculator.ErrorMessages)
{
// LogManager.Messages.Add(errorMessage);##Bka
}
foreach (var soilProfileProbability in scenario.Location.Segment.SoilProfileProbabilities)
{
if (soilProfileProbability.SegmentFailureMechanismType == null ||
soilProfileProbability.SegmentFailureMechanismType == damFailureMechanismeCalculationSpecification.FailureMechanismSystemType)
{
scenario.CalculationResults.Add(damProjectCalculatorLogBuilder.Build(soilProfileProbability));
scenario.CalculationResult = CalculationResult.UnexpectedError;
}
}
throw;
}
}
///
/// Determine for each scenario if uplift occurs
///
///
///
///
private bool DetermineStabilityUpliftForScenarios(DesignScenario scenario, StabilityKernelType stabilityKernelType)
{
if (stabilityKernelType == StabilityKernelType.AdvancedWti ||
stabilityKernelType == StabilityKernelType.AdvancedDotNet)
{
return true;
}
var res = true;
Dike dike = damProjectData.Dike;
double upliftCriterion = scenario.GetUpliftCriterionStability(scenario.Location.ModelFactors.UpliftCriterionStability);
foreach (var soilProfileProbability in scenario.Location.Segment.SoilProfileProbabilities)
{
if (soilProfileProbability.SegmentFailureMechanismType == FailureMechanismSystemType.StabilityInside ||
soilProfileProbability.SegmentFailureMechanismType == FailureMechanismSystemType.StabilityOutside ||
soilProfileProbability.SegmentFailureMechanismType == null)
{
try
{
SurfaceLine2 surfaceLineWithNewHeight = DamFailureMechanismeCalculator.RedesignSurfaceLineHeight(FailureMechanismSystemType.StabilityInside, scenario,
scenario.Location.LocalXZSurfaceLine2);
// for scenarios the uplift should be calculated with the redesigned height, else a problem may occur with the waterlevel above the dike
var upliftSituation = new UpliftSituation();
PLLines plLines = CreateAllPLLines(out upliftSituation, scenario.RiverLevel,
scenario.RiverLevelLow, scenario.Location, soilProfileProbability,
surfaceLineWithNewHeight);
if (plLines != null)
{
string fullSoilGeometry2DName = (soilProfileProbability.SoilGeometry2DName == null) ? null :
Path.Combine(ProjectDataDirectory, Path.Combine(dike.MapForSoilGeometries2D, soilProfileProbability.SoilGeometry2DName));
double? upliftFactor = GetLowestUpliftFactor(surfaceLineWithNewHeight,
soilProfileProbability.SoilProfile, fullSoilGeometry2DName, plLines, scenario.Location);
upliftSituation.IsUplift = (upliftFactor < upliftCriterion);
}
else
{
upliftSituation.IsUplift = false;
}
scenario.SetStabilityUpliftSituation(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, upliftSituation);
}
catch (Exception exception)
{
string errorMessage = String.Format("{0} in location '{1}' scenario '{2}' soilprofile '{3}'",
exception.Message, scenario.Location.Name,
scenario.LocationScenarioID,
soilProfileProbability.SoilGeometryName);
scenario.SetResultMessage(soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName, exception.Message);
var resultRecord = new DesignResult("Error: " + exception.Message,
damProjectData.DamProjectCalculationSpecification.DamCalculationSpecifications[0],
scenario,
soilProfileProbability.SoilProfile,
soilProfileProbability.SoilGeometry2DName,
DamProjectCalculationSpecification.SelectedAnalysisType,
0);
scenario.CalculationResults.Add(resultRecord);
scenario.Errors.Add(errorMessage);
scenario.CalculationResult = CalculationResult.RunFailed;
res = false;
}
}
}
foreach (var error in scenario.Errors)
{
var logMessage = new LogMessage(LogMessageType.Error, null, error);
//LogManager.Messages.Add(logMessage); ##Bka
}
return res;
}
///
/// Determines whether the specified calculation result is Bishop.
///
/// The calculation result.
///
/// true if it is Bishop; otherwise, false.
///
private bool IsBishopResult(DesignResult calculationResult)
{
return ((calculationResult.DamFailureMechanismeCalculation.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside) &&
(calculationResult.DamFailureMechanismeCalculation.FailureMechanismeParamatersMStab.MStabParameters.Model == MStabModelType.Bishop));
}
///
/// Determines whether the specified calculation result is UpliftVan.
///
/// The calculation result.
///
/// true if it is UpliftVan; otherwise, false.
///
private bool IsUpliftVanResult(DesignResult calculationResult)
{
return ((calculationResult.DamFailureMechanismeCalculation.FailureMechanismSystemType == FailureMechanismSystemType.StabilityInside) &&
(calculationResult.DamFailureMechanismeCalculation.FailureMechanismeParamatersMStab.MStabParameters.Model == MStabModelType.UpliftVan));
}
///
/// Create new results depending on Uplift
///
///
private void PostprocessForStabilityUpliftVanBishop(ref List> allCalculationResults)
{
var normativeCalculationResults = new List();
var bishopCalculationResults = new List();
var upliftVanCalculationResults = new List();
// First collect all Bishop and Uplift calculations
foreach (var calculationResults in allCalculationResults)
{
if (calculationResults.Count > 0)
{
foreach (var calculationResult in calculationResults)
{
if (IsBishopResult(calculationResult))
{
bishopCalculationResults.Add(calculationResult);
}
if (IsUpliftVanResult(calculationResult))
{
upliftVanCalculationResults.Add(calculationResult);
}
}
}
}
if ((bishopCalculationResults.Any()) && (upliftVanCalculationResults.Any()))
{
var bishopLiftvancalculation = bishopCalculationResults[0].DamFailureMechanismeCalculation.Clone();
bishopLiftvancalculation.FailureMechanismeParamatersMStab.MStabParameters.Model = MStabModelType.BishopUpliftVan;
foreach (var bishopCalculationRecord in bishopCalculationResults)
{
DesignResult liftVanCalculationResult = (from calculationResult in upliftVanCalculationResults
where calculationResult.LocationName.Equals(bishopCalculationRecord.LocationName) &&
calculationResult.ScenarioName.Equals(bishopCalculationRecord.ScenarioName) &&
calculationResult.ProfileName.Equals(bishopCalculationRecord.ProfileName)
select calculationResult).ToList().FirstOrDefault();
DesignResult normativeCalculationResult = SelectStabilityNormativeResult(bishopCalculationRecord, liftVanCalculationResult,
DamProjectCalculationSpecification.SelectedAnalysisType);
// Clone this result, to make sure the original won't be changed
normativeCalculationResult = (DesignResult) normativeCalculationResult.Clone();
normativeCalculationResult.DamFailureMechanismeCalculation = bishopLiftvancalculation;
normativeCalculationResults.Add(normativeCalculationResult);
// Add the normative result also to the scenario
normativeCalculationResult.Scenario.CalculationResults.Add(normativeCalculationResult);
}
allCalculationResults.Add(normativeCalculationResults);
}
}
///
/// Select which result is the norm for stability Bishop/UpliftVan calculation
///
///
///
///
private DesignResult SelectStabilityNormativeResult(DesignResult bishopCalculationRecord, DesignResult liftVanCalculationResult, AnalysisType analysisType)
{
switch (analysisType)
{
case AnalysisType.NoAdaption:
{
return SelectStabilityNormativeResultDeterministicNormal(liftVanCalculationResult, bishopCalculationRecord);
}
case AnalysisType.AdaptNWO:
case AnalysisType.AdaptGeometry:
{
return SelectStabilityNormativeResultDeterministicDesign(liftVanCalculationResult, bishopCalculationRecord);
}
default:
throw new ArgumentOutOfRangeException("analysisType");
}
}
///
/// Select which result is the norm for stability Bishop/UpliftVan normal deterministic calculation
///
///
///
///
private DesignResult SelectStabilityNormativeResultDeterministicNormal(DesignResult liftVanCalculationResult, DesignResult bishopCalculationRecord)
{
if ((liftVanCalculationResult != null) && (liftVanCalculationResult.SafetyFactor.HasValue))
{
if ((bishopCalculationRecord != null) && (bishopCalculationRecord.SafetyFactor.HasValue))
{
return (liftVanCalculationResult.SafetyFactor.Value < bishopCalculationRecord.SafetyFactor.Value
? liftVanCalculationResult
: bishopCalculationRecord);
}
else
{
return liftVanCalculationResult;
}
}
else
{
return bishopCalculationRecord;
}
}
///
/// Select which result is the norm for stability Bishop/UpliftVan design deterministic calculation
///
///
///
///
private DesignResult SelectStabilityNormativeResultDeterministicDesign(DesignResult liftVanCalculationResult, DesignResult bishopCalculationRecord)
{
if ((liftVanCalculationResult != null) && (liftVanCalculationResult.SafetyFactor.HasValue))
{
if ((bishopCalculationRecord != null) && (bishopCalculationRecord.SafetyFactor.HasValue))
{
bool dla = liftVanCalculationResult.DikeLength.HasValue;
dla = dla && bishopCalculationRecord.DikeLength.HasValue;
if (dla && (Math.Abs(liftVanCalculationResult.DikeLength.Value - bishopCalculationRecord.DikeLength.Value) < GeometryPoint.Precision))
{
return (liftVanCalculationResult.SafetyFactor <
bishopCalculationRecord.SafetyFactor
? liftVanCalculationResult
: bishopCalculationRecord);
}
else
{
return (liftVanCalculationResult.DikeLength > bishopCalculationRecord.DikeLength
? liftVanCalculationResult
: bishopCalculationRecord);
}
}
else
{
return liftVanCalculationResult;
}
}
else
{
return bishopCalculationRecord;
}
}
///
/// Create PLLines with selected model
///
///
///
///
///
///
/// the created pl lines
private PLLines CreateAllPLLines(out UpliftSituation upliftSituation, double waterLevel, double? waterLevelLow, Location location, SoilGeometryProbability soilProfileProbability, SurfaceLine2 surfaceLine)
{
switch (location.ModelParametersForPLLines.PLLineCreationMethod)
{
case PLLineCreationMethod.ExpertKnowledgeLinearInDike:
case PLLineCreationMethod.ExpertKnowledgeRRD:
case PLLineCreationMethod.GaugesWithFallbackToExpertKnowledgeRRD:
return CreateAllPLLinesExpertKnowledge(out upliftSituation, waterLevel, waterLevelLow, location, soilProfileProbability, surfaceLine);
default:
upliftSituation.Pl3HeadAdjusted = 0;
upliftSituation.Pl3LocationXMinUplift = 0;
upliftSituation.Pl3MinUplift = 0;
upliftSituation.Pl4HeadAdjusted = 0;
upliftSituation.Pl4LocationXMinUplift = 0;
upliftSituation.Pl4MinUplift = 0;
upliftSituation.IsUplift = false; // must be determined later on; just to avoid compiler error
return null;
}
}
///
/// Create PLLines with expert knowledge
///
///
///
///
///
///
/// the created pl lines
private PLLines CreateAllPLLinesExpertKnowledge(out UpliftSituation upliftSituation, double waterLevel,
double? waterLevelLow, Location location, SoilGeometryProbability soilProfileProbability,
SurfaceLine2 surfaceLine)
{
var plLinesCreator = new PLLinesCreator();
// Determine geometry type
SoilGeometryType soilGeometryType = soilProfileProbability.SoilGeometryType;
string mapForSoilGeometries2D = location.MapForSoilGeometries2D;
SoilProfile1D soilProfile = soilProfileProbability.SoilProfile;
string soilGeometry2DName = soilProfileProbability.SoilGeometry2DName;
if ((soilProfileProbability.SoilGeometry2DName != null) && (mapForSoilGeometries2D != null))
{
soilGeometry2DName = Path.Combine(mapForSoilGeometries2D, soilGeometry2DName);
soilGeometry2DName = Path.Combine(ProjectDataDirectory, soilGeometry2DName);
}
plLinesCreator.WaterLevelRiverHigh = waterLevel;
plLinesCreator.WaterLevelRiverLow = waterLevelLow;
plLinesCreator.IsUseLowWaterLevel = (damProjectData.DamProjectCalculationSpecification.CurrentSpecification.FailureMechanismSystemType == FailureMechanismSystemType.StabilityOutside);
plLinesCreator.SurfaceLine = surfaceLine;
plLinesCreator.WaterLevelPolder = location.PolderLevel;
plLinesCreator.HeadInPLLine2 = location.HeadPl2;
plLinesCreator.HeadInPLLine3 = location.HeadPl3;
plLinesCreator.HeadInPLLine4 = location.HeadPl4;
plLinesCreator.ModelParametersForPLLines = location.ModelParametersForPLLines;
plLinesCreator.SoilProfile = soilProfile;
plLinesCreator.SoilGeometry2DName = soilGeometry2DName;
plLinesCreator.SoilGeometryType = soilGeometryType;
plLinesCreator.GaugePLLines = location.GaugePLLines;
plLinesCreator.Gauges = location.Gauges;
plLinesCreator.GaugeMissVal = location.GaugeMissVal;
plLinesCreator.IsAdjustPL3AndPL4SoNoUpliftWillOccurEnabled = true; // for stability this must set to true
plLinesCreator.SoilList = location.SoilList;
plLinesCreator.DikeEmbankmentMaterial = location.SoilList.GetSoilByName(location.DikeEmbankmentMaterial);
plLinesCreator.PlLineOffsetBelowDikeTopAtRiver = location.PlLineOffsetBelowDikeTopAtRiver;
plLinesCreator.PlLineOffsetBelowDikeTopAtPolder = location.PlLineOffsetBelowDikeTopAtPolder;
plLinesCreator.PlLineOffsetBelowShoulderBaseInside = location.PlLineOffsetBelowShoulderBaseInside;
plLinesCreator.PlLineOffsetBelowDikeToeAtPolder = location.PlLineOffsetBelowDikeToeAtPolder;
plLinesCreator.PlLineOffsetBelowDikeCrestMiddle = location.PlLineOffsetBelowDikeCrestMiddle;
plLinesCreator.PlLineOffsetFactorBelowShoulderCrest = location.PlLineOffsetFactorBelowShoulderCrest;
plLinesCreator.UsePlLineOffsetBelowDikeCrestMiddle = location.UsePlLineOffsetBelowDikeCrestMiddle;
plLinesCreator.UsePlLineOffsetFactorBelowShoulderCrest = location.UsePlLineOffsetFactorBelowShoulderCrest;
plLinesCreator.XSoilGeometry2DOrigin = location.XSoilGeometry2DOrigin;
//PLLines plLines = plLinesCreator.CreateAllPLLines(location); ##Bka
upliftSituation.Pl3HeadAdjusted = plLinesCreator.Pl3HeadAdjusted;
upliftSituation.Pl3LocationXMinUplift = plLinesCreator.Pl3LocationXMinUplift;
upliftSituation.Pl3MinUplift = plLinesCreator.Pl3MinUplift;
upliftSituation.Pl4HeadAdjusted = plLinesCreator.Pl4HeadAdjusted;
upliftSituation.Pl4LocationXMinUplift = plLinesCreator.Pl4LocationXMinUplift;
upliftSituation.Pl4MinUplift = plLinesCreator.Pl4MinUplift;
upliftSituation.IsUplift = false; // must be determined later on; just to avoid compiler error
return null; //plLines; ##Bka
}
}
}