def test_linear_pde(): """Test Newton solver for a linear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 12) V = function.FunctionSpace(mesh, ("Lagrange", 1)) u = function.Function(V) v = TestFunction(V) F = inner(10.0, v) * dx - inner(grad(u), grad(v)) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector.set(1.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve solver = dolfinx.cpp.nls.NewtonSolver(MPI.COMM_WORLD) n, converged = solver.solve(problem, u.vector) assert converged assert n == 1 # Increment boundary condition and solve again u_bc.vector.set(2.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) n, converged = solver.solve(problem, u.vector) assert converged assert n == 1
def test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 15) V = function.FunctionSpace(mesh, ("Lagrange", 1)) u = function.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector.set(1.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) u.vector.set(0.9) u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) b = dolfinx.cpp.la.create_vector(V.dofmap.index_map) J = dolfinx.cpp.fem.create_matrix(problem.a_comp._cpp_object) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b) snes.setJacobian(problem.J, J) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().setTolerances(rtol=1.0e-9) snes.getKSP().getPC().setType("lu") snes.getKSP().getPC().setFactorSolverType("superlu_dist") snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6 # Modify boundary condition and solve again u_bc.vector.set(0.5) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def test_newton_solver_inheritance_override_methods(): import functools called_methods = {} def check_is_called(method): @functools.wraps(method) def wrapper(*args, **kwargs): called_methods[method.__name__] = True return method(*args, **kwargs) return wrapper class CustomNewtonSolver(dolfinx.cpp.nls.NewtonSolver): def __init__(self, comm): super().__init__(comm) @check_is_called def update_solution(self, x, dx, relaxation, problem, it): return super().update_solution(x, dx, relaxation, problem, it) @check_is_called def converged(self, r, problem, it): return super().converged(r, problem, it) mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 12) V = function.FunctionSpace(mesh, ("Lagrange", 1)) u = function.Function(V) v = TestFunction(V) F = inner(10.0, v) * dx - inner(grad(u), grad(v)) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = function.Function(V) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve solver = CustomNewtonSolver(MPI.COMM_WORLD) n, converged = solver.solve(problem, u.vector) assert called_methods[CustomNewtonSolver.converged.__name__] assert called_methods[CustomNewtonSolver.update_solution.__name__]
def test_nonlinear_pde(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 12, 5) V = fem.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfinx.fem.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = fem.Function(V) with u_bc.vector.localForm() as u_local: u_local.set(1.0) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve with u.vector.localForm() as u_local: u_local.set(0.9) solver = dolfinx.cpp.nls.NewtonSolver(MPI.COMM_WORLD) solver.setF(problem.F, problem.vector()) solver.setJ(problem.J, problem.matrix()) solver.set_form(problem.form) n, converged = solver.solve(u.vector) assert converged assert n < 6 # Modify boundary condition and solve again with u_bc.vector.localForm() as u_local: u_local.set(0.5) n, converged = solver.solve(u.vector) assert converged assert n < 6
def test_nonlinear_pde(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = dolfinx.generation.UnitSquareMesh(dolfinx.MPI.comm_world, 12, 5) V = function.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfinx.function.Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[0] < 1.0e-8, x[0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector.set(1.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc = fem.DirichletBC(u_bc, fem.locate_dofs_geometrical(V, boundary)) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve u.vector.set(0.9) u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) solver = dolfinx.cpp.nls.NewtonSolver(dolfinx.MPI.comm_world) n, converged = solver.solve(problem, u.vector) assert converged assert n < 6 # Modify boundary condition and solve again u_bc.vector.set(0.5) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) n, converged = solver.solve(problem, u.vector) assert converged assert n < 6