#include "unicorn/CNSmix2D.h"
#include "unicorn/CNSmix3D.h"
#include "unicorn/CNSResDensity2D.h"
#include "unicorn/CNSResDensity3D.h"
#include "unicorn/CNSResMomentum2D.h"
#include "unicorn/CNSResMomentum3D.h"
#include "unicorn/CNSResEnergy2D.h"
#include "unicorn/CNSResEnergy3D.h"

#include "unicorn/FormFactory.h"

using namespace dolfin;
using namespace dolfin::unicorn;

void dolfin::unicorn::
FormFactory(Mesh& mesh,
	    Form*& a, Form*& L,
	    Form*& Lres_rho,
	    Form*& Lres_m, Form*& Lres_e,
	    Function& w0,
	    Function& u,
	    Function& um,
	    Function& P,
	    Function& rho,
	    Function& rho0,
	    Function& m,
	    Function& m0,
	    Function& e,
	    Function& e0,
	    Function& nu_rho,
	    Function& nu_m,
	    Function& nu_e,
	    Function& delta,
	    Function& vol_inv,
	    Function& fk)
{
  int nsdim = mesh.topology().dim();

  if ( nsdim == 3 )
    {
       a = new CNSmix3DBilinearForm(um, delta, nu_rho, nu_m, nu_e, fk);
       L = new CNSmix3DLinearForm(w0, P, um, delta, nu_rho, nu_m, nu_e, fk);

       Lres_rho = new CNSResDensity3DLinearForm(u, rho, rho0, vol_inv, fk);
       Lres_m   = new CNSResMomentum3DLinearForm(P, u, m, m0, vol_inv, fk);
       Lres_e   = new CNSResEnergy3DLinearForm(P, u, e, e0, vol_inv, fk);

    }
  else if ( nsdim == 2 )
    {
       a = new CNSmix2DBilinearForm(um, delta, nu_rho, nu_m, nu_e, fk);
       L = new CNSmix2DLinearForm(w0, P, um, delta, nu_rho, nu_m, nu_e, fk);

       Lres_rho = new CNSResDensity2DLinearForm(u, rho, rho0, vol_inv, fk);
       Lres_m   = new CNSResMomentum2DLinearForm(P, u, m, m0, vol_inv, fk);
       Lres_e   = new CNSResEnergy2DLinearForm(P, u, e, e0, vol_inv, fk);
    }
  else
    {
      error("CNS-Stokes solver only implemented for 2 and 3 space dimensions.");
    }
  
}

