diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculator.cs index ff143c2..2dda3cf 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculator.cs @@ -60,7 +60,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking private void ProcessCalculations() { - datasLogic = new GetTupleInputDatasLogic(InputData.Primitives, InputData.ForceActions) + datasLogic = new GetTupleInputDatasLogic(InputData.Primitives, InputData.ForceActions, InputData.UserCrackInputData) { LimitState = limitState, LongTerm = longTerm, diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculatorUpdateStrategy.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculatorUpdateStrategy.cs index f50346e..72afe64 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculatorUpdateStrategy.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackCalculatorUpdateStrategy.cs @@ -10,7 +10,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { public class CrackCalculatorUpdateStrategy : IUpdateStrategy { - private CrackInputDataUpdateStrategy inputDataUpdateStrategy => new(); + private CrackInputDataUpdateStrategy crackInputDataUpdateStrategy => new(); public void Update(CrackCalculator targetObject, CrackCalculator sourceObject) { if (ReferenceEquals(targetObject, sourceObject)) { return; } @@ -18,7 +18,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking targetObject.Name = sourceObject.Name; targetObject.InputData ??= new(); - inputDataUpdateStrategy.Update(targetObject.InputData, sourceObject.InputData); + crackInputDataUpdateStrategy.Update(targetObject.InputData, sourceObject.InputData); } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackInputData.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackInputData.cs index 5283702..4105123 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackInputData.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackInputData.cs @@ -16,10 +16,20 @@ namespace StructureHelperLogics.NdmCalculations.Cracking public List Primitives { get; private set; } /// public List ForceActions { get; private set; } + public UserCrackInputData UserCrackInputData { get; private set; } public CrackInputData() { Primitives = new(); ForceActions = new(); + UserCrackInputData = new() + { + SetSofteningFactor = true, + SofteningFactor = 1d, + SetLengthBetweenCracks = true, + LengthBetweenCracks = 0.4d, + UltimateLongCrackWidth = 0.0003d, + UltimateShortCrackWidth = 0.0004d + }; } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackInputDataUpdateStrategy.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackInputDataUpdateStrategy.cs index 53af0f6..d018e8f 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackInputDataUpdateStrategy.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackInputDataUpdateStrategy.cs @@ -10,6 +10,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { public class CrackInputDataUpdateStrategy : IUpdateStrategy { + private UserCrackInputDataUpdateStrategy userCrackInputDataUpdateStrategy => new(); public void Update(CrackInputData targetObject, CrackInputData sourceObject) { if (ReferenceEquals(targetObject, sourceObject)) { return; } @@ -18,6 +19,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking targetObject.ForceActions.AddRange(sourceObject.ForceActions); targetObject.Primitives.Clear(); targetObject.Primitives.AddRange(sourceObject.Primitives); + + userCrackInputDataUpdateStrategy.Update(targetObject.UserCrackInputData, sourceObject.UserCrackInputData); } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthTupleResult.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthTupleResult.cs index 7928c9f..cfd5e91 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthTupleResult.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackWidthTupleResult.cs @@ -11,6 +11,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { public IForceTuple? ForceTuple { get; set; } public double CrackWidth { get; set; } + public double UltimateCrackWidth { get; set; } + public bool IsCrackLessThanUltimate => CrackWidth <= UltimateCrackWidth; public double RebarStrain { get; set; } public double ConcreteStrain { get; set; } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/CrackedLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/CrackedLogic.cs index 3a0a361..4124ca3 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/CrackedLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/CrackedLogic.cs @@ -29,7 +29,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking } public bool IsSectionCracked(double factor) { - sectionCrackedLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); + sectionCrackedLogic.TraceLogger ??= TraceLogger?.GetSimilarTraceLogger(50); var actualTuple = ForceTupleService.InterpolateTuples(EndTuple, StartTuple, factor); sectionCrackedLogic.Tuple = actualTuple; diff --git a/StructureHelperLogics/NdmCalculations/Cracking/Factories/CrackWidthLogicInputDataFactory.cs b/StructureHelperLogics/NdmCalculations/Cracking/Factories/CrackWidthLogicInputDataFactory.cs index 5496bc6..5ab2b8f 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/Factories/CrackWidthLogicInputDataFactory.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/Factories/CrackWidthLogicInputDataFactory.cs @@ -22,143 +22,41 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { internal class CrackWidthLogicInputDataFactory : ILogic { - private IStressLogic stressLogic => new StressLogic(); + private const double longTermFactor = 1.4d; + private const double shortTermFactor = 1d; + private ICrackSofteningLogic softeningLogic; - private const double minimumPsiSFactor = 0.2d; - private INdm concreteNdm; - private INdm rebarNdm; - private StrainTuple strainTupleActual; - private double rebarStrainActual; - private double concreteStrainActual; - private double rebarStressActual; + public double RebarStrain { get; set; } + public double ConcreteStrain { get; set;} public CalcTerms CalcTerm { get; set; } - public RebarPrimitive RebarPrimitive { get; set; } public RebarCrackInputData InputData { get; set; } public IShiftTraceLogger? TraceLogger { get; set; } + public CrackWidthLogicInputDataFactory(ICrackSofteningLogic softeningLogic) + { + this.softeningLogic = softeningLogic; + } + public ICrackWidthLogicInputData GetCrackWidthLogicInputData() { - GetNdms(); + CrackWidthLogicInputDataSP63 data = new(); if (CalcTerm == CalcTerms.LongTerm) { - data.TermFactor = 1.4d; + data.TermFactor = longTermFactor; } else { - data.TermFactor = 1d; + data.TermFactor = shortTermFactor; } - data.PsiSFactor = GetPsiSFactor(InputData.ForceTuple, InputData.NdmCollection); + data.PsiSFactor = softeningLogic.GetSofteningFactor(); data.StressStateFactor = 1.0d; data.BondFactor = 0.5d; data.Length = InputData.Length; - data.ConcreteStrain = concreteStrainActual; - data.RebarStrain = rebarStrainActual; + data.ConcreteStrain = ConcreteStrain; + data.RebarStrain = RebarStrain; return data; } - - private void GetNdms() - { - var options = new TriangulationOptions() - { - CalcTerm = CalcTerms.ShortTerm, - LimiteState = LimitStates.SLS, - }; - concreteNdm = RebarPrimitive.GetConcreteNdm(options); - concreteNdm.StressScale = 1d; - rebarNdm = RebarPrimitive.GetRebarNdm(options); - } - - private double GetPsiSFactor(ForceTuple forceTuple, IEnumerable ndms) - { - var crackResult = calculateCrackTuples(forceTuple, ndms); - strainTupleActual = CalcStrainMatrix(forceTuple, ndms); - rebarStrainActual = stressLogic.GetTotalStrain(TupleConverter.ConvertToLoaderStrainMatrix(strainTupleActual), rebarNdm); - TraceLogger?.AddMessage($"Actual strain of rebar EpsilonS = {rebarStrainActual}(dimensionless)"); - concreteStrainActual = concreteNdm.Prestrain; - //concreteStrainActual = stressLogic.GetTotalStrain(TupleConverter.ConvertToLoaderStrainMatrix(strainTupleActual), concreteNdm); - TraceLogger?.AddMessage($"Actual strain of concrete on the axis of rebar EpsilonC = {concreteStrainActual}(dimensionless"); - if (crackResult.IsValid == false) - { - string errorString = LoggerStrings.CalculationError + crackResult.Description; - TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); - throw new StructureHelperException(errorString); - } - if (crackResult.IsSectionCracked == false) - { - TraceLogger?.AddMessage($"Section is not cracked PsiS = {minimumPsiSFactor}"); - return minimumPsiSFactor; - } - if (crackResult.FactorOfCrackAppearance == 0d) - { - TraceLogger?.AddMessage($"Section is cracked in start force combination, PsiS = 1.0"); - return 1d; - } - var strainTupleInCacking = CalcStrainMatrix(crackResult.TupleOfCrackAppearance as ForceTuple, ndms); - var stressInCracking = stressLogic.GetStress(TupleConverter.ConvertToLoaderStrainMatrix(strainTupleInCacking), rebarNdm); - TraceLogger?.AddMessage($"Stress in rebar immediately after cracing Sigma,scrc = {stressInCracking}(Pa)"); - rebarStressActual = stressLogic.GetStress(TupleConverter.ConvertToLoaderStrainMatrix(strainTupleActual), rebarNdm); - TraceLogger?.AddMessage($"Actual stress in rebar Sigma,s = {rebarStressActual}(Pa)"); - var stressRatio = stressInCracking / rebarStressActual; - var logic = new ExpSofteningLogic() - { - ForceRatio = stressRatio, - PsiSMin = minimumPsiSFactor, - PowerFactor = 1d, - BettaFactor = 0.8d, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) - }; - double psiS = logic.GetSofteningFactor(); - TraceLogger?.AddMessage($"PsiS = {psiS}"); - return psiS; - } - - private CrackForceResult calculateCrackTuples(ForceTuple forceTuple, IEnumerable ndms) - { - var sectionCrackedLogic = new SectionCrackedLogic() - { - NdmCollection = ndms, - CheckedNdmCollection = new List() { concreteNdm }, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(100) - }; - var crackedLogis = new CrackedLogic(sectionCrackedLogic) - { - StartTuple = new ForceTuple(), - EndTuple = forceTuple, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(100) - }; - var calculator = new CrackForceCalculator(crackedLogis) - { - NdmCollection = ndms, - EndTuple = forceTuple, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(150) - }; - calculator.Run(); - return calculator.Result as CrackForceResult; - } - - private StrainTuple CalcStrainMatrix(ForceTuple forceTuple, IEnumerable ndms) - { - IForceTupleInputData inputData = new ForceTupleInputData() - { - NdmCollection = ndms, - Tuple = forceTuple - }; - IForceTupleCalculator calculator = new ForceTupleCalculator() - { - InputData = inputData, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) - }; - calculator.Run(); - var forceResult = calculator.Result as IForcesTupleResult; - if (forceResult.IsValid == false) - { - TraceLogger?.AddMessage(LoggerStrings.CalculationError + $": {forceResult.Description}", TraceLogStatuses.Error); - throw new StructureHelperException(ErrorStrings.CalculationError); - } - var strain = TupleConverter.ConvertToStrainTuple(forceResult.LoaderResults.StrainMatrix); - return strain; - } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/GetTupleInputDatasLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/GetTupleInputDatasLogic.cs index b49e534..c58881b 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/GetTupleInputDatasLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/GetTupleInputDatasLogic.cs @@ -22,11 +22,13 @@ namespace StructureHelperLogics.NdmCalculations.Cracking public LimitStates LimitState { get; set; } public CalcTerms LongTerm { get; set; } public CalcTerms ShortTerm { get; set; } + public UserCrackInputData UserCrackInputData { get; set; } - public GetTupleInputDatasLogic(List primitives, List forceActions) + public GetTupleInputDatasLogic(List primitives, List forceActions, UserCrackInputData userCrackInputData) { Primitives = primitives; ForceActions = forceActions; + UserCrackInputData = userCrackInputData; } public List GetTupleInputDatas() @@ -52,7 +54,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking IsValid = true, LongTermTuple = tuple.LongTuple, ShortTermTuple = tuple.ShortTuple, - NdmPrimitives = Primitives + NdmPrimitives = Primitives, + UserCrackInputData = UserCrackInputData }); } } @@ -64,7 +67,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { if (ForceActions is null) { - TraceLogger?.AddMessage("Force action is null", TraceLogStatuses.Error); + TraceLogger?.AddMessage("Force action list is null", TraceLogStatuses.Error); throw new StructureHelperException(ErrorStrings.DataIsInCorrect + $": {nameof(ForceActions)} is null"); } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/IGetTupleInputDatasLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/IGetTupleInputDatasLogic.cs index dd2dec1..26c8f93 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/IGetTupleInputDatasLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/IGetTupleInputDatasLogic.cs @@ -11,5 +11,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking CalcTerms LongTerm { get; set; } CalcTerms ShortTerm { get; set; } List GetTupleInputDatas(); + UserCrackInputData UserCrackInputData { get; set; } } } \ No newline at end of file diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ILengthBetweenCracksLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ILengthBetweenCracksLogic.cs index 4c92067..93fe5df 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ILengthBetweenCracksLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/ILengthBetweenCracksLogic.cs @@ -9,10 +9,23 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { + /// + /// Interface of logic of obtaining of length between cracks + /// public interface ILengthBetweenCracksLogic : ILogic { + /// + /// Full collection of ndm parts of cross-section + /// IEnumerable NdmCollection { get; set; } + /// + /// Strain matrix in cracked state + /// IStrainMatrix StrainMatrix { get; set; } + /// + /// Returns length between cracks + /// + /// Length betwenn cracks double GetLength(); } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ITensileConcreteAreaLogic.cs similarity index 91% rename from StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs rename to StructureHelperLogics/NdmCalculations/Cracking/ITensileConcreteAreaLogic.cs index fc422aa..02543c6 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ITensileAreaLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/ITensileConcreteAreaLogic.cs @@ -13,7 +13,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking /// /// Logic fo calculating of tensile area of RC crosssection /// - public interface ITensileAreaLogic : ILogic + public interface ITensileConcreteAreaLogic : ILogic { IEnumerable NdmCollection { get; set; } IStrainMatrix StrainMatrix { get; set; } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ITensionRebarAreaLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/ITensionRebarAreaLogic.cs new file mode 100644 index 0000000..b88bdbf --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/ITensionRebarAreaLogic.cs @@ -0,0 +1,28 @@ +using LoaderCalculator.Data.Matrix; +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Models.Forces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +//Copyright (c) 2023 Redikultsev Evgeny, Ekaterinburg, Russia +//All rights reserved. + + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + /// + /// Logic for obtaining of summary area in tension zone of cracked cross-section + /// + public interface ITensionRebarAreaLogic : ILogic + { + + IStrainMatrix StrainMatrix { get; set; } + IEnumerable Rebars { get; set; } + double GetTensionRebarArea(); + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs b/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs index c399c72..0fa026f 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/LengthBetweenCracksLogicSP63.cs @@ -13,6 +13,9 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { + /// + /// Logic for obtaining of length between cracks according to SP63.13330.2018 + /// public class LengthBetweenCracksLogicSP63 : ILengthBetweenCracksLogic { const double minDiameterFactor = 10d; @@ -21,50 +24,57 @@ namespace StructureHelperLogics.NdmCalculations.Cracking const double maxLength = 0.4d; private const double areaFactor = 0.5d; readonly IAverageDiameterLogic diameterLogic; - readonly ITensileAreaLogic tensileAreaLogic; - IStressLogic stressLogic; + readonly ITensileConcreteAreaLogic concreteAreaLogic; + ITensionRebarAreaLogic rebarAreaLogic; + + /// public IEnumerable NdmCollection { get; set; } + /// public IStrainMatrix StrainMatrix { get; set; } + /// public IShiftTraceLogger? TraceLogger { get; set; } - public LengthBetweenCracksLogicSP63(IAverageDiameterLogic diameterLogic, ITensileAreaLogic tensileAreaLogic) + public LengthBetweenCracksLogicSP63(IAverageDiameterLogic diameterLogic, ITensileConcreteAreaLogic concreteAreaLogic, ITensionRebarAreaLogic rebarAreaLogic) { this.diameterLogic = diameterLogic; - this.tensileAreaLogic = tensileAreaLogic; - stressLogic = new StressLogic(); + this.concreteAreaLogic = concreteAreaLogic; + this.rebarAreaLogic = rebarAreaLogic; } public LengthBetweenCracksLogicSP63() : this ( new EquivalentDiameterLogic(), - new TensileAreaLogicSP63()) + new TensileConcreteAreaLogicSP63(), + new TensionRebarAreaSimpleSumLogic()) { } + /// public double GetLength() { TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + IEnumerable rebars = GetRebars(); + double rebarArea = GetRebarArea(rebars); + double rebarDiameter = GetAverageDiameter(rebars); + double concreteArea = GetConcreteArea(); + double length = GetLengthBetweenCracks(rebarArea, rebarDiameter, concreteArea); + return length; + } + + private IEnumerable GetRebars() + { var rebars = NdmCollection - .Where(x => x is RebarNdm & stressLogic.GetTotalStrain(StrainMatrix, x) > 0d) + .Where(x => x is RebarNdm) .Select(x => x as RebarNdm); - if (! rebars.Any()) + if (!rebars.Any()) { string errorString = ErrorStrings.DataIsInCorrect + ": Collection of rebars does not contain any tensile rebars"; TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); throw new StructureHelperException(errorString); } - if (TraceLogger is not null) - { - TraceService.TraceNdmCollection(TraceLogger, rebars); - } - var rebarArea = rebars.Sum(x => x.Area * x.StressScale); - TraceLogger?.AddMessage($"Summary rebar area As = {rebarArea}"); - diameterLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); - diameterLogic.Rebars = rebars; - var rebarDiameter = diameterLogic.GetAverageDiameter(); - TraceLogger?.AddMessage($"Average rebar diameter ds = {rebarDiameter}"); - tensileAreaLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); - tensileAreaLogic.NdmCollection = NdmCollection; - tensileAreaLogic.StrainMatrix = StrainMatrix; - var concreteArea = tensileAreaLogic.GetTensileArea(); - TraceLogger?.AddMessage($"Concrete effective area Ac,eff = {concreteArea}(m^2)"); + + return rebars; + } + + private double GetLengthBetweenCracks(double rebarArea, double rebarDiameter, double concreteArea) + { var length = areaFactor * concreteArea / rebarArea * rebarDiameter; TraceLogger?.AddMessage($"Base length between cracks Lcrc = {areaFactor} * {concreteArea} / {rebarArea} * {rebarDiameter} = {length}(m)"); double minLengthByDiameter = minDiameterFactor * rebarDiameter; @@ -81,5 +91,34 @@ namespace StructureHelperLogics.NdmCalculations.Cracking TraceLogger?.AddMessage($"Finally Lcrc = {length}(m)"); return length; } + + private double GetConcreteArea() + { + concreteAreaLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); + concreteAreaLogic.NdmCollection = NdmCollection; + concreteAreaLogic.StrainMatrix = StrainMatrix; + var concreteArea = concreteAreaLogic.GetTensileArea(); + TraceLogger?.AddMessage($"Concrete effective area Ac,eff = {concreteArea}(m^2)"); + return concreteArea; + } + + private double GetAverageDiameter(IEnumerable rebars) + { + diameterLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); + diameterLogic.Rebars = rebars; + var rebarDiameter = diameterLogic.GetAverageDiameter(); + TraceLogger?.AddMessage($"Average rebar diameter ds = {rebarDiameter}"); + return rebarDiameter; + } + + private double GetRebarArea(IEnumerable rebars) + { + rebarAreaLogic.StrainMatrix = StrainMatrix; + rebarAreaLogic.Rebars = rebars; + rebarAreaLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); + var rebarArea = rebarAreaLogic.GetTensionRebarArea(); + TraceLogger?.AddMessage($"Summary rebar area As = {rebarArea}(m^2)"); + return rebarArea; + } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs index a116394..96d5f58 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculator.cs @@ -1,6 +1,8 @@ using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Infrastructures.Exceptions; using StructureHelperCommon.Models; using StructureHelperCommon.Models.Calculators; +using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Loggers; using StructureHelperLogics.NdmCalculations.Primitives; @@ -8,8 +10,11 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { public class RebarCrackCalculator : ICalculator { - ICrackWidthLogic crackWidthLogic = new CrackWidthLogicSP63(); - RebarCrackResult result; + private ICrackSofteningLogic crackSofteningLogic; + private ICrackWidthLogic crackWidthLogic = new CrackWidthLogicSP63(); + private RebarCrackResult result; + private RebarStressResult rebarStressResult; + public string Name { get; set; } public RebarCrackCalculatorInputData InputData { get; set; } public IResult Result => result; @@ -32,16 +37,36 @@ namespace StructureHelperLogics.NdmCalculations.Cracking crackWidthLogic.TraceLogger = TraceLogger?.GetSimilarTraceLogger(50); try { + GetSofteningLogic(InputData.LongRebarData); + rebarStressResult = GetRebarStressResult(InputData.LongRebarData); var dataAcrc1 = GetCrackWidthInputData(InputData.LongRebarData, CalcTerms.LongTerm); var dataAcrc2 = GetCrackWidthInputData(InputData.LongRebarData, CalcTerms.ShortTerm); - var dataAcrc3 = GetCrackWidthInputData(InputData.ShortRebarData, CalcTerms.ShortTerm); - - crackWidthLogic.InputData = dataAcrc1; + crackWidthLogic.InputData = dataAcrc1; var acrc1 = crackWidthLogic.GetCrackWidth(); - var longRebarResult = new CrackWidthTupleResult() { CrackWidth = acrc1, + UltimateCrackWidth = InputData.UserCrackInputData.UltimateLongCrackWidth, + RebarStrain = rebarStressResult.RebarStrain, + ConcreteStrain = rebarStressResult.ConcreteStrain + }; + + GetSofteningLogic(InputData.ShortRebarData); + rebarStressResult = GetRebarStressResult(InputData.ShortRebarData); + var dataAcrc3 = GetCrackWidthInputData(InputData.ShortRebarData, CalcTerms.ShortTerm); + + crackWidthLogic.InputData = dataAcrc2; + var acrc2 = crackWidthLogic.GetCrackWidth(); + crackWidthLogic.InputData = dataAcrc3; + var acrc3 = crackWidthLogic.GetCrackWidth(); + + double acrcShort = acrc1 - acrc2 + acrc3; + TraceLogger?.AddMessage($"Long crack width acrc = acrc,1 = {acrc1}(m)"); + TraceLogger?.AddMessage($"Short crack width acrc = acrc,1 - acrc,2 + acrc,3 = {acrc1} - {acrc2} + {acrc3} = {acrcShort}(m)"); + var shortRebarResult = new CrackWidthTupleResult() + { + CrackWidth = acrcShort, + UltimateCrackWidth = InputData.UserCrackInputData.UltimateShortCrackWidth }; result.LongTermResult = longRebarResult; } @@ -53,13 +78,35 @@ namespace StructureHelperLogics.NdmCalculations.Cracking result.RebarPrimitive = InputData.RebarPrimitive; } + private void GetSofteningLogic(RebarCrackInputData rebarData) + { + if (InputData.UserCrackInputData.SetSofteningFactor == true) + { + crackSofteningLogic = new StabSoftetingLogic(InputData.UserCrackInputData.SofteningFactor) + { + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + } + else + { + crackSofteningLogic = new RebarStressSofteningLogic() + { + RebarPrimitive = InputData.RebarPrimitive, + InputData = rebarData, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + } + } + private ICrackWidthLogicInputData GetCrackWidthInputData(RebarCrackInputData inputData, CalcTerms calcTerm) { - var factoryInputData = new CrackWidthLogicInputDataFactory() + + var factoryInputData = new CrackWidthLogicInputDataFactory(crackSofteningLogic) { CalcTerm = calcTerm, InputData = inputData, - RebarPrimitive = InputData.RebarPrimitive, + RebarStrain = rebarStressResult.RebarStrain, + ConcreteStrain = rebarStressResult.ConcreteStrain, TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) }; var crackWidthInputData = factoryInputData.GetCrackWidthLogicInputData(); @@ -70,5 +117,24 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { throw new NotImplementedException(); } + + private RebarStressResult GetRebarStressResult(RebarCrackInputData inputData) + { + var calculator = new RebarStressCalculator() + { + ForceTuple = inputData.ForceTuple, + NdmCollection = inputData.CrackedNdmCollection, + RebarPrimitive = InputData.RebarPrimitive + }; + calculator.Run(); + var result = calculator.Result as RebarStressResult; + if (result.IsValid == false) + { + string errorString = LoggerStrings.CalculationError + result.Description; + TraceLogger?.AddMessage($"Rebar name: {InputData.RebarPrimitive.Name}\n" + errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + return result; + } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculatorInputData.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculatorInputData.cs index 92e7a72..085847e 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculatorInputData.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackCalculatorInputData.cs @@ -23,5 +23,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking /// public RebarCrackInputData? ShortRebarData { get; set; } public RebarPrimitive RebarPrimitive { get; set; } + public UserCrackInputData UserCrackInputData { get; set; } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputData.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputData.cs index 8ed542f..a100c6f 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputData.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarCrackInputData.cs @@ -13,7 +13,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { public class RebarCrackInputData : IInputData { - public IEnumerable NdmCollection { get; set; } + public IEnumerable CrackableNdmCollection { get; set; } + public IEnumerable CrackedNdmCollection { get; set; } public ForceTuple ForceTuple { get; set; } public double Length { get; set; } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarStressCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarStressCalculator.cs new file mode 100644 index 0000000..49e88ae --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarStressCalculator.cs @@ -0,0 +1,103 @@ +using LoaderCalculator.Data.Ndms; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models.Forces; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models; +using StructureHelperCommon.Services.Forces; +using StructureHelperLogics.NdmCalculations.Analyses.ByForces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using LoaderCalculator.Logics; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperLogics.NdmCalculations.Triangulations; +using StructureHelperCommon.Models.Calculators; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class RebarStressCalculator : ICalculator + { + private IStressLogic stressLogic; + private Ndm concreteNdm; + private RebarNdm rebarNdm; + private RebarStressResult result; + + public ForceTuple ForceTuple { get; set; } + public IEnumerable NdmCollection { get; set; } + public RebarPrimitive RebarPrimitive { get; set; } + public string Name { get; set; } + + public IResult Result => result; + + public IShiftTraceLogger? TraceLogger { get; set; } + + public StrainTuple GetStrainTuple() + { + IForceTupleInputData inputData = new ForceTupleInputData() + { + NdmCollection = NdmCollection, + Tuple = ForceTuple + }; + IForceTupleCalculator calculator = new ForceTupleCalculator() + { + InputData = inputData, + //TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + calculator.Run(); + var forceResult = calculator.Result as IForcesTupleResult; + if (forceResult.IsValid == false) + { + //TraceLogger?.AddMessage(LoggerStrings.CalculationError + $": {forceResult.Description}", TraceLogStatuses.Error); + throw new StructureHelperException(ErrorStrings.CalculationError); + } + var strain = TupleConverter.ConvertToStrainTuple(forceResult.LoaderResults.StrainMatrix); + return strain; + } + public RebarStressCalculator(IStressLogic stressLogic) + { + this.stressLogic = stressLogic; + } + public RebarStressCalculator() : this(new StressLogic()) + { + + } + + + public void Run() + { + GetNdms(); + result = new RebarStressResult() + { + IsValid = true, + Description = string.Empty + }; + var strainTuple = GetStrainTuple(); + result.StrainTuple = strainTuple; + var strainMatrix = TupleConverter.ConvertToLoaderStrainMatrix(strainTuple); + result.RebarStrain = stressLogic.GetTotalStrain(strainMatrix, rebarNdm); + result.RebarStress = stressLogic.GetStress(strainMatrix, rebarNdm); + result.ConcreteStrain = concreteNdm.Prestrain; + } + + + private void GetNdms() + { + var options = new TriangulationOptions() + { + CalcTerm = CalcTerms.ShortTerm, + LimiteState = LimitStates.SLS, + }; + concreteNdm = RebarPrimitive.GetConcreteNdm(options); + concreteNdm.StressScale = 1d; + rebarNdm = RebarPrimitive.GetRebarNdm(options); + } + + public object Clone() + { + throw new NotImplementedException(); + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/RebarStressResult.cs b/StructureHelperLogics/NdmCalculations/Cracking/RebarStressResult.cs new file mode 100644 index 0000000..a6aaf44 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/RebarStressResult.cs @@ -0,0 +1,20 @@ +using StructureHelperCommon.Models.Calculators; +using StructureHelperCommon.Models.Forces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class RebarStressResult : IResult + { + public bool IsValid { get; set; } + public string? Description { get; set; } + public StrainTuple StrainTuple { get; set; } + public double RebarStress { get; set; } + public double RebarStrain { get; set; } + public double ConcreteStrain { get; set; } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ExpSofteningLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ExpSofteningLogic.cs similarity index 96% rename from StructureHelperLogics/NdmCalculations/Cracking/ExpSofteningLogic.cs rename to StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ExpSofteningLogic.cs index 65f2c63..22b42e0 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ExpSofteningLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ExpSofteningLogic.cs @@ -11,6 +11,9 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { + /// + /// Logic of calculating of factor of softening by power expression + /// public class ExpSofteningLogic : ICrackSofteningLogic { private double forceRatio; diff --git a/StructureHelperLogics/NdmCalculations/Cracking/ICrackSofteningLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ICrackSofteningLogic.cs similarity index 59% rename from StructureHelperLogics/NdmCalculations/Cracking/ICrackSofteningLogic.cs rename to StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ICrackSofteningLogic.cs index 2f0feaa..32016ae 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/ICrackSofteningLogic.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/ICrackSofteningLogic.cs @@ -7,8 +7,15 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { + /// + /// Logic of calculating of factor of softening in crack of RC structures + /// public interface ICrackSofteningLogic : ILogic { + /// + /// Returns softening factor + /// + /// double GetSofteningFactor(); } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/RebarStressSofteningLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/RebarStressSofteningLogic.cs new file mode 100644 index 0000000..b96e5c1 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/RebarStressSofteningLogic.cs @@ -0,0 +1,161 @@ +using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using StructureHelperCommon.Infrastructures.Enums; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Calculators; +using StructureHelperCommon.Models.Forces; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Services.Forces; +using StructureHelperLogics.NdmCalculations.Analyses.ByForces; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Triangulations; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class RebarStressSofteningLogic : ICrackSofteningLogic + { + private IStressLogic stressLogic; + private RebarStressResult afterCrackingRebarResult; + private RebarStressResult actualRebarResult; + + + private INdm concreteNdm; + private INdm rebarNdm; + + private double rebarStrainActual; + private double concreteStrainActual; + private double rebarStressActual; + + public double MinValueOfFactor { get; set; } = 0.2d; + public RebarPrimitive RebarPrimitive { get; set; } + public RebarCrackInputData InputData { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + + public double GetSofteningFactor() + { + GetNdms(); + return GetPsiSFactor(InputData.ForceTuple, InputData.CrackableNdmCollection, InputData.CrackedNdmCollection); + } + + private void GetNdms() + { + var options = new TriangulationOptions() + { + CalcTerm = CalcTerms.ShortTerm, + LimiteState = LimitStates.SLS, + }; + concreteNdm = RebarPrimitive.GetConcreteNdm(options); + concreteNdm.StressScale = 1d; + rebarNdm = RebarPrimitive.GetRebarNdm(options); + } + + private double GetPsiSFactor(ForceTuple forceTuple, IEnumerable crackableNndms, IEnumerable crackedNndms) + { + + var crackResult = calculateCrackTuples(forceTuple, crackableNndms); + if (crackResult.IsValid == false) + { + string errorString = LoggerStrings.CalculationError + crackResult.Description; + TraceLogger?.AddMessage($"Rebar name: {RebarPrimitive.Name}\n" + errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + + + actualRebarResult = GetRebarStressResult(forceTuple); + rebarStrainActual = actualRebarResult.RebarStrain; + rebarStressActual = actualRebarResult.RebarStress; + TraceLogger?.AddMessage($"Actual strain of rebar EpsilonS = {rebarStrainActual}(dimensionless)"); + concreteStrainActual = concreteNdm.Prestrain; + //concreteStrainActual = stressLogic.GetTotalStrain(TupleConverter.ConvertToLoaderStrainMatrix(strainTupleActual), concreteNdm); + TraceLogger?.AddMessage($"Actual strain of concrete on the axis of rebar EpsilonC = {concreteStrainActual}(dimensionless)"); + if (crackResult.IsSectionCracked == false) + { + TraceLogger?.AddMessage($"Section is not cracked PsiS = {MinValueOfFactor}"); + return MinValueOfFactor; + } + if (crackResult.FactorOfCrackAppearance == 0d) + { + TraceLogger?.AddMessage($"Section is cracked in start force combination, PsiS = 1.0"); + return 1d; + } + afterCrackingRebarResult = GetRebarStressResult(crackResult.TupleOfCrackAppearance as ForceTuple); + + var stressInCracking = afterCrackingRebarResult.RebarStress; + TraceLogger?.AddMessage($"Stress in rebar immediately after cracking Sigma,scrc = {stressInCracking}(Pa)"); + TraceLogger?.AddMessage($"Actual stress in rebar Sigma,s = {rebarStressActual}(Pa)"); + double psiS = GetExponentialSofteningFactor(stressInCracking); + TraceLogger?.AddMessage($"PsiS = {psiS}"); + //return 0.94d; + return psiS; + } + + private double GetExponentialSofteningFactor(double stressInCracking) + { + var stressRatio = stressInCracking / rebarStressActual; + var logic = new ExpSofteningLogic() + { + ForceRatio = stressRatio, + PsiSMin = MinValueOfFactor, + PowerFactor = 1d, + BettaFactor = 0.8d, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + }; + double psiS = logic.GetSofteningFactor(); + return psiS; + } + + private CrackForceResult calculateCrackTuples(ForceTuple forceTuple, IEnumerable ndms) + { + var sectionCrackedLogic = new SectionCrackedLogic() + { + NdmCollection = ndms, + CheckedNdmCollection = new List() { concreteNdm }, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(100) + }; + var crackedLogis = new CrackedLogic(sectionCrackedLogic) + { + StartTuple = new ForceTuple(), + EndTuple = forceTuple, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(100) + }; + var calculator = new CrackForceCalculator(crackedLogis) + { + NdmCollection = ndms, + EndTuple = forceTuple, + Accuracy = new Accuracy() + { + IterationAccuracy = 0.01d, + MaxIterationCount = 1000 + }, + TraceLogger = TraceLogger?.GetSimilarTraceLogger(150) + }; + calculator.Run(); + return calculator.Result as CrackForceResult; + } + + private RebarStressResult GetRebarStressResult(ForceTuple forceTuple) + { + var calculator = new RebarStressCalculator() + { + ForceTuple = forceTuple, + NdmCollection = InputData.CrackedNdmCollection, + RebarPrimitive = RebarPrimitive + }; + calculator.Run(); + var result = calculator.Result as RebarStressResult; + if (result.IsValid == false) + { + string errorString = LoggerStrings.CalculationError + result.Description; + TraceLogger?.AddMessage($"Rebar name: {RebarPrimitive.Name}\n" + errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + return result; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/StabSoftetingLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/StabSoftetingLogic.cs new file mode 100644 index 0000000..f4178a7 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/SofteningLogics/StabSoftetingLogic.cs @@ -0,0 +1,24 @@ +using StructureHelperCommon.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class StabSoftetingLogic : ICrackSofteningLogic + { + private double stabSofteningValue; + public IShiftTraceLogger? TraceLogger { get; set; } + public StabSoftetingLogic(double stabSofteningValue) + { + this.stabSofteningValue = stabSofteningValue; + } + public double GetSofteningFactor() + { + TraceLogger?.AddMessage($"Constant value of softening factor PsiS = {stabSofteningValue}"); + return stabSofteningValue; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs b/StructureHelperLogics/NdmCalculations/Cracking/TensileConcreteAreaLogicSP63.cs similarity index 97% rename from StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs rename to StructureHelperLogics/NdmCalculations/Cracking/TensileConcreteAreaLogicSP63.cs index bbeb239..8436f83 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TensileAreaLogicSP63.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TensileConcreteAreaLogicSP63.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; namespace StructureHelperLogics.NdmCalculations.Cracking { - public class TensileAreaLogicSP63 : ITensileAreaLogic + public class TensileConcreteAreaLogicSP63 : ITensileConcreteAreaLogic { const double maxConcreteFactor = 0.5d; const double minConcreteFactor = 0.1d; diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaByStrainLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaByStrainLogic.cs new file mode 100644 index 0000000..134c75d --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaByStrainLogic.cs @@ -0,0 +1,64 @@ +using LoaderCalculator.Data.Matrix; +using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models.Loggers; +using StructureHelperCommon.Models; +using StructureHelperLogics.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class TensionRebarAreaByStrainLogic : ITensionRebarAreaLogic + { + IStressLogic stressLogic; + public IStrainMatrix StrainMatrix { get; set; } + public IEnumerable Rebars { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + public TensionRebarAreaByStrainLogic(IStressLogic stressLogic) + { + this.stressLogic = stressLogic; + } + public TensionRebarAreaByStrainLogic() : this(new StressLogic()) + { + + } + public double GetTensionRebarArea() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage("Method of obtaining of summary area of rebars in tension based on areas which are proportional by maximum strain"); + var rebars = Rebars + .Where(x => stressLogic.GetTotalStrain(StrainMatrix, x) > 0d); + if (!rebars.Any()) + { + string errorString = ErrorStrings.DataIsInCorrect + ": Collection of rebars does not contain any tensile rebars"; + TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + var maxStrain = rebars + .Select(x => stressLogic.GetTotalStrain(StrainMatrix, x)) + .Max(); + TraceLogger?.AddMessage($"Maximum strain maxStrain = {maxStrain}"); + if (TraceLogger is not null) + { + TraceService.TraceNdmCollection(TraceLogger, rebars); + } + double sumArea = 0d; + foreach (var rebar in rebars) + { + double area = rebar.Area * rebar.StressScale; + double strain = stressLogic.GetTotalStrain(StrainMatrix, rebar); + TraceLogger?.AddMessage($"Rebar area = {area}(m^2)"); + TraceLogger?.AddMessage($"Rebar strain = {strain}"); + var reducedArea = area * strain / maxStrain; + TraceLogger?.AddMessage($"Reduced rebar area = area * strain / maxStrain = {area} * {strain} / {maxStrain} = {reducedArea}(m^2)"); + sumArea += reducedArea; + } + return sumArea; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaSimpleSumLogic.cs b/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaSimpleSumLogic.cs new file mode 100644 index 0000000..a9abe5b --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/TensionRebarAreaSimpleSumLogic.cs @@ -0,0 +1,50 @@ +using LoaderCalculator.Data.Matrix; +using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperCommon.Models.Loggers; +using StructureHelperLogics.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + public class TensionRebarAreaSimpleSumLogic : ITensionRebarAreaLogic + { + IStressLogic stressLogic; + public IStrainMatrix StrainMatrix { get; set; } + public IEnumerable Rebars { get; set; } + public IShiftTraceLogger? TraceLogger { get; set; } + public TensionRebarAreaSimpleSumLogic(IStressLogic stressLogic) + { + this.stressLogic = stressLogic; + } + public TensionRebarAreaSimpleSumLogic() : this(new StressLogic()) + { + + } + public double GetTensionRebarArea() + { + TraceLogger?.AddMessage(LoggerStrings.CalculatorType(this), TraceLogStatuses.Service); + TraceLogger?.AddMessage("Method of obtaining of summary area of rebars in tension based on ordinary summarizing of areas"); + var rebars = Rebars + .Where(x => stressLogic.GetTotalStrain(StrainMatrix, x) > 0d); + if (!rebars.Any()) + { + string errorString = ErrorStrings.DataIsInCorrect + ": Collection of rebars does not contain any tensile rebars"; + TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error); + throw new StructureHelperException(errorString); + } + if (TraceLogger is not null) + { + TraceService.TraceNdmCollection(TraceLogger, rebars); + } + var rebarArea = rebars.Sum(x => x.Area * x.StressScale); + return rebarArea; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs index dac8bc4..7590c30 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackCalculator.cs @@ -16,16 +16,14 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { private static readonly ILengthBetweenCracksLogic lengthLogic = new LengthBetweenCracksLogicSP63(); private TupleCrackResult result; - private IEnumerable ndmPrimitives; private ICrackedSectionTriangulationLogic triangulationLogic; private List? rebarPrimitives; - private IEnumerable defaultNdms; - private IEnumerable fulyCrackedNdms; + private IEnumerable crackableNdms; + private IEnumerable crackedNdms; private IEnumerable elasticNdms; private CrackForceResult crackForceResult; private StrainTuple longDefaultStrainTuple; private StrainTuple shortDefaultStrainTuple; - private ITriangulatePrimitiveLogic triangulateLogic; private double longLength; private double shortLength; @@ -69,13 +67,22 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { CheckInputData(); Triangulate(); - longDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, defaultNdms); - shortDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, defaultNdms); + longDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, crackableNdms); + shortDefaultStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, crackableNdms); var longElasticStrainTuple = CalcStrainMatrix(InputData.LongTermTuple as ForceTuple, elasticNdms); var shortElasticStrainTuple = CalcStrainMatrix(InputData.ShortTermTuple as ForceTuple, elasticNdms); if (result.IsValid == false) { return; } - longLength = GetLengthBetweenCracks(longElasticStrainTuple); - shortLength = GetLengthBetweenCracks(shortElasticStrainTuple); + if (InputData.UserCrackInputData.SetLengthBetweenCracks == true) + { + longLength = InputData.UserCrackInputData.LengthBetweenCracks; + shortLength = InputData.UserCrackInputData.LengthBetweenCracks; + TraceLogger?.AddMessage($"User value of length between cracks Lcrc = {longLength}"); + } + else + { + longLength = GetLengthBetweenCracks(longElasticStrainTuple); + shortLength = GetLengthBetweenCracks(shortElasticStrainTuple); + } CalcCrackForce(); foreach (var rebar in rebarPrimitives) { @@ -95,13 +102,15 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { var longRebarData = new RebarCrackInputData() { - NdmCollection = fulyCrackedNdms, + CrackableNdmCollection = crackableNdms, + CrackedNdmCollection = crackedNdms, ForceTuple = InputData.LongTermTuple as ForceTuple, Length = longLength }; var shortRebarData = new RebarCrackInputData() { - NdmCollection = fulyCrackedNdms, + CrackableNdmCollection = crackableNdms, + CrackedNdmCollection = crackedNdms, ForceTuple = InputData.ShortTermTuple as ForceTuple, Length = shortLength }; @@ -109,7 +118,8 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { RebarPrimitive = rebar, LongRebarData = longRebarData, - ShortRebarData = shortRebarData + ShortRebarData = shortRebarData, + UserCrackInputData = InputData.UserCrackInputData }; return rebarCalculatorData; } @@ -124,7 +134,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking IForceTupleCalculator calculator = new ForceTupleCalculator() { InputData = inputData, - TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + //TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) }; calculator.Run(); var forceResult = calculator.Result as IForcesTupleResult; @@ -152,11 +162,11 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { triangulationLogic = new CrackedSectionTriangulationLogic(InputData.NdmPrimitives) { - TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) + //TraceLogger = TraceLogger?.GetSimilarTraceLogger(50) }; rebarPrimitives = triangulationLogic.GetRebarPrimitives(); - defaultNdms = triangulationLogic.GetNdmCollection(); - fulyCrackedNdms = triangulationLogic.GetCrackedNdmCollection(); + crackableNdms = triangulationLogic.GetNdmCollection(); + crackedNdms = triangulationLogic.GetCrackedNdmCollection(); elasticNdms = triangulationLogic.GetElasticNdmCollection(); } @@ -164,7 +174,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking { var calculator = new CrackForceCalculator(); calculator.EndTuple = InputData.LongTermTuple; - calculator.NdmCollection = defaultNdms; + calculator.NdmCollection = crackableNdms; calculator.Run(); crackForceResult = calculator.Result as CrackForceResult; } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackInputData.cs b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackInputData.cs index 427618a..9e26612 100644 --- a/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackInputData.cs +++ b/StructureHelperLogics/NdmCalculations/Cracking/TupleCrackInputData.cs @@ -16,5 +16,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking public IForceTuple? LongTermTuple { get; set; } public IForceTuple? ShortTermTuple { get; set; } public List? NdmPrimitives {get;set;} + public UserCrackInputData UserCrackInputData { get; set; } } } diff --git a/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputData.cs b/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputData.cs new file mode 100644 index 0000000..7816977 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputData.cs @@ -0,0 +1,40 @@ +using StructureHelperCommon.Models.Calculators; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + /// + /// Settings for crack calculations assigned by user + /// + public class UserCrackInputData : IInputData + { + /// + /// Flag of assigning of user value of softening factor + /// + public bool SetSofteningFactor {get;set;} + /// + /// User value of softening factor, dimensionless + /// + public double SofteningFactor {get;set;} + /// + /// Flag of assigning of user value of length between cracks + /// + public bool SetLengthBetweenCracks {get;set;} + /// + /// Length between cracks, m + /// + public double LengthBetweenCracks {get;set;} + /// + /// Ultimate long-term crack width, m + /// + public double UltimateLongCrackWidth { get; set; } + /// + /// Ultimate short-term crack width, m + /// + public double UltimateShortCrackWidth { get; set; } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputDataUpdateStrategy.cs b/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputDataUpdateStrategy.cs new file mode 100644 index 0000000..910a6e8 --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Cracking/UserCrackInputDataUpdateStrategy.cs @@ -0,0 +1,24 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.NdmCalculations.Cracking +{ + internal class UserCrackInputDataUpdateStrategy : IUpdateStrategy + { + public void Update(UserCrackInputData targetObject, UserCrackInputData sourceObject) + { + if (ReferenceEquals(targetObject, sourceObject)) { return; } + CheckObject.CompareTypes(targetObject, sourceObject); + + targetObject.SetSofteningFactor = sourceObject.SetSofteningFactor; + targetObject.SofteningFactor = sourceObject.SofteningFactor; + targetObject.SetLengthBetweenCracks = sourceObject.SetLengthBetweenCracks; + targetObject.LengthBetweenCracks = sourceObject.LengthBetweenCracks; + } + } +} diff --git a/StructureHelperTests/UnitTests/Ndms/Cracks/TensionREbarAreaSumLogicTest.cs b/StructureHelperTests/UnitTests/Ndms/Cracks/TensionREbarAreaSumLogicTest.cs new file mode 100644 index 0000000..1ecb6ed --- /dev/null +++ b/StructureHelperTests/UnitTests/Ndms/Cracks/TensionREbarAreaSumLogicTest.cs @@ -0,0 +1,87 @@ +using LoaderCalculator.Data.Matrix; +using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using Moq; +using NUnit.Framework; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperLogics.NdmCalculations.Cracking; +namespace StructureHelperTests.UnitTests.Ndms.Cracks +{ + public class TensionRebarAreaSimpleSumLogicTests + { + [Test] + public void GetTensionRebarArea_ShouldReturnCorrectSumArea_WhenRebarsInTension() + { + // Arrange + var mockStressLogic = new Mock(); + var mockStrainMatrix = new Mock(); + var mockTraceLogger = new Mock(); + + var rebars = new List + { + new RebarNdm { Area = 1.0, StressScale = 1.0 }, + new RebarNdm { Area = 2.0, StressScale = 1.0 }, + new RebarNdm { Area = 3.0, StressScale = 1.0 } + }; + + // Setup the mock to return positive strains + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 1.0))) + .Returns(0.5); + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 2.0))) + .Returns(1.0); + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 3.0))) + .Returns(1.5); + + var logic = new TensionRebarAreaSimpleSumLogic(mockStressLogic.Object) + { + StrainMatrix = mockStrainMatrix.Object, + Rebars = rebars, + TraceLogger = mockTraceLogger.Object + }; + + // Act + var result = logic.GetTensionRebarArea(); + + // Assert + // Expected result calculation: + // rebarArea = 1.0 * 1.0 + 2.0 * 1.0 + 3.0 * 1.0 = 6.0 + Assert.AreEqual(6.0, result); + + } + + [Test] + public void GetTensionRebarArea_ShouldThrowException_WhenNoRebarsInTension() + { + // Arrange + var mockStressLogic = new Mock(); + var mockStrainMatrix = new Mock(); + var mockTraceLogger = new Mock(); + + var rebars = new List + { + new RebarNdm { Area = 1.0, StressScale = 1.0 } + }; + + // Setup the mock to return non-positive strain + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.IsAny())) + .Returns(0.0); + + var logic = new TensionRebarAreaSimpleSumLogic(mockStressLogic.Object) + { + StrainMatrix = mockStrainMatrix.Object, + Rebars = rebars, + TraceLogger = mockTraceLogger.Object + }; + + // Act & Assert + var ex = Assert.Throws(() => logic.GetTensionRebarArea()); + StringAssert.Contains("Collection of rebars does not contain any tensile rebars", ex.Message); + } + } +} + + + + + diff --git a/StructureHelperTests/UnitTests/Ndms/Cracks/TensionRebarAreaByStrainLogicTest.cs b/StructureHelperTests/UnitTests/Ndms/Cracks/TensionRebarAreaByStrainLogicTest.cs new file mode 100644 index 0000000..736ebf8 --- /dev/null +++ b/StructureHelperTests/UnitTests/Ndms/Cracks/TensionRebarAreaByStrainLogicTest.cs @@ -0,0 +1,91 @@ +using LoaderCalculator.Data.Matrix; +using LoaderCalculator.Data.Ndms; +using LoaderCalculator.Logics; +using Moq; +using NUnit.Framework; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Models; +using StructureHelperLogics.NdmCalculations.Cracking; +using System.Collections.Generic; +using System.Linq; + +namespace StructureHelperTests.UnitTests.Ndms.Cracks +{ + public class TensionRebarAreaByStrainLogicTests + { + [Test] + public void GetTensionRebarArea_ShouldReturnCorrectSumArea_WhenRebarsInTension() + { + // Arrange + var mockStressLogic = new Mock(); + var mockStrainMatrix = new Mock(); + var mockTraceLogger = new Mock(); + + var rebars = new List + { + new RebarNdm { Area = 1.0, StressScale = 1.0 }, + new RebarNdm { Area = 2.0, StressScale = 1.0 }, + new RebarNdm { Area = 3.0, StressScale = 1.0 } + }; + + // Setup the mock to return positive strains + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 1.0))) + .Returns(0.5); + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 2.0))) + .Returns(1.0); + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.Is(r => r.Area == 3.0))) + .Returns(1.5); + + var logic = new TensionRebarAreaByStrainLogic(mockStressLogic.Object) + { + StrainMatrix = mockStrainMatrix.Object, + Rebars = rebars, + TraceLogger = mockTraceLogger.Object + }; + + // Act + var result = logic.GetTensionRebarArea(); + + // Assert + // Expected result calculation: + // maxStrain = 1.5 + // reducedArea for rebar 1 = 1.0 * 0.5 / 1.5 = 0.333... + // reducedArea for rebar 2 = 2.0 * 1.0 / 1.5 = 1.333... + // reducedArea for rebar 3 = 3.0 * 1.5 / 1.5 = 3.0 + // sumArea = 0.333... + 1.333... + 3.0 = 4.666... + Assert.AreEqual(4.666666666666667, result, 9); + } + [Test] + public void GetTensionRebarArea_ShouldThrowException_WhenNoRebarsInTension() + { + // Arrange + var mockStressLogic = new Mock(); + var mockStrainMatrix = new Mock(); + var mockTraceLogger = new Mock(); + + var rebars = new List + { + new RebarNdm { Area = 1.0, StressScale = 1.0 } + }; + + // Setup the mock to return non-positive strain + mockStressLogic.Setup(s => s.GetTotalStrain(It.IsAny(), It.IsAny())) + .Returns(0.0); + + var logic = new TensionRebarAreaByStrainLogic(mockStressLogic.Object) + { + StrainMatrix = mockStrainMatrix.Object, + Rebars = rebars, + TraceLogger = mockTraceLogger.Object + }; + + // Act & Assert + var ex = Assert.Throws(() => logic.GetTensionRebarArea()); + StringAssert.Contains("Collection of rebars does not contain any tensile rebars", ex.Message); + + } + } +} + + +