From b6f93716dd80403fec5892d962867f672da6bd6a Mon Sep 17 00:00:00 2001 From: Pablo Vargas Date: Tue, 17 Sep 2024 12:11:27 +0200 Subject: [PATCH] to_dataframe() support for some bc list commands --- src/ansys/mapdl/core/commands.py | 129 +++++++++++++-- tests/test_commands.py | 269 +++++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 12 deletions(-) diff --git a/src/ansys/mapdl/core/commands.py b/src/ansys/mapdl/core/commands.py index 4a74c124ac..25e88dd528 100644 --- a/src/ansys/mapdl/core/commands.py +++ b/src/ansys/mapdl/core/commands.py @@ -52,9 +52,8 @@ REG_FLOAT_INT = re.compile( r"[+-]?[0-9]*[.]?[0-9]*[Ee]?[+-]?[0-9]+|\s[0-9]+\s" ) # match number groups -BC_REGREP = re.compile( - r"^\s*([0-9]+)\s*([A-Za-z]+)\s*([0-9]*[.]?[0-9]+)\s+([0-9]*[.]?[0-9]+)" -) +BC_REGREP = re.compile(r"^\s*([0-9]+)\s*([A-Za-z]+)((?:\s+[0-9]*[.]?[0-9]+)+)$") + MSG_NOT_PANDAS = """'Pandas' is not installed or could not be found. Hence this command is not applicable. @@ -105,7 +104,34 @@ "SWLI", ] -CMD_BC_LISTING = ["FLIS", "DLIS"] +CMD_BC_LISTING = [ + "DKLI", + "DLLI", + "DALI", + "DLIS", + "FKLI", + "FLIS", + "SFLL", + # "SFAL", Define two integers before label (regex) + # "SFLI", Use two lines to define each BC in the list + # "SFEL", Use two lines to define each BC in the list + "BFKL", + "BFLL", + "BFAL", +] + +COLNAMES_BC_LISTING = { + "DKLI": ["KEYPOINT", "LABEL", "REAL", "IMAG", "EXP KEY"], + "DLLI": ["LINE", "LABEL", "REAL", "IMAG", "NAREA"], + "DALI": ["AREA", "LABEL", "REAL", "IMAG"], + "DLIS": ["NODE", "LABEL", "REAL", "IMAG"], + "FKLI": ["KEYPOINT", "LABEL", "REAL", "IMAG"], + "FLIS": ["NODE", "LABEL", "REAL", "IMAG"], + "SFLL": ["LINE", "LABEL", "VALI", "VALJ", "VAL2I", "VAL2J"], + "BFKL": ["KEYPOINT", "LABEL", "VALUE"], + "BFLL": ["LINE", "LABEL", "VALUE"], + "BFAL": ["AREA", "LABEL", "VALUE"], +} CMD_ENTITY_LISTING = [ "NLIS", @@ -793,15 +819,92 @@ class BoundaryConditionsListingOutput(CommandListingOutput): """ + def bc_colnames(self): + """Get the column names based on bc list command""" + + bc_type = { + "BODY FORCES": "BF", + "SURFACE LOAD": "SF", + "POINT LOAD": "F", + "FORCES": "F", + "CONSTRAINTS": "D", + } + + entity = { + "KEYPOINT": "K", + "LINE": "L", + "AREA": "A", + "NODE": "", + "ELEMENT": "E", + } + + title = self._get_body()[0] + + _bcType = [i for i in bc_type.keys() if i in title] + _entity = [i for i in entity.keys() if i in title] + + if _bcType and _entity: + + key_bc = bc_type[_bcType[0]] + entity[_entity[0]] + "LIST" + key_bc = key_bc[:4] + + if key_bc in COLNAMES_BC_LISTING.keys(): + + _cols = COLNAMES_BC_LISTING[key_bc] + + # Check num columns in data + ldata = [] + for line in self.splitlines(): + line = line.strip() + # exclude any line containing characters [A-Z] except for E + if line: + items = BC_REGREP.findall(line) + if items: + ldata = list(items[0][:2]) + items[0][2].split() + break + + if ldata: + if len(_cols) > len(ldata): + _cols = _cols[: len(ldata)] + + return _cols + + return None + + def get_columns(self): + """Get the column names for the dataframe. + + Returns + ------- + List of strings + + """ + if self._columns_names: + return self._columns_names + + bc_colnames = self.bc_colnames() + + if bc_colnames: + return bc_colnames + + body = self._get_body() + + pairs = list(self._get_data_group_indexes(body)) + try: + return body[pairs[0][0]].split() + except: + return None + def _parse_table(self): """Parse tabular command output.""" parsed_lines = [] for line in self.splitlines(): + line = line.strip() # exclude any line containing characters [A-Z] except for E if line: items = BC_REGREP.findall(line) if items: - parsed_lines.append(list(items[0])) + parsed_lines.append(list(items[0][:2]) + items[0][2].split()) return parsed_lines @@ -838,17 +941,19 @@ def to_dataframe(self): """ df = super().to_dataframe(data=self.to_list()) - if "NODE" in df.columns: - df["NODE"] = df["NODE"].astype(np.int32, copy=False) + + primitives = ["KEYPOINT", "LINE", "AREA", "VOLUME", "NODE", "ELEMENT"] + + float_col = ["REAL", "IMAG", "VALUE", "VALI", "VALJ"] + + for i in df.columns.intersection(primitives): + df[i] = df[i].astype(np.int32, copy=False) if "LABEL" in df.columns: df["LABEL"] = df["LABEL"].astype(str, copy=False) - if "REAL" in df.columns: - df["REAL"] = df["REAL"].astype(np.float64, copy=False) - - if "IMAG" in df.columns: - df["IMAG"] = df["IMAG"].astype(np.float64, copy=False) + for i in df.columns.intersection(float_col): + df[i] = df[i].astype(np.float64, copy=False) return df diff --git a/tests/test_commands.py b/tests/test_commands.py index 347b2f56ed..4dcf722d87 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -766,3 +766,272 @@ def test_cmlist(mapdl): assert len(cmlist_all.to_array()) == len(cmlist_all.to_list()) for each_ in cmlist_all.to_list(): assert each_ in cmlist_all + + +class Test_bc_cmdlist_solid: + + def solid_model(self, mapdl): + # Solid model (Geometry) + + mapdl.clear() + + mapdl.prep7() + + # Define keypoints, lines and area + # -------------------- + mapdl.k(1, 0, 0) + mapdl.k(2, 1, 0) + mapdl.k(3, 1, 1) + mapdl.l(1, 2) + mapdl.l(2, 3) + mapdl.l(3, 1) + mapdl.a(1, 2, 3) + + # Define a material + # -------------------- + mapdl.mp("EX", 1, 30e6) + mapdl.mp("NUXY", 1, 0.25) # Poisson's Ratio + + # Define section + # -------------------- + mapdl.et(1, "PLANE183") + mapdl.keyopt(1, 1, 0) + mapdl.keyopt(1, 3, 3) + mapdl.keyopt(1, 6, 0) + mapdl.r(1, 0.01) + + def test_dklist(self, mapdl): + + df_dk = pd.DataFrame( + { + "KEYPOINT": [1], + "LABEL": ["UX"], + "REAL": [0.0], + "IMAG": [0.0], + "EXP KEY": ["0"], + } + ) + + self.solid_model(mapdl) + mapdl.dk(1, "UX", 0) + + dklist_result = mapdl.dklist().to_dataframe() + + assert not dklist_result.empty + assert dklist_result.compare(df_dk).empty + + def test_dllist(self, mapdl): + + df_dl = pd.DataFrame( + { + "LINE": [2, 2], + "LABEL": ["UX", "UY"], + "REAL": [0.0, 0.0], + "IMAG": [0.0, 0.0], + "NAREA": ["0", "0"], + } + ) + + self.solid_model(mapdl) + mapdl.dl(2, 1, "ALL", 0) + + dllist_result = mapdl.dllist().to_dataframe() + + assert not dllist_result.empty + assert dllist_result.compare(df_dl).empty + + def test_dalist(self, mapdl): + + df_da = pd.DataFrame( + { + "AREA": [1], + "LABEL": ["UZ"], + "REAL": [0.0], + "IMAG": [0.0], + } + ) + + self.solid_model(mapdl) + mapdl.da(1, "UZ", 0) + + dalist_result = mapdl.dalist().to_dataframe() + + assert not dalist_result.empty + assert dalist_result.compare(df_da).empty + + def test_fklist(self, mapdl): + + df_fk = pd.DataFrame( + { + "KEYPOINT": [2, 3], + "LABEL": ["FY", "FY"], + "REAL": [200.0, 100.0], + "IMAG": [0.0, 0.0], + } + ) + + self.solid_model(mapdl) + mapdl.fk(2, "FY", 200) + mapdl.fk(3, "FY", 100) + + fklist_result = mapdl.fklist().to_dataframe() + + assert not fklist_result.empty + assert fklist_result.compare(df_fk).empty + + def test_sfllist(self, mapdl): + + df_sfl = pd.DataFrame( + { + "LINE": [2, 3], + "LABEL": ["PRES", "PRES"], + "VALI": [50.0, 50.0], + "VALJ": [500.0, 500.0], + } + ) + + self.solid_model(mapdl) + mapdl.sfl(2, "PRES", 50, 500) + mapdl.sfl(3, "PRES", 50, 500) + + sfllist_result = mapdl.sfllist().to_dataframe() + + assert not sfllist_result.empty + assert sfllist_result.compare(df_sfl).empty + + def test_bfklist(self, mapdl): + + df_bfk = pd.DataFrame( + { + "KEYPOINT": [2], + "LABEL": ["TEMP"], + "VALUE": [10.0], + } + ) + + self.solid_model(mapdl) + mapdl.bfk(2, "TEMP", 10) + + bfklist_result = mapdl.bfklist().to_dataframe() + + assert not bfklist_result.empty + assert bfklist_result.compare(df_bfk).empty + + def test_bfllist(self, mapdl): + + df_bfl = pd.DataFrame( + { + "LINE": [3], + "LABEL": ["TEMP"], + "VALUE": [15.0], + } + ) + + self.solid_model(mapdl) + mapdl.bfl(3, "TEMP", 15) + + bfllist_result = mapdl.bfllist().to_dataframe() + + assert not bfllist_result.empty + assert bfllist_result.compare(df_bfl).empty + + def test_bfalist(self, mapdl): + + df_bfa = pd.DataFrame( + { + "AREA": [1], + "LABEL": ["TEMP"], + "VALUE": [20.0], + } + ) + + self.solid_model(mapdl) + mapdl.bfa(1, "TEMP", 20) + + bfalist_result = mapdl.bfalist().to_dataframe() + + assert not bfalist_result.empty + assert bfalist_result.compare(df_bfa).empty + + +class Test_bc_cmdlist_model: + + def solid_model(self, mapdl): + # Solid model (Geometry) + + mapdl.clear() + + mapdl.prep7() + + # Define keypoints, lines and area + # -------------------- + mapdl.k(1, 0, 0) + mapdl.k(2, 1, 0) + mapdl.k(3, 1, 1) + mapdl.l(1, 2) + mapdl.l(2, 3) + mapdl.l(3, 1) + mapdl.a(1, 2, 3) + + # Define a material + # -------------------- + mapdl.mp("EX", 1, 30e6) + mapdl.mp("NUXY", 1, 0.25) # Poisson's Ratio + + # Define section + # -------------------- + mapdl.et(1, "PLANE183") + mapdl.keyopt(1, 1, 0) + mapdl.keyopt(1, 3, 3) + mapdl.keyopt(1, 6, 0) + mapdl.r(1, 0.01) + + def fe_model(self, mapdl): + # FE model (Mesh) + + self.solid_model(mapdl) + + mapdl.esize(0.02) + mapdl.mshape(0, "2D") + mapdl.mshkey(0) + mapdl.amesh(1, 1, 1) + + def test_dlist(self, mapdl): + + df_d = pd.DataFrame( + { + "NODE": [2, 2], + "LABEL": ["UX", "UY"], + "REAL": [0.0, 0.0], + "IMAG": [0.0, 0.0], + } + ) + + self.fe_model(mapdl) + mapdl.d(2, "UX", 0) + mapdl.d(2, "UY", 0) + + dlist_result = mapdl.dlist().to_dataframe() + + assert not dlist_result.empty + assert dlist_result.compare(df_d).empty + + def test_flist(self, mapdl): + + df_f = pd.DataFrame( + { + "NODE": [4, 4], + "LABEL": ["FX", "FY"], + "REAL": [10.0, 20.0], + "IMAG": [0.0, 0.0], + } + ) + + self.fe_model(mapdl) + mapdl.f(4, "FX", 10) + mapdl.f(4, "FY", 20) + + flist_result = mapdl.flist().to_dataframe() + + assert not flist_result.empty + assert flist_result.compare(df_f).empty