This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Update plot each time step

+5 votes

Hi all,

Does anyone have a nice way to plot a solution of a time dependant problem, and then update the same plot each time step? Maybe plot( ..) / viper has a way to id a window and keep plotting new function in it?

Thanks!

asked Mar 3, 2014 by mwelland FEniCS User (8,410 points)

2 Answers

+4 votes
 
Best answer

As long as you keep plotting the same Function object, the plot window shouldn't change. Don't create a new Function object within the time loop, use e.g. Function.assign to update the existing Function object.

Alternatively you could do:

p = plot(f)
...
p.plot(f)
answered Mar 3, 2014 by Øyvind Evju FEniCS Expert (17,700 points)
selected Mar 4, 2014 by mwelland

Thanks, I see what you mean for normal cases, but this method doesn't seem to work with mixed elements...
For example, using the Cahn-Hilliard demo, I add a plot(u.split()[0]) before the time loop and during, and instead of updating the plot I get a bunch of new plots:

"""This demo illustrates how to use of DOLFIN for solving the Cahn-Hilliard
equation, which is a time-dependent nonlinear PDE """

# Copyright (C) 2009 Garth N. Wells
#
# This file is part of DOLFIN.
#
# DOLFIN is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DOLFIN is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
#
# First added:  2009-06-20
# Last changed: 2013-11-20

# Begin demo

import random
from dolfin import *

# Class representing the intial conditions
class InitialConditions(Expression):
    def __init__(self):
        random.seed(2 + MPI.process_number())
    def eval(self, values, x):
        values[0] = 0.63 + 0.02*(0.5 - random.random())
        values[1] = 0.0
    def value_shape(self):
        return (2,)

# Class for interfacing with the Newton solver
class CahnHilliardEquation(NonlinearProblem):
    def __init__(self, a, L):
        NonlinearProblem.__init__(self)
        self.L = L
        self.a = a
        self.reset_sparsity = True
    def F(self, b, x):
        assemble(self.L, tensor=b)
    def J(self, A, x):
        assemble(self.a, tensor=A, reset_sparsity=self.reset_sparsity)
        self.reset_sparsity = False

# Model parameters
lmbda  = 1.0e-02  # surface parameter
dt     = 5.0e-06  # time step
theta  = 0.5      # time stepping family, e.g. theta=1 -> backward Euler, theta=0.5 -> Crank-Nicolson

# Form compiler options
parameters["form_compiler"]["optimize"]     = True
parameters["form_compiler"]["cpp_optimize"] = True
parameters["form_compiler"]["representation"] = "quadrature"

# Create mesh and define function spaces
mesh = UnitSquareMesh(96, 96)
V = FunctionSpace(mesh, "Lagrange", 1)
ME = V*V

# Define trial and test functions
du    = TrialFunction(ME)
q, v  = TestFunctions(ME)

# Define functions
u   = Function(ME)  # current solution
u0  = Function(ME)  # solution from previous converged step

# Split mixed functions
dc, dmu = split(du)
c,  mu  = split(u)
c0, mu0 = split(u0)

# Create intial conditions and interpolate
u_init = InitialConditions()
u.interpolate(u_init)
u0.interpolate(u_init)

# Compute the chemical potential df/dc
c = variable(c)
f    = 100*c**2*(1-c)**2
dfdc = diff(f, c)

# mu_(n+theta)
mu_mid = (1.0-theta)*mu0 + theta*mu

# Weak statement of the equations
L0 = c*q*dx - c0*q*dx + dt*dot(grad(mu_mid), grad(q))*dx
L1 = mu*v*dx - dfdc*v*dx - lmbda*dot(grad(c), grad(v))*dx
L = L0 + L1

# Compute directional derivative about u in the direction of du (Jacobian)
a = derivative(L, u, du)

# Create nonlinear problem and Newton solver
problem = CahnHilliardEquation(a, L)
solver = NewtonSolver()
solver.parameters["linear_solver"] = "lu"
solver.parameters["convergence_criterion"] = "incremental"
solver.parameters["relative_tolerance"] = 1e-6

# Output file
file = File("output.pvd", "compressed")

# Step in time
t = 0.0
T = 50*dt
plot(u.split()[0])
while (t < T):
    t += dt
    plot(u.split()[0])
    u0.vector()[:] = u.vector()
    solver.solve(problem, u.vector())
    file << (u.split()[0], t)

plot(u.split()[0])
interactive()

As far as I can tell, the u.split command returns a new Function object every time its called. The following is not ideal, but is an alternative:

up = Function(V)
...
while (t < T):
    ...
    up.assign(u.split()[0])
    plot(up)
    ...

Thanks, that works great!

For anyone else who wants to use this, I found the graph disappears after a few iterations unless I disable rescaling:

plot(up, rescale = False)
+3 votes

For anyone Googling this and wondering about what to do if you have made a vector from components and want to avoid popping up a new plot window every timestep

V = FunctionSpace(.....)
u0 = Function(V)
u1 = Function(V)
u = as_vector([u0, u1])

plot(u)
plot(u) # new window ...

The easy solution is to call:

plot(u, key='u')
plot(u, key='u')# No new window

The "key" parameter makes it pick the previous plot window opened with the same key. You can also define the window title to make it more meaningfull:

plot(u, key='u', title='velocity')

This works in FEniCS 1.5. I am not sure it will also solve the original question, but I guess so

answered Apr 23, 2015 by Tormod Landet FEniCS User (5,130 points)
...