Conjugate gradient solver for nonlinear variational Problem

Hi,
Thank you so much for following up on my question @nate @bhaveshshrimali
I am using SNES to solve my nonlinear variational problem, but I am getting the following error:

*** Error: Unable to solve nonlinear variational problem.
*** Reason: Unknown nonlinear solver type.
*** Where: This error was encountered inside NonlinearVariationalSolver.cpp.

Following is my minimal code:

import numpy as np
from numpy import linalg as LA
from numpy.linalg import inv     
import matplotlib.pyplot as plt
from dolfin import *
from scipy import optimize
import numdifftools as nd 


parameters["form_compiler"]["cpp_optimize"] = True
parameters["form_compiler"]["representation"] = "uflacs"



# Create mesh and define function space
mesh = RectangleMesh(Point(-1,-1),Point(1,1), 50, 50)
V = VectorFunctionSpace(mesh, "Lagrange", 1)


################################################################################
# Define boundary condictions
################################################################################

F11=0.5
F12=0.0 + 0.1
F21=0.0 - 0.1
F22=2.0  

y_BC = Expression(("F11*x[0]+F12*x[1]", "F21*x[0]+F22*x[1]"), F11=F11,F12=F12,F21=F21,F22=F22,degree=2)

tol = 1E-3
def x0_boundary(x, on_boundary):
    return on_boundary and near(x[0], -1, tol) or near(x[0], 1, tol) or \
                            near(x[1], -1, tol) or near(x[1], 1, tol) 

bcs = DirichletBC(V, y_BC, x0_boundary)

################################################################################
# Define functions
################################################################################

dy = TrialFunction(V)            # Incremental displacement
v  = TestFunction(V)             # Test function
y  = Function(V)
B  = Constant((0, 0))       # Body force per unit area
T  = Constant((0, 0))       # Traction force on the boundary

y_reference = Expression(("x[0]","x[1]"),degree=3)

################################################################################
# Elasticity model: Stored strain energy density (compressible neo-Hookean model)
################################################################################

E, nu = 10.0, 0.3
mu, blk = Constant(E/(2*(1 + nu))), Constant(E/(3*(1 - 2*nu)))

def W(y):                       #Stored strain energy density 
    F = grad(y)                 # Deformation gradient
    C = F.T*F                   # Right Cauchy-Green tensor
    Ic = tr(C)
    J  = det(F)
    return (mu/2)*(Ic - 3) - mu*ln(J) + (blk/2 - mu/3)*(J-1)**2

################################################################################
# Total potential energy and solve
################################################################################

Pi = W(y)*dx -dot(B, (y-y_reference))*dx  + dot(T, (y-y_reference))*ds

F = derivative(Pi, y, v) # first variation (derivative at u in the direction of v)

dF = derivative(F, y, dy) # Jacobian of F

problem=NonlinearVariationalProblem(F, y, bcs=bcs, J=dF)
solver=NonlinearVariationalSolver(problem)

solver.parameters['nonlinear_solver'] = 'snesncg'
solver.parameters["snes_solver"]["maximum_iterations"] = 50
solver.parameters["snes_solver"]["report"] = False

solver.solve()

To solve the problem, I tried implementing what Nate has suggested in this link: Using petsc4py.PETSc.SNES directly - #11 by niewiarowski

However, I am getting another error that says: TypeError: 'DirichletBC' object is not iterable
The code that I have used based on the mentioned link is as below:

import numpy as np
from numpy import linalg as LA
from numpy.linalg import inv     
import matplotlib.pyplot as plt
from dolfin import *
from scipy import optimize
import numdifftools as nd 


parameters["form_compiler"]["cpp_optimize"] = True
parameters["form_compiler"]["representation"] = "uflacs"



# Create mesh and define function space
mesh = RectangleMesh(Point(-1,-1),Point(1,1), 50, 50)
V = VectorFunctionSpace(mesh, "Lagrange", 1)


################################################################################
# Define boundary condictions
################################################################################

F11=0.5
F12=0.0 + 0.1
F21=0.0 - 0.1
F22=2.0  

y_BC = Expression(("F11*x[0]+F12*x[1]", "F21*x[0]+F22*x[1]"), F11=F11,F12=F12,F21=F21,F22=F22,degree=2)

tol = 1E-3
def x0_boundary(x, on_boundary):
    return on_boundary and near(x[0], -1, tol) or near(x[0], 1, tol) or \
                            near(x[1], -1, tol) or near(x[1], 1, tol) 

bcs = DirichletBC(V, y_BC, x0_boundary)

################################################################################
# Define functions
################################################################################

dy = TrialFunction(V)            # Incremental displacement
v  = TestFunction(V)             # Test function
y  = Function(V)
B  = Constant((0, 0))       # Body force per unit area
T  = Constant((0, 0))       # Traction force on the boundary

y_reference = Expression(("x[0]","x[1]"),degree=3)

################################################################################
# Elasticity model: Stored strain energy density (compressible neo-Hookean model)
################################################################################

E, nu = 10.0, 0.3
mu, blk = Constant(E/(2*(1 + nu))), Constant(E/(3*(1 - 2*nu)))

def W(y):                       #Stored strain energy density 
    F = grad(y)                 # Deformation gradient
    C = F.T*F                   # Right Cauchy-Green tensor
    Ic = tr(C)
    J  = det(F)
    return (mu/2)*(Ic - 3) - mu*ln(J) + (blk/2 - mu/3)*(J-1)**2

################################################################################
# Total potential energy and solve
################################################################################

Pi = W(y)*dx -dot(B, (y-y_reference))*dx  + dot(T, (y-y_reference))*ds

F = derivative(Pi, y, v) # first variation (derivative at u in the direction of v)

class SNESProblem():
    def __init__(self, F, y, bcs):
        V = y.function_space()
        dy = TrialFunction(V)
        self.L = F
        self.a = derivative(F, y, dy)
        self.bcs = bcs
        self.y = y

    def F(self, snes, x, F):
        x = PETScVector(x)
        F  = PETScVector(F)
        assemble(self.L, tensor=F)
        for bc in self.bcs:
            bc.apply(F, x)                

    def J(self, snes, x, J, P):
        J = PETScMatrix(J)
        assemble(self.a, tensor=J)
        for bc in self.bcs:
            bc.apply(J)


problem = SNESProblem(F, y, bcs)
import petsc4py, sys
petsc4py.init(sys.argv)
from petsc4py import PETSc
    
b = PETScVector()  # same as b = PETSc.Vec()
J_mat = PETScMatrix()

snes = PETSc.SNES().create(MPI.comm_world)   
snes.setFunction(problem.F, b.vec())
snes.setJacobian(problem.J, J_mat.mat())
snes.solve(None, problem.y.vector().vec())

I would be so thankful if you could help me to solve my nonlinear variational problem using SNES (and preferably, its conjugate gradient method (NCG)).

Thank you very much!
Mary