How to save residuals data in every step

Hi, guys,

I’m trying to save the residual data of every iteration to a txt file. But I don’t know how to do it. I give a nonlinear example code:

from dolfin import *

# Sub domain for Dirichlet boundary condition
class DirichletBoundary(SubDomain):
    def inside(self, x, on_boundary):
        return abs(x[0] - 1.0) < DOLFIN_EPS and on_boundary

# Create mesh and define function space
mesh = UnitSquareMesh(32, 32)
V = FunctionSpace(mesh, "CG", 1)

# Define boundary condition
g = Constant(1.0)
bc = DirichletBC(V, g, DirichletBoundary())

# Define variational problem
u = Function(V)
v = TestFunction(V)
f = Expression("x[0]*sin(x[1])", degree=0)
F = inner((1 + u**2)*grad(u), grad(v))*dx - f*v*dx

# Compute solution
solve(F == 0, u, bc, solver_parameters={"newton_solver":
                                            #{"relative_tolerance": 1e-6}})

and get the output

Solving nonlinear variational problem.
  Newton iteration 0: r (abs) = 1.776e+01 (tol = 1.000e-10) r (rel) = 1.000e+00 (tol = 1.000e-07)
  Newton iteration 1: r (abs) = 9.034e-03 (tol = 1.000e-10) r (rel) = 5.086e-04 (tol = 1.000e-07)
  Newton iteration 2: r (abs) = 2.719e-04 (tol = 1.000e-10) r (rel) = 1.530e-05 (tol = 1.000e-07)
  Newton iteration 3: r (abs) = 1.267e-07 (tol = 1.000e-10) r (rel) = 7.132e-09 (tol = 1.000e-07)
  Newton solver finished in 3 iterations and 3 linear solver iterations.

I wanna save the r(abs) abd r(rel) data to a txt ot csv file. Thanks a lot.

best

The residual is sent through the logger. thus, you cannot obtain it inside python, but you could simply pipe it:

python3 name_of_script.py > output.txt

results in

cat output.txt 
No Jacobian form specified for nonlinear variational problem.
Differentiating residual form F to obtain Jacobian J = F'.
Solving nonlinear variational problem.
  Newton iteration 0: r (abs) = 1.776e+01 (tol = 1.000e-10) r (rel) = 1.000e+00 (tol = 1.000e-06)
  Newton iteration 1: r (abs) = 9.034e-03 (tol = 1.000e-10) r (rel) = 5.086e-04 (tol = 1.000e-06)
  Newton iteration 2: r (abs) = 2.719e-04 (tol = 1.000e-10) r (rel) = 1.530e-05 (tol = 1.000e-06)
  Newton iteration 3: r (abs) = 1.267e-07 (tol = 1.000e-10) r (rel) = 7.132e-09 (tol = 1.000e-06)
  Newton solver finished in 3 iterations and 3 linear solver iterations.

Thanks a lot! It’s enough for me.

Hi @dokken, I’m using Legacy Fenics through Docker. When I just redirect the stream (i.e. use >log.txt), my print statements and the residual information are out of order. Using the example above,

print('Performing first solve')
solve(F == 0, u, bc, solver_parameters={"newton_solver":
                                            #{"relative_tolerance": 1e-6}})

print('Performing second solve')
solve(F == 0, u, bc, solver_parameters={"newton_solver":
                                            #{"relative_tolerance": 1e-6}})

Would print the newton iterations follow by the print statements, making it difficult to track which iterations correspond to which solve.

I thought I could get around this issue by using the log file. Do you know how to set the output log file? I’ve used the commands for setting logging from the documentation:

set_log_active(True)
set_log_level(LogLevel.INFO)

I also muted some output and tried to redirect the stream using the python logging package:

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logging.getLogger('UFL').setLevel(logging.WARNING)
logging.getLogger('FFC').setLevel(logging.WARNING)

But the output from the nonlinear solver still ends up in the console.

The function set_output_stream() doesn’t seem to exists even though it is in the documentation. At a bit of a loss here. Will I just need to create a custom solver so that I can access my residuals?

Call basicConfig prior to import dolfin (as ffc calls basic config, and it can only be called once).
MWE:

import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
from dolfin import *
set_log_level(LogLevel.DEBUG)
mesh = UnitSquareMesh(10, 10)
V = FunctionSpace(mesh, "Lagrange", 1)

Thanks for the reply, this is still outputting messages to console only for me and not the log file. I tried to add the specific log file for it to redirect to as well.

import logging
import sys

fh = logging.FileHandler("test.log", mode='w')
sh = logging.StreamHandler(sys.stdout)
logging.basicConfig(level=logging.DEBUG,
                    handlers=[fh,sh])

from dolfin import *
set_log_level(LogLevel.DEBUG)

mesh = UnitSquareMesh(10, 10)
V = FunctionSpace(mesh, "Lagrange", 1)

logging.debug('Prints to log file')