using FeMM.Common.Helpers;
using FeMM.Common.Models;
using FeMM.Grasshopper.Components.Parameters;
using FeMM.Grasshopper.DataTypes.FeMM;
using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using Grasshopper.Kernel.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Versioning;
namespace FeMM.Grasshopper.Components.Models
{
#if NETCOREAPP
[SupportedOSPlatform("windows")]
#endif
public class BuildModelComponent : GH_Component
{
/// <summary>
/// Initializes a new instance of the BuildModelComponent class.
/// </summary>
public BuildModelComponent()
: base("Build Model", "BM", "Build the FEM model", CategoryNameConstants.CATEGORY_FEMM, CategoryNameConstants.SUBCATEGORY_MODEL)
{
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Elements", "E", "The model elements", GH_ParamAccess.list);
pManager.AddTextParameter("Name", "N", "The name of the model", GH_ParamAccess.item, "");
pManager.AddIntegerParameter("Units", "U", "The measure units", GH_ParamAccess.item, 2);
Param_Integer type_param = (Param_Integer)pManager[2];
Array names = Enum.GetValues(typeof(ModelModel.ModelUnits));
foreach (ModelModel.ModelUnits name in names)
type_param.AddNamedValue(name.GetDescription(), (int)name);
int i = pManager.AddGenericParameter("Cases/Combinations", "LCB", "The load cases and combinations list", GH_ParamAccess.list);
pManager[i].Optional = true;
pManager.AddGenericParameter("Functions/Definitions", "FD", "The analysis functions and definitions", GH_ParamAccess.list);
pManager[pManager.ParamCount - 1].Optional = true;
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Model", "M", "The FEM model", GH_ParamAccess.item);
}
/// <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)
{
try
{
var elements = new List<IGH_GeometricGoo>();
string name = "";
int units = 0;
var objs = new List<object>();
var functions = new List<GH_FunctionDefinition>();
if (!DA.GetDataList(0, elements))
return;
DA.GetData(1, ref name);
if (!DA.GetData(2, ref units))
return;
bool hasCombo = DA.GetDataList(3, objs);
bool hasFunction = DA.GetDataList(4, functions);
var inputCases = new List<CaseModel>();
for (int i = 0; i < objs.Count; i++)
{
if (objs[i] is GH_Case gH_Case)
{
if (gH_Case.Value is StagedConstructionCombinationModel stagedConstructionModel)
inputCases.Add(stagedConstructionModel);
else if (gH_Case.Value is StageConstructionLoadCaseModel stageConstructionLoadCaseModel)
inputCases.Add(stageConstructionLoadCaseModel);
else if (gH_Case.Value is LoadCaseModel loadCaseModel)
inputCases.Add(loadCaseModel);
else if (gH_Case.Value is LoadCaseLinearStaticSAPModel loadCaseLinearStaticSAPModel)
inputCases.Add(loadCaseLinearStaticSAPModel);
else if (gH_Case.Value is LoadCaseResponseSpectrumModel loadCaseResponseSpectrumModel)
inputCases.Add(loadCaseResponseSpectrumModel);
else if (gH_Case.Value is FreedomCaseModel freedomCaseModel)
inputCases.Add(freedomCaseModel);
else if (gH_Case.Value is ModalEigenModel modalEigenModel)
inputCases.Add(modalEigenModel);
else if (gH_Case.Value is ModalRitzModel modalRitzModel)
inputCases.Add(modalRitzModel);
}
else if (objs[i] is GH_Combination gH_Combination)
{
if (gH_Combination.Value is FreedomCaseCombinationModel freedomCaseCombinationModel)
inputCases.Add(freedomCaseCombinationModel);
else if (gH_Combination.Value is LoadCaseCombinationModel loadCaseCombinationModel)
inputCases.Add(loadCaseCombinationModel);
}
}
var cases = new List<CaseModel>();
Helpers.ModelHelper.ParseElements(elements, out List<GH_Node> nodes, out List<GH_Beam> beams, out List<GH_Plate> plates, out List<GH_Link> links);
Helpers.ModelHelper.GetCases(nodes, beams, plates, out List<CaseModel> loadCases);
Common.Helpers.CommonModelHelper.GetStagedConstructionConstructionModel(inputCases, out List<StagedConstructionCombinationModel> stagedConstr);
Common.Helpers.CommonModelHelper.GetStagedModelModel([.. functions.Select(i => i.Value)], out List<StagedModel> stagedModels);
Common.Helpers.CommonModelHelper.GetStageConstructionLoadCaseModel(inputCases, out List<StageConstructionLoadCaseModel> stageConstructionLoadCaseModels);
Common.Helpers.CommonModelHelper.GetLoadCombinations(inputCases, out List<LoadCaseCombinationModel> loadComb);
Common.Helpers.CommonModelHelper.GetLoadCaseLinearStaticSAPModel(inputCases, out List<LoadCaseLinearStaticSAPModel> lcls);
Common.Helpers.CommonModelHelper.GetLoadCaseResponseSpectrumModel(inputCases, out List<LoadCaseResponseSpectrumModel> lclm);
var cccase = new List<CaseModel>();
for (int i = 0; i < inputCases.Count; i++)
{
if (inputCases[i] is ModalEigenModel modalEigenModel)
cccase.Add(modalEigenModel);
else if (inputCases[i] is ModalRitzModel modalRitzModel)
cccase.Add(modalRitzModel);
}
List<FreedomCaseModel> freedomCases = Helpers.ModelHelper.GetFreedomCases(nodes, beams, plates, inputCases);
cases.AddRange(loadCases);
cases.AddRange(freedomCases);
cases.AddRange(loadComb);
cases.AddRange(lcls);
cases.AddRange(lclm);
cases.AddRange(cccase);
if (hasCombo)
{
// Check the load cases names if the combinatoin is provided
var cc = cases.Where(j => j != null).Where(i => i.GetType() == typeof(LoadCaseCombinationModel)).ToArray();
if (cc.Length > 0)
{
LoadCaseCombinationModel[] cmbs = [.. cc.Where(i => i is LoadCaseCombinationModel).Select(i => (LoadCaseCombinationModel)i)];
var lcases = cmbs.SelectMany(c => c.Values.Keys).Select(lc => lc).Distinct().ToArray();
if (lcases.Length > 0)
{
for (int i = 0; i < lcases.Length; i++)
{
string lcase = lcases[i].Name;
if (!cases.Any(lc => lc.Name == lcase) && lcases[i].GetType() != typeof(StageConstructionLoadCaseModel) && lcases[i].GetType() != typeof(LoadCaseCombinationModel)
&& lcases[i].GetType() != typeof(FreedomCaseModel))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"The load case {lcase} don't have associated load.");
cases.Add(lcases[i]);
}
}
}
}
var fcc = cases.Where(j => j != null).Where(i => i.GetType() == typeof(FreedomCaseCombinationModel)).ToArray();
if (fcc.Length > 0)
{
FreedomCaseCombinationModel[] cmbs = [.. cc.Where(i => i is FreedomCaseCombinationModel).Select(i => (FreedomCaseCombinationModel)i)];
CaseModel[] lcases = [.. cmbs.SelectMany(c => c.Values.Keys).Select(lc => lc).Distinct()];
if (lcases.Length > 0)
{
for (int i = 0; i < lcases.Length; i++)
{
string lcase = lcases[i].Name;
if (!cases.Any(lc => lc.Name == lcase))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $"The load case {lcase} don't have associated load.");
cases.Add(lcases[i]);
}
}
}
}
}
cases.AddRange(stagedConstr);
cases.AddRange(stageConstructionLoadCaseModels);
// Connect the LoadCombinationsComponent
IGH_Param[] combinations_params = [.. Params.Input[3].Sources.Where(s => s.GetType() == typeof(LoadCombinationsParam))];
for (int i = 0; i < combinations_params.Length; i++)
{
LoadCombinationsParam param = (LoadCombinationsParam)combinations_params[i];
param.UpdateLoadCases(cases);
}
var model = new GH_Model((ModelModel.ModelUnits)units, nodes, beams, plates, links, cases, [.. functions.Select(i => i.Value)]);
model.Value.Name = name;
Message = ((ModelModel.ModelUnits)units).GetDescription();
DA.SetData(0, model);
}
catch (Exception e)
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message);
}
}
public override GH_Exposure Exposure => GH_Exposure.tertiary;
/// <summary>
/// Provides an Icon for the component.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.BuildModelIcon;
/// <summary>
/// Gets the unique ID for this component. Do not change this ID after release.
/// </summary>
public override Guid ComponentGuid => new("c3c8837b-57fa-4fdc-8b99-849bfe468232");
}
}