using System;
using Deltares.Geotechnics;
using Deltares.Geotechnics.Soils;
using Deltares.Standard;
using Deltares.Standard.Logging;
namespace Deltares.Stability.Calculation2
{
public class BishopCalculation : SlidingCurveCalculation
{
public ModelOptions ModelOption { get; set; }
public override void CreateSlices(SlidingCurve slidingCurve)
{
var sliceCreatorCreator = new SlicesCreator();
sliceCreatorCreator.ChangingPoints = PreProcessCalculation.ChangingPoints;
sliceCreatorCreator.SetSoilProfile2D(PreProcessCalculation.Profile2D);
sliceCreatorCreator.SetWaternet(PreProcessCalculation.Waternet);
sliceCreatorCreator.SetSurfaceLine(PreProcessCalculation.SurfaceLine);
sliceCreatorCreator.StriveWidth = slidingCurve.MaximumSliceWidth;
sliceCreatorCreator.CreateBishopSlices((SlidingCircle) slidingCurve);
}
public override void FillSlices(SlidingCurve slidingCurve)
{
var fillSlicesFiller = new SlicesFiller();
fillSlicesFiller.PreProces = PreProcessCalculation;
for (int i = 0; i < slidingCurve.Slices.Count; i++)
{
fillSlicesFiller.FillSlicesByInterpolation(slidingCurve.Slices[i], 0.0);
}
}
public override double GetSafetyFactor(SlidingCurve slidingCurve)
{
if (slidingCurve is SlidingCircle)
{
var slidingCircle = (SlidingCircle) slidingCurve;
return CalculateStabilityFactor(slidingCircle); // to be implemented
}
else
{
throw new ArgumentException("Sliding curve should be circle");
}
}
///
/// Determines the soil moment due to weight of the soil
///
///
private double DetermineDrivingSoilMoment(SlidingCircle slidingCircle)
{
double moment = 0;
for (int i = 0; i < slidingCircle.Slices.Count; i++)
{
double HorDistance = slidingCircle.Slices[i].XCenter - slidingCircle.Center.X;
// Bereken aandrijvend moment : dx * lamel gewicht
moment = moment - HorDistance*slidingCircle.Slices[i].Weight;
}
return moment;
}
private double DetermineWaterMoment(SlidingCircle slidingCircle)
{
double moment = 0;
for (int i = 0; i < slidingCircle.Slices.Count; i++)
{
// Calculate watermoment due to waterforces on slidingCurve.Slices
if ((Math.Abs(slidingCircle.Slices[i].VPoreOnSurface - 0.0) > 0.001) || (Math.Abs(slidingCircle.Slices[i].HPoreOnSurface - 0.0) > 0.001))
{
double horDistance = slidingCircle.Slices[i].XCenter - slidingCircle.Center.X;
double vertDistance = slidingCircle.Center.Y - slidingCircle.Slices[i].ZCenterTop;
moment = moment + horDistance*slidingCircle.Slices[i].VPoreOnSurface + vertDistance*slidingCircle.Slices[i].HPoreOnSurface;
}
}
var circle = new Circle()
{
XleftSide = slidingCircle.LeftPoint.X,
XrightSide = slidingCircle.RightPoint.X,
Xcentre = slidingCircle.Center.X,
Zcentre = slidingCircle.Center.Y,
Radius = slidingCircle.Radius
};
moment = moment + WaterMomentOnVerticals(circle);
return moment;
}
private double BishopMethode(SlidingCircle slidingCircle)
{
double result;
const double Pir = Math.PI/180.0;
int i;
double Fn;
double Fo;
bool Ready;
double Salfa;
double TgPhi;
// double LSinPhi;
// double LCosPhi;
// double LCosDilet;
// double LSinDilet;
double LTau;
double Coh;
double alfa;
double h;
double tgalfa;
//double LCohTerm;
//double LSigTerm;
int numberOfIterations = 0;
// Initialisatie
slidingCircle.ResistingMoment = 0.0;
Fn = StartValueSafetyfactor;
Ready = false;
slidingCircle.DrivingMoment = slidingCircle.WaterMoment + slidingCircle.SoilMoment + slidingCircle.LoadMoment;
// Controleer aandrijvend moment op 1 kNm
if (Math.Abs(slidingCircle.DrivingMoment) < 0.001)
{
Ready = true;
}
// Start iteratie
if (Ready == false)
{
do
{
numberOfIterations++;
Fo = Fn;
slidingCircle.ResistingMoment = 0.0;
for (i = 0; i < slidingCircle.Slices.Count; i++)
{
Slice slice = slidingCircle.Slices[i];
Coh = slice.Cohesion;
// cohesie
// LSinPhi = Math.Sin(slice.Phi * Pir);
// LCosPhi = System.Math.Cos(slice.Phi * Pir);
// LCosDilet = Math.Cos(slice.Dilatancy * Pir);
//LSinDilet = Math.Sin(slice.Dilatancy * Pir);
TgPhi = Math.Tan(slice.Phi*Pir);
// formula based on Tau-alfa =
// 1/Fo * (coh * cotgphi + Salfa')* cospsi*sinphi/(1 - sinphi*sinpsi)
// (after tuenissen))
// note that if psi = phi then tau = coh + salfa * tgphi
// LSigTerm = LCosDilet * LSinPhi / (1 - LSinDilet * LSinPhi);
// LCohTerm = LCosDilet * LCosPhi / (1 - LSinDilet * LSinPhi);
// Tau-alfa = Coh*LCohTerm + Salfa'*LSigTerm
alfa = slice.BottomAngle;
// Hoek onderkant lamel [rad]
if (slidingCircle.DrivingMoment > 0.0)
{
alfa = -alfa;
// Passieve alfa nagatief maken
}
// Afsnuiten indien nodig
h = 0.5*Math.Atan(TgPhi/Fo) - 0.25*Math.PI;
if (alfa <= h)
{
alfa = h;
}
tgalfa = Math.Tan(alfa);
// Bereken het tegen werkend moment
// LTau = Coh * LCohTerm + slice.EffectiveStress * LSigTerm;
LTau = Coh + slice.EffectiveStress*TgPhi;
slidingCircle.ResistingMoment = slidingCircle.ResistingMoment + slice.ArcLength*LTau/(1 + tgalfa*TgPhi/Fo);
// Bereken het tegen werkend moment
// FResistingMom := FResistingMom + ArcLength * (coh + EffectiveStress * tgphi) /
// (1 + tgalfa * tgphi / Fo);
// Vertikaal Evenwicht : Sigma-v' = Salfa' + Tau-alfa*Tgalfa
// en Tau volgens Bishop : Tau-alfa = 1/Fo * (Coh*LCohTerm + Salfa'*LSigTerm
// Uit deze twee vergelijkingen kan Salfa opgelost worden :
Salfa = (Fo*slice.EffectiveStress - Coh*tgalfa)/(Fo + TgPhi*tgalfa);
// Salfa := (Fo * EffectiveStress - LLocCoh * tgalfa) / (Fo + tgalfa * tgphi);
// Nieuwe Tau - alfa
slice.NormalStress = Salfa;
slice.ShearStress = (Coh + Salfa*TgPhi)/Fo;
}
slidingCircle.ResistingMoment = slidingCircle.ResistingMoment*slidingCircle.Radius;
Fn = slidingCircle.ResistingMoment/Math.Abs(slidingCircle.DrivingMoment);
// Sla ongeitereerd moment, dus bij 1e iteratie op, om te kunnen uitvoeren
if (numberOfIterations == 1)
{
slidingCircle.ResistingMomentUniterated = slidingCircle.ResistingMoment;
}
// Stoppen als veiligheidscoefficient oud en nieuw ongeveer gelijk zijn
if (Math.Abs(Fn - Fo) < 0.001)
{
Ready = true;
}
// Teveel iteratie dan stoppen
if (numberOfIterations > Constants.CMaxIter)
{
Ready = true;
}
// Als tegenwerkend moment = 0, dan ook stoppen.
if ((Math.Abs(slidingCircle.ResistingMoment) < 0.001) || (Fn < 0.001))
{
Ready = true;
}
} while (!(Ready));
}
result = Fn;
if (Math.Abs(slidingCircle.DrivingMoment) < 0.001)
{
result = 1001;
LogManager.Add(new LogMessage(LogMessageType.Warning, this, "Driving moment too small"));
}
else if (numberOfIterations >= Constants.CMaxIter)
{
result = 1001;
LogManager.Add(new LogMessage(LogMessageType.Warning, this, "More than max " + Constants.CMaxIter + " iterations"));
}
else if (Math.Abs(slidingCircle.ResistingMoment) < 0.001 || Fn < 0.001)
{
result = 1001;
LogManager.Add(new LogMessage(LogMessageType.Warning, this, "Resisting moment too small"));
}
return result;
}
///
/// Calculates the stability calculation for Bishop method
///
///
private double CalculateStabilityFactor(SlidingCircle slidingCircle)
{
slidingCircle.SoilMoment = DetermineDrivingSoilMoment(slidingCircle);
if (PreProcessCalculation.Waternet.PhreaticLine != null)
{
slidingCircle.WaterMoment = DetermineWaterMoment(slidingCircle);
}
slidingCircle.LoadMoment = 0;
foreach (var uniformLoad in PreProcessCalculation.UniformLoads)
{
slidingCircle.LoadMoment += uniformLoad.GetMomentRoundX(slidingCircle.Center.X,
slidingCircle.LeftPoint.X,
slidingCircle.RightPoint.X);
}
//
// Nu aandrijvende momenten en lamel grootheden bekend zijn,
// kunnen de tegenwerkende momenten en de stabiliteits factor bepaald worden
//
slidingCircle.SafetyFactor = BishopMethode(slidingCircle);
return slidingCircle.SafetyFactor;
}
}
}