Dolfin parameter handling for custom class issue in v2019.1

Hi all,

I am working to on upgrading a specialized solver class to run on Fenics v2019.1, from v2017.2. There appears to be an issue with the handling of parameters for the solver that I do not understand. I have included a MWE below, and the resulting output when run on fenics v2019.1 through Docker on a mac. Any guidance or tips are much appreciated!

-Ellery

# MWE CODE
from dolfin import *

class TestClass:

    def __init__(self):

        # Create parameter set
        self.parameters = \
            Parameters(type_one = Parameters("type_one"),
                           type_two = Parameters("type_two"))

        self.parameters.type_one.add("p1", 1.0)
        self.parameters.type_two.add("q1", 1.0)
        self.parameters.type_two.add("q2", False)

    def _solve(self):
        print("success")

# Run solver class
if __name__ == "__main__":
    
    # Create Solver
    solver = TestClass()
    solver.parameters.type_two = True

    # Solve
    solver.solve()
#####
OUTPUT

fenics@093c63af784a:~/shared/sandbox/issue_par$ python3 myclass.py
Traceback (most recent call last):
File “myclass.py”, line 30, in
solver = TestClass()
File “myclass.py”, line 13, in init
type_two = Parameters(“type_two”))
TypeError: init(): incompatible constructor arguments. The following argument types are supported:
1. dolfin.cpp.parameter.Parameters()
2. dolfin.cpp.parameter.Parameters(arg0: str)
3. dolfin.cpp.parameter.Parameters(arg0: dolfin.cpp.parameter.Parameters)
4. dolfin.cpp.parameter.Parameters(arg0: str, **kwargs)

Invoked with: kwargs: type_one=<dolfin.cpp.parameter.Parameters object at 0x7f241f2a49d0>, type_two=<dolfin.cpp.parameter.Parameters object at 0x7f241f2a4d18>

Take a look at this modified version of your MWE, which seems to work as intended:

from dolfin import *

class TestClass:

    def __init__(self):

        # Create parameter set
        
        # A string positional argument for the name is required when
        # passing kwargs to the constructor:
        self.parameters = \
            Parameters("",type_one = Parameters("type_one"),
                       type_two = Parameters("type_two"))

        #self.parameters.type_one.add("p1", 1.0)
        #self.parameters.type_two.add("q1", 1.0)
        #self.parameters.type_two.add("q2", False)

        # Use the indexing operator instead of . to access attributes
        # from kwargs:
        self.parameters["type_one"].add("p1",1.0)
        self.parameters["type_two"].add("q1",1.0)
        self.parameters["type_two"].add("q2", False)
        
    def _solve(self):
        print("success")

# Run solver class
if __name__ == "__main__":
    
    # Create Solver
    solver = TestClass()
    
    #solver.parameters.type_two = True

    # Again, use the index operator:
    solver.parameters["type_two"]["q2"] = True

    # Check values:
    info(solver.parameters, True)
    
    # Solve

    # Added underscore from name of method in class definition:
    solver._solve()

Great! Thanks David. This works as desired --I’ll try implementing this is the application.

Best,
Ellery