Hello,
I’m trying to solve a multiple equation system by using the Newton solver on each equation in the system iteratively, similar to how pressure, velocity and turbulence model corrections are handled in separate correction steps for the Reynolds-averaged Navier-Stokes equations in solvers like simpleFoam in OpenFOAM.
I have been trying to set up a simple example of a set of equations solved in this manner by adapting the convection-diffusion equation tutorial, but without much success so far. Specifically, I have been trying to set up a system of two coupled, steady, nonlinear convection-diffusion equations in 2D and solve them by
- Create initial guesses for both concentrations c1 and c2
- In a loop, iterate until convergence:
- Plug the current guess for c2 into equation 1 and solve for c1
- Plug the current guess for c1 into equation 2 and solve for c2
This is the current code I use for this purpose:
import fenics
import numpy as np
class SteadyConvectionDiffusionGenerator:
def __init__(self):
self.ndims = 2
#mesh
p_bottomleft = fenics.Point(*[-2.0 for _ in range(self.ndims)])
p_topright = fenics.Point(*[2.0 for _ in range(self.ndims)])
self.mesh = fenics.RectangleMesh.create(p=[p_bottomleft,p_topright],n=[100 for _ in range(self.ndims)],cell_type=fenics.CellType.Type.triangle)
#finite element setup stuff
P1 = fenics.FiniteElement('CG', fenics.triangle, 1)
element = P1
self.FuncSpace = fenics.FunctionSpace(self.mesh, element)
self.TestFuncs = [fenics.TestFunctions(self.FuncSpace) for _ in range(self.ndims)]
self.SolnFuncs = [fenics.Function(self.FuncSpace) for _ in range(self.ndims)]
self.u = [fenics.split(sf) for sf in self.SolnFuncs]
#forcing
f_1 = fenics.Expression('pow(2*x[0]-0.1,2)+pow(x[1]-0.1,2)<0.05*0.05 ? 0.1 : 0',degree=1)
f_2 = fenics.Expression('pow(2*x[0]-0.1,2)+pow(x[1]-0.3,2)<0.05*0.05 ? 0.1 : 0',degree=1)
#equations
diffusion_coeff = fenics.Constant(0.01)
closure_coeff = fenics.Constant(10.0)
self.eq1_linear_part = \
+ fenics.inner(fenics.grad(self.u[0][0]),fenics.grad(self.TestFuncs[0][0]))*diffusion_coeff*fenics.dx \
- f_1 * self.TestFuncs[0][0] * fenics.dx
self.eq1 = self.eq1_linear_part + closure_coeff * self.u[0][0] * self.u[1][0] * self.TestFuncs[0][0] * fenics.dx
self.eq2_linear_part = \
+ fenics.inner(fenics.grad(self.u[1][0]),fenics.grad(self.TestFuncs[1][0]))*diffusion_coeff*fenics.dx \
- f_2 * self.TestFuncs[1][0] * fenics.dx
self.eq2 = self.eq2_linear_part + closure_coeff * self.u[0][0] * self.u[1][0] * self.TestFuncs[1][0] * fenics.dx
self.sp = {
"newton_solver":{"maximum_iterations":50, 'relative_tolerance': 1e-6, 'absolute_tolerance': 1e-5, "error_on_nonconvergence": False, "linear_solver": "lu"}
}
def solve_together(self):
fenics.solve(self.eq1 + self.eq2 == 0, self.SolnFuncs[0], solver_parameters = self.sp)
def solve_one_by_one(self):
for k in range(10):
print('---Solving eq 1---')
fenics.solve(self.eq1 == 0, self.SolnFuncs[0], solver_parameters = self.sp)
print('---Solving eq 2---')
fenics.solve(self.eq2 == 0, self.SolnFuncs[1], solver_parameters = self.sp)
print('\n')
if __name__ == '__main__':
g = SteadyConvectionDiffusionGenerator()
# g.solve_together()
g.solve_one_by_one()
This code runs, but I am unable to export or plot the solutions to see if the solutions are as expected, as I get the following error for the VTK export functionality:
*** -------------------------------------------------------------------------
*** DOLFIN encountered an error. If you are not able to resolve this issue
*** using the information listed below, you can ask for help at
***
*** fenics-support@googlegroups.com
***
*** Remember to include the error message listed below and, if possible,
*** include a minimal running example to reproduce the error.
***
*** -------------------------------------------------------------------------
*** Error: Unable to write data to VTK file.
*** Reason: Don’t know how to handle vector function with dimension other than 2 or 3.
*** Where: This error was encountered inside VTKFile.cpp.
*** Process: 0
***
*** DOLFIN version: 2019.1.0
*** Git changeset: unknown
*** -------------------------------------------------------------------------
However, when I inspect the solution I get by looking at the raw values in g.SolnFuncs[0].vector() for example, I see that they are on the order of 1e+12 which should not be the case for this problem, so there’s certainly something wrong here.
I could not find much info on how to do this kind of thing with Fenics - there’s this unanswered post from about a year ago: How to decouple and iteratively solve Cahn-Hilliard equation
First of all, how can I fix the export problem? Secondly, could anyone point me towards resources showing how to implement such a solution algorithm?