← Back to team overview

dolfin team mailing list archive

Problem with non-linear solver

 

Hi everyone,

I have a problem with the non-linear solver. I want to solve a non-linear pde of the form f(u,grad(u))*dot(grad(u),grad(v)) = 0 for all v. If I define f inside the form-file everything works fine, but if I define f as a function which is calculated outside the form-file it only works when f=f(u) but not when f=f(grad(u)).

I have attached an example of this discrepancy.

Regards, Jesper


# Copyright (C) 2007 Jesper Carlsson.
# Licensed under the GNU GPL Version 2.
#
# Modified by Jesper Carlsson
# First added:  2007-04-03
# Last changed: 2007-04-03

# The linear form L(v) for the gradient product at each cell.
#
# Compile this form with FFC: ffc MassMat.form.

element0 = FiniteElement("Discontinuous Lagrange", "triangle", 0)
element1 = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element0)
f = Function(element1)

# Used to assemble gradients of functions
L = dot(grad(f), grad(f))*v*dx          
# Copyright (C) 2007 Jesper Carlsson.
# Licensed under the GNU GPL Version 2.
#
# Modified by Jesper Carlsson
# First added:  2007-05-25
# Last changed: 2007-06-01

element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)

# Alternative 1 (works)

u0= Function(element)

a = (1+u0*u0)*dot(grad(u),grad(v))*dx + 2*u0*u*dot(grad(u0),grad(v))*dx
L = -(1+u0*u0)*dot(grad(u0),grad(v))*dx
# Copyright (C) 2007 Jesper Carlsson.
# Licensed under the GNU GPL Version 2.
#
# Modified by Jesper Carlsson
# First added:  2007-05-25
# Last changed: 2007-06-01

element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)

# Alternative 2 (?)

u0= Function(element)
f = Function(element)  # f=1+u0^2
fp = Function(element) # fp=1

a = f*dot(grad(u),grad(v))*dx + 2*fp*u0*u*dot(grad(u0),grad(v))*dx
L = -f*dot(grad(u0),grad(v))*dx
# Copyright (C) 2007 Jesper Carlsson.
# Licensed under the GNU GPL Version 2.
#
# Modified by Jesper Carlsson
# First added:  2007-05-25
# Last changed: 2007-06-01

element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)

# Alternative 3 (works)

u0= Function(element)

a = (1+dot(grad(u0),grad(u0)))*dot(grad(u),grad(v))*dx + 2*dot(grad(u0),grad(u))*dot(grad(u0),grad(v))*dx
L = -(1+dot(grad(u0),grad(u0)))*dot(grad(u0),grad(v))*dx


# Copyright (C) 2007 Jesper Carlsson.
# Licensed under the GNU GPL Version 2.
#
# Modified by Jesper Carlsson
# First added:  2007-05-25
# Last changed: 2007-06-01

element0 = FiniteElement("Discontinuous Lagrange", "triangle", 0)
element1 = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element1)
u = TrialFunction(element1)

# Alternative 4 (does not work)

u0= Function(element1)
f= Function(element0)  # f = 1 + |grad(u)|^2
fp= Function(element0) # fp = 1

a = f*dot(grad(u),grad(v))*dx + 2*fp*dot(grad(u0),grad(u))*dot(grad(u0),grad(v))*dx
L = -f*dot(grad(u0),grad(v))*dx
// Copyright (C) 2007 Jesper Carlsson.
// Licensed under the GNU GPL Version 2.
//
// Modified by Jesper Carlsson
// First added:  2007-05-29
// Last changed: 2007-05-29
//

#include <dolfin.h>
#include "dolfin/Test1.h"
#include "dolfin/Test2.h"
#include "dolfin/Test3.h"
#include "dolfin/Test4.h"
#include "dolfin/GradProd.h"
  
using namespace dolfin;

int TEST = 4;

// Dirichlet boundary condition
class DirichletBC : public BoundaryCondition {
  void eval(BoundaryValue& value, const Point& p, unsigned int i) {
    if ( fabs(p.x()) < DOLFIN_EPS )
      value = 0.25-pow(p.y()-0.5, 2);
    else
      value = 0.0;
  }
};

// User defined nonlinear problem 
class MyNonlinearProblem : public NonlinearProblem
{
public:
  
  // Constructor 
  MyNonlinearProblem(Mesh& mesh, BoundaryCondition& dbc, Function& U,
                     Function& F, Function& Fprim) 
    : NonlinearProblem(), _mesh(&mesh), _dbc(&dbc), _U(&U), _F(&F), _Fprim(&Fprim)
  {

    // Create forms

    if (TEST==1)
      {
        // Alternative 1 (OK)
        a = new Test1::BilinearForm(U);
        L = new Test1::LinearForm(U);
      }
    else if (TEST==2)
      {
        // Alternative 2 (OK)
        a = new Test2::BilinearForm(U, F, Fprim);
        L = new Test2::LinearForm(U, F);
      }
    else if (TEST==3)
      {
        // Alternative 1 (OK)
        a = new Test3::BilinearForm(U);
        L = new Test3::LinearForm(U);
      }
    else if (TEST==4)
      {
        // Alternative 4 (NOT OK)
        a = new Test4::BilinearForm(U, F, Fprim);
        L = new Test4::LinearForm(U, F);
      }
    
    gp = new GradProd::LinearForm(U);
    
    // Initialise solution vector u
    U.init(mesh, a->test());

    // Initialise cell-wise defined vectors
    F.init(mesh, gp->test());
    Fprim.init(mesh, gp->test());

  }
    
  // Destructor 
  ~MyNonlinearProblem()
  {
    delete a;
    delete L;
    delete gp;
  }
  
  // User defined assemble of Jacobian and residual vector 
  void form(GenericMatrix& A, GenericVector& b, const GenericVector& x)
  {

    // Assemble gradients
    dolfin_log(false);
    FEM::assemble(*gp, grad2, *_mesh);
    dolfin_log(true);

    // Calculate f and fp
    dolfin_assert(_F->vector().size()==grad2.size());
    dolfin_assert(_Fprim->vector().size()==grad2.size());

    for (int i=0; i<grad2.size(); ++i)
      {
        if (TEST==2)
          {
            // Alternative 2
            _F->vector()(i) = 1+pow(_U->vector().get(i), 2);
            _Fprim->vector()(i) = 1;
          }
        else if (TEST==4)
          {
            // Alternative 4
            _F->vector()(i) = 1+grad2(i);
            _Fprim->vector()(i) = 1;
          }
        
      }

    dolfin_log(false);
    FEM::assemble(*a, *L, A, b, *_mesh);
    FEM::applyBC(A, *_mesh, a->test(), *_dbc);
    FEM::applyResidualBC(b, x, *_mesh, a->test(), *_dbc);
    dolfin_log(true);
  }
  
private:
  
  // Pointers to forms, mesh and boundary conditions
  BilinearForm *a;
  LinearForm *L, *gp;
  Mesh* _mesh;
  BoundaryCondition* _dbc;
  Function *_U, *_F, *_Fprim;
  Vector grad2;
  
};

int main()
{

  // Set up problem
  UnitSquare mesh(64, 64);
  DirichletBC dbc;
  Function U, F, Fprim;
  
  // Create user-defined nonlinear problem
  MyNonlinearProblem nonlinear_problem(mesh, dbc, U, F, Fprim);

  // Create nonlinear solver and set parameters
  NewtonSolver nonlinear_solver;
  nonlinear_solver.set("Newton maximum iterations", 50);
  nonlinear_solver.set("Newton relative tolerance", 1e-10);
  nonlinear_solver.set("Newton absolute tolerance", 1e-10);

  
  // Solve nonlinear problem
  Vector& u = U.vector();
  nonlinear_solver.solve(nonlinear_problem, u);
    
  // Save function to file
  File file("nonlinear_poisson.pvd");
  file << U;
  
  return 0;

}

Follow ups