I found an example that shares one PDE with me:
https://fenicsproject.org/qa/13269/scalar-mixed-function-space-problem/
I’ve updated its code to use current FEniCS terms, and it ran fine in 2D. However, when I switch into 1D, the Newton Solver won’t converge. Error message:
Error: Unable to solve nonlinear system with NewtonSolver.
*** Reason: Newton solver did not converge because maximum number of iterations reached.
*** Where: This error was encountered inside NewtonSolver.cpp.
*** Process: 0
***
*** DOLFIN version: 2019.1.0
*** Git changeset: unknown
My code is:
from dolfin import *
import mshr
# Define boundaries; made 1D, getting rid of y-direction
class Left(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 0.0)
class Right(SubDomain):
def inside(self, x, on_boundary):
return near(x[0], 1.0)
# Initialize sub-domain instances
left = Left()
right = Right()
# Mesh. Not sure on this number of cells; have tried up to 10,000 and low as 20.
mesh = IntervalMesh(100, 0, 1)
# Marking boundary domains.
# Got rid of y-boundaries and re-numbered left & right boundaries.
boundaries = MeshFunction('size_t', mesh, mesh.topology().dim()-1, 0)
boundaries.set_all(0)
left.mark(boundaries, 1)
right.mark(boundaries, 2)
CG1_elem = FiniteElement("CG", mesh.ufl_cell(), 1)
#Defining the function spaces for the concentration
V_c = FunctionSpace(mesh, CG1_elem)
#Defining the function spaces for the voltage
V_phi = FunctionSpace(mesh, CG1_elem)
#Defining the mixed function space
W_elem = MixedElement([CG1_elem, CG1_elem])
W = FunctionSpace(mesh, W_elem)
#Defining the "Trial" functions
u = Function(W)
c, phi = split(u)
#Defining the test functions
(v_1, v_2) = TestFunctions(W)
# Time variables
dt = 0.05; t = 0; T = 10
# Previous solution
W_const = Constant(1.0)
C_previous= interpolate(W_const, V_c)
# Define Dirichlet boundary conditions at right boundary,
# previously top boundary; (V=4.0 volt)
Voltage = Constant(4.0)
bc_right = DirichletBC(W.sub(0), Voltage, boundaries, 2)
# Define Dirichlet boundary conditions at left boundary,
# previously bottom boundary (V=0.0 volt)
bc_left = DirichletBC(W.sub(0), 0.0, boundaries, 1)
#Collecting the boundary conditions
bcs = [bc_right, bc_left]
#Define eps in the weak form
eps=0.0082
# Define variational form
a = dot(grad(phi), grad(v_2)) * dx \
+ c*v_1 * dx \
- (1./(2 * (pow(eps,2)))) * c * v_2 * dx \
+ dt * eps * dot(grad(c),grad(v_1)) * dx \
+ dt * eps * c * dot(grad(phi),grad(v_1)) * dx
L = C_previous * v_1 * dx - (1./(2 * (pow(eps,2)))) * v_2 * dx
# For nonlinear solver
F = a - L
# Create VTK files for visualization output
vtkfile_phi = File('solution/phi.pvd')
vtkfile_c = File('solution/c.pvd')
while t <= T:
solve(F == 0, u, bcs)
(c, phi) = u.split(True)
C_previous.assign(c)
# Save solution to file (VTK)
vtkfile_c << (c, t)
vtkfile_phi << (phi, t)
# Update current time
t += dt
Is there a reason the one spatial dimension version can’t work? I’ve tried using meshes with fewer points and many more points (20 or 1,000 or even 10,000).