ansys / pymapdl

Pythonic interface to MAPDL
https://mapdl.docs.pyansys.com
MIT License
423 stars 120 forks source link

Allow arrays/tables as arguments #3332

Open germa89 opened 1 month ago

germa89 commented 1 month ago

Writing something somewhere I had an idea.

I thought we could replicate the MAPDL behaviour accepting arrays as arguments.

For examples, the command D can accept tables for the argument values:

D,Node,TEMP,%tabname%

I think we could wrap every APDL command with something like:

    def _allow_array_tables_on_args(self):
        def _upload_arg_as_array(arg):
            # to be defined
            # we might need to sanitize the name of the new array from the variable
            # name.
            return arg_name # Array name in MAPDL database

        def _upload_arg_as_table(arg):
            # to be defined
            # we might need to sanitize the name of the new array from the variable
            # name.
            return arg_name # table name in MAPDL database

        def _process_arg(arg):
            if isinstance(each_arg, np.array):
                arg =_upload_arg_as_array(arg)

            elif isinstance(each_arg, pd.DataFrame):
                arg = _upload_arg_as_table(arg)

            return arg

        def wrap_bc_listing_function(func):
            @wraps(func)
            def inner_wrapper(*args, **kwargs):

                args_ = []
                for each_arg in args:
                    arg = _process_arg(each_arg)
                    args_.append(arg)

                kwargs_ = {}
                for each_key, each_value in kwargs:
                    arg = _process_arg(each_value)
                    args_.append(arg)

                return func(*args_, **kwargs)
            return inner_wrapper

        for name in dir(self):
            if name[0:4].upper() in CMD_LISTING and name in dir(
                Commands
            ):  # avoid matching Mapdl properties which starts with same letters as MAPDL commands.
                func = self.__getattribute__(name)
                setattr(self, name, wrap_listing_function(func))

I think it could be useful because then you can do something like:

mytable = pd.Dataframe(index=[1,2,3], data = [[35],[36],[37]])
# apply temperatures 35,36 and 37 to nodes 1,2 and 3 respectively
mapdl.d("all",TEMP, mytable)

Pinging @mikerife, @mcMunich @koubaa and @pmaroneh for feedback. This an idea, I cannot work on it yet, but I'm happy to heard about this.

References:

germa89 commented 1 month ago

Corollary

Same approach could be done for components. If a list/array is used as an argument, create the component with the parameter name and use it. When using an object defined in the same line, for instance:

mapdl.d([1,2,3], Temp, mytable)

we can create a temporary component and use it.

It might be not super obvious to the user though that the component/array/table is being created on the background.

pmaroneh commented 1 month ago

That is a great suggestion. Being able to use lists and/or pandas dataframes to define tabular load value would be so much easier than having to create MAPDL tables.