diff --git a/RFEM/Imperfections/imperfectionCase.py b/RFEM/Imperfections/imperfectionCase.py index 4bb76677..f14d2925 100644 --- a/RFEM/Imperfections/imperfectionCase.py +++ b/RFEM/Imperfections/imperfectionCase.py @@ -3,7 +3,7 @@ class ImperfectionCase(): def __init__(self, no: int = 1, - v: str = '1', + assigned_to_load_cases: str = '1', comment: str = '', params: dict = {}): diff --git a/RFEM/Tools/ModelCheck.py b/RFEM/Tools/ModelCheck.py new file mode 100644 index 00000000..d0726f60 --- /dev/null +++ b/RFEM/Tools/ModelCheck.py @@ -0,0 +1,108 @@ +from RFEM.initModel import Model +from RFEM.enums import ModelCheckGetOptionType, ModelCheckProcessOptionType + +class ModelCheck(): + + def __init__(self): + pass + + def GetIdenticalNodes(self, tolerance): + """ + Args: + tolerance (float): Tolerance + Returns: + Identical Nodes Object Group + """ + + operation = ModelCheckGetOptionType.IDENTICAL_NODES.name + object_groups = Model.clientModel.service.model_check__get_object_groups_operation(operation, tolerance) + + return object_groups + + def DeleteUnusedNodes(self, tolerance, object_groups): + """ + Args: + tolerance (float): Tolerance + object_groups (dict): Object Groups of Identical Nodes + """ + + process = ModelCheckProcessOptionType.DELETE_UNUSED_NODES.name + Model.clientModel.service.model_check__process_object_groups_operation(process, tolerance, object_groups) + + def UniteNodes(self, tolerance, object_groups): + """ + Args: + tolerance (float): Tolerance + object_groups (dict): Object Groups of Identical Nodes + """ + + process = ModelCheckProcessOptionType.UNITE_NODES_AND_DELETE_UNUSED_NODES.name + Model.clientModel.service.model_check__process_object_groups_operation(process, tolerance, object_groups) + + def GetNotConnectedLines(self, tolerance): + """ + Args: + tolerance (float): Tolerance + Returns: + Not Connected Lines Line Groups + """ + + operation = ModelCheckGetOptionType.CROSSING_LINES.name + line_groups = Model.clientModel.service.model_check__get_object_groups_operation(operation, tolerance) + + return line_groups + + def CrossLines(self, tolerance, line_groups): + """ + Args: + tolerance (float): Tolerance + line_groups (dict): Line Groups of Not Connected Lines + """ + + process = ModelCheckProcessOptionType.CROSS_LINES.name + Model.clientModel.service.model_check__process_object_groups_operation(process, tolerance, line_groups) + + def GetNotConnectedMembers(self, tolerance): + """ + Args: + tolerance (float): Tolerance + Returns: + Not Connected Members Member Groups + """ + + operation = ModelCheckGetOptionType.CROSSING_MEMBERS.name + member_groups = Model.clientModel.service.model_check__get_object_groups_operation(operation, tolerance) + + return member_groups + + def CrossMembers(self, tolerance, member_groups): + """ + Args: + tolerance (float): Tolerance + member_groups (dict): Member Groups of Not Connected Members + """ + + process = ModelCheckProcessOptionType.CROSS_MEMBERS.name + Model.clientModel.service.model_check__process_object_groups_operation(process, tolerance, member_groups) + + def GetOverlappingLines(self): + """ + Returns: + Overlapping Line Groups + """ + + operation = ModelCheckGetOptionType.OVERLAPPING_LINES.name + overlapping_lines = Model.clientModel.service.model_check__get_object_groups_operation(operation) + + return overlapping_lines + + def GetOverlappingMembers(self): + """ + Returns: + Overlapping Member Groups + """ + + operation = ModelCheckGetOptionType.OVERLAPPING_MEMBERS.name + overlapping_members = Model.clientModel.service.model_check__get_object_groups_operation(operation) + + return overlapping_members diff --git a/RFEM/Tools/PlausibilityCheck.py b/RFEM/Tools/PlausibilityCheck.py new file mode 100644 index 00000000..27cf03ee --- /dev/null +++ b/RFEM/Tools/PlausibilityCheck.py @@ -0,0 +1,26 @@ +from RFEM.initModel import Model +from RFEM.enums import PlausibilityCheckResult + +class PlausiblityCheck(): + + def __init__(self, + skip_warnings:bool = False): + + response = Model.clientModel.service.plausibility_check(skip_warnings) + + if "failed" in response: + self.checkresult = PlausibilityCheckResult.CHECK_FAILED + self.message = response.split("Messages received:", 1)[1] + self.errormessage = self.message.split("Result 'false'", 1)[0] + else: + self.checkresult = PlausibilityCheckResult.CHECK_IS_OK + self.message = 'Success' + self.errormessage = "" + + def IsModelOK(self): + + return self.checkresult == PlausibilityCheckResult.CHECK_IS_OK + + def GetErrorMessage(self): + + return self.errormessage diff --git a/RFEM/enums.py b/RFEM/enums.py index 9945fae4..c971686a 100644 --- a/RFEM/enums.py +++ b/RFEM/enums.py @@ -986,3 +986,21 @@ class CqsDampingRule(Enum): Spectal Analysis Settings Damping for CQC Rule ''' CONSTANT_FOR_EACH_MODE, DIFFERENT_FOR_EACH_MODE = range(2) + +class PlausibilityCheckResult(Enum): + ''' + Plausibility Check Result + ''' + CHECK_IS_OK, CHECK_FAILED = range(2) + +class ModelCheckGetOptionType(Enum): + ''' + Model Check Get Object Groups Option Type + ''' + CROSSING_LINES, CROSSING_MEMBERS, IDENTICAL_NODES, OVERLAPPING_LINES, OVERLAPPING_MEMBERS = range(5) + +class ModelCheckProcessOptionType(Enum): + ''' + Model Check Process Object Groups Option Type + ''' + CROSS_LINES, CROSS_MEMBERS, DELETE_UNUSED_NODES, UNITE_NODES_AND_DELETE_UNUSED_NODES = range(4) \ No newline at end of file diff --git a/UnitTests/template.py b/UnitTests/template.py index d64297b1..a72e2526 100644 --- a/UnitTests/template.py +++ b/UnitTests/template.py @@ -33,7 +33,7 @@ #pytestmark = pytest.mark.skipif(CheckIfMethodOrTypeExists(Model... # Use 'skipif' if you wish to skip individual test function conditionally -@pytest.mark.skipif(CheckIfMethodOrTypeExists(Model().clientModel,'set_model_settings_and_options', True), reason="set_model_settings_and_options not in RFEM yet") +@pytest.mark.skipif(CheckIfMethodOrTypeExists(Model.clientModel,'set_model_settings_and_options', True), reason="set_model_settings_and_options not in RFEM yet") # Name of the test function starts with test_... # If no specific need to atomize the testing procedure, pack as much funtionality as possible in one test function. diff --git a/UnitTests/test_ModelCheck.py b/UnitTests/test_ModelCheck.py new file mode 100644 index 00000000..42c8369e --- /dev/null +++ b/UnitTests/test_ModelCheck.py @@ -0,0 +1,80 @@ +import sys +import os +PROJECT_ROOT = os.path.abspath(os.path.join( + os.path.dirname(__file__), + os.pardir) +) +sys.path.append(PROJECT_ROOT) + +from RFEM.BasicObjects.member import Member +from RFEM.BasicObjects.line import Line +from RFEM.BasicObjects.node import Node +from RFEM.BasicObjects.section import Section +from RFEM.BasicObjects.material import Material +from RFEM.initModel import Model, CheckIfMethodOrTypeExists +from RFEM.Tools.ModelCheck import ModelCheck +import pytest + +if Model.clientModel is None: + Model() + +@pytest.mark.skipif(CheckIfMethodOrTypeExists(Model.clientModel,'model_check__get_object_groups_operation', True), reason="model_check__get_object_groups_operation not in RFEM yet") +def test_model_check(): + + Model.clientModel.service.delete_all() + Model.clientModel.service.begin_modification() + + Material(1, 'S235') + Section(1, 'IPE 300', 1) + + Node(1, 0, 0, 0) + Node(2, 0, 0, 0) + Node(3, 1, 1, 1) + Node(4, 1, 1, 1) + + Node(5, 10, 0, 0) + Node(6, 10, 3, 0) + Node(7, 9, 2, 0) + Node(8, 11, 2, 0) + + Node(9, 13, 0, 0) + Node(10, 13, 3, 0) + Node(11, 12, 2, 0) + Node(12, 14, 2, 0) + + Node(13, 5, 0, 0) + Node(14, 5, 3, 0) + + Node(15, 7, 0, 0) + Node(16, 7, 3, 0) + + Line(1, '5 6') + Line(2, '7 8') + + Line(3, '13 14') + Line(4, '13 14') + + Member(1, 9, 10, 0, 1, 1) + Member(2, 11, 12, 0, 1, 1) + Member(3, 15, 16, 0, 1, 1) + Member(4, 15, 16, 0, 1, 1) + + Model.clientModel.service.finish_modification() + + # TODO: UniteNodes(), CrossMembers() not covered + # US-8140 ToReview + identical_nodes = ModelCheck.GetIdenticalNodes(0, 0.0005) + assert identical_nodes[0][0] == "1,2" + assert identical_nodes[0][1] == "3,4" + ModelCheck.DeleteUnusedNodes(0, 0.0005, identical_nodes) + connected_lines = ModelCheck.GetNotConnectedLines(0, 0.0005) + assert connected_lines[0][0] == "1,2" + assert connected_lines[0][1] == "5,6" + ModelCheck.CrossLines(0, 0.0005, connected_lines) + ModelCheck.GetNotConnectedMembers(0, 0.0005) + overlapping_lines = ModelCheck.GetOverlappingLines(0) + assert overlapping_lines[0][0] == "3,4" + assert overlapping_lines[0][1] == "7,8" + overlapping_members = ModelCheck.GetOverlappingMembers(0) + assert overlapping_members[0][0] == "3,4" + diff --git a/UnitTests/test_plausiblityCheck.py b/UnitTests/test_plausiblityCheck.py new file mode 100644 index 00000000..1724754e --- /dev/null +++ b/UnitTests/test_plausiblityCheck.py @@ -0,0 +1,44 @@ +import os +import sys +PROJECT_ROOT = os.path.abspath(os.path.join( + os.path.dirname(__file__), + os.pardir) +) +sys.path.append(PROJECT_ROOT) +from RFEM.TypesForNodes.nodalSupport import NodalSupport, NodalSupportType +from RFEM.BasicObjects.member import Member +from RFEM.BasicObjects.node import Node +from RFEM.BasicObjects.section import Section +from RFEM.BasicObjects.material import Material +from RFEM.initModel import Model +from RFEM.Tools.PlausibilityCheck import PlausiblityCheck + +if Model.clientModel is None: + Model() + +def test_plausibility_check(): + + Model.clientModel.service.delete_all() + Model.clientModel.service.begin_modification() + + # Create Material + Material(1, 'S235') + + # Create Sections + Section(1, 'HEA 240', 1) + + # Create Nodes + Node(1, 0, 0, 0) + Node(2, 6, 0, 0) + + # Create Members + Member(1, 1, 2, 0, 1, 1) + + # Create Nodal Supports + NodalSupport(1, '1', NodalSupportType.FIXED) + + Model.clientModel.service.finish_modification() + + check = PlausiblityCheck() + assert check.message == 'Success' + assert check.errormessage == ''