diff --git a/DocsGeneration/Setup/GrasshopperFixture.cs b/DocsGeneration/Setup/GrasshopperFixture.cs index 7532e5eaa..0562832fb 100644 --- a/DocsGeneration/Setup/GrasshopperFixture.cs +++ b/DocsGeneration/Setup/GrasshopperFixture.cs @@ -60,7 +60,7 @@ public GrasshopperFixture() { InitializeCore(); - Utility.SetupUnitsDuringLoad(); + OasysGH.Units.Utility.SetupUnitsDuringLoad(); } public void AddPluginToGh() { diff --git a/GsaGH/Components/4_Analysis/CreateModalDynamicParameter.cs b/GsaGH/Components/4_Analysis/CreateModalDynamicParameter.cs index 9c5edfdfb..65ef491b7 100644 --- a/GsaGH/Components/4_Analysis/CreateModalDynamicParameter.cs +++ b/GsaGH/Components/4_Analysis/CreateModalDynamicParameter.cs @@ -16,6 +16,9 @@ using System.Linq; using Grasshopper.Kernel.Parameters; +using Rhino.PlugIns; +using Grasshopper; +using GsaGH.Helpers; namespace GsaGH.Components { /// @@ -114,11 +117,71 @@ protected override void SolveInternal(IGH_DataAccess da) { double? dampingStiffness = taskParameter.ModalDamping.StiffnessProportion; da.GetData(index, ref dampingStiffness); - taskParameter.ModalDamping = new ModalDamping(dampingStiffness); + taskParameter.ModalDamping = new ModalDamping(dampingStiffness); + if (!ValidateMassParticipation(taskParameter)) { + return; + } da.SetData(0, new GsaModalDynamicGoo(taskParameter)); } + + private bool ValidateMassParticipation(GsaModalDynamic parameter) { + bool validationStatus = true; + switch (parameter.Method()) { + case ModeCalculationMethod.NumberOfMode: { + var method = parameter.ModeCalculationStrategy as ModeCalculationStrategyByNumberOfModes; + if (method.NumberOfModes < 1) { + this.AddRuntimeError("Number of mode should be greater than 1"); + validationStatus = false; + } + } + break; + case ModeCalculationMethod.FrquencyRange: { + var method = parameter.ModeCalculationStrategy as ModeCalculationStrategyByFrequency; + double higherFrequency = method.HigherFrequency ?? double.MaxValue; + if (method.LowerFrequency.HasValue && (!GsaGH.Helpers.Utility.IsInRange + (method.LowerFrequency.Value, 0, higherFrequency) || GsaGH.Helpers.Utility.IsApproxEqual(method.LowerFrequency.Value, higherFrequency))) { + this.AddRuntimeError("Lower frquency should be positive value and less than higher frquency"); + validationStatus = false; + } + double lowerFrequency = method.LowerFrequency ?? 0; + if (method.HigherFrequency.HasValue && (!GsaGH.Helpers.Utility.IsInRange + (method.HigherFrequency.Value, lowerFrequency, method.HigherFrequency.Value) || GsaGH.Helpers.Utility.IsApproxEqual(method.HigherFrequency.Value, lowerFrequency))) { + this.AddRuntimeError("Upper frquency should be positive value and greater than lower frquency"); + validationStatus = false; + } + + } + break; + case ModeCalculationMethod.TargetMassRatio: { + var method = parameter.ModeCalculationStrategy as ModeCalculationStrategyByMassParticipation; + if (!GsaGH.Helpers.Utility.IsInRange(method.TargetMassInXDirection, 0, 100) || !GsaGH.Helpers.Utility.IsInRange(method.TargetMassInYDirection, 0, 100) || !GsaGH.Helpers.Utility.IsInRange(method.TargetMassInZDirection, 0, 100)) { + this.AddRuntimeError("Target Mass participation ratio should be within the range of [0:100]"); + validationStatus = false; + } + } + break; + } + + double? dampingStiffness = parameter.ModalDamping.StiffnessProportion; + if (dampingStiffness.HasValue && !GsaGH.Helpers.Utility.IsInRange(dampingStiffness.Value, 0, 1)) { + this.AddRuntimeError("Damping stiffness should be within the range [0:1]"); + validationStatus = false; + } + + if (parameter.AdditionalMassDerivedFromLoads.ScaleFactor < 0) { + this.AddRuntimeError("Load scale factor should have positive value"); + validationStatus = false; + } + + if (parameter.MassOption.ScaleFactor < 0) { + this.AddRuntimeError("Mass scale factor should have positive value"); + validationStatus = false; + } + return validationStatus; + } + public override void SetSelected(int i, int j) { _selectedItems[i] = _dropDownItems[i][j]; diff --git a/GsaGH/Helpers/Utility.cs b/GsaGH/Helpers/Utility.cs new file mode 100644 index 000000000..b13eab6fc --- /dev/null +++ b/GsaGH/Helpers/Utility.cs @@ -0,0 +1,16 @@ + +using System; + +namespace GsaGH.Helpers { + public static class Utility { + public static bool IsInRange(double value, double min, double max) { + float epsilon = 10e-12f; + return value <= max + epsilon && value >= min - epsilon; + } + + public static bool IsApproxEqual(double value1, double value2) { + float epsilon = 10e-12f; + return Math.Abs(value1 - value2) < epsilon; + } + } +} diff --git a/GsaGHTests/3_Components/4_Analysis/CreateModalDynamicParameterTests.cs b/GsaGHTests/3_Components/4_Analysis/CreateModalDynamicParameterTests.cs index 99da686e8..05ca1f3f3 100644 --- a/GsaGHTests/3_Components/4_Analysis/CreateModalDynamicParameterTests.cs +++ b/GsaGHTests/3_Components/4_Analysis/CreateModalDynamicParameterTests.cs @@ -1,5 +1,6 @@ using System.Linq; +using Grasshopper.Kernel; using Grasshopper.Kernel.Types; using GsaAPI; @@ -29,8 +30,23 @@ public CreateModalDynamicParameterByNumberOfModesTests(ModalMassOption massOptio private void PrepareComponent(ModalMassOption massOption, Direction direction) { _component = ComponentMother(massOption, direction); var _modalDynamicAnalysisGoo = (GsaModalDynamicGoo)ComponentTestHelper.GetOutput(_component); - _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; - _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByNumberOfModes; + if (_modalDynamicAnalysisGoo != null) { + _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; + _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByNumberOfModes; + } + } + + private void SetNumberOfMode(double value) { + ComponentTestHelper.SetInput(_component, value, 0); + } + + private void SetStiffness(double value) { + ComponentTestHelper.SetInput(_component, value, 4); + } + + private void SetScaleFactor(double loadScaleFactor, double massScalefactor) { + ComponentTestHelper.SetInput(_component, loadScaleFactor, 2); + ComponentTestHelper.SetInput(_component, massScalefactor, 3); } public static GH_OasysComponent ComponentMother(ModalMassOption massOption, Direction direction) { @@ -42,7 +58,7 @@ public static GH_OasysComponent ComponentMother(ModalMassOption massOption, Dire ComponentTestHelper.SetInput(comp, "L1", index++); ComponentTestHelper.SetInput(comp, 1.1, index++); ComponentTestHelper.SetInput(comp, 1.2, index++); - ComponentTestHelper.SetInput(comp, 1.3, index); + ComponentTestHelper.SetInput(comp, 1, index); switch (massOption) { case ModalMassOption.LumpMassAtNode: @@ -79,6 +95,27 @@ public void ComponentShouldReturnCorrectNumberOfMode() { Assert.Equal(5, _modeCalculationStrategy.NumberOfModes); } + [Fact] + public void ComponentShouldReportErrorWhenNumberOfModeIsNegativeValue() { + SetNumberOfMode(-1); + ComponentTestHelper.ComputeOutput(_component); + Assert.Single(_component.RuntimeMessages(GH_RuntimeMessageLevel.Error)); + } + + [Fact] + public void ComponentShouldReportErrorWhenStiffnessIsNotInRange() { + SetStiffness(2); + ComponentTestHelper.ComputeOutput(_component); + Assert.Single(_component.RuntimeMessages(GH_RuntimeMessageLevel.Error)); + } + + [Fact] + public void ComponentShouldReportErrorWhenScaleFactorsAreNegative() { + SetScaleFactor(-1,-2); + ComponentTestHelper.ComputeOutput(_component); + Assert.Equal(2,_component.RuntimeMessages(GH_RuntimeMessageLevel.Error).Count); + } + [Fact] public void ComponentShouldReturnCorrectCaseDefinition() { Assert.Equal("L1", _modalDynamicAnalysis.AdditionalMassDerivedFromLoads.CaseDefinition); @@ -96,7 +133,7 @@ public void ComponentShouldReturnCorrectMassScaleFactor() { [Fact] public void ComponentShouldReturnCorrectStiffnessProportion() { - Assert.Equal(1.3, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); + Assert.Equal(1, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); } [Fact] @@ -156,11 +193,18 @@ public CreateModalDynamicParameterByFrquencyRangeTest(ModalMassOption massOption private void PrepareComponent(ModalMassOption massOption, Direction direction) { _component = ComponentMother(massOption, direction); var _modalDynamicAnalysisGoo = (GsaModalDynamicGoo)ComponentTestHelper.GetOutput(_component); - _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; - _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByFrequency; + if (_modalDynamicAnalysisGoo != null) { + _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; + _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByFrequency; + } } - public static GH_OasysComponent ComponentMother(ModalMassOption massOption= ModalMassOption.LumpMassAtNode, Direction direction= Direction.Y) { + private void SetFrequency(double lower, double upper) { + ComponentTestHelper.SetInput(_component, lower, 0); + ComponentTestHelper.SetInput(_component, upper, 1); + } + + public static GH_OasysComponent ComponentMother(ModalMassOption massOption = ModalMassOption.LumpMassAtNode, Direction direction = Direction.Y) { var comp = new CreateModalDynamicParameter(); comp.CreateAttributes(); comp.SetSelected(0, 1); @@ -171,7 +215,7 @@ public static GH_OasysComponent ComponentMother(ModalMassOption massOption= Moda ComponentTestHelper.SetInput(comp, "L1", index++); ComponentTestHelper.SetInput(comp, 1.1, index++); ComponentTestHelper.SetInput(comp, 1.2, index++); - ComponentTestHelper.SetInput(comp, 1.3, index); + ComponentTestHelper.SetInput(comp, 1, index); switch (massOption) { case ModalMassOption.LumpMassAtNode: @@ -213,6 +257,13 @@ public void ComponentShouldReturnCorrectUpperFrequency() { Assert.Equal(10, _modeCalculationStrategy.HigherFrequency); } + [Fact] + public void ComponentShouldReportErrorFrequenciesAreNotCorrect() { + SetFrequency(6, 5); + ComponentTestHelper.ComputeOutput(_component); + Assert.Equal(2, _component.RuntimeMessages(GH_RuntimeMessageLevel.Error).Count); + } + [Fact] public void ComponentShouldReturnCorrectLowerFrequency() { Assert.Equal(5, _modeCalculationStrategy.LowerFrequency); @@ -235,7 +286,7 @@ public void ComponentShouldReturnCorrectMassScaleFactor() { [Fact] public void ComponentShouldReturnCorrectStiffnessProportion() { - Assert.Equal(1.3, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); + Assert.Equal(1, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); } [Fact] @@ -295,8 +346,10 @@ public CreateModalDynamicParameterByTargetMassParticipationTest(ModalMassOption private void PrepareComponent(ModalMassOption massOption, Direction direction) { _component = ComponentMother(massOption, direction); var _modalDynamicAnalysisGoo = (GsaModalDynamicGoo)ComponentTestHelper.GetOutput(_component); - _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; - _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByMassParticipation; + if (_modalDynamicAnalysisGoo != null) { + _modalDynamicAnalysis = _modalDynamicAnalysisGoo.Value; + _modeCalculationStrategy = _modalDynamicAnalysis.ModeCalculationStrategy as ModeCalculationStrategyByMassParticipation; + } } public static GH_OasysComponent ComponentMother(ModalMassOption massOption, Direction direction) { @@ -312,7 +365,7 @@ public static GH_OasysComponent ComponentMother(ModalMassOption massOption, Dire ComponentTestHelper.SetInput(comp, "L1", index++); ComponentTestHelper.SetInput(comp, 1.1, index++); ComponentTestHelper.SetInput(comp, 1.2, index++); - ComponentTestHelper.SetInput(comp, 1.3, index); + ComponentTestHelper.SetInput(comp, 1, index); switch (massOption) { case ModalMassOption.LumpMassAtNode: @@ -386,7 +439,7 @@ public void ComponentShouldReturnCorrectMassScaleFactor() { [Fact] public void ComponentShouldReturnCorrectStiffnessProportion() { - Assert.Equal(1.3, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); + Assert.Equal(1, _modalDynamicAnalysis.ModalDamping.StiffnessProportion); } [Fact] diff --git a/GsaGHTests/GrasshopperFixture.cs b/GsaGHTests/GrasshopperFixture.cs index 03ff6f2e4..d6c7d4f07 100644 --- a/GsaGHTests/GrasshopperFixture.cs +++ b/GsaGHTests/GrasshopperFixture.cs @@ -62,7 +62,7 @@ public GrasshopperFixture() { InitializeCore(); - Utility.SetupUnitsDuringLoad(); + OasysGH.Units.Utility.SetupUnitsDuringLoad(); } public void AddPluginToGh() { diff --git a/IntegrationTests/GrasshopperFixture.cs b/IntegrationTests/GrasshopperFixture.cs index b79691825..36c6a4241 100644 --- a/IntegrationTests/GrasshopperFixture.cs +++ b/IntegrationTests/GrasshopperFixture.cs @@ -68,7 +68,7 @@ public GrasshopperFixture() { InitializeCore(); // setup headless units - Utility.SetupUnitsDuringLoad(); + OasysGH.Units.Utility.SetupUnitsDuringLoad(); } // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources