Skip to content

Commit fa99294

Browse files
committed
Math name issue (#1465)
* Making sure the vector is generated even if not name is given. * Adding unit tests * Adding ``_parm`` to math module. * Adding unit tests. * changing test name. * Adding LSENGINE case to parse *STATUS * fixing tests * commenting assert until we get feedback * Fixing unit tests. * Coverage. * Fixing test * Fixing test
1 parent 68afcb0 commit fa99294

File tree

3 files changed

+160
-17
lines changed

3 files changed

+160
-17
lines changed

src/ansys/mapdl/core/math.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .common_grpc import ANSYS_VALUE_TYPE, DEFAULT_CHUNKSIZE, DEFAULT_FILE_CHUNK_SIZE
1818
from .errors import ANSYSDataTypeError, protect_grpc
1919
from .mapdl_grpc import MapdlGrpc
20+
from .parameters import interp_star_status
2021

2122
MYCTYPE = {
2223
np.int32: "I",
@@ -166,6 +167,10 @@ def _status(self):
166167
"""Print out the status of all APDLMath Objects"""
167168
return self._mapdl.run("*STATUS,MATH", mute=False)
168169

170+
@property
171+
def _parm(self):
172+
return interp_star_status(self._status)
173+
169174
def vec(self, size=0, dtype=np.double, init=None, name=None, asarray=False):
170175
"""Create a vector.
171176
@@ -199,19 +204,16 @@ def vec(self, size=0, dtype=np.double, init=None, name=None, asarray=False):
199204

200205
if not name:
201206
name = id_generator()
207+
208+
if name not in self._parm:
202209
self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},ALLOC,{size}", mute=True)
203210

204-
ans_vec = AnsVec(name, self._mapdl, dtype, init)
205-
if asarray:
206-
return self._mapdl._vec_data(ans_vec.id)
207-
else:
208-
return ans_vec
211+
ans_vec = AnsVec(name, self._mapdl, dtype, init)
212+
213+
if asarray:
214+
return self._mapdl._vec_data(ans_vec.id)
209215
else:
210-
ans_vec = AnsVec(name, self._mapdl)
211-
if asarray:
212-
return self._mapdl._vec_data(ans_vec.id)
213-
else:
214-
return ans_vec
216+
return ans_vec
215217

216218
def mat(self, nrow=0, ncol=0, dtype=np.double, init=None, name=None, asarray=False):
217219
"""Create an APDLMath matrix.
@@ -1391,8 +1393,10 @@ def __mul__(self, vec):
13911393
AnsVec
13921394
Hadamard product between this vector and the other vector.
13931395
"""
1394-
if not meets_version(self._mapdl._server_version, (0, 4, 0)):
1395-
raise VersionError(f"``{func.__name__}`` requires MAPDL version 2021R2")
1396+
if not meets_version(
1397+
self._mapdl._server_version, (0, 4, 0)
1398+
): # pragma: no cover
1399+
raise VersionError("``AnsVec`` requires MAPDL version 2021R2")
13961400

13971401
if not isinstance(vec, AnsVec):
13981402
raise TypeError("Must be an Ansys vector object")

src/ansys/mapdl/core/parameters.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,19 @@ def interp_star_status(status):
602602
Dictionary of parameters.
603603
"""
604604
parameters = {}
605-
st = status.find("NAME VALUE")
605+
if "APDLMATH" in status:
606+
header = " Name Type"
607+
incr = 84
608+
else: # normal parameters
609+
header = "NAME VALUE"
610+
incr = 80
611+
612+
st = status.find(header)
606613

607614
if st == -1:
608615
return {}
609616

610-
for line in status[st + 80 :].splitlines():
617+
for line in status[st + incr :].splitlines():
611618
items = line.split()
612619
if not items:
613620
continue
@@ -626,6 +633,27 @@ def interp_star_status(status):
626633
value = items[1]
627634
parameters[name] = {"type": items[2], "value": value}
628635
elif len(items) == 5:
629-
shape = (int(items[2]), int(items[3]), int(items[4]))
630-
parameters[name] = {"type": items[1], "shape": shape}
636+
if items[1] in ["DMAT", "VEC", "SMAT"]:
637+
parameters[name] = {
638+
"type": items[1],
639+
"MemoryMB": float(items[2]),
640+
"dimensions": get_apdl_math_dimensions(items[3]),
641+
"workspace": int(items[4]),
642+
}
643+
elif items[1] in ["LSENGINE"]:
644+
parameters[name] = {
645+
"type": items[1],
646+
"workspace": int(items[4]),
647+
}
648+
else:
649+
shape = (int(items[2]), int(items[3]), int(items[4]))
650+
parameters[name] = {"type": items[1], "shape": shape}
631651
return parameters
652+
653+
654+
def get_apdl_math_dimensions(dimensions_str):
655+
"""Convert the dimensions string to a tuple (arrays) or int (vectors)"""
656+
if ":" in dimensions_str:
657+
return tuple([int(each) for each in dimensions_str[1:-1].split(":")])
658+
else:
659+
return int(dimensions_str)

tests/test_math.py

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pytest
77
from scipy import sparse
88

9+
from ansys.mapdl.core.check_version import VersionError, meets_version
910
from ansys.mapdl.core.errors import ANSYSDataTypeError
1011
from ansys.mapdl.core.launcher import get_start_instance
1112
import ansys.mapdl.core.math as apdl_math
@@ -410,15 +411,32 @@ def test_solve_py(mapdl, mm, cube_solve):
410411
assert np.allclose(w_n, eigval, atol=0.1)
411412

412413

414+
def test_copy2(mm):
415+
dim = 1000
416+
m2 = mm.rand(dim, dim)
417+
m3 = m2.copy()
418+
419+
assert np.allclose(m2.asarray(), m3.asarray())
420+
421+
413422
def test_dense_solver(mm):
414423
dim = 1000
415424
m2 = mm.rand(dim, dim)
425+
# factorize do changes inplace in m2, so we
426+
# need a copy to later compare.
416427
m3 = m2.copy()
428+
417429
solver = mm.factorize(m2)
418430

419431
v = mm.ones(dim)
420-
solver.solve(v)
432+
C = solver.solve(v)
433+
421434
# TODO: we need to verify this works
435+
m3_ = m3.asarray()
436+
v_ = v.asarray()
437+
x = np.linalg.solve(m3_, v_)
438+
439+
assert np.allclose(C, x)
422440

423441

424442
def test_solve_py(mapdl, mm, cube_solve):
@@ -655,3 +673,96 @@ def test_status(mm, capsys):
655673
# Checking also _status property
656674
assert "APDLMATH PARAMETER STATUS-" in mm._status
657675
assert all([each in mm._status for each in ["Name", "Type", "Dims", "Workspace"]])
676+
677+
678+
def test_mult(mapdl, mm):
679+
680+
rand_ = np.random.rand(100, 100)
681+
682+
if not meets_version(mapdl._server_version, (0, 4, 0)):
683+
with pytest.raises(VersionError):
684+
AA = mm.matrix(rand_, name="AA")
685+
686+
else:
687+
AA = mm.matrix(rand_, name="AA")
688+
689+
BB = mm.vec(size=rand_.shape[1])
690+
CC = mm.vec(size=rand_.shape[1], init="zeros")
691+
BB_trans = mm.matrix(np.random.rand(1, 100), "BBtrans")
692+
693+
assert mapdl.mult(m1=AA.id, m2=BB.id, m3=CC.id)
694+
assert mapdl.mult(m1=BB.id, t1="Trans", m2=AA.id, m3=CC.id)
695+
assert mapdl.mult(m1=AA.id, m2=BB_trans.id, t2="Trans", m3=CC.id)
696+
697+
698+
def test__parm(mm, mapdl):
699+
sz = 5000
700+
mat = sparse.random(sz, sz, density=0.05, format="csr")
701+
702+
rand_ = np.random.rand(100, 100)
703+
if not meets_version(mapdl._server_version, (0, 4, 0)):
704+
705+
with pytest.raises(VersionError):
706+
AA = mm.matrix(rand_, name="AA")
707+
708+
else:
709+
AA = mm.matrix(rand_, name="AA")
710+
assert AA.id == "AA"
711+
BB = mm.vec(size=rand_.shape[1], name="BB")
712+
assert BB.id == "BB"
713+
CC = mm.matrix(mat, "CC")
714+
assert CC.id == "CC"
715+
716+
assert isinstance(mm._parm, dict)
717+
AA_parm = mm._parm["AA"]
718+
assert AA_parm["type"] == "DMAT"
719+
assert AA_parm["dimensions"] == AA.shape
720+
assert AA_parm["workspace"] == 1
721+
722+
BB_parm = mm._parm["BB"]
723+
assert BB_parm["type"] == "VEC"
724+
assert BB_parm["dimensions"] == BB.size
725+
assert BB_parm["workspace"] == 1
726+
727+
# Sparse matrices are made of three matrices
728+
assert "CC_DATA" in mm._parm
729+
assert "CC_IND" in mm._parm
730+
assert "CC_PTR" in mm._parm
731+
732+
assert mm._parm["CC_DATA"]["dimensions"] == mat.indices.shape[0]
733+
assert mm._parm["CC_DATA"]["type"] == "VEC"
734+
assert mm._parm["CC_IND"]["dimensions"] == sz + 1
735+
assert mm._parm["CC_IND"]["type"] == "VEC"
736+
assert mm._parm["CC_PTR"]["dimensions"] == mat.indices.shape[0]
737+
assert mm._parm["CC_PTR"]["type"] == "VEC"
738+
739+
740+
def test_vec2(mm, mapdl):
741+
mapdl.clear()
742+
743+
assert mm._parm == {}
744+
745+
# Create a new vector if no name is provided
746+
mm.vec(100)
747+
assert mm._parm != {}
748+
assert len(mm._parm.keys()) == 1
749+
name_ = list(mm._parm.keys())[0]
750+
parameter_ = mm._parm[name_]
751+
assert parameter_["type"] == "VEC"
752+
assert parameter_["dimensions"] == 100
753+
754+
# retrieve a vector if the name is given and exists
755+
vec = mm.vec(10, name=name_)
756+
assert vec.size != 10
757+
assert vec.size == 100
758+
assert vec.id == name_
759+
760+
parameter_ = mm._parm[name_]
761+
assert parameter_["type"] == "VEC"
762+
assert parameter_["dimensions"] == 100
763+
764+
# Create a new vector if a name is given and doesn't exist
765+
vec_ = mm.vec(20, name="ASDF")
766+
parameter_ = mm._parm["ASDF"]
767+
assert parameter_["type"] == "VEC"
768+
assert parameter_["dimensions"] == vec_.size

0 commit comments

Comments
 (0)