
// Copyright (C) 2007 Johan Jansson.
// Licensed under the GNU GPL Version 2.

#include <dolfin.h>
#include <unicorn/ElasticityPDE.h>
#include "unicorn/Coefficients.h"

using namespace dolfin;
using namespace dolfin::unicorn;

  
int main()
{
  //UnitSquare mesh(20, 10);
  UnitCube mesh(12, 6, 6);
  
  transform(mesh);

  //Mesh mesh("testcell2D.xml");
  //Mesh mesh("testcell3D.xml");

  //int d = mesh.topology().dim();

  real E = 1.0e3; // Young's modulus
  real nu = 0.0; // Poisson's ratio

  real lmbdaval = E * nu / ((1 + nu) * (1 - 2 * nu));
  real muval = E / (2 * (1 + nu));

  real betaval = 0.0 * muval; // Damping (sqrt(E))

  real kk = 2.0e-02;

  cout << "lmbda: " << lmbdaval << endl;
  cout << "mu: " << muval << endl;

  MySource f(mesh);
  Density rho(mesh);
  MyBC bcf(mesh);
  InitialValue u0(mesh);

  Function lmbda(mesh, lmbdaval);
  Function mu(mesh, muval);
  Function beta(mesh, betaval);
  Function kf(mesh, kk);

  DirichletBoundary dboundary;

  DirichletBC bc(bcf, mesh, dboundary);

  real T = 2.0;

  set("ODE method", "cg");
  set("ODE order", 1);
  //set("ODE implicit", false);
  set("ODE implicit", true);
  set("ODE nonlinear solver", "newton");
  //set("ODE linear solver", "direct");
  set("ODE linear solver", "iterative");
  set("ODE matrix-free jacobian", false);
  //set("ODE M matrix constant", true);
  set("ODE tolerance", 1.0e-01);
  set("ODE discrete tolerance", 1.0e-01);
  
  set("ODE monitor convergence", true);
  
  set("ODE fixed time step", true);
  set("ODE initial time step", kk);
  set("ODE maximum time step", kk);

  set("ODE save solution", false);
  
  Function U;
  Function B;
  Function B0;

  Form* a;
  Form* L;
  Form* aJac;
  Form* aS;
  Form* LS;
  Form* aP;
  Form* LP;

  FormFactory(mesh,
	      a, L, aJac, aS, LS, aP, LP,
	      U, B, u0, rho, mu, lmbda, beta, kf, f);

  ElasticityPDE pde(a, L, mesh, bc, T, aJac, aP, LP, aS, LS, U, B, B0, kk);

  // Compute solution
  pde.solve(U);

  return 0;
}
