Obtaining softening factors was added

This commit is contained in:
Evgeny Redikultsev
2023-07-22 19:03:18 +05:00
parent d7a4b1f0a7
commit 580087b2a6
26 changed files with 546 additions and 196 deletions

View File

@@ -41,6 +41,7 @@
<StackPanel Grid.Column="1"> <StackPanel Grid.Column="1">
<Button Margin="3" Content="Graphic" ToolTip="Show graphic results" Command="{Binding ShowIsoFieldCommand}"/> <Button Margin="3" Content="Graphic" ToolTip="Show graphic results" Command="{Binding ShowIsoFieldCommand}"/>
<Button Margin="3" Content="Diagrams" ToolTip="Show diagrams" Command="{Binding ShowGraphsCommand}"/> <Button Margin="3" Content="Diagrams" ToolTip="Show diagrams" Command="{Binding ShowGraphsCommand}"/>
<Button Margin="3" Content="CrcDiagrams" ToolTip="Show diagrams for cracked section" Command="{Binding ShowCrackGraphsCommand}"/>
<Button Margin="3" Content="Interpolate" ToolTip="Create analysis by substep" Command="{Binding InterpolateCommand}"/> <Button Margin="3" Content="Interpolate" ToolTip="Create analysis by substep" Command="{Binding InterpolateCommand}"/>
<Button Margin="3" Content="Export" ToolTip="Export results to *.csv" Command="{Binding ExportToCSVCommand}"/> <Button Margin="3" Content="Export" ToolTip="Export results to *.csv" Command="{Binding ExportToCSVCommand}"/>
<Button Margin="3" Content="Set Prestrain" ToolTip="Set strains as auto prestrain" Command="{Binding SetPrestrainCommand}"/> <Button Margin="3" Content="Set Prestrain" ToolTip="Set strains as auto prestrain" Command="{Binding SetPrestrainCommand}"/>

View File

@@ -1,7 +1,9 @@
using StructureHelper.Windows.ViewModels.Graphs; using StructureHelper.Windows.ViewModels.Graphs;
using StructureHelperCommon.Models.Parameters;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@@ -27,5 +29,8 @@ namespace StructureHelper.Windows.Graphs
InitializeComponent(); InitializeComponent();
DataContext = vm; DataContext = vm;
} }
public GraphView(ArrayParameter<double> arrayParameter) : this(new GraphViewModel(arrayParameter))
{
}
} }
} }

View File

@@ -0,0 +1,43 @@
using StructureHelper.Windows.CalculationWindows.CalculatorsViews.ForceCalculatorViews;
using StructureHelper.Windows.Forces;
using StructureHelper.Windows.ViewModels.Forces;
using StructureHelperCommon.Models.Forces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.Services.NdmCalculations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
{
internal class InterpolateLogic
{
public void Show(IDesignForceTuple finishDesignTuple, IForceCalculator forceCalculator)
{
IDesignForceTuple startDesignTuple;
var viewModel = new InterpolateTuplesViewModel(finishDesignTuple, null, 100);
var wndTuples = new InterpolateTuplesView(viewModel);
wndTuples.ShowDialog();
if (wndTuples.DialogResult != true) return;
startDesignTuple = viewModel.StartDesignForce;
finishDesignTuple = viewModel.FinishDesignForce;
int stepCount = viewModel.StepCount;
var calculator = InterpolateService.InterpolateForceCalculator(forceCalculator, finishDesignTuple, startDesignTuple, stepCount);
calculator.Run();
var result = calculator.Result;
if (result is null || result.IsValid == false)
{
MessageBox.Show(result.Description, "Check data for analisys", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
var vm = new ForcesResultsViewModel(calculator);
var wnd = new ForceResultsView(vm);
wnd.ShowDialog();
}
}
}
}

View File

@@ -0,0 +1,66 @@
using StructureHelper.Windows.Errors;
using StructureHelper.Windows.ViewModels.Errors;
using StructureHelperCommon.Infrastructures.Enums;
using StructureHelperCommon.Infrastructures.Settings;
using StructureHelperCommon.Models.Forces;
using StructureHelperLogics.NdmCalculations.Cracking;
using StructureHelperLogics.NdmCalculations.Primitives;
using StructureHelperLogics.Services.NdmPrimitives;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StructureHelper.Windows.ViewModels.Calculations.Calculators.ForceResultLogic
{
internal class ShowCrackResultLogic
{
public static GeometryNames GeometryNames => ProgramSetting.GeometryNames;
public LimitStates LimitState { get; set; }
public CalcTerms CalcTerm { get; set; }
public ForceTuple ForceTuple { get; set; }
public IEnumerable<INdmPrimitive> ndmPrimitives { get; set; }
public void Show()
{
var calculator = new CrackForceCalculator();
calculator.EndTuple = ForceTuple;
calculator.NdmCollection = NdmPrimitivesService.GetNdms(ndmPrimitives, LimitState, CalcTerm);
calculator.Run();
var result = (CrackForceResult)calculator.Result;
if (result.IsValid)
{
//var softLogic = new ExponentialSofteningLogic() { ForceRatio = result.ActualFactor };
string message = string.Empty;
if (result.IsSectionCracked)
{
message += $"Actual crack factor {result.FactorOfCrackAppearance}\n";
message += $"Softening crack factor PsiS={result.PsiS}\n";
message += $"{GeometryNames.MomFstName}={result.TupleOfCrackAppearance.Mx},\n {GeometryNames.MomSndName}={result.TupleOfCrackAppearance.My},\n {GeometryNames.LongForceName}={result.TupleOfCrackAppearance.Nz}";
}
else
{
message += "Cracks are not apeared";
}
MessageBox.Show(
message,
"Crack results",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
var errorVM = new ErrorProcessor()
{
ShortText = "Error apeared while crack calculate",
DetailText = result.Description
};
var wnd = new ErrorMessage(errorVM);
wnd.ShowDialog();
}
}
}
}

View File

@@ -0,0 +1,164 @@
using LoaderCalculator;
using LoaderCalculator.Data.Materials.MaterialBuilders;
using LoaderCalculator.Data.Ndms;
using StructureHelper.Windows.Errors;
using StructureHelper.Windows.Graphs;
using StructureHelper.Windows.ViewModels.Errors;
using StructureHelper.Windows.ViewModels.Graphs;
using StructureHelperCommon.Infrastructures.Enums;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Settings;
using StructureHelperCommon.Models.Parameters;
using StructureHelperCommon.Services.Units;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.NdmCalculations.Cracking;
using StructureHelperLogics.NdmCalculations.Primitives;
using StructureHelperLogics.Services.NdmPrimitives;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
{
internal class ShowDiagramLogic
{
static readonly CrackForceCalculator calculator = new();
ArrayParameter<double> arrayParameter;
private static GeometryNames GeometryNames => ProgramSetting.GeometryNames;
public void Show(List<IForcesTupleResult> results)
{
var resultList = results.Where(x => x.IsValid == true).ToList();
var unitForce = CommonOperation.GetUnit(UnitTypes.Force, "kN");
var unitMoment = CommonOperation.GetUnit(UnitTypes.Moment, "kNm");
var unitCurvature = CommonOperation.GetUnit(UnitTypes.Curvature, "1/m");
string[] labels = GetLabels(unitForce, unitMoment, unitCurvature);
arrayParameter = new ArrayParameter<double>(resultList.Count(), labels.Count(), labels);
CalculateWithoutCrack(resultList, unitForce, unitMoment, unitCurvature);
SafetyProcessor.RunSafeProcess(ShowWindow, "Errors apearred during showing graph, see detailed information");
}
public void ShowCracks(List<IForcesTupleResult> results, IEnumerable<INdmPrimitive> ndmPrimitives)
{
var resultList = results.Where(x => x.IsValid == true).ToList();
var unitForce = CommonOperation.GetUnit(UnitTypes.Force, "kN");
var unitMoment = CommonOperation.GetUnit(UnitTypes.Moment, "kNm");
var unitCurvature = CommonOperation.GetUnit(UnitTypes.Curvature, "1/m");
string[] labels = GetCrackLabels(unitForce, unitMoment, unitCurvature);
arrayParameter = new ArrayParameter<double>(resultList.Count(), labels.Count(), labels);
CalculateWithCrack(resultList, ndmPrimitives, unitForce, unitMoment, unitCurvature);
SafetyProcessor.RunSafeProcess(ShowWindow, "Errors apearred during showing graph, see detailed information");
}
private void CalculateWithCrack(List<IForcesTupleResult> resultList, IEnumerable<INdmPrimitive> ndmPrimitives, IUnit unitForce, IUnit unitMoment, IUnit unitCurvature)
{
var data = arrayParameter.Data;
for (int i = 0; i < resultList.Count(); i++)
{
var valueList = new List<double>
{
resultList[i].DesignForceTuple.ForceTuple.Mx * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.My * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.Nz * unitForce.Multiplyer
};
calculator.EndTuple = resultList[i].DesignForceTuple.ForceTuple;
var limitState = resultList[i].DesignForceTuple.LimitState;
var calcTerm = resultList[i].DesignForceTuple.CalcTerm;
var ndms = NdmPrimitivesService.GetNdms(ndmPrimitives, limitState, calcTerm);
calculator.NdmCollection = ndms;
calculator.Run();
var result = (CrackForceResult)calculator.Result;
if (result.IsValid == false)
{
MessageBox.Show(
"Result is not valid",
"Crack results",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
valueList.Add(result.ReducedStrainTuple.Mx);
valueList.Add(result.ReducedStrainTuple.My);
valueList.Add(result.ReducedStrainTuple.Nz);
valueList.Add(result.SofteningFactors.Mx);
valueList.Add(result.SofteningFactors.My);
valueList.Add(result.SofteningFactors.Nz);
valueList.Add(result.PsiS);
for (int j = 0; j < valueList.Count; j++)
{
data[i, j] = valueList[j];
}
}
}
private void CalculateWithoutCrack(List<IForcesTupleResult> resultList, IUnit unitForce, IUnit unitMoment, IUnit unitCurvature)
{
var data = arrayParameter.Data;
for (int i = 0; i < resultList.Count(); i++)
{
var valueList = ProcessResultWithouCrack(resultList, unitForce, unitMoment, unitCurvature, i);
for (int j = 0; j < valueList.Count; j++)
{
data[i, j] = valueList[j];
}
}
}
private void ShowWindow()
{
var wnd = new GraphView(arrayParameter);
wnd.ShowDialog();
}
private static List<double> ProcessResultWithouCrack(List<IForcesTupleResult> resultList, IUnit unitForce, IUnit unitMoment, IUnit unitCurvature, int i)
{
return new List<double>
{
resultList[i].DesignForceTuple.ForceTuple.Mx * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.My * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.Nz * unitForce.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.Kx * unitCurvature.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.Ky * unitCurvature.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.EpsZ
};
}
private static string[] GetLabels(IUnit unitForce, IUnit unitMoment, IUnit unitCurvature)
{
return new string[]
{
$"{GeometryNames.MomFstName}, {unitMoment.Name}",
$"{GeometryNames.MomSndName}, {unitMoment.Name}",
$"{GeometryNames.LongForceName}, {unitForce.Name}",
$"{GeometryNames.CurvFstName}, {unitCurvature.Name}",
$"{GeometryNames.CurvSndName}, {unitCurvature.Name}",
$"{GeometryNames.StrainTrdName}"
};
}
private static string[] GetCrackLabels(IUnit unitForce, IUnit unitMoment, IUnit unitCurvature)
{
const string crc = "CrcSofteningFactor";
return new string[]
{
$"{GeometryNames.MomFstName}, {unitMoment.Name}",
$"{GeometryNames.MomSndName}, {unitMoment.Name}",
$"{GeometryNames.LongForceName}, {unitForce.Name}",
$"{GeometryNames.CurvFstName}, {unitCurvature.Name}",
$"{GeometryNames.CurvSndName}, {unitCurvature.Name}",
$"{GeometryNames.StrainTrdName}",
$"{crc}Ix",
$"{crc}Iy",
$"{crc}Az",
$"PsiFactor"
};
}
}
}

View File

@@ -12,6 +12,7 @@ using StructureHelper.Windows.Errors;
using StructureHelper.Windows.Forces; using StructureHelper.Windows.Forces;
using StructureHelper.Windows.Graphs; using StructureHelper.Windows.Graphs;
using StructureHelper.Windows.PrimitivePropertiesWindow; using StructureHelper.Windows.PrimitivePropertiesWindow;
using StructureHelper.Windows.ViewModels.Calculations.Calculators.ForceResultLogic;
using StructureHelper.Windows.ViewModels.Errors; using StructureHelper.Windows.ViewModels.Errors;
using StructureHelper.Windows.ViewModels.Forces; using StructureHelper.Windows.ViewModels.Forces;
using StructureHelper.Windows.ViewModels.Graphs; using StructureHelper.Windows.ViewModels.Graphs;
@@ -41,6 +42,9 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
{ {
public class ForcesResultsViewModel : ViewModelBase public class ForcesResultsViewModel : ViewModelBase
{ {
private static readonly ShowDiagramLogic showDiagramLogic = new();
private static readonly InterpolateLogic interpolateLogic = new();
private static readonly ShowCrackResultLogic showCrackResultLogic = new();
private IForceCalculator forceCalculator; private IForceCalculator forceCalculator;
private IForcesResults forcesResults; private IForcesResults forcesResults;
private IEnumerable<INdmPrimitive> ndmPrimitives; private IEnumerable<INdmPrimitive> ndmPrimitives;
@@ -48,25 +52,24 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
private IEnumerable<INdm> ndms; private IEnumerable<INdm> ndms;
private IReport isoFieldReport; private IReport isoFieldReport;
static string firstAxisName => ProgramSetting.CrossSectionAxisNames.FirstAxis; public static GeometryNames GeometryNames => ProgramSetting.GeometryNames;
static string secondAxisName => ProgramSetting.CrossSectionAxisNames.SecondAxis;
static string thirdAxisName => ProgramSetting.CrossSectionAxisNames.ThirdAxis;
public ForcesTupleResult SelectedResult { get; set; } public ForcesTupleResult SelectedResult { get; set; }
private RelayCommand showIsoFieldCommand; private ICommand showIsoFieldCommand;
private RelayCommand exportToCSVCommand; private ICommand exportToCSVCommand;
private RelayCommand interpolateCommand; private ICommand interpolateCommand;
private RelayCommand setPrestrainCommand; private ICommand setPrestrainCommand;
private ICommand showAnchorageCommand; private ICommand showAnchorageCommand;
private ICommand showGeometryResultCommand; private ICommand showGeometryResultCommand;
private ICommand showGraphsCommand; private ICommand showGraphsCommand;
private ICommand showCrackResult; private ICommand showCrackResult;
private ICommand showCrackGraphsCommand;
public IForcesResults ForcesResults public IForcesResults ForcesResults
{ {
get => forcesResults; get => forcesResults;
} }
public RelayCommand ShowIsoFieldCommand public ICommand ShowIsoFieldCommand
{ {
get get
{ {
@@ -104,7 +107,19 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
} }
public ICommand ShowGraphsCommand public ICommand ShowGraphsCommand
{ {
get => showGraphsCommand ??= new RelayCommand(o => showGraphs()); get => showGraphsCommand ??= new RelayCommand(o =>
{
showDiagramLogic.Show(forcesResults.ForcesResultList);
}
);
}
public ICommand ShowCrackGraphsCommand
{
get => showCrackGraphsCommand ??= new RelayCommand(o =>
{
showDiagramLogic.ShowCracks(forcesResults.ForcesResultList, ndmPrimitives);
}
);
} }
public ICommand ShowCrackResultCommand public ICommand ShowCrackResultCommand
{ {
@@ -113,138 +128,27 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
SafetyProcessor.RunSafeProcess(ShowCrackResult); SafetyProcessor.RunSafeProcess(ShowCrackResult);
}, o => (SelectedResult != null) && SelectedResult.IsValid); }, o => (SelectedResult != null) && SelectedResult.IsValid);
} }
private void ShowCrackResult() private void ShowCrackResult()
{ {
var limitState = SelectedResult.DesignForceTuple.LimitState; showCrackResultLogic.LimitState = SelectedResult.DesignForceTuple.LimitState;
var calcTerm = SelectedResult.DesignForceTuple.CalcTerm; showCrackResultLogic.CalcTerm = CalcTerms.ShortTerm; //= SelectedResult.DesignForceTuple.CalcTerm;
var calculator = new CrackForceCalculator(); showCrackResultLogic.ForceTuple = SelectedResult.DesignForceTuple.ForceTuple;
calculator.EndTuple = SelectedResult.DesignForceTuple.ForceTuple; showCrackResultLogic.ndmPrimitives = ndmPrimitives;
calculator.NdmCollection = NdmPrimitivesService.GetNdms(ndmPrimitives, limitState, calcTerm); showCrackResultLogic.Show();
//Act
calculator.Run();
var result = (CrackForceResult)calculator.Result;
if (result.IsValid)
{
var softLogic = new ExponentialSofteningLogic() { ForceRatio = result.ActualFactor };
string message = string.Empty;
if (result.IsSectionCracked)
{
message += $"Actual crack factor {result.ActualFactor}\n";
message += $"Softening crack factor PsiS={softLogic.SofteningFactor()}\n";
message += $"M{firstAxisName}={result.ActualTuple.Mx}, M{secondAxisName}={result.ActualTuple.My}, N{thirdAxisName}={result.ActualTuple.Nz}";
}
else
{
message += "Cracks are not apeared";
}
MessageBox.Show(
message,
"Crack results",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
var errorVM = new ErrorProcessor()
{
ShortText = "Error apeared while crack calculate",
DetailText = result.Description
};
var wnd = new ErrorMessage(errorVM);
wnd.ShowDialog();
}
} }
public ICommand InterpolateCommand
private void showGraphs()
{
var unitForce = CommonOperation.GetUnit(UnitTypes.Force, "kN");
var unitMoment = CommonOperation.GetUnit(UnitTypes.Moment, "kNm");
var unitCurvature = CommonOperation.GetUnit(UnitTypes.Curvature, "1/m");
var labels = new string[]
{
$"M{firstAxisName}, {unitMoment.Name}",
$"M{secondAxisName}, {unitMoment.Name}",
$"N{thirdAxisName}, {unitForce.Name}",
$"K{firstAxisName}, {unitCurvature.Name}",
$"K{secondAxisName}, {unitCurvature.Name}",
$"Eps_{thirdAxisName}"
};
var resultList = forcesResults.ForcesResultList.Where(x => x.IsValid == true).ToList();
var array = new ArrayParameter<double>(resultList.Count(), labels.Count(), labels);
var data = array.Data;
for (int i = 0; i < resultList.Count(); i++)
{
var valueList = new List<double>
{
resultList[i].DesignForceTuple.ForceTuple.Mx * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.My * unitMoment.Multiplyer,
resultList[i].DesignForceTuple.ForceTuple.Nz * unitForce.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.Kx * unitCurvature.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.Ky * unitCurvature.Multiplyer,
resultList[i].LoaderResults.ForceStrainPair.StrainMatrix.EpsZ
};
for (int j = 0; j < valueList.Count(); j++)
{
data[i, j] = valueList[j];
}
}
var graphViewModel = new GraphViewModel(array);
var wnd = new GraphView(graphViewModel);
try
{
wnd.ShowDialog();
}
catch(Exception ex)
{
var vm = new ErrorProcessor()
{
ShortText = "Errors apearred during showing isofield, see detailed information",
DetailText = $"{ex}"
};
new ErrorMessage(vm).ShowDialog();
}
}
public RelayCommand InterpolateCommand
{ {
get get
{ {
return interpolateCommand ?? return interpolateCommand ??
(interpolateCommand = new RelayCommand(o => (interpolateCommand = new RelayCommand(o =>
{ {
Interpolate(); IDesignForceTuple finishDesignTuple = SelectedResult.DesignForceTuple.Clone() as IDesignForceTuple;
interpolateLogic.Show(finishDesignTuple, forceCalculator);
}, o => SelectedResult != null)); }, o => SelectedResult != null));
} }
} }
private void Interpolate() public ICommand SetPrestrainCommand
{
IDesignForceTuple startDesignTuple, finishDesignTuple;
finishDesignTuple = SelectedResult.DesignForceTuple.Clone() as IDesignForceTuple;
var viewModel = new InterpolateTuplesViewModel(finishDesignTuple, null, 100);
var wndTuples = new InterpolateTuplesView(viewModel);
wndTuples.ShowDialog();
if (wndTuples.DialogResult != true) return;
startDesignTuple = viewModel.StartDesignForce;
finishDesignTuple = viewModel.FinishDesignForce;
int stepCount = viewModel.StepCount;
var calculator = InterpolateService.InterpolateForceCalculator(forceCalculator, finishDesignTuple, startDesignTuple, stepCount);
calculator.Run();
var result = calculator.Result;
if (result is null || result.IsValid == false)
{
MessageBox.Show(result.Description, "Check data for analisys", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
var vm = new ForcesResultsViewModel(calculator);
var wnd = new ForceResultsView(vm);
wnd.ShowDialog();
}
}
public RelayCommand SetPrestrainCommand
{ {
get get
{ {
@@ -256,7 +160,6 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
)); ));
} }
} }
private void SetPrestrain() private void SetPrestrain()
{ {
var source = StrainTupleService.ConvertToStrainTuple(SelectedResult.LoaderResults.StrainMatrix); var source = StrainTupleService.ConvertToStrainTuple(SelectedResult.LoaderResults.StrainMatrix);
@@ -271,7 +174,6 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
} }
} }
} }
public ICommand ShowAnchorageCommand public ICommand ShowAnchorageCommand
{ {
get get
@@ -304,7 +206,6 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
new ErrorMessage(vm).ShowDialog(); new ErrorMessage(vm).ShowDialog();
} }
} }
public ICommand ShowGeometryResultCommand => public ICommand ShowGeometryResultCommand =>
showGeometryResultCommand ??= new RelayCommand(o => showGeometryResultCommand ??= new RelayCommand(o =>
showGeometryResult(), o => SelectedResult != null && SelectedResult.IsValid); showGeometryResult(), o => SelectedResult != null && SelectedResult.IsValid);
@@ -333,14 +234,12 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
} }
} }
} }
public ForcesResultsViewModel(IForceCalculator forceCalculator) public ForcesResultsViewModel(IForceCalculator forceCalculator)
{ {
this.forceCalculator = forceCalculator; this.forceCalculator = forceCalculator;
this.forcesResults = this.forceCalculator.Result as IForcesResults; this.forcesResults = this.forceCalculator.Result as IForcesResults;
ndmPrimitives = this.forceCalculator.Primitives; ndmPrimitives = this.forceCalculator.Primitives;
} }
private void ShowIsoField() private void ShowIsoField()
{ {
try try
@@ -384,7 +283,6 @@ namespace StructureHelper.Windows.ViewModels.Calculations.Calculators
} }
ndms = ndmRange; ndms = ndmRange;
} }
private bool SelectPrimitives() private bool SelectPrimitives()
{ {
var vm = new SelectPrimitivesViewModel(ndmPrimitives); var vm = new SelectPrimitivesViewModel(ndmPrimitives);

View File

@@ -47,7 +47,7 @@ namespace StructureHelper.Windows.ViewModels.Forces
if (dialogResult == DialogResult.Yes) if (dialogResult == DialogResult.Yes)
{ {
if (DeleteAction() != true) return; if (DeleteAction() != true) return;
GlobalRepository.Materials.Delete(SelectedItem.Id); GlobalRepository.Actions.Delete(SelectedItem.Id);
base.DeleteMethod(parameter); base.DeleteMethod(parameter);
} }
} }

View File

@@ -3,6 +3,7 @@ using StructureHelper.Windows.CalculationWindows.CalculatorsViews.ForceCalculato
using StructureHelper.Windows.ViewModels.Calculations.Calculators; using StructureHelper.Windows.ViewModels.Calculations.Calculators;
using StructureHelper.Windows.ViewModels.Errors; using StructureHelper.Windows.ViewModels.Errors;
using StructureHelperCommon.Infrastructures.Enums; using StructureHelperCommon.Infrastructures.Enums;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Models.Calculators; using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Forces;
using StructureHelperLogics.Models.CrossSections; using StructureHelperLogics.Models.CrossSections;
@@ -67,7 +68,7 @@ namespace StructureHelper.Windows.ViewModels.NdmCrossSections
( (
runCommand = new RelayCommand(o => runCommand = new RelayCommand(o =>
{ {
SafetyProcessor.RunSafeProcess(RunCalculator); SafetyProcessor.RunSafeProcess(RunCalculator, ErrorStrings.ErrorOfExuting + $": {SelectedItem.Name}");
}, o => SelectedItem != null)); }, o => SelectedItem != null));
} }
} }

View File

@@ -19,5 +19,6 @@
public static string SizeMustBeGreaterThanZero => "#0014: Size must be greater than zero"; public static string SizeMustBeGreaterThanZero => "#0014: Size must be greater than zero";
public static string ParameterIsNull => "#0015: Parameter is null"; public static string ParameterIsNull => "#0015: Parameter is null";
public static string ResultIsNotValid => "#0016: Result is not valid"; public static string ResultIsNotValid => "#0016: Result is not valid";
public static string ErrorOfExuting => "#0017: Error of executing";
} }
} }

View File

@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperCommon.Infrastructures.Settings
{
public class CrossSectionAxisNames
{
public string FirstAxis => "x";
public string SecondAxis => "y";
public string ThirdAxis => "z";
}}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperCommon.Infrastructures.Settings
{
public class GeometryNames
{
const string shortMoment = "M";
const string shortLongForce = "N";
const string shortShearForce = "Q";
const string fullMoment = "Moment M";
const string fullLongForce = "Force N";
const string fullShearForce = "Force Q";
const string curvature = "K";
const string strain = "Eps_";
public string FstAxisName => "x";
public string SndAxisName => "y";
public string TrdAxisName => "z";
public string MomFstName => shortMoment + FstAxisName;
public string MomSndName => shortMoment + SndAxisName;
public string LongForceName => shortLongForce + TrdAxisName;
public string FullMomFstName => fullMoment + FstAxisName;
public string FullMomSndName => fullMoment + SndAxisName;
public string FullLongForceName => fullLongForce + TrdAxisName;
public string CurvFstName => curvature + FstAxisName;
public string CurvSndName => curvature + SndAxisName;
public string StrainTrdName => strain + TrdAxisName;
}
}

View File

@@ -14,6 +14,7 @@ namespace StructureHelperCommon.Infrastructures.Settings
private static List<ICodeEntity> codesList; private static List<ICodeEntity> codesList;
private static IMaterialRepository materialRepository; private static IMaterialRepository materialRepository;
private static NatSystems natSystem; private static NatSystems natSystem;
private static GeometryNames geometryNames;
public static CodeTypes CodeType => CodeTypes.SP63_2018; public static CodeTypes CodeType => CodeTypes.SP63_2018;
public static CodeTypes FRCodeType => CodeTypes.SP164_2014; public static CodeTypes FRCodeType => CodeTypes.SP164_2014;
@@ -29,7 +30,7 @@ namespace StructureHelperCommon.Infrastructures.Settings
materialRepository = new MaterialRepository(codesList); materialRepository = new MaterialRepository(codesList);
} }
} }
public static CrossSectionAxisNames CrossSectionAxisNames => new CrossSectionAxisNames(); public static GeometryNames GeometryNames => geometryNames ??= new GeometryNames();
public static LimitStatesList LimitStatesList => new LimitStatesList(); public static LimitStatesList LimitStatesList => new LimitStatesList();
public static CalcTermList CalcTermList => new CalcTermList(); public static CalcTermList CalcTermList => new CalcTermList();
public static List<ICodeEntity> CodesList public static List<ICodeEntity> CodesList

View File

@@ -7,7 +7,7 @@ namespace StructureHelperCommon.Services.Forces
{ {
public static IStrainMatrix ConvertToLoaderStrainMatrix(StrainTuple strainTuple) public static IStrainMatrix ConvertToLoaderStrainMatrix(StrainTuple strainTuple)
{ {
IStrainMatrix strainMatrix = new StrainMatrix() { Kx = strainTuple.Nz, Ky = strainTuple.My, EpsZ = strainTuple.Nz }; IStrainMatrix strainMatrix = new StrainMatrix() { Kx = strainTuple.Mx, Ky = strainTuple.My, EpsZ = strainTuple.Nz };
return strainMatrix; return strainMatrix;
} }

View File

@@ -14,16 +14,18 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces
{ {
public class ForceTupleCalculator : IForceTupleCalculator public class ForceTupleCalculator : IForceTupleCalculator
{ {
public IForceTupleInputData InputData { get; set; }
public string Name { get; set; } public string Name { get; set; }
public IResult Result { get; private set; } public IResult Result { get; private set; }
private IForceTupleInputData inputData;
public ForceTupleCalculator(IForceTupleInputData inputData) public ForceTupleCalculator(IForceTupleInputData inputData)
{ {
this.inputData = inputData; InputData = inputData;
}
public ForceTupleCalculator()
{
} }
public void Run() public void Run()
{ {
Result = CalculateResult(); Result = CalculateResult();
@@ -31,9 +33,9 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces
private IForcesTupleResult CalculateResult() private IForcesTupleResult CalculateResult()
{ {
var ndmCollection = inputData.NdmCollection; var ndmCollection = InputData.NdmCollection;
var tuple = inputData.Tuple; var tuple = InputData.Tuple;
var accuracy = inputData.Accuracy; var accuracy = InputData.Accuracy;
var mx = tuple.Mx; var mx = tuple.Mx;

View File

@@ -14,5 +14,9 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces
public IEnumerable<INdm> NdmCollection { get; set; } public IEnumerable<INdm> NdmCollection { get; set; }
public IForceTuple Tuple { get; set; } public IForceTuple Tuple { get; set; }
public IAccuracy Accuracy { get; set; } public IAccuracy Accuracy { get; set; }
public ForceTupleInputData()
{
Accuracy ??= new Accuracy() { IterationAccuracy = 0.01d, MaxIterationCount = 1000 };
}
} }
} }

View File

@@ -9,5 +9,6 @@ namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces
{ {
public interface IForceTupleCalculator : ICalculator public interface IForceTupleCalculator : ICalculator
{ {
IForceTupleInputData InputData {get;set;}
} }
} }

View File

@@ -0,0 +1,30 @@
using LoaderCalculator.Data.Ndms;
using LoaderCalculator.Logics;
using LoaderCalculator.Logics.Geometry;
using StructureHelperCommon.Models.Forces;
using StructureHelperCommon.Services.Forces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces.Logics
{
internal class SofteningFactorLogic
{
public static IStressLogic stressLogic = new StressLogic();
public IEnumerable<INdm> NdmCollection { get; set; }
public StrainTuple StrainTuple { get; set; }
public StrainTuple GetSofteningFactors()
{
var strainTuple = new StrainTuple();
var loaderStainMatrix = StrainTupleService.ConvertToLoaderStrainMatrix(StrainTuple);
var (MxFactor, MyFactor, NzFactor) = GeometryOperations.GetSofteningsFactors(NdmCollection, loaderStainMatrix);
strainTuple.Mx = MxFactor;
strainTuple.My = MyFactor;
strainTuple.Nz = NzFactor;
return strainTuple;
}
}
}

View File

@@ -4,6 +4,8 @@ using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Forces;
using StructureHelperCommon.Services; using StructureHelperCommon.Services;
using StructureHelperCommon.Services.Forces; using StructureHelperCommon.Services.Forces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces.Logics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -15,20 +17,28 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
public class CrackForceCalculator : ICalculator public class CrackForceCalculator : ICalculator
{ {
static readonly CrackedLogic crackedLogic = new(); static readonly CrackedLogic crackedLogic = new();
static readonly ExpSofteningLogic softeningLogic = new();
static readonly CrackStrainLogic crackStrainLogic = new();
static readonly SofteningFactorLogic softeningFactorLogic = new();
IForceTupleCalculator forceTupleCalculator;
private CrackForceResult result; private CrackForceResult result;
public string Name { get; set; } public string Name { get; set; }
public IForceTuple StartTuple { get; set; } public ForceTuple StartTuple { get; set; }
public IForceTuple EndTuple { get; set; } public ForceTuple EndTuple { get; set; }
public IEnumerable<INdm> NdmCollection { get; set; } public IEnumerable<INdm> NdmCollection { get; set; }
public Accuracy Accuracy {get;set; } public Accuracy Accuracy {get;set; }
public IResult Result => result; public IResult Result => result;
public CrackForceCalculator() public CrackForceCalculator(IForceTupleCalculator forceTupleCalculator)
{ {
StartTuple ??= new ForceTuple(); StartTuple ??= new ForceTuple();
Accuracy ??= new Accuracy() { IterationAccuracy = 0.0001d, MaxIterationCount = 10000 }; Accuracy ??= new Accuracy() { IterationAccuracy = 0.0001d, MaxIterationCount = 10000 };
this.forceTupleCalculator = forceTupleCalculator;
}
public CrackForceCalculator() : this(new ForceTupleCalculator())
{
} }
public void Run() public void Run()
{ {
result = new CrackForceResult(); result = new CrackForceResult();
@@ -47,18 +57,12 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
} }
if (crackedLogic.IsSectionCracked(0d) == true) if (crackedLogic.IsSectionCracked(0d) == true)
{ {
result.IsValid = true; SectionCrackedAtStart();
result.ActualFactor = 0d;
result.ActualTuple = (IForceTuple)StartTuple.Clone();
result.IsSectionCracked = true;
result.Description += "Section cracked in start tuple";
return; return;
} }
if (crackedLogic.IsSectionCracked(1d) == false) if (crackedLogic.IsSectionCracked(1d) == false)
{ {
result.IsValid = true; SectionIsNotCracked();
result.IsSectionCracked = false;
result.Description = "Section is not cracked";
return; return;
} }
var parameterCalculator = new FindParameterCalculator() var parameterCalculator = new FindParameterCalculator()
@@ -70,11 +74,7 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
var paramResult = parameterCalculator.Result as FindParameterResult; var paramResult = parameterCalculator.Result as FindParameterResult;
if (paramResult.IsValid == true) if (paramResult.IsValid == true)
{ {
result.IsValid = true; SectionIsCrackedBetween(paramResult);
result.IsSectionCracked = true;
result.Description += paramResult.Description;
result.ActualFactor = paramResult.Parameter;
result.ActualTuple = ForceTupleService.InterpolateTuples(EndTuple, StartTuple, paramResult.Parameter);
} }
else else
{ {
@@ -83,6 +83,76 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
} }
} }
private void SectionIsCrackedBetween(FindParameterResult? paramResult)
{
var factorOfCrackAppearance = paramResult.Parameter;
softeningLogic.ForceRatio = factorOfCrackAppearance;
var psiS = softeningLogic.GetSofteningFactor();
result.IsValid = true;
result.IsSectionCracked = true;
result.Description += paramResult.Description;
result.FactorOfCrackAppearance = factorOfCrackAppearance;
result.TupleOfCrackAppearance = ForceTupleService.InterpolateTuples(EndTuple, StartTuple, factorOfCrackAppearance);
var reducedStrainTuple = GetReducedStrainTuple(factorOfCrackAppearance, psiS);
result.ReducedStrainTuple = reducedStrainTuple;
result.SofteningFactors=GetSofteningFactors(reducedStrainTuple);
result.PsiS = psiS;
}
private StrainTuple GetSofteningFactors(StrainTuple reducedStrainTuple)
{
softeningFactorLogic.NdmCollection = NdmCollection;
softeningFactorLogic.StrainTuple = reducedStrainTuple;
return softeningFactorLogic.GetSofteningFactors();
}
private StrainTuple GetReducedStrainTuple(double factorOfCrackAppearance, double softeningFactor)
{
const double notCrackedFactor = 0.99d;
var notCrackedForceTuple = ForceTupleService.InterpolateTuples(EndTuple, StartTuple, factorOfCrackAppearance * notCrackedFactor) as ForceTuple;
var crackAppearanceStrainTuple = GetStrainTuple(notCrackedForceTuple);
var actualStrainTuple = GetStrainTuple(EndTuple);
crackStrainLogic.BeforeCrackingTuple = crackAppearanceStrainTuple;
crackStrainLogic.AfterCrackingTuple = actualStrainTuple;
crackStrainLogic.SofteningFactor = softeningFactor;
var reducedStrainTuple = crackStrainLogic.GetCrackedStrainTuple();
return reducedStrainTuple is null
? throw new StructureHelperException(ErrorStrings.ResultIsNotValid + "\n Strain Tuple is null")
: reducedStrainTuple;
}
private void SectionCrackedAtStart()
{
result.IsValid = true;
result.FactorOfCrackAppearance = 0d;
result.TupleOfCrackAppearance = (IForceTuple)StartTuple.Clone();
softeningLogic.ForceRatio = result.FactorOfCrackAppearance;
result.PsiS = softeningLogic.GetSofteningFactor();
result.ReducedStrainTuple = GetStrainTuple(EndTuple);
result.SofteningFactors = GetSofteningFactors(result.ReducedStrainTuple);
result.IsSectionCracked = true;
result.Description += "Section cracked in start tuple";
}
private void SectionIsNotCracked()
{
result.IsValid = true;
result.IsSectionCracked = false;
result.ReducedStrainTuple = GetStrainTuple(EndTuple);
result.SofteningFactors = GetSofteningFactors(result.ReducedStrainTuple);
result.Description = "Section is not cracked";
}
private StrainTuple GetStrainTuple(ForceTuple forceTuple)
{
ForceTupleInputData inputData = new();
inputData.NdmCollection = NdmCollection;
inputData.Tuple = forceTuple;
forceTupleCalculator.InputData = inputData;
forceTupleCalculator.Run();
var result = forceTupleCalculator.Result as IForcesTupleResult;
var loaderStrainMatrix = result.LoaderResults.ForceStrainPair.StrainMatrix;
StrainTuple strainTuple = StrainTupleService.ConvertToStrainTuple(loaderStrainMatrix);
return strainTuple;
}
private void Check() private void Check()
{ {
CheckObject.IsNull(EndTuple); CheckObject.IsNull(EndTuple);
@@ -91,7 +161,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
throw new StructureHelperException(ErrorStrings.DataIsInCorrect + ": Section is not cracked"); throw new StructureHelperException(ErrorStrings.DataIsInCorrect + ": Section is not cracked");
} }
} }
public object Clone() public object Clone()
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@@ -1,4 +1,5 @@
using StructureHelperCommon.Models.Calculators; using LoaderCalculator.Data.Ndms;
using StructureHelperCommon.Models.Calculators;
using StructureHelperCommon.Models.Forces; using StructureHelperCommon.Models.Forces;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -13,7 +14,14 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
public bool IsValid { get; set; } public bool IsValid { get; set; }
public string Description { get; set; } public string Description { get; set; }
public bool IsSectionCracked { get; set; } public bool IsSectionCracked { get; set; }
public double ActualFactor { get; set; } public double FactorOfCrackAppearance { get; set; }
public IForceTuple ActualTuple { get; set; } public IForceTuple StartTuple { get; set; }
public IForceTuple EndTuple { get; set; }
public IForceTuple TupleOfCrackAppearance { get; set; }
public StrainTuple ReducedStrainTuple { get; set; }
public StrainTuple SofteningFactors { get; set; }
public IEnumerable<INdm> NdmCollection { get; set; }
public double PsiS { get; set; }
} }
} }

View File

@@ -0,0 +1,23 @@
using StructureHelperCommon.Models.Forces;
using StructureHelperCommon.Services.Forces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Cracking
{
internal class CrackStrainLogic : ICrackStrainLogic
{
public StrainTuple BeforeCrackingTuple { get; set; }
public StrainTuple AfterCrackingTuple { get; set; }
public double SofteningFactor { get; set; }
public StrainTuple GetCrackedStrainTuple()
{
var strainTuple = ForceTupleService.InterpolateTuples(AfterCrackingTuple, BeforeCrackingTuple, SofteningFactor) as StrainTuple;
return strainTuple;
}
}
}

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Cracking namespace StructureHelperLogics.NdmCalculations.Cracking
{ {
public class ExponentialSofteningLogic : ICrackSofteningLogic public class ExpSofteningLogic : ICrackSofteningLogic
{ {
private double forceRatio; private double forceRatio;
private double powerFactor; private double powerFactor;
@@ -42,13 +42,13 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
} }
} }
public double FiMin {get;set;} public double FiMin {get;set;}
public ExponentialSofteningLogic() public ExpSofteningLogic()
{ {
FiMin = 0.2d; FiMin = 0.2d;
PowerFactor = 2d; PowerFactor = 1d;
BettaFactor = 0.8; BettaFactor = 0.8;
} }
public double SofteningFactor() public double GetSofteningFactor()
{ {
double fi; double fi;
fi = 1 - BettaFactor * Math.Pow(ForceRatio, PowerFactor); fi = 1 - BettaFactor * Math.Pow(ForceRatio, PowerFactor);

View File

@@ -8,6 +8,6 @@ namespace StructureHelperLogics.NdmCalculations.Cracking
{ {
public interface ICrackSofteningLogic public interface ICrackSofteningLogic
{ {
double SofteningFactor(); double GetSofteningFactor();
} }
} }

View File

@@ -0,0 +1,17 @@
using StructureHelperCommon.Models.Forces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StructureHelperLogics.NdmCalculations.Cracking
{
internal interface ICrackStrainLogic
{
StrainTuple BeforeCrackingTuple { get; set; }
StrainTuple AfterCrackingTuple { get; set; }
double SofteningFactor { get; set; }
StrainTuple GetCrackedStrainTuple();
}
}

View File

@@ -18,8 +18,8 @@ namespace StructureHelperLogics.Services.NdmPrimitives
{ {
const string prefixInitial = "Initial"; const string prefixInitial = "Initial";
const string prefixActual = "Actual"; const string prefixActual = "Actual";
static string firstAxisName => ProgramSetting.CrossSectionAxisNames.FirstAxis; static string firstAxisName => ProgramSetting.GeometryNames.FstAxisName;
static string secondAxisName => ProgramSetting.CrossSectionAxisNames.SecondAxis; static string secondAxisName => ProgramSetting.GeometryNames.SndAxisName;
static IEnumerable<IUnit> units = UnitsFactory.GetUnitCollection(); static IEnumerable<IUnit> units = UnitsFactory.GetUnitCollection();
private IEnumerable<INdm> ndms; private IEnumerable<INdm> ndms;
private IStrainMatrix strainMatrix; private IStrainMatrix strainMatrix;
@@ -133,10 +133,9 @@ namespace StructureHelperLogics.Services.NdmPrimitives
}; };
try try
{ {
var initialMoments = GeometryOperations.GetReducedMomentsOfInertia(locNdms); var actualMoments = GeometryOperations.GetSofteningsFactors(locNdms, locStrainMatrix);
var actualMoments = GeometryOperations.GetReducedMomentsOfInertia(locNdms, locStrainMatrix); firstParameter.Value = actualMoments.MxFactor.ToString();
firstParameter.Value = (actualMoments.MomentX / initialMoments.MomentX).ToString(); secondParameter.Value = actualMoments.MyFactor.ToString();
secondParameter.Value = (actualMoments.MomentY / initialMoments.MomentY).ToString();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -196,9 +195,8 @@ namespace StructureHelperLogics.Services.NdmPrimitives
}; };
try try
{ {
var actual = GeometryOperations.GetReducedArea(locNdms, locStrainMatrix); var actual = GeometryOperations.GetSofteningsFactors(locNdms, locStrainMatrix);
var initial = GeometryOperations.GetReducedArea(locNdms); firstParameter.Value = actual.NzFactor.ToString();
firstParameter.Value = (actual / initial).ToString();
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -35,7 +35,7 @@ namespace StructureHelperTests.FunctionalTests.Ndms.Calculators.CrackCalculatorT
//Assert //Assert
Assert.NotNull(result); Assert.NotNull(result);
Assert.IsTrue(result.IsValid); Assert.IsTrue(result.IsValid);
Assert.AreEqual(expectedFactor, result.ActualFactor, 0.01d); Assert.AreEqual(expectedFactor, result.FactorOfCrackAppearance, 0.01d);
} }
} }
} }