diff --git a/Lbracket/topo.geo b/Lbracket/topo.geo
new file mode 100644
index 0000000000000000000000000000000000000000..959aca07f33039902f603189122887ada66f89e6
--- /dev/null
+++ b/Lbracket/topo.geo
@@ -0,0 +1,39 @@
+lc=0.004;
+mm=1e-3;
+
+Point(1) = {0, 0, 0, lc};
+Point(2) = {600*mm, 0, 0, lc};
+Point(3) = {600*mm, 240*mm, 0, lc};
+Point(4) = {240*mm, 240*mm, 0, lc};
+Point(5) = {240*mm, 600*mm, 0, lc};
+Point(6) = {0, 600*mm, 0, lc};
+Point(10) = {(600-10)*mm, 240*mm, 0, lc};
+Point(11) = {(600-10)*mm, (240-30)*mm, 0, lc};
+Point(12) = {600*mm, (240-30)*mm, 0, lc};
+
+Line(1) = {6, 1};
+Line(2) = {1, 2};
+Line(3) = {2, 12};
+Line(4) = {12, 3};
+Line(5) = {10, 3};
+Line(6) = {10, 4};
+Line(7) = {4, 5};
+Line(8) = {5, 6};
+Line(9) = {12, 11};
+Line(10) = {11, 10};
+
+Line Loop(1) = {1, 2, 3, 9, 10, 6, 7, 8};
+Plane Surface(1) = {1};
+
+Line Loop(2) = -{9, 10, 5, -4};
+Plane Surface(2) = {2};
+
+Physical Surface(1000) = {1};
+Physical Surface(1004) = {2};
+Physical Line(1001) = {8};
+Physical Line(1003) = {4};
+Physical Point(1002) = {3};
+
+Solver.AutoMesh = 0;
+Mesh.Algorithm = 1; 
+
diff --git a/Lbracket/topo.pro b/Lbracket/topo.pro
new file mode 100644
index 0000000000000000000000000000000000000000..817b987007fb10c3a7bbd7cff1b7e4c52adeb781
--- /dev/null
+++ b/Lbracket/topo.pro
@@ -0,0 +1,755 @@
+Struct OPT::YOUNG_LAW [ Enum, simp, modifiedSimp, ramp, none];
+
+DefineConstant [
+  Opt_ResDir = "res_opt/"
+  Opt_ResDir_Onelab = "Optimization/Results/"
+  densityFieldInit = {0.5, Name "Optimization/3Density/0Inital value"}
+  Opt_filter_radius = {0.004, Name "Optimization/3Density/2filter radius"}
+  Flag_PrintLevel = {1, Name "General/Verbosity", Visible 1}
+  Flag_opt_matlaw = {OPT::YOUNG_LAW.modifiedSimp, 
+    Choices {
+      OPT::YOUNG_LAW.simp="simp",
+      OPT::YOUNG_LAW.modifiedSimp="modified-simp",
+      OPT::YOUNG_LAW.ramp="ramp",
+      OPT::YOUNG_LAW.none="none"},	
+    Name "Optimization/5Young Interpolation/0Material law"}
+  Flag_opt_matlaw_penal = {3.0, 
+    Name "Optimization/5Young Interpolation/1penalization",
+    Visible (Flag_opt_matlaw == OPT::YOUNG_LAW.simp 
+       || Flag_opt_matlaw == OPT::YOUNG_LAW.ramp
+       || Flag_opt_matlaw == OPT::YOUNG_LAW.modifiedSimp) }
+  Flag_opt_stress_penal = {2.5, 
+    Name "Optimization/5Young Interpolation/2penalization of stress",
+    Visible Flag_opt_matlaw != OPT::YOUNG_LAW.none}
+  Flag_EPC = 1
+  iP = 1     
+];
+
+Group {
+  Sur_Clamp~{iP} = Region[{1001}];
+  Vol_Force~{iP} = Region[{}];
+  Sur_Force~{iP} = Region[{1003}];
+  Vol_Elast~{iP} = Region[{1000,1004}];
+  Domain~{iP} = Region[ { Vol_Elast~{iP}, 
+			  Vol_Force~{iP},
+                          Sur_Force~{iP}, 
+			  Sur_Clamp~{iP}} ];
+
+  // Define the group for topology optimization 
+  DomainDensity = Region[1000];
+}
+
+Function {
+  YoungFull = 1.0; // N/m2
+  PoissonFull = 0.33; 
+  rhoElastFull = 7874.0; // kg/m3
+
+  Poisson[] = PoissonFull;
+  rhoElast[Region[{Vol_Elast~{iP},-DomainDensity}]] = rhoElastFull;
+  Young[Region[{Vol_Elast~{iP},-DomainDensity}]] = YoungFull;
+
+  // Handling of the modified Young law - allowing to set up a continuous
+  // problem with smoothly varying material properties between the "material"
+  // and "void" regions.
+  If(Flag_opt_matlaw == OPT::YOUNG_LAW.simp) 
+    Young[DomainDensity] = YoungFull * $1 ^ Flag_opt_matlaw_penal;
+    dYoung[DomainDensity] = Flag_opt_matlaw_penal * YoungFull * $1 ^ (Flag_opt_matlaw_penal - 1);
+  ElseIf(Flag_opt_matlaw == OPT::YOUNG_LAW.modifiedSimp) 
+    YoungMin = 1e-6;
+    Young[DomainDensity] = YoungMin + (YoungFull-YoungMin) * $1 ^ Flag_opt_matlaw_penal;
+    dYoung[DomainDensity] = Flag_opt_matlaw_penal * (YoungFull-YoungMin) * $1 ^ (Flag_opt_matlaw_penal - 1);
+  ElseIf(Flag_opt_matlaw == OPT::YOUNG_LAW.ramp) 
+    YoungMin = 1.0e-6;
+    Young[DomainDensity] = YoungMin + $1*(YoungFull-YoungMin)/(1.0+Flag_opt_matlaw_penal*(1.0-$1));
+    dYoung[DomainDensity] = (YoungFull-YoungMin)*(1.0+Flag_opt_matlaw_penal)/(1.0+Flag_opt_matlaw_penal*(1.0-$1))^2.0;
+  EndIf
+
+  // Force for elastic model
+  pressure_x[Region[1003]] = 0;
+  pressure_y[Region[1003]] = -2.5;
+
+  // Plane stress
+  a[] = Young[$1]/(1.-Poisson[]^2); //$1:{xe}
+  c[] = Young[$1]*Poisson[]/(1.-Poisson[]^2);
+  a1[] = 1/(1.-Poisson[]^2); //$1:{xe}
+  c1[] = Poisson[]/(1.-Poisson[]^2);
+  b1[] = 1./2./(1.+Poisson[]);
+
+  C_xx[] = Tensor[ (Young[$1])#9000*a1[],0  ,0  ,    0  ,#9000*b1[],0 , 0 ,0,#9000*b1[]];
+  C_xy[] = Tensor[ 0  ,#9000*c1[],0  ,    #9000*b1[],0  ,0  ,    0  ,0  ,0   ];
+
+  C_yx[] = Tensor[ 0  ,#9000*b1[],0  ,    #9000*c1[],0  ,0  ,    0  ,0  ,0   ];
+  C_yy[] = Tensor[ #9000*b1[],0  ,0  ,    0  ,#9000*a1[],0  ,    0  ,0  ,#9000*b1[]];
+
+  // macroscopic stress (voigt notation),
+  // with $1:{d ux}, $2:{d uy}, $3:{xe}
+  C_2d[] = a[$1] * TensorSym[1,Poisson[],0,  1,0,  (1-Poisson[])/2];
+  epsElast[] = Vector[CompX[$1],CompY[$2],CompY[$1]+CompX[$2]];
+  sigM[] = C_2d[1] * epsElast[$1,$2]; 
+
+  // Von-Mises stress (scalar)
+  // with $1:{d ux}, $2:{d uy}, $3:{xe}
+  VMmat[] = TensorSym[1., -0.5, 0., 1., 0., 3.];
+  sigVM[] = Sqrt[sigM[$1,$2]#1015 * (VMmat[] * #1015)];
+
+  sigVMqp[#{Vol_Elast~{iP},-DomainDensity}] = sigVM[$1,$2];
+  sigVMqp[DomainDensity] = ($3 ^ (Flag_opt_matlaw_penal-Flag_opt_stress_penal)) * sigVM[$1,$2];
+
+  // $1:{xe}, $2:{d ux}, $3:{d uy}
+  InternalEnergy[] = 0.5 * (C_xx[$1] * $2 + C_xy[$1] * $3) * $2
+   + 0.5 * (C_yx[$1] * $2 + C_yy[$1] * $3) * $3;
+
+  da1[] = 1 / (1 - Poisson[]^2);
+  dc1[] = Poisson[] / (1 - Poisson[]^2);
+  db1[] = 0.5 / (1 + Poisson[]);
+
+  dC_xx[] = Tensor[ (dYoung[$1]#6001)* da1[],0,0,0, #6001*db1[],0, 0,0,#6001*db1[] ];
+  dC_xy[] = Tensor[ 0,#6001*dc1[],0 ,#6001*db1[],0,0 ,0,0,0 ];
+
+  dC_yx[] = Tensor[ 0, #6001*db1[],0, #6001*dc1[],0,0, 0,0,0 ];
+  dC_yy[] = Tensor[ #6001*db1[],0,0, 0, #6001*da1[], 0,    0,0,#6001*db1[] ];
+
+  // $1:{xe}, $2:{d ux}, $3:{d uy}, $4:{d lamx}, $5:{d lamy}
+  GradPartialElast[] = (dC_xx[$1] * $2 + dC_xy[$1] * $3) * $4
+    + (dC_yx[$1] * $2 + dC_yy[$1] * $3) * $5;
+
+  uElast[] = Vector[$1,$2,0];
+}
+
+Jacobian {
+  { Name Vol; Case { { Region All ; Jacobian Vol; } } }
+  { Name Sur; Case { { Region All ; Jacobian Sur; } } }
+}
+
+Integration {
+  { Name I1 ; Case {
+      { Type Gauss ;
+        Case {
+          { GeoElement Triangle   ; NumberOfPoints  6 ; }
+	  { GeoElement Quadrangle ; NumberOfPoints  4 ; }
+	  { GeoElement Line       ; NumberOfPoints  13 ; }
+        }
+      }
+    }
+  }
+}
+
+// -------------------------------------------------------------------------
+
+// Density field handling (through a fully-fixed function space defined on
+// DomainDensity - a subset of ConductingDomain) and filtering. This is done on
+// densities, defined ayt the barycenter of elements.
+//
+// Beware of the special 1-point Gauss integration rule, which is required to
+// evaluate the densities precisely where the "Depth 0" post-operations generate
+// the data!
+
+Integration {
+  { Name GaussOnePoint ; Case {
+      { Type Gauss ;
+        Case {
+          { GeoElement Point       ; NumberOfPoints  1; }
+          { GeoElement Line        ; NumberOfPoints  1; }
+          { GeoElement Triangle    ; NumberOfPoints  1; }
+          { GeoElement Quadrangle  ; NumberOfPoints  1; }
+          { GeoElement Prism       ; NumberOfPoints  1; }
+          { GeoElement Tetrahedron ; NumberOfPoints  1; }
+          { GeoElement Hexahedron  ; NumberOfPoints  1; }
+          { GeoElement Pyramid     ; NumberOfPoints  1; }
+        }
+      }
+    }
+  }
+}
+
+Function {
+  l_xe() = ListFromServer["Optimization/Results/designVariable"];
+  If(#l_xe() > 1)
+    densityField[] = ValueFromIndex[]{l_xe()};
+  Else
+    densityField[] = densityFieldInit;
+  EndIf
+}
+
+Constraint {
+  { Name ConstraintDensity;
+    Case {
+      { Region DomainDensity; Value (densityField[]*ElementVol[]); }
+    }
+  }
+}
+
+FunctionSpace {
+  { Name H_DensityField; Type Form3; // filtered - L2
+    BasisFunction {
+      { Name sxn ; NameOfCoef uxn ; Function BF_Volume ;
+        Support DomainDensity; Entity VolumesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef uxn; EntityType VolumesOf; NameOfConstraint ConstraintDensity; }
+    }
+  }
+}
+
+Formulation {
+  { Name DensityField ; Type FemEquation ;
+    Quantity {
+      { Name xe ; Type Local ; NameOfSpace H_DensityField;}
+    }
+    Equation {
+      Galerkin { [ 0*Dof{xe}, {xe} ] ;
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }
+    }
+  }
+}
+
+Resolution {
+  { Name DensityField;
+    System {
+      { Name D; NameOfFormulation DensityField; }
+    }
+    Operation{
+      Generate[D];
+      // Solve[D]; // no need: no unknowns :-)
+      PostOperation[DensityField];
+    }
+  }
+}
+
+PostProcessing {
+  { Name DensityField; NameOfFormulation DensityField;
+    PostQuantity {
+      { Name xe; Value { Term { [{xe}]; In DomainDensity; Jacobian Vol;} } }
+    }
+  }
+}
+
+PostOperation {
+  { Name DensityField; NameOfPostProcessing DensityField;
+    Operation {
+      Print[ xe, OnElementsOf DomainDensity, Depth 0,
+        Format ElementTable, File "", Hidden 1,
+        SendToServer StrCat[Opt_ResDir_Onelab,"designVariable"]];
+      If(Flag_PrintLevel > 0)
+        CreateDir[Opt_ResDir];
+        Print[ xe, OnElementsOf DomainDensity,
+          File StrCat[Opt_ResDir,"xeCurrentMesh.pos"]];
+      EndIf
+    }
+  }
+}
+
+Function {
+  l_filt() = ListFromServer["Optimization/Results/filterInput"];
+  If(#l_filt() > 1)
+    filtSource[] = ValueFromIndex[]{l_filt()};
+  Else
+    filtSource[] = ***;
+  EndIf
+}
+
+Constraint {
+  { Name psi0;
+    Case {
+      { Region DomainDensity; Value filtSource[] * ElementVol[]; }
+    }
+  }
+}
+
+FunctionSpace {
+  { Name H_psi0; Type Form3;
+    BasisFunction {
+      { Name sn ; NameOfCoef un ; Function BF_Volume ;
+        Support DomainDensity; Entity VolumesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef un; EntityType VolumesOf; NameOfConstraint psi0; }
+    }
+  }
+  { Name H_psif ; Type Form0;
+    BasisFunction {
+      { Name sn ; NameOfCoef un ; Function BF_Node ;
+        Support DomainDensity; Entity NodesOf[ All ] ; }
+    }
+  }
+}
+
+Formulation {
+  { Name FilterDensity ; Type FemEquation ;
+    Quantity {
+      { Name psi0 ; Type Local ; NameOfSpace H_psi0;}
+      { Name psif ; Type Local ; NameOfSpace H_psif;}
+    }
+    Equation {
+      Galerkin { [ Dof{d psif} * Opt_filter_radius^2.0, {d psif} ] ;
+        In DomainDensity; Jacobian Vol ; Integration GaussOnePoint; }
+      Galerkin { [ Dof{psif}, {psif} ] ;
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }
+
+      Galerkin { [ -{psi0}, {psif} ] ;
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }
+
+      Galerkin { [ 0*Dof{psi0}, {psi0} ] ;
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint ; }
+    }
+  }
+}
+
+Resolution {
+  { Name FilterDensity;
+    System {
+      { Name F; NameOfFormulation FilterDensity; }
+    }
+    Operation{
+      InitSolution[F];
+      Generate[F];
+      Solve[F];
+      PostOperation[FilterDensity];
+    }
+  }
+}
+
+PostProcessing {
+  { Name FilterDensity; NameOfFormulation FilterDensity;
+    PostQuantity {
+      { Name filtSource; Value { Term { [ {psi0} ]; In DomainDensity;Jacobian Vol;} } }
+      { Name filtOut; Value { Term { [ {psif} ]; In DomainDensity; Jacobian Vol; } } }
+    }
+  }
+}
+
+PostOperation {
+  { Name FilterDensity; NameOfPostProcessing FilterDensity;
+    Operation {
+      Print[ filtOut, OnElementsOf DomainDensity, Depth 0,
+        Format ElementTable, File "", Hidden 1,
+        SendToServer StrCat[Opt_ResDir_Onelab,"filterOutput"]];
+      If(Flag_PrintLevel > 1)
+        CreateDir[Opt_ResDir];
+        Print[ filtOut, OnElementsOf DomainDensity, Depth 0, Format Table,
+          File StrCat[Opt_ResDir,"filtOut.pos"] ];
+      EndIf
+      If(Flag_PrintLevel > 5)
+        Print[ filtSource, OnElementsOf DomainDensity,
+          File StrCat[Opt_ResDir,"filtSource.pos"]];
+        Print[ filtOut, OnElementsOf DomainDensity,
+          File StrCat[Opt_ResDir,"filtOut_v.pos"]];
+      EndIf
+    }
+  }
+}
+
+// -------------------------------------------------------------------------
+
+// Handling of the direct linear elastic problem, using the densities to
+// interpolate the hook material law as well as the material density.
+
+Constraint {
+  { Name Displacement_x;
+    Case {
+      { Region Sur_Clamp~{iP} ; Type Assign ; Value 0; }
+    }
+  }
+  { Name Displacement_y;
+    Case {
+       { Region Sur_Clamp~{iP} ; Type Assign ; Value 0; }
+    }
+  }
+  { Name Displacement_z;
+    Case {
+       { Region Sur_Clamp~{iP} ; Type Assign ; Value 0; }
+    }
+  }
+}
+
+FunctionSpace {
+  { Name H_ux_Mec ; Type Form0 ;
+    BasisFunction {
+      { Name sxn ; NameOfCoef uxn ; Function BF_Node ;
+        Support Domain~{iP} ; Entity NodesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef uxn ;
+        EntityType NodesOf ; NameOfConstraint Displacement_x ; }
+    }
+  }
+  { Name H_uy_Mec ; Type Form0 ;
+    BasisFunction {
+      { Name syn ; NameOfCoef uyn ; Function BF_Node ;
+        Support Domain~{iP} ; Entity NodesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef uyn ;
+        EntityType NodesOf ; NameOfConstraint Displacement_y ; }
+    }
+  }
+}
+
+Formulation {
+  { Name Elast_u ; Type FemEquation ;
+    Quantity {
+      { Name ux  ; Type Local ; NameOfSpace H_ux_Mec ; }
+      { Name uy  ; Type Local ; NameOfSpace H_uy_Mec ; }
+      { Name xe ; Type Local ; NameOfSpace H_DensityField;}
+    }
+    Equation {
+      Galerkin { [ C_xx[{xe}] * Dof{d ux}, {d ux} ] ;
+        In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+      Galerkin { [ C_xy[{xe}] * Dof{d uy}, {d ux} ] ;
+        In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+      Galerkin { [ C_yx[{xe}] * Dof{d ux}, {d uy} ] ;
+        In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+      Galerkin { [ C_yy[{xe}] * Dof{d uy}, {d uy} ] ;
+        In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+
+      Galerkin { [ -pressure_x[] , {ux} ];
+        In Sur_Force~{iP} ; Jacobian Sur ; Integration I1 ; }
+      Galerkin { [ -pressure_y[] , {uy} ];
+        In Sur_Force~{iP} ; Jacobian Sur ; Integration I1 ; }
+
+      // DO NOT REMOVE!!!
+      Galerkin { [ 0*Dof{xe}, {xe} ] ;
+        In DomainDensity; Jacobian Vol ; Integration GaussOnePoint ; }
+    }
+  }
+}
+
+// -------------------------------------------------------------------------
+
+// Handling of the adjoint linear elastic problems, depending on the chosen
+// objective function.
+
+FunctionSpace {
+  { Name H_lamx_Mec ; Type Form0 ;
+    BasisFunction {
+      { Name sxn ; NameOfCoef uxn ; Function BF_Node ;
+        Support Domain~{iP} ; Entity NodesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef uxn ;
+        EntityType NodesOf ; NameOfConstraint Displacement_x ; }
+    }
+  }
+  { Name H_lamy_Mec ; Type Form0 ;
+    BasisFunction {
+      { Name syn ; NameOfCoef uyn ; Function BF_Node ;
+        Support Domain~{iP} ; Entity NodesOf[ All ] ; }
+    }
+    Constraint {
+      { NameOfCoef uyn ;
+        EntityType NodesOf ; NameOfConstraint Displacement_y ; }
+    }
+  }
+}
+
+Macro AdjointFormulationOf_Elast_u
+  /* 
+    Generate the adjoint formulation of EM_Formulations
+    for a given performance function, without the Frechet derivative terms. 
+    These are added by the user latter on. 
+ 
+    Input: _AdjointName_ -> the name of the adjoint formulation.
+  */
+
+  Formulation {
+    { Name S2N[_AdjointName_] ; Type FemEquation ;
+      Quantity {
+        { Name ux  ; Type Local ; NameOfSpace H_ux_Mec ; }
+        { Name uy  ; Type Local ; NameOfSpace H_uy_Mec ; }
+        { Name lamx  ; Type Local ; NameOfSpace H_lamx_Mec ; }
+        { Name lamy  ; Type Local ; NameOfSpace H_lamy_Mec ; }
+        { Name xe ; Type Local ; NameOfSpace H_DensityField;}
+      }
+      Equation {
+        Galerkin { [ Transpose[C_xx[{xe}]] * Dof{d lamx}, {d lamx} ] ;
+          In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+        Galerkin { [ Transpose[C_xy[{xe}]] * Dof{d lamx}, {d lamy} ] ;
+          In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+        Galerkin { [ Transpose[C_yx[{xe}]] * Dof{d lamy}, {d lamx} ] ;
+          In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+        Galerkin { [ Transpose[C_yy[{xe}]] * Dof{d lamy}, {d lamy} ] ;
+          In Vol_Elast~{iP} ; Jacobian Vol ; Integration I1 ; }
+
+        // DO NOT REMOVE!!!
+        Galerkin { [ 0*Dof{xe}, {xe} ] ;
+          In DomainDensity; Jacobian Vol ; Integration GaussOnePoint ; }
+      }
+    } 
+  }
+Return
+
+Macro CreateAdjointFormulation
+  // This Macro creates the adjoint formulation for a given perfromance function
+  // and a given physical problem.
+  //
+  // Input:
+  // * OPT_AdjointWithoutFrechet: name of the Macro which generates the adjoint
+  //   problem without the Frechet derivative terms.
+  // * OPT_FrechetDerivative: name of Macro which writes the Frechet
+  //   derivative Galerkin terms of the performance function
+  // * OPT_PartialDerivative: name of Macro which writes the partial
+  //   derivative post-op terms of the performance function
+  // Output:
+  // * The adjoint formulation for the given perfromance function with a name,
+  //   AdjointFormulationOf_OPT_PhysFormulationName_OPT_FrechetDerivative
+  // * The corresponding post-processing and post-operation
+  _AdjointName_ = StrCat[OPT_AdjointWithoutFrechet,"_",OPT_FrechetDerivative];
+
+  Printf[StrCat["Add the Frechet term ",OPT_FrechetDerivative,
+    " to the adjoint formulation ",OPT_AdjointWithoutFrechet]];
+
+  // Load the template of the adjoint formulation for a given physical system
+  // (specified by the string OPT_PhysFormulationName).
+  Call S2N[OPT_AdjointWithoutFrechet];
+
+  Formulation {
+    { // Adjoint formulation of OPT_FUNC_NAME
+      Append;
+      Name S2N[_AdjointName_]; Type FemEquation;
+
+      // Add the Fréchet derivative terms of the perfromanec function
+      Equation {
+        Call S2N[OPT_FrechetDerivative];
+      }
+    }
+  }
+
+  PostProcessing {
+    { // Adjoint postpro of OPT_FUNC_NAME
+      Append;
+      Name S2N[_AdjointName_]; NameOfFormulation S2N[_AdjointName_];
+      PostQuantity {
+        // Add the Partial derivative of the performance function
+        If(Exists(OPT_PartialDerivative))
+          Call S2N[OPT_PartialDerivative];
+        EndIf
+      }
+    }
+  }
+Return
+
+// -------------------------------------------------------------------------
+
+// In the following, we create the post-operations necessary 
+// for the computation of objective and constraints.
+// We also make use of the adjoint method to compute their
+// sensitivity wit respect to the density field.
+
+DefineConstant[
+  PARAM_pnorm = {8,
+    Name "Optimization/7Parameter(s) of performances/Von-Mises/Pnorm penalization"}
+];
+
+PostProcessing{ 
+  { Name ObjectiveConstraints; NameOfFormulation Elast_u; 
+    Quantity {
+      { Name density ; Value { Term { [ {xe} ]; In DomainDensity; Jacobian Vol; } } }
+      { Name Felast_pressure; Value { 
+        Term{ [ Vector[pressure_x[{xe}],pressure_y[{xe}],0] ];In Sur_Force~{iP}; }}}
+      { Name uElast ; Value { Term { [ uElast[ {ux},{uy}] ]; 
+        In Vol_Elast~{iP}; Jacobian Vol; } } }
+      { Name Young; Value { Term { [ Young[{xe}] ]; 
+        In Vol_Elast~{iP} ; Jacobian Vol; }}}
+
+      { Name VolumeDomainFull; Value { Integral { [ 1 ]; 
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint;}}}
+      { Name VolumeMaterial; Value { Integral { [ {xe} ];
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint;}}}
+
+      // internal energy
+      { Name Compliance; Value {
+        Integral { [ InternalEnergy[{xe}, {d ux}, {d uy}] ];
+          In DomainDensity ; Jacobian Vol; Integration I1; }}}
+
+      // macroscopic Von-Mises stresses 
+      { Name vonMises; Value { Term { [ sigVM[{d ux},{d uy}] ]; 
+        In Vol_Elast~{iP} ; Jacobian Vol; }}}
+
+      // qp-relaxed Von-Mises stresses
+      { Name vonMises_qp; Value { Term { [ sigVMqp[{d ux},{d uy},{xe}] ]; 
+        In Vol_Elast~{iP} ; Jacobian Vol; }}}
+
+      // P-norm of qp-relaxed Von-Mises stresses 
+      { Name vonMises_qp_sum; Value { Integral { 
+        [ (sigVMqp[{d ux},{d uy},{xe}]^PARAM_pnorm)/ElementVol[] ];
+        In DomainDensity;Jacobian Vol;Integration I1; }}}
+
+      { Name vonMises_qp_pnorm; Value { Term { Type Global; 
+        [ $vonMises_qp_sum ^ (1/PARAM_pnorm) ]; In Vol_Elast~{iP}; }}}
+    }
+  }
+}
+
+PostOperation Get_DensityField UsingPost ObjectiveConstraints {
+  CreateDir[Opt_ResDir];
+  Print[density, OnElementsOf DomainDensity,
+    File StrCat[Opt_ResDir,"densityField.pos"]];
+}
+PostOperation Get_ObjectiveConstraints UsingPost ObjectiveConstraints {
+  // Volume
+  Print[ VolumeDomainFull[DomainDensity], OnGlobal,
+    Format Table, File "", Color "LightYellow",
+    SendToServer StrCat[Opt_ResDir_Onelab,"VolumeDomainFull"] ];
+
+  Print[ VolumeMaterial[DomainDensity], OnGlobal,
+    Format Table, File "", Color "LightYellow",
+    SendToServer StrCat[Opt_ResDir_Onelab,"VolumeDomain"] ];
+
+  // p-norm of Von-Mises 
+  Print[ vonMises_qp_sum[DomainDensity], OnGlobal, 
+    Format Table, File "", StoreInVariable $vonMises_qp_sum ];
+
+  Print[ vonMises_qp_pnorm, OnRegion DomainDensity, 
+    Format Table, StoreInVariable $vonMises_qp_pnorm, File "", Color "LightYellow", 
+    SendToServer StrCat[Opt_ResDir_Onelab,"pnorm of Von-Mises"] ] ;
+
+  If(Flag_PrintLevel > 2)
+    CreateDir[Opt_ResDir];
+    Print[ vonMises_qp, OnElementsOf Vol_Elast~{iP},
+      File StrCat[Opt_ResDir,"vm_qp.pos"]];
+  EndIf
+  If(Flag_PrintLevel > 4)
+    Print[ vonMises, OnElementsOf Vol_Elast~{iP},
+      File StrCat[Opt_ResDir,"vm.pos"]];
+  EndIf
+  If(Flag_PrintLevel > 5)
+    Print[ Young, OnElementsOf Vol_Elast~{iP},
+      File StrCat[Opt_ResDir, "young.pos"] ];
+    //Print[ Felast_pressure, OnElementsOf Sur_Force~{iP},
+    //  File StrCat[Opt_ResDir, "force_pressure.pos"] ];
+    Print[ uElast, OnElementsOf Vol_Elast~{iP},
+      File StrCat[Opt_ResDir, "u.pos"] ];
+  EndIf
+}
+
+// -------------------------------------------------------------------------
+
+// Sensitivity of volume
+
+PostProcessing{ 
+  { Name GradOf_Volume; NameOfFormulation Elast_u; 
+    Quantity {
+      { Name SensVolume; Value { Integral{ [ 1. ]; 
+        In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }}}
+    }
+  }
+}
+
+PostOperation Get_GradOf_Volume UsingPost GradOf_Volume {
+  // evaluate the sensitivity of the volume fraction at the barycenter
+  // of the elements and store it with a reference "SensVolumeFraction"
+  Print[ SensVolume, OnElementsOf DomainDensity,
+    Format ElementTable, Depth 0, Name "", File "", Hidden 1,
+    SendToServer StrCat[Opt_ResDir_Onelab,"GradOfVolume"] ];
+  If (Flag_PrintLevel > 5)
+    CreateDir[Opt_ResDir];
+    Print[ SensVolume, OnElementsOf DomainDensity, Depth 1,
+      File StrCat[Opt_ResDir, StrCat["SensVolume.pos"]]] ;
+  EndIf
+}
+
+// -------------------------------------------------------------------------
+
+// Sensitivity of the p-norm of the Von-Mises
+
+Function {
+  pnormVMCoef_qp[] = ( $vonMises_qp_pnorm^(1-PARAM_pnorm) )
+    * ( sigVMqp[$1,$2,$3]^(PARAM_pnorm-1) ) / ElementVol[];
+
+  Frechet_VM_qp[] = pnormVMCoef_qp[$1,$2,$3]  
+    * ($3 ^ (Flag_opt_matlaw_penal-Flag_opt_stress_penal)) 
+    * (Transpose[C_2d[1]] * (VMmat[] * sigM[$1,$2]))
+    / sigVM[$1,$2];
+
+  Partial_VM_qp[] = pnormVMCoef_qp[$1,$2,$3] 
+    * (Flag_opt_matlaw_penal-Flag_opt_stress_penal)
+    * sigVMqp[$1,$2,$3] / $3 ; 
+
+  Frechet_VM_wrt_dux[] = Vector[CompX[Frechet_VM_qp[$1,$2,$3]#105], CompZ[#105], 0]; 
+  Frechet_VM_wrt_duy[] = Vector[CompZ[Frechet_VM_qp[$1,$2,$3]#105], CompY[#105], 0]; 
+}
+
+Macro OPT_FRECHET_PnormVonMises
+  // Galerkin Term of the Fréchet derivative of torque at a given u* 
+  Galerkin { [ - Frechet_VM_wrt_dux[{d ux},{d uy},{xe}], {d lamx} ];
+    In DomainDensity ; Jacobian Vol ; Integration I1 ; }
+  Galerkin { [ - Frechet_VM_wrt_duy[{d ux},{d uy},{xe}], {d lamy} ];
+    In DomainDensity ; Jacobian Vol ; Integration I1 ; }
+Return
+
+// Finally, we create the adjoint formulation of CurrentMismatchNorm
+OPT_AdjointWithoutFrechet = "AdjointFormulationOf_Elast_u";
+OPT_FrechetDerivative = "OPT_FRECHET_PnormVonMises"; 
+Call CreateAdjointFormulation; 
+nameAdjoint_vonMises = Str(_AdjointName_); 
+
+PostProcessing {
+  { Name GradOf_VonMises; NameOfFormulation S2N[nameAdjoint_vonMises];
+    PostQuantity {
+      { Name Grad_vm; 
+        Value { 
+          Integral {[ Partial_VM_qp[{d ux},{d uy},{xe}] ]; 
+            In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }
+          Integral {[ -GradPartialElast[{xe},{d ux},{d uy},{d lamx},{d lamy}] ]; 
+            In DomainDensity; Jacobian Vol; Integration GaussOnePoint; }
+        }
+      }
+
+      { Name lamElast ; Value { Term { [ uElast[ {lamx},{lamy}] ]; 
+        In Vol_Elast~{iP}; Jacobian Vol; } } }
+    }
+  }
+}
+
+PostOperation Get_GradOf_VonMises UsingPost GradOf_VonMises {
+  Print[ Grad_vm, OnElementsOf DomainDensity,
+    Name "", Depth 0, Format ElementTable, File "", Hidden 1,
+    SendToServer StrCat[Opt_ResDir_Onelab,"GradOfVonMises"] ];
+
+  If(Flag_PrintLevel > 5)
+    CreateDir[Opt_ResDir];
+    Print[ Grad_vm, OnElementsOf DomainDensity,
+      File StrCat[Opt_ResDir,"GradOfVonMises.pos"] ];
+    Print[ lamElast, OnElementsOf Vol_Elast~{iP},
+      File StrCat[Opt_ResDir,"lamElast.pos"] ];
+  EndIf
+}
+
+// -------------------------------------------------------------------------
+
+// Let us define the optimization problem.
+
+Resolution {
+  { Name ComputePerformancesAndGradient;
+    System {
+      { Name SYS; NameOfFormulation Elast_u;}
+      { Name LAM; NameOfFormulation S2N[nameAdjoint_vonMises];}
+    }
+    Operation {
+      // Initialization of the systems
+      InitSolution[SYS];
+      InitSolution[LAM];
+ 
+      // Show the density field
+      If(Flag_PrintLevel > 0)
+        PostOperation[Get_DensityField];
+      EndIf
+
+      // Provide the density field to {xe} of the physical system
+      UpdateConstraint[SYS];
+
+      // Solve the physical problem
+      Generate[SYS];
+      Solve[SYS];
+
+      // Compute the objective function and the constraints
+      PostOperation[Get_ObjectiveConstraints];
+
+      // Compute the sensitivity of objective/constraints
+      PostOperation[Get_GradOf_Volume];
+      Generate[LAM];
+      SolveAgainWithOther[LAM,SYS];
+      PostOperation[Get_GradOf_VonMises];
+    }
+  }
+}
diff --git a/Lbracket/topo.py b/Lbracket/topo.py
new file mode 100644
index 0000000000000000000000000000000000000000..dc41a711d8e61df0c60379b6a3ffabe7e67f946d
--- /dev/null
+++ b/Lbracket/topo.py
@@ -0,0 +1,207 @@
+# Open this file with Gmsh (interactively with File->Open->topo.py, or on the
+# command line with 'gmsh topo.py')
+#
+
+import numpy as np
+import optlab
+import onelab
+
+c = onelab.client(__file__)
+
+# get paths to the gmsh and getdp executable from Gmsh options
+mygmsh = c.getString('General.ExecutableFileName')
+mygetdp = ''
+for s in range(9):
+   n = c.getString('Solver.Name' + str(s))
+   if(n == 'GetDP'):
+      mygetdp = c.getString('Solver.Executable' + str(s))
+      break
+if(not len(mygetdp)):
+   c.sendError('This appears to be the first time you are trying to run GetDP')
+   c.sendError('Please run a GetDP model interactively once with Gmsh to ' +
+               'initialize the solver location')
+   exit(0)
+
+c.sendInfo('Will use gmsh={0} and getdp={1}'.format(mygmsh, mygetdp))
+
+# append correct path to model file names
+topo_geo = c.getPath('topo.geo')
+topo_msh = c.getPath('topo.msh')
+topo_pro = c.getPath('topo.pro')
+
+# build command strings with appropriate parameters and options
+mygetdp += ' -p 0 ' + topo_pro + ' -msh ' + topo_msh + ' '
+mygmsh += ' -p 0 -v 2 ' + topo_geo + ' '
+
+# load geometry in GUI to have something to look at
+c.openProject(topo_geo)
+
+# dry getdp run (without -solve or -pos option) to get model parameters in the GUI
+c.runSubClient('myGetDP', mygetdp)
+
+# define now optimization parameters
+# some of them as Onelab parameter, to be editable in the GUI
+maxIter = c.defineNumber('Optimization/00Max iterations', value=1600)
+maxChange = c.defineNumber('Optimization/01Max change', value=1e-2)
+filtering = c.defineNumber('Optimization/02Filtering/00Filter densities', value=1, choices=[0,1])
+filterContinuation = c.defineNumber('Optimization/02Filtering/01continuation?', value=0, choices=[0,1])
+nbLoopReduceFilterRadius = c.defineNumber('Optimization/02Filtering/02frequency of radius update', value=40)
+filterRadiusDecrease = c.defineNumber('Optimization/02Filtering/03reduce factor', value=0.7)
+filterRadiusMin = c.defineNumber('Optimization/02Filtering/04radius min', value=0.0015)
+filterRadius = c.getNumber('Optimization/3Density/2filter radius')
+
+# end of check phase. We're done if we do not start the optimization
+if c.action == 'check' :
+   exit(0)
+
+# mesh the geometry to create the density (background) mesh
+c.runSubClient('myGmsh', mygmsh + '-2')
+
+# initializes the density 'xe' field
+# This is done with a GetDP problem named 'DensityField'
+# that solves no FE equations
+# but only fills up the function space with an initial value. 
+c.runSubClient('myGetDP', mygetdp + '-solve DensityField')
+
+# read in the 'xe' field from GetDP into a python variable 'd'
+d = c.getNumbers('Optimization/Results/designVariable')
+
+# the variable d contains the following serialized data: [N, ele1, xe1, ..., eleN, xeN]
+# split it into homogeneous vectors
+numElements = d[0] # N
+elements = np.array(d[1::2]) # [ele1, ..., eleN ]
+#x = np.array(d[2::2]) # [xe1, ..., xeN]
+x = 0.5*np.ones(numElements)
+
+print 'number of elements in topology optimization:', numElements
+
+# This function serializes the python variables 'ele' and 'var' into
+# an ElementTable variable [N, ele1, xe1, ..., eleN, xeN]
+# and set it as a Onelab parameter named `var' 
+def setElementTable(var, ele, val):
+   data = np.ravel(np.column_stack((ele, val)))
+   data = np.insert(data, 0, numElements)
+   c.setNumber(var, values=data, visible=0)
+
+# The following function evaluates the optimization problem
+# at point `point' in the design space, i.e.
+# - the objective function,
+# - the constraints,
+# - the derivatives of the objective function w.r.t. the design variables,
+# - the derivatives of the constraints w.r.t. the design variables.
+def myOptimizationProblem(point=None):
+    #objective = c.getNumber('Optimization/Results/Energy')
+    objective = c.getNumber('Optimization/Results/pnorm of Von-Mises')
+    tmp = [c.getNumber('Optimization/Results/VolumeDomain')\
+      / (0.5*c.getNumber('Optimization/Results/VolumeDomainFull')) - 1.0]
+    constraints = np.array(tmp)
+
+    #grad_objective = np.array(c.getNumbers('Optimization/Results/GradOfCompliance')[2::2])
+    grad_objective = np.array(c.getNumbers('Optimization/Results/GradOfVonMises')[2::2])
+
+    tmp = list(np.asarray(c.getNumbers('Optimization/Results/GradOfVolume')[2::2])\
+         /(0.5*c.getNumber('Optimization/Results/VolumeDomainFull')))
+    grad_constraints = np.array(tmp)
+
+    return objective,constraints,grad_objective,grad_constraints
+
+# number of design variables and number of constraints
+numVariables = len(x)
+
+# lower bound for design variables (here all set to 0.001)
+lowerBound = 0.001*np.ones(numVariables)
+
+# upper bound for design variables (here all set to 1)
+upperBound = np.ones(numVariables)
+
+# Initialize the MMA optimizer
+optlab.mma.initialize(x, lowerBound, upperBound)
+
+# Set appropriate options for MMA
+optlab.mma.option.setNumber('General.Verbosity', 4)
+optlab.mma.option.setNumber('General.SaveHistory', 0)
+optlab.mma.option.setNumber('SubProblem.isRobustMoveLimit', 1)
+optlab.mma.option.setNumber('SubProblem.isRobustAsymptotes', 1)
+optlab.mma.option.setNumber('SubProblem.type', 0)
+optlab.mma.option.setNumber('SubProblem.addConvexity', 1)
+optlab.mma.option.setNumber('SubProblem.asymptotesRmax', 100.0)
+optlab.mma.option.setNumber('SubProblem.asymptotesRmin', 0.001)
+
+# Get iteration count (here it will be 1 - could be different in case of restart)
+it = optlab.mma.getOuterIteration()
+change = 1.0
+
+while change > maxChange and it <= maxIter and c.getString('topo/Action') != 'stop':
+
+    c.setNumber('Optimization/01Current iteration', value=it, readOnly=1,
+                attributes={'Highlight':'LightYellow'})
+    c.setNumber('Optimization/02Current change', value=change, readOnly=1,
+                attributes={'Highlight':'LightYellow'})
+
+    # get (copy of) current point
+    x = np.array(optlab.mma.getCurrentPoint())
+
+    if filtering:
+        setElementTable('Optimization/Results/filterInput', elements, x)
+        c.runSubClient('myGetDP', mygetdp + '-solve FilterDensity')
+        x = np.array(c.getNumbers('Optimization/Results/filterOutput')[2::2])
+
+    setElementTable('Optimization/Results/designVariable', elements, x)
+
+    # compute objective function and constraints as well as their sensitivity
+    # with respect to design variables at `x'
+    c.runSubClient('myGetDP', mygetdp + '-solve ComputePerformancesAndGradient')
+
+    # get the value of the objective function and of the constraints
+    # as well as their sensitivity with respect to design variables at `x'
+    objective,constraints,grad_objective,grad_constraints = myOptimizationProblem()
+    objective = c.getNumber('Optimization/Results/pnorm of Von-Mises')
+    constraints = np.array([c.getNumber('Optimization/Results/VolumeDomain')\
+      / (0.5*c.getNumber('Optimization/Results/VolumeDomainFull')) - 1.0])
+    grad_objective = np.array(c.getNumbers('Optimization/Results/GradOfVonMises')[2::2])
+    grad_constraints = np.asarray(c.getNumbers('Optimization/Results/GradOfVolume')[2::2])\
+         /(0.5*c.getNumber('Optimization/Results/VolumeDomainFull'))
+
+    if filtering:
+        # apply the chain rule for the sensitivity of objective
+        setElementTable('Optimization/Results/filterInput', elements, grad_objective)
+        c.runSubClient('myGetDP', mygetdp + '-solve FilterDensity')
+        grad_objective = np.array(c.getNumbers('Optimization/Results/filterOutput')[2::2])
+
+        # apply the chain rule for the sensitivity of constraints
+        d_con_dx = grad_constraints.reshape((len(constraints), numVariables))
+        for k,dfe in enumerate(d_con_dx):
+            setElementTable('Optimization/Results/filterInput', elements, dfe)
+            c.runSubClient('myGetDP', mygetdp + '-solve FilterDensity')
+            d_con_dx[k] = np.array(c.getNumbers('Optimization/Results/filterOutput')[2::2])
+        grad_constraints = d_con_dx.reshape((len(constraints) * numVariables,))
+
+    if it == 1: fscale = 1.0 / np.abs(objective)
+    objective *= fscale
+    grad_objective *= fscale
+
+    print '*'*50
+    print 'iteration: ', it
+    print 'change: ', change
+    print 'objective:', objective
+    print 'constraints:', constraints
+    c.sendInfo('Optimization: it. {}, obj. {}, constr. {}, change {}'.format(it,objective,constraints[0], change))
+
+    # call MMA and update the current point
+    optlab.mma.setMoveLimits(lowerBound, upperBound, 0.1)
+    optlab.mma.updateCurrentPoint(constraints, grad_objective, grad_constraints)
+    change = optlab.mma.getDesignChange()
+    it = optlab.mma.getOuterIteration()
+
+    if filtering and filterContinuation and \
+        (it % nbLoopReduceFilterRadius == 0.0 or change <= maxChange): 
+        filterRadius *= filterRadiusDecrease
+        print "decrease filter radius: ", filterRadius
+        c.setNumber('Optimization/3Density/2filter radius',value=filterRadius)
+        filtering = filterRadius <= filterRadiusMin
+        print "filtering: ",filtering
+        c.setNumber('Optimization/02Filtering/00Filter densities',value=filtering)
+        change = 1.0
+
+# This should be called at the end
+optlab.mma.finalize()