How to define mixed elements on Dolfin legacy

Hello everyone, I hope everyone is having a good day. I was trying to solve the Cahn-Hilliard equation (code that I found on FeniCs webpage), and found an error. I think this has to do with some outdated versions, since I’ve seen multiples ways to formulate mixed elements, but none seem to work on the code provided.

Here’s the code found on the web:

  import random
  from dolfin import *
  
  # Class representing the intial conditions
  class InitialConditions(Expression):
      def __init__(self):
          random.seed(2 + MPI.rank(mpi_comm_world()))
      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
      def F(self, b, x):
          assemble(self.L, tensor=b)
      def J(self, A, x):
          assemble(self.a, tensor=A)
  
  # 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
  while (t < T):
      t += dt
      u0.vector()[:] = u.vector()
      solver.solve(problem, u.vector())
      file << (u.split()[0], t)
  
  plot(u.split()[0]) 

And the error it raises goes like: TypeError: unsupported operand type(s) for *: ‘FunctionSpace’ and ‘FunctionSpace’.

I also tried to modify the formulation for:
ME = MixedElement([V, V])
But got no results as well

Please add a link to where you found the code and what version of legacy dolfin you are running.

I’m running dolfin 2019.2.0.dev0

The .py file I got can be found on this page: https://fenicsproject.org/olddocs/dolfin/1.3.0/python/demo/documented/cahn-hilliard/python/documentation.html

As you can see from the link, you are looking at v 1.3.0 of dolfin

Thus, the newest demo for 2019.2.0.dev0 is at: https://fenicsproject.org/olddocs/dolfin/latest/python/demos/cahn-hilliard/demo_cahn-hilliard.py.html

1 Like

Worked perfectly, thanks a lot