using FeMM.Common.Models;
using FeMM.Grasshopper.Components.Models.MeCheck2;
using FeMM.Grasshopper.DataTypes;
using GH_IO.Serialization;
using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Maffeis.Checkers.Concrete.Checkers;
using Maffeis.Model.Sections;
using Maffeis.Model.Sections.Steel;
using Maffeis.Model.Standards;
using Maffeis.Utilities.Maths;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.Versioning;
namespace FeMM.Grasshopper.Components.MeCheck2
{
#if NETCOREAPP
[SupportedOSPlatform("windows")]
#endif
public class SuperElementCheckComponentV2 : SuperElementCheckComponentBase
{
protected double[][] _rds;
private List<CompositeSectionStiffeners> CompositeSectionStiffeners { get; set; }
public SuperElementCheckComponentV2()
: base()
{
_rds = null;
}
public override GH_Exposure Exposure => GH_Exposure.tertiary;
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid => new("2c6c7e87-cd4d-42a1-b5d3-a06b0f8b5949");
protected override void RegisterInputs(GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Section Stiffeners", "SS", "Stiffeners data", GH_ParamAccess.list);
pManager[6].Optional = true;
pManager.AddIntegerParameter("Class 4 max iterations", "C4", "Maximum number of iterations to be made for section reduction in class 4. The value 1 means it stops after the first reduction. Value between 1 and 20.", GH_ParamAccess.item, 7);
pManager[7].Optional = true;
}
protected override void RegisterOutputs(GH_OutputParamManager pManager)
{
pManager.AddNumberParameter("Shear Resistance", "SR", "The shear Rd values", GH_ParamAccess.list);
}
protected override void LoadReadedData(IGH_DataAccess DA)
{
if (_rds != null)
{
DataTree<double> rdsSaved = new();
for (int i = 0; i < _rds.Length; i++)
rdsSaved.AddRange(_rds[i], new GH_Path(i));
DA.SetDataTree(3, rdsSaved);
}
}
protected override void ReadAdditionalParams(IGH_DataAccess DA)
{
CompositeSectionStiffeners = [];
DA.GetDataList(6, CompositeSectionStiffeners);
DA.GetData(7, ref _class4MaxIterations);
if (_class4MaxIterations < 1 || _class4MaxIterations > 20)
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Class 4 max iterations value must be between 1 and 20.");
_forcesDataTree = null;
}
protected override bool ComputeStiffeners(IGH_DataAccess DA, List<GH_CompositeBeam> beams, SectionCheckerModelCode2010[][] checkers, double tolerance = 10)
{
StandardEN1993p11 EN1993p11 = new();
double cumulativeBeamLength = 0;
double cumulativeStiffenersLength = 0;
int c = 0;
List<int> multipleStiffenerBeams = [];
_rds = new double[beams.Count][];
DataTree<double> rds = new();
for (int i = 0; i < beams.Count; i++)
{
CompositeBeamModel currentBeam = beams[i].Value;
List<CompositeSectionStiffeners> beamStiffeners;
SteelSection steelSectionStart = checkers[i][0].CheckerAttribute.Section.SteelSections[0].Section;
SteelSection steelSectionEnd = checkers[i][checkers[i].Length - 1].CheckerAttribute.Section.SteelSections[0].Section;
if (Math.Abs(cumulativeBeamLength - cumulativeStiffenersLength) <= tolerance)
{
c++;
if (CompositeSectionStiffeners.Count > c)
cumulativeStiffenersLength += CompositeSectionStiffeners[c].BeamLength;
}
if (CompositeSectionStiffeners.Count > c)
{
beamStiffeners = [CompositeSectionStiffeners[c]];
cumulativeBeamLength += currentBeam.Length;
if (cumulativeBeamLength > cumulativeStiffenersLength)
{
c++;
if (Math.Abs(cumulativeBeamLength - cumulativeStiffenersLength) > tolerance)
{
if (CompositeSectionStiffeners.Count > c)
beamStiffeners.Add(CompositeSectionStiffeners[c]);
else
beamStiffeners.Add(new CompositeSectionStiffeners(double.MaxValue, double.MaxValue, 1, 1, true, false));
}
if (CompositeSectionStiffeners.Count > c)
cumulativeStiffenersLength += CompositeSectionStiffeners[c].BeamLength;
}
}
else
beamStiffeners = [new CompositeSectionStiffeners(double.MaxValue, double.MaxValue, 1, 1, true, false)];
double[] branchResults = new double[beamStiffeners.Count];
for (int j = 0; j < beamStiffeners.Count; j++)
{
branchResults[j] = GetRd(steelSectionStart, steelSectionEnd, currentBeam.Length, beamStiffeners[j], EN1993p11) / 1000;
if (double.IsNaN(branchResults[j]))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"The Length value of the composite stiffeners {c} is not valid.");
Message = "Error";
return false;
}
}
if (branchResults.Length > 1)
multipleStiffenerBeams.Add(i);
_rds[i] = [.. branchResults];
rds.AddRange(branchResults, new GH_Path(i));
}
if (multipleStiffenerBeams.Count > 0)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"The stiffeners zones don't respect beams boundaries. Some beams have multiple zones defined inside them: {string.Join(", ", multipleStiffenerBeams)}.");
}
DA.SetDataTree(3, rds);
return true;
}
/// <summary>
/// Simplified version of the <see cref="EN1993p11Checker.ShearStiffnerCheck(SteelSection, StationResultBeamForces, double, double, double, bool, bool)"/> method. Returns the list of Shear Rd values for each beam.
/// </summary>
/// <param name="steelSectionStart"></param>
/// <param name="steelSectionEnd"></param>
/// <param name="beamLength"></param>
/// <param name="beamStiffeners"></param>
/// <param name="EN1993p11"></param>
/// <returns></returns>
private static double GetRd(SteelSection steelSectionStart, SteelSection steelSectionEnd, double beamLength, CompositeSectionStiffeners beamStiffeners, StandardEN1993p11 EN1993p11)
{
if (steelSectionStart.SectionShape is SectionH sectionHStart && steelSectionEnd.SectionShape is SectionH sectionHEnd)
{
double spacing = beamStiffeners.GeometryStiffenerSpacing;
double width = beamStiffeners.GeometryStiffenerWidth;
double thickness = beamStiffeners.GeometryStiffenerThickness;
bool symm = beamStiffeners.GeometryStiffenerSymmetric;
bool rigid = beamStiffeners.GeometryStiffenerRigid;
double tw;
double hw;
double fyk;
double E;
// il calcolo viene fatto sulla sezione media del beam
try
{
tw = Interpolation.GetLinearInterpolation(0, beamLength, sectionHStart.ThicknessWeb, sectionHEnd.ThicknessWeb, beamLength / 2);
hw = Interpolation.GetLinearInterpolation(0, beamLength, sectionHStart.HeightWeb, sectionHEnd.HeightWeb, beamLength / 2);
fyk = Interpolation.GetLinearInterpolation(0, beamLength, steelSectionStart.SteelMaterial.Fyk, steelSectionEnd.SteelMaterial.Fyk, beamLength / 2);
E = Interpolation.GetLinearInterpolation(0, beamLength, steelSectionStart.SteelMaterial.E, steelSectionEnd.SteelMaterial.E, beamLength / 2);
}
catch (ArgumentException)
{
return double.NaN;
}
double gm1 = EN1993p11.GammaM1;
double gm0 = EN1993p11.GammaM0;
double eta = 1.2;
double sigmaE = 190000.0 * Math.Pow(tw / hw, 2.0);
double kt = spacing / hw < 1.0 ? 4.0 + 5.34 * Math.Pow(hw / spacing, 2.0) : 5.34 + 4.0 * Math.Pow(hw / spacing, 2.0);
double v1 = kt * sigmaE;
double lambdaW = 0.76 * Math.Sqrt(fyk / v1);
double stiffnersConsideredArea = symm ? (width + width) * thickness : width * thickness;
double j = symm ? 1.0 / 12.0 * thickness * Math.Pow(width + tw + width, 3) : 1.0 / 12.0 * thickness * Math.Pow(width, 3);
double nCr = Math.PI * Math.PI * E * j / Math.Pow(hw, 2);
double lambdaSigned = Math.Sqrt(fyk * stiffnersConsideredArea / nCr);
double chiW;
if (lambdaW < 0.83 / eta)
{
chiW = eta;
}
else if (lambdaW >= 0.83 / eta && lambdaW < 1.08)
{
chiW = 0.83 / eta;
}
else
{
if (rigid)
chiW = 1.37 / (0.7 / lambdaSigned);
else
chiW = 0.83 / lambdaW;
}
chiW = chiW > gm1 / gm0 ? gm1 / gm0 : chiW;
return chiW * fyk * hw * tw / (Math.Pow(3, 0.5) * gm1);
}
return -1;
}
protected override void ResetData()
{
_rds = null;
}
//public override bool Write(GH_IWriter writer)
//{
// bool success = base.Write(writer);
// if (!success)
// return false;
// if (_rds != null)
// writer.SetString("RdsDataTree", JsonConvert.SerializeObject(_rds));
// return true;
//}
//public override bool Read(GH_IReader reader)
//{
// bool success = base.Read(reader);
// if (!success)
// return false;
// try
// {
// string rds = string.Empty;
// if (reader.TryGetString("RdsDataTree", ref rds) && !string.IsNullOrWhiteSpace(rds))
// _rds = JsonConvert.DeserializeObject<double[][]>(rds);
// }
// catch
// {
// _rds = null;
// }
// _just_loaded = true;
// return true;
//}
}
}