From 8de8c00182c4a2e3b4ffa90f2c52ef37032739ec Mon Sep 17 00:00:00 2001 From: ear Date: Fri, 1 Dec 2023 20:07:26 +0500 Subject: [PATCH] Soil anchor was added --- .../Infrastructures/Exceptions/ErrorString.cs | 1 + .../Models/Calculators/IResult.cs | 2 +- .../Models/Soils/AnchorCalculator.cs | 114 ++++++++++++++ .../Models/Soils/AnchorResult.cs | 40 +++++ .../Models/Soils/AnchorSoilProperties.cs | 38 +++++ .../Models/Soils/IAnchorSoilProperties.cs | 46 ++++++ .../Models/Soils/SoilAnchor.cs | 148 ++++++++++++++++++ StructureHelperCommon/Services/CheckObject.cs | 8 + .../Calcuators/LimitCurveCalculatorTest.cs | 2 - .../Calcuators/SoilAnchorCalculatorTest.cs | 65 ++++++++ 10 files changed, 461 insertions(+), 3 deletions(-) create mode 100644 StructureHelperCommon/Models/Soils/AnchorCalculator.cs create mode 100644 StructureHelperCommon/Models/Soils/AnchorResult.cs create mode 100644 StructureHelperCommon/Models/Soils/AnchorSoilProperties.cs create mode 100644 StructureHelperCommon/Models/Soils/IAnchorSoilProperties.cs create mode 100644 StructureHelperCommon/Models/Soils/SoilAnchor.cs create mode 100644 StructureHelperTests/UnitTests/Calcuators/SoilAnchorCalculatorTest.cs diff --git a/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs b/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs index 6719810..bb50945 100644 --- a/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs +++ b/StructureHelperCommon/Infrastructures/Exceptions/ErrorString.cs @@ -23,5 +23,6 @@ public static string ErrorOfExuting => "#0017: Error of executing"; public static string ExpectedWas(System.Type expected, System.Type was) => $"{DataIsInCorrect}: Expected {expected}, but was {was}"; public static string ExpectedWas(System.Type expected, object obj) => ExpectedWas(expected, obj.GetType()); + public static string NullReference => "#0018: Null reference"; } } diff --git a/StructureHelperCommon/Models/Calculators/IResult.cs b/StructureHelperCommon/Models/Calculators/IResult.cs index 2f81734..76ba85d 100644 --- a/StructureHelperCommon/Models/Calculators/IResult.cs +++ b/StructureHelperCommon/Models/Calculators/IResult.cs @@ -12,6 +12,6 @@ namespace StructureHelperCommon.Models.Calculators /// True if result of calculation is valid /// bool IsValid { get; set; } - string Description { get; set; } + string? Description { get; set; } } } diff --git a/StructureHelperCommon/Models/Soils/AnchorCalculator.cs b/StructureHelperCommon/Models/Soils/AnchorCalculator.cs new file mode 100644 index 0000000..088cb3b --- /dev/null +++ b/StructureHelperCommon/Models/Soils/AnchorCalculator.cs @@ -0,0 +1,114 @@ +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models.Calculators; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Soils +{ + public class AnchorCalculator : ICalculator + { + private AnchorResult result; + + public string Name { get; set; } + + public IAnchorSoilProperties Soil { get; set; } + public SoilAnchor Anchor { get; set; } + + public IResult Result => result; + + public Action ActionToOutputResults { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public AnchorCalculator(SoilAnchor soilAnchor, IAnchorSoilProperties anchorSoilProperties) + { + Anchor = soilAnchor; + Soil = anchorSoilProperties; + } + + public object Clone() + { + throw new NotImplementedException(); + } + + public void Run() + { + const double ratioFactor = 1.01d; + + CheckParameters(); + + result = new() { IsValid = true }; + + var alpha = Math.PI / 180d * Anchor.AngleToHorizont; + var fi = Math.PI / 180d * Soil.FrictionAngle; + var sinFi = Math.Sin(fi); + + double ksi0 = GetKsi(); + + var hk = Anchor.GroundLevel - Anchor.HeadLevel; + hk += Anchor.FreeLength * Math.Sin(alpha); + result.AnchorCenterLevel = hk; + + var decrement = Math.Sqrt(Math.Pow(Math.Cos(alpha), 2) + Math.Pow(ksi0 * Math.Sin(alpha), 2)); + var sigma0g = 0.5d * (Soil.VolumetricWeight * hk + Anchor.AdditionalSurfPressure) * (ksi0 + decrement); + result.AverageSidePressure = sigma0g; + + var overA1 = (1 + Soil.PoissonRatio) * (sigma0g + Soil.Coheasion / Math.Tan(fi)) * sinFi; + var a1 = Soil.YoungsModulus / overA1; + + double kp = GetKp(ratioFactor, sinFi, a1); + + var charRak = Math.PI * Anchor.RootDiameter * Anchor.RootLength; + charRak *= 1 + sinFi; + charRak *= sigma0g * Math.Tan(fi) + Soil.Coheasion; + charRak *= kp * GetGammaC(); + + result.CharBearingCapacity = charRak; + result.DesignBearingCapacity = charRak / GetGammaN(); + + result.MortarVolumeFstStady = 0.5d * (Anchor.RootDiameter * Anchor.RootDiameter - Anchor.JetTubeDiameter * Anchor.JetTubeDiameter) * (1 + 3.1 * Anchor.WaterCementRatio) * Anchor.RootLength; + result.MortarVolumeSndStady = 0.5d * (Anchor.RootDiameter * Anchor.RootDiameter - Anchor.BoreHoleDiameter * Anchor.BoreHoleDiameter) * (1 + 3.1d * Anchor.WaterCementRatio) * Anchor.RootLength; + } + + private void CheckParameters() + { + if (Anchor.RootDiameter < Anchor.BoreHoleDiameter) + { + throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": Diameter of root {Anchor.RootDiameter}m must be greater than diameter of borehole {Anchor.BoreHoleDiameter}m"); + } + } + + private double GetKp(double ratioFactor, double sinFi, double a1) + { + var tetta = sinFi / (1 + sinFi); + var kp = ratioFactor - Math.Pow(Anchor.BoreHoleDiameter / Anchor.RootDiameter, 2); + kp /= ratioFactor - a1 * a1 / (1 + a1 * a1); + kp = Math.Pow(kp, tetta); + return kp; + } + + private double GetKsi() + { + if (Soil.SoilType == SoilType.SandAndSemiSand) { return 0.43d; } + else if (Soil.SoilType == SoilType.SemiClay) { return 0.55d; } + else if (Soil.SoilType == SoilType.Clay) { return 0.72d; } + else { throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknown); } + } + + private double GetGammaC() + { + if (Soil.SoilType == SoilType.SandAndSemiSand) { return 0.72d; } + else if (Soil.SoilType == SoilType.SemiClay) { return 0.64d; } + else if (Soil.SoilType == SoilType.Clay) { return 0.64; } + else { throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknown + $": {Soil.SoilType}"); } + } + + private double GetGammaN() + { + if (Anchor.DurabilityType == DurabilityType.Temporary) { return 1.2d; } + else if (Anchor.DurabilityType == DurabilityType.Eturnal) { return 1.4d; } + else { throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknown + $": {Anchor.DurabilityType}"); } + } + } +} diff --git a/StructureHelperCommon/Models/Soils/AnchorResult.cs b/StructureHelperCommon/Models/Soils/AnchorResult.cs new file mode 100644 index 0000000..5814d0b --- /dev/null +++ b/StructureHelperCommon/Models/Soils/AnchorResult.cs @@ -0,0 +1,40 @@ +using StructureHelperCommon.Models.Calculators; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Permissions; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Soils +{ + public class AnchorResult : IResult + { + /// + public bool IsValid { get; set; } + /// + public string? Description { get; set; } + /// + /// Characteristic Bearing Capacity, N + /// + public double CharBearingCapacity { get; set; } + /// + /// Design Bearing Capacity, N + /// + public double DesignBearingCapacity { get; set; } + /// + /// Average side pressure, Pa + /// + public double AverageSidePressure { get;set; } + /// + /// Volume of mortar of first stady, m^3 + /// + public double MortarVolumeFstStady { get; set; } + /// + /// Volume of mortar of second stady, m^3 + /// + public double MortarVolumeSndStady { get; set; } + public double AnchorCenterLevel { get; set; } + + } +} diff --git a/StructureHelperCommon/Models/Soils/AnchorSoilProperties.cs b/StructureHelperCommon/Models/Soils/AnchorSoilProperties.cs new file mode 100644 index 0000000..a7ae184 --- /dev/null +++ b/StructureHelperCommon/Models/Soils/AnchorSoilProperties.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Soils +{ + public class AnchorSoilProperties : IAnchorSoilProperties + { + public Guid Id { get;} + /// + public double YoungsModulus { get; set; } + /// + public double PoissonRatio { get; set; } + /// + public double VolumetricWeight { get; set; } + /// + public double FrictionAngle { get; set; } + /// + public double Coheasion { get; set; } + /// + public SoilType SoilType { get; set; } + + + public AnchorSoilProperties(Guid id) + { + Id = id; + YoungsModulus = 20e6d; //20MPa + PoissonRatio = 0.3d; + VolumetricWeight = 20e3d; //20kN/m^3 + FrictionAngle = 25d; + Coheasion = 30e3d; //30kPa + SoilType = SoilType.SandAndSemiSand; + } + public AnchorSoilProperties() : this(Guid.NewGuid()) { } + } +} diff --git a/StructureHelperCommon/Models/Soils/IAnchorSoilProperties.cs b/StructureHelperCommon/Models/Soils/IAnchorSoilProperties.cs new file mode 100644 index 0000000..c3c2b55 --- /dev/null +++ b/StructureHelperCommon/Models/Soils/IAnchorSoilProperties.cs @@ -0,0 +1,46 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Soils +{ + public enum SoilType + { + SandAndSemiSand, + SemiClay, + Clay + } + /// + /// Properties of soil for calculating of soil anchor + /// + public interface IAnchorSoilProperties : ISaveable + { + /// + /// Young's modulus, Pa + /// + double YoungsModulus { get; set; } + /// + /// Poison ratio + /// + double PoissonRatio { get; set; } + /// + /// Volumetric weight, N/m^3 + /// + double VolumetricWeight { get; set; } + /// + /// Angle of internal friction, degree + /// + double FrictionAngle { get; set; } + /// + /// Coheasion, Pa + /// + double Coheasion { get; set; } + /// + /// Type of Soil + /// + SoilType SoilType { get; set; } + } +} diff --git a/StructureHelperCommon/Models/Soils/SoilAnchor.cs b/StructureHelperCommon/Models/Soils/SoilAnchor.cs new file mode 100644 index 0000000..6d88ffb --- /dev/null +++ b/StructureHelperCommon/Models/Soils/SoilAnchor.cs @@ -0,0 +1,148 @@ +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Permissions; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Models.Soils +{ + public enum DurabilityType + { + Temporary, + Eturnal + } + public class SoilAnchor : ISaveable + { + private double rootLength; + private double rootDiameter; + private double freeLength; + private double jetTubeDiameter; + private double waterCementRatio; + private double boreHoleDiameter; + private double angleToHorizont; + private double additionalSurfPressure; + private double headLevel; + + /// + public Guid Id {get; private set;} + /// + /// Length of root, m + /// + public double RootLength + { + get => rootLength; set + { + CheckObject.CheckMinMax(value, 0d, 10d); + rootLength = value; + } + } + /// + /// Diameter of root, m + /// + public double RootDiameter + { + get => rootDiameter; set + { + CheckObject.CheckMinMax(value, 0d, 1d); + rootDiameter = value; + } + } + /// + /// + /// + public double GroundLevel { get; set; } + /// + /// Absolute level of head of anchor, m + /// + public double HeadLevel { get => headLevel; set => headLevel = value; } + /// + /// Free Length, m + /// + public double FreeLength + { + get => freeLength; set + { + CheckObject.CheckMinMax(value, 0d, 20d); + freeLength = value; + } + } + /// + /// Diameter of boregole, m + /// + public double BoreHoleDiameter + { + get => boreHoleDiameter; set + { + CheckObject.CheckMinMax(value, 0d, 1d); + boreHoleDiameter = value; + } + } + /// + /// Diameter of tube for jetting of mortar + /// + public double JetTubeDiameter + { + get => jetTubeDiameter; set + { + CheckObject.CheckMinMax(value, 0d, 0.1d); + jetTubeDiameter = value; + } + } + /// + /// Water-Cement ratio of jetting mortar + /// + public double WaterCementRatio + { + get => waterCementRatio; set + { + CheckObject.CheckMinMax(value, 0d, 3d); + waterCementRatio = value; + } + } + /// + /// Angle between horizontal plane and axis of anchor, degree + /// + public double AngleToHorizont + { + get => angleToHorizont; set + { + CheckObject.CheckMinMax(value, 0d, 60d); + angleToHorizont = value; + } + } + /// + /// Additional pressure on the surface of ground, Pa + /// + public double AdditionalSurfPressure + { + get => additionalSurfPressure; set + { + CheckObject.CheckMinMax(value, 0d, 2e4d); //20kPa + additionalSurfPressure = value; + } + } + public DurabilityType DurabilityType {get;set;} + + + public SoilAnchor(Guid id) + { + Id = id; + RootLength = 6; + HeadLevel = -4d; + FreeLength = 7d; + BoreHoleDiameter = 0.145d; + RootDiameter = boreHoleDiameter / 0.9d; + JetTubeDiameter = 0.025d; + WaterCementRatio = 0.45d; + AngleToHorizont = 15; + DurabilityType = DurabilityType.Temporary; + } + + public SoilAnchor() : this(Guid.NewGuid()) { } + + } +} diff --git a/StructureHelperCommon/Services/CheckObject.cs b/StructureHelperCommon/Services/CheckObject.cs index bd56adc..c81a017 100644 --- a/StructureHelperCommon/Services/CheckObject.cs +++ b/StructureHelperCommon/Services/CheckObject.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Forms; namespace StructureHelperCommon.Services { @@ -43,5 +44,12 @@ namespace StructureHelperCommon.Services throw new StructureHelperException($"{ErrorStrings.ExpectedWas(targetType, sourceObject.GetType())}"); } } + + public static void CheckMinMax (double value, double minValue, double maxValue) + { + if (value == null || minValue == null || maxValue == null) { throw new StructureHelperException(ErrorStrings.NullReference); } + if (value < minValue) { throw new StructureHelperException($"{ErrorStrings.IncorrectValue}: Value must be greater than {minValue}"); } + if (value > maxValue) { throw new StructureHelperException($"{ErrorStrings.IncorrectValue}: Value must be less than {maxValue}"); } + } } } diff --git a/StructureHelperTests/UnitTests/Calcuators/LimitCurveCalculatorTest.cs b/StructureHelperTests/UnitTests/Calcuators/LimitCurveCalculatorTest.cs index f832820..4349bbc 100644 --- a/StructureHelperTests/UnitTests/Calcuators/LimitCurveCalculatorTest.cs +++ b/StructureHelperTests/UnitTests/Calcuators/LimitCurveCalculatorTest.cs @@ -15,8 +15,6 @@ namespace StructureHelperTests.UnitTests.Calcuators //Arrange var calculator = new LimitCurveCalculator(new StabLimitCurveLogic()) { - XMax = xmax, - Ymax = ymax }; //Act calculator.Run(); diff --git a/StructureHelperTests/UnitTests/Calcuators/SoilAnchorCalculatorTest.cs b/StructureHelperTests/UnitTests/Calcuators/SoilAnchorCalculatorTest.cs new file mode 100644 index 0000000..eca8f6f --- /dev/null +++ b/StructureHelperTests/UnitTests/Calcuators/SoilAnchorCalculatorTest.cs @@ -0,0 +1,65 @@ +using NUnit.Framework; +using StructureHelperCommon.Models.Soils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperTests.UnitTests.Calcuators +{ + [TestFixture] + public class SoilAnchorCalculatorTest + { + [TestCase(6d, 0.483d, 7d, 0d, -2.188d, 25d, 30e3d, 2005767.1007324921d, 1671472.5839437435d)] + [TestCase(6d, 0.483d, 7d, 0d, -2.188d, 30d, 0d, 1437198.1109237692d, 1197665.0924364743d)] + public void Run_ShouldPass(double rootLength, double rootDiameter, double freeLength, double graundLevel, double headLevel, double fi, double c, double expectedCharBearingCapacity, double expectedDesignBearingCapacity) + { + //Arrange + var anchor = new SoilAnchor() + { + RootLength = rootLength, + RootDiameter = rootDiameter, + FreeLength = freeLength, + GroundLevel = graundLevel, + HeadLevel = headLevel, + }; + var soil = new AnchorSoilProperties() + { + FrictionAngle = fi, + Coheasion = c + }; + //Act + var calculator = new AnchorCalculator(anchor, soil); + calculator.Run(); + var result = calculator.Result as AnchorResult; + //Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedCharBearingCapacity, result.CharBearingCapacity, expectedCharBearingCapacity * 1e-6d); + Assert.AreEqual(expectedDesignBearingCapacity, result.DesignBearingCapacity, expectedDesignBearingCapacity * 1e-6d); + } + + [TestCase(6d, 0.2d, 7d, 0.145d, 0.28290937500000002d, 0.13633537500000006d)] + [TestCase(6d, 0.483, 7d, 0.145d, 1.6716908400000001d, 1.5251168399999999d)] + public void Run_ShouldPass_Volume(double rootLength, double rootDiameter, double freeLength, double boreHoleDiameter, double expectedVolume1, double expectedVolume2) + { + //Arrange + var anchor = new SoilAnchor() + { + RootLength = rootLength, + RootDiameter = rootDiameter, + FreeLength = freeLength, + BoreHoleDiameter = boreHoleDiameter, + }; + var soil = new AnchorSoilProperties(); + //Act + var calculator = new AnchorCalculator(anchor, soil); + calculator.Run(); + var result = calculator.Result as AnchorResult; + //Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedVolume1, result.MortarVolumeFstStady, expectedVolume1 * 1e-6d); + Assert.AreEqual(expectedVolume2, result.MortarVolumeSndStady, expectedVolume2 * 1e-6d); + } + } +}