using FeMM.Common.Helpers;
using FeMM.Common.Models;
using FeMM.Grasshopper.DataTypes.FeMM;
using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Parameters;
using Grasshopper.Kernel.Types;
using Maffeis.Utilities.Units;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Versioning;
namespace FeMM.Grasshopper.Components.Checks
{
#if NETCOREAPP
[SupportedOSPlatform("windows")]
#endif
public class SteelFrameChecksComponent : GH_Component
{
public enum LengthUnits
{
mm,
cm,
m,
inch
}
public enum ForceUnits
{
N,
daN,
kN,
lbf
}
/// <summary>
/// Initializes a new instance of the BeamComponent class.
/// </summary>
public SteelFrameChecksComponent()
: base("Steel frame checks", "SFC", "Check steel frames", CategoryNameConstants.CATEGORY_CHECKS, CategoryNameConstants.SUBCATEGORY_STEELCHECKS)
{
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
int n;
pManager.AddGenericParameter("Frames", "Bs", "The frames containing results", GH_ParamAccess.list);
pManager.AddNumberParameter(char.ConvertFromUtf32(0x3B3) + "M0", char.ConvertFromUtf32(0x3B3) + "M0", "Partial safety factor on resistance checks", GH_ParamAccess.item, 1.05);
pManager.AddNumberParameter(char.ConvertFromUtf32(0x3B3) + "M1", char.ConvertFromUtf32(0x3B3) + "M1", "Partial safety factor on buckling checks", GH_ParamAccess.item, 1.05);
//pManager.AddNumberParameter("Min deflection factor", "MinDF", "Minimum deflection factor allowed for beam", GH_ParamAccess.item);
//pManager.AddNumberParameter("Max allowed deflection", "MaxD", "Maximum deflection admitted", GH_ParamAccess.item);
n = pManager.AddIntegerParameter("Length unit", "LU", "Units of the length", GH_ParamAccess.item);
Param_Integer length_param = (Param_Integer)pManager[n];
foreach (LengthUnits value in Enum.GetValues(typeof(LengthUnits)))
length_param.AddNamedValue(value.GetDescription(), (int)value);
n = pManager.AddIntegerParameter("Force unit", "FU", "Units of the forces", GH_ParamAccess.item);
Param_Integer force_param = (Param_Integer)pManager[n];
foreach (ForceUnits value in Enum.GetValues(typeof(ForceUnits)))
force_param.AddNamedValue(value.GetDescription(), (int)value);
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Steel Frames", "SFs", "Steel frames where results are calculated", GH_ParamAccess.list);
pManager.AddNumberParameter("Ascissas", "As", "Ascissas of Frames where the UR are calculated", GH_ParamAccess.tree);
pManager.AddNumberParameter("Resistance URs", "RUR", "The maximum resistance utilization ratios, one for each beam", GH_ParamAccess.tree);
pManager.AddNumberParameter("Buckling URs", "BUR", "The maximum buckling utilization ratios, one for each beam", GH_ParamAccess.tree);
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
protected override void SolveInstance(IGH_DataAccess DA)
{
var frames = new List<GH_Beam>();
double gammaM0 = 0;
double gammaM1 = 0;
//double minDeflectionFactor = 0;
//double maxDeflectionAdmitted = 0;
int lengthValue = -1;
int forceValue = -1;
//double toll;
LengthUnits lengthUnits;
ForceUnits forceUnits;
if (!DA.GetDataList(0, frames))
return;
if (!DA.GetData(1, ref gammaM0))
return;
if (!DA.GetData(2, ref gammaM1))
return;
//if (!DA.GetData("fyk", ref fyk))
// return;
//if (!DA.GetData("Min deflection factor", ref minDeflectionFactor))
// return;
//if (!DA.GetData("Max allowed deflection", ref maxDeflectionAdmitted))
// return;
if (!DA.GetData(3, ref lengthValue))
return;
if (!DA.GetData(4, ref forceValue))
return;
Dictionary<BeamModel, List<double>> ascissas, resistanceUrs, bucklingUrs;
ascissas = [];
resistanceUrs = [];
bucklingUrs = [];
lengthUnits = (LengthUnits)lengthValue;
forceUnits = (ForceUnits)forceValue;
foreach (GH_Beam beam in frames)
{
if (beam.Value.BeamProperty.Material.Kind == MaterialModel.MaterialKind.Steel)
{
double area, w11, w22, e, l0, j11, j22;
List<double> beamAscissas, beamResistanceUrs, beamBucklingUrs;
double nCr11, lambdaAdim11, nCr22, lambdaAdim22;
double chi11, chi22, chi;
BeamPropertyModel bp;
double nbRd;
double sigmaRd;
double fyk;
double angleXTo1;
//props
bp = beam.Value.BeamProperty;
area = bp.SectionArea;
w11 = bp.W11;
w22 = bp.W22;
l0 = (beam.Value.PointFrom - beam.Value.PointTo).Length;
j11 = bp.I11;
j22 = bp.I22;
angleXTo1 = beam.Value.BeamProperty.AngleX1Rad;
//Getting E,fyk in units. In material E,fyk is on N mm
UnitsConvert.ForceUnits utilsForceUnits;
UnitsConvert.LengthUnits utilsLengthUnits;
switch (forceUnits)
{
case ForceUnits.N:
utilsForceUnits = UnitsConvert.ForceUnits.N;
break;
case ForceUnits.daN:
utilsForceUnits = UnitsConvert.ForceUnits.daN;
break;
case ForceUnits.kN:
utilsForceUnits = UnitsConvert.ForceUnits.kN;
break;
case ForceUnits.lbf:
utilsForceUnits = UnitsConvert.ForceUnits.lbf;
break;
default:
throw new NotSupportedException();
}
switch (lengthUnits)
{
case LengthUnits.mm:
utilsLengthUnits = UnitsConvert.LengthUnits.mm;
break;
case LengthUnits.cm:
utilsLengthUnits = UnitsConvert.LengthUnits.cm;
break;
case LengthUnits.m:
utilsLengthUnits = UnitsConvert.LengthUnits.m;
break;
case LengthUnits.inch:
utilsLengthUnits = UnitsConvert.LengthUnits.inch;
break;
default:
throw new NotSupportedException();
}
e = UnitsConvert.ConvertFromDefaultUnits(bp.Material.Modulus, utilsForceUnits, 1, utilsLengthUnits, -2);
fyk = UnitsConvert.ConvertFromDefaultUnits(bp.Material.MinimumYieldStress, utilsForceUnits, 1, utilsLengthUnits, -2);
//e = bp.Material.Modulus;
//fyk = bp.Material.MinimumYieldStress;
//switch (forceCode)
//{
// case ForceCodes.N:
// break;
// case ForceCodes.daN:
// e /= 10d;
// fyk /= 10d;
// break;
// case ForceCodes.kN:
// e /= 1000d;
// fyk /= 1000d;
// break;
// default:
// throw new NotSupportedException();
//}
//switch (lengthCode)
//{
// case LengthCodes.mm:
// e /= Math.Pow(10d, 6d);
// fyk /= Math.Pow(10d, 6d);
// break;
// case LengthCodes.cm:
// e /= Math.Pow(10d, 4d);
// fyk /= Math.Pow(10d, 4d);
// break;
// case LengthCodes.m:
// break;
// default:
// throw new NotSupportedException();
//}
sigmaRd = fyk / gammaM0;
//buckling resistance
nCr11 = Math.PI * Math.PI * e * j11 / (l0 * l0);
lambdaAdim11 = Math.Sqrt(area * fyk / nCr11);
if (lambdaAdim11 > 0.2)
{
double alfa;
double fi;
switch (bp.SectionType)
{
case SectionModel.SectionTypes.SolidCircle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.Undefined:
alfa = 0.76;
break;
case SectionModel.SectionTypes.HollowCircle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.SolidRectangle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.HollowRectangle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.I:
if (Math.Max(bp.B1, bp.B2) * 1.2 > bp.D)
{
alfa = 0.34;
}
else
{
alfa = 0.21;
}
break;
case SectionModel.SectionTypes.T:
alfa = 0.49;
break;
case SectionModel.SectionTypes.C:
alfa = 0.49;
break;
case SectionModel.SectionTypes.Omega:
alfa = 0.76;
break;
case SectionModel.SectionTypes.Angle:
alfa = 0.34;
break;
case SectionModel.SectionTypes.Z:
alfa = 0.49;
break;
default:
throw new NotSupportedException();
}
fi = 0.5 * (1 + alfa * (lambdaAdim11 - 0.2) + lambdaAdim11 * lambdaAdim11);
chi11 = Math.Min(1, 1 / (fi + Math.Sqrt(fi * fi - lambdaAdim11 * lambdaAdim11)));
}
else
{
chi11 = 1;
}
nCr22 = Math.PI * Math.PI * e * j22 / (l0 * l0);
lambdaAdim22 = Math.Sqrt(area * fyk / nCr22);
if (lambdaAdim22 > 0.2)
{
double alfa;
double fi;
switch (bp.SectionType)
{
case SectionModel.SectionTypes.SolidCircle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.Undefined:
alfa = 0.76;
break;
case SectionModel.SectionTypes.HollowCircle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.SolidRectangle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.HollowRectangle:
alfa = 0.49;
break;
case SectionModel.SectionTypes.I:
if (Math.Max(bp.B1, bp.B2) * 1.2 > bp.D)
{
alfa = 0.49;
}
else
{
alfa = 0.34;
}
break;
case SectionModel.SectionTypes.T:
alfa = 0.49;
break;
case SectionModel.SectionTypes.C:
alfa = 0.49;
break;
case SectionModel.SectionTypes.Omega:
alfa = 0.76;
break;
case SectionModel.SectionTypes.Angle:
alfa = 0.34;
break;
case SectionModel.SectionTypes.Z:
alfa = 0.49;
break;
default:
throw new NotSupportedException();
}
fi = 0.5 * (1 + alfa * (lambdaAdim22 - 0.2) + lambdaAdim22 * lambdaAdim22);
chi22 = Math.Min(1, 1 / (fi + Math.Sqrt(fi * fi - lambdaAdim22 * lambdaAdim22)));
}
else
{
chi22 = 1;
}
chi = Math.Min(chi11, chi22);
nbRd = chi * area * fyk / gammaM1;
beamAscissas = [];
beamResistanceUrs = [];
beamBucklingUrs = [];
BeamForceResultModel[] results = [.. beam.Value.Results.
Where(r => r.GetType() == typeof(BeamForceResultModel)).Cast<BeamForceResultModel>()];
for (int resCounter = 0; resCounter < results.Length; resCounter++)
{
double n, mx, my, m1, m2, sigmaEd;
int index;
double resUr, buckUr;
n = beam.Value.Results.Cast<BeamForceResultModel>().ElementAt(resCounter).AxialForce;
mx = results[resCounter].BendingMoment.Y;//asse 3 di sap e 1 di st7
my = results[resCounter].BendingMoment.X;//asse 2 di sap e st7
//ruoto i momenti nel sdr principale
m1 = mx * Math.Cos(angleXTo1) + my * Math.Sin(angleXTo1);
m2 = -mx * Math.Sin(angleXTo1) + my * Math.Cos(angleXTo1);
//resistance
sigmaEd = Math.Abs(n / area) + Math.Abs(m1 / w11) + Math.Abs(m2 / w22);
resUr = sigmaEd / sigmaRd;
//buckling
if (n >= 0)
{
buckUr = 0;
}
else
{
buckUr = Math.Abs(n / nbRd);
}
index = beamAscissas.IndexOf(results[resCounter].Station);
if (index < 0)
{
beamAscissas.Add(results[resCounter].Station);
beamResistanceUrs.Add(resUr);
beamBucklingUrs.Add(buckUr);
}
else
{
beamResistanceUrs[index] = Math.Max(beamResistanceUrs[index], resUr);
beamBucklingUrs[index] = Math.Max(beamBucklingUrs[index], buckUr);
}
}
ascissas.Add(beam.Value, beamAscissas);
resistanceUrs.Add(beam.Value, beamResistanceUrs);
bucklingUrs.Add(beam.Value, beamBucklingUrs);
}
}
//deformation checks TODO Emanuele mancano le deformate nelle beam
//switch (lengthCode)
//{
// case LengthCodes.mm:
// toll = 0.1;
// break;
// case LengthCodes.cm:
// toll = 0.01;
// break;
// case LengthCodes.m:
// toll = 0.0001;
// break;
// default:
// throw new NotSupportedException();
//} //List<BeamResultsSequence> seqs;
//seqs = BeamResultsSequence.GetSequences(beams, toll);
List<GH_Beam> steelFrames;
steelFrames = [];
foreach (BeamModel bm in ascissas.Keys)
{
steelFrames.Add(new GH_Beam(bm));
}
DA.SetDataList(0, steelFrames);
DA.SetDataTree(1, GetStructure(ascissas));
DA.SetDataTree(2, GetStructure(resistanceUrs));
DA.SetDataTree(3, GetStructure(bucklingUrs));
}
public static GH_Structure<GH_Number> GetStructure(Dictionary<BeamModel, List<double>> dic)
{
GH_Structure<GH_Number> result;
result = new GH_Structure<GH_Number>();
int i = 0;
foreach (KeyValuePair<BeamModel, List<double>> kvp in dic)
{
GH_Path path;
List<GH_Number> bufferNum;
path = new GH_Path([i, 0]);
result.EnsurePath(path);
bufferNum = [];
foreach (double value in kvp.Value)
{
bufferNum.Add(new GH_Number(value));
}
result.AppendRange(bufferNum, path);
i++;
}
return result;
}
//public static void GetDeformationChecks(List<BeamResultsSequence> seqs,
// double minDeflectionFactor,
// Dictionary<BeamModel, List<double>> beamAscissasList,
// ref Dictionary<int, double> deformationURs)
//{ //deformation checks
// foreach (BeamResultsSequence seq in seqs)
// {
// double unCm;
// double lengthFromStart;
// List<double> bufferAscissas, bufferDisps;
// bool isStartRestrained, isEndRestrained;
// List<double> pillarPoss;
// lengthFromStart = 0;
// bufferAscissas = new List<double>();
// bufferDisps = new List<double>();
// lengthFromStart = 0;
// pillarPoss = new List<double>();
// foreach (GH_BeamResults data in seq.Sequence)
// {
// double[] beamRes;
// int numColumns = 0;
// List<double> ascissas;
// List<double> fzs;
// Point3d startP, endP;
// double dataLength;
// //start = model.Value.GetNode(data.Beam.StartNode);
// //end = model.Value.GetNode(data.Beam.EndNode);
// startP = data.Beam.PointFrom;// new Rhino.Geometry.Point3d(start.X, start.Y, start.Z);
// endP = data.Beam.PointTo; //new Rhino.Geometry.Point3d(end.X, end.Y, end.Z);
// dataLength = (startP - endP).Length;
// ascissas = beamAscissasList[data.Beam];
// for (int counter = 0; counter < ascissas.Count; counter++)
// {
// fzs.Add(beamRes[counter * numColumns + 2]);
// }
// if (seq.IsEquiverseTo(data))
// {
// for (int i = 0; i < ascissas.Count; i++)
// {
// ascissas[i] += lengthFromStart;
// }
// CreateBeamReinforcementComponent.AddPillar(model, data, lengthFromStart, data.Beam.StartNode, ref pillarPoss);
// lengthFromStart += dataLength;
// CreateBeamReinforcementComponent.AddPillar(model, data, lengthFromStart, data.Beam.EndNode, ref pillarPoss);
// }
// else
// {
// CreateBeamReinforcementComponent.AddPillar(model, data, lengthFromStart, data.Beam.EndNode, ref pillarPoss);
// lengthFromStart += dataLength;
// for (int i = ascissas.Count - 1; i >= 0; i--)
// {
// ascissas[i] = lengthFromStart - ascissas[i];
// }
// CreateBeamReinforcementComponent.AddPillar(model, data, lengthFromStart, data.Beam.StartNode, ref pillarPoss);
// fzs.Reverse();
// }
// bufferAscissas.AddRange(ascissas);
// bufferDisps.AddRange(fzs);
// }
// List<double> modifiedPillarPoss;
// pillarPoss.Sort();
// if (pillarPoss.Count == 0)
// {
// //beam sostained from other beams. Adding a restrain at start and at end
// isStartRestrained = true;
// isEndRestrained = true;
// modifiedPillarPoss = new List<double>();
// modifiedPillarPoss.Add(0);
// modifiedPillarPoss.Add(lengthFromStart);
// }
// else
// {
// unCm = CreateBeamReinforcementComponent.ConvertLengthTo(1, "cm", model.Value.LengthUnit, 1);
// isStartRestrained = Math.Abs(pillarPoss[0]) < unCm;
// isEndRestrained = Math.Abs(pillarPoss[pillarPoss.Count - 1] - lengthFromStart) < unCm;
// modifiedPillarPoss = new List<double>(pillarPoss);
// if (!isStartRestrained)
// {
// modifiedPillarPoss.Insert(0, 0);
// }
// if (!isEndRestrained)
// {
// modifiedPillarPoss.Add(lengthFromStart);
// }
// }
// for (int i = 0; i < modifiedPillarPoss.Count - 1; i++)
// {
// bool bufferIsStartRestrained, bufferIsEndRestrained;
// List<double> ascissas;
// List<double> fzs;
// double prevPillar, nextPillar;
// if ((i == 0) && (!isStartRestrained))
// {
// bufferIsStartRestrained = false;
// }
// else
// {
// bufferIsStartRestrained = true;
// }
// if ((i == pillarPoss.Count - 2) && (!isEndRestrained))
// {
// bufferIsEndRestrained = false;
// }
// else
// {
// bufferIsEndRestrained = true;
// }
// prevPillar = modifiedPillarPoss[i];
// nextPillar = modifiedPillarPoss[i + 1];
// ascissas = new List<double>();
// fzs = new List<double>();
// for (int index = 0; index < bufferAscissas.Count; index++)
// {
// if ((bufferAscissas[index] >= prevPillar) &&
// (bufferAscissas[index] <= nextPillar))
// {
// //inside pillars
// ascissas.Add(bufferAscissas[index]);
// fzs.Add(bufferDisps[index]);
// }
// }
// if (ascissas.Count > 0)
// {
// double maxDz;
// double length;
// double lengthCm;
// maxDz = 0;
// length = nextPillar - prevPillar;
// lengthCm = CreateBeamReinforcementComponent.ConvertLengthTo(length, model.Value.LengthUnit, "cm", 1);
// if (lengthCm > 100)
// {
// if (!bufferIsStartRestrained)
// {
// //cantilever start. Net displacement depure at end
// foreach (double dispZ in fzs)
// {
// maxDz = Math.Max(maxDz, Math.Abs(dispZ - fzs[fzs.Count - 1]));
// }
// length *= 2;
// }
// else if (!bufferIsEndRestrained)
// {
// //cantilever end. Net displacement depure at start
// foreach (double dispZ in fzs)
// {
// maxDz = Math.Max(maxDz, Math.Abs(dispZ - fzs[0]));
// }
// length *= 2;
// }
// else
// {
// double firstDisp, lastDisp;
// //simply supported beam
// firstDisp = fzs[0];
// lastDisp = fzs[fzs.Count - 1];
// for (int index = 0; index < ascissas.Count; index++)
// {
// double rigidDisp;
// rigidDisp = fzs[0] + (fzs[fzs.Count - 1] - fzs[0]) / length * (ascissas[index] - ascissas[0]);
// maxDz = Math.Max(maxDz, Math.Abs(fzs[index] - rigidDisp));
// }
// }
// double ur;
// double limitDeflection;
// limitDeflection = length / minDeflectionFactor;
// ur = maxDz / limitDeflection;
// foreach (CreateBeamReinforcementComponent.BeamData data in seq.Sequence)
// {
// deformationURs[data.Beam.Id] = Math.Max(deformationURs[data.Beam.Id], ur);
// }
// }
// }
// }
// }
//}
public override GH_Exposure Exposure => GH_Exposure.tertiary;
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.SteelBeamChecksIcon;
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid => new("07DE430A-7B39-4500-9A3E-42A819385BE2");
}
}