diff --git a/lua/CMakeLists.txt b/lua/CMakeLists.txt
index 75a083eecf8479ed95a24a051f891a52f1f5abcc..cbf1abc63de5a4b931fdfb9f4396c26b1414b551 100644
--- a/lua/CMakeLists.txt
+++ b/lua/CMakeLists.txt
@@ -4,6 +4,11 @@ set(src
   LuaMesh.cpp
   LuaGroupOfElement.cpp
   LuaFunctionSpace.cpp
+
+  LuaDofTest.cpp
+  LuaDof.cpp
+  LuaTest.cpp
+  LuaIntegrand.cpp
   LuaFormulation.cpp
   LuaSystem.cpp
 )
diff --git a/lua/LuaDof.cpp b/lua/LuaDof.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b471210cd4cd513f6bead66824ccae30483ad86a
--- /dev/null
+++ b/lua/LuaDof.cpp
@@ -0,0 +1,55 @@
+#include "LuaDof.h"
+
+#ifdef HAVE_LUA
+
+extern "C"{
+#include "lauxlib.h"
+}
+
+using namespace sf;
+using namespace std;
+
+
+const struct luaL_Reg libsf_Dof_f[] = {
+  {"Dof", lua_Dof_new},
+  {NULL,  NULL}
+};
+
+const struct luaL_Reg libsf_Dof_m[] = {
+  {"__mul",      lua_Dof_associate},
+  {"__tostring", lua_Dof_toString},
+  {"__gc",       lua_Dof_delete},
+  {NULL,         NULL}
+};
+
+extern "C" int luaopen_libsf_dof(lua_State *L){
+  luaL_newmetatable(L, "sf.Dof");   // Metatable
+  lua_pushvalue(L, -1);             //  --> duplicate
+  lua_setfield(L, -2, "__index");   //  --> __index
+  luaL_setfuncs(L, libsf_Dof_m, 0); // Methods
+  luaL_newlib(L, libsf_Dof_f);      // Library
+
+  return 1;
+}
+
+
+int lua_Dof_new(lua_State *L){
+  return lua_DofTest_new(L, "sf.Dof");
+}
+
+int lua_Dof_delete(lua_State *L){
+  return lua_DofTest_delete(L, "sf.Dof");
+}
+
+int lua_Dof_associate(lua_State *L){
+  lua_DofTest **dof  = (lua_DofTest**)luaL_checkudata(L, 1, "sf.Dof");
+  lua_DofTest **test = (lua_DofTest**)luaL_checkudata(L, 2, "sf.Test");
+
+  return lua_DofTest_associate(L, *dof, *test);
+}
+
+int lua_Dof_toString(lua_State *L){
+  return lua_DofTest_toString(L, "sf.Dof");
+}
+
+#endif
diff --git a/lua/LuaDof.h b/lua/LuaDof.h
new file mode 100644
index 0000000000000000000000000000000000000000..216e0c4fe4e898b08548bf1dba3ad767e3f758d3
--- /dev/null
+++ b/lua/LuaDof.h
@@ -0,0 +1,21 @@
+#ifndef _LUADOF_H_
+#define _LUADOF_H_
+
+#include "SmallFemConfig.h"
+#ifdef HAVE_LUA
+
+#include "LuaDofTest.h"
+extern "C"{
+#include "lua.h"
+}
+
+extern "C" int luaopen_libsf_dof(lua_State *L);
+
+int lua_Dof_new(lua_State *L);
+int lua_Dof_delete(lua_State *L);
+
+int lua_Dof_associate(lua_State *L);
+int lua_Dof_toString(lua_State *L);
+
+#endif
+#endif
diff --git a/lua/LuaDofTest.cpp b/lua/LuaDofTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..428f1bfdaff80789a46303cfd2d147685e251bc7
--- /dev/null
+++ b/lua/LuaDofTest.cpp
@@ -0,0 +1,90 @@
+#include "LuaDofTest.h"
+
+#ifdef HAVE_LUA
+
+#include "LuaFunctionSpace.h"
+#include "LuaIntegrand.h"
+extern "C"{
+#include "lauxlib.h"
+}
+
+using namespace sf;
+using namespace std;
+
+
+int lua_DofTest_new(lua_State *L, string type){
+  // Take FunctionSpace //
+  FunctionSpace **fs =
+    (FunctionSpace**)luaL_checkudata(L, 1, "sf.FunctionSpace");
+
+  // Dof or Test //
+  lua_DofTest dt;
+  dt.functionspace = *fs;
+  dt.derivative    = false;
+
+  return lua_DofTest_new(L, &dt, type);
+}
+
+int lua_DofTest_new(lua_State *L, lua_DofTest *dt, string type){
+  // Sanity //
+  if((type.compare("sf.Dof") != 0 && type.compare("sf.Test") != 0)
+     || dt == NULL)
+    luaL_error(L, "lua_DofTest_new: incoherent state =/!");
+
+  // New //
+  lua_DofTest **lua = (lua_DofTest**)lua_newuserdata(L, sizeof(lua_DofTest*));
+  *lua = new lua_DofTest;
+
+  (*lua)->functionspace = dt->functionspace;
+  (*lua)->derivative    = dt->derivative;
+
+  luaL_getmetatable(L, type.c_str());
+  lua_setmetatable(L, -2);
+
+  // Done //
+  return 1;
+}
+
+int lua_DofTest_delete(lua_State *L, string type){
+  lua_DofTest **lua = (lua_DofTest**)luaL_checkudata(L, 1, type.c_str());
+  if(*lua)
+    delete *lua;
+
+  return 0;
+}
+
+int lua_DofTest_associate(lua_State *L, lua_DofTest *dof, lua_DofTest *test){
+  lua_Integrand **lua =
+    (lua_Integrand**)lua_newuserdata(L, sizeof(lua_Integrand*));
+  *lua = new lua_Integrand;
+  (*lua)->dof  = dof;
+  (*lua)->test = test;
+
+  luaL_getmetatable(L, "sf.Integrand");
+  lua_setmetatable(L, -2);
+
+  return 1;
+}
+
+int lua_DofTest_toString(lua_State *L, string type){
+  lua_DofTest **lua = (lua_DofTest**)luaL_checkudata(L, 1, type.c_str());
+  lua_pushstring(L, lua_DofTest_toString(*lua).c_str());
+
+  return 1;
+}
+
+string lua_DofTest_toString(lua_DofTest *dt){
+  stringstream str;
+  str << lua_FunctionSpace_toString(dt->functionspace)
+      << " | "
+      << "Derivative: ";
+
+  if(dt->derivative)
+    str << "True";
+  else
+    str << "False";
+
+  return str.str();
+}
+
+#endif
diff --git a/lua/LuaDofTest.h b/lua/LuaDofTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..31c666011e65797ef509597980207cb741db83ff
--- /dev/null
+++ b/lua/LuaDofTest.h
@@ -0,0 +1,26 @@
+#ifndef _LUADOFTEST_H_
+#define _LUADOFTEST_H_
+
+#include "SmallFemConfig.h"
+#ifdef HAVE_LUA
+
+#include "FunctionSpace.h"
+extern "C"{
+#include "lua.h"
+}
+
+typedef struct{
+  sf::FunctionSpace *functionspace;
+  bool              derivative;
+} lua_DofTest;
+
+int lua_DofTest_new(lua_State *L, std::string type);
+int lua_DofTest_new(lua_State *L, lua_DofTest *dt, std::string type);
+int lua_DofTest_delete(lua_State *L, std::string type);
+
+int lua_DofTest_associate(lua_State *L, lua_DofTest *dof, lua_DofTest *test);
+int         lua_DofTest_toString(lua_State *L, std::string type);
+std::string lua_DofTest_toString(lua_DofTest *dt);
+
+#endif
+#endif
diff --git a/lua/LuaFormulation.cpp b/lua/LuaFormulation.cpp
index b806332f30036091f591ed904a36bff6bdade181..e95872fac2f91a5d35005b969af28b7e01381029 100644
--- a/lua/LuaFormulation.cpp
+++ b/lua/LuaFormulation.cpp
@@ -2,6 +2,7 @@
 
 #ifdef HAVE_LUA
 
+#include "LuaIntegrand.h"
 extern "C"{
 #include "lauxlib.h"
 }
@@ -55,7 +56,9 @@ int lua_Formulation_new(lua_State *L){
 
   FunctionSpace *field; bool isFieldDerived;
   FunctionSpace *test;  bool isTestDerived;
-  lua_Formulation_getIntegrand(L, &field, &isFieldDerived, &test, &isTestDerived);
+  lua_Formulation_getIntegrand(L,
+                               &field, &isFieldDerived,
+                               &test, &isTestDerived);
   lua_remove(L, -1);
 
   // Get quadrature order (optional) //
@@ -123,49 +126,19 @@ void lua_Formulation_getDomain(lua_State *L,
 
 }
 
-void lua_Formulation_getIntegrand(lua_State *L,
-                                  FunctionSpace **fs, bool *derivative,
-                                  string type){
-  // Function space //
-  lua_pushstring(L, "functionspace");
-  lua_gettable(L, -2);
-  if(lua_isnoneornil(L, -1))
-    luaL_error(L, "%s: no function space (functionspace) given", type.c_str());
-
-  FunctionSpace **lua =
-    (FunctionSpace**)luaL_testudata(L, -1, "sf.FunctionSpace");
-  if(lua == NULL)
-    luaL_error(L, "%s: the given function space (functionspace) is invalid",
-               type.c_str());
-  *fs = *lua;
-  lua_remove(L, -1);
-
-  // Derivative //
-  lua_pushstring(L, "derivative");
-  lua_gettable(L, -2);
-  if(lua_isnoneornil(L, -1))
-    luaL_error(L, "%s: no derivative given", type.c_str());
-
-  if(!lua_isboolean(L, -1))
-    luaL_error(L, "%s: derivative must be a boolean", type.c_str());
-  *derivative = lua_toboolean(L, -1);
-  lua_remove(L, -1);
-}
-
 void lua_Formulation_getIntegrand(lua_State *L,
                                   FunctionSpace **dofFs, bool *dofD,
                                   FunctionSpace **testFs, bool *testD){
+  // Get integrand //
+  lua_Integrand **lua = (lua_Integrand**)luaL_checkudata(L, -1, "sf.Integrand");
+
   // Get ansatz part //
-  lua_pushstring(L, "dof");
-  lua_gettable(L, -2);
-  lua_Formulation_getIntegrand(L, dofFs, dofD, "Dof");
-  lua_remove(L, -1);
+  *dofFs = (*lua)->dof->functionspace;
+  *dofD  = (*lua)->dof->derivative;
 
   // Get test part //
-  lua_pushstring(L, "test");
-  lua_gettable(L, -2);
-  lua_Formulation_getIntegrand(L, testFs, testD, "Test");
-  lua_remove(L, -1);
+  *testFs = (*lua)->test->functionspace;
+  *testD  = (*lua)->test->derivative;
 }
 
 #endif
diff --git a/lua/LuaFormulation.h b/lua/LuaFormulation.h
index e671f2242cd8e1864a8f47081276832ae4989618..5f4a3a5573a45aa51491bc593a0b4c59c78d35aa 100644
--- a/lua/LuaFormulation.h
+++ b/lua/LuaFormulation.h
@@ -18,9 +18,6 @@ int lua_Formulation_delete(lua_State *L);
 
 void lua_Formulation_getDomain(lua_State *L,
                                std::vector<const sf::GroupOfElement*>& vGoe);
-void lua_Formulation_getIntegrand(lua_State *L,
-                                  sf::FunctionSpace **fs, bool *derivative,
-                                  std::string type);
 void lua_Formulation_getIntegrand(lua_State *L,
                                   sf::FunctionSpace **dofFs, bool *dofD,
                                   sf::FunctionSpace **testFs, bool *testD);
diff --git a/lua/LuaIntegrand.cpp b/lua/LuaIntegrand.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7fbfdf0e52a7ae9b2e7203969ecb479e3ae1698
--- /dev/null
+++ b/lua/LuaIntegrand.cpp
@@ -0,0 +1,77 @@
+#include "LuaIntegrand.h"
+
+#ifdef HAVE_LUA
+
+extern "C"{
+#include "lauxlib.h"
+}
+
+using namespace sf;
+using namespace std;
+
+
+const struct luaL_Reg libsf_Integrand_f[] = {
+  {"derivative", lua_Integrand_derivative},
+  {NULL,         NULL}
+};
+
+const struct luaL_Reg libsf_Integrand_m[] = {
+  {"__tostring", lua_Integrand_toString},
+  {"__gc",       lua_Integrand_delete},
+  {NULL,         NULL}
+};
+
+extern "C" int luaopen_libsf_integrand(lua_State *L){
+  luaL_newmetatable(L, "sf.Integrand");   // Metatable
+  lua_pushvalue(L, -1);                   //  --> duplicate
+  lua_setfield(L, -2, "__index");         //  --> __index
+  luaL_setfuncs(L, libsf_Integrand_m, 0); // Methods
+  luaL_newlib(L, libsf_Integrand_f);      // Library
+
+  return 1;
+}
+
+
+int lua_Integrand_delete(lua_State *L){
+  lua_Integrand **lua = (lua_Integrand**)luaL_checkudata(L, 1, "sf.Integrand");
+  if(*lua)
+    delete *lua;
+
+  return 0;
+}
+
+int lua_Integrand_toString(lua_State *L){
+  lua_Integrand **lua = (lua_Integrand**)luaL_checkudata(L, 1, "sf.Integrand");
+
+  stringstream str;
+  str << "Integrand: " << endl
+      << " * Dof  - "  << lua_DofTest_toString((*lua)->dof) << endl
+      << " * Test - "  << lua_DofTest_toString((*lua)->test);
+
+  lua_pushstring(L, str.str().c_str());
+  return 1;
+}
+
+int lua_Integrand_derivative(lua_State *L){
+  lua_DofTest **dof  = (lua_DofTest**)luaL_testudata(L, 1, "sf.Dof");
+  lua_DofTest **test = (lua_DofTest**)luaL_testudata(L, 1, "sf.Test");
+
+  string       type;
+  lua_DofTest *item = NULL;
+  if(dof){
+    type = "sf.Dof";
+    item = *dof;
+  }
+  else if(test){
+    type = "sf.Test";
+    item = *test;
+  }
+  else{
+    luaL_error(L, "Integrand: derivative takes a Dof or a Test as argument");
+  }
+
+  item->derivative = true;
+  return lua_DofTest_new(L, item, type);
+}
+
+#endif
diff --git a/lua/LuaIntegrand.h b/lua/LuaIntegrand.h
new file mode 100644
index 0000000000000000000000000000000000000000..816069c7bdc2e31f56b5bc62c1a944d352e5bbb2
--- /dev/null
+++ b/lua/LuaIntegrand.h
@@ -0,0 +1,25 @@
+#ifndef _LUAINTEGRAND_H_
+#define _LUAINTEGRAND_H_
+
+#include "SmallFemConfig.h"
+#ifdef HAVE_LUA
+
+#include "LuaDof.h"
+extern "C"{
+#include "lua.h"
+}
+
+extern "C" int luaopen_libsf_integrand(lua_State *L);
+
+typedef struct{
+  lua_DofTest *dof;
+  lua_DofTest *test;
+} lua_Integrand;
+
+int lua_Integrand_delete(lua_State *L);
+int lua_Integrand_toString(lua_State *L);
+
+int lua_Integrand_derivative(lua_State *L);
+
+#endif
+#endif
diff --git a/lua/LuaTest.cpp b/lua/LuaTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..38756420e81a72b4fa4a16825b2a6fb34a699726
--- /dev/null
+++ b/lua/LuaTest.cpp
@@ -0,0 +1,55 @@
+#include "LuaTest.h"
+
+#ifdef HAVE_LUA
+
+extern "C"{
+#include "lauxlib.h"
+}
+
+using namespace sf;
+using namespace std;
+
+
+const struct luaL_Reg libsf_Test_f[] = {
+  {"Test", lua_Test_new},
+  {NULL,  NULL}
+};
+
+const struct luaL_Reg libsf_Test_m[] = {
+  {"__mul",      lua_Test_associate},
+  {"__tostring", lua_Test_toString},
+  {"__gc",       lua_Test_delete},
+  {NULL,         NULL}
+};
+
+extern "C" int luaopen_libsf_test(lua_State *L){
+  luaL_newmetatable(L, "sf.Test");   // Metatable
+  lua_pushvalue(L, -1);             //  --> duplicate
+  lua_setfield(L, -2, "__index");   //  --> __index
+  luaL_setfuncs(L, libsf_Test_m, 0); // Methods
+  luaL_newlib(L, libsf_Test_f);      // Library
+
+  return 1;
+}
+
+
+int lua_Test_new(lua_State *L){
+  return lua_DofTest_new(L, "sf.Test");
+}
+
+int lua_Test_delete(lua_State *L){
+  return lua_DofTest_delete(L, "sf.Test");
+}
+
+int lua_Test_associate(lua_State *L){
+  lua_DofTest **test = (lua_DofTest**)luaL_checkudata(L, 1, "sf.Test");
+  lua_DofTest **dof  = (lua_DofTest**)luaL_checkudata(L, 2, "sf.Dof");
+
+  return lua_DofTest_associate(L, *dof, *test);
+}
+
+int lua_Test_toString(lua_State *L){
+  return lua_DofTest_toString(L, "sf.Test");
+}
+
+#endif
diff --git a/lua/LuaTest.h b/lua/LuaTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..5adadd3f7741605aecb59360fc455b098ca4dd6a
--- /dev/null
+++ b/lua/LuaTest.h
@@ -0,0 +1,21 @@
+#ifndef _LUATEST_H_
+#define _LUATEST_H_
+
+#include "SmallFemConfig.h"
+#ifdef HAVE_LUA
+
+#include "LuaDofTest.h"
+extern "C"{
+#include "lua.h"
+}
+
+extern "C" int luaopen_libsf_test(lua_State *L);
+
+int lua_Test_new(lua_State *L);
+int lua_Test_delete(lua_State *L);
+
+int lua_Test_associate(lua_State *L);
+int lua_Test_toString(lua_State *L);
+
+#endif
+#endif