private static bool Add1dLoadsWithAppId(string entityKeyword, string loadCaseKeyword, IEnumerable <GsaLoadBeamUdl> gsaLoads, ref List <Structural1DLoad> structural1DLoads)
        {
            var gsaGroups = gsaLoads.GroupBy(gl => new { ApplicationId = gl.ApplicationId.Substring(0, gl.ApplicationId.IndexOf("_")), gl.LoadCaseIndex });

            foreach (var group in gsaGroups)
            {
                var gList = group.ToList();

                var applicationId = gList[0].ApplicationId.Substring(0, gList[0].ApplicationId.IndexOf("_"));
                var name          = (gList.Any(gl => !string.IsNullOrEmpty(gl.Name))) ? gList.FirstOrDefault(gl => !string.IsNullOrEmpty(gl.Name)).Name : "";

                //Assume the element refs are the same for those with application IDs - so just take the indices of the first record and resolve them to application IDs for entities
                var elementRefs = gList[0].Entities.Select(ei => Initialiser.AppResources.Cache.GetApplicationId(entityKeyword, ei)).Where(aid => !string.IsNullOrEmpty(aid)).ToList();
                var loadCaseRef = Initialiser.AppResources.Cache.GetApplicationId(loadCaseKeyword, gList[0].LoadCaseIndex.Value);

                var loadings        = gList.Select(gl => Helper.GsaLoadToLoading(gl.LoadDirection, gl.Load.Value)).ToList();
                var combinedLoading = new StructuralVectorSix(Enumerable.Range(0, 6).Select(i => loadings.Sum(l => l.Value[i])));

                var load = new Structural1DLoad()
                {
                    ApplicationId = applicationId,
                    Name          = name,
                    ElementRefs   = elementRefs,
                    LoadCaseRef   = loadCaseRef,
                    Loading       = combinedLoading
                };
                structural1DLoads.Add(load);
            }
            return(true);
        }
        private static bool Add1dLoadsWithoutAppId(string keyword, string axisKeyword, string entityKeyword, string loadCaseKeyword, IEnumerable <GsaLoadBeamUdl> gsaLoads, ref List <Structural1DLoad> structural1DLoads)
        {
            var gsaGroups = gsaLoads.GroupBy(gl => gl.LoadCaseIndex).Select(g => g.OfType <GsaLoadBeamUdl>().ToList()).ToList();

            foreach (var gsaGroup in gsaGroups)
            {
                //This is the group which might have axes, so if this is true, then they need to be transformed
                var transformedGsaLoads  = new List <StructuralVectorSix>();
                var uniqueLoadings       = new List <StructuralVectorSix>();
                var uniqueToLoadingsList = new Dictionary <int, List <int> >();

                var glByIndex = gsaGroup.Where(gl => gl.Index.HasValue).ToDictionary(gl => gl.Index.Value, gl => gl);

                foreach (var gl in gsaGroup)
                {
                    if (!gl.Index.HasValue || gl.Index == 0)
                    {
                        continue;
                    }

                    var loading = Helper.GsaLoadToLoading(gl.LoadDirection, gl.Load.Value);
                    if (gl.AxisRefType == LoadBeamAxisRefType.Reference && gl.AxisIndex.HasValue && gl.AxisIndex.Value > 0)
                    {
                        var axisGwa = Initialiser.AppResources.Cache.GetGwa(axisKeyword, gl.AxisIndex.Value);
                        if (axisGwa != null && axisGwa.Count() > 0 && string.IsNullOrEmpty(axisGwa.First()))
                        {
                            return(false);
                        }
                        var gsaAxis = new GsaAxis();
                        gsaAxis.FromGwa(axisGwa.First());
                        var loadAxis = (StructuralAxis)gsaAxis.ToSpeckle();
                        //Converts from loads on an axis to their global equivalent
                        loading.TransformOntoAxis(loadAxis);
                    }

                    int uniqueLoadingIndex;
                    if (loading != null)
                    {
                        var matching = uniqueLoadings.Where(k => k.Value.SequenceEqual(loading.Value));
                        if (matching.Count() > 0)
                        {
                            uniqueLoadingIndex = uniqueLoadings.IndexOf(matching.First());
                        }
                        else
                        {
                            uniqueLoadingIndex = uniqueLoadings.Count();
                            uniqueLoadings.Add(loading);
                        }
                        if (!uniqueToLoadingsList.ContainsKey(uniqueLoadingIndex))
                        {
                            uniqueToLoadingsList.Add(uniqueLoadingIndex, new List <int>());
                        }
                        uniqueToLoadingsList[uniqueLoadingIndex].Add(gl.Index.Value);
                    }
                }

                foreach (var ul in uniqueToLoadingsList.Keys)
                {
                    var entityIndices = uniqueToLoadingsList[ul].SelectMany(ei => glByIndex[ei].Entities).Distinct().OrderBy(n => n).ToList();
                    var elementRefs   = entityIndices.Select(ei => Initialiser.AppResources.Cache.GetApplicationId(entityKeyword, ei)).Where(aid => !string.IsNullOrEmpty(aid)).ToList();
                    var loadCaseRef   = (gsaGroup.First().LoadCaseIndex.HasValue) ? Initialiser.AppResources.Cache.GetApplicationId(loadCaseKeyword, gsaGroup.First().LoadCaseIndex.Value) : null;
                    var load          = new Structural1DLoad()
                    {
                        ApplicationId = SpeckleStructuralGSA.Helper.FormatApplicationId(keyword, uniqueToLoadingsList[ul]),
                        Name          = gsaGroup.First().Name,
                        ElementRefs   = elementRefs,
                        LoadCaseRef   = loadCaseRef,
                        Loading       = uniqueLoadings[ul]
                    };
                    structural1DLoads.Add(load);
                }
            }

            return(true);
        }
        private static bool Add0dLoadsWithoutAppId(string keyword, string nodeKeyword, string loadCaseKeyword, IEnumerable <GsaLoadNode> gsaLoads,
                                                   List <GSANode> gsaNodes, ref List <Structural0DLoad> structural0DLoads, ref List <int> nodeIndicesReferenced)
        {
            var summaries      = new List <D0LoadingSummary>();
            var uniqueLoadings = new List <StructuralVectorSix>();

            foreach (var gl in gsaLoads.Where(l => l.Value != null))
            {
                var relevantGsaNodes = gsaNodes.Where(n => gl.NodeIndices.Any(ni => ni == n.GSAId)).ToList();
                foreach (var n in relevantGsaNodes)
                {
                    var loading            = Helper.GsaLoadToLoading(gl.LoadDirection, gl.Value.Value);
                    int?uniqueLoadingIndex = null;
                    if (!gl.GlobalAxis)
                    {
                        var loadAxis = (StructuralAxis)SpeckleStructuralGSA.Helper.Parse0DAxis(gl.AxisIndex.Value, out string _, n.Value.Value.ToArray());
                        if (!Helper.IsZeroAxis(loadAxis))
                        {
                            //Converts from loads on an axis to their global equivalent
                            loading.TransformOntoAxis(loadAxis);
                        }
                    }
                    if (loading != null)
                    {
                        var matching = uniqueLoadings.Where(k => k.Value.SequenceEqual(loading.Value));
                        if (matching.Count() > 0)
                        {
                            uniqueLoadingIndex = uniqueLoadings.IndexOf(matching.First());
                        }
                        else
                        {
                            uniqueLoadingIndex = uniqueLoadings.Count();
                            uniqueLoadings.Add(loading);
                        }
                    }

                    summaries.Add(new D0LoadingSummary(gl.Index.Value, gl.LoadCaseIndex, n.GSAId)
                    {
                        UniqueLoadingIndex = uniqueLoadingIndex, Name = gl.Name
                    });
                }
            }

            var groups = summaries.GroupBy(s => new { s.LoadCaseIndex, s.UniqueLoadingIndex });

            var allNodeIndices = nodeIndicesReferenced.ToList();

            foreach (var group in groups)
            {
                var indices     = group.Select(i => i.Index).Distinct().ToList();
                var nodeIndices = group.Select(i => i.NodeIndex).Where(i => i != null).Distinct().ToList();
                allNodeIndices.AddRange(nodeIndices.Where(ni => ni.HasValue && !allNodeIndices.Contains(ni.Value)).Select(ni => ni.Value));
                var nodeRefs      = nodeIndices.Select(ni => SpeckleStructuralGSA.Helper.GetApplicationId(nodeKeyword, ni.Value)).OrderBy(r => r).ToList();
                var loadCaseRef   = SpeckleStructuralGSA.Helper.GetApplicationId(loadCaseKeyword, group.First().LoadCaseIndex.Value);
                var applicationId = SpeckleStructuralGSA.Helper.FormatApplicationId(keyword, indices);
                var name          = string.Join("-", group.Where(i => !string.IsNullOrEmpty(i.Name)).Select(i => i.Name));
                var loading       = uniqueLoadings[group.First().UniqueLoadingIndex.Value];
                var obj           = new Structural0DLoad()
                {
                    ApplicationId = applicationId, Loading = loading, NodeRefs = nodeRefs, LoadCaseRef = loadCaseRef
                };
                if (!string.IsNullOrEmpty(name))
                {
                    obj.Name = name;
                }
                Helper.AddCustomStructuralProperty(obj, indices.Count() == 1 ? "NativeId" : "NativeIds",
                                                   indices.Count() == 1 ? (object)indices.First().ToString() : indices.Select(i => i.ToString()).ToList());
                structural0DLoads.Add(obj);
            }

            nodeIndicesReferenced = allNodeIndices;
            return(true);
        }
        private static bool Add0dLoadsWithAppId(string nodeKeyword, string loadCaseKeyword, IEnumerable <GsaLoadNode> gsaLoads,
                                                List <GSANode> gsaNodes, ref List <Structural0DLoad> structural0DLoads, ref List <int> nodeIndicesReferenced)
        {
            var summaries = new List <D0LoadingSummary>();

            //All loads here have an application ID and axis is set to GLOBAL
            foreach (var gl in gsaLoads)
            {
                //Assume an underscore is the end of the original Application ID of the Speckle object that created up to 6 rows of 0D loads
                var appId            = gl.ApplicationId.Substring(0, gl.ApplicationId.IndexOf("_"));
                var relevantGsaNodes = gsaNodes.Where(n => gl.NodeIndices.Any(ni => ni == n.GSAId)).ToList();
                foreach (var n in relevantGsaNodes)
                {
                    summaries.Add(new D0LoadingSummary(gl.Index.Value, gl.LoadCaseIndex, n.GSAId)
                    {
                        ApplicationId = appId
                    });
                }
            }

            var groups = summaries.GroupBy(s => new { s.LoadCaseIndex, s.ApplicationId });

            var allNodeIndices = nodeIndicesReferenced.ToList();

            foreach (var group in groups)
            {
                var indices     = group.Select(i => i.Index).Distinct().ToList();
                var nodeIndices = group.Select(i => i.NodeIndex).Where(i => i != null).Distinct().ToList();
                allNodeIndices.AddRange(nodeIndices.Where(ni => ni.HasValue && !allNodeIndices.Contains(ni.Value)).Select(ni => ni.Value));
                var nodeRefs        = nodeIndices.Select(ni => SpeckleStructuralGSA.Helper.GetApplicationId(nodeKeyword, ni.Value)).OrderBy(r => r).ToList();
                var loadCaseRef     = SpeckleStructuralGSA.Helper.GetApplicationId(loadCaseKeyword, group.First().LoadCaseIndex.Value);
                var applicationId   = group.First().ApplicationId;
                var name            = string.Join("-", group.Where(i => !string.IsNullOrEmpty(i.Name)).Select(i => i.Name));
                var loadings        = indices.Select(i => gsaLoads.First(l => l.Index == i)).Select(gl => Helper.GsaLoadToLoading(gl.LoadDirection, gl.Value.Value)).ToList();
                var combinedLoading = new StructuralVectorSix(Enumerable.Range(0, 6).Select(i => loadings.Sum(l => l.Value[i])));
                var obj             = new Structural0DLoad()
                {
                    ApplicationId = applicationId, Loading = combinedLoading, NodeRefs = nodeRefs, LoadCaseRef = loadCaseRef
                };
                if (!string.IsNullOrEmpty(name))
                {
                    obj.Name = name;
                }
                Helper.AddCustomStructuralProperty(obj, indices.Count() == 1 ? "NativeId" : "NativeIds",
                                                   indices.Count() == 1 ? (object)indices.First().ToString() : indices.Select(i => i.ToString()).ToList());
                structural0DLoads.Add(obj);
            }

            nodeIndicesReferenced = allNodeIndices;

            return(true);
        }