///
/// This file is part of Rheolef.
///
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
///
/// Rheolef is free software; you can redistribute it and/or modify
/// it under the terms of the GNU General Public License as published by
/// the Free Software Foundation; either version 2 of the License, or
/// (at your option) any later version.
///
/// Rheolef 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 General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with Rheolef; if not, write to the Free Software
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
/// 
/// =========================================================================
//! @examplefile combustion2.icc The combustion problem: class body for the Newton method
field combustion::residue (const field& uh) const { 
  test v(Xh);
  field mrh = integrate(dot(grad(uh),grad(v)) - lambda*exp(uh)*v);
  mrh.set_b() = 0;
  return mrh;
}
form combustion::derivative (const field& uh) const {
  trial du(Xh); test v(Xh);
  return integrate(dot(grad(du),grad(v)) - lambda*exp(uh)*du*v);
}
problem::determinant_type
combustion::update_derivative (const field& uh) const {
  a1 = derivative (uh);
  solver_option sopt;
  sopt.compute_determinant = true;
  pa1 = problem (a1, sopt);
  return pa1.det();
}
field combustion::derivative_versus_parameter (const field& uh) const {
  test v(Xh);
  return - integrate(exp(uh)*v);
}
field combustion::derivative_solve (const field& rh) const {
  field delta_uh (Xh,0);
  pa1.solve (rh, delta_uh);
  return delta_uh;
}
field combustion::derivative_trans_mult (const field& mrh) const {
  field rh = unmassify(mrh);
  field mgh = a1*rh;
  mgh["boundary"] = 0;
  return mgh;
}
field combustion::unmassify (const field& mrh) const {
  field rh (Xh, 0);
  pm.solve (mrh, rh);
  return rh;
}
Float combustion::space_dot (const field& xh, const field& yh) const {
  return m(xh,yh); }
Float combustion::dual_space_dot (const field& mrh, const field& msh) const{
  return dual(unmassify(mrh), msh); }
