Skip to content

Commit

Permalink
Math name issue (#1465)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
germa89 committed Oct 11, 2022
1 parent 68afcb0 commit fa99294
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 17 deletions.
28 changes: 16 additions & 12 deletions src/ansys/mapdl/core/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .common_grpc import ANSYS_VALUE_TYPE, DEFAULT_CHUNKSIZE, DEFAULT_FILE_CHUNK_SIZE
from .errors import ANSYSDataTypeError, protect_grpc
from .mapdl_grpc import MapdlGrpc
from .parameters import interp_star_status

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

@property
def _parm(self):
return interp_star_status(self._status)

def vec(self, size=0, dtype=np.double, init=None, name=None, asarray=False):
"""Create a vector.
Expand Down Expand Up @@ -199,19 +204,16 @@ def vec(self, size=0, dtype=np.double, init=None, name=None, asarray=False):

if not name:
name = id_generator()

if name not in self._parm:
self._mapdl.run(f"*VEC,{name},{MYCTYPE[dtype]},ALLOC,{size}", mute=True)

ans_vec = AnsVec(name, self._mapdl, dtype, init)
if asarray:
return self._mapdl._vec_data(ans_vec.id)
else:
return ans_vec
ans_vec = AnsVec(name, self._mapdl, dtype, init)

if asarray:
return self._mapdl._vec_data(ans_vec.id)
else:
ans_vec = AnsVec(name, self._mapdl)
if asarray:
return self._mapdl._vec_data(ans_vec.id)
else:
return ans_vec
return ans_vec

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

if not isinstance(vec, AnsVec):
raise TypeError("Must be an Ansys vector object")
Expand Down
36 changes: 32 additions & 4 deletions src/ansys/mapdl/core/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,19 @@ def interp_star_status(status):
Dictionary of parameters.
"""
parameters = {}
st = status.find("NAME VALUE")
if "APDLMATH" in status:
header = " Name Type"
incr = 84
else: # normal parameters
header = "NAME VALUE"
incr = 80

st = status.find(header)

if st == -1:
return {}

for line in status[st + 80 :].splitlines():
for line in status[st + incr :].splitlines():
items = line.split()
if not items:
continue
Expand All @@ -626,6 +633,27 @@ def interp_star_status(status):
value = items[1]
parameters[name] = {"type": items[2], "value": value}
elif len(items) == 5:
shape = (int(items[2]), int(items[3]), int(items[4]))
parameters[name] = {"type": items[1], "shape": shape}
if items[1] in ["DMAT", "VEC", "SMAT"]:
parameters[name] = {
"type": items[1],
"MemoryMB": float(items[2]),
"dimensions": get_apdl_math_dimensions(items[3]),
"workspace": int(items[4]),
}
elif items[1] in ["LSENGINE"]:
parameters[name] = {
"type": items[1],
"workspace": int(items[4]),
}
else:
shape = (int(items[2]), int(items[3]), int(items[4]))
parameters[name] = {"type": items[1], "shape": shape}
return parameters


def get_apdl_math_dimensions(dimensions_str):
"""Convert the dimensions string to a tuple (arrays) or int (vectors)"""
if ":" in dimensions_str:
return tuple([int(each) for each in dimensions_str[1:-1].split(":")])
else:
return int(dimensions_str)
113 changes: 112 additions & 1 deletion tests/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from scipy import sparse

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


def test_copy2(mm):
dim = 1000
m2 = mm.rand(dim, dim)
m3 = m2.copy()

assert np.allclose(m2.asarray(), m3.asarray())


def test_dense_solver(mm):
dim = 1000
m2 = mm.rand(dim, dim)
# factorize do changes inplace in m2, so we
# need a copy to later compare.
m3 = m2.copy()

solver = mm.factorize(m2)

v = mm.ones(dim)
solver.solve(v)
C = solver.solve(v)

# TODO: we need to verify this works
m3_ = m3.asarray()
v_ = v.asarray()
x = np.linalg.solve(m3_, v_)

assert np.allclose(C, x)


def test_solve_py(mapdl, mm, cube_solve):
Expand Down Expand Up @@ -655,3 +673,96 @@ def test_status(mm, capsys):
# Checking also _status property
assert "APDLMATH PARAMETER STATUS-" in mm._status
assert all([each in mm._status for each in ["Name", "Type", "Dims", "Workspace"]])


def test_mult(mapdl, mm):

rand_ = np.random.rand(100, 100)

if not meets_version(mapdl._server_version, (0, 4, 0)):
with pytest.raises(VersionError):
AA = mm.matrix(rand_, name="AA")

else:
AA = mm.matrix(rand_, name="AA")

BB = mm.vec(size=rand_.shape[1])
CC = mm.vec(size=rand_.shape[1], init="zeros")
BB_trans = mm.matrix(np.random.rand(1, 100), "BBtrans")

assert mapdl.mult(m1=AA.id, m2=BB.id, m3=CC.id)
assert mapdl.mult(m1=BB.id, t1="Trans", m2=AA.id, m3=CC.id)
assert mapdl.mult(m1=AA.id, m2=BB_trans.id, t2="Trans", m3=CC.id)


def test__parm(mm, mapdl):
sz = 5000
mat = sparse.random(sz, sz, density=0.05, format="csr")

rand_ = np.random.rand(100, 100)
if not meets_version(mapdl._server_version, (0, 4, 0)):

with pytest.raises(VersionError):
AA = mm.matrix(rand_, name="AA")

else:
AA = mm.matrix(rand_, name="AA")
assert AA.id == "AA"
BB = mm.vec(size=rand_.shape[1], name="BB")
assert BB.id == "BB"
CC = mm.matrix(mat, "CC")
assert CC.id == "CC"

assert isinstance(mm._parm, dict)
AA_parm = mm._parm["AA"]
assert AA_parm["type"] == "DMAT"
assert AA_parm["dimensions"] == AA.shape
assert AA_parm["workspace"] == 1

BB_parm = mm._parm["BB"]
assert BB_parm["type"] == "VEC"
assert BB_parm["dimensions"] == BB.size
assert BB_parm["workspace"] == 1

# Sparse matrices are made of three matrices
assert "CC_DATA" in mm._parm
assert "CC_IND" in mm._parm
assert "CC_PTR" in mm._parm

assert mm._parm["CC_DATA"]["dimensions"] == mat.indices.shape[0]
assert mm._parm["CC_DATA"]["type"] == "VEC"
assert mm._parm["CC_IND"]["dimensions"] == sz + 1
assert mm._parm["CC_IND"]["type"] == "VEC"
assert mm._parm["CC_PTR"]["dimensions"] == mat.indices.shape[0]
assert mm._parm["CC_PTR"]["type"] == "VEC"


def test_vec2(mm, mapdl):
mapdl.clear()

assert mm._parm == {}

# Create a new vector if no name is provided
mm.vec(100)
assert mm._parm != {}
assert len(mm._parm.keys()) == 1
name_ = list(mm._parm.keys())[0]
parameter_ = mm._parm[name_]
assert parameter_["type"] == "VEC"
assert parameter_["dimensions"] == 100

# retrieve a vector if the name is given and exists
vec = mm.vec(10, name=name_)
assert vec.size != 10
assert vec.size == 100
assert vec.id == name_

parameter_ = mm._parm[name_]
assert parameter_["type"] == "VEC"
assert parameter_["dimensions"] == 100

# Create a new vector if a name is given and doesn't exist
vec_ = mm.vec(20, name="ASDF")
parameter_ = mm._parm["ASDF"]
assert parameter_["type"] == "VEC"
assert parameter_["dimensions"] == vec_.size

0 comments on commit fa99294

Please sign in to comment.