diff --git a/README.md b/README.md
index b2530e512740968d92d0fafadf377df718ec1ebc..ae94909629b33953ad17c02389d8c63533c68bf6 100644
--- a/README.md
+++ b/README.md
@@ -18,4 +18,69 @@ To build the independent FEM solver:
 - similar procedure but to be done in the srcs/FEM folder
 
 To build the independent BEM solver:
-- similar procedure but to be done in the srcs/BEM folder
\ No newline at end of file
+- similar procedure but to be done in the srcs/BEM folder
+
+## Creation of a .geo file 
+
+To create a .geo file compatible with the program, some rules must be respected:  
+- For the elastic FEM part:    
+  1. The FEM domain should be defined as a `Physical Surface` with the precise name `FEM_domain`.
+        First, a `Curve Loop` gathering the lines representing the boundary of the FEM domain must be created.
+        Then, a `Plane Surface` containing the corresponding curve loop must be created.
+        Finally, if the plane surface is the first of the .geo file, the physical surface must be created as: 
+        `Physical Surface("FEM_domain", x) = {1};`,
+        where x is the tag of the physical surface.
+        Multiple sub domains can be included in the FEM domain. For example, if plane surfaces have been created for
+        five sub domains, the physical surface must be created as:
+        <pre><code>Physical Surface("FEM_domain", x) = {1, 2, 3, 4, 5};.<code><pre> 
+    
+  2. The mechanical boundary conditions, material properties and volumic forces must be specified for the FEM domain:  
+    - **BOUNDARY CONDITIONS**:
+      1. The edges on which the user wants to impose a boundary condition must be defined as `Physical Curve`.
+                As an example, if the user want to impose a condition on the bottom edge related to the `Line(1)`: 
+                <pre><code>`Physical Curve("bottom_edge", x) = {1};`<code><pre>
+      2. All boundary conditions must be written as `SetNumber("Boundary Conditions/name_of_the_physical_curve/...")` 
+                with `name_of_the_physical_curve` the physical curve on which the condition is imposed.
+      3. The Dirichlet boundary conditions, i.e the imposed horizontal and vertical displacement `u_x` and `u_y` of an edge,    
+                expressed in [m], must be written as `Setnumber("Boundary Conditions/name_of_the_physical_curve/ux", desired_value);`, same applies for `u_y`. Note that the horizontal displacement can be imposed on a physical curve without imposing the vertical displacement, and vice-versa.
+                As an example, if the user wants the left edge to be clamped: 
+                    <pre><code>SetNumber("Boundary Conditions/left_edge/ux", 0.);
+                        SetNumber("Boundary Conditions/left_edge/uy", 0.);<code><pre>
+      4. The Neumann boundary conditions, i.e surface traction in the horizontal (`t_x`) or vertical (`t_y`) direction imposed on
+                an edge, expressed in [Pa], must be written as `SetNumber("Boundary Conditions/name_of_the_physical_curve/tx", desired_value)`, 
+                same applies for `t_y`. Note that on a specific edge, both horizontal and vertical surface tractions must be 
+                prescribed. If the user only wants to prescribe `t_x`, `t_y` must also be set to zero.
+      5. Dirichlet boundary conditions can also be imposed on a specific point of the domain. In this case, a `Physical Point`
+                must be created.
+    - **MATERIAL PROPERTIES**:
+                All the material properties must be written as `SetNumber("Materials/FEM_domain/name_of_property", value_of_property);`.
+                The different properties that must be specified are:
+      - Young's modulus, expressed in [Pa], named `Young`.
+      - Poisson's ratio, without physical units, named `Poisson`.
+      - Mass density, expressed in [kg/m3], named `rho`.
+    - **VOLUMIC FORCES**:
+                Volumic forces in the horizontal (`b_x`) or vertical (`b_y`) direction, expressed in [m/s2], must be written as `SetNumber("Volumic Forces/FEM_domain/b_x",0);`, same applies for `b_y`.
+- For the electrostatic BEM part:
+  1. The lines corresponding to the boundary of the BEM surfaces must be created in such a way that the area of the BEM surface is located on the left of the Curve Loop.
+  2. Multiple BEM domains can be defined. One BEM domain should be defined as a `Physical Surface` with the precise name `BEM_domain_X`, with `X` the identifier of the BEM domain (`X=1` if it is the first domain, `X=2` if it is the second one, ...).
+  3. Boundary conditions and material properties must then be specified for the BEM domain: 
+    - **BOUNDARY CONDITIONS**:
+      1. Dirichlet boundary conditions, corresponding to imposing an electric potential expressed in [V], can be imposed on a physical curve as:
+       `SetNumber("Boundary Conditions/name_of_the_physical_curve/BEM_domain_X/dirichlet", value_of_potential);`.
+      2. Neumann boundary conditions, corresponding to imposing the normal component of the electric field expressed in [V/m], can be imposed on a physical curve as: `SetNumber("Boundary Conditions/name_of_the_physical_curve/BEM_domain_X/neumann", value_of_field);`.
+    - **MATERIAL PROPERTIES**: The dielectric permittivity of the material inside the BEM domain must be specified. It is done writing `SetNumber("Materials/BEM_domain_X/Epsilon", value_of_Epsilon);`.
+
+  **Note**: These operations must be done for each BEM domain the user wants to create, replacing `X` by the given identifier of the BEM domain. 
+- For the coupling between the FEM and BEM domains:
+  1. All the lines belonging to the interface between the FEM domain and the different BEM domains must be specified as a single `Physical Curve("BEM_FEM_boundary, x)={List_of_the_interface_lines}`. As an example, if `Line(1)`, `Line(4)` and `Line(5)` belong to the intersection of the BEM domains and the FEM domain: 
+        <pre><code> Physical Curve("BEM_FEM_boundary", x) = {1, 4, 5};<code><pre>
+- For the mechanical or the coupled solver, the user can choose between the linear or non-linear iterative solver, by setting 
+  `SetNumber("Non_linear_solver",0);` for the linear solver, or `SetNumber("Non_linear_solver",1);` for the non-linear solver.
+
+
+
+
+
+
+
+
diff --git a/bem.nb b/bem.nb
new file mode 100644
index 0000000000000000000000000000000000000000..1ba81baaaf6a0e0c29c1d9f3b54138982f4a2f07
--- /dev/null
+++ b/bem.nb
@@ -0,0 +1,4647 @@
+(* Content-type: application/vnd.wolfram.mathematica *)
+
+(*** Wolfram Notebook File ***)
+(* http://www.wolfram.com/nb *)
+
+(* CreatedBy='Mathematica 12.1' *)
+
+(*CacheID: 234*)
+(* Internal cache information:
+NotebookFileLineBreakTest
+NotebookFileLineBreakTest
+NotebookDataPosition[       158,          7]
+NotebookDataLength[    195984,       4639]
+NotebookOptionsPosition[    190249,       4554]
+NotebookOutlinePosition[    190641,       4570]
+CellTagsIndexPosition[    190598,       4567]
+WindowFrame->Normal*)
+
+(* Beginning of Notebook Content *)
+Notebook[{
+Cell[TextData[StyleBox["temps et complexit\[EAcute] des diff\[EAcute]rents \
+algorithmes de la bem", "Title"]], "Text",
+ CellChangeTimes->{
+  3.8612586147638197`*^9},ExpressionUUID->"2a4634af-38af-46df-ba82-\
+22e16ff7cedb"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{"\[IndentingNewLine]", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"tottime", "=", 
+     RowBox[{"{", 
+      RowBox[{
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "9"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "26"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "66"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "115"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "194"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "286"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "394"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "506"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "702"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "847"}], "}"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "7"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "21"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "50"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "88"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "141"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "200"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "283"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "345"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "452"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "535"}], "}"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "42"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "251"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "599"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "1157"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "2389"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "3561"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "5576"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "7523"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "11067"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "13760"}], "}"}]}], "}"}], ",", 
+       "\[IndentingNewLine]", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "54"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "494"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "1285"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "2973"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "6234"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "10100"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "16246"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "25339"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "42998"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "51864"}], "}"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "65"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "250"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "456"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "800"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "1241"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "1830"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "2547"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "3241"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "4391"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "5325"}], "}"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "188"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "1665"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "4583"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "11210"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "24026"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "40420"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "62792"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "95113"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "142988"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "180652"}], "}"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"{", 
+          RowBox[{"0", ",", "0"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"50", ",", "547"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"100", ",", "2942"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"150", ",", "7483"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"200", ",", "17045"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"250", ",", "35325"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"300", ",", "57890"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"350", ",", "90039"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"400", ",", "134877"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"450", ",", "206100"}], "}"}], ",", 
+         RowBox[{"{", 
+          RowBox[{"500", ",", "257071"}], "}"}]}], "}"}]}], "}"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"tottime", "=", 
+    RowBox[{"tottime", "[", 
+     RowBox[{"[", "7", "]"}], "]"}]}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"g1", "=", 
+     RowBox[{"ListPlot", "[", "tottime", "]"}]}], ";"}], 
+   "\[IndentingNewLine]", "interpolation", "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"f", "=", 
+     RowBox[{"Interpolation", "[", 
+      RowBox[{"tottime", ",", 
+       RowBox[{"InterpolationOrder", "\[Rule]", "1"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"g2", "=", 
+     RowBox[{"Plot", "[", 
+      RowBox[{
+       RowBox[{"f", "[", "x", "]"}], ",", 
+       RowBox[{"{", 
+        RowBox[{"x", ",", "0", ",", "500"}], "}"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"Show", "[", 
+    RowBox[{"g1", ",", "g2"}], "]"}], "\[IndentingNewLine]", "fit", 
+   "\[IndentingNewLine]", 
+   RowBox[{"(*", 
+    RowBox[{"line", "=", 
+     RowBox[{"Fit", "[", 
+      RowBox[{"tottime", ",", 
+       RowBox[{"{", 
+        RowBox[{"1", ",", "x"}], "}"}], ",", "x"}], "]"}]}], "*)"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"parabola", "=", 
+    RowBox[{"Fit", "[", 
+     RowBox[{"tottime", ",", 
+      RowBox[{"{", 
+       RowBox[{"x", "^", "3"}], "}"}], ",", "x"}], "]"}]}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"Show", "[", 
+    RowBox[{
+     RowBox[{"ListPlot", "[", 
+      RowBox[{"tottime", ",", 
+       RowBox[{"PlotStyle", "\[Rule]", "Red"}]}], "]"}], ",", 
+     RowBox[{"Plot", "[", 
+      RowBox[{
+       RowBox[{"{", "parabola", "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{"x", ",", "0", ",", "500"}], "}"}], ",", 
+       RowBox[{"PlotRange", "\[Rule]", 
+        RowBox[{"{", 
+         RowBox[{
+          RowBox[{"{", 
+           RowBox[{"0", ",", "500"}], "}"}], ",", 
+          RowBox[{"{", 
+           RowBox[{"0", ",", "260000"}], "}"}]}], "}"}]}]}], "]"}], ",", 
+     RowBox[{"Frame", "->", "True"}]}], "]"}], "\[IndentingNewLine]", 
+   "formula", "\[IndentingNewLine]", 
+   RowBox[{"fit", "=", 
+    RowBox[{"FindFormula", "[", 
+     RowBox[{"tottime", ",", "x"}], "]"}]}], "\[IndentingNewLine]", 
+   RowBox[{"Show", "[", 
+    RowBox[{"g1", ",", 
+     RowBox[{"Plot", "[", 
+      RowBox[{"fit", ",", 
+       RowBox[{"{", 
+        RowBox[{"x", ",", "0", ",", "500"}], "}"}]}], "]"}]}], "]"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"(*", 
+    RowBox[{"juste", " ", "quelques", " ", "petits", " ", "tests"}], "*)"}], 
+   "\[IndentingNewLine]", "nonlinearmodelfit", "\[IndentingNewLine]", 
+   RowBox[{"nlm", "=", 
+    RowBox[{"NonlinearModelFit", "[", 
+     RowBox[{"tottime", ",", 
+      RowBox[{"a", "*", 
+       RowBox[{"x", "^", "3"}]}], ",", 
+      RowBox[{"{", "a", "}"}], ",", "x"}], "]"}]}], "\[IndentingNewLine]", 
+   RowBox[{"Normal", "[", "nlm", "]"}], "\[IndentingNewLine]", 
+   RowBox[{"Show", "[", 
+    RowBox[{
+     RowBox[{"ListPlot", "[", "tottime", "]"}], ",", 
+     RowBox[{"Plot", "[", 
+      RowBox[{
+       RowBox[{"nlm", "[", "x", "]"}], ",", 
+       RowBox[{"{", 
+        RowBox[{"x", ",", "0", ",", "500"}], "}"}]}], "]"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}], "\[IndentingNewLine]", 
+   RowBox[{"nlm", "[", "\"\<FitResiduals\>\"", "]"}], "\[IndentingNewLine]", 
+   RowBox[{"ListPlot", "[", 
+    RowBox[{"%", ",", 
+     RowBox[{"Filling", "\[Rule]", "Axis"}]}], "]"}], 
+   "\[IndentingNewLine]"}]}]], "Input",
+ CellChangeTimes->{
+  3.860953426578657*^9, {3.860953463836258*^9, 3.860953584913463*^9}, {
+   3.8609536201467247`*^9, 3.860953707544536*^9}, {3.860953745800506*^9, 
+   3.860953819621065*^9}, {3.8609538556351748`*^9, 3.8609539466166277`*^9}, {
+   3.860954009342905*^9, 3.8609541499745893`*^9}, {3.86095418287741*^9, 
+   3.860954253405746*^9}, {3.8609542847431583`*^9, 3.860954306660102*^9}, 
+   3.8609543371796837`*^9, {3.860954377783967*^9, 3.8609544724716043`*^9}, {
+   3.860954537244658*^9, 3.860954579100382*^9}, {3.8609546179977207`*^9, 
+   3.860954722852202*^9}, {3.860954871127983*^9, 3.860954949325055*^9}, {
+   3.860954981711828*^9, 3.8609550095180683`*^9}, {3.860955064155086*^9, 
+   3.86095510202353*^9}, {3.860955210151617*^9, 3.86095527115606*^9}, {
+   3.8609553014468193`*^9, 3.8609553018922*^9}, {3.860955344616881*^9, 
+   3.860955369640203*^9}, {3.860955401632543*^9, 3.860955422826654*^9}, {
+   3.8611196515343533`*^9, 3.861119686934135*^9}, {3.861123389830142*^9, 
+   3.861123393073531*^9}, {3.861123423637659*^9, 3.8611234462467403`*^9}, {
+   3.8611269092812862`*^9, 3.861127052199102*^9}, {3.861127251583521*^9, 
+   3.861127310227153*^9}, {3.8612586019290237`*^9, 3.8612586182822723`*^9}, 
+   3.8612588223947983`*^9, {3.861258880213319*^9, 3.86125892206304*^9}, {
+   3.861260785357984*^9, 3.861260794129675*^9}},
+ CellLabel->"In[59]:=",ExpressionUUID->"4ed55133-bec1-4475-ad1f-833b36b2d4c6"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{"0", ",", "0"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"50", ",", "547"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"100", ",", "2942"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"150", ",", "7483"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"200", ",", "17045"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"250", ",", "35325"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"300", ",", "57890"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"350", ",", "90039"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"400", ",", "134877"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"450", ",", "206100"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"500", ",", "257071"}], "}"}]}], "}"}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794774898*^9},
+ CellLabel->"Out[60]=",ExpressionUUID->"65fdfe1a-aa66-4933-962e-56e19b792ce1"],
+
+Cell[BoxData["interpolation"], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794857626*^9},
+ CellLabel->"Out[62]=",ExpressionUUID->"89f7ea64-7da5-4498-b160-d9b88f8879d8"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{0., 0.}, {50., 547.}, {100., 2942.}, {150., 7483.}, {200., 
+      17045.}, {250., 35325.}, {300., 57890.}, {350., 90039.}, {400., 
+      134877.}, {450., 206100.}, {500., 257071.}}]}, {{}, {}}}, {{{}, {}, 
+     TagBox[
+      {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], 
+       Opacity[1.], LineBox[CompressedData["
+1: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
+q1xJdkLE5y6TmSVdNo7vezl03lGI+D+rp8is
+        "]]},
+      Annotation[#, "Charting`Private`Tag$53917#1"]& ]}, {}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0, 0},
+  DisplayFunction->Identity,
+  Frame->{{False, False}, {False, False}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  ImageMargins->0.,
+  ImageSize->Automatic,
+  ImageSizeRaw->Automatic,
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{0, 500.}, {0, 257071.}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794910377*^9},
+ CellLabel->"Out[65]=",ExpressionUUID->"7a89971a-d470-4aba-b097-89238335c823"],
+
+Cell[BoxData[
+ RowBox[{"914.5652349321464`", "\[VeryThinSpace]", "+", 
+  RowBox[{"0.0021137341020296026`", " ", 
+   SuperscriptBox["x", "3"]}]}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794917577*^9},
+ CellLabel->"Out[66]=",ExpressionUUID->"c024bf23-b077-4190-b9e3-f1d5fb19ed2f"],
+
+Cell[BoxData[
+ RowBox[{"0.002124924552859501`", " ", 
+  SuperscriptBox["x", "3"]}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794921052*^9},
+ CellLabel->"Out[67]=",ExpressionUUID->"c87b3cd2-72e1-4211-9c33-d98771a9e76c"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, 
+    {RGBColor[1, 0, 0], PointSize[0.012833333333333334`], AbsoluteThickness[
+     1.6], PointBox[{{0., 0.}, {50., 547.}, {100., 2942.}, {150., 7483.}, {
+      200., 17045.}, {250., 35325.}, {300., 57890.}, {350., 90039.}, {400., 
+      134877.}, {450., 206100.}, {500., 257071.}}]}, {{}, {}}}, {{{}, {}, 
+     TagBox[
+      {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], 
+       Opacity[1.], LineBox[CompressedData["
+1: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
+
+        "]]},
+      Annotation[#, "Charting`Private`Tag$53999#1"]& ]}, {}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0, 0},
+  DisplayFunction->Identity,
+  Frame->True,
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  ImageMargins->0.,
+  ImageSize->Automatic,
+  ImageSizeRaw->Automatic,
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{0, 500.}, {0, 257071.}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.8612607949648123`*^9},
+ CellLabel->"Out[68]=",ExpressionUUID->"9b57112f-d238-4317-89cb-371ba4a2c235"],
+
+Cell[BoxData["formula"], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260794976637*^9},
+ CellLabel->"Out[69]=",ExpressionUUID->"8a451dcb-573e-4f9f-97e1-ed70aded0195"],
+
+Cell[BoxData[
+ RowBox[{"914.9059240288545`", "\[VeryThinSpace]", "+", 
+  RowBox[{"0.0021137341020296026`", " ", 
+   SuperscriptBox["x", "3"]}]}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.8612607963488626`*^9},
+ CellLabel->"Out[70]=",ExpressionUUID->"71c50b88-43c3-43d1-9b99-9504c5bd5f96"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{0., 0.}, {50., 547.}, {100., 2942.}, {150., 7483.}, {200., 
+      17045.}, {250., 35325.}, {300., 57890.}, {350., 90039.}, {400., 
+      134877.}, {450., 206100.}, {500., 257071.}}]}, {{}, {}}}, {{{}, {}, 
+     TagBox[
+      {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], 
+       Opacity[1.], LineBox[CompressedData["
+1:eJwV02k41VsbBvAIEW1TJGWODPsgYwr7/ktkyBxRVCpDKZTioK0kxbtt2xQZ
+t4whSeakgaKckjpEpaQ0mWeSvP/zYV3r+n1a9/U865bz9Hc4yrlixYoF8vx3
+D03+tjbzGjRu+CKxh5bKwKmCv7VNc5tp9soSrv85hH/Ea33ua5qlpsiZ/6xv
+KlXFCuyjBe/lePifw5oKV3Dlfqbd+P3RCaTfvjUuosV8p90JKd5FkN421707
+LHCEdlR5T5UJ6ecx+qHvqBO0BO/+W6akl1Iv7l5gT9FWJ5o6mpOmFnbIrhOb
+pbFXhtdYkt5ftWFaJ2aepihxYcKGNOORd6vD0i/acTWbjU6kG1/eSQ8IXKKZ
+XuuzcSM9/GH5BHNwmXb+nkruIdLM2QLZbioHpqaoasdIFy5ZrR704oRf2ieu
+INJNXJNTU+yVuM9jYhZBups/rY/zHRca03etYpAeFTFuFRbjgW7F2IF00jyS
+XypkbVfh9/UtPiWkpeVi0zVieDHwgndrI2k9Zc0o42Y+NMT7f+sgbaPRfWL3
+0mo4EQeZg6S99MJd9usLIJLWZbpE+pyRPHE8cA3WfW2TX5fGQLJpm2poKQWf
+WbrQJl1mdXJtzKAg6jLEqu1Je6qsXm6PF4K35+Frp0iPUvtOv6YKoxnrua+S
+DtWs+P72qTCyErcINZLm0bnoPuAlgtY7ha++kJbermI+wRaF3WtWn/E1BkqM
+f9+dN1oLh5hfewJI65l0aK54txZD50oG80nbWJyRFBQTx6bEJyXr0sn9Wu+K
+F68Uh6/vZiFn0l52G7ikbdchdrR2OJU03eXhCDVGAsWB9seVMhhYvS/ZU0dp
+PSw22xqdJn3Vw/vN9ub1WPPr6Ndm0uVH1zy0XJKEqVebVGAm+V98+3Ud0jfA
+rZb3/XPST/zulLjqb8S7ZKtO9SwG+k67JvsESsHjyKMHS6R9gql8ARRpcFOG
+fh7PZmA6dPlccKk09t1ZLv1AWiCywDt6UAYHDnY7vMph4B8Tw1EzQhYVMnE+
+jmwGElsKip/Fy2LOYv2ZXtLSbSFSr6hyuGWT8Wo6l4EvFgNv9oTJobn/kmPs
+dXJe7VaJvU/lILZbQ00xj5xXh/SqT17yqFYoNj6eT86ru2V8jK2A3tdJKduL
+GIj46O5KmVWAlpmguGAxAxXfZx9SrTbhW1HVgx+khReVk3xnNmHl3kpKdQkD
+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
+vN6pklmuLkT8H5cWJlE=
+        "]]},
+      Annotation[#, "Charting`Private`Tag$81847#1"]& ]}, {}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0, 0},
+  DisplayFunction->Identity,
+  Frame->{{False, False}, {False, False}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  ImageMargins->0.,
+  ImageSize->Automatic,
+  ImageSizeRaw->Automatic,
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{0, 500.}, {0, 257071.}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.8612607963738747`*^9},
+ CellLabel->"Out[71]=",ExpressionUUID->"db2bab01-4618-4db7-8683-117d6150b911"],
+
+Cell[BoxData["nonlinearmodelfit"], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260796380981*^9},
+ CellLabel->"Out[72]=",ExpressionUUID->"ba354193-5beb-4a8c-962b-96de2fd88bc5"],
+
+Cell[BoxData[
+ TagBox[
+  RowBox[{"FittedModel", "[", 
+   TagBox[
+    PanelBox[
+     TagBox[
+      RowBox[{"0.002124924552859501`", " ", 
+       SuperscriptBox["x", "3"]}],
+      Short[#, 2]& ],
+     FrameMargins->5],
+    Editable -> False], "]"}],
+  InterpretTemplate[
+  FittedModel[{
+    "Nonlinear", {$CellContext`a -> 
+      0.002124924552859501}, {{$CellContext`x}, $CellContext`a \
+$CellContext`x^3}}, {1}, {{0, 0}, {50, 547}, {100, 2942}, {150, 7483}, {200, 
+    17045}, {250, 35325}, {300, 57890}, {350, 90039}, {400, 134877}, {450, 
+    206100}, {500, 257071}}, 
+    Function[Null, 
+     Internal`LocalizedBlock[{$CellContext`a, $CellContext`x}, #], {
+     HoldAll}]]& ],
+  Editable->False,
+  SelectWithContents->True,
+  Selectable->True]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260796505725*^9},
+ CellLabel->"Out[73]=",ExpressionUUID->"b590e101-f372-4eaa-b07a-74c6853e96a8"],
+
+Cell[BoxData[
+ RowBox[{"0.002124924552859501`", " ", 
+  SuperscriptBox["x", "3"]}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260796514821*^9},
+ CellLabel->"Out[74]=",ExpressionUUID->"6b5e6dbe-960f-4c2f-b7df-540c1741735c"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{0., 0.}, {50., 547.}, {100., 2942.}, {150., 7483.}, {200., 
+      17045.}, {250., 35325.}, {300., 57890.}, {350., 90039.}, {400., 
+      134877.}, {450., 206100.}, {500., 257071.}}]}, {{}, {}}}, {{{}, {}, 
+     TagBox[
+      {RGBColor[0.368417, 0.506779, 0.709798], AbsoluteThickness[1.6], 
+       Opacity[1.], LineBox[CompressedData["
+1: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
+        "]]},
+      Annotation[#, "Charting`Private`Tag$81961#1"]& ]}, {}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0, 0},
+  DisplayFunction->Identity,
+  Frame->True,
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  ImageMargins->0.,
+  ImageSize->Automatic,
+  ImageSizeRaw->Automatic,
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{0, 500.}, {0, 257071.}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.86126079657021*^9},
+ CellLabel->"Out[75]=",ExpressionUUID->"f64ed0f3-5f81-46ef-b0d2-0deaec21c948"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+  "0.`", ",", "281.38443089256236`", ",", "817.0754471404989`", ",", 
+   "311.37963409918393`", ",", "45.60357712399127`", ",", 
+   "2123.053861570297`", ",", "517.0370727934715`", ",", 
+   RowBox[{"-", "1067.140203851115`"}], ",", 
+   RowBox[{"-", "1118.1713830080698`"}], ",", "12466.250120677956`", ",", 
+   RowBox[{"-", "8544.569107437623`"}]}], "}"}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260796584264*^9},
+ CellLabel->"Out[76]=",ExpressionUUID->"1ad22f7c-dddb-4448-9317-229eaab684eb"],
+
+Cell[BoxData[
+ GraphicsBox[{{}, GraphicsComplexBox[CompressedData["
+1:eJxTTMoPSmViYGBQAGIQDQEf7BlQgQPXJ8aFatMKHSBcDgeNE+wtszo6oXwB
+B4F2k99CZcVQvogDg8gTZqezblC+hMOD1H2TpactgPJlHBxkLr3x1miA8hUc
+HHRnTuxfM+EAhK/kwPCbrX59xcQDMPtRnaPm4GDSfMNjw4ED909asmYYKjtU
+zA3weOKx20Fmd1HmpFYVOB/mXlT9Amh8ETS+BBpfBo2vgMZXwnAfKn+whaeK
+w4fAL8wKkSccYO6FhScAM8lexg==
+    "], {{{}, {}, {}, 
+      {RGBColor[0.368417, 0.506779, 0.709798], Opacity[0.3], LineBox[{19, 8}],
+        LineBox[{20, 9}], LineBox[{21, 11}]}, 
+      {RGBColor[0.368417, 0.506779, 0.709798], Opacity[0.3], LineBox[{10, 2}],
+        LineBox[{14, 3}], LineBox[{15, 4}], LineBox[{16, 5}], 
+       LineBox[{17, 6}], LineBox[{18, 7}]}}, 
+     {RGBColor[0.368417, 0.506779, 0.709798], PointSize[
+      0.012833333333333334`], AbsoluteThickness[1.6], 
+      PointBox[{22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}]}}], {{}, {}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0., 0},
+  DisplayFunction->Identity,
+  Frame->{{False, False}, {False, False}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  ImageMargins->0.,
+  ImageSize->Automatic,
+  ImageSizeRaw->Automatic,
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{0., 11.}, {-8544.569107437623, 6984.891728437848}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.05], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{
+  3.860953469098629*^9, 3.860953709361183*^9, 3.860953820838641*^9, 
+   3.860953948078908*^9, 3.860954013883754*^9, 3.860954046377944*^9, 
+   3.860954151038829*^9, 3.860954255700719*^9, 3.860954350633729*^9, {
+   3.860954414483062*^9, 3.860954437320591*^9}, 3.860954583772027*^9, 
+   3.8609546361711683`*^9, {3.860954685049466*^9, 3.860954723270211*^9}, {
+   3.860954914169093*^9, 3.860954938685191*^9}, {3.860954982682733*^9, 
+   3.860955010729517*^9}, {3.860955047851603*^9, 3.86095510246842*^9}, {
+   3.86095527369858*^9, 3.860955302695095*^9}, {3.860955345454904*^9, 
+   3.860955369948269*^9}, {3.860955402566491*^9, 3.860955428206354*^9}, {
+   3.861123438131472*^9, 3.861123456327256*^9}, 3.861127055114929*^9, {
+   3.861127264611608*^9, 3.861127274891913*^9}, 3.861127311959764*^9, 
+   3.861181688408037*^9, 3.861259438722706*^9, 3.861260796613441*^9},
+ CellLabel->"Out[77]=",ExpressionUUID->"f67cbd93-c669-4bc7-87c6-cf7ae689c11a"]
+}, Open  ]],
+
+Cell[TextData[StyleBox["\[EAcute]tude de la convergence de la solution num\
+\[EAcute]rique vers la solution analytique du champ \[EAcute]lectrique de la \
+BEM en fonction du nombre de points de gauss utilis\[EAcute] pour l\
+\[CloseCurlyQuote]int\[EAcute]gration", "Title"]], "Text",
+ CellChangeTimes->{{3.861258741265164*^9, 
+  3.86125880430346*^9}},ExpressionUUID->"a9e8cb00-e27d-4ce1-93f1-\
+c63f24dce0c4"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{
+   "convergence", " ", "de", " ", "la", " ", "solution", " ", 
+    "num\[EAcute]rique", " ", "g\[EAcute]n\[EAcute]ralisation"}], "*)"}], 
+  "\[IndentingNewLine]", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"dataelectricfieldgauss", "=", 
+     RowBox[{
+     "Import", "[", "\"\</Users/Kevin/BEM/build/Debug/gauss_square.csv\>\"", 
+      "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"dataelectricfieldanaly", "=", 
+     RowBox[{
+     "Import", "[", "\"\</Users/Kevin/BEM/build/Debug/analytique.csv\>\"", 
+      "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{"(*", 
+    RowBox[{
+     RowBox[{"dataelectricfieldgauss", "=", 
+      RowBox[{
+      "Import", "[", "\"\</Users/Kevin/BEM/build/Debug/gauss_hole_48.csv\>\"",
+        "]"}]}], ";", "\[IndentingNewLine]", 
+     RowBox[{"dataelectricfieldanaly", "=", 
+      RowBox[{
+      "Import", "[", 
+       "\"\</Users/Kevin/BEM/build/Debug/gauss_hole_analytique.csv\>\"", 
+       "]"}]}], ";"}], "*)"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"dataelectricfieldanaly", "=", 
+     RowBox[{"dataelectricfieldanaly", "[", 
+      RowBox[{"[", "1", "]"}], "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"abserror", "=", 
+     RowBox[{"{", "}"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"relativeerror", "=", 
+     RowBox[{"{", "}"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{"For", "[", 
+    RowBox[{
+     RowBox[{"i", "=", "1"}], ",", 
+     RowBox[{"i", "\[LessEqual]", 
+      RowBox[{"Length", "[", "dataelectricfieldgauss", "]"}]}], ",", 
+     RowBox[{"i", "++"}], ",", "\[IndentingNewLine]", 
+     RowBox[{
+      RowBox[{"AppendTo", "[", 
+       RowBox[{"abserror", ",", 
+        RowBox[{"{", 
+         RowBox[{
+          RowBox[{"2", "*", "i"}], ",", 
+          RowBox[{"Sqrt", "[", 
+           RowBox[{"Sum", "[", 
+            RowBox[{
+             RowBox[{
+              RowBox[{"(", 
+               RowBox[{
+                RowBox[{"dataelectricfieldgauss", "[", 
+                 RowBox[{"[", 
+                  RowBox[{"i", ",", "j"}], "]"}], "]"}], "-", 
+                RowBox[{"dataelectricfieldanaly", "[", 
+                 RowBox[{"[", "j", "]"}], "]"}]}], ")"}], "^", "2"}], ",", 
+             RowBox[{"{", 
+              RowBox[{"j", ",", "1", ",", 
+               RowBox[{"Length", "[", "dataelectricfieldanaly", "]"}]}], 
+              "}"}]}], "]"}], "]"}]}], "}"}]}], "]"}], ";", 
+      "\[IndentingNewLine]", 
+      RowBox[{"AppendTo", "[", 
+       RowBox[{"relativeerror", ",", 
+        RowBox[{"{", 
+         RowBox[{
+          RowBox[{"i", "*", "2"}], ",", 
+          RowBox[{"Sqrt", "[", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"Sum", "[", 
+              RowBox[{
+               RowBox[{
+                RowBox[{"(", 
+                 RowBox[{
+                  RowBox[{"dataelectricfieldgauss", "[", 
+                   RowBox[{"[", 
+                    RowBox[{"i", ",", "j"}], "]"}], "]"}], "-", 
+                  RowBox[{"dataelectricfieldanaly", "[", 
+                   RowBox[{"[", "j", "]"}], "]"}]}], ")"}], "^", "2"}], ",", 
+               RowBox[{"{", 
+                RowBox[{"j", ",", "1", ",", 
+                 RowBox[{"Length", "[", "dataelectricfieldanaly", "]"}]}], 
+                "}"}]}], "]"}], ")"}], "/", 
+            RowBox[{"(", 
+             RowBox[{"Sum", "[", 
+              RowBox[{
+               RowBox[{
+                RowBox[{"dataelectricfieldanaly", "[", 
+                 RowBox[{"[", "j", "]"}], "]"}], "^", "2"}], ",", 
+               RowBox[{"{", 
+                RowBox[{"j", ",", "1", ",", 
+                 RowBox[{"Length", "[", "dataelectricfieldanaly", "]"}]}], 
+                "}"}]}], "]"}], ")"}]}], "]"}]}], "}"}]}], "]"}], ";"}]}], 
+    "]"}], "\[IndentingNewLine]", "abserror", "\[IndentingNewLine]", 
+   "relativeerror", "\[IndentingNewLine]", "\[IndentingNewLine]"}]}]], "Input",
+ CellChangeTimes->{{3.861120198227779*^9, 3.8611202086509027`*^9}, {
+  3.861120476136898*^9, 3.861120519489415*^9}, {3.861121142471794*^9, 
+  3.861121397677162*^9}, {3.8611214473307447`*^9, 3.8611217038415203`*^9}, {
+  3.861121977612794*^9, 3.861122033978256*^9}, {3.861122363404669*^9, 
+  3.8611223692759743`*^9}, {3.861122481670773*^9, 3.861122549413241*^9}, {
+  3.861122748564005*^9, 3.861122817288172*^9}, {3.861122981637671*^9, 
+  3.8611229828416443`*^9}, {3.861123153290061*^9, 3.861123155911878*^9}, {
+  3.8611289012277*^9, 3.8611289088187933`*^9}, {3.861129299526593*^9, 
+  3.8611293058475227`*^9}, {3.861173521581609*^9, 3.861173527697165*^9}},
+ CellLabel->
+  "In[259]:=",ExpressionUUID->"3022f7f2-8c9c-43ae-9732-d602151de8a8"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{"2", ",", "95004.77856950945`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"4", ",", "36205.63944299908`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"6", ",", "12316.897572120495`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"8", ",", "2753.571943809188`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"10", ",", "1108.913267961656`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"12", ",", "326.093452993495`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"14", ",", "99.14905399558761`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"16", ",", "30.407862601472058`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "9.580813127287266`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"20", ",", "3.011998313412531`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"22", ",", "0.8988662191894848`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"24", ",", "0.2548494065129372`"}], "}"}]}], "}"}]], "Output",
+ CellChangeTimes->{3.861122551406989*^9, 3.861123161460887*^9, 
+  3.8611289120849953`*^9, 3.861129326381927*^9, 3.861173532512989*^9},
+ CellLabel->
+  "Out[265]=",ExpressionUUID->"953df72a-406a-4325-a6b7-b588ecdbd337"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{"2", ",", "6.722461226945124`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"4", ",", "2.561881739182639`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"6", ",", "0.8715337018995811`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"8", ",", "0.19484052177773273`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"10", ",", "0.07846580519592629`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"12", ",", "0.02307410876712432`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"14", ",", "0.007015706801379136`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"16", ",", "0.0021516357430706665`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "0.0006779305813935762`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"20", ",", "0.00021312656249943826`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"22", ",", "0.00006360304605405775`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"24", ",", "0.000018032937708914684`"}], "}"}]}], "}"}]], "Output",\
+
+ CellChangeTimes->{3.861122551406989*^9, 3.861123161460887*^9, 
+  3.8611289120849953`*^9, 3.861129326381927*^9, 3.861173532566594*^9},
+ CellLabel->
+  "Out[266]=",ExpressionUUID->"505cf359-5431-4db8-b379-4278c65326ec"]
+}, Open  ]],
+
+Cell[BoxData[
+ RowBox[{"\[IndentingNewLine]", 
+  RowBox[{"(*", 
+   RowBox[{"plot", " ", "part"}], "*)"}]}]], "Input",
+ CellChangeTimes->{{3.861122068014279*^9, 
+  3.8611220747751293`*^9}},ExpressionUUID->"5184b6ce-6f3e-4ace-8f94-\
+4112569cfa78"],
+
+Cell[BoxData[{
+ RowBox[{
+  RowBox[{"g1", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"abserror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"PlotStyle", "\[Rule]", "Red"}], ",", 
+     RowBox[{"Joined", "\[Rule]", "True"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g2", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"abserror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{"Show", "[", 
+  RowBox[{"g1", ",", "g2"}], "]"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g3", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"relativeerror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"PlotStyle", "\[Rule]", "Red"}], ",", 
+     RowBox[{"Joined", "\[Rule]", "True"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g4", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"relativeerror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{"Show", "[", 
+  RowBox[{"g3", ",", "g4"}], "]"}]}], "Input",
+ CellChangeTimes->{{3.8611220359218893`*^9, 3.861122092969523*^9}},
+ CellLabel->
+  "In[267]:=",ExpressionUUID->"131c83d3-03c9-4c25-8f61-e5f9f199818d"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, {{}, {}, 
+     {RGBColor[1, 0, 0], PointSize[0.012833333333333334`], AbsoluteThickness[
+      1.6], LineBox[{{2., 11.461682470049317`}, {4., 10.496970171398734`}, {
+       6., 9.418727384930653}, {8., 7.920654236492377}, {10., 
+       7.011135776863383}, {12., 5.787184005910186}, {14., 
+       4.5966243137764415`}, {16., 3.414701213177399}, {18., 
+       2.259762465968268}, {20., 1.1026037499814914`}, {
+       22., -0.10662106627415432`}, {
+       24., -1.367082470968909}}]}}, {{}, {}}}, {{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{2., 11.461682470049317`}, {4., 10.496970171398734`}, {6., 
+      9.418727384930653}, {8., 7.920654236492377}, {10., 7.011135776863383}, {
+      12., 5.787184005910186}, {14., 4.5966243137764415`}, {16., 
+      3.414701213177399}, {18., 2.259762465968268}, {20., 
+      1.1026037499814914`}, {22., -0.10662106627415432`}, {
+      24., -1.367082470968909}}]}, {{}, {}}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{1.5416666666666667`, -2.3710061312278032`},
+  DisplayFunction->Identity,
+  Frame->{{True, True}, {True, True}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->FrontEndValueCache[{{
+      Charting`ScaledTicks[{Log, Exp}], 
+      Charting`ScaledFrameTicks[{Identity, Identity}]}, {
+     Automatic, Automatic}}, {{{{-2.3025850929940455`, 
+        FormBox[
+         TagBox[
+          InterpretationBox[
+           StyleBox["\"0.1\"", ShowStringCharacters -> False], 0.1, 
+           AutoDelete -> True], NumberForm[#, {
+            DirectedInfinity[1], 1}]& ], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox["1", TraditionalForm], {0.01, 0.}}, {2.302585092994046, 
+        FormBox["10", TraditionalForm], {0.01, 0.}}, {4.605170185988092, 
+        FormBox["100", TraditionalForm], {0.01, 0.}}, {6.907755278982137, 
+        FormBox["1000", TraditionalForm], {0.01, 0.}}, {9.210340371976184, 
+        FormBox[
+         TemplateBox[{"10", "4"}, "Superscript", SyntaxForm -> 
+          SuperscriptBox], TraditionalForm], {0.01, 0.}}, {
+       11.512925464970229`, 
+        FormBox[
+         TemplateBox[{"10", "5"}, "Superscript", SyntaxForm -> 
+          SuperscriptBox], TraditionalForm], {0.01, 0.}}, {-4.605170185988091, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.506557897319982, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.2188758248682006`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.8134107167600364`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.659260036932778, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.5257286443082556`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.4079456086518722`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.2039728043259361`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.916290731874155, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5108256237659907, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.35667494393873245`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.2231435513142097, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.10536051565782628`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.0986122886681098`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.3862943611198906`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.791759469228055, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.9459101490553132`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.0794415416798357`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.1972245773362196`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.4011973816621555`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.6888794541139363`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.0943445622221, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.248495242049359, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.382026634673881, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.499809670330265, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.298317366548036, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.703782474656201, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.991464547107982, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.214608098422191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.396929655216146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.551080335043404, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.684611727667927, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.802394763324311, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       7.600902459542082, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.006367567650246, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.294049640102028, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.517193191416238, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.699514748210191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.85366542803745, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.987196820661973, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.104979856318357, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.903487552536127, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.308952660644293`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.596634733096073`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.819778284410283`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.002099841204238`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.156250521031495`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.289781913656018`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.407564949312402`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.206072645530174`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.611537753638338`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.89921982609012, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.122363377404328`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.304684934198283`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.458835614025542`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.592367006650065`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.710150042306449`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.815510557964274`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.9108207377686, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.997832114758229`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       14.077874822431765`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       14.151982794585487`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}}, {{-2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {
+       2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {
+       7.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {
+       10., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       7., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}}}, {
+     Automatic, Automatic}}],
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& )}},
+  PlotRange->{{1.5416666666666667`, 24.}, {-2.3710061312278032`, 
+   11.461682470049317`}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, 
+    Charting`ScaledTicks[{Log, Exp}]}]], "Output",
+ CellChangeTimes->{{3.861121495823804*^9, 3.861121503028514*^9}, {
+   3.861121598448876*^9, 3.861121612760919*^9}, {3.861121651882359*^9, 
+   3.861121708912607*^9}, {3.861122010692439*^9, 3.8611220241323547`*^9}, 
+   3.861122096424819*^9, 3.861122537165831*^9, 3.861123164008923*^9, 
+   3.861128916416933*^9, 3.861129335734619*^9, 3.861173536753436*^9},
+ CellLabel->
+  "Out[269]=",ExpressionUUID->"d727041d-b24d-4120-99a1-a4716f0510ef"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, {{}, {}, 
+     {RGBColor[1, 0, 0], PointSize[0.012833333333333334`], AbsoluteThickness[
+      1.6], LineBox[{{2., 1.9054543414901217`}, {4., 0.940742042839539}, {
+       6., -0.1375007436285417}, {8., -1.6355738920668188`}, {
+       10., -2.545092351695813}, {12., -3.7690441226490092`}, {
+       14., -4.959603814782754}, {16., -6.141526915381797}, {
+       18., -7.296465662590927}, {20., -8.453624378577704}, {
+       22., -9.662849194833349}, {
+       24., -10.923310599528104`}}]}}, {{}, {}}}, {{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{2., 1.9054543414901217`}, {4., 0.940742042839539}, {
+      6., -0.1375007436285417}, {8., -1.6355738920668188`}, {
+      10., -2.545092351695813}, {12., -3.7690441226490092`}, {
+      14., -4.959603814782754}, {16., -6.141526915381797}, {
+      18., -7.296465662590927}, {20., -8.453624378577704}, {
+      22., -9.662849194833349}, {24., -10.923310599528104`}}]}, {{}, {}}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{1.5416666666666667`, -11.927234259787001`},
+  DisplayFunction->Identity,
+  Frame->{{True, True}, {True, True}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->FrontEndValueCache[{{
+      Charting`ScaledTicks[{Log, Exp}], 
+      Charting`ScaledFrameTicks[{Identity, Identity}]}, {
+     Automatic, Automatic}}, {{{{-11.512925464970229`, 
+        FormBox[
+         TemplateBox[{"10", 
+           RowBox[{"-", "5"}]}, "Superscript", SyntaxForm -> SuperscriptBox], 
+         TraditionalForm], {0.01, 0.}}, {-9.210340371976182, 
+        FormBox[
+         TemplateBox[{"10", 
+           RowBox[{"-", "4"}]}, "Superscript", SyntaxForm -> SuperscriptBox], 
+         TraditionalForm], {0.01, 0.}}, {-6.907755278982137, 
+        FormBox["0.001`", TraditionalForm], {0.01, 0.}}, {-4.605170185988091, 
+        
+        FormBox[
+         TagBox[
+          InterpretationBox[
+           StyleBox["\"0.010\"", ShowStringCharacters -> False], 0.01, 
+           AutoDelete -> True], NumberForm[#, {
+            DirectedInfinity[1], 3}]& ], TraditionalForm], {0.01, 
+        0.}}, {-2.3025850929940455`, 
+        FormBox[
+         TagBox[
+          InterpretationBox[
+           StyleBox["\"0.100\"", ShowStringCharacters -> False], 0.1, 
+           AutoDelete -> True], NumberForm[#, {
+            DirectedInfinity[1], 3}]& ], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox["1", TraditionalForm], {0.01, 0.}}, {2.302585092994046, 
+        FormBox["10", TraditionalForm], {0.01, 0.}}, {-13.815510557964274`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-13.122363377404328`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-12.716898269296165`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-12.429216196844383`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-12.206072645530174`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-12.02375108873622, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-11.86960040890896, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-11.736069016284437`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-11.618285980628055`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-10.819778284410283`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-10.41431317630212, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-10.126631103850338`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.903487552536127, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.721165995742174, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.567015315914915, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.433483923290392, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.315700887634009, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-8.517193191416238, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-8.111728083308073, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.824046010856292, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.600902459542082, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.418580902748128, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.264430222920869, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.1308988302963465`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7.013115794639964, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-6.214608098422191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.809142990314028, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.521460917862246, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.298317366548036, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.115995809754082, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.961845129926823, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.8283137373023015`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.710530701645918, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.506557897319982, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.2188758248682006`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.8134107167600364`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.659260036932778, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.5257286443082556`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.4079456086518722`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.2039728043259361`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.916290731874155, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5108256237659907, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.35667494393873245`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.2231435513142097, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.10536051565782628`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.0986122886681098`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.3862943611198906`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.791759469228055, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.9459101490553132`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.0794415416798357`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.1972245773362196`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.4011973816621555`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.6888794541139363`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.0943445622221, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.248495242049359, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.382026634673881, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.499809670330265, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.605170185988092, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}}, {{-10., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-7.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {
+       2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-12.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-12., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-11.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-11., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-10.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-9., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-8.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-8., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-7., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-6.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-6., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}}}, {
+     Automatic, Automatic}}],
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& )}},
+  PlotRange->{{1.5416666666666667`, 24.}, {-11.927234259787001`, 
+   1.9054543414901217`}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, 
+    Charting`ScaledTicks[{Log, Exp}]}]], "Output",
+ CellChangeTimes->{{3.861121495823804*^9, 3.861121503028514*^9}, {
+   3.861121598448876*^9, 3.861121612760919*^9}, {3.861121651882359*^9, 
+   3.861121708912607*^9}, {3.861122010692439*^9, 3.8611220241323547`*^9}, 
+   3.861122096424819*^9, 3.861122537165831*^9, 3.861123164008923*^9, 
+   3.861128916416933*^9, 3.861129335734619*^9, 3.8611735369093018`*^9},
+ CellLabel->
+  "Out[272]=",ExpressionUUID->"bbcb174f-e6ea-4287-b0fd-9ee0a29f0795"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{
+   "pour", " ", "le", " ", "carr\[EAcute]", " ", "uniquement", " ", 
+    "comparaison", " ", "par", " ", "rapport", " ", "\[AGrave]", " ", "la", 
+    " ", "vraie", " ", "valeur", " ", "analytique"}], "*)"}], 
+  "\[IndentingNewLine]", 
+  RowBox[{"(*", 
+   RowBox[{
+    RowBox[{
+     RowBox[{
+     "erreur", " ", "entre", " ", "la", " ", "solution", " ", 
+      "num\[EAcute]rique", " ", "de", " ", "gauss", " ", "et", " ", "la", " ",
+       "vrai", " ", "solution", " ", "analytique", " ", "du", " ", 
+      "carr\[EAcute]"}], " ", "-", " ", 
+     RowBox[{"exemple", " ", "100", "*", "100"}]}], ",", " ", 
+    RowBox[{"20000", " ", "\[EAcute]l\[EAcute]ments"}], ",", " ", "triangle", 
+    ",", " ", 
+    RowBox[{"200", "V", " ", 
+     RowBox[{"d", "'"}], "un", " ", "c\[OHat]t\[EAcute]", " ", "et", " ", 
+     "100", "V", " ", "de", " ", 
+     RowBox[{"l", "'"}], "autre"}], ",", " ", 
+    RowBox[{
+    "probl\[EGrave]mes", " ", "sur", " ", "les", " ", "bords", " ", "du", " ",
+      "aux", " ", "\[EAcute]l\[EAcute]ments", " ", "constants", " ", "de", 
+     " ", "la", " ", "BEM"}]}], "*)"}], "\[IndentingNewLine]", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"datasquareanalytique", " ", "=", " ", 
+     RowBox[{"Table", "[", 
+      RowBox[{"100", ",", 
+       RowBox[{"{", 
+        RowBox[{"i", ",", "1", ",", 
+         RowBox[{"Length", "[", "dataelectricfieldanaly", "]"}]}], "}"}]}], 
+      "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"abserror", "=", 
+     RowBox[{"{", "}"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"relativeerror", "=", 
+     RowBox[{"{", "}"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{"For", "[", 
+    RowBox[{
+     RowBox[{"i", "=", "1"}], ",", 
+     RowBox[{"i", "\[LessEqual]", 
+      RowBox[{"Length", "[", "dataelectricfieldgauss", "]"}]}], ",", 
+     RowBox[{"i", "++"}], ",", "\[IndentingNewLine]", 
+     RowBox[{
+      RowBox[{"AppendTo", "[", 
+       RowBox[{"abserror", ",", 
+        RowBox[{"{", 
+         RowBox[{
+          RowBox[{"2", "*", "i"}], ",", 
+          RowBox[{"Sqrt", "[", 
+           RowBox[{"Sum", "[", 
+            RowBox[{
+             RowBox[{
+              RowBox[{"(", 
+               RowBox[{
+                RowBox[{"dataelectricfieldgauss", "[", 
+                 RowBox[{"[", 
+                  RowBox[{"i", ",", "j"}], "]"}], "]"}], "-", 
+                RowBox[{"datasquareanalytique", "[", 
+                 RowBox[{"[", "j", "]"}], "]"}]}], ")"}], "^", "2"}], ",", 
+             RowBox[{"{", 
+              RowBox[{"j", ",", "1", ",", 
+               RowBox[{"Length", "[", "datasquareanalytique", "]"}]}], 
+              "}"}]}], "]"}], "]"}]}], "}"}]}], "]"}], ";", 
+      "\[IndentingNewLine]", 
+      RowBox[{"AppendTo", "[", 
+       RowBox[{"relativeerror", ",", 
+        RowBox[{"{", 
+         RowBox[{
+          RowBox[{"i", "*", "2"}], ",", 
+          RowBox[{"Sqrt", "[", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"Sum", "[", 
+              RowBox[{
+               RowBox[{
+                RowBox[{"(", 
+                 RowBox[{
+                  RowBox[{"dataelectricfieldgauss", "[", 
+                   RowBox[{"[", 
+                    RowBox[{"i", ",", "j"}], "]"}], "]"}], "-", 
+                  RowBox[{"datasquareanalytique", "[", 
+                   RowBox[{"[", "j", "]"}], "]"}]}], ")"}], "^", "2"}], ",", 
+               RowBox[{"{", 
+                RowBox[{"j", ",", "1", ",", 
+                 RowBox[{"Length", "[", "dataelectricfieldanaly", "]"}]}], 
+                "}"}]}], "]"}], ")"}], "/", 
+            RowBox[{"(", 
+             RowBox[{"Sum", "[", 
+              RowBox[{
+               RowBox[{
+                RowBox[{"datasquareanalytique", "[", 
+                 RowBox[{"[", "j", "]"}], "]"}], "^", "2"}], ",", 
+               RowBox[{"{", 
+                RowBox[{"j", ",", "1", ",", 
+                 RowBox[{"Length", "[", "datasquareanalytique", "]"}]}], 
+                "}"}]}], "]"}], ")"}]}], "]"}]}], "}"}]}], "]"}], ";"}]}], 
+    "]"}], "\[IndentingNewLine]", "abserror", "\[IndentingNewLine]", 
+   "relativeerror"}]}]], "Input",
+ CellChangeTimes->{{3.8611230061599903`*^9, 3.861123006703861*^9}, {
+  3.8611230866723146`*^9, 3.861123125388547*^9}, {3.861123206040749*^9, 
+  3.861123206521308*^9}, {3.861260836376354*^9, 
+  3.861260877461598*^9}},ExpressionUUID->"d24f20d6-729f-4ebb-9bdc-\
+788273f1e3f9"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{"2", ",", "94942.80299918952`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"4", ",", "36143.53185124503`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"6", ",", "12257.188553966953`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"8", ",", "2686.854589001577`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"10", ",", "1092.1147355483317`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"12", ",", "337.37939925116`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"14", ",", "133.75233133719817`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"16", ",", "94.47331513035483`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "90.44860982366231`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"20", ",", "89.91014036466134`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"22", ",", "89.89450332422635`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"24", ",", "89.8862246056054`"}], "}"}]}], "}"}]], "Output",
+ CellChangeTimes->{3.8611231276753063`*^9, 3.86112316929661*^9, 
+  3.86117354759518*^9},
+ CellLabel->
+  "Out[277]=",ExpressionUUID->"87820575-f7aa-4bd3-8d26-eb8329c9e90d"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{"2", ",", "6.713469982558538`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"4", ",", "2.5557336468047334`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"6", ",", "0.8667141144792165`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"8", ",", "0.18998930999452093`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"10", ",", "0.07722417353399785`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"12", ",", "0.023856326104313885`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"14", ",", "0.00945771804880428`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"16", ",", "0.006680272176984757`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "0.00639568253552078`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"20", ",", "0.006357606994928636`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"22", ",", "0.006356501289195709`"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"24", ",", "0.006355915895388069`"}], "}"}]}], "}"}]], "Output",
+ CellChangeTimes->{3.8611231276753063`*^9, 3.86112316929661*^9, 
+  3.861173547600374*^9},
+ CellLabel->
+  "Out[278]=",ExpressionUUID->"c9d67024-7484-400e-99a3-606c54038a95"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+ RowBox[{
+  RowBox[{"g1", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"abserror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"PlotStyle", "\[Rule]", "Red"}], ",", 
+     RowBox[{"Joined", "\[Rule]", "True"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g2", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"abserror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{"Show", "[", 
+  RowBox[{"g1", ",", "g2"}], "]"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g3", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"relativeerror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"PlotStyle", "\[Rule]", "Red"}], ",", 
+     RowBox[{"Joined", "\[Rule]", "True"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"g4", "=", 
+   RowBox[{"ListLogPlot", "[", 
+    RowBox[{"relativeerror", ",", 
+     RowBox[{"PlotRange", "\[Rule]", "All"}], ",", 
+     RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{"Show", "[", 
+  RowBox[{"g3", ",", "g4"}], "]"}]}], "Input",
+ CellLabel->
+  "In[279]:=",ExpressionUUID->"c0d3d828-445a-4391-980f-255c7b107643"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, {{}, {}, 
+     {RGBColor[1, 0, 0], PointSize[0.012833333333333334`], AbsoluteThickness[
+      1.6], LineBox[{{2., 11.461029915570789`}, {4., 10.49525328630111}, {6., 
+       9.413867864592913}, {8., 7.89612649066494}, {10., 6.995871219968924}, {
+       12., 5.821208110900904}, {14., 4.895989816182697}, {16., 
+       4.548317415050113}, {18., 4.504781842167219}, {20., 
+       4.49881073116398}, {22., 4.498636797497378}, {24., 
+       4.498544699543141}}]}}, {{}, {}}}, {{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{2., 11.461029915570789`}, {4., 10.49525328630111}, {6., 
+      9.413867864592913}, {8., 7.89612649066494}, {10., 6.995871219968924}, {
+      12., 5.821208110900904}, {14., 4.895989816182697}, {16., 
+      4.548317415050113}, {18., 4.504781842167219}, {20., 4.49881073116398}, {
+      22., 4.498636797497378}, {24., 4.498544699543141}}]}, {{}, {}}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{1.5416666666666667`, 3.9536907190774175`},
+  DisplayFunction->Identity,
+  Frame->{{True, True}, {True, True}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->FrontEndValueCache[{{
+      Charting`ScaledTicks[{Log, Exp}], 
+      Charting`ScaledFrameTicks[{Identity, Identity}]}, {
+     Automatic, Automatic}}, {{{{4.605170185988092, 
+        FormBox["100", TraditionalForm], {0.01, 0.}}, {6.907755278982137, 
+        FormBox["1000", TraditionalForm], {0.01, 0.}}, {9.210340371976184, 
+        FormBox[
+         TemplateBox[{"10", "4"}, "Superscript", SyntaxForm -> 
+          SuperscriptBox], TraditionalForm], {0.01, 0.}}, {
+       11.512925464970229`, 
+        FormBox[
+         TemplateBox[{"10", "5"}, "Superscript", SyntaxForm -> 
+          SuperscriptBox], TraditionalForm], {0.01, 0.}}, {
+       2.302585092994046, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.4011973816621555`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.6888794541139363`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.0943445622221, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.248495242049359, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.382026634673881, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.499809670330265, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.298317366548036, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.703782474656201, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.991464547107982, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.214608098422191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.396929655216146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.551080335043404, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.684611727667927, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.802394763324311, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       7.600902459542082, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.006367567650246, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.294049640102028, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.517193191416238, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.699514748210191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.85366542803745, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.987196820661973, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.104979856318357, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.903487552536127, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.308952660644293`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.596634733096073`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.819778284410283`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.002099841204238`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.156250521031495`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.289781913656018`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.407564949312402`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.206072645530174`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.611537753638338`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12.89921982609012, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.122363377404328`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.304684934198283`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.458835614025542`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.592367006650065`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.710150042306449`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       13.815510557964274`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}}, {{
+       4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {6., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {8., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {
+       10., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       5.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       6.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       7., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       7.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       8.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       9.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       10.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       11.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       12., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}}}, {
+     Automatic, Automatic}}],
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& )}},
+  PlotRange->{{1.5416666666666667`, 24.}, {3.9536907190774175`, 
+   11.461029915570789`}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, 
+    Charting`ScaledTicks[{Log, Exp}]}]], "Output",
+ CellChangeTimes->{3.861123181547842*^9, 3.861173551563908*^9},
+ CellLabel->"Out[281]=",ImageCache->GraphicsData["CompressedBitmap", "\<\
+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
+pd578w==\
+\>", "ImageResolution" -> \
+144.],ExpressionUUID->"97b112e4-ab45-4d66-a9b3-928d93705112"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, {{}, {}, 
+     {RGBColor[1, 0, 0], PointSize[0.012833333333333334`], AbsoluteThickness[
+      1.6], LineBox[{{2., 1.9041159533146328`}, {4., 0.9383393240449559}, {
+       6., -0.1430460976632426}, {8., -1.6607874715912152`}, {
+       10., -2.561042742287231}, {12., -3.735705851355251}, {
+       14., -4.660924146073459}, {16., -5.008596547206042}, {
+       18., -5.052132120088936}, {20., -5.058103231092176}, {
+       22., -5.058277164758778}, {
+       24., -5.058369262713015}}]}}, {{}, {}}}, {{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.012833333333333334`],
+      AbsoluteThickness[1.6], 
+     PointBox[{{2., 1.9041159533146328`}, {4., 0.9383393240449559}, {
+      6., -0.1430460976632426}, {8., -1.6607874715912152`}, {
+      10., -2.561042742287231}, {12., -3.735705851355251}, {
+      14., -4.660924146073459}, {16., -5.008596547206042}, {
+      18., -5.052132120088936}, {20., -5.058103231092176}, {
+      22., -5.058277164758778}, {24., -5.058369262713015}}]}, {{}, {}}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{1.5416666666666667`, -5.603223243178739},
+  DisplayFunction->Identity,
+  Frame->{{True, True}, {True, True}},
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->FrontEndValueCache[{{
+      Charting`ScaledTicks[{Log, Exp}], 
+      Charting`ScaledFrameTicks[{Identity, Identity}]}, {
+     Automatic, Automatic}}, {{{{-4.605170185988091, 
+        FormBox[
+         TagBox[
+          InterpretationBox[
+           StyleBox["\"0.01\"", ShowStringCharacters -> False], 0.01, 
+           AutoDelete -> True], NumberForm[#, {
+            DirectedInfinity[1], 2}]& ], TraditionalForm], {0.01, 
+        0.}}, {-2.3025850929940455`, 
+        FormBox[
+         TagBox[
+          InterpretationBox[
+           StyleBox["\"0.10\"", ShowStringCharacters -> False], 0.1, 
+           AutoDelete -> True], NumberForm[#, {
+            DirectedInfinity[1], 2}]& ], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox["1", TraditionalForm], {0.01, 0.}}, {2.302585092994046, 
+        FormBox["10", TraditionalForm], {0.01, 0.}}, {-6.907755278982137, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-6.214608098422191, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.809142990314028, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.521460917862246, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.298317366548036, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.115995809754082, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.961845129926823, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.8283137373023015`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.710530701645918, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.506557897319982, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.2188758248682006`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.8134107167600364`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.659260036932778, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.5257286443082556`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.4079456086518722`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.2039728043259361`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.916290731874155, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5108256237659907, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.35667494393873245`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.2231435513142097, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.10536051565782628`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.6931471805599453, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.0986122886681098`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.3862943611198906`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.6094379124341003`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.791759469228055, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.9459101490553132`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.0794415416798357`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.1972245773362196`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.995732273553991, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.4011973816621555`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.6888794541139363`, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.912023005428146, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.0943445622221, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.248495242049359, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.382026634673881, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4.499809670330265, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}}, {{-4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {0., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 0.}}, {2., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.01, 
+        0.}}, {-6., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-5., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-4.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 
+        0.}}, {-0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       0.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       1.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       2.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       3.5, 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}, {
+       4., 
+        FormBox[
+         TemplateBox[{0., 0.}, "Spacer2"], TraditionalForm], {0.005, 0.}}}}, {
+     Automatic, Automatic}}],
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Exp[
+         Part[#, 2]]}& )}},
+  PlotRange->{{1.5416666666666667`, 24.}, {-5.603223243178739, 
+   1.9041159533146328`}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, 
+    Charting`ScaledTicks[{Log, Exp}]}]], "Output",
+ CellChangeTimes->{3.861123181547842*^9, 3.861173551653295*^9},
+ CellLabel->
+  "Out[284]=",ExpressionUUID->"d62a01ba-286a-47ed-b239-185edba12dd4"]
+}, Open  ]],
+
+Cell[BoxData[" "], "Input",
+ CellChangeTimes->{
+  3.861173940573041*^9},ExpressionUUID->"69447a35-9817-4522-9f86-\
+97bb0194d98b"],
+
+Cell[TextData[StyleBox["Plot d\[CloseCurlyQuote]une coupe de potentiel du \
+domaine BEM", "Title"]], "Text",
+ CellChangeTimes->{{3.861258541228631*^9, 3.86125858675126*^9}, {
+  3.8612589640592527`*^9, 
+  3.861258967152192*^9}},ExpressionUUID->"d4c6205f-288d-4ba9-9e4e-\
+bc0171921df9"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{
+    RowBox[{"data", "=", 
+     RowBox[{"Import", "[", 
+      RowBox[{
+      "\"\</Users/Kevin/Downloads/phi.msh_Levelset.txt\>\"", ",", 
+       "\"\<Table\>\""}], "]"}]}], ";"}], "*)"}], "\[IndentingNewLine]", 
+  RowBox[{
+   RowBox[{
+    RowBox[{"data", "=", 
+     RowBox[{"Import", "[", 
+      RowBox[{
+      "\"\</Users/Kevin/Downloads/double_hole.txt\>\"", ",", 
+       "\"\<Table\>\""}], "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{"(*", 
+    RowBox[{
+     RowBox[{"data", "=", 
+      RowBox[{"Import", "[", 
+       RowBox[{
+       "\"\</Users/Kevin/Desktop/phi.msh_Levelset.txt\>\"", ",", 
+        "\"\<Table\>\""}], "]"}]}], ";"}], "*)"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data1", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "1"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data2", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "2"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data3", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "3"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data4", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "4"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data5", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "5"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data6", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "6"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data7", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "7"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data8", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "8"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data9", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "9"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data9", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "9"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data10", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "10"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data11", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "11"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data12", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "12"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data13", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "13"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data14", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "14"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data15", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "15"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"data16", "=", 
+     RowBox[{"data", "[", 
+      RowBox[{"[", 
+       RowBox[{"All", ",", "16"}], "]"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"length", "=", 
+     RowBox[{"Length", "[", "data16", "]"}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"potential1", "=", 
+     RowBox[{"Table", "[", 
+      RowBox[{
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"data6", "[", 
+          RowBox[{"[", "i", "]"}], "]"}], ",", 
+         RowBox[{"data8", "[", 
+          RowBox[{"[", "i", "]"}], "]"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{"i", ",", "1", ",", "length"}], "}"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"potential2", "=", 
+     RowBox[{"Table", "[", 
+      RowBox[{
+       RowBox[{"{", 
+        RowBox[{
+         RowBox[{"data14", "[", 
+          RowBox[{"[", "i", "]"}], "]"}], ",", 
+         RowBox[{"data16", "[", 
+          RowBox[{"[", "i", "]"}], "]"}]}], "}"}], ",", 
+       RowBox[{"{", 
+        RowBox[{"i", ",", "1", ",", "length"}], "}"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"potential", "=", 
+     RowBox[{"Join", "[", 
+      RowBox[{"potential1", ",", "potential2"}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"g1", "=", 
+     RowBox[{"ListPlot", "[", 
+      RowBox[{"potential", ",", 
+       RowBox[{"Frame", "\[Rule]", "True"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"rescale", "=", 
+     RowBox[{
+      RowBox[{"RescalingTransform", "[", 
+       RowBox[{"CoordinateBounds", "[", "potential", "]"}], "]"}], "@", 
+      "potential"}]}], ";"}], "\n", 
+   RowBox[{"new", "=", 
+    RowBox[{"FindCurvePath", "@", "rescale"}]}], "\n", 
+   RowBox[{
+    RowBox[{"g2", "=", 
+     RowBox[{"ListLinePlot", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{
+         RowBox[{"potential", "[", 
+          RowBox[{"[", "#", "]"}], "]"}], "&"}], "/@", "new"}], ",", 
+       RowBox[{"PlotStyle", "\[Rule]", "Red"}]}], "]"}]}], ";"}], 
+   "\[IndentingNewLine]", 
+   RowBox[{"Show", "[", 
+    RowBox[{"g2", ",", "g1", ",", 
+     RowBox[{"Frame", "->", "True"}]}], "]"}], 
+   "\[IndentingNewLine]"}]}]], "Input",
+ CellChangeTimes->{{3.8611851956862497`*^9, 3.861185302243578*^9}, {
+   3.861185349637801*^9, 3.861185369291651*^9}, {3.861185419887733*^9, 
+   3.86118546737477*^9}, 3.861187912937941*^9, {3.861187984360655*^9, 
+   3.8611879922982883`*^9}, {3.8611880322634363`*^9, 3.861188048614867*^9}, {
+   3.861188096279683*^9, 3.861188138790277*^9}, {3.8611881750587587`*^9, 
+   3.86118834581749*^9}, {3.861188399757311*^9, 3.861188473593074*^9}, {
+   3.861188511707906*^9, 3.861188550238516*^9}, {3.861188647426079*^9, 
+   3.861188954510017*^9}, {3.861189078808382*^9, 3.86118911851886*^9}, {
+   3.861189410491591*^9, 3.861189413179975*^9}, {3.861189633611978*^9, 
+   3.861189660756143*^9}, {3.861189697543219*^9, 3.8611896984885674`*^9}, {
+   3.8611897900042667`*^9, 3.861189803558625*^9}, {3.861189840651662*^9, 
+   3.861189867869316*^9}, {3.861190246562645*^9, 3.861190301065031*^9}, 
+   3.861190342461088*^9, {3.861190428180133*^9, 3.861190553086246*^9}, {
+   3.861190900168805*^9, 3.861190941666606*^9}, {3.8611954752493477`*^9, 
+   3.8611954755274143`*^9}, {3.861195713486902*^9, 3.861195716839321*^9}, {
+   3.861195857565535*^9, 3.861195861741111*^9}},
+ CellLabel->
+  "In[1326]:=",ExpressionUUID->"b039c25c-3c81-424e-b355-8af2a1fea5a1"],
+
+Cell[BoxData[
+ RowBox[{"{", 
+  RowBox[{
+   RowBox[{"{", 
+    RowBox[{
+    "2", ",", "1", ",", "52", ",", "49", ",", "7", ",", "3", ",", "30", ",", 
+     "35", ",", "103", ",", "43", ",", "41", ",", "38", ",", "20", ",", "32", 
+     ",", "22", ",", "26", ",", "24", ",", "28", ",", "46", ",", "54", ",", 
+     "114", ",", "59", ",", "57", ",", "11"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{
+    "8", ",", "4", ",", "31", ",", "34", ",", "102", ",", "42", ",", "40", 
+     ",", "39", ",", "21", ",", "33", ",", "23", ",", "27", ",", "25", ",", 
+     "29", ",", "47", ",", "55", ",", "115", ",", "60", ",", "58", ",", 
+     "12"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{
+    "10", ",", "9", ",", "19", ",", "51", ",", "66", ",", "5", ",", "65", ",",
+      "13", ",", "53", ",", "48", ",", "8"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "17", ",", "62", ",", "2"}], "}"}], ",", 
+   RowBox[{"{", 
+    RowBox[{"18", ",", "10"}], "}"}]}], "}"}]], "Output",
+ CellChangeTimes->{{3.861185259766171*^9, 3.861185302922409*^9}, 
+   3.861185352523041*^9, {3.861185428923902*^9, 3.8611854677912807`*^9}, 
+   3.861188049002152*^9, {3.861188118104989*^9, 3.861188139327779*^9}, {
+   3.861188180943853*^9, 3.86118834213377*^9}, {3.861188425687414*^9, 
+   3.861188436288494*^9}, {3.861188503504902*^9, 3.861188512232707*^9}, 
+   3.861188550741851*^9, 3.8611887322200603`*^9, {3.86118878471275*^9, 
+   3.861188861712639*^9}, {3.86118891927712*^9, 3.8611889553269978`*^9}, {
+   3.861189097359291*^9, 3.861189119265131*^9}, 3.861189221033667*^9, 
+   3.8611894137688503`*^9, 3.8611896614846*^9, 3.861189805499155*^9, 
+   3.8611898706038837`*^9, 3.8611902659300528`*^9, {3.861190343287168*^9, 
+   3.8611903641335173`*^9}, {3.861190431354424*^9, 3.86119055360843*^9}, 
+   3.8611909427969017`*^9, 3.861195486997033*^9, 3.861195717614942*^9, 
+   3.8611958634851627`*^9},
+ CellLabel->
+  "Out[1350]=",ExpressionUUID->"75c96493-d7f7-4956-b2cf-f98cdd66fda1"],
+
+Cell[BoxData[
+ GraphicsBox[{{{}, {{}, {}, 
+     {RGBColor[1, 0, 0], PointSize[
+       NCache[
+        Rational[1, 60], 0.016666666666666666`]], AbsoluteThickness[1.6], 
+      LineBox[CompressedData["
+1:eJxTTMoPSmViYGCQAGIQHbRwAq9KyM79FR8t/l8TzXa4eMPQ2Nj48H5HHaCk
+Q5YDAxhc2A+mgPy7XC4rdZou7S/vyUm/ppjpwHFD7snR3Zf3Zzw8PitkWobD
+O5leTs7VV/crf9C+1Lkr3SG1Ss3w7qNr+2++X3Kx1CDdQftxTco19pv7NZyX
+xC2xS3NIOhEgFPb+5v7fLlGtr2+kOjw7Km5ekXFn/7q2vDsbjqQ4KOb4Vmd8
+uLM/pvSV3ITOFAfxyt2WEw/f3z/z8zbZ4sBkh/+f7LZwf7m/X6i64OFMm2SH
+xMQUPuYrD/bveL4xrbEpyWHRcuGtLLUP9/9WPXGQ/1OiQ19ek/Ll/of777Hw
+L5V5lOjwcNdTO1bGx/vnv7CfeWdlgsNp9o7cu9aP9xvc5rTJqUhwuCh4eiVz
+8ZP90TH3Hpo8j3PwuK5Xzr36yf4G5/0WGzrjHAxfayheWf10/zHVazlr7sY4
+NFu8WG349On+k4GSDCl1MQ4TetOP8u1+tv9HrQf7daloaHi+gIQnQ6QDANwo
+uO8=
+       "]]}, 
+     {RGBColor[1, 0, 0], PointSize[
+       NCache[
+        Rational[1, 60], 0.016666666666666666`]], AbsoluteThickness[1.6], 
+      LineBox[CompressedData["
+1:eJwBUQGu/iFib1JlAgAAABQAAAACAAAACNge5MW70z8sn/DnPPpsQOocjQkJ
+q9U/24+hfurNa0BjeiYx3eLWP+W6MitGEWtAJ+N8ZNYH2T/2VyIxA8dpQF/I
+UBJW79k/dnIDqxs8aUDkxRc3eGjcP7E+IToUw2dAHWxNe2jw3D8CRyHpY3Jn
+QBd5uzmRw98/sxj4bqzIZUD/8j60C/TfP3aekTU+rGVAX2FkDgPU4D8h6unT
+lq5kQKCnE7UEfeE/mClhl7HpY0CMboIj04/hP6U174H202NA4brlPgUB4z8q
+dudKmypiQMsHiG3dO+M/M5xqoknnYUDSEcupA3PkP2I0jsUwhGBASdcudwur
+5D85Ti8cjERgQDHrKCHUq+U/Z/pCzpNCXkCDOOirMeXlP93X7KLtwF1AkI1n
+xQ675j/YyLCDHN1bQAAAAAAAAOg/AAAAAAAAWUCndJX9
+       "]]}, 
+     {RGBColor[1, 0, 0], PointSize[
+       NCache[
+        Rational[1, 60], 0.016666666666666666`]], AbsoluteThickness[1.6], 
+      LineBox[{{-0.005541704640846631, 229.0153249535908}, {
+       0.02881512838732802, 233.6160342365152}, {0.03597247053500965, 
+       234.5721069260967}, {0.04189221989451287, 235.3707250988907}, {
+       0.07256871407405026, 239.4982910187085}, {0.09613814558468319, 
+       242.6884857924242}, {0.1149695112192741, 245.2413719521836}, {0.15, 
+       250.}, {0.25, 250.}, {0.2891952183710324, 237.7777554985219}, {
+       0.3083357551325894, 231.8199348163265}}]}, 
+     {RGBColor[1, 0, 0], PointSize[
+       NCache[
+        Rational[1, 60], 0.016666666666666666`]], AbsoluteThickness[1.6], 
+      LineBox[{{-0.0465353753516164, 
+       223.5857702997704}, {-0.04885286659846285, 
+       223.2779014698886}, {-0.05092566205446281, 
+       223.0053827702079}, {-0.09894013720680064, 216.6824947464154}}]}, 
+     {RGBColor[1, 0, 0], PointSize[
+       NCache[
+        Rational[1, 60], 0.016666666666666666`]], AbsoluteThickness[1.6], 
+      LineBox[{{-0.0465353753516164, 
+       223.5857702997704}, {-0.005541704640846631, 
+       229.0153249535908}}]}}, {{}, {}}}, {{}, 
+    {RGBColor[0.368417, 0.506779, 0.709798], PointSize[0.009166666666666668], 
+     AbsoluteThickness[1.6], PointBox[CompressedData["
+1:eJyllGtMk1cYxwtlQSSTiHdEl07xRiN09YLa9DxT4mWJRpiXuCLQGwV6wWBE
+nOAEd5EFFDQ6URxCSkgtIaCz4RI9GmRiiE6oKxBapNLSAnNgZ4yBLKxyePnw
+9sP5sJO8OfnlPTk5z5P/7+HJMuKV/hwOJ9v7fdw7ugVCobAFf8n3AqRDfEXx
+pysPNOLstzGTlgVq+Du8KCjI+CdeMRbZWdCkgmHCqPdixZnhZ2qQrI/KyC9r
+QJ/tksybdUjnw7O6lztam8041f7k+oGrqQwjfvmYSzSugb7BTedNeTfRJamu
+yCTUgmh8JXfwThb+6Y9HP+fe0gBnarkx2Y8wjBgWTq0WwpDBMDnvrUd1cNK7
+XNgd5jd1fprR0FnC21JM0WKuAXdeKS9xuNXQGJyzMMdcjTUhkooHHjUII/w7
+JtIr0Qt+1N198VqY9Ih/C373CoeePmYvFckZRlm/lmwU1yihsnrevYBcO56I
+aHsU4pHCLcLo2lrpL/VDcrA3OcWf+A3gcjcqtRqSGUbrslxf3Vgngwu6/BXm
+i3bcFxBSFf5aCoWEUdXG0bz3Zjm0B57X2rYN4OjeIJEmO5lhJCxLr9zjkoLy
+21UC22sL7hnVd5yIVoGcMHI2fRG5c64apFLFHO7Lftzgqk/Jy5dBEmHEGx4y
+X61VwOqBHIUlsAe9P/y5gPskDSIJ4zU79Il6cQq1vkWnmreUtLzCpf+Ylh2P
+m2F0d/EHXU2bEpZp9p5OHbMi/128IXmmCniEccKJ4eXFBQpwtC7anJ1qRfVi
+3tb5LSoYJIxrf9RZ6x7T39cxt93APe7AkoQ++wZXInQSRrINF1qjv0+G3tmx
+Bn5+J/I8+y5poEELNsL4ZKFGZeGlwfz+KR9QgNkbE5QB0ubnemdmFTr81j5u
+VWun8/diJl/TPJO/3V3rTwYbHfjsDhxTV5AIewijLfuiwgtjk33yVFykap3T
+PIg/5O4O7AqTMIy62+rOhdskcC7GbRQ4nfhp3BKO4kwCw8jW9Vflm4dHfXyN
+iwi7/Sb0Nl79MGcxv19N9a92f2O8XncflS2piWus1kFRpOFf6+U7qL3aj+MZ
+9e0Pu39sX9n+0Pxj95s9j2j9YdfL9pk9X2j5/L/+0fym5ZM2b2nzh+07ex7Q
+/Gf7yPaV5mdS2/7QQ6M9KCuTa1wqSgMZYTwR+80PI91K6n+aP1+fIr4tNJG8
+TDMeefqR06l5Zp9n3ycYWcN7aXTi3yMsmhpbAsNINb79+eXtiT7zgOYn7b7/
+AMLFk6k=
+      "]]}, {{}, {}}}},
+  AspectRatio->NCache[GoldenRatio^(-1), 0.6180339887498948],
+  Axes->{True, True},
+  AxesLabel->{None, None},
+  AxesOrigin->{0, 0},
+  DisplayFunction->Identity,
+  Frame->True,
+  FrameLabel->{{None, None}, {None, None}},
+  FrameTicks->{{Automatic, Automatic}, {Automatic, Automatic}},
+  GridLines->{None, None},
+  GridLinesStyle->Directive[
+    GrayLevel[0.5, 0.4]],
+  Method->{
+   "OptimizePlotMarkers" -> True, "OptimizePlotMarkers" -> True, 
+    "CoordinatesToolOptions" -> {"DisplayFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& ), "CopiedValueFunction" -> ({
+        Identity[
+         Part[#, 1]], 
+        Identity[
+         Part[#, 2]]}& )}},
+  PlotRange->{{-0.75, 0.75}, {0, 250.}},
+  PlotRangeClipping->True,
+  PlotRangePadding->{{
+     Scaled[0.02], 
+     Scaled[0.02]}, {
+     Scaled[0.02], 
+     Scaled[0.05]}},
+  Ticks->{Automatic, Automatic}]], "Output",
+ CellChangeTimes->{{3.861185259766171*^9, 3.861185302922409*^9}, 
+   3.861185352523041*^9, {3.861185428923902*^9, 3.8611854677912807`*^9}, 
+   3.861188049002152*^9, {3.861188118104989*^9, 3.861188139327779*^9}, {
+   3.861188180943853*^9, 3.86118834213377*^9}, {3.861188425687414*^9, 
+   3.861188436288494*^9}, {3.861188503504902*^9, 3.861188512232707*^9}, 
+   3.861188550741851*^9, 3.8611887322200603`*^9, {3.86118878471275*^9, 
+   3.861188861712639*^9}, {3.86118891927712*^9, 3.8611889553269978`*^9}, {
+   3.861189097359291*^9, 3.861189119265131*^9}, 3.861189221033667*^9, 
+   3.8611894137688503`*^9, 3.8611896614846*^9, 3.861189805499155*^9, 
+   3.8611898706038837`*^9, 3.8611902659300528`*^9, {3.861190343287168*^9, 
+   3.8611903641335173`*^9}, {3.861190431354424*^9, 3.86119055360843*^9}, 
+   3.8611909427969017`*^9, 3.861195486997033*^9, 3.861195717614942*^9, 
+   3.8611958635176287`*^9},
+ CellLabel->
+  "Out[1352]=",ExpressionUUID->"1674e868-ef4e-477c-b5e8-342b479f4694"]
+}, Open  ]],
+
+Cell[TextData[StyleBox["Calcul des matrices G, gradG, gradH de \
+mani\[EGrave]re analytique", "Title"]], "Text",
+ CellChangeTimes->{{3.861258663748384*^9, 
+  3.8612586958361387`*^9}},ExpressionUUID->"c6929cf8-3e79-4e5a-a751-\
+f0adefbedc6a"],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{
+   "calcul", " ", "de", " ", "G", " ", "par", " ", "changement", " ", "de", 
+    " ", "coordonn\[EAcute]es", " ", "\[Xi]"}], "*)"}], "\[IndentingNewLine]", 
+  RowBox[{"(*", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"j", "'"}], "ai", " ", "du", " ", "proc\[EAcute]der", " ", "par",
+      " ", "\[EAcute]tapes", " ", "car", " ", "m\[EHat]me", " ", "en", " ", 
+     "mettant", " ", "des", " ", "assumptions"}], ",", " ", 
+    RowBox[{
+    "mathematica", " ", "refuse", " ", "de", " ", "me", " ", "calculer", " ", 
+     
+     RowBox[{"l", "'"}], "int\[EAcute]grale", " ", "entre", " ", "2", " ", 
+     RowBox[{"bornes", ".", " ", "Je"}], " ", "passe", " ", "donc", " ", 
+     "par", " ", "le", " ", "calcul", " ", "de", " ", "la", " ", "primitive", 
+     " ", "que", " ", 
+     RowBox[{"j", "'"}], "\[EAcute]value", " ", "ensuite", " ", "aux", " ", 
+     "bornes", " ", 
+     RowBox[{"d", "'"}], "int\[EAcute]grations"}]}], "*)"}], "\n", 
+  RowBox[{
+   RowBox[{
+    RowBox[{
+     RowBox[{"x", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"xjp1", "+", "xj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"xjp1", "-", "xj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"y", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"yjp1", "+", "yj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"yjp1", "-", "yj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"r", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{"Sqrt", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"xi", "-", 
+          RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}], "+", 
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"yi", "-", 
+          RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}]}], "]"}]}], 
+    ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"matG", "=", 
+     RowBox[{"Integrate", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"lj", "/", 
+         RowBox[{"(", 
+          RowBox[{"4", "*", "Pi"}], ")"}]}], "*", 
+        RowBox[{"Log", "[", 
+         RowBox[{"r", "[", "\[Xi]", "]"}], "]"}]}], ",", "\[Xi]"}], "]"}]}], 
+    ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"bornesup", "=", 
+     RowBox[{"matG", "/.", 
+      RowBox[{"\[Xi]", "\[Rule]", "1"}]}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{
+    RowBox[{"borneinf", "=", 
+     RowBox[{"matG", "/.", 
+      RowBox[{"\[Xi]", "\[Rule]", 
+       RowBox[{"-", "1"}]}]}]}], ";"}], "\[IndentingNewLine]", 
+   RowBox[{"matG", "=", 
+    RowBox[{"FullSimplify", "[", 
+     RowBox[{"bornesup", "-", "borneinf"}], "]"}]}], "\[IndentingNewLine]", 
+   RowBox[{"formec", "=", 
+    RowBox[{"CForm", "[", "%", "]"}]}]}]}]], "Input",
+ CellChangeTimes->{{3.861257483289976*^9, 3.861257488134403*^9}, {
+  3.861257895179406*^9, 3.861257996199999*^9}, {3.8612580708324127`*^9, 
+  3.861258085264085*^9}},
+ CellLabel->"In[1]:=",ExpressionUUID->"aba879f4-4fa1-4a20-84ae-7797ad362ead"],
+
+Cell[BoxData[
+ RowBox[{
+  FractionBox["1", 
+   RowBox[{"4", " ", "\[Pi]", " ", 
+    RowBox[{"(", 
+     RowBox[{
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"xj", "-", "xjp1"}], ")"}], "2"], "+", 
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"yj", "-", "yjp1"}], ")"}], "2"]}], ")"}]}]], 
+  RowBox[{"lj", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"-", "2"}], " ", 
+      RowBox[{"(", 
+       RowBox[{
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"xj", "-", "xjp1"}], ")"}], "2"], "+", 
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"yj", "-", "yjp1"}], ")"}], "2"]}], ")"}]}], "+", 
+     RowBox[{"2", " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         RowBox[{"-", "xj"}], " ", "yi"}], "+", 
+        RowBox[{"xjp1", " ", "yi"}], "+", 
+        RowBox[{"xi", " ", "yj"}], "-", 
+        RowBox[{"xjp1", " ", "yj"}], "-", 
+        RowBox[{"xi", " ", "yjp1"}], "+", 
+        RowBox[{"xj", " ", "yjp1"}]}], ")"}], " ", 
+      RowBox[{"ArcTan", "[", 
+       FractionBox[
+        RowBox[{
+         RowBox[{
+          RowBox[{"(", 
+           RowBox[{"xi", "-", "xjp1"}], ")"}], " ", 
+          RowBox[{"(", 
+           RowBox[{"xj", "-", "xjp1"}], ")"}]}], "+", 
+         RowBox[{
+          RowBox[{"(", 
+           RowBox[{"yi", "-", "yjp1"}], ")"}], " ", 
+          RowBox[{"(", 
+           RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], 
+        RowBox[{
+         RowBox[{
+          RowBox[{"-", "xj"}], " ", "yi"}], "+", 
+         RowBox[{"xjp1", " ", "yi"}], "+", 
+         RowBox[{"xi", " ", "yj"}], "-", 
+         RowBox[{"xjp1", " ", "yj"}], "-", 
+         RowBox[{"xi", " ", "yjp1"}], "+", 
+         RowBox[{"xj", " ", "yjp1"}]}]], "]"}]}], "+", 
+     RowBox[{"2", " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         RowBox[{"-", "xjp1"}], " ", "yi"}], "-", 
+        RowBox[{"xi", " ", "yj"}], "+", 
+        RowBox[{"xjp1", " ", "yj"}], "+", 
+        RowBox[{"xj", " ", 
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yjp1"}], ")"}]}], "+", 
+        RowBox[{"xi", " ", "yjp1"}]}], ")"}], " ", 
+      RowBox[{"ArcTan", "[", 
+       FractionBox[
+        RowBox[{
+         RowBox[{
+          RowBox[{"(", 
+           RowBox[{"xi", "-", "xj"}], ")"}], " ", 
+          RowBox[{"(", 
+           RowBox[{"xj", "-", "xjp1"}], ")"}]}], "+", 
+         RowBox[{
+          RowBox[{"(", 
+           RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+          RowBox[{"(", 
+           RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], 
+        RowBox[{
+         RowBox[{"xjp1", " ", "yi"}], "+", 
+         RowBox[{"xi", " ", "yj"}], "-", 
+         RowBox[{"xjp1", " ", "yj"}], "-", 
+         RowBox[{"xi", " ", "yjp1"}], "+", 
+         RowBox[{"xj", " ", 
+          RowBox[{"(", 
+           RowBox[{
+            RowBox[{"-", "yi"}], "+", "yjp1"}], ")"}]}]}]], "]"}]}], "+", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         RowBox[{"-", 
+          RowBox[{"(", 
+           RowBox[{"xi", "-", "xj"}], ")"}]}], " ", 
+         RowBox[{"(", 
+          RowBox[{"xj", "-", "xjp1"}], ")"}]}], "-", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+         RowBox[{"(", 
+          RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], ")"}], " ", 
+      RowBox[{"Log", "[", 
+       RowBox[{
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"xi", "-", "xj"}], ")"}], "2"], "+", 
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yj"}], ")"}], "2"]}], "]"}]}], "+", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"xi", "-", "xjp1"}], ")"}], " ", 
+         RowBox[{"(", 
+          RowBox[{"xj", "-", "xjp1"}], ")"}]}], "+", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yjp1"}], ")"}], " ", 
+         RowBox[{"(", 
+          RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], ")"}], " ", 
+      RowBox[{"Log", "[", 
+       RowBox[{
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"xi", "-", "xjp1"}], ")"}], "2"], "+", 
+        SuperscriptBox[
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yjp1"}], ")"}], "2"]}], "]"}]}]}], 
+    ")"}]}]}]], "Output",
+ CellChangeTimes->{
+  3.8612578087441063`*^9, {3.861258073184415*^9, 3.86125808640173*^9}, 
+   3.8612581448196383`*^9},
+ CellLabel->"Out[7]=",ExpressionUUID->"1a498cc3-ec98-4fb7-9364-dcc415205357"],
+
+Cell["\<\
+(lj*(-2*(Power(xj - xjp1,2) + Power(yj - yjp1,2)) + 2*(-(xj*yi) + xjp1*yi + \
+xi*yj - xjp1*yj - xi*yjp1 + xj*yjp1)*
+        ArcTan(((xi - xjp1)*(xj - xjp1) + (yi - yjp1)*(yj - yjp1))/(-(xj*yi) \
++ xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*yjp1)) + 
+       2*(-(xjp1*yi) - xi*yj + xjp1*yj + xj*(yi - yjp1) + \
+xi*yjp1)*ArcTan(((xi - xj)*(xj - xjp1) + (yi - yj)*(yj - yjp1))/
+          (xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*(-yi + yjp1))) + (-((xi - \
+xj)*(xj - xjp1)) - (yi - yj)*(yj - yjp1))*Log(Power(xi - xj,2) + Power(yi - \
+yj,2)) + 
+       ((xi - xjp1)*(xj - xjp1) + (yi - yjp1)*(yj - yjp1))*Log(Power(xi - \
+xjp1,2) + Power(yi - yjp1,2))))/(4.*Pi*(Power(xj - xjp1,2) + Power(yj - \
+yjp1,2)))\
+\>", "Output",
+ CellChangeTimes->{
+  3.8612578087441063`*^9, {3.861258073184415*^9, 3.86125808640173*^9}, 
+   3.861258144830161*^9},
+ CellLabel->
+  "Out[8]//CForm=",ExpressionUUID->"b3ea9741-9cac-4165-ac03-4789f7b7458a"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{"calcul", " ", "de", " ", "gradGx", " ", "par", " ", "\[Xi]"}], 
+   "*)"}], "\n", 
+  RowBox[{
+   RowBox[{
+    RowBox[{
+     RowBox[{"x", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"xjp1", "+", "xj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"xjp1", "-", "xj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\n", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"y", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"yjp1", "+", "yj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"yjp1", "-", "yj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\n", 
+   RowBox[{
+    RowBox[{"r", "[", "\[Xi]_", "]"}], ":=", 
+    RowBox[{"Sqrt", "[", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"x", "[", "\[Xi]", "]"}], "-", "xi"}], ")"}], "^", "2"}], 
+      "+", 
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"y", "[", "\[Xi]", "]"}], "-", "yi"}], ")"}], "^", "2"}]}], 
+     "]"}]}], "\n", 
+   RowBox[{
+    RowBox[{"g1", "=", 
+     RowBox[{"Integrate", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"lj", "/", "2"}], "*", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"xi", "-", 
+           RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "/", 
+         RowBox[{"(", 
+          RowBox[{"2", "*", "Pi", "*", 
+           RowBox[{"(", 
+            RowBox[{
+             RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}], ")"}]}], ")"}]}]}],
+        ",", "\[Xi]"}], "]"}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g2", "=", 
+     RowBox[{"g1", "/.", 
+      RowBox[{"{", 
+       RowBox[{"\[Xi]", "\[Rule]", "1"}], "}"}]}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g3", "=", 
+     RowBox[{"Integrate", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"lj", "/", "2"}], "*", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"xi", "-", 
+           RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "/", 
+         RowBox[{"(", 
+          RowBox[{"2", "*", "Pi", "*", 
+           RowBox[{"(", 
+            RowBox[{
+             RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}], ")"}]}], ")"}]}]}],
+        ",", "\[Xi]"}], "]"}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g4", "=", 
+     RowBox[{"g3", "/.", 
+      RowBox[{"{", 
+       RowBox[{"\[Xi]", "\[Rule]", 
+        RowBox[{"-", "1"}]}], "}"}]}]}], ";"}], "\n", 
+   RowBox[{"FullSimplify", "[", 
+    RowBox[{"g2", "-", "g4"}], "]"}], "\n", 
+   RowBox[{"CForm", "[", "%", "]"}]}]}]], "Input",
+ CellLabel->
+  "In[1359]:=",ExpressionUUID->"70e041ab-7a76-4842-a412-090b3714cc63"],
+
+Cell[BoxData[
+ FractionBox[
+  RowBox[{"lj", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"-", "2"}], " ", 
+      RowBox[{"(", 
+       RowBox[{"yj", "-", "yjp1"}], ")"}], " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"ArcTan", "[", 
+         FractionBox[
+          RowBox[{
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"xi", "-", "xj"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{"xj", "-", "xjp1"}], ")"}]}], "+", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], 
+          RowBox[{
+           RowBox[{"xjp1", " ", "yi"}], "+", 
+           RowBox[{"xi", " ", "yj"}], "-", 
+           RowBox[{"xjp1", " ", "yj"}], "-", 
+           RowBox[{"xi", " ", "yjp1"}], "+", 
+           RowBox[{"xj", " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yi"}], "+", "yjp1"}], ")"}]}]}]], "]"}], "+", 
+        RowBox[{"ArcTan", "[", 
+         FractionBox[
+          RowBox[{
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"xi", "-", "xjp1"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "xj"}], "+", "xjp1"}], ")"}]}], "+", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"yi", "-", "yjp1"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yj"}], "+", "yjp1"}], ")"}]}]}], 
+          RowBox[{
+           RowBox[{"xjp1", " ", "yi"}], "+", 
+           RowBox[{"xi", " ", "yj"}], "-", 
+           RowBox[{"xjp1", " ", "yj"}], "-", 
+           RowBox[{"xi", " ", "yjp1"}], "+", 
+           RowBox[{"xj", " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yi"}], "+", "yjp1"}], ")"}]}]}]], "]"}]}], 
+       ")"}]}], "-", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"xj", "-", "xjp1"}], ")"}], " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"Log", "[", 
+         RowBox[{
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"xi", "-", "xj"}], ")"}], "2"], "+", 
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"yi", "-", "yj"}], ")"}], "2"]}], "]"}], "-", 
+        RowBox[{"Log", "[", 
+         RowBox[{
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"xi", "-", "xjp1"}], ")"}], "2"], "+", 
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"yi", "-", "yjp1"}], ")"}], "2"]}], "]"}]}], ")"}]}]}], 
+    ")"}]}], 
+  RowBox[{"4", " ", "\[Pi]", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"xj", "-", "xjp1"}], ")"}], "2"], "+", 
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"yj", "-", "yjp1"}], ")"}], "2"]}], ")"}]}]]], "Output",
+ CellChangeTimes->{3.861257820955475*^9},
+ CellLabel->
+  "Out[1366]=",ExpressionUUID->"fb22a801-d9c9-4302-a409-04f757cc31d5"],
+
+Cell["\<\
+(lj*(-2*(yj - yjp1)*(ArcTan(((xi - xj)*(xj - xjp1) + (yi - yj)*(yj - \
+yjp1))/(xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*(-yi + yjp1))) + 
+          ArcTan(((xi - xjp1)*(-xj + xjp1) + (yi - yjp1)*(-yj + \
+yjp1))/(xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*(-yi + yjp1)))) - 
+       (xj - xjp1)*(Log(Power(xi - xj,2) + Power(yi - yj,2)) - Log(Power(xi - \
+xjp1,2) + Power(yi - yjp1,2)))))/(4.*Pi*(Power(xj - xjp1,2) + Power(yj - \
+yjp1,2)))\
+\>", "Output",
+ CellChangeTimes->{3.861257820963357*^9},
+ CellLabel->
+  "Out[1367]//CForm=",ExpressionUUID->"0edfe664-e358-4b8b-8c1e-f77d428b251b"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[
+ RowBox[{
+  RowBox[{"(*", 
+   RowBox[{"calcul", " ", "de", " ", "gradGy", " ", "par", " ", "\[Xi]"}], 
+   "*)"}], "\[IndentingNewLine]", 
+  RowBox[{
+   RowBox[{
+    RowBox[{
+     RowBox[{"x", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"xjp1", "+", "xj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"xjp1", "-", "xj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\n", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"y", "[", "\[Xi]_", "]"}], ":=", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{"yjp1", "+", "yj"}], ")"}], "/", "2"}], "+", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"(", 
+         RowBox[{"yjp1", "-", "yj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+    ";"}], "\n", 
+   RowBox[{
+    RowBox[{"r", "[", "\[Xi]_", "]"}], ":=", 
+    RowBox[{"Sqrt", "[", 
+     RowBox[{
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"x", "[", "\[Xi]", "]"}], "-", "xi"}], ")"}], "^", "2"}], 
+      "+", 
+      RowBox[{
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"y", "[", "\[Xi]", "]"}], "-", "yi"}], ")"}], "^", "2"}]}], 
+     "]"}]}], "\n", 
+   RowBox[{
+    RowBox[{"g1", "=", 
+     RowBox[{"Integrate", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"lj", "/", "2"}], "*", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"yi", "-", 
+           RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "/", 
+         RowBox[{"(", 
+          RowBox[{"2", "*", "Pi", "*", 
+           RowBox[{"(", 
+            RowBox[{
+             RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}], ")"}]}], ")"}]}]}],
+        ",", "\[Xi]"}], "]"}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g2", "=", 
+     RowBox[{"g1", "/.", 
+      RowBox[{"{", 
+       RowBox[{"\[Xi]", "\[Rule]", "1"}], "}"}]}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g3", "=", 
+     RowBox[{"Integrate", "[", 
+      RowBox[{
+       RowBox[{
+        RowBox[{"lj", "/", "2"}], "*", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"yi", "-", 
+           RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "/", 
+         RowBox[{"(", 
+          RowBox[{"2", "*", "Pi", "*", 
+           RowBox[{"(", 
+            RowBox[{
+             RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}], ")"}]}], ")"}]}]}],
+        ",", "\[Xi]"}], "]"}]}], ";"}], "\n", 
+   RowBox[{
+    RowBox[{"g4", "=", 
+     RowBox[{"g3", "/.", 
+      RowBox[{"{", 
+       RowBox[{"\[Xi]", "\[Rule]", 
+        RowBox[{"-", "1"}]}], "}"}]}]}], ";"}], "\n", 
+   RowBox[{"FullSimplify", "[", 
+    RowBox[{"g2", "-", "g4"}], "]"}], "\n", 
+   RowBox[{"CForm", "[", "%", "]"}]}]}]], "Input",
+ CellChangeTimes->{{3.861258155747745*^9, 3.861258156239802*^9}},
+ CellLabel->"In[9]:=",ExpressionUUID->"4421bad8-e670-4d02-a48b-904eeb29edfb"],
+
+Cell[BoxData[
+ FractionBox[
+  RowBox[{"lj", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     RowBox[{"2", " ", 
+      RowBox[{"(", 
+       RowBox[{"xj", "-", "xjp1"}], ")"}], " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"ArcTan", "[", 
+         FractionBox[
+          RowBox[{
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"xi", "-", "xj"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{"xj", "-", "xjp1"}], ")"}]}], "+", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{"yj", "-", "yjp1"}], ")"}]}]}], 
+          RowBox[{
+           RowBox[{"xjp1", " ", "yi"}], "+", 
+           RowBox[{"xi", " ", "yj"}], "-", 
+           RowBox[{"xjp1", " ", "yj"}], "-", 
+           RowBox[{"xi", " ", "yjp1"}], "+", 
+           RowBox[{"xj", " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yi"}], "+", "yjp1"}], ")"}]}]}]], "]"}], "+", 
+        RowBox[{"ArcTan", "[", 
+         FractionBox[
+          RowBox[{
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"xi", "-", "xjp1"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "xj"}], "+", "xjp1"}], ")"}]}], "+", 
+           RowBox[{
+            RowBox[{"(", 
+             RowBox[{"yi", "-", "yjp1"}], ")"}], " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yj"}], "+", "yjp1"}], ")"}]}]}], 
+          RowBox[{
+           RowBox[{"xjp1", " ", "yi"}], "+", 
+           RowBox[{"xi", " ", "yj"}], "-", 
+           RowBox[{"xjp1", " ", "yj"}], "-", 
+           RowBox[{"xi", " ", "yjp1"}], "+", 
+           RowBox[{"xj", " ", 
+            RowBox[{"(", 
+             RowBox[{
+              RowBox[{"-", "yi"}], "+", "yjp1"}], ")"}]}]}]], "]"}]}], 
+       ")"}]}], "-", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"yj", "-", "yjp1"}], ")"}], " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"Log", "[", 
+         RowBox[{
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"xi", "-", "xj"}], ")"}], "2"], "+", 
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"yi", "-", "yj"}], ")"}], "2"]}], "]"}], "-", 
+        RowBox[{"Log", "[", 
+         RowBox[{
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"xi", "-", "xjp1"}], ")"}], "2"], "+", 
+          SuperscriptBox[
+           RowBox[{"(", 
+            RowBox[{"yi", "-", "yjp1"}], ")"}], "2"]}], "]"}]}], ")"}]}]}], 
+    ")"}]}], 
+  RowBox[{"4", " ", "\[Pi]", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"xj", "-", "xjp1"}], ")"}], "2"], "+", 
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"yj", "-", "yjp1"}], ")"}], "2"]}], ")"}]}]]], "Output",
+ CellChangeTimes->{3.861257873532209*^9, 3.861258173520028*^9},
+ CellLabel->"Out[16]=",ExpressionUUID->"c8795095-361d-4b25-bcd0-742fae5fbfde"],
+
+Cell["\<\
+(lj*(2*(xj - xjp1)*(ArcTan(((xi - xj)*(xj - xjp1) + (yi - yj)*(yj - \
+yjp1))/(xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*(-yi + yjp1))) + 
+          ArcTan(((xi - xjp1)*(-xj + xjp1) + (yi - yjp1)*(-yj + \
+yjp1))/(xjp1*yi + xi*yj - xjp1*yj - xi*yjp1 + xj*(-yi + yjp1)))) - 
+       (yj - yjp1)*(Log(Power(xi - xj,2) + Power(yi - yj,2)) - Log(Power(xi - \
+xjp1,2) + Power(yi - yjp1,2)))))/(4.*Pi*(Power(xj - xjp1,2) + Power(yj - \
+yjp1,2)))\
+\>", "Output",
+ CellChangeTimes->{3.861257873532209*^9, 3.861258173530663*^9},
+ CellLabel->
+  "Out[17]//CForm=",ExpressionUUID->"a7803c49-73b0-4652-a89a-bc89a1cb4cec"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+ RowBox[{
+  RowBox[{
+   RowBox[{"x", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"(", 
+      RowBox[{"xjp1", "+", "xj"}], ")"}], "/", "2"}], "+", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"xjp1", "-", "xj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{
+   RowBox[{"y", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"(", 
+      RowBox[{"yjp1", "+", "yj"}], ")"}], "/", "2"}], "+", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"yjp1", "-", "yj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{
+   RowBox[{"r", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{"Sqrt", "[", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"xi", "-", 
+        RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}], "+", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"yi", "-", 
+        RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"gradHx", "=", 
+   RowBox[{"Integrate", "[", 
+    RowBox[{
+     RowBox[{
+      FractionBox["lj", 
+       RowBox[{"2", "*", "Pi"}]], "*", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         FractionBox[
+          RowBox[{"-", 
+           RowBox[{"(", 
+            RowBox[{
+             RowBox[{
+              RowBox[{"1", "/", "2"}], "*", 
+              RowBox[{
+               RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}]}], "-", 
+             RowBox[{
+              RowBox[{"(", 
+               RowBox[{"xi", "-", 
+                RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}]}], 
+            ")"}]}], 
+          RowBox[{
+           RowBox[{"r", "[", "\[Xi]", "]"}], "^", "4"}]], "*", "nx"}], "+", 
+        RowBox[{
+         FractionBox[
+          RowBox[{
+           RowBox[{"(", 
+            RowBox[{"xi", "-", 
+             RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "*", 
+           RowBox[{"(", 
+            RowBox[{"yi", "-", 
+             RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}]}], 
+          RowBox[{
+           RowBox[{"r", "[", "\[Xi]", "]"}], "^", "4"}]], "*", "ny"}]}], 
+       ")"}]}], ",", "\[Xi]"}], "]"}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"bornesup", "=", 
+   RowBox[{"gradHx", "/.", 
+    RowBox[{"\[Xi]", "\[Rule]", "1"}]}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"borneinf", "=", 
+   RowBox[{"gradHx", "/.", 
+    RowBox[{"\[Xi]", "\[Rule]", 
+     RowBox[{"-", "1"}]}]}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{"gradHx", "=", 
+  RowBox[{"FullSimplify", "[", 
+   RowBox[{"bornesup", "-", "borneinf"}], "]"}]}], "\[IndentingNewLine]", 
+ RowBox[{"formec", "=", 
+  RowBox[{"CForm", "[", "%", "]"}]}]}], "Input",
+ CellLabel->"In[30]:=",ExpressionUUID->"c1f1582f-6978-4e3e-9743-4da5fa3fe712"],
+
+Cell[BoxData[
+ FractionBox[
+  RowBox[{"lj", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     RowBox[{"nx", " ", 
+      RowBox[{"(", 
+       RowBox[{
+        SuperscriptBox["xi", "2"], "+", 
+        RowBox[{"xj", " ", "xjp1"}], "-", 
+        RowBox[{"xi", " ", 
+         RowBox[{"(", 
+          RowBox[{"xj", "+", "xjp1"}], ")"}]}], "-", 
+        RowBox[{
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+         RowBox[{"(", 
+          RowBox[{"yi", "-", "yjp1"}], ")"}]}]}], ")"}]}], "-", 
+     RowBox[{"ny", " ", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{"xj", " ", "yi"}], "+", 
+        RowBox[{"xjp1", " ", "yi"}], "-", 
+        RowBox[{"xjp1", " ", "yj"}], "-", 
+        RowBox[{"xj", " ", "yjp1"}], "+", 
+        RowBox[{"xi", " ", 
+         RowBox[{"(", 
+          RowBox[{
+           RowBox[{
+            RowBox[{"-", "2"}], " ", "yi"}], "+", "yj", "+", "yjp1"}], 
+          ")"}]}]}], ")"}]}]}], ")"}]}], 
+  RowBox[{"2", " ", "\[Pi]", " ", 
+   RowBox[{"(", 
+    RowBox[{
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"xi", "-", "xj"}], ")"}], "2"], "+", 
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"yi", "-", "yj"}], ")"}], "2"]}], ")"}], " ", 
+   RowBox[{"(", 
+    RowBox[{
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"xi", "-", "xjp1"}], ")"}], "2"], "+", 
+     SuperscriptBox[
+      RowBox[{"(", 
+       RowBox[{"yi", "-", "yjp1"}], ")"}], "2"]}], ")"}]}]]], "Output",
+ CellChangeTimes->{3.861258377252224*^9},
+ CellLabel->"Out[36]=",ExpressionUUID->"8918a234-b86f-421c-aab8-2633de35a885"],
+
+Cell["\<\
+(lj*(nx*(Power(xi,2) + xj*xjp1 - xi*(xj + xjp1) - (yi - yj)*(yi - yjp1)) - \
+ny*(xj*yi + xjp1*yi - xjp1*yj - xj*yjp1 + xi*(-2*yi + yj + yjp1))))/
+   (2.*Pi*(Power(xi - xj,2) + Power(yi - yj,2))*(Power(xi - xjp1,2) + \
+Power(yi - yjp1,2)))\
+\>", "Output",
+ CellChangeTimes->{3.8612583772630167`*^9},
+ CellLabel->
+  "Out[37]//CForm=",ExpressionUUID->"7827bc67-ba5a-419b-a3b4-d82b0dca4cef"]
+}, Open  ]],
+
+Cell[CellGroupData[{
+
+Cell[BoxData[{
+ RowBox[{
+  RowBox[{
+   RowBox[{"x", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"(", 
+      RowBox[{"xjp1", "+", "xj"}], ")"}], "/", "2"}], "+", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"xjp1", "-", "xj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{
+   RowBox[{"y", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{
+    RowBox[{
+     RowBox[{"(", 
+      RowBox[{"yjp1", "+", "yj"}], ")"}], "/", "2"}], "+", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"yjp1", "-", "yj"}], ")"}], "/", "2"}], "*", "\[Xi]"}]}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{
+   RowBox[{"r", "[", "\[Xi]_", "]"}], ":=", 
+   RowBox[{"Sqrt", "[", 
+    RowBox[{
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"xi", "-", 
+        RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}], "+", 
+     RowBox[{
+      RowBox[{"(", 
+       RowBox[{"yi", "-", 
+        RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}]}], "]"}]}], 
+  ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"gradHy", "=", 
+   RowBox[{"Integrate", "[", 
+    RowBox[{
+     RowBox[{
+      FractionBox["lj", 
+       RowBox[{"2", "*", "Pi"}]], "*", 
+      RowBox[{"(", 
+       RowBox[{
+        RowBox[{
+         FractionBox[
+          RowBox[{
+           RowBox[{"(", 
+            RowBox[{"xi", "-", 
+             RowBox[{"x", "[", "\[Xi]", "]"}]}], ")"}], "*", 
+           RowBox[{"(", 
+            RowBox[{"yi", "-", 
+             RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}]}], 
+          RowBox[{
+           RowBox[{"r", "[", "\[Xi]", "]"}], "^", "4"}]], "*", "nx"}], "-", 
+        RowBox[{
+         FractionBox[
+          RowBox[{"(", 
+           RowBox[{
+            RowBox[{
+             RowBox[{"1", "/", "2"}], "*", 
+             RowBox[{
+              RowBox[{"r", "[", "\[Xi]", "]"}], "^", "2"}]}], "-", 
+            RowBox[{
+             RowBox[{"(", 
+              RowBox[{"yi", "-", 
+               RowBox[{"y", "[", "\[Xi]", "]"}]}], ")"}], "^", "2"}]}], ")"}], 
+          RowBox[{
+           RowBox[{"r", "[", "\[Xi]", "]"}], "^", "4"}]], "*", "ny"}]}], 
+       ")"}]}], ",", "\[Xi]"}], "]"}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"bornesup", "=", 
+   RowBox[{"gradHy", "/.", 
+    RowBox[{"\[Xi]", "\[Rule]", "1"}]}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{
+  RowBox[{"borneinf", "=", 
+   RowBox[{"gradHy", "/.", 
+    RowBox[{"\[Xi]", "\[Rule]", 
+     RowBox[{"-", "1"}]}]}]}], ";"}], "\[IndentingNewLine]", 
+ RowBox[{"gradHy", "=", 
+  RowBox[{"FullSimplify", "[", 
+   RowBox[{"bornesup", "-", "borneinf"}], "]"}]}], "\[IndentingNewLine]", 
+ RowBox[{"formec", "=", 
+  RowBox[{"CForm", "[", "%", "]"}]}]}], "Input",
+ CellLabel->"In[38]:=",ExpressionUUID->"03f15880-2958-4e18-9bb8-16c122fc0a39"],
+
+Cell[BoxData[
+ RowBox[{"-", 
+  FractionBox[
+   RowBox[{"lj", " ", 
+    RowBox[{"(", 
+     RowBox[{
+      RowBox[{"ny", " ", 
+       RowBox[{"(", 
+        RowBox[{
+         SuperscriptBox["xi", "2"], "+", 
+         RowBox[{"xj", " ", "xjp1"}], "-", 
+         RowBox[{"xi", " ", 
+          RowBox[{"(", 
+           RowBox[{"xj", "+", "xjp1"}], ")"}]}], "-", 
+         RowBox[{
+          RowBox[{"(", 
+           RowBox[{"yi", "-", "yj"}], ")"}], " ", 
+          RowBox[{"(", 
+           RowBox[{"yi", "-", "yjp1"}], ")"}]}]}], ")"}]}], "+", 
+      RowBox[{"nx", " ", 
+       RowBox[{"(", 
+        RowBox[{
+         RowBox[{"xj", " ", "yi"}], "+", 
+         RowBox[{"xjp1", " ", "yi"}], "-", 
+         RowBox[{"xjp1", " ", "yj"}], "-", 
+         RowBox[{"xj", " ", "yjp1"}], "+", 
+         RowBox[{"xi", " ", 
+          RowBox[{"(", 
+           RowBox[{
+            RowBox[{
+             RowBox[{"-", "2"}], " ", "yi"}], "+", "yj", "+", "yjp1"}], 
+           ")"}]}]}], ")"}]}]}], ")"}]}], 
+   RowBox[{"2", " ", "\[Pi]", " ", 
+    RowBox[{"(", 
+     RowBox[{
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"xi", "-", "xj"}], ")"}], "2"], "+", 
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"yi", "-", "yj"}], ")"}], "2"]}], ")"}], " ", 
+    RowBox[{"(", 
+     RowBox[{
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"xi", "-", "xjp1"}], ")"}], "2"], "+", 
+      SuperscriptBox[
+       RowBox[{"(", 
+        RowBox[{"yi", "-", "yjp1"}], ")"}], "2"]}], ")"}]}]]}]], "Output",
+ CellChangeTimes->{3.861258380590827*^9},
+ CellLabel->"Out[44]=",ExpressionUUID->"a3781fd5-d327-4440-918d-e56f72684d55"],
+
+Cell["\<\
+-(lj*(ny*(Power(xi,2) + xj*xjp1 - xi*(xj + xjp1) - (yi - yj)*(yi - yjp1)) + \
+nx*(xj*yi + xjp1*yi - xjp1*yj - xj*yjp1 + xi*(-2*yi + yj + yjp1))))/
+   (2.*Pi*(Power(xi - xj,2) + Power(yi - yj,2))*(Power(xi - xjp1,2) + \
+Power(yi - yjp1,2)))\
+\>", "Output",
+ CellChangeTimes->{3.8612583806008244`*^9},
+ CellLabel->
+  "Out[45]//CForm=",ExpressionUUID->"f99fcb66-bf4a-41a0-b4d3-08c71e8326bd"]
+}, Open  ]]
+},
+WindowSize->{1440, 768},
+WindowMargins->{{0, Automatic}, {Automatic, 0}},
+FrontEndVersion->"12.1 for Mac OS X x86 (64-bit) (June 19, 2020)",
+StyleDefinitions->"Default.nb",
+ExpressionUUID->"62450a5e-61bb-4842-a3e4-6a2b62f893d3"
+]
+(* End of Notebook Content *)
+
+(* Internal cache information *)
+(*CellTagsOutline
+CellTagsIndex->{}
+*)
+(*CellTagsIndex
+CellTagsIndex->{}
+*)
+(*NotebookFileOutline
+Notebook[{
+Cell[558, 20, 223, 4, 73, "Text",ExpressionUUID->"2a4634af-38af-46df-ba82-22e16ff7cedb"],
+Cell[CellGroupData[{
+Cell[806, 28, 11065, 286, 799, "Input",ExpressionUUID->"4ed55133-bec1-4475-ad1f-833b36b2d4c6"],
+Cell[11874, 316, 1718, 38, 34, "Output",ExpressionUUID->"65fdfe1a-aa66-4933-962e-56e19b792ce1"],
+Cell[13595, 356, 998, 14, 34, "Output",ExpressionUUID->"89f7ea64-7da5-4498-b160-d9b88f8879d8"],
+Cell[14596, 372, 10273, 185, 232, "Output",ExpressionUUID->"7a89971a-d470-4aba-b097-89238335c823"],
+Cell[24872, 559, 1114, 17, 34, "Output",ExpressionUUID->"c024bf23-b077-4190-b9e3-f1d5fb19ed2f"],
+Cell[25989, 578, 1052, 16, 34, "Output",ExpressionUUID->"c87b3cd2-72e1-4211-9c33-d98771a9e76c"],
+Cell[27044, 596, 7500, 140, 232, "Output",ExpressionUUID->"9b57112f-d238-4317-89cb-371ba4a2c235"],
+Cell[34547, 738, 992, 14, 34, "Output",ExpressionUUID->"8a451dcb-573e-4f9f-97e1-ed70aded0195"],
+Cell[35542, 754, 1116, 17, 34, "Output",ExpressionUUID->"71c50b88-43c3-43d1-9b99-9504c5bd5f96"],
+Cell[36661, 773, 7697, 143, 232, "Output",ExpressionUUID->"db2bab01-4618-4db7-8683-117d6150b911"],
+Cell[44361, 918, 1002, 14, 34, "Output",ExpressionUUID->"ba354193-5beb-4a8c-962b-96de2fd88bc5"],
+Cell[45366, 934, 1716, 37, 46, "Output",ExpressionUUID->"b590e101-f372-4eaa-b07a-74c6853e96a8"],
+Cell[47085, 973, 1052, 16, 34, "Output",ExpressionUUID->"6b5e6dbe-960f-4c2f-b7df-540c1741735c"],
+Cell[48140, 991, 7759, 144, 232, "Output",ExpressionUUID->"f64ed0f3-5f81-46ef-b0d2-0deaec21c948"],
+Cell[55902, 1137, 1365, 22, 34, "Output",ExpressionUUID->"1ad22f7c-dddb-4448-9317-229eaab684eb"],
+Cell[57270, 1161, 2871, 62, 249, "Output",ExpressionUUID->"f67cbd93-c669-4bc7-87c6-cf7ae689c11a"]
+}, Open  ]],
+Cell[60156, 1226, 407, 6, 197, "Text",ExpressionUUID->"a9e8cb00-e27d-4ce1-93f1-c63f24dce0c4"],
+Cell[CellGroupData[{
+Cell[60588, 1236, 4682, 111, 472, "Input",ExpressionUUID->"3022f7f2-8c9c-43ae-9732-d602151de8a8"],
+Cell[65273, 1349, 1194, 30, 56, "Output",ExpressionUUID->"953df72a-406a-4325-a6b7-b588ecdbd337"],
+Cell[66470, 1381, 1227, 31, 56, "Output",ExpressionUUID->"505cf359-5431-4db8-b379-4278c65326ec"]
+}, Open  ]],
+Cell[67712, 1415, 245, 6, 52, "Input",ExpressionUUID->"5184b6ce-6f3e-4ace-8f94-4112569cfa78"],
+Cell[67960, 1423, 1468, 39, 224, InheritFromParent,ExpressionUUID->"131c83d3-03c9-4c25-8f61-e5f9f199818d"],
+Cell[69431, 1464, 15945, 392, 238, "Output",ExpressionUUID->"d727041d-b24d-4120-99a1-a4716f0510ef"],
+Cell[85379, 1858, 15836, 389, 238, "Output",ExpressionUUID->"bbcb174f-e6ea-4287-b0fd-9ee0a29f0795"],
+Cell[CellGroupData[{
+Cell[101240, 2251, 4431, 108, 373, "Input",ExpressionUUID->"d24f20d6-729f-4ebb-9bdc-788273f1e3f9"],
+Cell[105674, 2361, 1145, 30, 56, "Output",ExpressionUUID->"87820575-f7aa-4bd3-8d26-eb8329c9e90d"],
+Cell[106822, 2393, 1171, 30, 56, "Output",ExpressionUUID->"c9d67024-7484-400e-99a3-606c54038a95"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[108030, 2428, 1400, 38, 224, "Input",ExpressionUUID->"c0d3d828-445a-4391-980f-255c7b107643"],
+Cell[109433, 2468, 23699, 472, 238, 9980, 246, "CachedBoxData", "BoxData", "Output",ExpressionUUID->"97b112e4-ab45-4d66-a9b3-928d93705112"],
+Cell[133135, 2942, 10339, 254, 246, "Output",ExpressionUUID->"d62a01ba-286a-47ed-b239-185edba12dd4"]
+}, Open  ]],
+Cell[143489, 3199, 129, 3, 30, "Input",ExpressionUUID->"69447a35-9817-4522-9f86-97bb0194d98b"],
+Cell[143621, 3204, 284, 5, 73, "Text",ExpressionUUID->"d4c6205f-288d-4ba9-9e4e-bc0171921df9"],
+Cell[CellGroupData[{
+Cell[143930, 3213, 6943, 204, 1045, "Input",ExpressionUUID->"b039c25c-3c81-424e-b355-8af2a1fea5a1"],
+Cell[150876, 3419, 1948, 37, 56, "Output",ExpressionUUID->"75c96493-d7f7-4956-b2cf-f98cdd66fda1"],
+Cell[152827, 3458, 5964, 122, 244, "Output",ExpressionUUID->"1674e868-ef4e-477c-b5e8-342b479f4694"]
+}, Open  ]],
+Cell[158806, 3583, 240, 4, 73, "Text",ExpressionUUID->"c6929cf8-3e79-4e5a-a751-f0adefbedc6a"],
+Cell[CellGroupData[{
+Cell[159071, 3591, 3247, 89, 299, "Input",ExpressionUUID->"aba879f4-4fa1-4a20-84ae-7797ad362ead"],
+Cell[162321, 3682, 4424, 136, 138, "Output",ExpressionUUID->"1a498cc3-ec98-4fb7-9364-dcc415205357"],
+Cell[166748, 3820, 932, 18, 106, "Output",ExpressionUUID->"b3ea9741-9cac-4165-ac03-4789f7b7458a"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[167717, 3843, 2745, 91, 293, "Input",ExpressionUUID->"70e041ab-7a76-4842-a412-090b3714cc63"],
+Cell[170465, 3936, 2984, 91, 68, "Output",ExpressionUUID->"fb22a801-d9c9-4302-a409-04f757cc31d5"],
+Cell[173452, 4029, 595, 11, 70, "Output",ExpressionUUID->"0edfe664-e358-4b8b-8c1e-f77d428b251b"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[174084, 4045, 2822, 91, 293, "Input",ExpressionUUID->"4421bad8-e670-4d02-a48b-904eeb29edfb"],
+Cell[176909, 4138, 2979, 89, 68, "Output",ExpressionUUID->"c8795095-361d-4b25-bcd0-742fae5fbfde"],
+Cell[179891, 4229, 614, 11, 81, "Output",ExpressionUUID->"a7803c49-73b0-4652-a89a-bc89a1cb4cec"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[180542, 4245, 2852, 90, 258, "Input",ExpressionUUID->"c1f1582f-6978-4e3e-9743-4da5fa3fe712"],
+Cell[183397, 4337, 1564, 49, 62, "Output",ExpressionUUID->"8918a234-b86f-421c-aab8-2633de35a885"],
+Cell[184964, 4388, 397, 8, 63, "Output",ExpressionUUID->"7827bc67-ba5a-419b-a3b4-d82b0dca4cef"]
+}, Open  ]],
+Cell[CellGroupData[{
+Cell[185398, 4401, 2803, 88, 258, "Input",ExpressionUUID->"03f15880-2958-4e18-9bb8-16c122fc0a39"],
+Cell[188204, 4491, 1628, 50, 62, "Output",ExpressionUUID->"a3781fd5-d327-4440-918d-e56f72684d55"],
+Cell[189835, 4543, 398, 8, 63, "Output",ExpressionUUID->"f99fcb66-bf4a-41a0-b4d3-08c71e8326bd"]
+}, Open  ]]
+}
+]
+*)
+
diff --git a/srcs/BEM/functionsBEM.hpp b/srcs/BEM/functionsBEM.hpp
index e705a73356775bcb6d84184ecb05b2d99d7b7f7a..c2cce535a33e45229b983a63ae0000941a7ff197 100644
--- a/srcs/BEM/functionsBEM.hpp
+++ b/srcs/BEM/functionsBEM.hpp
@@ -206,4 +206,4 @@ double computeAnalyticalGradHx(const double x, const double y, const elementStru
 double computeAnalyticalGradHy(const double x, const double y, const elementStruct &element);
 double computeAnalyticalGradGx(const double x, const double y, const elementStruct &element);
 double computeAnalyticalGradGy(const double x, const double y, const elementStruct &element);
-double computeAnalyticalG(const double x, const double y, const elementStruct &element);
\ No newline at end of file
+double computeAnalyticalG(const double x, const double y, const elementStruct &element);
diff --git a/srcs/BEM/mainBEM.cpp b/srcs/BEM/mainBEM.cpp
index 35655adb9b513d22220df01b905da9a8178b7b90..02035781a5f8ac07e30bc7e0ac8848a8994c4116 100644
--- a/srcs/BEM/mainBEM.cpp
+++ b/srcs/BEM/mainBEM.cpp
@@ -22,7 +22,7 @@ int main(int argc, char **argv)
     std::map<int,std::pair<double,double>> nodalDisplacements;
     const bool postProcessing = true;
     const bool meshUntangler = false;
-    
+
     solverBEM(electrostaticPressure, nbViews, nodalDisplacements, postProcessing, 1, meshUntangler); // iteration number randomly set to 1
 
     if(postProcessing)
diff --git a/srcs/FEM/complex_validation.geo b/srcs/FEM/complex_validation.geo
index 47e62fe7faf89f96039b9b0497e4db00896d6c36..c6497d704d992ca7c8e18d45c13bd1a1477d9b89 100644
--- a/srcs/FEM/complex_validation.geo
+++ b/srcs/FEM/complex_validation.geo
@@ -2,15 +2,15 @@
 
 Lx = 5;
 Ly = 2;
-nx = 50;
-ny = 20;
-
-Point(1) = {0, 0, 0, 0.1};
-Point(2) = {Lx, 0, 0, 0.2};
-Point(3) = {Lx, Ly, 0, 0.2};
-Point(4) = {0, Ly, 0, 0.1};
-Point(5) = {Lx/2, 0, 0, 0.15}; 
-Point(6) = {Lx/2, Ly, 0, 0.15}; 
+nx = 250;
+ny = 100;
+
+Point(1) = {0, 0, 0, 0.05}; //4th number is mesh density
+Point(2) = {Lx, 0, 0, 0.1};
+Point(3) = {Lx, Ly, 0, 0.1};
+Point(4) = {0, Ly, 0, 0.05};
+Point(5) = {Lx/2, 0, 0, 0.075}; 
+Point(6) = {Lx/2, Ly, 0, 0.075}; 
 Line(1) = {1, 5};
 Line(2) = {2, 5};
 Line(3) = {3, 2};
@@ -52,6 +52,8 @@ SetNumber("Boundary Conditions/right_edge/tx", 21e3); //for simple tension condi
 SetNumber("Boundary Conditions/right_edge/ty", 0.);
 SetNumber("Volumic Forces/FEM_domain/bx",0.);
 SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
-SetNumber("Boundary Conditions/fixed_node/uy",0.);
+SetNumber("Boundary Conditions/fixed_node/uy",2);
 
 Physical Curve("BEM_FEM_boundary", 10) = {1,2,3,4,5,6};
+
+SetNumber("Non_linear_solver", 0);
\ No newline at end of file
diff --git a/srcs/FEM/functionsFEM.cpp b/srcs/FEM/functionsFEM.cpp
index 5e9c0f8d378069bb173514d0d35f8ca361783761..4e39d98fc945929feef1a900577489a4f010f6de 100644
--- a/srcs/FEM/functionsFEM.cpp
+++ b/srcs/FEM/functionsFEM.cpp
@@ -1,82 +1,236 @@
 #ifdef _MSC_VER
-#include <gmsh.h_cwrap>       // gmsh main header
+#include <gmsh.h_cwrap>
 #else
-#include <gmsh.h>       // gmsh main header
+#include <gmsh.h>
 #endif
 
 #include "functionsFEM.hpp"
 
-#include <iostream>     // for std::cout
+#include <iostream> 
 #include <map>
-#include <sstream>  // for std::stringstream
-#include <Eigen/Dense> // Eigen library
-#include <Eigen/Sparse> // Eigen library for sparse matrices
+#include <sstream>
+#include <Eigen/Dense> 
+#include <Eigen/Sparse>
 #include <Eigen/SparseCholesky> // solving sparse linear systems
 #include <Eigen/Core>
 #include <cmath>
-#include <algorithm> // to sort and merge the FEM node vectors
+#include <algorithm> 
 #ifdef _OPENMP
 #include <omp.h>
 #endif
 #define PI M_PI
 
-//Compute the matrix H
-Eigen::Matrix<double, 3, 3> computeHmatrix(const double E, const double nu)
+// returns the boolean non_linear_solver parameter based on what is set in the .geo file,
+// add SetNumber("Non_linear_solver", 0); in .geo file to use linear solver.
+bool getNonLinearParameter()
 {
-    Eigen::Matrix<double, 3, 3> H_matrix;
-    H_matrix(0,0) = 1.;
-    H_matrix(1,0) = nu;
-    H_matrix(2,0) = 0.;
-    H_matrix(0,1) = nu;
-    H_matrix(1,1) = 1.;
-    H_matrix(2,1) = 0.;
-    H_matrix(0,2) = 0.;
-    H_matrix(1,2) = 0.;
-    H_matrix(2,2) = (1-nu)/2;
-    H_matrix = E/(1-nu*nu)*H_matrix;
-    return H_matrix;
+    std::vector<std::string> keys;
+    gmsh::onelab::getNames(keys, "Non_linear_solver");
+    if(keys.size())
+    {
+        std::vector<double> value;
+        gmsh::onelab::getNumber(keys[0], value);
+        if(value[0])
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    else
+    {
+        std::cout << "you did not choose the type of solver (linear or not) in the .geo file, 'SetNumber('Non_linear_solver',x);'. Automatically set to non linear type \n";
+        return true;
+    }
 }
 
-//Compute the full matrix "f" of one given thread
-void assembleFthread(const int i, const int el, 
-                          const std::vector<std::vector<std::size_t>> & nodeTags, 
-                          const int numNodes, std::map<int, int> & nodeIndexMap,
-                          std::list<std::pair<int,double>> & thread_f_vector, 
-                          std::vector<double> & f_vector)
+// fills the "FEM_nodeTags" vector with the nodes in the FEM domain, fills the "FEM_nodeCoordsMap" with the coordinates (x,y)
+// corresponding to each nodeTag, looking at entity tags "tags" of dimension "dim" corresponding to the FEM domain.
+void RetrieveFEMNodeTagsAndCoords(std::vector<std::size_t> & FEM_nodeTags, 
+                            std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, 
+                            const int & dim, const std::vector<int> & tags)
 {
-    int first_node_index;
-    int first_node;
-    int my_row;
-    for (int j = 0; j < 2*numNodes; ++j)
+    //loop over the entities of the FEM domain to retrieve all nodeTags by taking care not to take some nodes twice
+    //using sort and set_union methods + retrieving the node coordinates and storing them in a map
+    std::vector<double> FEM_nodecoord;
+    std::vector<double> FEM_nodeparametricCoord;
+    std::vector<std::vector<std::size_t>> tmp_nodeTags(tags.size()); // will store the nodeTags associated to one given entity of the domain
+    gmsh::model::mesh::getNodes(tmp_nodeTags[0], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[0], true); 
+    for(std::size_t j = 0; j < tmp_nodeTags[0].size(); j++)
     {
-        first_node_index = (int) j/2;
-        first_node = nodeTags[i][numNodes*el+first_node_index];
-        my_row = nodeIndexMap[first_node] + j % 2; 
-        thread_f_vector.push_back(std::pair<int, double>(my_row, f_vector[j]));
+        FEM_nodeCoordsMap[tmp_nodeTags[0][j]] = std::pair<double, double>(FEM_nodecoord[3*j], FEM_nodecoord[3*j+1]);
+    }
+    std::sort(tmp_nodeTags[0].begin(), tmp_nodeTags[0].end()); // need to sort the vectors in order to merge them afterwards
+    for (std::size_t i = 1; i < tags.size(); i++)
+    { // in the case the domain contains multiple entities
+        gmsh::model::mesh::getNodes(tmp_nodeTags[i], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[i], true);
+        for(std::size_t j = 0; j < tmp_nodeTags[i].size(); j++)
+        {
+            FEM_nodeCoordsMap[tmp_nodeTags[i][j]] = std::pair<double, double>(FEM_nodecoord[3*j], FEM_nodecoord[3*j+1]);
+        }
+        std::sort(tmp_nodeTags[i].begin(), tmp_nodeTags[i].end());
+        std::set_union(tmp_nodeTags[i-1].begin(), tmp_nodeTags[i-1].end(),
+                       tmp_nodeTags[i].begin(), tmp_nodeTags[i].end(), std::back_inserter(FEM_nodeTags)); // works only for 2 domains -> see little trick just below
+        
+    }
+    if(tags.size() == 1){ // if the domain contains one single entity
+        FEM_nodeTags = tmp_nodeTags[0];
+    }
+    else{ // little trick for more than 2 domains
+        std::sort(FEM_nodeTags.begin(), FEM_nodeTags.end());
+        auto last = std::unique(FEM_nodeTags.begin(), FEM_nodeTags.end());
+        FEM_nodeTags.erase(last, FEM_nodeTags.end());
     }
 }
 
+// fills the "FEM_elementTags" vector with all element tags of the elements of dimension "dim" (in practice: 2)
+// in the entities associated to the entity tags "tags" (corresponding to the FEM domain).
+// associates an initialized elementData structure to each element tag through the "FEM_kinematicsMap" map,
+// using the "FEM_nodeCoordsMap" map gathering the coordinates of each node in the FEM domain.
+int initKinematics(std::vector<std::size_t> & FEM_elementTags, std::map<int, elementData> & FEM_kinematicsMap, 
+                std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, 
+                const int & dim, const std::vector<int> & tags)
+{
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> elnodeTags;
 
-void computeBmatrix(const int j, const int numNodes, const std::vector<double> & basisFunctionsGradient,
-                      const std::vector<double> & determinants, 
-                      const Eigen::Matrix<double, 2, 2> & jacobinvtrans,
-                      const Eigen::Matrix<double, 3, 3> & H_matrix,
-                      Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & B_matrix)
+    std::string elementName;
+    int elDim, order, numNodes, numPrimaryNodes;
+    std::vector<double> localNodeCoord;
+    
+    int nbelems=0; // will store total number of elements in FEM domain
+    for(std::size_t i=0; i< tags.size(); ++i)
+    {
+        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
+        for(std::size_t j=0; j< elementTags.size(); ++j)
+        {
+            nbelems+=elementTags[j].size();
+            // filling the FEM_elementTags vector
+            FEM_elementTags.insert(FEM_elementTags.end(), elementTags[j].begin(), elementTags[j].end());
+
+            // getting element properties, in particular: number of nodes
+            gmsh::model::mesh::getElementProperties(elementTypes[j],
+                                                        elementName, elDim, order,
+                                                        numNodes, localNodeCoord, 
+                                                        numPrimaryNodes);
+            for(std::size_t k = 0; k < elementTags[j].size(); k++)
+            {
+                elementData element;
+                std::vector<size_t> tmp_nodes(numNodes);
+                std::vector<double> tmp_x(numNodes);
+                std::vector<double> tmp_y(numNodes);
+                std::vector<double> tmp_u(numNodes);
+                std::vector<double> tmp_v(numNodes);
+                std::vector<double> tmp_ui(numNodes);
+                std::vector<double> tmp_vi(numNodes);
+                double tmp_xc = 0; 
+                double tmp_yc = 0;
+                for(int l = 0; l < numNodes; l++)
+                {
+                    tmp_nodes[l] = elnodeTags[j][numNodes*k + l];
+                    tmp_x[l] = FEM_nodeCoordsMap[tmp_nodes[l]].first;
+                    tmp_y[l] = FEM_nodeCoordsMap[tmp_nodes[l]].second;
+                    tmp_u[l] = 0; // initializing the displacement at zero
+                    tmp_v[l] = 0;
+                    tmp_ui[l] = 0;
+                    tmp_vi[l] = 0;
+                    tmp_xc += tmp_x[l];
+                    tmp_yc += tmp_y[l];
+                }
+                tmp_xc = tmp_xc / numNodes;
+                tmp_yc = tmp_yc / numNodes;
+
+                std::vector<double> tmp_xi(numNodes);
+                std::vector<double> tmp_yi(numNodes);
+                for(int l = 0; l < numNodes; l++)
+                {
+                    tmp_xi[l] = tmp_x[l] - tmp_xc;
+                    tmp_yi[l] = tmp_y[l] - tmp_yc;
+                }
+                element.nodes = tmp_nodes;
+                element.x = tmp_x;
+                element.y = tmp_y;
+                element.xc = tmp_xc;
+                element.yc = tmp_yc;
+                element.xi = tmp_xi;
+                element.yi = tmp_yi;
+                element.u = tmp_u;
+                element.v = tmp_v;
+                element.uc = 0;
+                element.vc = 0;
+                element.theta = 0;
+                element.ui = tmp_ui;
+                element.vi = tmp_vi;
+                element.pl = Eigen::Matrix<double, Eigen::Dynamic, 1>::Zero(2*numNodes,1);
+                element.A = Eigen::Matrix<double, Eigen::Dynamic, 1>(2*numNodes,1);
+                element.G = Eigen::Matrix<double, 1, Eigen::Dynamic>(1,2*numNodes);
+                element.E = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>::Zero(2*numNodes, 2*numNodes);
+
+                FEM_kinematicsMap[elementTags[j][k]] = element;
+                updateKinMatrices(& FEM_kinematicsMap[elementTags[j][k]], false);
+            }
+        }
+    }
+    return nbelems;
+}
+
+// updates the kinematics matrices of one element "element" based on its updated nodal positions and rotation angle.
+// if "computeFl" is set as true, also computes the local nodal forces vector "fl = Kl*pl", only OK if 
+// the local stiffness matrix Kl has already been initialized, using "fillElementalKandF".
+void updateKinMatrices(elementData* element, const bool computeFl)
 {
-    for (int l = 0; l < numNodes; ++l){ // looping over the number of shape functions
-        B_matrix(0,2*l) = jacobinvtrans(0,0)*basisFunctionsGradient[3*l+numNodes*3*j]+jacobinvtrans(0,1)*basisFunctionsGradient[3*l+numNodes*3*j+1];
-        B_matrix(1,2*l) = 0.;
-        B_matrix(2,2*l) = jacobinvtrans(1,0)*basisFunctionsGradient[3*l+numNodes*3*j]+jacobinvtrans(1,1)*basisFunctionsGradient[3*l+numNodes*3*j+1];
-        B_matrix(0,2*l+1) = 0.;
-        B_matrix(1,2*l+1) = B_matrix(2,2*l);
-        B_matrix(2,2*l+1) = B_matrix(0,2*l);
+    // for the different formulas, please refer to the report
+    size_t numNodes = element->nodes.size();
+    // update A matrix
+    for(size_t i = 0; i < numNodes; i++)
+    {
+        element->A(2*i, 0) = -(element->vi[i]+element->yi[i]);
+        element->A(2*i + 1, 0) = element->ui[i]+element->xi[i];
+    }
+
+    // update G matrix
+    double denominator = 0;
+    for(size_t i = 0; i < numNodes; i++)
+    {
+        element->G(0, 2*i) = -element->yi[i];
+        element->G(0, 2*i + 1) = element->xi[i];
+        denominator += element->xi[i]*(element->ui[i]+element->xi[i]) + element->yi[i]*(element->vi[i]+element->yi[i]);
+    }
+    element->G *= 1 / denominator;
+
+    // update P matrix 
+    element->P = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>::Identity(2*numNodes,2*numNodes) - element->A*element->G;
+
+    // update E matrix
+    double tmp_cos = cos(element->theta);
+    double tmp_sin = sin(element->theta);
+    for(size_t i = 0; i < numNodes; i++)
+    {
+        element->E(2*i, 2*i) = tmp_cos;
+        element->E(2*i, 2*i + 1) = -tmp_sin;
+        element->E(2*i + 1, 2*i) = tmp_sin;
+        element->E(2*i + 1, 2*i + 1) = tmp_cos;
+    }
+
+    //update C matrix
+    element->C = element->P*element->E.transpose();
+
+    //update fl vector, only if Kl has been initialized
+    if(computeFl)
+    {
+        element->fl = element->Kl*element->pl;
     }
 }
 
-//Get physical properties of domain
-void getPhysicalProperties(const std::vector<std::string> & keys, double & E, double & nu, double & rho,
-                              double & bx, double & by)
+// gets physical properties of FEM_domain: Young's modulus "E", Poisson's ratio "nu",
+// density "rho", volumic force along x "bx", volumic force along y "by".
+void getPhysicalProperties(double & E, double & nu, double & rho, double & bx, double & by)
 {
+    std::vector<std::string> keys;
+    gmsh::onelab::getNames(keys, "(Volumic Forces|Materials).+");
     for (auto &key : keys)
     {
         // get corresponding value
@@ -110,12 +264,30 @@ void getPhysicalProperties(const std::vector<std::string> & keys, double & E, do
     }
 }
 
-void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double rho, const double bx, const double by,
-              const std::string & integration_rule, 
-              int & dim, std::vector<int> & tags, std::map<int, int>  & nodeIndexMap,
-              std::vector<std::list<Eigen::Triplet <double>>> & my_k_list, 
-              std::vector<std::list<std::pair<int,double>>> & thread_f_vector,
-              std::map<int, elementData> & FEM_kinematicsMap)
+// computes the Hooke's matrix in plane stress "H_matrix" based on the Young's modulus "E" and Poisson's ratio "nu".
+Eigen::Matrix<double, 3, 3> computeHmatrix(const double E, const double nu)
+{
+    Eigen::Matrix<double, 3, 3> H_matrix;
+    H_matrix(0,0) = 1.;
+    H_matrix(1,0) = nu;
+    H_matrix(2,0) = 0.;
+    H_matrix(0,1) = nu;
+    H_matrix(1,1) = 1.;
+    H_matrix(2,1) = 0.;
+    H_matrix(0,2) = 0.;
+    H_matrix(1,2) = 0.;
+    H_matrix(2,2) = (1-nu)/2;
+    H_matrix = E/(1-nu*nu)*H_matrix;
+    return H_matrix;
+}
+
+// looping over every element in the FEM_domain (dimension "dim" and entity tags "tags"), filling "full_f_vector",
+// with the local volumic forces computed based on the volumic force ("bx","by") and density "rho" with the help of
+// "nodeIndexMap" mapping each nodeTag to its global index.
+// filling the local stiffness matrices stored in the elementData structure contained in "FEM_kinematicsMap".
+void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double & rho, const double & bx, 
+                const double & by, const int & dim, const std::vector<int> & tags, std::map<int, int> & nodeIndexMap,
+                std::vector<double> & full_f_vector, std::map<int, elementData> & FEM_kinematicsMap)
 {
     std::vector<int> elementTypes;
     std::vector<std::vector<std::size_t>> elementTags;
@@ -133,7 +305,7 @@ void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double
         gmsh::model::mesh::getElements(elementTypes, elementTags,
                                        nodeTags, dim, tags[k]);
         
-        // looping over element types, enlever les déclarations des boucles pr aller plus vite (cfr Boman)
+        // looping over element types
         for (std::size_t i = 0; i < elementTypes.size(); ++i)
         {
             // getting element properties
@@ -141,17 +313,24 @@ void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double
                                             elementName, elDim, order,
                                             numNodes, localNodeCoord, 
                                             numPrimaryNodes);
+
+            // adapting the composite integration rule as a function of the order of the elements
+            std::string adapting_integration_rule = "CompositeGauss14";
+            if(order < 8)
+            {
+                adapting_integration_rule = "CompositeGauss" + std::to_string(2*order);
+            }
             
             // get Gauss points coordinates and weights
             gmsh::model::mesh::getIntegrationPoints(elementTypes[i], 
-                                                    integration_rule, // "Gauss2"
+                                                    adapting_integration_rule, 
                                                     localCoords, weights);
 
             // get determinants and Jacobians
             std::vector<double> jacobians, determinants, coords;
             gmsh::model::mesh::getJacobians(elementTypes[i], 
                                             localCoords, jacobians, 
-                                            determinants, coords);
+                                            determinants, coords, tags[k]);
 
             // values and derivatives of the shape functions at the Gauss points of the reference element
             // we are here working with derivatives in the reference space, same for all elements
@@ -167,15 +346,16 @@ void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double
 
             /*---------computing the K matrix (and f vector, only volumic part for now)------*/
             // looping over the elements (computing elemental K matrices)
-            //double test1 = omp_get_wtime();
-            //Eigen::setNbThreads(1);
-            #pragma omp parallel for
             #ifdef _MSC_VER
             // https://github.com/tesseract-ocr/tesseract/issues/3285
             // OpenMP 2.0 standard is enforced - we may use /openmp:llvm and keep size_t
-            for (int el = 0; el < elementTags[i].size(); el++){
+            #pragma omp parallel for
+            for (size_t el = 0; el < elementTags[i].size(); el++)
+            {
             #else
-            for (std::size_t el = 0; el < elementTags[i].size(); el++){
+            #pragma omp parallel for
+            for (std::size_t el = 0; el < elementTags[i].size(); el++)
+            {
             #endif
                 // elemental K matrix and f vector initialization
                 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> K_matrix(2*numNodes,2*numNodes);
@@ -183,12 +363,13 @@ void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double
                 K_matrix.setZero();
                 for (int j = 0; j < 2*numNodes; ++j)f_vector[j] = 0.;
 
-                // looping over the Gauss points (formula of slide 17)
-                for (std::size_t j = 0; j < weights.size(); ++j){
+                // looping over the Gauss points
+                for (std::size_t gaussIndex = 0; gaussIndex < weights.size(); ++gaussIndex)
+                {
                     // converting jacobian to Eigen format
                     Eigen::Matrix<double, 2, 2> jacob2D;
                     Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
-                        jacob(&jacobians[9*j+9*weights.size()*el], 3, 3);
+                        jacob(&jacobians[9*gaussIndex+9*weights.size()*el], 3, 3);
                     // 3D to 2D (plane stress case)
                     jacob2D(0,0) = jacob(0,0);
                     jacob2D(1,0) = jacob(1,0);
@@ -204,67 +385,68 @@ void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double
                     // computing the B matrix (formula slide 19) and the f vector (also using gauss integration)
                     Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
 
-
-                    computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, 
-                                     jacobinvtrans, H_matrix, B_matrix);
+                    computeBmatrix(gaussIndex, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
                     
-                    for (int l = 0; l < numNodes; ++l){ // looping over the number of shape functions
-                        f_vector[2*l] = f_vector[2*l] + rho*basisFunctions[l+numNodes*j]*bx*determinants[j+weights.size()*el]*weights[j]; //pas oublier le dét !
-                        f_vector[2*l+1] = f_vector[2*l+1] + rho*basisFunctions[l+numNodes*j]*by*determinants[j+weights.size()*el]*weights[j]; // pas oublier le weights[j] non plus !
+                    for (int l = 0; l < numNodes; ++l)
+                    { // looping over the number of shape functions
+                        f_vector[2*l] = f_vector[2*l] + rho*basisFunctions[l+numNodes*gaussIndex]*bx*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
+                        f_vector[2*l+1] = f_vector[2*l+1] + rho*basisFunctions[l+numNodes*gaussIndex]*by*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
                     }
 
-                    K_matrix = K_matrix + B_matrix.transpose()*H_matrix*B_matrix*determinants[j+weights.size()*el]*weights[j];
+                    K_matrix = K_matrix + B_matrix.transpose()*H_matrix*B_matrix*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
                 }
                 /*------------- ASSEMBLY PROCESS ------------*/
-                // USE LIST OF TRIPLETS TO PUSH ONLY ONCE -> more rapid and easier to parallelize
                 FEM_kinematicsMap[elementTags[i][el]].Kl = K_matrix;
-                assembleFthread(i, el, nodeTags, numNodes, nodeIndexMap, thread_f_vector[omp_get_thread_num()], f_vector);
-                //std::cout << omp_get_thread_num() << "\n";
+                assembleFlocal(el, nodeTags[i], numNodes, nodeIndexMap, full_f_vector, f_vector);
             }
-            //double test2 = omp_get_wtime() - test1;
-            //std::cout << "loop time: " << test2 << "\n";
         }
     }
 }
 
-/*-----------computing the f vector components related to this Neumann BC---------*/
-void computeNeumannBC(const int numNodes, const int i, const std::vector<std::vector<std::size_t>> & elementTags,
-                        const double tx, const double ty, std::map<int, int> & nodeIndexMap,
-                        std::vector<double> & f_vector,
-                        const std::vector<double> & weights, const std::vector<double> & basisFunctions, 
-                        const std::vector<double> & determinants, const std::vector<std::vector<std::size_t>> & nodeTags,
-                        std::vector<double> & full_f_vector)
+// computing the strain displacement "B_matrix" at the "gaussIndex"-th gaussian point of the element
+// consisting of "numNodes" nodes, based on the "basisFunctionsGradient", "determinants" and the inverse of the jacobian
+// matrix "jacobinvtrans".
+void computeBmatrix(const int &gaussIndex, const int &numNodes, const std::vector<double> & basisFunctionsGradient,
+                      const std::vector<double> & determinants, 
+                      const Eigen::Matrix<double, 2, 2> & jacobinvtrans,
+                      Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & B_matrix)
+{
+    for (int l = 0; l < numNodes; ++l){ // looping over the number of shape functions
+        B_matrix(0,2*l) = jacobinvtrans(0,0)*basisFunctionsGradient[3*l+numNodes*3*gaussIndex]+jacobinvtrans(0,1)*basisFunctionsGradient[3*l+numNodes*3*gaussIndex+1];
+        B_matrix(1,2*l) = 0.;
+        B_matrix(2,2*l) = jacobinvtrans(1,0)*basisFunctionsGradient[3*l+numNodes*3*gaussIndex]+jacobinvtrans(1,1)*basisFunctionsGradient[3*l+numNodes*3*gaussIndex+1];
+        B_matrix(0,2*l+1) = 0.;
+        B_matrix(1,2*l+1) = B_matrix(2,2*l);
+        B_matrix(2,2*l+1) = B_matrix(0,2*l);
+    }
+}
+
+// assembles the local "f_vector" into the full f vector, "elIndex" is the element index with respect to "nodeTags"
+// having "numNodes" nodes, "nodeTags" gathering all the nodeTags of the current element type in the current entity.
+// "nodeIndexMap" associates a global index to each nodetag.
+void assembleFlocal(const int &elIndex, const std::vector<std::size_t> & nodeTags, const int &numNodes, 
+                std::map<int, int> & nodeIndexMap, std::vector<double> & full_f_vector, const std::vector<double> & f_vector)
 {
     int first_node_index;
     int first_node;
     int my_row;
-
-    for (std::size_t el = 0; el < elementTags[i].size(); el++){
-        for (int j = 0; j < 2*numNodes; ++j){
-            f_vector[j] = 0.;
-        }
-    // looping over the Gauss points (formula of slide 17)
-        for (std::size_t j = 0; j < weights.size(); ++j){
-            // looping over the number of shape functions
-            for (int l = 0; l < numNodes; ++l){ 
-                f_vector[2*l] = f_vector[2*l] + basisFunctions[l+numNodes*j]*tx*determinants[j+weights.size()*el]*weights[j]; //pas oublier le dét !
-                f_vector[2*l+1] = f_vector[2*l+1] + basisFunctions[l+numNodes*j]*ty*determinants[j+weights.size()*el]*weights[j]; // le weight non plus !
-            }
-        }
-    /*------------- ASSEMBLY PROCESS ------------*/
-        for (int j = 0; j < 2*numNodes; ++j){
-            first_node_index = (int) j/2;
-            first_node = nodeTags[i][numNodes*el+first_node_index];
-            my_row = nodeIndexMap[first_node] + j % 2;
-            full_f_vector[my_row] += f_vector[j];
-        }
-    }    
+    for (int j = 0; j < 2*numNodes; ++j)
+    {
+        first_node_index = (int) j/2;
+        first_node = nodeTags[numNodes*elIndex+first_node_index];
+        my_row = nodeIndexMap[first_node] + j % 2; 
+        #pragma omp atomic update
+        full_f_vector[my_row] +=  f_vector[j];
+    }
 }
 
-/*-----------focus on neumann BC's (surface traction) into full_f_vector------------*/
-void includeNeumannBC(const std::vector<std::string> & keys, const std::string & integration_rule,
-                std::map<int, int> & nodeIndexMap,
-                std::map<std::string, std::pair<int, int>> & groups,
+// fills the "full_f_vector" with the surfacic contribution of the neumann boundary conditions based on the 
+// "nodeIndexMap" associating a global index to each node tag, the local integration of the surfacic forces is 
+// performed using Gauss integration based on "integration rule".
+// "BCkeys" gathers the keys associated to boundary conditions in the .geo file (using SetNumber(...)).
+// "groups" associates a dimension and a tag to each physical group.
+void includeNeumannBC(const std::vector<std::string> & BCkeys, const std::string & integration_rule,
+                std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups,
                 std::vector<double> & full_f_vector)
 {
     double tx = 0; // surface traction along x axis
@@ -283,7 +465,7 @@ void includeNeumannBC(const std::vector<std::string> & keys, const std::string &
     int numComponents, numOrientations;
     std::vector<double> basisFunctions;
 
-    for (auto &key : keys)
+    for (auto &key : BCkeys)
     {
         // get corresponding value
         std::vector<double> value;
@@ -306,9 +488,8 @@ void includeNeumannBC(const std::vector<std::string> & keys, const std::string &
                 if(tx || ty) // there is no need the consider Neumann BC if it is homogeneous
                     groupname = words[1];
             }
-            //here, if we are dealing with neumann BC's, we should have retrieved a non-empty group_name
+            //here, if we are dealing with neumann BC's, we should have retrieved a non-empty groupname
             if(groupname.compare("") != 0){
-                //loop over elements of group_name
                 dim = groups[groupname].first;
                 tag = groups[groupname].second;
                 if (tag == 0)
@@ -316,7 +497,7 @@ void includeNeumannBC(const std::vector<std::string> & keys, const std::string &
                     std::cerr << "Group '" << groupname << "' does not exist!\n";
                     return;
                 }
-                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
+                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags); // entities of particular groupname
 
                 // loop over entities
                 for (std::size_t k = 0; k < tags.size(); ++k)
@@ -334,26 +515,44 @@ void includeNeumannBC(const std::vector<std::string> & keys, const std::string &
                     
                         // get Gauss points coordinates and weights
                         gmsh::model::mesh::getIntegrationPoints(elementTypes[i], 
-                                                                integration_rule, //maybe use different integration method on boundary than in domain
+                                                                integration_rule,
                                                                 localCoords, weights);
 
                         // get determinants and Jacobians (only determinants will be useful)
                         std::vector<double> jacobians, determinants, coords;
                         gmsh::model::mesh::getJacobians(elementTypes[i], 
                                                         localCoords, jacobians, 
-                                                        determinants, coords,tags[k]); // ai dû rajouter mon tags[k] pr focus on this particular entity
+                                                        determinants, coords, tags[k]);
 
                         gmsh::model::mesh::getBasisFunctions(elementTypes[i], localCoords, 
                                                             "Lagrange", numComponents, 
                                                             basisFunctions, 
                                                             numOrientations);
 
-                        /*-----------computing the f vector components related to this Neumann BC---------*/
-                        //looping over the elements
-                        std::vector<double> f_vector(2*numNodes);
-                        computeNeumannBC(numNodes, i, elementTags, tx, ty, nodeIndexMap,
-                                           f_vector, weights, basisFunctions, 
-                                           determinants, nodeTags, full_f_vector);
+                        //looping over the element types
+                        #pragma omp parallel for
+                        for (std::size_t el = 0; el < elementTags[i].size(); el++){
+                            std::vector<double> f_vector(2*numNodes);
+                            for (int j = 0; j < 2*numNodes; ++j){
+                                f_vector[j] = 0.;
+                            }
+                            // looping over the Gauss points
+                            for (std::size_t j = 0; j < weights.size(); ++j){
+                                // looping over the number of shape functions
+                                for (int l = 0; l < numNodes; ++l){ 
+                                    f_vector[2*l] = f_vector[2*l] + basisFunctions[l+numNodes*j]*tx*determinants[j+weights.size()*el]*weights[j]; //pas oublier le dét !
+                                    f_vector[2*l+1] = f_vector[2*l+1] + basisFunctions[l+numNodes*j]*ty*determinants[j+weights.size()*el]*weights[j]; // le weight non plus !
+                                }
+                            }
+                            /*------------- ASSEMBLY PROCESS ------------*/
+                            for (int j = 0; j < 2*numNodes; ++j){
+                                int first_node_index = (int) j/2;
+                                int first_node = nodeTags[i][numNodes*el+first_node_index];
+                                int my_row = nodeIndexMap[first_node] + j % 2;
+                                #pragma omp atomic update
+                                full_f_vector[my_row] += f_vector[j];
+                            }
+                        }    
                     }
                 }
             }
@@ -361,367 +560,20 @@ void includeNeumannBC(const std::vector<std::string> & keys, const std::string &
     }
 }
 
-// looping over the boundary conditions imposed in the .geo file, the purpose of the whole loop is
-// to fill the two vectors defined just above
-void fillDOFindicesDirBC(const std::vector<std::string> & keys, 
-                             std::map<int, int> & nodeIndexMap,
-                             std::map<std::string, std::pair<int, int>> & groups, 
-                             std::vector<int> & new_DOFindices,
-                             std::vector<double> & dir_BC)
+// for the coupled solver, fills the "full_f_vector" with the electrostatic pressure contained in the 
+// "electrostaticPressure" map for different element tags, using Gauss integration "integration_rule", the "nodeIndexMap" 
+// associating a global nodal index to each nodeTag, "nodeCoordsMap" gathering the coordinates of each node and "groups"
+// containing the different physical groups of the domain.
+void applyElecPressure(const std::string & integration_rule, std::map<int,std::pair<double,double>> & nodeCoordsMap, 
+                    std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, 
+                    std::map<int, double> &electrostaticPressure, std::vector<double> & full_f_vector)
 {
-
-    for (std::size_t j = 0; j < new_DOFindices.size(); ++j){
-        new_DOFindices[j] = (int) j;
-    } 
-    for (std::size_t j = 0; j < dir_BC.size(); ++j){
-        dir_BC[j] = 0;
-    }
-
-    double ux; // imposed displacement along x axis
-    double uy; // imposed displacement along y axis
-
-    int dim;
-    int tag;
+    // electrostatic pressure must only be applied on the BEM_FEM_boundary
+    std::string groupname = "BEM_FEM_boundary";
+    int dim = groups[groupname].first;
+    int tag = groups[groupname].second;
     std::vector<int> tags;
-    std::vector<int> elementTypes;
-    std::vector<std::vector<std::size_t>> elementTags;
-    std::vector<std::vector<std::size_t>> nodeTags;
-    std::string elementName;
-    int elDim, order, numNodes, numPrimaryNodes;
-    std::vector<double> localNodeCoord;
-
-    int first_node_index;
-    int first_node;
-    int my_row;
-
-    for (auto &key : keys)
-    {
-        // get corresponding value
-        std::vector<double> value;
-        gmsh::onelab::getNumber(key, value);
-        // expected key structure is "type/group_name/field"
-        // => split the key string into components
-        std::stringstream ss(key);
-        std::vector<std::string> words;
-        std::string word;
-        while(std::getline(ss, word, '/')) // read string until '/'
-            words.push_back(word);
-        if(words.size()==3) 
-        {
-            if(words[2].compare("ux") == 0 || words[2].compare("uy") == 0){
-                ux = 0;
-                uy = 0;
-                if(words[2].compare("ux") == 0)
-                    ux = value[0];
-                if(words[2].compare("uy") == 0)
-                    uy = value[0];
-                std::string groupname = words[1];
-                
-                //loop over elements of group_name
-                dim = groups[groupname].first;
-                tag = groups[groupname].second;
-                if (tag == 0)
-                {
-                    std::cerr << "Group '" << groupname << "' does not exist!\n";
-                    return;
-                }
-                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-
-                for (std::size_t k = 0; k < tags.size(); ++k)
-                {
-                    gmsh::model::mesh::getElements(elementTypes, elementTags,
-                                                nodeTags, dim, tags[k]);
-                    
-                    for (std::size_t i = 0; i < elementTypes.size(); ++i)
-                    {
-                        gmsh::model::mesh::getElementProperties(elementTypes[i],
-                                                        elementName, elDim, order,
-                                                        numNodes, localNodeCoord, 
-                                                        numPrimaryNodes);
-                        //looping over the elements
-                        for (std::size_t el = 0; el < elementTags[i].size(); el++){
-                            for (int j = 0; j < 2*numNodes; ++j){
-                                first_node_index = (int) j/2;
-                                first_node = nodeTags[i][numNodes*el+first_node_index];
-                                my_row = nodeIndexMap[first_node] + j % 2; // j % 2 == 1 corresponds to y nodal displacement
-                                if(words[2].compare("uy") == 0 && j % 2){ // we are dealing with a uy type of node
-                                    dir_BC[my_row] = uy;
-                                    new_DOFindices[my_row] = -1;
-                                }
-                                if(words[2].compare("ux") == 0 && j % 2 == 0){ // ux type of node
-                                    dir_BC[my_row] = ux;
-                                    new_DOFindices[my_row] = -1;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-void computeReactionForces(std::map<std::string, std::pair<int, int>> & groups,
-                     std::map<int, int> & nodeIndexMap, std::vector<double> & final_nodal_forces,
-                     const std::vector<std::string> & keys)
-{
-    double Rx;
-    double Ry;
-
-    int dim;
-    int tag;
-    std::vector<int> tags;
-
-    std::vector<std::size_t> nodeTags;
-    std::vector<double> coord; //useless but mandatory
-    std::vector<double> parametricCoord; //useless but mandatory
-
-    for (auto &key : keys)
-    {
-        // get corresponding value
-        std::vector<double> value;
-        gmsh::onelab::getNumber(key, value);
-        // expected key structure is "type/group_name/field"
-        // => split the key string into components
-        std::stringstream ss(key);
-        std::vector<std::string> words;
-        std::string word;
-        while(std::getline(ss, word, '/')) // read string until '/'
-            words.push_back(word);
-        if(words.size()==3) 
-        {
-            if(words[2].compare("ux") == 0 || words[2].compare("uy") == 0){
-                Rx = 0;
-                Ry = 0;
-                std::string groupname = words[1];
-                std::cout << "-------------------- " << groupname << " ------------------- \n";
-                
-                //loop over elements of group_name
-                dim = groups[groupname].first;
-                tag = groups[groupname].second;
-                if (tag == 0)
-                {
-                    std::cerr << "Group '" << groupname << "' does not exist!\n";
-                    return;
-                }
-                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-
-                // loop over entities
-                for (std::size_t k = 0; k < tags.size(); ++k)
-                {
-                    // retrieving all the nodes in this particular entity
-                    gmsh::model::mesh::getNodes(nodeTags, coord, parametricCoord, dim, tags[k], true);
-                    
-                    
-                    for (std::size_t j = 0; j < nodeTags.size(); ++j){
-                        if(words[2].compare("ux") == 0){    // computing Rx
-                            int my_new_col = nodeIndexMap[nodeTags[j]]; // le noeud numéro nodeIndexMap[nodeTags[j]] correspond à la ligne/colonne dans K, f
-                            Rx += final_nodal_forces[my_new_col];
-                        }
-                        if(words[2].compare("uy") == 0){    // computing Ry
-                            int my_new_col = nodeIndexMap[nodeTags[j]] + 1;
-                            Ry += final_nodal_forces[my_new_col];
-                        }
-                    }
-                }
-                std::cout << "Rx: " << Rx << " [N/m], Ry: " << Ry << " [N/m] \n";
-            }
-        }
-    }
-}
-
-void plotUxUy(const std::vector<std::size_t> & FEM_nodeTags, const std::vector<double> & full_d_vector, const int nbViews, std::vector<std::string> & names)
-{
-    int viewtag1 = gmsh::view::add("ux");
-    int viewtag2 = gmsh::view::add("uy");
-    std::vector<std::vector<double>> data1(FEM_nodeTags.size());
-    std::vector<std::vector<double>> data2(FEM_nodeTags.size());
-    for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
-    {
-        data1[i].resize(1);
-        data1[i][0] = full_d_vector[2*i]; //ux // à modifier ici
-        data2[i].resize(1);
-        data2[i][0] = full_d_vector[2*i+1]; //uy
-    }
-
-    gmsh::view::addModelData(viewtag1, 0, names[0], "NodeData",
-                            FEM_nodeTags, data1); //independent of time here
-    gmsh::view::addModelData(viewtag2, 0, names[0], "NodeData",
-                            FEM_nodeTags, data2); //independent of time here
-
-    // save the results to disk
-    //gmsh::view::write(viewtag1, "ux.msh");
-    //gmsh::view::write(viewtag2, "uy.msh");
-
-    // set display options & view results
-    /*gmsh::option::setNumber("View[" + std::to_string(nbViews +2) + "].IntervalsType", 3);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews + 2) + "].AdaptVisualizationGrid", 1);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews + 2) + "].MaxRecursionLevel", 3);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews + 2) + "].TargetError", -0.0001);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews +3) + "].IntervalsType", 3);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews +3) + "].AdaptVisualizationGrid", 1);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews +3) + "].MaxRecursionLevel", 3);
-    gmsh::option::setNumber("View[" + std::to_string(nbViews +3) + "].TargetError", -0.0001);*/
-}
-
-void computeStressStrainElNodal(const std::vector<int> & elementTypes, const std::vector<std::vector<std::size_t>> &elementTags,
-                           const std::vector<std::vector<std::size_t>> &elnodeTags,
-                           std::vector<std::size_t> & elems2D, const Eigen::Matrix<double, 3, 3> &H_matrix, 
-                           const double nu, const double E, std::map<int, elementData> & FEM_kinematicsMap,
-                           std::vector<std::vector<double>> & data3, std::vector<std::vector<double>> & data4,
-                           std::vector<std::vector<double>> & data5, std::vector<std::vector<double>> & data6,
-                           std::vector<std::vector<double>> & data7, std::vector<std::vector<double>> & data8,
-                           std::vector<std::vector<double>> & data9, std::vector<std::vector<double>> & data10,
-                           int & k)
-{
-    // The strains and stresses are computed in local axes
-    // They are then converted back into global axes, using a simple rotation matrix
-
-    std::string name;
-    int dim, order, numNodes, numPrimaryNodes;
-    std::vector<double> paramCoord2D;
-    int numComponents, numOrientations;
-    std::vector<double> basisFunctionsGradient;
-
-    Eigen::Vector3d epsilon; // will contain local values of the strains (Voigt notation)
-    Eigen::Vector3d sigma; // will contain local values of the stresses (Voigt notation)
-
-    Eigen::Matrix<double, 2, 2> jacob2D;
-    Eigen::Matrix<double, 2, 2> jacobinv;
-    Eigen::Matrix<double, 2, 2> jacobinvtrans;
-
-    elementData* element;
-    double theta;
-    double dN_dx_local;
-    double dN_dy_local;
-
-    Eigen::Matrix<double, 2, 2> strain_tensor;
-    Eigen::Matrix<double, 2, 2> stress_tensor;
-    Eigen::Matrix<double, 2, 2> rotation_tensor;
-
-    for (std::size_t ityp = 0; ityp < elementTypes.size(); ++ityp)
-    {
-        // get info about this type of element
-        gmsh::model::mesh::getElementProperties(elementTypes[ityp], name, dim, order,
-                                                numNodes, paramCoord2D, numPrimaryNodes);
-        //paramCoord contains the coordinates of the nodes in 2D
-        // passage en 3D pour utiliser getJacobians
-        std::vector<double> paramCoord(3*paramCoord2D.size()/2);
-        for(std::size_t j = 0; j < paramCoord2D.size()/2; ++j){
-            paramCoord[3*j] = paramCoord2D[2*j];
-            paramCoord[3*j+1] = paramCoord2D[2*j+1];
-            paramCoord[3*j+2] = 0.;
-        }
-        
-        // select element/node tags for this type of element
-        auto &etags = elementTags[ityp];
-
-        // get determinants and Jacobians (only jacob useful here) AT NODES AND NOT AT GAUSS POINTS
-        std::vector<double> jacobians, determinants, coords;
-        gmsh::model::mesh::getJacobians(elementTypes[ityp], 
-                                        paramCoord, jacobians, 
-                                        determinants, coords);
-
-        // derivatives of the shape functions at the nodes of the reference element
-        // we are here working with derivatives in the reference space, same for all elements
-        gmsh::model::mesh::getBasisFunctions(elementTypes[ityp], paramCoord, 
-                                                "GradLagrange", numComponents, 
-                                                basisFunctionsGradient, 
-                                                numOrientations);
-
-        // loop over elements of type "ityp"
-        for (std::size_t i = 0; i < etags.size(); ++i)
-        {
-            element = & FEM_kinematicsMap[etags[i]];
-            elems2D[k] = etags[i];
-
-            theta = element->theta;
-            rotation_tensor(0,0) = cos(theta);
-            rotation_tensor(0,1) = sin(theta);
-            rotation_tensor(1,0) = -sin(theta);
-            rotation_tensor(1,1) = cos(theta);
-
-            data3[k].resize(numNodes);
-            data4[k].resize(numNodes);
-            data5[k].resize(numNodes);
-            data6[k].resize(numNodes);
-            data7[k].resize(numNodes);
-            data8[k].resize(numNodes);
-            data9[k].resize(numNodes);
-            data10[k].resize(numNodes);
-
-            for (int j = 0; j < numNodes; ++j){
-                // converting jacobian to Eigen format
-                Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
-                    jacob(&jacobians[9*j+9*numNodes*i], 3, 3);
-                // 3D to 2D (plane stress case)
-                jacob2D(0,0) = jacob(0,0);
-                jacob2D(1,0) = jacob(1,0);
-                jacob2D(0,1) = jacob(0,1);
-                jacob2D(1,1) = jacob(1,1);
-                        
-                // computing the inverse
-                jacobinv = jacob2D.inverse();
-
-                // computing the transpose of the inverse
-                jacobinvtrans = jacobinv.transpose();
-
-                // computing the B matrix (formula slide 19) 
-                Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
-
-                computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, 
-                                 jacobinvtrans, H_matrix, B_matrix);
-                
-                // WARNING, the B_matrix is expressed in terms of global axes -> convert back to local axes
-                for(int l = 0; l < numNodes; l++)
-                {
-                    dN_dx_local = cos(theta)*B_matrix(0,2*l) + sin(theta)*B_matrix(2,2*l);
-                    dN_dy_local = -sin(theta)*B_matrix(0,2*l) + cos(theta)*B_matrix(2,2*l);
-                    B_matrix(0,2*l) = dN_dx_local;
-                    B_matrix(2,2*l) = dN_dy_local;
-                    B_matrix(1,2*l+1) = dN_dy_local;
-                    B_matrix(2,2*l+1) = dN_dx_local;
-                }
-                // expressed in local axes (and in Voigt notation)
-                epsilon = B_matrix*element->pl; 
-                sigma = H_matrix*epsilon;
-
-                // converting to tensor notation (still in local axes)
-                strain_tensor(0,0) = epsilon(0);
-                strain_tensor(1,0) = epsilon(2)/2; // divide by 2 because engineering shear strain -> pure shear strain
-                strain_tensor(0,1) = epsilon(2)/2;
-                strain_tensor(1,1) = epsilon(1);
-
-                stress_tensor(0,0) = sigma(0);
-                stress_tensor(1,0) = sigma(2);
-                stress_tensor(0,1) = sigma(2);
-                stress_tensor(1,1) = sigma(1);
-
-                //converting back to global axes
-                strain_tensor = rotation_tensor.transpose()*strain_tensor*rotation_tensor;
-                stress_tensor = rotation_tensor.transpose()*stress_tensor*rotation_tensor;
-
-                data3[k][j] = strain_tensor(0,0);
-                data4[k][j] = strain_tensor(1,1);
-                data5[k][j] = strain_tensor(1,0);
-                data6[k][j] = -nu/E*(stress_tensor(0,0)+stress_tensor(1,1));// formula slide 11/20 elasticity
-                data7[k][j] = stress_tensor(0,0);
-                data8[k][j] = stress_tensor(1,1);
-                data9[k][j] = stress_tensor(1,0);
-                data10[k][j] = sqrt(stress_tensor(0,0)*stress_tensor(0,0) + stress_tensor(1,1)*stress_tensor(1,1) - stress_tensor(0,0)*stress_tensor(1,1) + 3*stress_tensor(1,0)*stress_tensor(1,0));
-            }
-            k++;
-        }
-    }
-}
-
-void applyElecPressure(const std::string & integration_rule, std::map<int,std::pair<double,double>> & nodeCoordsMap, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, std::map<int, double> &electrostaticPressure, std::vector<double> & full_f_vector)
-{
-    std::string groupname = "BEM_FEM_boundary";
-    int dim = groups[groupname].first;
-    int tag = groups[groupname].second;
-    std::vector<int> tags;
-    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
+    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
 
     int first_nodeTag;
     int second_nodeTag;
@@ -756,14 +608,14 @@ void applyElecPressure(const std::string & integration_rule, std::map<int,std::p
             // get Gauss points coordinates and weights
             std::vector<double> localCoords, weights;
             gmsh::model::mesh::getIntegrationPoints(elementTypes[j], 
-                                                    integration_rule, //maybe use different integration method on boundary than in domain
+                                                    integration_rule,
                                                     localCoords, weights);
 
             // get determinants and Jacobians (only determinants will be useful)
             std::vector<double> jacobians, determinants, coords;
             gmsh::model::mesh::getJacobians(elementTypes[j], 
                                             localCoords, jacobians, 
-                                            determinants, coords,tags[i]); // ai dû rajouter mon tags[k] pr focus on this particular entity
+                                            determinants, coords,tags[i]);
 
             int numComponents, numOrientations;
             std::vector<double> basisFunctions;
@@ -772,11 +624,12 @@ void applyElecPressure(const std::string & integration_rule, std::map<int,std::p
                                                 basisFunctions, 
                                                 numOrientations);
 
-            /*-----------computing the f vector components related to this Neumann BC---------*/
-            std::vector<double> f_vector(2*numNodes);
-
+            #pragma omp parallel for private(first_nodeTag, second_nodeTag, nx, ny, norm, p, tx, ty, first_node_index, first_node)
             for(std::size_t k=0; k < elementTags[j].size(); ++k)
             {
+                std::vector<double> f_vector(2*numNodes);
+                // computing the outward normal to the element, assuming the BEM domain is traveled "aire à gauche", hence
+                // the FEM domain "aire à droite"
                 first_nodeTag = elnodeTags[j][numNodes*k];
                 second_nodeTag = elnodeTags[j][numNodes*k+1];
                 nx = -(nodeCoordsMap[second_nodeTag].second - nodeCoordsMap[first_nodeTag].second);
@@ -785,18 +638,18 @@ void applyElecPressure(const std::string & integration_rule, std::map<int,std::p
                 nx = nx / norm; //normalisation
                 ny = ny / norm;
                 p = electrostaticPressure[elementTags[j][k]];
-                tx = p*nx;
+                tx = p*nx; // projecting the pressure onto the outward normal
                 ty = p*ny;
 
                 for (int n = 0; n < 2*numNodes; ++n){
                     f_vector[n] = 0.;
                 }
-                // looping over the Gauss points (formula of slide 17)
+                // looping over the Gauss points
                 for (std::size_t n = 0; n < weights.size(); ++n){
                     // looping over the number of shape functions
                     for (int l = 0; l < numNodes; ++l){ 
-                        f_vector[2*l] = f_vector[2*l] + basisFunctions[l+numNodes*n]*tx*determinants[n+weights.size()*k]*weights[n]; //pas oublier le dét !
-                        f_vector[2*l+1] = f_vector[2*l+1] + basisFunctions[l+numNodes*n]*ty*determinants[n+weights.size()*k]*weights[n]; // le weight non plus !
+                        f_vector[2*l] = f_vector[2*l] + basisFunctions[l+numNodes*n]*tx*determinants[n+weights.size()*k]*weights[n];
+                        f_vector[2*l+1] = f_vector[2*l+1] + basisFunctions[l+numNodes*n]*ty*determinants[n+weights.size()*k]*weights[n];
                     }
                 }
                 /*------------- ASSEMBLY PROCESS ------------*/
@@ -804,6 +657,7 @@ void applyElecPressure(const std::string & integration_rule, std::map<int,std::p
                     first_node_index = (int) n/2;
                     first_node = elnodeTags[j][numNodes*k+first_node_index];
                     my_row = nodeIndexMap[first_node] + n % 2;
+                    #pragma omp atomic update
                     full_f_vector[my_row] += f_vector[n];
                 }
             }
@@ -811,95 +665,122 @@ void applyElecPressure(const std::string & integration_rule, std::map<int,std::p
     }
 }
 
-int initKinematics(std::vector<std::size_t> & FEM_elementTags, std::map<int, elementData> & FEM_kinematicsMap, std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, int & dim, std::vector<int> & tags)
+// looping over the boundary conditions imposed in the .geo file and gathered in "BCkeys" related to the
+// physical groups "groups", the goal is to fill the two vectors "new_DOFindices" and "dir_BC":
+// "new_DOFindices" vector will contain the new indices of the K matrix after the "number_removed_lines" rows/columns
+// corresponding to dirichlet boundary conditions have been removed. A removed index will correspond to "new_DOFindices"= -1.
+// dir_BC[index] will contain the dirichlet boundary condition prescribed to the node whose global index is retrieved using
+// "nodeIndexMap".
+void fillDOFindicesDirBC(const std::vector<std::string> & BCkeys, std::map<int, int> & nodeIndexMap,
+                        std::map<std::string, std::pair<int, int>> & groups, 
+                        std::vector<int> & new_DOFindices, std::vector<double> & dir_BC, int & number_removed_lines)
 {
+
+    for (std::size_t j = 0; j < new_DOFindices.size(); ++j){
+        new_DOFindices[j] = (int) j;
+    } 
+    for (std::size_t j = 0; j < dir_BC.size(); ++j){
+        dir_BC[j] = 0;
+    }
+
+    double ux; // imposed displacement along x axis
+    double uy; // imposed displacement along y axis
+
+    int dim;
+    int tag;
+    std::vector<int> tags;
     std::vector<int> elementTypes;
     std::vector<std::vector<std::size_t>> elementTags;
-    std::vector<std::vector<std::size_t>> elnodeTags;
-
+    std::vector<std::vector<std::size_t>> nodeTags;
     std::string elementName;
     int elDim, order, numNodes, numPrimaryNodes;
     std::vector<double> localNodeCoord;
-    
-    int nbelems=0; // will store total number of elements in FEM domain
-    for(std::size_t i=0; i< tags.size(); ++i)
+
+    int first_node_index;
+    int first_node;
+    int my_row;
+
+    for (auto &key : BCkeys)
     {
-        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
-        for(std::size_t j=0; j< elementTags.size(); ++j)
+        // get corresponding value
+        std::vector<double> value;
+        gmsh::onelab::getNumber(key, value);
+        // expected key structure is "type/group_name/field"
+        // => split the key string into components
+        std::stringstream ss(key);
+        std::vector<std::string> words;
+        std::string word;
+        while(std::getline(ss, word, '/')) // read string until '/'
+            words.push_back(word);
+        if(words.size()==3) 
         {
-            nbelems+=elementTags[j].size();
-            // filling the FEM_elementTags vector
-            FEM_elementTags.insert(FEM_elementTags.end(), elementTags[j].begin(), elementTags[j].end());
+            if(words[2].compare("ux") == 0 || words[2].compare("uy") == 0){
+                ux = 0;
+                uy = 0;
+                if(words[2].compare("ux") == 0)
+                    ux = value[0];
+                if(words[2].compare("uy") == 0)
+                    uy = value[0];
+                std::string groupname = words[1];
+                
+                //loop over elements of group_name
+                dim = groups[groupname].first;
+                tag = groups[groupname].second;
+                if (tag == 0)
+                {
+                    std::cerr << "Group '" << groupname << "' does not exist!\n";
+                    return;
+                }
+                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
 
-            // getting element properties, in particular: number of nodes
-            gmsh::model::mesh::getElementProperties(elementTypes[j],
+                for (std::size_t k = 0; k < tags.size(); ++k)
+                {
+                    gmsh::model::mesh::getElements(elementTypes, elementTags,
+                                                nodeTags, dim, tags[k]);
+                    
+                    for (std::size_t i = 0; i < elementTypes.size(); ++i)
+                    {
+                        gmsh::model::mesh::getElementProperties(elementTypes[i],
                                                         elementName, elDim, order,
                                                         numNodes, localNodeCoord, 
                                                         numPrimaryNodes);
-            for(std::size_t k = 0; k < elementTags[j].size(); k++)
-            {
-                elementData element;
-                std::vector<size_t> tmp_nodes(numNodes);
-                std::vector<double> tmp_x(numNodes);
-                std::vector<double> tmp_y(numNodes);
-                std::vector<double> tmp_u(numNodes);
-                std::vector<double> tmp_v(numNodes);
-                std::vector<double> tmp_ui(numNodes);
-                std::vector<double> tmp_vi(numNodes);
-                double tmp_xc = 0;
-                double tmp_yc = 0;
-                for(int l = 0; l < numNodes; l++)
-                {
-                    tmp_nodes[l] = elnodeTags[j][numNodes*k + l];
-                    tmp_x[l] = FEM_nodeCoordsMap[tmp_nodes[l]].first;
-                    tmp_y[l] = FEM_nodeCoordsMap[tmp_nodes[l]].second;
-                    tmp_u[l] = 0; // initializing the displacement at zero
-                    tmp_v[l] = 0;
-                    tmp_ui[l] = 0;
-                    tmp_vi[l] = 0;
-                    tmp_xc += tmp_x[l];
-                    tmp_yc += tmp_y[l];
-                }
-                tmp_xc = tmp_xc / numNodes;
-                tmp_yc = tmp_yc / numNodes;
-
-                std::vector<double> tmp_xi(numNodes);
-                std::vector<double> tmp_yi(numNodes);
-                for(int l = 0; l < numNodes; l++)
-                {
-                    tmp_xi[l] = tmp_x[l] - tmp_xc;
-                    tmp_yi[l] = tmp_y[l] - tmp_yc;
+                        //looping over the elements
+                        for (std::size_t el = 0; el < elementTags[i].size(); el++){
+                            for (int j = 0; j < 2*numNodes; ++j){
+                                first_node_index = (int) j/2;
+                                first_node = nodeTags[i][numNodes*el+first_node_index];
+                                my_row = nodeIndexMap[first_node] + j % 2; // j % 2 == 1 corresponds to y nodal displacement
+                                if(words[2].compare("uy") == 0 && j % 2){ // we are dealing with a uy type of node
+                                    dir_BC[my_row] = uy;
+                                    new_DOFindices[my_row] = -1;
+                                }
+                                if(words[2].compare("ux") == 0 && j % 2 == 0){ // ux type of node
+                                    dir_BC[my_row] = ux;
+                                    new_DOFindices[my_row] = -1;
+                                }
+                            }
+                        }
+                    }
                 }
-                element.nodes = tmp_nodes;
-                element.x = tmp_x;
-                element.y = tmp_y;
-                element.xc = tmp_xc;
-                element.yc = tmp_yc;
-                element.xi = tmp_xi;
-                element.yi = tmp_yi;
-                element.u = tmp_u;
-                element.v = tmp_v;
-                element.uc = 0;
-                element.vc = 0;
-                element.theta = 0;
-                element.ui = tmp_ui;
-                element.vi = tmp_vi;
-                element.pl = Eigen::Matrix<double, Eigen::Dynamic, 1>::Zero(2*numNodes,1);
-                element.A = Eigen::Matrix<double, Eigen::Dynamic, 1>(2*numNodes,1);
-                element.G = Eigen::Matrix<double, 1, Eigen::Dynamic>(1,2*numNodes);
-                element.E = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>::Zero(2*numNodes, 2*numNodes);
-
-                FEM_kinematicsMap[elementTags[j][k]] = element;
-                updateKinMatrices(& FEM_kinematicsMap[elementTags[j][k]], false);
             }
         }
     }
-    return nbelems;
+    for (std::size_t j = 0; j < new_DOFindices.size(); ++j){
+        if(new_DOFindices[j] < 0){ // line has to be removed
+            number_removed_lines++;
+        }
+        else{
+            new_DOFindices[j] -= number_removed_lines;
+        }
+    }
 }
 
-void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, std::vector<std::size_t> & FEM_elementTags)
+// updating the kinematics of the "FEM_elementTags" contained in the "FEM_kinematicsMap",
+// based on the "full_d_vector" gathering the nodal displacements associated to the global
+// node indices contained in "nodeIndexMap".
+void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, const std::vector<double> & full_d_vector, 
+                std::map<int, int> & nodeIndexMap, const std::vector<std::size_t> & FEM_elementTags)
 {
-    elementData* element;
     size_t numNodes;
     size_t tmp_nodeTag;
     int node_index;
@@ -909,9 +790,10 @@ void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vecto
     double angle2;
     double norm1;
     double norm2;
+    #pragma omp parallel for private(numNodes, tmp_nodeTag, node_index, numerator, denominator, angle1, angle2, norm1, norm2)
     for(std::size_t i=0; i< FEM_elementTags.size(); ++i)
     {
-        element = & FEM_kinematicsMap[FEM_elementTags[i]];
+        elementData* element = & FEM_kinematicsMap[FEM_elementTags[i]];
         numNodes = element->nodes.size();
         element->uc = 0;
         element->vc = 0;
@@ -929,7 +811,7 @@ void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vecto
         element->vc = element->vc / numNodes;
 
         numerator = 0;
-        denominator =0;
+        denominator = 0;
         for(size_t l = 0; l < numNodes; l++)
         {
             numerator += element->xi[l]*(element->yi[l]+element->v[l]-element->vc);
@@ -947,7 +829,7 @@ void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vecto
         {
             angle2 = angle1 - PI;
         }
-        // filling ui and vi while finding the angle minimizing equation (4) in the paper (what i call the norm)
+        // filling ui and vi while finding the angle minimizing equation (70) in the report (VERIFIER EQUATION)
         std::vector<double> tmp_ui1(numNodes);
         std::vector<double> tmp_ui2(numNodes);
         std::vector<double> tmp_vi1(numNodes);
@@ -984,264 +866,670 @@ void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vecto
     }
 }
 
-void updateKinMatrices(elementData* element, bool computeFl)
+// retrieving the global nodal forces based on local nodal forces of the 
+// "FEM_elementTags" contained in the "FEM_kinematicsMap", 
+// each node Tag corresponds to a global index given by "nodeIndexMap".
+void retrieveTotalNodalForces(std::vector<double> & final_nodal_forces, std::map<int, elementData> & FEM_kinematicsMap, 
+                        std::map<int, int> & nodeIndexMap, const std::vector<std::size_t> & FEM_elementTags)
 {
-    size_t numNodes = element->nodes.size();
-    // update A matrix
-    for(size_t i = 0; i < numNodes; i++)
+    for(size_t i = 0; i < final_nodal_forces.size(); i++)
     {
-        element->A(2*i, 0) = -(element->vi[i]+element->yi[i]);
-        element->A(2*i + 1, 0) = element->ui[i]+element->xi[i];
+        final_nodal_forces[i] = 0;
     }
 
-    // update G matrix
-    double denominator = 0;
-    for(size_t i = 0; i < numNodes; i++)
+    #pragma omp parallel for
+    for(size_t i = 0; i < FEM_elementTags.size(); i++)
     {
-        element->G(0, 2*i) = -element->yi[i];
-        element->G(0, 2*i + 1) = element->xi[i];
-        denominator += element->xi[i]*(element->ui[i]+element->xi[i]) + element->yi[i]*(element->vi[i]+element->yi[i]);
+        elementData* element = & FEM_kinematicsMap[FEM_elementTags[i]];
+        int numNodes = (int) element->nodes.size();
+        Eigen::Matrix<double, Eigen::Dynamic, 1> fg = element->C.transpose()*element->fl;
+        for(int j = 0; j < numNodes; j++)
+        {
+            int nodeTag = element->nodes[j];
+            #pragma omp atomic update
+            final_nodal_forces[nodeIndexMap[nodeTag]] += fg(2*j);
+            #pragma omp atomic update
+            final_nodal_forces[nodeIndexMap[nodeTag] + 1] += fg(2*j + 1);
+        }
     }
-    element->G *= 1 / denominator;
+}
 
-    // update P matrix 
-    element->P = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>::Identity(2*numNodes,2*numNodes) - element->A*element->G;
+// assembles the "global_f_vector" based on the local nodal forces vector of the 
+// "FEM_elementTags" contained in the "FEM_kinematicsMap", 
+// without taking into account the DOFs fixed by a dirichlet boundary condition,
+// the nodes are renumbered using "new_DOFindices".
+// each node Tag corresponds to a global index given by "nodeIndexMap".
+void assembleGlobalF(std::vector<double> & global_f_vector, std::map<int, elementData> & FEM_kinematicsMap, 
+                std::map<int, int> & nodeIndexMap, const std::vector<int> & new_DOFindices, 
+                const std::vector<std::size_t> & FEM_elementTags)
+{
+    #pragma omp parallel for
+    for(size_t i = 0; i < FEM_elementTags.size(); i++)
+    {
+        elementData* element = & FEM_kinematicsMap[FEM_elementTags[i]];
+        int numNodes = (int) element->nodes.size();
+        Eigen::Matrix<double, Eigen::Dynamic, 1> fg = element->C.transpose()*element->fl;
+        for(int j = 0; j < numNodes; j++)
+        {
+            int nodeTag = element->nodes[j];
+            int index1 = new_DOFindices[nodeIndexMap[nodeTag]]; // current index related to x DOF of the node (= -1 if dirichlet BC)
+            int index2 = new_DOFindices[nodeIndexMap[nodeTag] + 1]; // current index related to y DOF of the node (= -1 if dirichlet BC)
+            if(index1 >= 0) // need to assemble in global f vector
+            {
+                #pragma omp atomic update
+                global_f_vector[index1] += fg(2*j);
+            }
+            if(index2 >= 0)
+            {
+                #pragma omp atomic update
+                global_f_vector[index2] += fg(2*j + 1);
+            }
+        }
+    }
+}
 
-    // update E matrix
-    double tmp_cos = cos(element->theta);
-    double tmp_sin = sin(element->theta);
-    for(size_t i = 0; i < numNodes; i++)
+// assembling the global tangent stiffness matrix based on the local elemental stiffness matrices contained
+// in the "FEM_kinematicsMap" associated to each "FEM_elementTags".
+// "new_DOFindices" maps the global initial node index (from "nodeIndexMap") to the index
+// obtained without considering the fixed DOFs.
+void assembleGlobalKg(Eigen::SparseMatrix<double> & global_tangent_matrix, std::map<int, elementData> & FEM_kinematicsMap, 
+                    std::map<int, int> & nodeIndexMap, const std::vector<int> & new_DOFindices, 
+                    const std::vector<std::size_t> & FEM_elementTags)
+{
+    // to allow efficient parallelization, one triplet list is created for every thread, then the different lists are assembled
+    // to further increase efficiency, space is reserved for each list
+    int estimated_number_of_entries = (int) new_DOFindices.size()/2 *8*8; // accurate in the case of Q4 elements, otherwise it provides a good estimation
+    std::vector<Eigen::Triplet <double>> Kg_tripletList;
+    Kg_tripletList.reserve(estimated_number_of_entries);
+    
+    int max_threads = omp_get_max_threads();
+    int estimated_number_of_entries_per_thread = (int) estimated_number_of_entries / max_threads;
+    std::vector<std::vector<Eigen::Triplet <double>>> thread_Kg_list(max_threads);
+    for(int i = 0; i < max_threads; i++)
     {
-        element->E(2*i, 2*i) = tmp_cos;
-        element->E(2*i, 2*i + 1) = -tmp_sin;
-        element->E(2*i + 1, 2*i) = tmp_sin;
-        element->E(2*i + 1, 2*i + 1) = tmp_cos;
+        thread_Kg_list[i].reserve(estimated_number_of_entries_per_thread);
     }
 
-    //update B matrix
-    element->B = element->P*element->E.transpose();
+    std::vector<Eigen::Triplet <double>>* my_Kg_list;
 
-    //update fl vector, only if Kl has been initialized
-    if(computeFl)
+    #pragma omp parallel for private(my_Kg_list)
+    for(size_t i = 0; i < FEM_elementTags.size(); i++)
     {
-        element->fl = element->Kl*element->pl;
+        elementData* element = & FEM_kinematicsMap[FEM_elementTags[i]];
+        int numNodes = (int) element->nodes.size();
+        Eigen::Matrix<double, Eigen::Dynamic, 1> tmp_F = element->P.transpose()*element->fl;
+
+        Eigen::Matrix<double, 1, Eigen::Dynamic> F(1,2*numNodes);
+        for(int j = 0; j < numNodes; j++)
+        {
+            F(0,2*j) = tmp_F(2*j+1, 0);
+            F(0,2*j+1) = -tmp_F(2*j, 0);
+        }
+        
+        // see report for the formula
+        Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Kh = element->E*(-F.transpose()*element->G - element->G.transpose()*F*element->P)*element->E.transpose();
+
+        Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Kg = element->C.transpose()*element->Kl*element->C + Kh;
+
+        int threadNum = omp_get_thread_num();
+        my_Kg_list = & thread_Kg_list[threadNum];
+
+        // assemble Kg into tripletlist
+        for (int j = 0; j < 2*numNodes; ++j)
+        {
+            int first_node_index = (int) j/2;
+            int first_node = element->nodes[first_node_index];
+            int my_row = new_DOFindices[nodeIndexMap[first_node] + j % 2]; 
+            if(my_row >= 0) // else, the DOF corresponds to a Dirichlet BC
+            {
+                for(int l = 0; l <= j; ++l)
+                {   // to exploit symmetry
+                    int second_node_index = (int) l/2;
+                    int second_node = element->nodes[second_node_index];
+                    int my_col = new_DOFindices[nodeIndexMap[second_node] + l % 2];
+
+                    if(my_col >= 0) // else, the DOF corresponds to a Dirichlet BC
+                    {
+                        (*my_Kg_list).push_back(Eigen::Triplet<double>(my_row,my_col,Kg(j,l)));
+                        if(j != l)
+                        {
+                            (*my_Kg_list).push_back(Eigen::Triplet<double>(my_col,my_row,Kg(j,l)));
+                        }
+                    }
+                }
+            }
+        }
     }
+    // gathering the different lists in one single list
+    Kg_tripletList = thread_Kg_list[0];
+    if(max_threads > 1)
+    {
+        for (int i = 1; i < max_threads; i++)
+        {
+            Kg_tripletList.insert(Kg_tripletList.end(), thread_Kg_list[i].begin(), thread_Kg_list[i].end());
+        }
+    }
+    global_tangent_matrix.setFromTriplets(Kg_tripletList.begin(), Kg_tripletList.end());
 }
 
-void assembleGlobalF(std::vector<double> & global_f_vector, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> &  nodeIndexMap, std::vector<int> & new_DOFindices, std::vector<std::size_t> & FEM_elementTags)
+// updating the "full_d_vector" based on the "global_p_vector", using the global and reduced index mapping:
+// "new_DOFindices".
+void updateNodalDispVector(std::vector<double> & full_d_vector, const std::vector<double> & global_p_vector, 
+                        const std::vector<int> & new_DOFindices)
 {
-    elementData* element;
-    Eigen::Matrix<double, Eigen::Dynamic, 1> fg;
-    int numNodes;
-    int index1;
-    int index2;
+    for(size_t i = 0; i < full_d_vector.size(); i++)
+    {
+        if(new_DOFindices[i] >= 0)
+        {
+            full_d_vector[i] = global_p_vector[new_DOFindices[i]];
+        }
+    }
+}
+
+// retrieving the nodal displacements on the BEM_FEM_boundary in order to communicate them to the
+// BEM solver in the two-way coupled solver. Using the "groups" to find the physical group associated
+// to the boundary, all nodes of the boundary are associated through the "boundaryDisplacementMap" their
+// nodal displacement (u,v) retrieved from "full_d_vector" using the indexation of "nodeIndexMap".
+void retrieveBoundaryDisplacements(std::map<int,std::pair<double,double>> & boundaryDisplacementMap, 
+                            const std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, 
+                            std::map<std::string, std::pair<int, int>> & groups)
+{
+    std::string groupname = "BEM_FEM_boundary";
+    int dim = groups[groupname].first;
+    int tag = groups[groupname].second;
+    std::vector<int> tags;
+    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> elnodeTags;
+
     int nodeTag;
-    for(size_t i = 0; i < FEM_elementTags.size(); i++)
+    double u;
+    double v;
+
+    std::string elementName;
+    int elDim, order, numNodes, numPrimaryNodes;
+    std::vector<double> localNodeCoord;
+
+    for(std::size_t i=0; i< tags.size(); ++i)
     {
-        element = & FEM_kinematicsMap[FEM_elementTags[i]];
-        numNodes = (int) element->nodes.size();
-        fg = element->B.transpose()*element->fl;
-        for(int j = 0; j < numNodes; j++)
+        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
+        for(std::size_t j=0; j< elementTypes.size(); ++j)
         {
-            nodeTag = element->nodes[j];
-            index1 = new_DOFindices[nodeIndexMap[nodeTag]]; // current index related to x DOF of the node (= -1 if dirichlet BC)
-            index2 = new_DOFindices[nodeIndexMap[nodeTag] + 1]; // current index related to y DOF of the node (= -1 if dirichlet BC)
-            if(index1 >= 0) // need to assemble in global f vector
+
+            // getting element properties
+            gmsh::model::mesh::getElementProperties(elementTypes[j],
+                                                        elementName, elDim, order,
+                                                        numNodes, localNodeCoord, 
+                                                        numPrimaryNodes);
+
+            for(std::size_t k=0; k < elementTags[j].size(); ++k)
             {
-                global_f_vector[index1] += fg(2*j);
+                for(int l = 0; l < numNodes; l++)
+                {
+                    nodeTag = elnodeTags[j][numNodes*k + l];
+                    u = full_d_vector[nodeIndexMap[nodeTag]];
+                    v = full_d_vector[nodeIndexMap[nodeTag] + 1];
+                    boundaryDisplacementMap[nodeTag] = std::pair<double, double>(u, v);
+                }
             }
-            if(index2 >= 0)
+        }
+    }
+}
+
+// computing the reaction forces on all the physical groups "groups" for which a dirichlet boundary
+// condition has been prescribed (using the "BCkeys" to retrieve the groups from the .geo file),
+// based on the "final_nodal_forces" and the "nodeIndexMap" to retrieve the global index associated
+// to one given node tag.
+void computeReactionForces(std::map<std::string, std::pair<int, int>> & groups,
+                     std::map<int, int> & nodeIndexMap, const std::vector<double> & final_nodal_forces,
+                     const std::vector<std::string> & BCkeys)
+{
+    double Rx;
+    double Ry;
+
+    int dim;
+    int tag;
+    std::vector<int> tags;
+
+    std::vector<std::size_t> nodeTags;
+    std::vector<double> coord; //useless but mandatory
+    std::vector<double> parametricCoord; //useless but mandatory
+
+    for (auto &key : BCkeys)
+    {
+        // get corresponding value
+        std::vector<double> value;
+        gmsh::onelab::getNumber(key, value);
+        // expected key structure is "type/group_name/field"
+        // => split the key string into components
+        std::stringstream ss(key);
+        std::vector<std::string> words;
+        std::string word;
+        while(std::getline(ss, word, '/')) // read string until '/'
+            words.push_back(word);
+        if(words.size()==3) 
+        {
+            if(words[2].compare("ux") == 0 || words[2].compare("uy") == 0){
+                Rx = 0;
+                Ry = 0;
+                std::string groupname = words[1];
+                std::cout << "-------------------- " << groupname << " ------------------- \n";
+                
+                //loop over elements of group_name
+                dim = groups[groupname].first;
+                tag = groups[groupname].second;
+                if (tag == 0)
+                {
+                    std::cerr << "Group '" << groupname << "' does not exist!\n";
+                    return;
+                }
+                gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
+
+                // loop over entities
+                for (std::size_t k = 0; k < tags.size(); ++k)
+                {
+                    // retrieving all the nodes in this particular entity
+                    gmsh::model::mesh::getNodes(nodeTags, coord, parametricCoord, dim, tags[k], true);
+                    
+                    
+                    for (std::size_t j = 0; j < nodeTags.size(); ++j){
+                        if(words[2].compare("ux") == 0){    // computing Rx
+                            int my_new_col = nodeIndexMap[nodeTags[j]]; //nodeIndexMap[nodeTags[j]] corresponds to line/column index in K, f
+                            Rx += final_nodal_forces[my_new_col];
+                        }
+                        if(words[2].compare("uy") == 0){    // computing Ry
+                            int my_new_col = nodeIndexMap[nodeTags[j]] + 1;
+                            Ry += final_nodal_forces[my_new_col];
+                        }
+                    }
+                }
+                std::cout << "Rx: " << Rx << " [N/m], Ry: " << Ry << " [N/m] \n";
+            }
+        }
+    }
+}
+
+// plotting the nodal displacement values associated to "FEM_nodeTags" in the "names[0]" model,
+// based on the "full_d_vector".
+void plotUxUy(const std::vector<std::size_t> & FEM_nodeTags, const std::vector<double> & full_d_vector, 
+            const std::vector<std::string> & names)
+{
+    int viewtagUx = gmsh::view::add("ux");
+    int viewtagUy = gmsh::view::add("uy");
+    std::vector<std::vector<double>> dataUx(FEM_nodeTags.size());
+    std::vector<std::vector<double>> dataUy(FEM_nodeTags.size());
+    for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
+    {
+        dataUx[i].resize(1);
+        dataUx[i][0] = full_d_vector[2*i]; //ux // à modifier ici
+        dataUy[i].resize(1);
+        dataUy[i][0] = full_d_vector[2*i+1]; //uy
+    }
+
+    gmsh::view::addModelData(viewtagUx, 0, names[0], "NodeData",
+                            FEM_nodeTags, dataUx); //independent of time here
+    gmsh::view::addModelData(viewtagUy, 0, names[0], "NodeData",
+                            FEM_nodeTags, dataUy); //independent of time here
+}
+
+// computing the elemental-nodal strains and stresses in the FEM domain (dimension "dim" and entity tags "tags"),
+// based on Hooke's matrix in plane stress "H_matrix", Young's modulus "E", Poisson's ratio "nu", looping over the
+// "nbelems" elements contained in "FEM_kinematicsMap".
+// returning the "max_VM_stress" and the corresponding nodetag "max_VM_nodeTag".
+void computeStressStrainElNodal(const int & dim, const std::vector<int> & tags, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           const double nu, const double E, std::map<int, elementData> & FEM_kinematicsMap,
+                           const int & nbelems, double & max_VM_stress, int & max_VM_nodeTag)
+{
+    std::vector<std::string> names;
+    gmsh::model::list(names);
+
+    int viewTagEpsX = gmsh::view::add("nodal_eps_x");
+    int viewTagEpsY = gmsh::view::add("nodal_eps_y");
+    int viewTagEpsXY = gmsh::view::add("nodal_2eps_xy");
+    int viewTagEpsZ = gmsh::view::add("nodal_eps_z");
+    int viewTagSigX = gmsh::view::add("nodal_sig_x");
+    int viewTagSigY = gmsh::view::add("nodal_sig_y");
+    int viewTagSigXY = gmsh::view::add("nodal_sig_xy");
+    int viewTagSigVM = gmsh::view::add("nodal_sig_VM");
+
+    std::vector<std::vector<std::vector<double>>> dataEps(4);
+    dataEps[0].resize(nbelems); // eps X
+    dataEps[1].resize(nbelems); // eps Y
+    dataEps[2].resize(nbelems); // eps XY
+    dataEps[3].resize(nbelems); // eps Z
+
+    std::vector<std::vector<std::vector<double>>> dataSig(4);
+    dataSig[0].resize(nbelems); // Sig X
+    dataSig[1].resize(nbelems); // Sig Y
+    dataSig[2].resize(nbelems); // Sig XY
+    dataSig[3].resize(nbelems); // Sig VM
+    std::vector<std::size_t> elems2D(nbelems);
+
+    int data_index = 0;
+
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> elnodeTags;
+    for(std::size_t entityTag = 0; entityTag < tags.size(); ++entityTag)
+    {
+        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[entityTag]);
+
+        std::string name;
+        int dim, order, numNodes, numPrimaryNodes;
+        std::vector<double> paramCoord2D;
+        int numComponents, numOrientations;
+        std::vector<double> basisFunctionsGradient;
+
+        Eigen::Vector3d epsilon; // will contain local values of the strains (Voigt notation)
+        Eigen::Vector3d sigma; // will contain local values of the stresses (Voigt notation)
+
+        Eigen::Matrix<double, 2, 2> jacob2D;
+        Eigen::Matrix<double, 2, 2> jacobinv;
+        Eigen::Matrix<double, 2, 2> jacobinvtrans;
+
+        elementData* element;
+        double theta;
+
+        Eigen::Matrix<double, 2, 2> strain_tensor;
+        Eigen::Matrix<double, 2, 2> stress_tensor;
+        Eigen::Matrix<double, 2, 2> rotation_tensor;
+
+        for (std::size_t ityp = 0; ityp < elementTypes.size(); ++ityp)
+        {
+            // get info about this type of element
+            gmsh::model::mesh::getElementProperties(elementTypes[ityp], name, dim, order,
+                                                    numNodes, paramCoord2D, numPrimaryNodes);
+            //paramCoord contains the coordinates of the nodes in 2D
+            // passage en 3D pour utiliser getJacobians
+            std::vector<double> paramCoord(3*paramCoord2D.size()/2);
+            for(std::size_t j = 0; j < paramCoord2D.size()/2; ++j){
+                paramCoord[3*j] = paramCoord2D[2*j];
+                paramCoord[3*j+1] = paramCoord2D[2*j+1];
+                paramCoord[3*j+2] = 0.;
+            }
+            
+            // select element/node tags for this type of element
+            auto &etags = elementTags[ityp];
+
+            // get determinants and Jacobians (only jacob useful here) AT NODES AND NOT AT GAUSS POINTS
+            std::vector<double> jacobians, determinants, coords;
+            gmsh::model::mesh::getJacobians(elementTypes[ityp], 
+                                            paramCoord, jacobians, 
+                                            determinants, coords, tags[entityTag]);
+
+            // derivatives of the shape functions at the nodes of the reference element
+            // we are here working with derivatives in the reference space, same for all elements
+            gmsh::model::mesh::getBasisFunctions(elementTypes[ityp], paramCoord, 
+                                                    "GradLagrange", numComponents, 
+                                                    basisFunctionsGradient, 
+                                                    numOrientations);
+
+            // loop over elements of type "ityp"
+            for (std::size_t i = 0; i < etags.size(); ++i)
             {
-                global_f_vector[index2] += fg(2*j + 1);
+                element = & FEM_kinematicsMap[etags[i]];
+                elems2D[data_index] = etags[i];
+
+                theta = element->theta;
+                rotation_tensor(0,0) = cos(theta);
+                rotation_tensor(0,1) = sin(theta);
+                rotation_tensor(1,0) = -sin(theta);
+                rotation_tensor(1,1) = cos(theta);
+
+                dataEps[0][data_index].resize(numNodes);
+                dataEps[1][data_index].resize(numNodes);
+                dataEps[2][data_index].resize(numNodes);
+                dataEps[3][data_index].resize(numNodes);
+                dataSig[0][data_index].resize(numNodes);
+                dataSig[1][data_index].resize(numNodes);
+                dataSig[2][data_index].resize(numNodes);
+                dataSig[3][data_index].resize(numNodes);
+
+                for (int j = 0; j < numNodes; ++j){
+                    // converting jacobian to Eigen format
+                    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
+                        jacob(&jacobians[9*j+9*numNodes*i], 3, 3);
+                    // 3D to 2D (plane stress case)
+                    jacob2D(0,0) = jacob(0,0);
+                    jacob2D(1,0) = jacob(1,0);
+                    jacob2D(0,1) = jacob(0,1);
+                    jacob2D(1,1) = jacob(1,1);
+                            
+                    // computing the inverse
+                    jacobinv = jacob2D.inverse();
+
+                    // computing the transpose of the inverse
+                    jacobinvtrans = jacobinv.transpose();
+
+                    // computing the B matrix (formula slide 19) 
+                    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
+
+                    computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
+                    
+                    // expressed in local axes (and in Voigt notation)
+                    epsilon = B_matrix*element->pl; 
+                    sigma = H_matrix*epsilon;
+
+                    // converting to tensor notation (still in local axes)
+                    strain_tensor(0,0) = epsilon(0);
+                    strain_tensor(1,0) = epsilon(2)/2; // divide by 2 because engineering shear strain -> pure shear strain
+                    strain_tensor(0,1) = epsilon(2)/2;
+                    strain_tensor(1,1) = epsilon(1);
+
+                    stress_tensor(0,0) = sigma(0);
+                    stress_tensor(1,0) = sigma(2);
+                    stress_tensor(0,1) = sigma(2);
+                    stress_tensor(1,1) = sigma(1);
+
+                    strain_tensor = rotation_tensor.transpose()*strain_tensor*rotation_tensor;
+                    stress_tensor = rotation_tensor.transpose()*stress_tensor*rotation_tensor;
+
+                    dataEps[0][data_index][j] = strain_tensor(0,0);
+                    dataEps[1][data_index][j] = strain_tensor(1,1);
+                    dataEps[2][data_index][j] = strain_tensor(1,0);
+                    dataEps[3][data_index][j] = -nu/E*(stress_tensor(0,0)+stress_tensor(1,1));// from plane stress hypothesis
+                    dataSig[0][data_index][j] = stress_tensor(0,0);
+                    dataSig[1][data_index][j] = stress_tensor(1,1);
+                    dataSig[2][data_index][j] = stress_tensor(1,0);
+                    // VM stress in plane stress
+                    dataSig[3][data_index][j] = sqrt(stress_tensor(0,0)*stress_tensor(0,0) + stress_tensor(1,1)*stress_tensor(1,1) - stress_tensor(0,0)*stress_tensor(1,1) + 3*stress_tensor(1,0)*stress_tensor(1,0));
+                    
+                    //retrieving maximal nodal von mises stress
+                    if(dataSig[3][data_index][j] > max_VM_stress)
+                    {
+                        max_VM_stress = dataSig[3][data_index][j];
+                        max_VM_nodeTag = (int) elnodeTags[ityp][numNodes*i+j];
+                    }
+                }
+                data_index++;
             }
         }
     }
+
+    gmsh::view::addModelData(viewTagEpsX, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[0], 1); 
+    gmsh::view::addModelData(viewTagEpsY, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[1], 1); 
+    gmsh::view::addModelData(viewTagEpsXY, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[2], 1); 
+    gmsh::view::addModelData(viewTagEpsZ, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[3], 1); 
+    gmsh::view::addModelData(viewTagSigX, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[0], 1); 
+    gmsh::view::addModelData(viewTagSigY, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[1], 1); 
+    gmsh::view::addModelData(viewTagSigXY, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[2], 1); 
+    gmsh::view::addModelData(viewTagSigVM, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[3], 1); 
 }
 
-double computeResidualNorm(std::vector<double> & global_f_vector, std::vector<double> & f_app_vector, Eigen::Matrix<double, Eigen::Dynamic, 1> & residual)
+// computing the work done by external forces, as the nodal forces are energy consistent, it
+// is sufficient to compute the "externalWork" as the dot product of the nodal displacements
+// "full_d_vector" and the nodal forces "final_nodal_forces".
+void computeWorkDoneByExternalForces(double &externalWork, const std::vector<double> & full_d_vector, 
+                                const std::vector<double> & final_nodal_forces)
 {
-    // norm computed as a geometrical norm (one could also use an other norm)
-    double res = 0;
-    for(size_t i = 0; i < global_f_vector.size(); i++)
+    for(size_t i = 0; i < full_d_vector.size(); i++)
     {
-        residual(i,0) = global_f_vector[i] - f_app_vector[i];
-        res += residual(i,0)*residual(i,0);
+        externalWork += full_d_vector[i]*final_nodal_forces[i];
     }
-    res = res / f_app_vector.size();
-    res = sqrt(res);
-    return res;
 }
 
-void assembleGlobalKg(Eigen::SparseMatrix<double> & global_tangent_matrix, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> &  nodeIndexMap, std::vector<int> & new_DOFindices, std::vector<std::size_t> & FEM_elementTags)
+// computing the total (internal) strain energy "strain_energy" in the whole FEM domain (dimension "dim" and 
+// entity tags "tags"), using the elementData stored in "FEM_kinematicsMap" gathering the informations for all
+// FEM elements. The Hooke's matrix in plane stress "H_matrix" is used to compute the stresses from the strains.
+// Computed as a sum of integrals over the finite elements, using Gauss integration "integration_rule".
+void computeStrainEnergy(double & strainEnergy, const int & dim, const std::vector<int> & tags,
+                           std::map<int, elementData> & FEM_kinematicsMap, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           const std::string & integration_rule)
 {
-    std::list<Eigen::Triplet <double>> Kg_tripletList;
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> nodeTags;
+    std::string elementName;
+    int elDim, order, numNodes, numPrimaryNodes;
+    std::vector<double> localNodeCoord;
+    std::vector<double> localCoords, weights;
+    int numComponents, numOrientations;
+    std::vector<double> basisFunctions;
+    std::vector<double> basisFunctionsGradient;
+
+    for (std::size_t k = 0; k < tags.size(); ++k)
+    {
+        gmsh::model::mesh::getElements(elementTypes, elementTags,
+                                       nodeTags, dim, tags[k]);
+        
+        // looping over element types
+        for (std::size_t i = 0; i < elementTypes.size(); ++i)
+        {
+            // getting element properties
+            gmsh::model::mesh::getElementProperties(elementTypes[i],
+                                            elementName, elDim, order,
+                                            numNodes, localNodeCoord, 
+                                            numPrimaryNodes);
+            
+            // get Gauss points coordinates and weights
+            gmsh::model::mesh::getIntegrationPoints(elementTypes[i], 
+                                                    integration_rule,
+                                                    localCoords, weights);
+
+            // get determinants and Jacobians
+            std::vector<double> jacobians, determinants, coords;
+            gmsh::model::mesh::getJacobians(elementTypes[i], 
+                                            localCoords, jacobians, 
+                                            determinants, coords, tags[k]);
 
-    elementData* element;
-    Eigen::Matrix<double, Eigen::Dynamic, 1> fg;
-    int numNodes;
-    Eigen::Matrix<double, Eigen::Dynamic, 1> tmp_F;
-    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Kh;
-    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Kg;
+            // values and derivatives of the shape functions at the Gauss points of the reference element
+            // we are here working with derivatives in the reference space, same for all elements
+            gmsh::model::mesh::getBasisFunctions(elementTypes[i], localCoords, 
+                                                 "Lagrange", numComponents, 
+                                                 basisFunctions, 
+                                                 numOrientations);
+
+            gmsh::model::mesh::getBasisFunctions(elementTypes[i], localCoords, 
+                                                 "GradLagrange", numComponents, 
+                                                 basisFunctionsGradient, 
+                                                 numOrientations);
+
+            #pragma omp parallel for
+            for (std::size_t el = 0; el < elementTags[i].size(); el++){
+
+                Eigen::Matrix<double, Eigen::Dynamic, 1> local_nodal_displacement = FEM_kinematicsMap[elementTags[i][el]].pl;
+
+                double elementalStrainEnergy = 0;
+
+                // looping over the Gauss points: Gauss integration
+                for (std::size_t gaussIndex = 0; gaussIndex < weights.size(); ++gaussIndex){
+                    // converting jacobian to Eigen format
+                    Eigen::Matrix<double, 2, 2> jacob2D;
+                    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
+                        jacob(&jacobians[9*gaussIndex+9*weights.size()*el], 3, 3);
+                    // 3D to 2D (plane stress case)
+                    jacob2D(0,0) = jacob(0,0);
+                    jacob2D(1,0) = jacob(1,0);
+                    jacob2D(0,1) = jacob(0,1);
+                    jacob2D(1,1) = jacob(1,1);
+                            
+                    // computing the inverse
+                    Eigen::Matrix<double, 2, 2> jacobinv = jacob2D.inverse();
 
-    int first_node_index;
-    int first_node;
-    int my_row;
-    int second_node_index;
-    int second_node;
-    int my_col;
-    for(size_t i = 0; i < FEM_elementTags.size(); i++)
-    {
-        element = & FEM_kinematicsMap[FEM_elementTags[i]];
-        numNodes = (int) element->nodes.size();
-        tmp_F = element->P.transpose()*element->fl;
+                    // computing the transpose of the inverse
+                    Eigen::Matrix<double, 2, 2> jacobinvtrans = jacobinv.transpose();
 
-        Eigen::Matrix<double, 1, Eigen::Dynamic> F(1,2*numNodes);
-        for(int j = 0; j < numNodes; j++)
-        {
-            F(0,2*j) = tmp_F(2*j+1, 0);
-            F(0,2*j+1) = -tmp_F(2*j, 0);
-        }
-        
-        Kh = element->E*(-F.transpose()*element->G - element->G.transpose()*F*element->P)*element->E.transpose();
+                    // computing the B matrix
+                    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
 
-        Kg = element->B.transpose()*element->Kl*element->B + Kh;
+                    computeBmatrix(gaussIndex, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
 
-        // assemble Kg into tripletlist
-        for (int j = 0; j < 2*numNodes; ++j)
-        {
-            first_node_index = (int) j/2;
-            first_node = element->nodes[first_node_index];
-            my_row = new_DOFindices[nodeIndexMap[first_node] + j % 2]; 
-            if(my_row >= 0) // else, the DOF corresponds to a Dirichlet BC
-            {
-                for(int l = 0; l <= j; ++l)
-                {   // to exploit symmetry
-                    second_node_index = (int) l/2;
-                    second_node = element->nodes[second_node_index];
-                    my_col = new_DOFindices[nodeIndexMap[second_node] + l % 2];
+                    Eigen::Vector3d epsilon = B_matrix*local_nodal_displacement;
+                    Eigen::Vector3d sigma = H_matrix*epsilon;
 
-                    if(my_col >= 0) // else, the DOF corresponds to a Dirichlet BC
+                    double dot_product = 0;
+                    for(int z = 0; z < 3; z++)
                     {
-                        Kg_tripletList.push_back(Eigen::Triplet<double>(my_row,my_col,Kg(j,l)));
-                        if(j != l)
-                        {
-                            Kg_tripletList.push_back(Eigen::Triplet<double>(my_col,my_row,Kg(j,l)));
-                        }
+                        dot_product += epsilon(z)*sigma(z);
                     }
+
+                    elementalStrainEnergy += 0.5*dot_product*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
                 }
+                /*------------- ASSEMBLY PROCESS ------------*/
+                #pragma omp atomic update
+                strainEnergy += elementalStrainEnergy;
             }
         }
     }
-    global_tangent_matrix.setFromTriplets(Kg_tripletList.begin(), Kg_tripletList.end());
-}
-void updateNodalDispVector(std::vector<double> & full_d_vector, std::vector<double> & global_p_vector, std::vector<int> & new_DOFindices)
-{
-    for(size_t i = 0; i < full_d_vector.size(); i++)
-    {
-        if(new_DOFindices[i] >= 0)
-        {
-            full_d_vector[i] = global_p_vector[new_DOFindices[i]];
-        }
-    }
 }
 
-void retrieveFinalNodalForces(std::vector<double> & final_nodal_forces, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> & nodeIndexMap, std::vector<std::size_t> & FEM_elementTags)
+//displays the time of the desired code section "function_name", if "display_time" is set as true.
+void displayTime(const double &start, const double &end, const std::string &function_name, const bool &display_time)
 {
-    elementData* element;
-    Eigen::Matrix<double, Eigen::Dynamic, 1> fg;
-    int numNodes;
-    int nodeTag;
-    for(size_t i = 0; i < FEM_elementTags.size(); i++)
+    if(display_time)
     {
-        element = & FEM_kinematicsMap[FEM_elementTags[i]];
-        numNodes = (int) element->nodes.size();
-        fg = element->B.transpose()*element->fl;
-        for(int j = 0; j < numNodes; j++)
-        {
-            nodeTag = element->nodes[j];
-            final_nodal_forces[nodeIndexMap[nodeTag]] += fg(2*j);
-            final_nodal_forces[nodeIndexMap[nodeTag] + 1] += fg(2*j + 1);
-        }
-    }
-}
-
-void retrieveBoundaryDisplacements(std::map<int,std::pair<double,double>> & boundaryDisplacementMap, const std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups)
-{
-    std::string groupname = "BEM_FEM_boundary";
-    int dim = groups[groupname].first;
-    int tag = groups[groupname].second;
-    std::vector<int> tags;
-    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-    std::vector<int> elementTypes;
-    std::vector<std::vector<std::size_t>> elementTags;
-    std::vector<std::vector<std::size_t>> elnodeTags;
-
-    int nodeTag;
-    double u;
-    double v;
-
-    std::string elementName;
-    int elDim, order, numNodes, numPrimaryNodes;
-    std::vector<double> localNodeCoord;
+        std::cout << std::endl;
+        std::cout << function_name << std::endl;
+        std::cout << "Elapsed time in nanoseconds: "
+        << end - start << " ns" << std::endl;
 
-    for(std::size_t i=0; i< tags.size(); ++i)
-    {
-        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
-        for(std::size_t j=0; j< elementTypes.size(); ++j)
-        {
+        std::cout << "Elapsed time in microseconds: "
+        << end - start << " µs" << std::endl;
 
-            // getting element properties
-            gmsh::model::mesh::getElementProperties(elementTypes[j],
-                                                        elementName, elDim, order,
-                                                        numNodes, localNodeCoord, 
-                                                        numPrimaryNodes);
+        std::cout << "Elapsed time in milliseconds: "
+        << end - start << " ms" << std::endl;
 
-            for(std::size_t k=0; k < elementTags[j].size(); ++k)
-            {
-                for(int l = 0; l < numNodes; l++)
-                {
-                    nodeTag = elnodeTags[j][numNodes*k + l];
-                    u = full_d_vector[nodeIndexMap[nodeTag]];
-                    v = full_d_vector[nodeIndexMap[nodeTag] + 1];
-                    boundaryDisplacementMap[nodeTag] = std::pair<double, double>(u, v);
-                }
-            }
-        }
+        std::cout << "Elapsed time in seconds: "
+        << end - start << " sec";
+        std::cout << std::endl;
+        std::cout << std::endl;
     }
 }
 
 /*-------------- FUNCTIONS SPECIFIC TO LINEAR FEM ------------------*/
 
-void assembleKtriplet(const int i, const int el, 
-                          const std::vector<std::vector<std::size_t>> & nodeTags, 
-                          const int numNodes, std::map<int, int> & nodeIndexMap,
-                          std::list<Eigen::Triplet <double>> & k_tripletList,
-                          Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & K_matrix,
-                          std::vector<double> & f_vector)
+// assembling the full stiffness matrix "full_K_matrix" using first a triplet vector, assembling the volumic part 
+// of the nodal forces "full_f_vector", in the FEM_domain (dimension "dim" and entity tag "tags") using the global
+// node indexation defined by "nodeIndexMap". "H_matrix" is the plane stress Hooke's matrix, "rho" the density of the
+// material, "bx" the volumic force along x, "by" the volumic force along y.
+void assembleKVolumicF(const Eigen::Matrix<double, 3, 3> & H_matrix, const double & rho, const double & bx, const double & by,
+                const int & dim, const std::vector<int> & tags, std::map<int, int> & nodeIndexMap, 
+                Eigen::SparseMatrix<double> & full_K_matrix, std::vector<double> & full_f_vector)
 {
-    for (int j = 0; j < 2*numNodes; ++j){
-        int first_node_index = (int) j/2;
-        int first_node = nodeTags[i][numNodes*el+first_node_index];
-        int my_row = nodeIndexMap[first_node] + j % 2; // node list begins at 1, '-1' correction to begin at 0
-        for(int l = 0; l <= j; ++l){ // to exploit symmetry
-            int second_node_index = (int) l/2;
-            int second_node = nodeTags[i][numNodes*el+second_node_index];
-            int my_col = nodeIndexMap[second_node] + l % 2;
-
-            k_tripletList.push_back(Eigen::Triplet<double>(my_row,my_col,K_matrix(j,l)));
-            if(j != l){
-                k_tripletList.push_back(Eigen::Triplet<double>(my_col,my_row,K_matrix(j,l)));
-            }
-        }
+    // to allow efficient parallelization, one triplet list (as a vector) is created for every thread, then the different lists are assembled
+    // to further increase efficiency, space is reserved for each list
+    int estimated_number_of_entries = (int) full_f_vector.size()/2 *8*8; // accurate in the case of Q4 elements, otherwise it provides a good estimation
+    std::vector<Eigen::Triplet <double>> K_tripletList;
+    K_tripletList.reserve(estimated_number_of_entries);
+    
+    int max_threads = omp_get_max_threads();
+    int estimated_number_of_entries_per_thread = (int) estimated_number_of_entries / max_threads;
+    std::vector<std::vector<Eigen::Triplet <double>>> thread_K_list(max_threads);
+    for(int i = 0; i < max_threads; i++)
+    {
+        thread_K_list[i].reserve(estimated_number_of_entries_per_thread);
     }
-}
 
-void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const double rho, const double bx, const double by,
-              const std::string & integration_rule, 
-              int & dim, std::vector<int> & tags, std::map<int, int>  & nodeIndexMap,
-              std::vector<std::list<Eigen::Triplet <double>>> & my_k_list, 
-              std::vector<std::list<std::pair<int,double>>> & thread_f_vector)
-{
+    std::vector<Eigen::Triplet <double>>* my_K_list;
 
     std::vector<int> elementTypes;
     std::vector<std::vector<std::size_t>> elementTags;
@@ -1259,7 +1547,7 @@ void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const dou
         gmsh::model::mesh::getElements(elementTypes, elementTags,
                                        nodeTags, dim, tags[k]);
         
-        // looping over element types, enlever les déclarations des boucles pr aller plus vite (cfr Boman)
+        // looping over element types
         for (std::size_t i = 0; i < elementTypes.size(); ++i)
         {
             // getting element properties
@@ -1267,17 +1555,24 @@ void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const dou
                                             elementName, elDim, order,
                                             numNodes, localNodeCoord, 
                                             numPrimaryNodes);
+
+            // adapting the composite integration rule as a function of the order of the elements
+            std::string adapting_integration_rule = "CompositeGauss14";
+            if(order < 8)
+            {
+                adapting_integration_rule = "CompositeGauss" + std::to_string(2*order);
+            }
             
             // get Gauss points coordinates and weights
             gmsh::model::mesh::getIntegrationPoints(elementTypes[i], 
-                                                    integration_rule, // "Gauss2"
+                                                    adapting_integration_rule, 
                                                     localCoords, weights);
 
             // get determinants and Jacobians
             std::vector<double> jacobians, determinants, coords;
             gmsh::model::mesh::getJacobians(elementTypes[i], 
                                             localCoords, jacobians, 
-                                            determinants, coords);
+                                            determinants, coords, tags[k]);
 
             // values and derivatives of the shape functions at the Gauss points of the reference element
             // we are here working with derivatives in the reference space, same for all elements
@@ -1293,15 +1588,15 @@ void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const dou
 
             /*---------computing the K matrix (and f vector, only volumic part for now)------*/
             // looping over the elements (computing elemental K matrices)
-            //double test1 = omp_get_wtime();
-            //Eigen::setNbThreads(1);
-            #pragma omp parallel for
             #ifdef _MSC_VER
             // https://github.com/tesseract-ocr/tesseract/issues/3285
             // OpenMP 2.0 standard is enforced - we may use /openmp:llvm and keep size_t
+            #pragma omp parallel for
             for (int el = 0; el < elementTags[i].size(); el++){
             #else
-            for (std::size_t el = 0; el < elementTags[i].size(); el++){
+            #pragma omp parallel for private (my_K_list)
+            for (std::size_t el = 0; el < elementTags[i].size(); el++)
+            {
             #endif
                 // elemental K matrix and f vector initialization
                 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> K_matrix(2*numNodes,2*numNodes);
@@ -1309,12 +1604,15 @@ void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const dou
                 K_matrix.setZero();
                 for (int j = 0; j < 2*numNodes; ++j)f_vector[j] = 0.;
 
-                // looping over the Gauss points (formula of slide 17)
-                for (std::size_t j = 0; j < weights.size(); ++j){
+                int threadNum = omp_get_thread_num();
+                my_K_list = & thread_K_list[threadNum];
+
+                // looping over the Gauss points
+                for (std::size_t gaussIndex = 0; gaussIndex < weights.size(); ++gaussIndex){
                     // converting jacobian to Eigen format
                         Eigen::Matrix<double, 2, 2> jacob2D;
                     Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
-                        jacob(&jacobians[9*j+9*weights.size()*el], 3, 3);
+                        jacob(&jacobians[9*gaussIndex+9*weights.size()*el], 3, 3);
                     // 3D to 2D (plane stress case)
                     jacob2D(0,0) = jacob(0,0);
                     jacob2D(1,0) = jacob(1,0);
@@ -1327,37 +1625,74 @@ void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const dou
                     // computing the transpose of the inverse
                     Eigen::Matrix<double, 2, 2> jacobinvtrans = jacobinv.transpose();
 
-                    // computing the B matrix (formula slide 19) and the f vector (also using gauss integration)
+                    // computing the B matrix and the f vector (also using gauss integration)
                     Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
 
-
-                    computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, 
-                                     jacobinvtrans, H_matrix, B_matrix);
+                    computeBmatrix(gaussIndex, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
                     
                     for (int l = 0; l < numNodes; ++l){ // looping over the number of shape functions
-                        f_vector[2*l] = f_vector[2*l] + rho*basisFunctions[l+numNodes*j]*bx*determinants[j+weights.size()*el]*weights[j]; //pas oublier le dét !
-                        f_vector[2*l+1] = f_vector[2*l+1] + rho*basisFunctions[l+numNodes*j]*by*determinants[j+weights.size()*el]*weights[j]; // pas oublier le weights[j] non plus !
+                        f_vector[2*l] = f_vector[2*l] + rho*basisFunctions[l+numNodes*gaussIndex]*bx*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
+                        f_vector[2*l+1] = f_vector[2*l+1] + rho*basisFunctions[l+numNodes*gaussIndex]*by*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex]; 
                     }
 
-                    K_matrix = K_matrix + B_matrix.transpose()*H_matrix*B_matrix*determinants[j+weights.size()*el]*weights[j];
+                    K_matrix = K_matrix + B_matrix.transpose()*H_matrix*B_matrix*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
                 }
                 /*------------- ASSEMBLY PROCESS ------------*/
                 // USE LIST OF TRIPLETS TO PUSH ONLY ONCE -> more rapid and easier to parallelize
-                assembleKtriplet(i, el, nodeTags, numNodes, nodeIndexMap, my_k_list[omp_get_thread_num()], K_matrix, f_vector);
-                assembleFthread(i, el, nodeTags, numNodes, nodeIndexMap, thread_f_vector[omp_get_thread_num()], f_vector);
+                assembleKtriplet(el, nodeTags[i], numNodes, nodeIndexMap, *my_K_list, K_matrix);
+                assembleFlocal(el, nodeTags[i], numNodes, nodeIndexMap, full_f_vector, f_vector);
+            }
+        }
+    }
+    // gathering all triplet vectors in one single vector
+    K_tripletList = thread_K_list[0];
+    if(max_threads > 1)
+    {
+        for (int i = 1; i < max_threads; i++)
+        {
+            K_tripletList.insert(K_tripletList.end(), thread_K_list[i].begin(), thread_K_list[i].end());
+        }
+    }
+    // assembling the full sparse K matrix
+    full_K_matrix.setFromTriplets(K_tripletList.begin(), K_tripletList.end());
+}
+
+// assembles the elemental "K_matrix" into a vector of triplets "k_tripletList" using 
+// the node tags provided by "nodeTags" vector (index of the element is "elIndex").
+// The element has "numNodes" nodes. "nodeIndexMap" provides the global nodal index corresponding to a given node tag.
+void assembleKtriplet(const int &elIndex, const std::vector<std::size_t> & nodeTags, const int numNodes, 
+                    std::map<int, int> & nodeIndexMap, std::vector<Eigen::Triplet <double>> & k_tripletList,
+                    const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & K_matrix)
+{
+    //we go through the lower half of the elemental K_matrix before assembling in the triplet vector
+    for (int j = 0; j < 2*numNodes; ++j){
+        int first_node_index = (int) j/2;
+        int first_node = nodeTags[numNodes*elIndex+first_node_index];
+        int my_row = nodeIndexMap[first_node] + j % 2; 
+        for(int l = 0; l <= j; ++l){ // to exploit symmetry
+            int second_node_index = (int) l/2;
+            int second_node = nodeTags[numNodes*elIndex+second_node_index];
+            int my_col = nodeIndexMap[second_node] + l % 2;
+
+            k_tripletList.push_back(Eigen::Triplet<double>(my_row,my_col,K_matrix(j,l)));
+            if(j != l){
+                k_tripletList.push_back(Eigen::Triplet<double>(my_col,my_row,K_matrix(j,l)));
             }
-            //double test2 = omp_get_wtime() - test1;
-            //std::cout << "loop time: " << test2 << "\n";
         }
     }
 }
 
+// the "full_f_vector" and "full_K_matrix" are reduced in "reduced_f_vector" and "reduced_K_matrix" respectively,
+// taking into account the dirichlet boundary conditions contained in "dir_BC".
+// "new_DOFindices" gathers the new indices of the DOFs when taking the boundary conditions into account.
 void fillReducedKf(const std::vector<double> & full_f_vector, const Eigen::SparseMatrix<double> & full_K_matrix,
-                      const std::vector<int> & new_DOFindices, const std::vector<double> & dir_BC,
-                      Eigen::SparseMatrix<double> & reduced_K_matrix, 
-                      std::vector<double> & reduced_f_vector,
-                      std::list<Eigen::Triplet <double>> & reduced_k_tripletList)
+                const std::vector<int> & new_DOFindices, const std::vector<double> & dir_BC,
+                Eigen::SparseMatrix<double> & reduced_K_matrix, std::vector<double> & reduced_f_vector)
 {
+    //the correction term on the f vector comes from the "Finite Element Method" theoretical course (JP Ponthot, ULiege), Chap2 Slide 38/50
+    std::list<Eigen::Triplet <double>> reduced_k_tripletList;
+
+    // initializing the reduced f vector
     for (std::size_t j = 0; j < reduced_f_vector.size(); ++j){
         reduced_f_vector[j] = 0.;
     }
@@ -1367,7 +1702,7 @@ void fillReducedKf(const std::vector<double> & full_f_vector, const Eigen::Spars
     int new_row;
     int new_col;
     double k_value;
-    for (int col=0; col<full_K_matrix.outerSize(); ++col){
+    for (int col=0; col < full_K_matrix.outerSize(); ++col){
         new_col = new_DOFindices[col];
         for (Eigen::SparseMatrix<double>::InnerIterator it(full_K_matrix,col); it; ++it){
             k_value = it.value();
@@ -1393,121 +1728,293 @@ void fillReducedKf(const std::vector<double> & full_f_vector, const Eigen::Spars
     reduced_K_matrix.setFromTriplets(reduced_k_tripletList.begin(), reduced_k_tripletList.end());
 }
 
-void computeStressStrainLinearWay(const std::vector<int> & elementTypes, const std::vector<std::vector<std::size_t>> &elementTags,
-                           const std::vector<std::vector<std::size_t>> &elnodeTags,
-                           const std::vector<double> &full_d_vector, std::vector<std::size_t> & elems2D,
-                           const Eigen::Matrix<double, 3, 3> &H_matrix, const double nu, const double E,
-                           std::map<int, int> & nodeIndexMap,
-                           std::vector<std::vector<double>> & data3, std::vector<std::vector<double>> & data4,
-                           std::vector<std::vector<double>> & data5, std::vector<std::vector<double>> & data6,
-                           std::vector<std::vector<double>> & data7, std::vector<std::vector<double>> & data8,
-                           std::vector<std::vector<double>> & data9, std::vector<std::vector<double>> & data10,
-                           int & k)
+
+// computing the elemental-nodal strains and stresses in the FEM domain (dimension "dim" and entity tags "tags"),
+// based on Hooke's matrix in plane stress "H_matrix", Young's modulus "E", Poisson's ratio "nu", and the full nodal
+// displacement vector "full_d_vector" and the global nodal index map "nodeIndexMap".
+// "nbelems" is the number of 2D elements contained in the FEM domain.
+// returning the "max_VM_stress" and the corresponding nodetag "max_VM_nodeTag".
+void computeStressStrainLinearWay(const int & dim, const std::vector<int> & tags, const std::vector<double> &full_d_vector,
+                           const Eigen::Matrix<double, 3, 3> &H_matrix, const double &nu, const double &E,
+                           std::map<int, int> & nodeIndexMap, const int &nbelems, double &max_VM_stress, int &max_VM_nodeTag)
+{
+    std::vector<std::string> names;
+    gmsh::model::list(names);
+
+    int viewTagEpsX = gmsh::view::add("nodal_eps_x");
+    int viewTagEpsY = gmsh::view::add("nodal_eps_y");
+    int viewTagEpsXY = gmsh::view::add("nodal_2eps_xy");
+    int viewTagEpsZ = gmsh::view::add("nodal_eps_z");
+    int viewTagSigX = gmsh::view::add("nodal_sig_x");
+    int viewTagSigY = gmsh::view::add("nodal_sig_y");
+    int viewTagSigXY = gmsh::view::add("nodal_sig_xy");
+    int viewTagSigVM = gmsh::view::add("nodal_sig_VM");
+
+    std::vector<std::vector<std::vector<double>>> dataEps(4);
+    dataEps[0].resize(nbelems); // eps X
+    dataEps[1].resize(nbelems); // eps Y
+    dataEps[2].resize(nbelems); // eps XY
+    dataEps[3].resize(nbelems); // eps Z
+
+    std::vector<std::vector<std::vector<double>>> dataSig(4);
+    dataSig[0].resize(nbelems); // Sig X
+    dataSig[1].resize(nbelems); // Sig Y
+    dataSig[2].resize(nbelems); // Sig XY
+    dataSig[3].resize(nbelems); // Sig VM
+    std::vector<std::size_t> elems2D(nbelems);
+
+
+    int data_index = 0;
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> elnodeTags;
+
+    for(std::size_t entityTag = 0; entityTag< tags.size(); ++entityTag)
+    {
+        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[entityTag]);
+
+        std::string name;
+        int dim, order, numNodes, numPrimaryNodes;
+        std::vector<double> paramCoord2D;
+        int numComponents, numOrientations;
+        std::vector<double> basisFunctionsGradient;
+        Eigen::Vector3d epsilon; // will contain local values of the strains
+        Eigen::Vector3d sigma; // will contain local values of the stresses
+        int nodeTag;
+        Eigen::Matrix<double, 2, 2> jacob2D;
+        Eigen::Matrix<double, 2, 2> jacobinv;
+        Eigen::Matrix<double, 2, 2> jacobinvtrans;
+
+        for (std::size_t ityp = 0; ityp < elementTypes.size(); ++ityp)
+        {
+            // get info about this type of element
+            gmsh::model::mesh::getElementProperties(elementTypes[ityp], name, dim, order,
+                                                    numNodes, paramCoord2D, numPrimaryNodes);
+            //paramCoord contains the coordinates of the nodes in 2D
+            // passage en 3D pour utiliser getJacobians
+            std::vector<double> paramCoord(3*paramCoord2D.size()/2);
+            for(std::size_t j = 0; j < paramCoord2D.size()/2; ++j){
+                paramCoord[3*j] = paramCoord2D[2*j];
+                paramCoord[3*j+1] = paramCoord2D[2*j+1];
+                paramCoord[3*j+2] = 0.;
+            }
+            
+
+            // select element/node tags for this type of element
+            auto &etags = elementTags[ityp];
+            auto &enods = elnodeTags[ityp];
+
+            // will contain the d vector inside each element
+            Eigen::VectorXd nodal_displacement(2*numNodes); //use eigen vector to use Eigen matric product later
+
+            // get determinants and Jacobians (only jacob useful here) AT NODES AND NOT AT GAUSS POINTS
+            std::vector<double> jacobians, determinants, coords;
+            gmsh::model::mesh::getJacobians(elementTypes[ityp], 
+                                            paramCoord, jacobians, 
+                                            determinants, coords, tags[entityTag]);
+
+            // derivatives of the shape functions at the nodes of the reference element
+            // we are here working with derivatives in the reference space, same for all elements
+            gmsh::model::mesh::getBasisFunctions(elementTypes[ityp], paramCoord, 
+                                                    "GradLagrange", numComponents, 
+                                                    basisFunctionsGradient, 
+                                                    numOrientations);
+
+            // loop over elements of type "ityp"
+            for (std::size_t i = 0; i < etags.size(); ++i)
+            {
+                elems2D[data_index] = etags[i];
+
+                dataEps[0][data_index].resize(numNodes);
+                dataEps[1][data_index].resize(numNodes);
+                dataEps[2][data_index].resize(numNodes);
+                dataEps[3][data_index].resize(numNodes);
+                dataSig[0][data_index].resize(numNodes);
+                dataSig[1][data_index].resize(numNodes);
+                dataSig[2][data_index].resize(numNodes);
+                dataSig[3][data_index].resize(numNodes);
+
+                // loop over nodes of the element, filling the local nodal displacement vector "d"
+                for (int j = 0; j < numNodes; ++j)
+                {
+                    nodeTag = enods[numNodes * i + j];
+                    nodal_displacement(2*j) = full_d_vector[nodeIndexMap[nodeTag]];
+                    nodal_displacement(2*j+1) = full_d_vector[nodeIndexMap[nodeTag]+1];
+                }
+                // looping over the nodes
+                for (int j = 0; j < numNodes; ++j){
+                    // converting jacobian to Eigen format
+                    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
+                        jacob(&jacobians[9*j+9*numNodes*i], 3, 3);
+                    // 3D to 2D (plane stress case)
+                    jacob2D(0,0) = jacob(0,0);
+                    jacob2D(1,0) = jacob(1,0);
+                    jacob2D(0,1) = jacob(0,1);
+                    jacob2D(1,1) = jacob(1,1);
+                            
+                    // computing the inverse
+                    jacobinv = jacob2D.inverse();
+
+                    // computing the transpose of the inverse
+                    jacobinvtrans = jacobinv.transpose();
+
+                    // computing the B matrix  
+                    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
+
+                    computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
+
+                    epsilon = B_matrix*nodal_displacement;
+                    sigma = H_matrix*epsilon;
+
+                    dataEps[0][data_index][j] = epsilon(0);
+                    dataEps[1][data_index][j] = epsilon(1);
+                    dataEps[2][data_index][j] = epsilon(2);
+                    dataEps[3][data_index][j] = -nu/E*(sigma(0)+sigma(1));
+                    dataSig[0][data_index][j] = sigma(0);
+                    dataSig[1][data_index][j] = sigma(1);
+                    dataSig[2][data_index][j] = sigma(2);
+                    dataSig[3][data_index][j] = sqrt(sigma(0)*sigma(0) + sigma(1)*sigma(1) - sigma(0)*sigma(1) + 3*sigma(2)*sigma(2));
+
+                    //retrieving maximal nodal von mises stress
+                    if(dataSig[3][data_index][j] > max_VM_stress)
+                    {
+                        max_VM_stress = dataSig[3][data_index][j];
+                        max_VM_nodeTag = (int) elnodeTags[ityp][numNodes*i+j];
+                    }
+                }
+                data_index++;
+            }
+        }
+    }
+    
+    gmsh::view::addModelData(viewTagEpsX, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[0], 1);
+    gmsh::view::addModelData(viewTagEpsY, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[1], 1);
+    gmsh::view::addModelData(viewTagEpsXY, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[2], 1);
+    gmsh::view::addModelData(viewTagEpsZ, 0, names[0], "ElementNodeData",
+                                elems2D, dataEps[3], 1);
+    gmsh::view::addModelData(viewTagSigX, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[0], 1);
+    gmsh::view::addModelData(viewTagSigY, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[1], 1);
+    gmsh::view::addModelData(viewTagSigXY, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[2], 1);
+    gmsh::view::addModelData(viewTagSigVM, 0, names[0], "ElementNodeData",
+                                elems2D, dataSig[3], 1);
+}
+
+// computing the total (internal) strain energy "strain_energy" in the whole FEM domain (dimension "dim" and 
+// entity tags "tags"), using the nodal displacements in "full_d_vector". The nodes are indexed using the "nodeIndexMap".
+// The Hooke's matrix in plane stress "H_matrix" is used to compute the stresses from the strains.
+// Computed as a sum of integrals over the finite elements, using Gauss integration "integration_rule".
+void computeStrainEnergyLinearWay(double & strainEnergy, const int & dim, const std::vector<int> & tags,
+                           const std::vector<double> &full_d_vector, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           std::map<int, int> & nodeIndexMap, const std::string & integration_rule)
 {
-    std::string name;
-    int dim, order, numNodes, numPrimaryNodes;
-    std::vector<double> paramCoord2D;
+    std::vector<int> elementTypes;
+    std::vector<std::vector<std::size_t>> elementTags;
+    std::vector<std::vector<std::size_t>> nodeTags;
+    std::string elementName;
+    int elDim, order, numNodes, numPrimaryNodes;
+    std::vector<double> localNodeCoord;
+    std::vector<double> localCoords, weights;
     int numComponents, numOrientations;
+    std::vector<double> basisFunctions;
     std::vector<double> basisFunctionsGradient;
+    int nodeTag;
+
     Eigen::Vector3d epsilon; // will contain local values of the strains
     Eigen::Vector3d sigma; // will contain local values of the stresses
-    int nodeTag;
-    Eigen::Matrix<double, 2, 2> jacob2D;
-    Eigen::Matrix<double, 2, 2> jacobinv;
-    Eigen::Matrix<double, 2, 2> jacobinvtrans;
 
-    for (std::size_t ityp = 0; ityp < elementTypes.size(); ++ityp)
+    for (std::size_t k = 0; k < tags.size(); ++k)
     {
-        // get info about this type of element
-        gmsh::model::mesh::getElementProperties(elementTypes[ityp], name, dim, order,
-                                                numNodes, paramCoord2D, numPrimaryNodes);
-        //paramCoord contains the coordinates of the nodes in 2D
-        // passage en 3D pour utiliser getJacobians
-        std::vector<double> paramCoord(3*paramCoord2D.size()/2);
-        for(std::size_t j = 0; j < paramCoord2D.size()/2; ++j){
-            paramCoord[3*j] = paramCoord2D[2*j];
-            paramCoord[3*j+1] = paramCoord2D[2*j+1];
-            paramCoord[3*j+2] = 0.;
-        }
+        gmsh::model::mesh::getElements(elementTypes, elementTags,
+                                       nodeTags, dim, tags[k]);
         
+        // looping over element types
+        for (std::size_t i = 0; i < elementTypes.size(); ++i)
+        {
+            // getting element properties
+            gmsh::model::mesh::getElementProperties(elementTypes[i],
+                                            elementName, elDim, order,
+                                            numNodes, localNodeCoord, 
+                                            numPrimaryNodes);
+            
+            // get Gauss points coordinates and weights
+            gmsh::model::mesh::getIntegrationPoints(elementTypes[i], 
+                                                    integration_rule,
+                                                    localCoords, weights);
 
-        // select element/node tags for this type of element
-        auto &etags = elementTags[ityp];
-        auto &enods = elnodeTags[ityp];
+            // get determinants and Jacobians
+            std::vector<double> jacobians, determinants, coords;
+            gmsh::model::mesh::getJacobians(elementTypes[i], 
+                                            localCoords, jacobians, 
+                                            determinants, coords, tags[k]);
 
-        // will contain the d vector inside each element
-        Eigen::VectorXd nodal_displacement(2*numNodes); //use eigen vector to use Eigen matric product later
+            // values and derivatives of the shape functions at the Gauss points of the reference element
+            // we are here working with derivatives in the reference space, same for all elements
+            gmsh::model::mesh::getBasisFunctions(elementTypes[i], localCoords, 
+                                                 "Lagrange", numComponents, 
+                                                 basisFunctions, 
+                                                 numOrientations);
 
-        // get determinants and Jacobians (only jacob useful here) AT NODES AND NOT AT GAUSS POINTS
-        std::vector<double> jacobians, determinants, coords;
-        gmsh::model::mesh::getJacobians(elementTypes[ityp], 
-                                        paramCoord, jacobians, 
-                                        determinants, coords);
+            gmsh::model::mesh::getBasisFunctions(elementTypes[i], localCoords, 
+                                                 "GradLagrange", numComponents, 
+                                                 basisFunctionsGradient, 
+                                                 numOrientations);
+                                                
+            Eigen::VectorXd nodal_displacement(2*numNodes); //use eigen vector to use Eigen matric product later
 
-        // derivatives of the shape functions at the nodes of the reference element
-        // we are here working with derivatives in the reference space, same for all elements
-        gmsh::model::mesh::getBasisFunctions(elementTypes[ityp], paramCoord, 
-                                                "GradLagrange", numComponents, 
-                                                basisFunctionsGradient, 
-                                                numOrientations);
+            for (std::size_t el = 0; el < elementTags[i].size(); el++){
 
-        // loop over elements of type "ityp"
-        for (std::size_t i = 0; i < etags.size(); ++i)
-        {
-            elems2D[k] = etags[i];
-
-            data3[k].resize(numNodes);
-            data4[k].resize(numNodes);
-            data5[k].resize(numNodes);
-            data6[k].resize(numNodes);
-            data7[k].resize(numNodes);
-            data8[k].resize(numNodes);
-            data9[k].resize(numNodes);
-            data10[k].resize(numNodes);
-
-            // loop over nodes of the element, filling the local nodal displacement vector "d"
-            for (int j = 0; j < numNodes; ++j)
-            {
-                nodeTag = enods[numNodes * i + j];
-                nodal_displacement(2*j) = full_d_vector[nodeIndexMap[nodeTag]];
-                nodal_displacement(2*j+1) = full_d_vector[nodeIndexMap[nodeTag]+1];
-            }
-            // looping over the nodes
-            for (int j = 0; j < numNodes; ++j){
-                // converting jacobian to Eigen format
-                Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
-                    jacob(&jacobians[9*j+9*numNodes*i], 3, 3);
-                // 3D to 2D (plane stress case)
-                jacob2D(0,0) = jacob(0,0);
-                jacob2D(1,0) = jacob(1,0);
-                jacob2D(0,1) = jacob(0,1);
-                jacob2D(1,1) = jacob(1,1);
-                        
-                // computing the inverse
-                jacobinv = jacob2D.inverse();
-
-                // computing the transpose of the inverse
-                jacobinvtrans = jacobinv.transpose();
-
-                // computing the B matrix (formula slide 19) 
-                Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
-
-                computeBmatrix(j, numNodes, basisFunctionsGradient, determinants, 
-                                 jacobinvtrans, H_matrix, B_matrix);
-
-                epsilon = B_matrix*nodal_displacement;
-                sigma = H_matrix*epsilon;
-
-                data3[k][j] = epsilon(0);
-                data4[k][j] = epsilon(1);
-                data5[k][j] = epsilon(2);
-                data6[k][j] = -nu/E*(sigma(0)+sigma(1));// formula slide 11/20 elasticity
-                data7[k][j] = sigma(0);
-                data8[k][j] = sigma(1);
-                data9[k][j] = sigma(2);
-                data10[k][j] = sqrt(sigma(0)*sigma(0) + sigma(1)*sigma(1) - sigma(0)*sigma(1) + 3*sigma(2)*sigma(2));
+                for (int j = 0; j < numNodes; ++j)
+                {
+                    nodeTag = nodeTags[i][numNodes * el + j];
+                    nodal_displacement(2*j) = full_d_vector[nodeIndexMap[nodeTag]];
+                    nodal_displacement(2*j+1) = full_d_vector[nodeIndexMap[nodeTag]+1];
+                }
+
+                double elementalStrainEnergy = 0;
+
+                // looping over the Gauss points
+                for (std::size_t gaussIndex = 0; gaussIndex < weights.size(); ++gaussIndex){
+                    // converting jacobian to Eigen format
+                    Eigen::Matrix<double, 2, 2> jacob2D;
+                    Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> >
+                        jacob(&jacobians[9*gaussIndex+9*weights.size()*el], 3, 3);
+                    // 3D to 2D (plane stress case)
+                    jacob2D(0,0) = jacob(0,0);
+                    jacob2D(1,0) = jacob(1,0);
+                    jacob2D(0,1) = jacob(0,1);
+                    jacob2D(1,1) = jacob(1,1);
+                            
+                    // computing the inverse
+                    Eigen::Matrix<double, 2, 2> jacobinv = jacob2D.inverse();
+
+                    // computing the transpose of the inverse
+                    Eigen::Matrix<double, 2, 2> jacobinvtrans = jacobinv.transpose();
+
+                    // computing the B matrix 
+                    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B_matrix(3,2*numNodes);
+
+                    computeBmatrix(gaussIndex, numNodes, basisFunctionsGradient, determinants, jacobinvtrans, B_matrix);
+
+                    epsilon = B_matrix*nodal_displacement;
+                    sigma = H_matrix*epsilon;
+
+                    double dot_product = 0;
+                    for(int z = 0; z < 3; z++)
+                    {
+                        dot_product += epsilon(z)*sigma(z);
+                    }
+
+                    elementalStrainEnergy += 0.5*dot_product*determinants[gaussIndex+weights.size()*el]*weights[gaussIndex];
+                }
+                /*------------- ASSEMBLY PROCESS ------------*/
+                strainEnergy += elementalStrainEnergy;
             }
-            k++;
         }
     }
 }
\ No newline at end of file
diff --git a/srcs/FEM/functionsFEM.hpp b/srcs/FEM/functionsFEM.hpp
index 5cd5c13da97758ba0262a73ac278af33c075836a..cadea106899f5c85d6499d90de0a282f1cffb5ec 100644
--- a/srcs/FEM/functionsFEM.hpp
+++ b/srcs/FEM/functionsFEM.hpp
@@ -1,10 +1,11 @@
 #include <iostream>
-#include <vector>   // Why should I include this ?
+#include <vector> 
 #include <map>
 #include <Eigen/Dense>
 #include <list>
-#include <Eigen/Sparse> // Eigen library for sparse matrices
+#include <Eigen/Sparse>
 
+// data structure used for the non-linear solver "solverFEMnonLinear"
 struct elementData{
     // will store all the kinematics data
     std::vector<size_t> nodes; // will contain the tags of the nodes
@@ -34,41 +35,232 @@ struct elementData{
 
     Eigen::Matrix<double, Eigen::Dynamic, 1> fl; //local current (iterative) forces under vector form
 
-    Eigen::Matrix<double, Eigen::Dynamic, 1> A;
-    Eigen::Matrix<double, 1, Eigen::Dynamic> G;
-    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> P;
-    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> E;
-    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> B;
+    Eigen::Matrix<double, Eigen::Dynamic, 1> A; // see report for exact definition
+    Eigen::Matrix<double, 1, Eigen::Dynamic> G; // see report for exact definition
+    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> P; // see report for exact definition
+    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> E; // see report for exact definition
+    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> C; // see report for exact definition
 };
 
+/*------------ "SOLVER" functions -----------------*/
+
+// solves the non-linear (large displacements, no large deformations) elastic problem.
+// if coupled to the BEM solver, "electrostaticPressure" is the pressure computed from the electric field
+// on the BEM_FEM boundary (mapping element tag -> pressure). "boundaryDisplacementMap" is filled for all
+// nodes on the BEM_FEM_boundary as (node tag -> (u,v) displacement)
+// "nbViews" is the current number of views already allocated in the gmsh window.
+// "postProcessing" boolean activates the post processing operations (must only be computed once at the end of the
+// coupled solver). "iteration" denotes the current iteration of the two-way coupled solver (starting at 1).
+// "viewTagU" and "viewTagF" correspond to the view tags of the nodal displacements and the nodal forces in the gmsh window.
+// when "untangleMesh" is activated, the nodal coordinates of the nodes in the FEM_domain are updated according to
+// their final nodal displacements.
+void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, 
+                    std::map<int,std::pair<double,double>> & boundaryDisplacementMap, int &nbViews, bool postProcessing, 
+                    const int iteration, const int viewTagU, const int viewTagF, bool untangleMesh);
+
+// solves the linear elastic problem in the FEM domain.
+// "electrostaticPressure" contains the pressure resulting from the electric field computation on the 
+// BEM_FEM_boundary. "nbViews" is the current number of views already allocated in the gmsh window.
+void solverFEM(std::map<int, double> &electrostaticPressure, int &nbViews);
+
+/*------------ More specific functions called inside the "SOLVER" functions -----------------*/
+
+// returns the boolean non_linear_solver parameter based on what is set in the .geo file,
+// add SetNumber("Non_linear_solver", 0); in .geo file to use linear solver.
+bool getNonLinearParameter();
+
+// fills the "FEM_nodeTags" vector with the nodes in the FEM domain, fills the "FEM_nodeCoordsMap" with the coordinates (x,y)
+// corresponding to each nodeTag, looking at entity tags "tags" of dimension "dim" corresponding to the FEM domain.
+void RetrieveFEMNodeTagsAndCoords(std::vector<std::size_t> & FEM_nodeTags, 
+                            std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, 
+                            const int & dim, const std::vector<int> & tags);
+
+// fills the "FEM_elementTags" vector with all element tags of the elements of dimension "dim" (in practice: 2)
+// in the entities associated to the entity tags "tags" (corresponding to the FEM domain).
+// associates an initialized elementData structure to each element tag through the "FEM_kinematicsMap" map,
+// using the "FEM_nodeCoordsMap" map gathering the coordinates of each node in the FEM domain.
+int initKinematics(std::vector<std::size_t> & FEM_elementTags, std::map<int, elementData> & FEM_kinematicsMap, 
+                std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, 
+                const int & dim, const std::vector<int> & tags);
+
+// updates the kinematics matrices of one element "element" based on its updated nodal positions and rotation angle.
+// if "computeFl" is set as true, also computes the local nodal forces vector "fl = Kl*pl", only OK if 
+// the local stiffness matrix Kl has already been initialized, using "fillElementalKandF".
+void updateKinMatrices(elementData* element, const bool computeFl);
+
+// gets physical properties of FEM_domain: Young's modulus "E", Poisson's ratio "nu",
+// density "rho", volumic force along x "bx", volumic force along y "by".
+void getPhysicalProperties(double & E, double & nu, double & rho, double & bx, double & by);
+
+// computes the Hooke's matrix in plane stress "H_matrix" based on the Young's modulus "E" and Poisson's ratio "nu".
 Eigen::Matrix<double, 3, 3> computeHmatrix(const double E, const double nu);
-void assembleFthread(const int i, const int el, const std::vector<std::vector<std::size_t>> & nodeTags, const int numNodes, std::map<int, int> & nodeIndexMap, std::list<std::pair<int,double>> & thread_f_vector, std::vector<double> & f_vector);
-void computeBmatrix(const int j, const int numNodes, const std::vector<double> & basisFunctionsGradient, const std::vector<double> & determinants, const Eigen::Matrix<double, 2, 2> & jacobinvtrans, const Eigen::Matrix<double, 3, 3> & H_matrix, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & B_matrix);
-void getPhysicalProperties(const std::vector<std::string> & keys, double & E, double & nu, double & rho, double & bx, double & by);
-void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double rho, const double bx, const double by, const std::string & integration_rule, int & dim, std::vector<int> & tags, std::map<int, int>  & nodeIndexMap, std::vector<std::list<Eigen::Triplet <double>>> & my_k_list, std::vector<std::list<std::pair<int,double>>> & thread_f_vector, std::map<int, elementData> & FEM_kinematicsMap);
-void computeNeumannBC(const int numNodes, const int i, const std::vector<std::vector<std::size_t>> & elementTags, const double tx, const double ty, std::map<int, int> & nodeIndexMap, std::vector<double> & f_vector, const std::vector<double> & weights, const std::vector<double> & basisFunctions, const std::vector<double> & determinants, const std::vector<std::vector<std::size_t>> & nodeTags, std::vector<double> & full_f_vector);
-void includeNeumannBC(const std::vector<std::string> & keys, const std::string & integration_rule, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, std::vector<double> & full_f_vector);
-void fillDOFindicesDirBC(const std::vector<std::string> & keys, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, std::vector<int> & new_DOFindices, std::vector<double> & dir_BC);
-void computeReactionForces(std::map<std::string, std::pair<int, int>> & groups, std::map<int, int> & nodeIndexMap, std::vector<double> & nodal_forces, const std::vector<std::string> & keys);
-void plotUxUy(const std::vector<std::size_t> & FEM_nodeTags, const std::vector<double> & full_d_vector, const int nbViews, std::vector<std::string> & names);
-void computeStressStrainElNodal(const std::vector<int> & elementTypes, const std::vector<std::vector<std::size_t>> &elementTags, const std::vector<std::vector<std::size_t>> &elnodeTags, std::vector<std::size_t> & elems2D, const Eigen::Matrix<double, 3, 3> &H_matrix, const double nu, const double E, std::map<int, elementData> & FEM_kinematicsMap, std::vector<std::vector<double>> & data3, std::vector<std::vector<double>> & data4, std::vector<std::vector<double>> & data5, std::vector<std::vector<double>> & data6, std::vector<std::vector<double>> & data7, std::vector<std::vector<double>> & data8, std::vector<std::vector<double>> & data9, std::vector<std::vector<double>> & data10, int & k);
-void applyElecPressure(const std::string & integration_rule, std::map<int,std::pair<double,double>> & nodeCoordsMap, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, std::map<int, double> &electrostaticPressure, std::vector<double> & full_f_vector);
-int initKinematics(std::vector<std::size_t> & FEM_elementTags, std::map<int, elementData> & FEM_kinematicsMap, std::map<int,std::pair<double,double>> & FEM_nodeCoordsMap, int & dim, std::vector<int> & tags);
-void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, std::vector<std::size_t> & FEM_elementTags);
-void updateKinMatrices(elementData* element, bool computeFl);
-void assembleGlobalF(std::vector<double> & global_f_vector, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> & nodeIndexMap, std::vector<int> & new_DOFindices, std::vector<std::size_t> & FEM_elementTags);
-double computeResidualNorm(std::vector<double> & global_f_vector, std::vector<double> & f_app_vector, Eigen::Matrix<double, Eigen::Dynamic, 1> & residual);
-void assembleGlobalKg(Eigen::SparseMatrix<double> & global_tangent_matrix, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> &  nodeIndexMap, std::vector<int> & new_DOFindices, std::vector<std::size_t> & FEM_elementTags);
-void updateNodalDispVector(std::vector<double> & full_d_vector, std::vector<double> & global_p_vector, std::vector<int> & new_DOFindices);
-void retrieveFinalNodalForces(std::vector<double> & final_nodal_forces, std::map<int, elementData> & FEM_kinematicsMap, std::map<int, int> & nodeIndexMap, std::vector<std::size_t> & FEM_elementTags);
-void retrieveBoundaryDisplacements(std::map<int,std::pair<double,double>> & boundaryDisplacementMap, const std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups);
-
-void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<int,std::pair<double,double>> & boundaryDisplacementMap, const int nbViews, bool postProcessing, const int iteration, const int viewTagU, const int viewTagF);
+
+// looping over every element in the FEM_domain (dimension "dim" and entity tags "tags"), filling "full_f_vector",
+// with the local volumic forces computed based on the volumic force ("bx","by") and density "rho" with the help of
+// "nodeIndexMap" mapping each nodeTag to its global index.
+// filling the local stiffness matrices stored in the elementData structure contained in "FEM_kinematicsMap".
+void fillElementalKandF(const Eigen::Matrix<double, 3, 3> H_matrix, const double & rho, const double & bx, 
+                const double & by, const int & dim, const std::vector<int> & tags, std::map<int, int> & nodeIndexMap,
+                std::vector<double> & full_f_vector, std::map<int, elementData> & FEM_kinematicsMap);
+
+// computing the strain displacement "B_matrix" at the "gaussIndex"-th gaussian point of the element
+// consisting of "numNodes" nodes, based on the "basisFunctionsGradient", "determinants" and the inverse of the jacobian
+// matrix "jacobinvtrans".
+void computeBmatrix(const int &gaussIndex, const int &numNodes, const std::vector<double> & basisFunctionsGradient,
+                      const std::vector<double> & determinants, 
+                      const Eigen::Matrix<double, 2, 2> & jacobinvtrans,
+                      Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & B_matrix);
+
+// assembles the local "f_vector" into the full f vector, "elIndex" is the element index with respect to "nodeTags"
+// having "numNodes" nodes, "nodeTags" gathering all the nodeTags of the current element type in the current entity.
+// "nodeIndexMap" associates a global index to each nodetag.
+void assembleFlocal(const int &elIndex, const std::vector<std::size_t> & nodeTags, const int &numNodes, 
+                std::map<int, int> & nodeIndexMap, std::vector<double> & full_f_vector, const std::vector<double> & f_vector);
+
+// fills the "full_f_vector" with the surfacic contribution of the neumann boundary conditions based on the 
+// "nodeIndexMap" associating a global index to each node tag, the local integration of the surfacic forces is 
+// performed using Gauss integration based on "integration rule".
+// "BCkeys" gathers the keys associated to boundary conditions in the .geo file (using SetNumber(...)).
+// "groups" associates a dimension and a tag to each physical group.
+void includeNeumannBC(const std::vector<std::string> & BCkeys, const std::string & integration_rule,
+                std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups,
+                std::vector<double> & full_f_vector);
+
+// for the coupled solver, fills the "full_f_vector" with the electrostatic pressure contained in the 
+// "electrostaticPressure" map for different element tags, using Gauss integration "integration_rule", the "nodeIndexMap" 
+// associating a global nodal index to each nodeTag, "nodeCoordsMap" gathering the coordinates of each node and "groups"
+// containing the different physical groups of the domain.
+void applyElecPressure(const std::string & integration_rule, std::map<int,std::pair<double,double>> & nodeCoordsMap, 
+                    std::map<int, int> & nodeIndexMap, std::map<std::string, std::pair<int, int>> & groups, 
+                    std::map<int, double> &electrostaticPressure, std::vector<double> & full_f_vector);
+
+// looping over the boundary conditions imposed in the .geo file and gathered in "BCkeys" related to the
+// physical groups "groups", the goal is to fill the two vectors "new_DOFindices" and "dir_BC":
+// "new_DOFindices" vector will contain the new indices of the K matrix after the "number_removed_lines" rows/columns
+// corresponding to dirichlet boundary conditions have been removed. A removed index will correspond to "new_DOFindices"= -1.
+// dir_BC[index] will contain the dirichlet boundary condition prescribed to the node whose global index is retrieved using
+// "nodeIndexMap".
+void fillDOFindicesDirBC(const std::vector<std::string> & BCkeys, std::map<int, int> & nodeIndexMap,
+                        std::map<std::string, std::pair<int, int>> & groups, 
+                        std::vector<int> & new_DOFindices, std::vector<double> & dir_BC, int & number_removed_lines);
+
+// updating the kinematics of the "FEM_elementTags" contained in the "FEM_kinematicsMap",
+// based on the "full_d_vector" gathering the nodal displacements associated to the global
+// node indices contained in "nodeIndexMap".
+void updateKinematics(std::map<int, elementData> & FEM_kinematicsMap, const std::vector<double> & full_d_vector, 
+                std::map<int, int> & nodeIndexMap, const std::vector<std::size_t> & FEM_elementTags);
+
+// retrieving the global nodal forces based on local nodal forces of the 
+// "FEM_elementTags" contained in the "FEM_kinematicsMap", 
+// each node Tag corresponds to a global index given by "nodeIndexMap".
+void retrieveTotalNodalForces(std::vector<double> & final_nodal_forces, std::map<int, elementData> & FEM_kinematicsMap, 
+                        std::map<int, int> & nodeIndexMap, const std::vector<std::size_t> & FEM_elementTags);
+
+// assembles the "global_f_vector" based on the local nodal forces vector of the 
+// "FEM_elementTags" contained in the "FEM_kinematicsMap", 
+// without taking into account the DOFs fixed by a dirichlet boundary condition,
+// the nodes are renumbered using "new_DOFindices".
+// each node Tag corresponds to a global index given by "nodeIndexMap".
+void assembleGlobalF(std::vector<double> & global_f_vector, std::map<int, elementData> & FEM_kinematicsMap, 
+                std::map<int, int> & nodeIndexMap, const std::vector<int> & new_DOFindices, 
+                const std::vector<std::size_t> & FEM_elementTags);
+
+// assembling the global tangent stiffness matrix based on the local elemental stiffness matrices contained
+// in the "FEM_kinematicsMap" associated to each "FEM_elementTags".
+// "new_DOFindices" maps the global initial node index (from "nodeIndexMap") to the index
+// obtained without considering the fixed DOFs.
+void assembleGlobalKg(Eigen::SparseMatrix<double> & global_tangent_matrix, std::map<int, elementData> & FEM_kinematicsMap, 
+                    std::map<int, int> & nodeIndexMap, const std::vector<int> & new_DOFindices, 
+                    const std::vector<std::size_t> & FEM_elementTags);
+
+// updating the "full_d_vector" based on the "global_p_vector", using the global and reduced index mapping:
+// "new_DOFindices".
+void updateNodalDispVector(std::vector<double> & full_d_vector, const std::vector<double> & global_p_vector, 
+                        const std::vector<int> & new_DOFindices);
+
+// retrieving the nodal displacements on the BEM_FEM_boundary in order to communicate them to the
+// BEM solver in the two-way coupled solver. Using the "groups" to find the physical group associated
+// to the boundary, all nodes of the boundary are associated through the "boundaryDisplacementMap" their
+// nodal displacement (u,v) retrieved from "full_d_vector" using the indexation of "nodeIndexMap".
+void retrieveBoundaryDisplacements(std::map<int,std::pair<double,double>> & boundaryDisplacementMap, 
+                            const std::vector<double> & full_d_vector, std::map<int, int> & nodeIndexMap, 
+                            std::map<std::string, std::pair<int, int>> & groups);
+
+// computing the reaction forces on all the physical groups "groups" for which a dirichlet boundary
+// condition has been prescribed (using the "BCkeys" to retrieve the groups from the .geo file),
+// based on the "final_nodal_forces" and the "nodeIndexMap" to retrieve the global index associated
+// to one given node tag.
+void computeReactionForces(std::map<std::string, std::pair<int, int>> & groups,
+                     std::map<int, int> & nodeIndexMap, const std::vector<double> & final_nodal_forces,
+                     const std::vector<std::string> & BCkeys);
+
+// plotting the nodal displacement values associated to "FEM_nodeTags" in the "names[0]" model,
+// based on the "full_d_vector".
+void plotUxUy(const std::vector<std::size_t> & FEM_nodeTags, const std::vector<double> & full_d_vector, 
+            const std::vector<std::string> & names);
+
+// computing the elemental-nodal strains and stresses in the FEM domain (dimension "dim" and entity tags "tags"),
+// based on Hooke's matrix in plane stress "H_matrix", Young's modulus "E", Poisson's ratio "nu", looping over the
+// "nbelems" elements contained in "FEM_kinematicsMap".
+// returning the "max_VM_stress" and the corresponding nodetag "max_VM_nodeTag".
+void computeStressStrainElNodal(const int & dim, const std::vector<int> & tags, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           const double nu, const double E, std::map<int, elementData> & FEM_kinematicsMap,
+                           const int & nbelems, double & max_VM_stress, int & max_VM_nodeTag);
+
+// computing the work done by external forces, as the nodal forces are energy consistent, it
+// is sufficient to compute the "externalWork" as the dot product of the nodal displacements
+// "full_d_vector" and the nodal forces "final_nodal_forces".
+void computeWorkDoneByExternalForces(double &externalWork, const std::vector<double> & full_d_vector, 
+                                const std::vector<double> & final_nodal_forces);
+
+// computing the total (internal) strain energy "strain_energy" in the whole FEM domain (dimension "dim" and 
+// entity tags "tags"), using the elementData stored in "FEM_kinematicsMap" gathering the informations for all
+// FEM elements. The Hooke's matrix in plane stress "H_matrix" is used to compute the stresses from the strains.
+// Computed as a sum of integrals over the finite elements, using Gauss integration "integration_rule".
+void computeStrainEnergy(double & strainEnergy, const int & dim, const std::vector<int> & tags,
+                           std::map<int, elementData> & FEM_kinematicsMap, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           const std::string & integration_rule);
+
+//displays the time of the desired code section "function_name", if "display_time" is set as true.
+void displayTime(const double &start, const double &end, const std::string &function_name, const bool &display_time);
 
 /*-------------- FUNCTIONS SPECIFIC TO LINEAR FEM ------------------*/
-void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews);
 
-void assembleKtriplet(const int i, const int el, const std::vector<std::vector<std::size_t>> & nodeTags, const int numNodes, std::map<int, int> & nodeIndexMap, std::list<Eigen::Triplet <double>> & k_tripletList, Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & K_matrix, std::vector<double> & f_vector);
-void assembleKlistVolumicF(const Eigen::Matrix<double, 3, 3> H_matrix, const double rho, const double bx, const double by, const std::string & integration_rule, int & dim, std::vector<int> & tags, std::map<int, int>  & nodeIndexMap, std::vector<std::list<Eigen::Triplet <double>>> & my_k_list, std::vector<std::list<std::pair<int,double>>> & thread_f_vector);
-void fillReducedKf(const std::vector<double> & full_f_vector, const Eigen::SparseMatrix<double> & full_K_matrix, const std::vector<int> & new_DOFindices, const std::vector<double> & dir_BC, Eigen::SparseMatrix<double> & reduced_K_matrix, std::vector<double> & reduced_f_vector, std::list<Eigen::Triplet <double>> & reduced_k_tripletList);
-void computeStressStrainLinearWay(const std::vector<int> & elementTypes, const std::vector<std::vector<std::size_t>> &elementTags, const std::vector<std::vector<std::size_t>> &elnodeTags, const std::vector<double> &full_d_vector, std::vector<std::size_t> & elems2D, const Eigen::Matrix<double, 3, 3> &H_matrix, const double nu, const double E, std::map<int, int> & nodeIndexMap, std::vector<std::vector<double>> & data3, std::vector<std::vector<double>> & data4, std::vector<std::vector<double>> & data5, std::vector<std::vector<double>> & data6, std::vector<std::vector<double>> & data7, std::vector<std::vector<double>> & data8, std::vector<std::vector<double>> & data9, std::vector<std::vector<double>> & data10, int & k);
\ No newline at end of file
+// assembling the full stiffness matrix "full_K_matrix" using first a triplet vector, assembling the volumic part 
+// of the nodal forces "full_f_vector", in the FEM_domain (dimension "dim" and entity tag "tags") using the global
+// node indexation defined by "nodeIndexMap". "H_matrix" is the plane stress Hooke's matrix, "rho" the density of the
+// material, "bx" the volumic force along x, "by" the volumic force along y.
+void assembleKVolumicF(const Eigen::Matrix<double, 3, 3> & H_matrix, const double & rho, const double & bx, const double & by,
+                const int & dim, const std::vector<int> & tags, std::map<int, int> & nodeIndexMap, 
+                Eigen::SparseMatrix<double> & full_K_matrix, std::vector<double> & full_f_vector);
+
+// assembles the elemental "K_matrix" into a vector of triplets "k_tripletList" using 
+// the node tags provided by "nodeTags" vector (index of the element is "elIndex").
+// The element has "numNodes" nodes. "nodeIndexMap" provides the global nodal index corresponding to a given node tag.
+void assembleKtriplet(const int &elIndex, const std::vector<std::size_t> & nodeTags, const int numNodes, 
+                    std::map<int, int> & nodeIndexMap, std::vector<Eigen::Triplet <double>> & k_tripletList,
+                    const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> & K_matrix);
+
+// the "full_f_vector" and "full_K_matrix" are reduced in "reduced_f_vector" and "reduced_K_matrix" respectively,
+// taking into account the dirichlet boundary conditions contained in "dir_BC".
+// "new_DOFindices" gathers the new indices of the DOFs when taking the boundary conditions into account.
+void fillReducedKf(const std::vector<double> & full_f_vector, const Eigen::SparseMatrix<double> & full_K_matrix,
+                const std::vector<int> & new_DOFindices, const std::vector<double> & dir_BC,
+                Eigen::SparseMatrix<double> & reduced_K_matrix, std::vector<double> & reduced_f_vector);
+
+// computing the elemental-nodal strains and stresses in the FEM domain (dimension "dim" and entity tags "tags"),
+// based on Hooke's matrix in plane stress "H_matrix", Young's modulus "E", Poisson's ratio "nu", and the full nodal
+// displacement vector "full_d_vector" and the global nodal index map "nodeIndexMap".
+// "nbelems" is the number of 2D elements contained in the FEM domain.
+// returning the "max_VM_stress" and the corresponding nodetag "max_VM_nodeTag".
+void computeStressStrainLinearWay(const int & dim, const std::vector<int> & tags, const std::vector<double> &full_d_vector,
+                           const Eigen::Matrix<double, 3, 3> &H_matrix, const double &nu, const double &E,
+                           std::map<int, int> & nodeIndexMap, const int &nbelems, double &max_VM_stress, int &max_VM_nodeTag);
+
+// computing the total (internal) strain energy "strain_energy" in the whole FEM domain (dimension "dim" and 
+// entity tags "tags"), using the nodal displacements in "full_d_vector". The nodes are indexed using the "nodeIndexMap".
+// The Hooke's matrix in plane stress "H_matrix" is used to compute the stresses from the strains.
+// Computed as a sum of integrals over the finite elements, using Gauss integration "integration_rule".
+void computeStrainEnergyLinearWay(double & strainEnergy, const int & dim, const std::vector<int> & tags,
+                           const std::vector<double> &full_d_vector, const Eigen::Matrix<double, 3, 3> &H_matrix, 
+                           std::map<int, int> & nodeIndexMap, const std::string & integration_rule);
\ No newline at end of file
diff --git a/srcs/FEM/large_rotation_validation.geo b/srcs/FEM/large_rotation_validation.geo
new file mode 100644
index 0000000000000000000000000000000000000000..113db4e8a52d2345b5b8075dc49a0b23ff2dab77
--- /dev/null
+++ b/srcs/FEM/large_rotation_validation.geo
@@ -0,0 +1,88 @@
+
+h = 1;
+H = 10;
+
+n = 16;
+
+Point(1) = {0, 0, 0, 0.5};
+Point(2) = {0.9*H, 0, 0, 0.5};
+Point(3) = {0.9*H, h, 0, 0.5};
+Point(4) = {0, h, 0, 0.5};
+
+Point(5) = {0.95*H, 0, 0, 0.5};
+Point(6) = {0.95*H, h, 0, 0.5};
+
+Point(7) = {0.95*H, H, 0, 0.5};
+Point(8) = {0.9*H, H, 0, 0.5};
+
+Point(9) = {H, 0, 0, 0.5};
+Point(10) = {H, h, 0, 0.5};
+Point(11) = {H, H, 0, 0.5};
+
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {3, 4};
+Line(4) = {4, 1};
+Curve Loop(1) = {1, 2, 3, 4};
+Plane Surface(1) = {1};
+
+Line(5) = {2, 5};
+Line(6) = {5, 6};
+Line(7) = {6, 3};
+Curve Loop(2) = {5, 6, 7, -2};
+Plane Surface(2) = {2};
+
+Line(8) = {6, 7};
+Line(9) = {7, 8};
+Line(10) = {8, 3};
+Curve Loop(3) = {-7, 8, 9, 10};
+Plane Surface(3) = {3};
+
+Line(11) = {5, 9};
+Line(12) = {9, 10};
+Line(13) = {10, 6};
+Curve Loop(4) = {11, 12, 13, -6};
+Plane Surface(4) = {4};
+
+Line(14) = {10, 11};
+Line(15) = {11, 7};
+Curve Loop(5) = {14, 15, -8, -13};
+Plane Surface(5) = {5};
+
+Transfinite Curve {1, 3, 8, 10, 14} = 18*n+1 Using Progression 1;
+Transfinite Curve {2, 4, 6, 12} = 2*n+1 Using Progression 1;
+Transfinite Curve {5, 7, 9, 11, 13, 15} = n+1 Using Progression 1;
+Transfinite Surface {1};
+Transfinite Surface {2};
+Transfinite Surface {3};
+Transfinite Surface {4};
+Transfinite Surface {5};
+
+Recombine Surface {1};
+Recombine Surface {2};
+Recombine Surface {3};
+Recombine Surface {4};
+Recombine Surface {5};
+
+Physical Curve("left_edge", 1) = {4};
+Physical Surface("FEM_domain", 2) = {1, 2, 3, 4, 5}; // the trick is to include both plane surfaces in one single domain
+Physical Curve("top_edge", 3) = {9, 15};
+
+Physical Point("point_A", 5) = {7};
+
+F = 40000;
+
+// additional parameters given to the solver
+SetNumber("Boundary Conditions/left_edge/ux", 0.); // ALWAYS NEED TO IMPOSE BOTH ux AND uy ON A GIVEN EDGE !! (pas très réaliste, faut y réfléchir)
+SetNumber("Boundary Conditions/left_edge/uy", 0.);
+SetNumber("Materials/FEM_domain/Young", 3e7);
+SetNumber("Materials/FEM_domain/Poisson", 0.3);
+SetNumber("Materials/FEM_domain/rho",7800); //volumic mass of acier
+SetNumber("Boundary Conditions/top_edge/tx", F); // ALWAYS NEED TO IMPOSE BOTH tx AND ty ON A GIVEN EDGE (realiste, OK) !
+SetNumber("Boundary Conditions/top_edge/ty", 0); //set to some other value for vertical deflection
+SetNumber("Volumic Forces/FEM_domain/bx",0.);
+SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
+
+SetNumber("Non_linear_solver",1); // activate non linear solver
+
+Physical Curve("BEM_FEM_boundary", 4) = {4};
\ No newline at end of file
diff --git a/srcs/FEM/large_rotation_validation_single_surface.geo b/srcs/FEM/large_rotation_validation_single_surface.geo
new file mode 100644
index 0000000000000000000000000000000000000000..d15291b19f3553b05de6fcccd5bd78e967e6b1a7
--- /dev/null
+++ b/srcs/FEM/large_rotation_validation_single_surface.geo
@@ -0,0 +1,56 @@
+
+h = 1;
+H = 2;
+
+n = 10;
+
+Point(1) = {0, 0, 0, 0.5};
+Point(2) = {(H-h), 0, 0, 0.5};
+Point(3) = {H-h, h, 0, 0.5};
+Point(4) = {0, h, 0, 0.5};
+
+Point(5) = {H, 0, 0, 0.5};
+Point(6) = {H, h, 0, 0.5};
+
+Point(7) = {H, H, 0, 0.5};
+Point(8) = {H-h, H, 0, 0.5};
+
+Line(1) = {1, 2};
+Line(3) = {3, 4};
+Line(4) = {4, 1};
+
+Line(5) = {2, 5};
+Line(6) = {5, 6};
+
+Line(8) = {6, 7};
+Line(9) = {7, 8};
+Line(10) = {8, 3};
+
+Curve Loop(1) = {1, 5, 6, 8, 9, 10, 3, 4};
+Plane Surface(1) = {1};
+
+Transfinite Curve {1, 3, 8, 10} = (H-h)*n+1 Using Progression 1;
+Transfinite Curve {4, 5, 6, 9} = n+1 Using Progression 1;
+
+Recombine Surface {1};
+
+Physical Curve("left_edge", 1) = {4};
+Physical Surface("FEM_domain", 2) = {1}; // the trick is to include both plane surfaces in one single domain
+Physical Curve("top_edge", 3) = {9};
+
+F = 40000;
+
+// additional parameters given to the solver
+SetNumber("Boundary Conditions/left_edge/ux", 0.); // ALWAYS NEED TO IMPOSE BOTH ux AND uy ON A GIVEN EDGE !! (pas très réaliste, faut y réfléchir)
+SetNumber("Boundary Conditions/left_edge/uy", 0.);
+SetNumber("Materials/FEM_domain/Young", 3e7);
+SetNumber("Materials/FEM_domain/Poisson", 0.3);
+SetNumber("Materials/FEM_domain/rho",7800); //volumic mass of acier
+SetNumber("Boundary Conditions/top_edge/tx", F); // ALWAYS NEED TO IMPOSE BOTH tx AND ty ON A GIVEN EDGE (realiste, OK) !
+SetNumber("Boundary Conditions/top_edge/ty", 0); //set to some other value for vertical deflection
+SetNumber("Volumic Forces/FEM_domain/bx",0.);
+SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
+
+Physical Curve("BEM_FEM_boundary", 4) = {4};//+
+
+Mesh.Algorithm = 8;
diff --git a/srcs/FEM/mainFEM.cpp b/srcs/FEM/mainFEM.cpp
index afa5756ec2b98155936a32737447af80df724c0b..3883e6b5f063b324b5d6f5f445e0dd7ee0f257ad 100644
--- a/srcs/FEM/mainFEM.cpp
+++ b/srcs/FEM/mainFEM.cpp
@@ -4,17 +4,18 @@
 #include <iostream>
 #include <omp.h>
 
+// this program implements a FEM solver, either linear or non-linear (by taking large displacements into account)
+// to choose the linear solver, please add: SetNumber("Non_linear_solver",0); in the .geo file.
 int main(int argc, char **argv)
 {
-
-    bool nonLinearSolver = true; // use non-linear solver or not
-
     if (argc < 2)
     {
         std::cout << "Usage: " << argv[0] << " <geo_file>\n";
         return 0;
     }
 
+    double start = omp_get_wtime();
+
     // If compiled with OpenMP support, gmsh::initialize 
     // also sets the number of threads to "General.NumThreads".
     int nthreads = omp_get_max_threads();
@@ -26,22 +27,32 @@ int main(int argc, char **argv)
 
     Eigen::initParallel();
 
+    // determine if non linear solver must be set
+    bool nonLinearSolver = getNonLinearParameter(); 
+
+    // maps the elementTags to a corresponding electrostaticPressure (only useful for coupled solver)
     std::map<int, double> electrostaticPressure;
 
+    int nbViews = 0; // number of views passed to the BEM solver (only useful for coupled solver)
+
     if(nonLinearSolver)
     {
-        std::map<int,std::pair<double,double>> boundaryDisplacementMap;
+        std::map<int,std::pair<double,double>> boundaryDisplacementMap; //(only useful for coupled solver)
 
-        int viewTagU = gmsh::view::add("u"); // à modifier plus tard
-        int viewTagF = gmsh::view::add("f");
+        int viewTagU = gmsh::view::add("u"); //viewtag of the displacement view
+        int viewTagF = gmsh::view::add("f"); //viewtag of the nodal forces view
 
-        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, 0, true, 1, viewTagU, viewTagF); //iteration randomly set to 1
+        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, true, 1, viewTagU, viewTagF, false);
     }
     else
     {
-        solverFEM(electrostaticPressure, 0);
+        solverFEM(electrostaticPressure, nbViews);
     }
 
+    double total_time = omp_get_wtime() - start;
+    std::cout << "-----------------------------------------\n";
+    std::cout << "total execution time: " << total_time << " [s]. \n";
+
     gmsh::fltk::run();
     
     gmsh::finalize();
diff --git a/srcs/FEM/my_geo.geo b/srcs/FEM/my_geo.geo
index e35f149294f371474652ecb2ff64bd827a7d2ae2..fde90809eae403a3dd4574e691689a4ee1ed5da6 100644
--- a/srcs/FEM/my_geo.geo
+++ b/srcs/FEM/my_geo.geo
@@ -1,7 +1,7 @@
-Lx = 5;
-Ly = 2;
-nx = 5; // prend beaucoup de temps àpd de 200x40
-ny = 2;
+Lx = 2;
+Ly = 1;
+nx = 16; // prend beaucoup de temps àpd de 200x40
+ny = 8;
 
 Point(1) = {0, 0, 0, 0.1};
 Point(2) = {Lx, 0, 0, 0.1};
@@ -21,7 +21,7 @@ Recombine Surface {1}; // quads instead of triangles
 
 Mesh.ElementOrder = 1;
 
-Physical Curve("left_edge", 5) = {4,5};
+Physical Curve("left_edge", 5) = {4};
 Physical Surface("FEM_domain", 6) = {1};
 Physical Curve("top_edge", 7) = {3};
 Physical Curve("right_edge", 8) = {2};
@@ -29,17 +29,17 @@ Physical Point("fixed_node", 9) = {1};
 
 // additional parameters given to the solver
 SetNumber("Boundary Conditions/left_edge/ux", 0.); // HERE YOU DO NOT HAVE TO IMPOSE BOTH ux and uy simultaneously ! (permet aussi de simuler appuis à roulettes)
-//SetNumber("Boundary Conditions/left_edge/uy", 2.);
+//SetNumber("Boundary Conditions/left_edge/uy", 0.);
 SetNumber("Materials/FEM_domain/Young", 210e3);
 SetNumber("Materials/FEM_domain/Poisson", 0.3);
 SetNumber("Materials/FEM_domain/rho",7800); //volumic mass of acier
 SetNumber("Boundary Conditions/top_edge/tx", 0.); // ALWAYS NEED TO IMPOSE BOTH tx AND ty ON A GIVEN EDGE (realiste, OK) !
 SetNumber("Boundary Conditions/top_edge/ty", 0.); //set to some non-zero value to induce vertical deflection
 SetNumber("Boundary Conditions/right_edge/tx", 21e3); // for simple tension conditions
-SetNumber("Boundary Conditions/right_edge/ty", 0.);
-SetNumber("Volumic Forces/FEM_domain/bx",0.);
+SetNumber("Boundary Conditions/right_edge/ty", 0);
+SetNumber("Volumic Forces/FEM_domain/bx",0);
 SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
-SetNumber("Boundary Conditions/fixed_node/uy",0.02);
-//SetNumber("Boundary Conditions/fixed_node/uy",0.);
+//SetNumber("Boundary Conditions/fixed_node/ux",0.);
+SetNumber("Boundary Conditions/fixed_node/uy",2.);
 
 Physical Curve("BEM_FEM_boundary", 10) = {1,2,3};
\ No newline at end of file
diff --git a/srcs/FEM/self_weight.geo b/srcs/FEM/self_weight.geo
index d50925376b3a42a31e2508c7fa480d9ccdfba644..c04a6a8a44f4dd0dc62137b00f36ea44a94cd666 100644
--- a/srcs/FEM/self_weight.geo
+++ b/srcs/FEM/self_weight.geo
@@ -37,4 +37,6 @@ SetNumber("Boundary Conditions/right_edge/ty", 0.);
 SetNumber("Volumic Forces/FEM_domain/bx",0.);
 SetNumber("Volumic Forces/FEM_domain/by",-9.81); //set to -9.81 for gravity
 
-Physical Curve("BEM_FEM_boundary", 9) = {1,2,3}; // useless but necessary to make it work
\ No newline at end of file
+Physical Curve("BEM_FEM_boundary", 9) = {1,2,3}; // useless but necessary to make it work
+
+SetNumber("Non_linear_solver", 1);
\ No newline at end of file
diff --git a/srcs/FEM/simple_tension.geo b/srcs/FEM/simple_tension.geo
index 18783ae0b69b461a559836c84cbd892676cec6a4..f1452e518608936d6c4b17101e93a32c0f296abd 100644
--- a/srcs/FEM/simple_tension.geo
+++ b/srcs/FEM/simple_tension.geo
@@ -1,7 +1,7 @@
 Lx = 5;
 Ly = 2;
-nx = 5;
-ny = 2;
+nx = 50;
+ny = 20;
 
 Point(1) = {0, 0, 0, 1.0};
 Point(2) = {Lx, 0, 0, 1.0};
@@ -39,6 +39,8 @@ SetNumber("Boundary Conditions/right_edge/tx", 21e3); // for simple tension cond
 SetNumber("Boundary Conditions/right_edge/ty", 0.);
 SetNumber("Volumic Forces/FEM_domain/bx",0.);
 SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
-SetNumber("Boundary Conditions/fixed_node/uy",0.);
+SetNumber("Boundary Conditions/fixed_node/uy",2.);
 
 Physical Curve("BEM_FEM_boundary", 10) = {1,2,3}; // useless in this case but necessary to make it work
+
+SetNumber("Non_linear_solver",1);
\ No newline at end of file
diff --git a/srcs/FEM/solverFEM.cpp b/srcs/FEM/solverFEM.cpp
index 7df3c0d51742e28e2a33cfd2ce20f54effba1cbb..97bcda367a82fab7ef26824712b9e056fac5069f 100644
--- a/srcs/FEM/solverFEM.cpp
+++ b/srcs/FEM/solverFEM.cpp
@@ -1,23 +1,35 @@
 #include "functionsFEM.hpp"
 
 #ifdef _MSC_VER
-#include <gmsh.h_cwrap>       // gmsh main header
+#include <gmsh.h_cwrap>
 #else
-#include <gmsh.h>       // gmsh main header
+#include <gmsh.h>
 #endif
 
-#include <iostream>     // for std::cout
+#include <iostream>
 #include <map>
-#include <sstream>  // for std::stringstream
-#include <Eigen/Dense> // Eigen library
-#include <Eigen/Sparse> // Eigen library for sparse matrices
-#include <Eigen/SparseCholesky> // solving sparse linear systems
+#include <sstream>
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+#include <Eigen/SparseCholesky>
 #include <Eigen/Core>
 #include <cmath>
-#include <algorithm> // to sort and merge the FEM node vectors
+#include <algorithm>
 #include <omp.h>
 
-void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<int,std::pair<double,double>> & boundaryDisplacementMap, const int nbViews, bool postProcessing, const int iteration, const int viewTagU, const int viewTagF)
+// solves the non-linear (large displacements, no large deformations) elastic problem.
+// if coupled to the BEM solver, "electrostaticPressure" is the pressure computed from the electric field
+// on the BEM_FEM boundary (mapping element tag -> pressure). "boundaryDisplacementMap" is filled for all
+// nodes on the BEM_FEM_boundary as (node tag -> (u,v) displacement)
+// "nbViews" is the current number of views already allocated in the gmsh window.
+// "postProcessing" boolean activates the post processing operations (must only be computed once at the end of the
+// coupled solver). "iteration" denotes the current iteration of the two-way coupled solver (starting at 1).
+// "viewTagU" and "viewTagF" correspond to the view tags of the nodal displacements and the nodal forces in the gmsh window.
+// when "untangleMesh" is activated, the nodal coordinates of the nodes in the FEM_domain are updated according to
+// their final nodal displacements.
+void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, 
+                    std::map<int,std::pair<double,double>> & boundaryDisplacementMap, int &nbViews, bool postProcessing, 
+                    const int iteration, const int viewTagU, const int viewTagF, bool untangleMesh)
 {
     /*--------------INITIALIZATION OF ITERATIVE ALGORITHM----------------*/
     /* FIRST STEP: 
@@ -26,17 +38,15 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
     - initialize the full d vector with Dirichlet boundary conditions and set pg = 0
     - important remark: in pg we focus only on the free DOFs (we do not focus on the DOFs fixed by dirichlet BCs)*/
 
-    bool openGUI = false;        // Graphical interface of GMSH.
+    bool display_time = false; //displays time of every different step of the algorithm
+    bool validation = false; //retrieves displacement of point A for large_rotation_validation.geo
 
-    //double start = omp_get_wtime();
-    int max_threads = omp_get_max_threads();
+    double start = omp_get_wtime();
 
+    /*--------Integration rule used in the code for surface integration (neumann BC)----------*/
+    std::string integration_rule = "CompositeGauss4"; 
 
-    /*--------Integration rule used in the code----------*/
-    // could be useful to pass it as an argument in the .geo file
-    std::string integration_rule = "CompositeGauss4"; // tested with other methods, OK too.
-
-    /*--------get physical groups--------------*/
+    /*--------get all physical groups--------------*/
     std::map<std::string, std::pair<int, int>> groups;
     gmsh::vectorpair dimTags;
     gmsh::model::getPhysicalGroups(dimTags);
@@ -50,41 +60,16 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
     }
 
     /*--------get nodes related to FEM-----------------*/
-    std::string groupname = "FEM_domain"; // we consider the domain as containing the FEM 2d model
+    std::string groupname = "FEM_domain"; // we consider the FEM_domain as containing the FEM 2d model
     int dim = groups[groupname].first;
     int tag = groups[groupname].second;
+    // Getting entities of the domain to fill FEM_nodeTags
+    std::vector<int> tags;
+    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
 
-    //loop over the entities of the domain to retrieve all nodeTags by taking care not to take some nodes twice
-    //using sort and set_union methods + retrieving the node coordinates and storing them in a map
     std::vector<std::size_t> FEM_nodeTags;
-    std::vector<double> FEM_nodecoord;
-    std::vector<double> FEM_nodeparametricCoord;
     std::map<int,std::pair<double,double>> FEM_nodeCoordsMap; // nodeTag -> (x,y)
-    // Getting entities of the domain to fill FEM_nodeTags, en faire une fonction ?
-    std::vector<int> tags;
-    gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-    std::vector<std::vector<std::size_t>> tmp_nodeTags(tags.size()); // will store the nodeTags associated to one given entity of the domain
-    gmsh::model::mesh::getNodes(tmp_nodeTags[0], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[0], true); 
-    for(std::size_t j = 0; j < tmp_nodeTags[0].size(); j++)
-    {
-        FEM_nodeCoordsMap[tmp_nodeTags[0][j]] = std::pair<double, double>(FEM_nodecoord[3*j], FEM_nodecoord[3*j+1]);
-    }
-    std::sort(tmp_nodeTags[0].begin(), tmp_nodeTags[0].end()); // need to sort the vectors in order to merge them afterwards
-    for (std::size_t i = 1; i < tags.size(); i++)
-    { // in the case the domain contains multiple entities
-        gmsh::model::mesh::getNodes(tmp_nodeTags[i], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[i], true);
-        for(std::size_t j = 0; j < tmp_nodeTags[i].size(); j++)
-        {
-            FEM_nodeCoordsMap[tmp_nodeTags[i][j]] = std::pair<double, double>(FEM_nodecoord[3*j], FEM_nodecoord[3*j+1]);
-        }
-        std::sort(tmp_nodeTags[i].begin(), tmp_nodeTags[i].end());
-        std::set_union(tmp_nodeTags[i-1].begin(), tmp_nodeTags[i-1].end(),
-                       tmp_nodeTags[i].begin(), tmp_nodeTags[i].end(), std::back_inserter(FEM_nodeTags));
-        
-    }
-    if(tags.size() == 1){ // if the domain contains one single entity
-        FEM_nodeTags = tmp_nodeTags[0];
-    }
+    RetrieveFEMNodeTagsAndCoords(FEM_nodeTags, FEM_nodeCoordsMap, dim, tags);
 
     /*-----get elements related to FEM--------------*/
     std::vector<std::size_t> FEM_elementTags;
@@ -92,6 +77,11 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
     // map is initialized, see functionsFEM.hpp for structure of elementData type
     int nbelems = initKinematics(FEM_elementTags, FEM_kinematicsMap, FEM_nodeCoordsMap, dim, tags);
 
+    if(iteration == 1)
+    {
+        std::cout << "The FEM domain contains " << nbelems << " element(s) and " << FEM_nodeTags.size() << " nodes\n";
+    }
+
     /*-------map between nodeTag and index of first nodal displacement associated to the node (second one is the same +1)------*/
     std::map<int, int> nodeIndexMap;
     for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
@@ -102,20 +92,18 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
     }
 
     /*-----------get physical properties of domain----------------------*/
-    std::vector<std::string> keys;
-    gmsh::onelab::getNames(keys, "(Volumic Forces|Materials).+");
     double E = 0; // Young modulus
     double nu = 0; // Poisson ratio
     double rho = 0; // volumic mass
     double bx = 0; // volumic force along x axis
     double by = 0; // volumic force along y axis
-
-    getPhysicalProperties(keys, E, nu, rho, bx, by);
+    getPhysicalProperties(E, nu, rho, bx, by);
 
     /*-----------------H matrix involved in stress computation------------------*/
     Eigen::Matrix<double, 3, 3> H_matrix = computeHmatrix(E, nu);
-    //double startbis = omp_get_wtime();
-    //std::cout << "preliminary: " << startbis-start << "\n";
+    double start2 = omp_get_wtime();
+    std::string step_name = "initialization of global variables";
+    displayTime(start, start2, step_name, display_time);
 
     /*------------computing full f vector------------------------*/
     // we first consider volumic part of the f vector, computed simultaneously with local K matrices
@@ -125,62 +113,44 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
         full_f_vector[i] = 0;
     }
 
-    std::vector<std::list<Eigen::Triplet <double>>> my_k_list(max_threads);
-    std::vector<std::list<std::pair<int,double>>> thread_f_vector(max_threads);
+    // Looping over entities of FEM_dimain and computing local K matrices and volumic f vector
+    fillElementalKandF(H_matrix, rho, bx, by, dim, tags, nodeIndexMap, full_f_vector, FEM_kinematicsMap);
 
-    // Looping over entities and compute local K matrices and volumic f vector
-    fillElementalKandF(H_matrix, rho, bx, by, integration_rule, dim, tags, nodeIndexMap, my_k_list, thread_f_vector, FEM_kinematicsMap);
-
-    for(int i = 0; i < max_threads; i++){
-        std::list<std::pair<int,double>> &tmp_vector = thread_f_vector[i];
-        for(auto &p : tmp_vector) {
-            full_f_vector[p.first] += p.second;
-        }
-    }
-
-    //double start2 = omp_get_wtime();
-    //std::cout << "time for K assembly: " << start2-startbis << "\n";
+    double start3 = omp_get_wtime();
+    step_name = "volumic f and elemental Kl";
+    displayTime(start2, start3, step_name, display_time);
 
 
     /*-----------------BOUNDARY CONDITIONS------------*/
     /*-----------get group_names related to BC's----------------------*/
-    gmsh::onelab::getNames(keys, "(Boundary Conditions).+");
+    std::vector<std::string> BCkeys;
+    gmsh::onelab::getNames(BCkeys, "(Boundary Conditions).+");
     /*-----------first focus on neumann BC's (surface traction) into full_f_vector------------*/
-    includeNeumannBC(keys, integration_rule, nodeIndexMap, groups, full_f_vector);
-
-    //double start3 = omp_get_wtime();
-    //std::cout << "time for neumann: " << start3 - start2 << "\n";
+    includeNeumannBC(BCkeys, integration_rule, nodeIndexMap, groups, full_f_vector);
 
-    /* taking ELECTROSTATIC PRESSURE */
-    if(electrostaticPressure.size() != 0)
+    /* taking ELECTROSTATIC PRESSURE into account */
+    if(electrostaticPressure.size() != 0) // size == 0 if FEM solver used alone
         applyElecPressure(integration_rule, FEM_nodeCoordsMap, nodeIndexMap, groups, electrostaticPressure, full_f_vector);
-    //double start4 = omp_get_wtime();
-    //std::cout << "time for elec pressure: " << start4 - start3 << "\n";
+    double start4 = omp_get_wtime();
+    step_name = "Neumann BC and elec pressure";
+    displayTime(start3, start4, step_name, display_time);
 
     /*------------FOCUS ON DIRICHLET BC'S---------------*/
     // new_DOFindices vector will contain the new indices of the K matrix after the rows/columns corresponding
     // to dirichlet boundary conditions have been removed
     // IN THIS IMPLEMENTATION WE DECIDE TO REMOVE EVERY ROW/COL ASSOCIATED TO DIR. BC's
-    // non-homo. dir BC will induce a correction in the RHS term f of the other rows, while homogeneous not
+    // non-homo. dir BC will induce a correction in the RHS term f of the other rows, while homogeneous not,
     // if the given index has been removed, it will be set to -1 in new_DOFindices
     std::vector<int> new_DOFindices(2*FEM_nodeTags.size());
 
     // dir_BC[index] will contain the dirichlet boundary condition prescribed to this node
     std::vector<double> dir_BC(2*FEM_nodeTags.size());
 
-    // Fill the two vectors defined just above
-    fillDOFindicesDirBC(keys, nodeIndexMap, groups, new_DOFindices, dir_BC);
-
+    // Fills the two vectors defined just above
     int number_removed_lines = 0;
-    for (std::size_t j = 0; j < new_DOFindices.size(); ++j){
-        if(new_DOFindices[j] < 0){ // line has to be removed
-            number_removed_lines++;
-        }
-        else{
-            new_DOFindices[j] -= number_removed_lines;
-        }
-    }
+    fillDOFindicesDirBC(BCkeys, nodeIndexMap, groups, new_DOFindices, dir_BC, number_removed_lines);
 
+    // initializing the full_d_vector with the dirichlet boundary conditions
     std::vector<double> full_d_vector(2*FEM_nodeTags.size());
     for (std::size_t j = 0; j < full_d_vector.size(); ++j){
         if(new_DOFindices[j] < 0){ // line was previously removed due to dirichlet boundary conditions
@@ -190,7 +160,7 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
             full_d_vector[j] = 0;
         }
     }
-    // initializing the applied forces vector (will remain constant) and the global p (p_g) vector
+    // initializing the applied forces vector (will remain constant) and the global p vector (p_g)
     std::vector<double> f_app_vector(2*FEM_nodeTags.size() - number_removed_lines);
     std::vector<double> global_p_vector(2*FEM_nodeTags.size() - number_removed_lines);
     int nb_free_DOFs = 0;
@@ -204,34 +174,36 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
         }
     }
 
-    // computing the norm of the applied forces vector
-    double f_app_norm = 0;
-    for(size_t i = 0; i < f_app_vector.size(); i++)
-    {
-        f_app_norm += f_app_vector[i]*f_app_vector[i];
-    }
-    f_app_norm = sqrt(f_app_norm);
-    std::cout << "f app norm: " << f_app_norm << "\n";
-
-    std::vector<double> global_f_vector(nb_free_DOFs);
-
+    // useful during the iterative process
+    std::vector<double> global_f_vector(nb_free_DOFs); // f_g
     Eigen::Matrix<double, Eigen::Dynamic, 1> residual(nb_free_DOFs, 1);
 
-    double residualNorm = 100000000; // hardcoded and arbitrary
-    double residualTolerance = 2e-12; // empirical
-
-    /*double max_applied_force = 0;
-    for(int i = 0; i < nb_free_DOFs; i++)
+    // useful for the stopping criterion
+    std::vector<double> previousTotalNodalForces(2*FEM_nodeTags.size());
+    std::vector<double> currentTotalNodalForces(2*FEM_nodeTags.size());
+    std::vector<double> relativeDifference(2*FEM_nodeTags.size());
+    double relativeForces = 1e17;
+    double previousRelativeForces = 1e17;
+    double currentMaxNodalForce;
+    for(size_t i = 0; i < 2*FEM_nodeTags.size(); i++)
     {
-        if(abs(f_app_vector[i]) > max_applied_force)
-            max_applied_force = abs(f_app_vector[i]);
+        previousTotalNodalForces[i] = 0;
+        currentTotalNodalForces[i] = 0;
     }
-    std::cout << "max applied force: " << max_applied_force << "\n";*/
+    double residualTolerance = 1e-12; // empirical
+
+    double start5 = omp_get_wtime();
+    step_name = "further initialization of global variables for the iterative algorithm";
+    displayTime(start4, start5, step_name, display_time);
 
 
     /*---------ITERATIVE PART---------------*/
-    int max_number_of_steps = 10; // purely arbitrary
-    for(int step = 0; step < max_number_of_steps; step++)
+    int max_number_of_steps = 200; // can be tuned
+    int step = 0;
+
+    double num_diverged_steps = 0; // stores the number of times the residual has increased between two steps, after 5 times,
+    // we take the assumption it has converged towards an other value
+    for(step = 0; step < max_number_of_steps; step++)
     {
         /*------------STEP 2 of the algorithm----------------*/
         /* 
@@ -240,7 +212,56 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
         - compute the residual = norm(f_g - f_app)*/
 
         /*--------- UPDATING KINEMATICS---------------*/
+        double start_update = omp_get_wtime();
         updateKinematics(FEM_kinematicsMap, full_d_vector, nodeIndexMap, FEM_elementTags);
+        double end_update = omp_get_wtime();
+        step_name = "update kinematics";
+        displayTime(start_update, end_update, step_name, display_time);
+
+
+        // stopping criterion: focussing on the iterative difference of the full nodal forces vector
+        for(size_t i = 0; i < 2*FEM_nodeTags.size(); i++)
+        {
+            previousTotalNodalForces[i] = currentTotalNodalForces[i];
+        }
+        retrieveTotalNodalForces(currentTotalNodalForces, FEM_kinematicsMap, nodeIndexMap, FEM_elementTags);
+        double end_retrieveTotalForces = omp_get_wtime();
+        step_name = "retrieve total nodal forces";
+        displayTime(end_update, end_retrieveTotalForces, step_name, display_time);
+
+        if(step > 1)
+        {
+            previousRelativeForces = relativeForces;
+            relativeForces = 0;
+            currentMaxNodalForce = 0;
+            for(size_t i = 0; i < 2*FEM_nodeTags.size(); i++)
+            {
+                if(previousTotalNodalForces[i] != 0.0)
+                    relativeDifference[i] = abs( (currentTotalNodalForces[i] - previousTotalNodalForces[i]));
+                else
+                    relativeDifference[i] = 0;
+                
+                if(abs(currentTotalNodalForces[i]) > currentMaxNodalForce)
+                    currentMaxNodalForce = abs(currentTotalNodalForces[i]);
+
+                relativeForces += relativeDifference[i]*relativeDifference[i];
+            }
+            if(currentMaxNodalForce > 0)
+                relativeForces = sqrt(relativeForces/(2*FEM_nodeTags.size())/currentMaxNodalForce); // norm made relative
+            else //to avoid division by zero
+                relativeForces = 1e17; 
+            std::cout << "step: " << step << ", relativeForces: " << relativeForces << "\n";
+
+            if(previousRelativeForces < relativeForces) //the current step induces an increase of nodal difference
+            {
+                num_diverged_steps++;
+                if(num_diverged_steps == 5)
+                {
+                    std::cout << "-----------------------------------------\n";
+                    std::cout << "Pay attention, the differential residual has not reached the tolerance of " << residualTolerance << ", it has converged towards: " << relativeForces << ", after " << step <<" steps\n";
+                }
+            }
+        }
 
         /*--------COMPUTING AND ASSEMBLING THE GLOBAL F VECTOR BASED ON PREVIOUS ITERATION-----------*/
         for(int i = 0; i < nb_free_DOFs; i++)
@@ -249,173 +270,217 @@ void solverFEMnonLinear(std::map<int, double> &electrostaticPressure, std::map<i
         }
         assembleGlobalF(global_f_vector, FEM_kinematicsMap, nodeIndexMap, new_DOFindices, FEM_elementTags);
 
-        residualNorm = computeResidualNorm(global_f_vector, f_app_vector, residual);
+        // computing the residual
+        for(size_t i = 0; i < global_f_vector.size(); i++)
+        {
+            residual(i,0) = global_f_vector[i] - f_app_vector[i];
+        }
 
-        std::cout << "residual value: " << residualNorm/f_app_norm << "\n";
+        double end_assembleglobalf = omp_get_wtime();
+        step_name = "assemble global f and residual norm";
+        displayTime(end_retrieveTotalForces, end_assembleglobalf, step_name, display_time);
 
         /*------------STEP 3: EVALUATING THE RESIDUAL, have we converged ??----------*/
-        if (residualNorm/f_app_norm < residualTolerance)
-            break;
+        if ((relativeForces < residualTolerance && step > 0) || num_diverged_steps == 5)
+           break;
 
         /*------------STEP 4: ASSEMBLING THE GLOBAL TANGENT STIFFNESS MATRIX----------*/
         // it is assembled as a sparse matrix
         Eigen::SparseMatrix<double> global_tangent_matrix(nb_free_DOFs, nb_free_DOFs);
         assembleGlobalKg(global_tangent_matrix, FEM_kinematicsMap, nodeIndexMap, new_DOFindices, FEM_elementTags);
 
+        double end_assembleglobalKg = omp_get_wtime();
+        step_name = "assemble global stiffness matrix";
+        displayTime(end_assembleglobalf, end_assembleglobalKg, step_name, display_time);
+
         //std::cout << "global tangent matrix: " << global_tangent_matrix << "\n";
 
         /*-----------STEP 5: SOLVING THE SYSTEM----------*/
         Eigen::Matrix<double, Eigen::Dynamic, 1> global_delta_p(nb_free_DOFs, 1);
         
-        // solve Kg*Deltapg=-res
+        // solve Kg*Deltapg=-res, using a direct sparse Cholesky factorization,
+        // efficient for sparse positive semi-definite matrix
         Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
         solver.compute(global_tangent_matrix);
 
         global_delta_p = solver.solve(-residual);
 
+        double end_solve = omp_get_wtime();
+        step_name = "solving the system";
+        displayTime(end_assembleglobalKg, end_solve, step_name, display_time);
+
         /*----------STEP 6: updating the global p vector and the full d vector of nodal values-----------*/
         for(size_t i = 0; i < global_p_vector.size(); i++)
         {
             global_p_vector[i] += global_delta_p(i,0);
         }
         updateNodalDispVector(full_d_vector, global_p_vector, new_DOFindices);
+
+        double end_updateNodalDisp = omp_get_wtime();
+        step_name = "updating the nodal disp vector";
+        displayTime(end_solve, end_updateNodalDisp, step_name, display_time);
     }
+
+    if(step == max_number_of_steps)
+    {
+        std::cout << "-----------------------------------------\n";
+        std::cout << "Pay attention, the differential residual has not reached the tolerance of " << residualTolerance << ", final value: " << relativeForces << "\n";
+    }
+
+    double start_postPro = omp_get_wtime();
     
     //updating the kinematics according to the results of last iteration
     updateKinematics(FEM_kinematicsMap, full_d_vector, nodeIndexMap, FEM_elementTags);
 
     /*--------------COMPUTING NODAL FORCES-------------*/
     std::vector<double> final_nodal_forces(2*FEM_nodeTags.size());
-    retrieveFinalNodalForces(final_nodal_forces, FEM_kinematicsMap, nodeIndexMap, FEM_elementTags);
-
-    /*--------------RETRIEVING NODAL DISPLACEMENTS ON BEM-FEM BOUNDARY------------*/
-    //those displacements will be sent to the BEM code in the non-linear iterative solver
-    //std::map<int,std::pair<double,double>> boundaryDisplacementMap;
-    // mapping nodeTag (of node on the boundary) into (u,v) displacements of the node
-    retrieveBoundaryDisplacements(boundaryDisplacementMap, full_d_vector, nodeIndexMap, groups);
+    retrieveTotalNodalForces(final_nodal_forces, FEM_kinematicsMap, nodeIndexMap, FEM_elementTags);
 
     std::vector<std::string> names;
     gmsh::model::list(names);
 
+    /*-------------POST PROCESSING---------------------*/
     if(postProcessing)
     {
-        /*--------------REACTION FORCES COMPUTATION------------------*/
-        computeReactionForces(groups, nodeIndexMap, final_nodal_forces, keys);
+        // retrieving and displaying maximal nodal displacement
+        double max_disp = 0;
+        double max_u = 0;
+        double max_v = 0;
+        int max_disp_nodeTag = 0;
 
-        //double start5 = omp_get_wtime();
-        //std::cout << "time for rest: " << start5 - start4 << "\n";
+        for(size_t i = 0; i < FEM_nodeTags.size(); i++)
+        {
+            double tmp_index = nodeIndexMap[FEM_nodeTags[i]];
+            double tmp_disp = full_d_vector[tmp_index]*full_d_vector[tmp_index] + full_d_vector[tmp_index + 1]*full_d_vector[tmp_index + 1];
+            if (tmp_disp > max_disp)
+            {
+                max_disp = tmp_disp;
+                max_disp_nodeTag = FEM_nodeTags[i];
+                max_u = full_d_vector[tmp_index];
+                max_v = full_d_vector[tmp_index + 1];
+            }
+        }
+        std::cout << "-----------------------------------------\n";
+        std::cout << "maximal nodal displacement (u,v) = (" << max_u << "," << max_v << ") [m], at node " << max_disp_nodeTag << "\n";
+
+        /*--------------REACTION FORCES COMPUTATION------------------*/
+        computeReactionForces(groups, nodeIndexMap, final_nodal_forces, BCkeys);
 
         /*--------------PLOTTING NODAL VALUES------------------*/
-        plotUxUy(FEM_nodeTags, full_d_vector, nbViews, names);
+        plotUxUy(FEM_nodeTags, full_d_vector, names);
 
         /*-------------POST PROCESSING---------------*/
-        /*-------------Computing and saving strains/stresses-----------------*/
-
-
-        /*-------------------ELEMENTAL-NODAL VALUES-----------------------*/
-        // éventuellement faire un tableau ici qui regroupe tout le bazar pour ne pas avoir la même ligne 7 fois ...
-        int viewtag3 = gmsh::view::add("nodal_eps_x");
-        int viewtag4 = gmsh::view::add("nodal_eps_y");
-        int viewtag5 = gmsh::view::add("nodal_eps_xy");
-        int viewtag6 = gmsh::view::add("nodal_eps_z");
-        int viewtag7 = gmsh::view::add("nodal_sig_x");
-        int viewtag8 = gmsh::view::add("nodal_sig_y");
-        int viewtag9 = gmsh::view::add("nodal_sig_xy");
-        int viewtag10 = gmsh::view::add("nodal_sig_VM");
-        std::vector<std::vector<double>> data3(nbelems);
-        std::vector<std::vector<double>> data4(nbelems);
-        std::vector<std::vector<double>> data5(nbelems);
-        std::vector<std::vector<double>> data6(nbelems);
-        std::vector<std::vector<double>> data7(nbelems);
-        std::vector<std::vector<double>> data8(nbelems);
-        std::vector<std::vector<double>> data9(nbelems);
-        std::vector<std::vector<double>> data10(nbelems);
-        std::vector<std::size_t> elems2D(nbelems);
-
-        std::vector<int> elementTypes;
-        std::vector<std::vector<std::size_t>> elementTags;
-        std::vector<std::vector<std::size_t>> elnodeTags;
-        
-        // computing the elemental nodal data for each physical group of the domain
-        int k = 0; // current index of data vectors, k is incremented in computeStressStrainElNodal at each element
-        for(std::size_t i=0; i< tags.size(); ++i)
-        {
-            gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
-            computeStressStrainElNodal(elementTypes, elementTags, elnodeTags, elems2D, H_matrix, 
-                                        nu, E, FEM_kinematicsMap, data3, data4, data5, data6, data7, data8, data9, data10, k);
-        }
-
-        gmsh::view::addModelData(viewtag3, 0, names[0], "ElementNodeData",
-                                    elems2D, data3, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag4, 0, names[0], "ElementNodeData",
-                                    elems2D, data4, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag5, 0, names[0], "ElementNodeData",
-                                    elems2D, data5, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag6, 0, names[0], "ElementNodeData",
-                                    elems2D, data6, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag7, 0, names[0], "ElementNodeData",
-                                    elems2D, data7, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag8, 0, names[0], "ElementNodeData",
-                                    elems2D, data8, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag9, 0, names[0], "ElementNodeData",
-                                    elems2D, data9, 1);  // the last ,1 is important!
-        gmsh::view::addModelData(viewtag10, 0, names[0], "ElementNodeData",
-                                    elems2D, data10, 1);  // the last ,1 is important!
-    }
-    // representing vector displacement field and nodal forces
-    //int viewTagU = gmsh::view::add("u");
-    //int viewTagF = gmsh::view::add("f");
-    std::vector<std::vector<double>> data11(FEM_nodeTags.size());
-    std::vector<std::vector<double>> data12(FEM_nodeTags.size());
+        /*-------------Computing and saving elemental-nodal strains/stresses-----------------*/
+        double max_VM_stress = 0;
+        int max_VM_nodeTag;
+        computeStressStrainElNodal(dim, tags, H_matrix, nu, E, FEM_kinematicsMap, nbelems, max_VM_stress, max_VM_nodeTag);
+        std::cout << "-----------------------------------------\n";
+        std::cout << "maximal nodal von Mises stress: " << max_VM_stress << " [Pa], at node " << max_VM_nodeTag << "\n";
+
+        // retrieving work done by external forces
+        double externalWork = 0;
+        computeWorkDoneByExternalForces(externalWork, full_d_vector, final_nodal_forces);
+        std::cout << "-----------------------------------------\n";
+        std::cout << "work done by external forces: " << externalWork << " [J/m].\n";
+
+        // strain energy
+        double strainEnergy = 0;
+        computeStrainEnergy(strainEnergy, dim, tags, FEM_kinematicsMap, H_matrix, integration_rule);
+        // peut etre pas OK en non-linear -> repartir des local displacements pour calculer tout ça
+
+        std::cout << "-----------------------------------------\n";
+        std::cout << "strain energy: " << strainEnergy << " [J/m].\n";
+
+        std::cout << "-----------------------------------------\n";
+        std::cout << "Total potential energy: " << strainEnergy - externalWork << " [J/m].\n";
+    }
+    // representing vector displacement field and nodal forces as vectorial quantities
+    std::vector<std::vector<double>> dataU(FEM_nodeTags.size());
+    std::vector<std::vector<double>> dataF(FEM_nodeTags.size());
     for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
     {
-        data11[i].resize(3);
-        data12[i].resize(3);
-        data11[i][0] = full_d_vector[2*i]; //ux, here use NodeIndexMap
-        data11[i][1] = full_d_vector[2*i+1]; //uy
-        data11[i][2] = 0.; //uz
-        data12[i][0] = final_nodal_forces[2*i]; //fx
-        data12[i][1] = final_nodal_forces[2*i+1]; //fy
-        data12[i][2] = 0.; //fz
+        dataU[i].resize(3);
+        dataF[i].resize(3);
+        dataU[i][0] = full_d_vector[2*i]; //ux, here use NodeIndexMap
+        dataU[i][1] = full_d_vector[2*i+1]; //uy
+        dataU[i][2] = 0.; //uz
+        dataF[i][0] = final_nodal_forces[2*i]; //fx
+        dataF[i][1] = final_nodal_forces[2*i+1]; //fy
+        dataF[i][2] = 0.; //fz
     }
 
     gmsh::view::addModelData(viewTagU, iteration, names[0], "NodeData",
-                             FEM_nodeTags, data11, iteration); //independent of time here
+                             FEM_nodeTags, dataU, iteration); 
     gmsh::view::addModelData(viewTagF, iteration, names[0], "NodeData",
-                             FEM_nodeTags, data12, iteration); //independent of time here
+                             FEM_nodeTags, dataF, iteration); 
 
 
     if(postProcessing)
     {
-        // empeche que tout se plot l'un sur l'autre
-        int nb_views = 12 + nbViews; //hardcoded
-        for( int i = 0; i < nb_views; ++i){
+        nbViews = 12 + nbViews; // FEM code adds 12 views
+        // avoiding that all the views are superposed
+        for( int i = 0; i < nbViews; ++i){
             std::string my_string = "View[" + std::to_string(i) + "].Visible";
             gmsh::option::setNumber(my_string, 0);
         }
-        gmsh::option::setNumber("View[0].VectorType", 5); // plot automatiquement sous forme de déplacement
-        gmsh::option::setNumber("View[0].RangeType", 3); // abscisses par step
+        gmsh::option::setNumber("View[0].VectorType", 5); // plot the displacement in deformed configuration
+        gmsh::option::setNumber("View[0].RangeType", 3);
     }
 
+    double end_postPro = omp_get_wtime();
+    step_name = "post processing";
+    displayTime(start_postPro, end_postPro, step_name, display_time);
 
-    if(openGUI && postProcessing)
-        gmsh::fltk::run(); // opens the gmsh window
-}
-
+    /*--------------RETRIEVING NODAL DISPLACEMENTS ON BEM-FEM BOUNDARY------------*/
+    // those displacements will be sent to the BEM code in the non-linear iterative solver
+    // mapping nodeTag (of node on the boundary) into (u,v) displacements of the node
+    retrieveBoundaryDisplacements(boundaryDisplacementMap, full_d_vector, nodeIndexMap, groups);
 
-void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
-{
-    /*--------------INIT----------------*/
+    // if mesh untangler is activated, all nodal coordinates are updated according to their final
+    // nodal displacements. It is useful when coupled to the BEM solver in order to untangle
+    // the BEM domain and compute the potential field in the whole BEM domain adapted to the
+    // displacement of the FEM domain.
+    if(untangleMesh)
+    {
+        for(size_t i = 0; i < FEM_nodeTags.size(); i++)
+        {
+            std::vector<double> coord, parametricCoord;
+            int dim, tag;
+            gmsh::model::mesh::getNode(FEM_nodeTags[i], coord, parametricCoord, dim, tag);
+            std::vector<double> total_disp = {coord[0] + full_d_vector[2*i], coord[1] + full_d_vector[2*i + 1], coord[2]};
+            gmsh::model::mesh::setNode(FEM_nodeTags[i], total_disp, {});
+        }
+    }
 
-    bool openGUI = false;        // Graphical interface of GMSH.
+    // it is only useful when using "large_rotation_validation.geo" file.
+    // printing the displacement of "point A" (see report for graph).
+    if(validation)
+    {
+        std::string groupname = "point_A";
+        int dim = groups[groupname].first;
+        int tag = groups[groupname].second;
+        std::vector<int> tags;
+        gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
+        std::vector<std::size_t> A_nodeTag;
+        std::vector<double> A_nodecoord;
+        std::vector<double> A_nodeparametricCoord;
+        gmsh::model::mesh::getNodes(A_nodeTag, A_nodecoord, A_nodeparametricCoord, dim, tags[0], true); 
+        std::cout << "-----------------------------------------\n";
+        std::cout << "point A displacement: u = " << full_d_vector[nodeIndexMap[A_nodeTag[0]]] << ", v = " << full_d_vector[nodeIndexMap[A_nodeTag[0]] + 1] << "\n";
+    }
+}
 
-    //double start = omp_get_wtime();
-    int max_threads = omp_get_max_threads();
+// solves the linear elastic problem in the FEM domain.
+// "electrostaticPressure" contains the pressure resulting from the electric field computation on the 
+// BEM_FEM_boundary. "nbViews" is the current number of views already allocated in the gmsh window.
+void solverFEM(std::map<int, double> &electrostaticPressure, int &nbViews)
+{
+    /*--------Integration rule used in the code for surface integration (neumann BC)----------*/
+    std::string integration_rule = "CompositeGauss4";
 
+    bool display_time = false; //displays the time performance of the different parts of the code
 
-    /*--------Integration rule used in the code----------*/
-    // could be useful to pass it as an argument in the .geo file
-    std::string integration_rule = "CompositeGauss4"; // tested with other methods, OK too.
+    double start_init = omp_get_wtime();
 
     /*--------get physical groups--------------*/
     std::map<std::string, std::pair<int, int>> groups;
@@ -435,58 +500,41 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
     int dim = groups[groupname].first;
     int tag = groups[groupname].second;
 
-    //loop over the entities of the domain to retrieve all nodeTags by taking care not to take some nodes twice
-    //using sort and set_union methods
-    std::vector<std::size_t> FEM_nodeTags;
-    std::vector<double> FEM_nodecoord;
-    std::vector<double> FEM_nodeparametricCoord;
-    // Getting entities of the domain to fill FEM_nodeTags, en faire une fonction ?
+    // Getting entities of the domain to fill FEM_nodeTags
     std::vector<int> tags;
     gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-    std::vector<std::vector<std::size_t>> tmp_nodeTags(tags.size()); // will store the nodeTags associated to one given entity of the domain
-    gmsh::model::mesh::getNodes(tmp_nodeTags[0], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[0], true); 
-    std::sort(tmp_nodeTags[0].begin(), tmp_nodeTags[0].end()); // need to sort the vectors in order to merge them afterwards
-    for (std::size_t i = 1; i < tags.size(); i++)
-    { // in the case the domain contains multiple entities
-        gmsh::model::mesh::getNodes(tmp_nodeTags[i], FEM_nodecoord, FEM_nodeparametricCoord, dim, tags[i], true);
-        std::sort(tmp_nodeTags[i].begin(), tmp_nodeTags[i].end());
-        std::set_union(tmp_nodeTags[i-1].begin(), tmp_nodeTags[i-1].end(),
-                       tmp_nodeTags[i].begin(), tmp_nodeTags[i].end(), std::back_inserter(FEM_nodeTags));
-        
-    }
-    if(tags.size() == 1){ // if the domain contains one single entity
-        FEM_nodeTags = tmp_nodeTags[0];
-    }
 
-    
+    std::vector<std::size_t> FEM_nodeTags;
+    std::map<int,std::pair<double,double>> FEM_nodeCoordsMap; // nodeTag -> (x,y) (useless in this linear case)
+    RetrieveFEMNodeTagsAndCoords(FEM_nodeTags, FEM_nodeCoordsMap, dim, tags);
 
     /*-------map between nodeTag and index of first nodal displacement associated to the node (second one is the same +1)------*/
     std::map<int, int> nodeIndexMap;
     for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
     {
-        int nodeTag = FEM_nodeTags[i];// use i à la place de nodeTag pour traiter cas ou le nodeTag n'est pas une suite continue
+        int nodeTag = FEM_nodeTags[i];
         int node_first_index = 2*i; 
         nodeIndexMap[nodeTag] = node_first_index;
     }
 
     /*-----------get physical properties of domain----------------------*/
-    std::vector<std::string> keys;
-    gmsh::onelab::getNames(keys, "(Volumic Forces|Materials).+");
     double E = 0; // Young modulus
     double nu = 0; // Poisson ratio
     double rho = 0; // volumic mass
     double bx = 0; // volumic force along x axis
     double by = 0; // volumic force along y axis
-
-    getPhysicalProperties(keys, E, nu, rho, bx, by);
+    getPhysicalProperties(E, nu, rho, bx, by);
 
     /*-----------------H matrix involved in stress computation------------------*/
     Eigen::Matrix<double, 3, 3> H_matrix = computeHmatrix(E, nu);
-    //double startbis = omp_get_wtime();
-    //std::cout << "preliminary: " << startbis-start << "\n";
+
+    double end_init = omp_get_wtime();
+    std::string step_name = "initialization";
+    displayTime(start_init, end_init, step_name, display_time);
 
     /*------------computing K matrix and f vector------------------------*/
     // we first consider the K matrix and the volumic part of the f vector
+    // K matrix declared as sparse matrix for efficiency.
     Eigen::SparseMatrix<double> full_K_matrix(2*FEM_nodeTags.size(),2*FEM_nodeTags.size());
     std::vector<double> full_f_vector(2*FEM_nodeTags.size());
     for (size_t i = 0; i < full_f_vector.size(); i++)
@@ -494,72 +542,30 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
         full_f_vector[i] = 0;
     }
 
-    std::vector<std::list<Eigen::Triplet <double>>> my_k_list(max_threads);
-    std::vector<std::list<std::pair<int,double>>> thread_f_vector(max_threads);
-
-    // Looping over entities and compute full K (under tripletlist form) and F
-    assembleKlistVolumicF(H_matrix, rho, bx, by, integration_rule, dim, tags, nodeIndexMap, my_k_list, thread_f_vector);
-
-
-    std::list<Eigen::Triplet <double>> k_tripletList = my_k_list[0];
-
-    if(max_threads > 1)
-    {
-        for (int i = 1; i < max_threads; i++)
-        {
-            k_tripletList.insert(k_tripletList.end(), my_k_list[i].begin(), my_k_list[i].end());
-        }
-    }
-    full_K_matrix.setFromTriplets(k_tripletList.begin(), k_tripletList.end());
-    for(int i = 0; i < max_threads; i++){
-        std::list<std::pair<int,double>> &tmp_vector = thread_f_vector[i];
-        for(auto &p : tmp_vector) {
-            full_f_vector[p.first] += p.second;
-        }
-    }
-
-    //double start2 = omp_get_wtime();
-    //std::cout << "time for K assembly: " << start2-startbis << "\n";
+    // Looping over entities and compute full K and volumic F
+    assembleKVolumicF(H_matrix, rho, bx, by, dim, tags, nodeIndexMap, full_K_matrix, full_f_vector);
 
+    double end_assembleK = omp_get_wtime();
+    step_name = "K assembly";
+    displayTime(end_init, end_assembleK, step_name, display_time);
+    
 
     /*-----------------BOUNDARY CONDITIONS------------*/
     /*-----------get group_names related to BC's----------------------*/
-    gmsh::onelab::getNames(keys, "(Boundary Conditions).+");
+    std::vector<std::string> BCkeys;
+    gmsh::onelab::getNames(BCkeys, "(Boundary Conditions).+");
     /*-----------first focus on neumann BC's (surface traction) into full_f_vector------------*/
-    includeNeumannBC(keys, integration_rule, nodeIndexMap, groups, full_f_vector);
-
-    //double start3 = omp_get_wtime();
-    //std::cout << "time for neumann: " << start3 - start2 << "\n";
+    includeNeumannBC(BCkeys, integration_rule, nodeIndexMap, groups, full_f_vector);
 
     /* ELECTROSTATIC PRESSURE */
-    if(electrostaticPressure.size() != 0)
+    if(electrostaticPressure.size() != 0) // size is only greater than zero if there was already a BEM solver
     {
-        std::string groupnameBoundary = "BEM_FEM_boundary";
-        int dimBoundary = groups[groupnameBoundary].first;
-        int tagBoundary = groups[groupnameBoundary].second;
-        std::vector<int> tagsBoundary;
-        gmsh::model::getEntitiesForPhysicalGroup(dimBoundary, tagBoundary, tagsBoundary);
-        std::vector<int> elementTypes;
-        std::vector<std::vector<std::size_t>> elementTags;
-        std::vector<std::vector<std::size_t>> elnodeTags;
-
-        std::map<int,std::pair<double,double>> nodeCoordsMap;
-        //filling the map with : nodeTag -> (x,y)
-        for(std::size_t i=0; i< tags.size(); ++i)
-        {
-            std::vector<std::size_t> entity_nodeTags;
-            std::vector<double> entity_nodecoord;
-            std::vector<double> entity_nodeparametricCoord;
-            gmsh::model::mesh::getNodes(entity_nodeTags, entity_nodecoord, entity_nodeparametricCoord, dim, tags[i], true); 
-            for ( std::size_t j=0; j < entity_nodeTags.size(); j++){
-                nodeCoordsMap[entity_nodeTags[j]] = std::pair<double, double>(entity_nodecoord[3*j], entity_nodecoord[3*j+1]);
-            }
-        }
-        applyElecPressure(integration_rule, nodeCoordsMap, nodeIndexMap, groups, electrostaticPressure, full_f_vector);
+        applyElecPressure(integration_rule, FEM_nodeCoordsMap, nodeIndexMap, groups, electrostaticPressure, full_f_vector);
     }
-        
-    //double start4 = omp_get_wtime();
-    //std::cout << "time for elec pressure: " << start4 - start3 << "\n";
+
+    double end_neumannBC = omp_get_wtime();
+    step_name = "neumann BC and elec pressure";
+    displayTime(end_assembleK, end_neumannBC, step_name, display_time);
 
     /*------------FOCUS ON DIRICHLET BC'S---------------*/
     // new_DOFindices vector will contain the new indices of the K matrix after the rows/columns corresponding
@@ -573,29 +579,23 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
     std::vector<double> dir_BC(2*FEM_nodeTags.size());
 
     // Fill the two vectors defined just above
-    fillDOFindicesDirBC(keys, nodeIndexMap, groups, new_DOFindices, dir_BC);
-
     int number_removed_lines = 0;
-    for (std::size_t j = 0; j < new_DOFindices.size(); ++j){
-        if(new_DOFindices[j] < 0){ // line has to be removed
-            number_removed_lines++;
-        }
-        else{
-            new_DOFindices[j] -= number_removed_lines;
-        }
-    }
+    fillDOFindicesDirBC(BCkeys, nodeIndexMap, groups, new_DOFindices, dir_BC, number_removed_lines);
 
-    //double start3 = omp_get_wtime();
-    //std::cout << "time for boundary conditions: " << start3 - start2 << "\n";
+    double end_dirichletBC = omp_get_wtime();
+    step_name = "dirichlet BC";
+    displayTime(end_neumannBC, end_dirichletBC, step_name, display_time);
 
     /*------------FILLING THE REDUCED K MATRIX AND F VECTOR--------------*/
-    //the correction term on the f vector comes from the "FEM" theoretical course (JP Ponthot), Chap2 Slide 38/50
+    //the correction term on the f vector comes from the "Finite Element Method" theoretical course (JP Ponthot, ULiege), Chap2 Slide 38/50
     Eigen::SparseMatrix<double> reduced_K_matrix(2*FEM_nodeTags.size() - number_removed_lines,2*FEM_nodeTags.size() - number_removed_lines);
     std::vector<double> reduced_f_vector(2*FEM_nodeTags.size() - number_removed_lines);
 
-    std::list<Eigen::Triplet <double>> reduced_k_tripletList;
+    fillReducedKf(full_f_vector, full_K_matrix, new_DOFindices, dir_BC, reduced_K_matrix, reduced_f_vector);
 
-    fillReducedKf(full_f_vector, full_K_matrix, new_DOFindices, dir_BC, reduced_K_matrix, reduced_f_vector, reduced_k_tripletList);
+    double end_reducedFilling = omp_get_wtime();
+    step_name = "filling reduced K and f";
+    displayTime(end_dirichletBC, end_reducedFilling, step_name, display_time);
 
     /*--------------SOLVING THE REDUCED SYSTEM--------------------*/
     Eigen::VectorXd final_reduced_d(2*FEM_nodeTags.size() - number_removed_lines);
@@ -606,14 +606,14 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
     }
 
     // solve Kd=f
-    Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
+    Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
     solver.compute(reduced_K_matrix);
 
     final_reduced_d = solver.solve(final_reduced_f);
 
-    //double start4 = omp_get_wtime();
-    //std::cout << "time to solve system: " << start4 -start3 << "\n";
-
+    double end_solveSystem = omp_get_wtime();
+    step_name = "solving the linear system";
+    displayTime(end_reducedFilling, end_solveSystem, step_name, display_time);
 
     /*-----------RECONSTRUCTING FULL NODAL VALUES--------------*/
     std::vector<double> full_d_vector(2*FEM_nodeTags.size());
@@ -640,21 +640,19 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
         nodal_forces[i] = nodalForces(i);
     }
 
-    /*--------------REACTION FORCES COMPUTATION------------------*/
-    computeReactionForces(groups, nodeIndexMap, nodal_forces, keys);
-
-    //double start5 = omp_get_wtime();
-    //std::cout << "time for rest: " << start5 - start4 << "\n";
+    double end_reconstructing = omp_get_wtime();
+    step_name = "reconstructing full nodal disp and forces";
+    displayTime(end_solveSystem, end_reconstructing, step_name, display_time);
 
     /*--------------PLOTTING AND SAVING NODAL VALUES------------------*/
     std::vector<std::string> names;
     gmsh::model::list(names);
-    plotUxUy(FEM_nodeTags, full_d_vector, nbViews, names);
+    plotUxUy(FEM_nodeTags, full_d_vector, names);
 
     /*-------------POST PROCESSING---------------*/
     /*-------------Computing and saving strains/stresses-----------------*/
 
-    groupname = "FEM_domain"; // we consider the domain as containing the FEM 2d model
+    groupname = "FEM_domain"; // we consider the FEM domain as containing the FEM 2d model
     dim = groups[groupname].first;
     tag = groups[groupname].second;
     gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
@@ -673,90 +671,86 @@ void solverFEM(std::map<int, double> &electrostaticPressure, const int nbViews)
         }
     }
 
+    std::cout << "The FEM domain contains " << nbelems << " element(s) and " << FEM_nodeTags.size() << " nodes\n";
 
-    /*-------------------ELEMENTAL-NODAL VALUES-----------------------*/
-    // éventuellement faire un tableau ici qui regroupe tout le bazar pour ne pas avoir la même ligne 7 fois ...
-    int viewtag3 = gmsh::view::add("nodal_eps_x");
-    int viewtag4 = gmsh::view::add("nodal_eps_y");
-    int viewtag5 = gmsh::view::add("nodal_2eps_xy");
-    int viewtag6 = gmsh::view::add("nodal_eps_z");
-    int viewtag7 = gmsh::view::add("nodal_sig_x");
-    int viewtag8 = gmsh::view::add("nodal_sig_y");
-    int viewtag9 = gmsh::view::add("nodal_sig_xy");
-    int viewtag10 = gmsh::view::add("nodal_sig_VM");
-    std::vector<std::vector<double>> data3(nbelems);
-    std::vector<std::vector<double>> data4(nbelems);
-    std::vector<std::vector<double>> data5(nbelems);
-    std::vector<std::vector<double>> data6(nbelems);
-    std::vector<std::vector<double>> data7(nbelems);
-    std::vector<std::vector<double>> data8(nbelems);
-    std::vector<std::vector<double>> data9(nbelems);
-    std::vector<std::vector<double>> data10(nbelems);
-    std::vector<std::size_t> elems2D(nbelems);
-    
-    // computing the elemental nodal data for each physical group of the domain
-    int k = 0; // current index of data vectors, k is incremented in Compute_Stress_Strain_Elemental_Nodal at each element
-    for(std::size_t i=0; i< tags.size(); ++i)
-    {
-        gmsh::model::mesh::getElements(elementTypes, elementTags, elnodeTags, dim, tags[i]);
-        computeStressStrainLinearWay(elementTypes, elementTags, elnodeTags, full_d_vector, elems2D, H_matrix, 
-                                    nu, E, nodeIndexMap, data3, data4, data5, data6, data7, data8, data9, data10, k);
-    }
+    // retrieving and displaying maximal nodal displacement
+        double max_disp = 0;
+        double max_u = 0;
+        double max_v = 0;
+        int max_disp_nodeTag = 0;
 
-    gmsh::view::addModelData(viewtag3, 0, names[0], "ElementNodeData",
-                                elems2D, data3, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag4, 0, names[0], "ElementNodeData",
-                                elems2D, data4, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag5, 0, names[0], "ElementNodeData",
-                                elems2D, data5, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag6, 0, names[0], "ElementNodeData",
-                                elems2D, data6, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag7, 0, names[0], "ElementNodeData",
-                                elems2D, data7, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag8, 0, names[0], "ElementNodeData",
-                                elems2D, data8, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag9, 0, names[0], "ElementNodeData",
-                                elems2D, data9, 1);  // the last ,1 is important!
-    gmsh::view::addModelData(viewtag10, 0, names[0], "ElementNodeData",
-                                elems2D, data10, 1);  // the last ,1 is important!
+        for(size_t i = 0; i < FEM_nodeTags.size(); i++)
+        {
+            double tmp_index = nodeIndexMap[FEM_nodeTags[i]];
+            double tmp_disp = full_d_vector[tmp_index]*full_d_vector[tmp_index] + full_d_vector[tmp_index + 1]*full_d_vector[tmp_index + 1];
+            if (tmp_disp > max_disp)
+            {
+                max_disp = tmp_disp;
+                max_disp_nodeTag = FEM_nodeTags[i];
+                max_u = full_d_vector[tmp_index];
+                max_v = full_d_vector[tmp_index + 1];
+            }
+        }
+        std::cout << "-----------------------------------------\n";
+        std::cout << "maximal nodal displacement (u,v) = (" << max_u << "," << max_v << ") [m], at node " << max_disp_nodeTag << "\n";
+
+    /*--------------REACTION FORCES COMPUTATION------------------*/
+    computeReactionForces(groups, nodeIndexMap, nodal_forces, BCkeys);
+
+    /*-------------------ELEMENTAL-NODAL VALUES-----------------------*/
+    double max_VM_stress = 0;
+    int max_VM_nodeTag;
+    computeStressStrainLinearWay(dim, tags, full_d_vector, H_matrix, nu, E, nodeIndexMap, nbelems, max_VM_stress, max_VM_nodeTag);
+    std::cout << "-----------------------------------------\n";
+    std::cout << "maximal nodal von Mises stress: " << max_VM_stress << " [Pa], at node " << max_VM_nodeTag << "\n";
 
     // representing vector displacement field and nodal forces
-    int viewtag11 = gmsh::view::add("u");
-    int viewtag12 = gmsh::view::add("f");
+    int viewTagU = gmsh::view::add("u");
+    int viewTagF = gmsh::view::add("f");
     int nodeIndex;
-    std::vector<std::vector<double>> data11(FEM_nodeTags.size());
-    std::vector<std::vector<double>> data12(FEM_nodeTags.size());
+    std::vector<std::vector<double>> dataU(FEM_nodeTags.size());
+    std::vector<std::vector<double>> dataF(FEM_nodeTags.size());
     for (std::size_t i = 0; i < FEM_nodeTags.size(); ++i)
     {
         nodeIndex = nodeIndexMap[FEM_nodeTags[i]];
-        data11[i].resize(3);
-        data12[i].resize(3);
-        data11[i][0] = full_d_vector[nodeIndex]; //ux
-        data11[i][1] = full_d_vector[nodeIndex+1]; //uy
-        data11[i][2] = 0.; //uz
-        data12[i][0] = nodal_forces[nodeIndex]; //fx
-        data12[i][1] = nodal_forces[nodeIndex+1]; //fy
-        data12[i][2] = 0.; //fz
-    }
-
-    gmsh::view::addModelData(viewtag11, 0, names[0], "NodeData",
-                             FEM_nodeTags, data11); //independent of time here
-    gmsh::view::addModelData(viewtag12, 0, names[0], "NodeData",
-                             FEM_nodeTags, data12); //independent of time here
-
-
-
-    // empeche que tout se plot l'un sur l'autre
-    int nb_views = 12 + nbViews; //hardcoded
+        dataU[i].resize(3);
+        dataF[i].resize(3);
+        dataU[i][0] = full_d_vector[nodeIndex]; //ux
+        dataU[i][1] = full_d_vector[nodeIndex+1]; //uy
+        dataU[i][2] = 0.; //uz
+        dataF[i][0] = nodal_forces[nodeIndex]; //fx
+        dataF[i][1] = nodal_forces[nodeIndex+1]; //fy
+        dataF[i][2] = 0.; //fz
+    }
+
+    gmsh::view::addModelData(viewTagU, 0, names[0], "NodeData",
+                             FEM_nodeTags, dataU); //independent of time here
+    gmsh::view::addModelData(viewTagF, 0, names[0], "NodeData",
+                             FEM_nodeTags, dataF); //independent of time here
+
+    int nb_views = 12 + nbViews; //FEM code adds 12 views
     for( int i = 0; i < nb_views; ++i){
-        std::string my_string = "View[" + std::to_string(i) + "].Visible";
+        std::string my_string = "View[" + std::to_string(i) + "].Visible"; // avoids that all views are represented on top of each other
         gmsh::option::setNumber(my_string, 0);
     }
 
-    //double start6 = omp_get_wtime();
-    //std::cout << "time for saving results: " << start6 - start5 << "\n";
+    // retrieving work done by external forces
+    double externalWork = 0;
+    computeWorkDoneByExternalForces(externalWork, full_d_vector, nodal_forces);
+    std::cout << "-----------------------------------------\n";
+    std::cout << "work done by external forces: " << externalWork << " [J/m].\n";
+
+    // strain energy
+    double strainEnergy = 0;
+    computeStrainEnergyLinearWay(strainEnergy, dim, tags, full_d_vector, H_matrix, nodeIndexMap, integration_rule);
+
+    std::cout << "-----------------------------------------\n";
+    std::cout << "strain energy: " << strainEnergy << " [J/m].\n";
 
+    std::cout << "-----------------------------------------\n";
+    std::cout << "Total potential energy: " << strainEnergy - externalWork << " [J/m].\n";
 
-    if(openGUI)
-        gmsh::fltk::run(); // opens the gmsh window
+    double end_postPro = omp_get_wtime();
+    step_name = "post processing";
+    displayTime(end_reconstructing, end_postPro, step_name, display_time);
 }
\ No newline at end of file
diff --git a/srcs/FEM/uniform_charge.geo b/srcs/FEM/uniform_charge.geo
index 1b19a8ee9cef22b003fa155be8fb51442f9bf7ea..930e4410c83958dd777d5c1f19e42af13acb4e13 100644
--- a/srcs/FEM/uniform_charge.geo
+++ b/srcs/FEM/uniform_charge.geo
@@ -38,3 +38,5 @@ SetNumber("Volumic Forces/FEM_domain/bx",0.);
 SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
 
 Physical Curve("BEM_FEM_boundary", 9) = {1,2,3};
+
+SetNumber("Non_linear_solver", 1);
\ No newline at end of file
diff --git a/srcs/FoldedFlexureBeam.geo b/srcs/FoldedFlexureBeam.geo
new file mode 100644
index 0000000000000000000000000000000000000000..1d71824d2c4a7997b4f1c1ae6c3182f5c3a7636b
--- /dev/null
+++ b/srcs/FoldedFlexureBeam.geo
@@ -0,0 +1,293 @@
+scale = 1e-6;
+
+nBEM = 10; // BEM element density (mettre ça dans quatrième coordonnée)
+
+nFEM = 0.5; // FEM element density
+
+phi = 100;
+SetNumber("Boundary Conditions/BEM_FEM_boundary/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/top_electrode/BEM_domain_1/dirichlet", phi);
+SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+// mechanical properties and boundary conditions
+SetNumber("Boundary Conditions/anchor/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/anchor/uy", 0);
+SetNumber("Boundary Conditions/left_edge/ux", 0);
+SetNumber("Materials/FEM_domain/Young", 160e9); // A DETERMINER PRECISEMENT
+SetNumber("Materials/FEM_domain/Poisson", 0.22);
+SetNumber("Materials/FEM_domain/rho",7800); //MODIF
+SetNumber("Volumic Forces/FEM_domain/bx",0);
+SetNumber("Volumic Forces/FEM_domain/by",0);
+SetNumber("Non_linear_solver",1);
+
+Wc = 4;
+g = 8;
+Lg = 20;
+Ls = 280;
+Ht = 40;
+Wt = 16;
+Ws = 2;
+Lc = 30;
+y0 = 20;
+Hbottom = 50;
+Htop = 180;
+Wtot = 400;
+
+// scaled quantities
+Wcs = Wc*scale;
+gs = g*scale;
+Lgs = Lg*scale;
+Lss = Ls*scale;
+Hts = Ht*scale;
+Wts = Wt*scale;
+Wss = Ws*scale;
+Lcs = Lc*scale;
+y0s = y0*scale;
+Hbottoms = Hbottom*scale;
+Htops = Htop*scale;
+Wtots = Wtot*scale;
+
+Ncombs = 4; // ne pas changer, pas généralisé
+
+// fixed bottom anchor
+y = -(Lg-2-4)*scale;
+x = (5*g + 4.5*Wc)*scale;
+Point(1) = {x, y-Wss-2*scale, 0, nBEM*scale}; // limite avec suite
+Point(2) = {x, y-Wts, 0, nBEM*scale};
+Point(3) = {x-Wts, y-Wts, 0, nBEM*scale};
+Point(4) = {x-Wts, y, 0, nBEM*scale};
+Point(5) = {x, y, 0, nBEM*scale};
+Point(6) = {x, y-2*scale, 0, nBEM*scale}; // limite avec suite
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {3, 4};
+Line(4) = {4, 5};
+Line(5) = {5, 6};
+Line(6) = {6, 1}; // limite avec suite
+Transfinite Curve{1} = (Wt - 2 - Ws)*nFEM+1 Using Progression 1;
+Transfinite Curve{2, 3, 4} = Wt*nFEM+1 Using Progression 1;
+Transfinite Curve{5} = 2*nFEM+1 Using Progression 1;
+Transfinite Curve{6} = Ws*nFEM+1 Using Progression 1;
+Curve Loop(1) = {1:6};
+Plane Surface(1) = {1};
+Transfinite Surface{1} = {2:5};
+Recombine Surface{1};
+
+// bottom long beam
+Point(7) = {x+Lss, y-2*scale, 0, nBEM*scale}; // limite avec suite
+Point(8) = {x+Lss, y-Wss-2*scale, 0, nBEM*scale}; // limite avec suite
+Line(7) = {6, 7};
+Line(8) = {7, 8}; // limite avec suite
+Line(9) = {8, 1};
+Transfinite Curve{7, 9} = Ls*nFEM+1 Using Progression 1;
+Transfinite Curve{8} = Ws*nFEM+1 Using Progression 1;
+Curve Loop(2) = {-6, 7:9};
+Plane Surface(2) = {2};
+Transfinite Surface{2};
+Recombine Surface{2};
+
+//truss
+x = x + Lss;
+y = y - 10*scale - Wss;
+Point(9) = {x, y + 8*scale + Wss + Lgs, 0 , nBEM*scale}; // limite avec suite
+Point(10) = {x, y + 8*scale + 2*Wss + Lgs, 0 , nBEM*scale}; // limite avec suite
+Point(11) = {x, y + 16*scale + 2*Wss + Lgs, 0 , nBEM*scale};
+Point(12) = {x + Wts, y + 16*scale + 2*Wss + Lgs, 0 , nBEM*scale};
+Point(13) = {x + Wts, y, 0 , nBEM*scale};
+Point(14) = {x, y, 0 , nBEM*scale};
+Line(10) = {7, 9};
+Line(11) = {9, 10}; // limite avec suite
+Line(12) = {10, 11};
+Line(13) = {11, 12};
+Line(14) = {12, 13};
+Line(15) = {13, 14};
+Line(16) = {14, 8};
+Transfinite Curve{10} = Lg*nFEM+1 Using Progression 1;
+Transfinite Curve{11} = Ws*nFEM+1 Using Progression 1;
+Transfinite Curve{12, 16} = 8*nFEM+1 Using Progression 1;
+Transfinite Curve{13, 15} = Wt*nFEM+1 Using Progression 1;
+Transfinite Curve{14} = (16 + 2*Ws + Lg)*nFEM+1 Using Progression 1;
+Curve Loop(3) = {-8, 10:16};
+Plane Surface(3) = {3};
+Transfinite Surface{3} = {11:14};
+Recombine Surface{3};
+
+//top long beam
+x = (5*g + 4.5*Wc)*scale;
+Point(15) = {x, 4*scale, 0 , nBEM*scale}; // limite avec suite
+Point(16) = {x, 4*scale + Wss, 0 , nBEM*scale}; // limite avec suite
+Line(17) = {9, 15};
+Line(18) = {15, 16}; // limite avec suite
+Line(19) = {16, 10};
+Transfinite Curve{17, 19} = Ls*nFEM+1 Using Progression 1;
+Transfinite Curve{18} = Ws*nFEM+1 Using Progression 1;
+Curve Loop(4) = {-11, 17:19};
+Plane Surface(4) = {4};
+Transfinite Surface{4};
+Recombine Surface{4};
+
+//bottom base moveable combs
+Point(17) = {x, 0, 0 , nBEM*scale};
+Point(18) = {0, 0, 0 , nBEM*scale}; // roulements
+Point(19) = {0, 14*scale + Wss, 0 , nBEM*scale}; // roulements + limite avec suite
+Point(20) = {x, 14*scale + Wss, 0 , nBEM*scale}; // limite avec suite
+Line(20) = {15, 17};
+Line(21) = {17, 18};
+Line(22) = {18, 19}; // roulements
+Line(23) = {19, 20}; // limite avec suite
+Line(24) = {20, 16};
+Transfinite Curve{20} = 4*nFEM+1 Using Progression 1;
+Transfinite Curve{21, 23} = (5*g + 4.5*Wc)*nFEM+1 Using Progression 1;
+Transfinite Curve{22} = (14+Ws)*nFEM+1 Using Progression 1;
+Transfinite Curve{24} = 10*nFEM+1 Using Progression 1;
+Curve Loop(5) = {-18, 20:24};
+Plane Surface(5) = {5};
+Transfinite Surface{5} = {17:20};
+Recombine Surface{5};
+
+//top base moveable combs
+y = 26*scale+Wss;
+Point(21) = {0, y, 0, nBEM*0.1*scale}; // roulements
+Point(22) = {Wcs/2+gs, y, 0, nBEM*0.1*scale};
+Point(23) = {Wcs/2+gs, y+Lcs, 0, nBEM*0.1*scale}; // top comb 1
+Point(24) = {3*Wcs/2+gs, y+Lcs, 0, nBEM*0.1*scale}; // top comb 1
+Point(25) = {3*Wcs/2+gs, y, 0, nBEM*0.1*scale};
+Point(26) = {5*Wcs/2+3*gs, y, 0, nBEM*0.1*scale};
+Point(27) = {5*Wcs/2+3*gs, y+Lcs, 0, nBEM*0.1*scale}; // top comb 2
+Point(28) = {7*Wcs/2+3*gs, y+Lcs, 0, nBEM*0.1*scale}; // top comb 2
+Point(29) = {7*Wcs/2+3*gs, y, 0, nBEM*0.1*scale};
+Point(30) = {9*Wcs/2+5*gs, y, 0, nBEM*0.1*scale};
+
+For i In {1:Ncombs-3}
+    Point(30+4*i-3) = {9*Wcs/2+5*gs + (i-1)*(2*Wcs+2*gs), y+Lcs, 0, nBEM*0.1*scale}; // top comb
+    Point(30+4*i-2) = {9*Wcs/2+5*gs + (i-1)*(2*Wcs+2*gs) + Wcs, y+Lcs, 0, nBEM*0.1*scale}; // top comb
+    Point(30+4*i-1) = {9*Wcs/2+5*gs + (i-1)*(2*Wcs+2*gs) + Wcs, y, 0, nBEM*0.1*scale};
+    Point(30+4*i) = {9*Wcs/2+5*gs + i*(2*Wcs+2*gs), y, 0, nBEM*0.1*scale};
+EndFor
+
+nbPts1 = 30 + (Ncombs-3)*4;
+x = (5*g + 4.5*Wc)*scale + 2*(Wcs+gs);
+Point(nbPts1 + 1) = {x, y+Lcs, 0, nBEM*0.1*scale}; // top last comb
+Point(nbPts1 + 2) = {x+Wcs, y+Lcs, 0, nBEM*0.1*scale}; // top last comb
+Point(nbPts1 + 3) = {x+Wcs, y, 0, nBEM*0.1*scale}; 
+Point(nbPts1 + 4) = {x+Wcs+gs, y, 0, nBEM*0.1*scale}; // last point right
+Point(nbPts1 + 5) = {x+Wcs+gs, y-12*scale, 0, nBEM*0.4*scale}; // last point right
+nbPts2 = nbPts1 + 5;
+
+
+Line(25) = {19, 21}; // roulements
+Line(26) = {21, 22};
+Line(27) = {22, 23};
+Line(28) = {23, 24}; // top comb 1
+Line(29) = {24, 25};
+Line(30) = {25, 26};
+Line(31) = {26, 27};
+Line(32) = {27, 28}; // top comb 2
+Line(33) = {28, 29}; 
+Line(34) = {29, 30};
+
+For i In {1:Ncombs-3}
+    Line(34+4*i-3) = {30+4*i-4, 30+4*i-3};
+    Line(34+4*i-2) = {30+4*i-3, 30+4*i-2}; // top comb
+    Line(34+4*i-1) = {30+4*i-2, 30+4*i-1};
+    Line(34+4*i) = {30+4*i-1, 30+4*i}; 
+    Transfinite Curve{34+4*i-3, 34+4*i-1} = Lc*nFEM+1 Using Progression 1;
+    Transfinite Curve{34+4*i-2} = Wc*nFEM+1 Using Progression 1;
+    Transfinite Curve{34+4*i} = (Wc+2*g)*nFEM+1 Using Progression 1;
+EndFor
+nbLines1 = 34 + (Ncombs-3)*4;
+Line(nbLines1 + 1) = {nbPts1, nbPts1 + 1};
+Line(nbLines1 + 2) = {nbPts1 + 1, nbPts1 + 2}; //top last comb
+Line(nbLines1 + 3) = {nbPts1 + 2, nbPts1 + 3};
+Line(nbLines1 + 4) = {nbPts1 + 3, nbPts1 + 4};
+Line(nbLines1 + 5) = {nbPts1 + 4, nbPts1 + 5}; // last line right
+Line(nbLines1 + 6) = {nbPts1 + 5, 20};
+nbLines2 = nbLines1 + 6;
+
+Transfinite Curve{25, nbLines1 + 5} = 12*nFEM+1 Using Progression 1;
+Transfinite Curve{26} = (Wc/2+g)*nFEM+1 Using Progression 1;
+Transfinite Curve{27, 29, 31, 33, nbLines1 + 1, nbLines1 + 3} = Lc*nFEM+1 Using Progression 1;
+Transfinite Curve{28, 32, nbLines1 + 2} = Wc*nFEM+1 Using Progression 1;
+Transfinite Curve{30, 34} = (Wc+2*g)*nFEM+1 Using Progression 1;
+Transfinite Curve{nbLines1 + 4} = g*nFEM+1 Using Progression 1;
+Transfinite Curve{nbLines1 + 6} = ((Ncombs-2)*(2*Wc+2*g)-g-Wc)*nFEM+1 Using Progression 1;
+
+// bottom lines
+Line(nbLines2 + 1) = {25, 22}; // bottom comb 1
+Line(nbLines2 + 2) = {29, 26}; // bottom comb 2
+For i In {1:Ncombs-3}
+    Line(nbLines2 + 2 + i) = {30+4*i-1, 30+4*i-4}; // bottom comb
+EndFor
+nbLines3 = nbLines2 + 2 + Ncombs-2;
+Line(nbLines3) = {nbPts1 + 3, nbPts1}; //bottom last comb
+Transfinite Curve{nbLines2 + 1: nbLines3} = Wc*nFEM+1 Using Progression 1;
+
+// top base combs
+Curve Loop(6) = {-23, 25, 26, -45,30,-46,34, -47, 38, -48, nbLines1+4:nbLines1+6}; // hardcoded
+Plane Surface(6) = {6};
+Transfinite Surface{6} = {19,21,nbPts2-1,nbPts2};
+Recombine Surface{6};
+// hardcoder le nombre de combs à partir d'ici
+// four combs
+Curve Loop(7) = {27, 28, 29, 45};
+Plane Surface(7) = {7};
+Curve Loop(8) = {31, 32, 33, 46};
+Plane Surface(8) = {8};
+Curve Loop(9) = {35, 36, 37, 47};
+Plane Surface(9) = {9};
+Curve Loop(10) = {39, 40, 41, 48};
+Plane Surface(10) = {10};
+Transfinite Surface{7:10};
+Recombine Surface{7:10};
+
+// mechanical physical surfaces
+Physical Curve("anchor", 1) = {1:6};
+
+Physical Surface("FEM_domain", 2) = {1:10};
+Physical Curve("BEM_FEM_boundary", 3) = {1:5, 7, 10, 17, 20, 21, 26:nbLines2, 24, 19, 12:16, 9};
+Physical Curve("left_edge", 4) = {22,25};
+
+//top electrode
+y = y + Lcs + (Lcs-y0s) + 12*scale;
+xtot = Ncombs*(2*gs+2*Wcs) + Wcs/2;
+Point(nbPts2 + 1) = {0, y, 0, nBEM*scale};
+Point(nbPts2 + 2) = {xtot, y, 0, nBEM*scale};
+For i In {1:Ncombs}
+    Point(nbPts2 + 2 + 4*i - 3) = {xtot-(i-1)*(2*Wcs+2*gs), y-12*scale-Lcs, 0, 0.2*nBEM*scale};
+    Point(nbPts2 + 2 + 4*i - 2) = {xtot-(i-1)*(2*Wcs+2*gs) - Wcs, y-12*scale - Lcs, 0, 0.2*nBEM*scale};
+    Point(nbPts2 + 2 + 4*i - 1) = {xtot-(i-1)*(2*Wcs+2*gs)-Wcs, y-12*scale, 0, 0.2*nBEM*scale};
+    Point(nbPts2 + 2 + 4*i) = {xtot-i*(2*Wcs+2*gs), y-12*scale, 0, 0.2*nBEM*scale};
+EndFor
+nbPts3 = nbPts2 + 2 + 4*Ncombs;
+Point(nbPts3 + 1) = {Wcs/2, y-12*scale-Lcs, 0, nBEM*scale};
+Point(nbPts3 + 2) = {0, y-12*scale-Lcs, 0, nBEM*scale};
+nbPts4 = nbPts3 + 2;
+
+For i In {nbPts2+1:nbPts4-1}
+    Line(nbLines3 + i - nbPts2) = {i, i+1};
+EndFor
+Line(nbLines3 + nbPts4 - nbPts2) = {nbPts4, nbPts2+1};
+nbLines4 = nbLines3 + nbPts4 - nbPts2;
+
+Physical Curve("top_electrode", 5) = {nbLines3+1:nbLines4-1};
+
+// rest of outside
+Line(nbLines4 + 1) = {nbPts4, 21};
+
+Point(nbPts4 + 1) = {0, -Hbottoms, 0, 2*nBEM*scale};
+Point(nbPts4 + 2) = {Wtots, -Hbottoms, 0, 2*nBEM*scale};
+Point(nbPts4 + 3) = {Wtots, Htops, 0, 2*nBEM*scale};
+Point(nbPts4 + 4) = {0, Htops, 0, 2*nBEM*scale};
+
+Line(nbLines4 + 2) = {18, nbPts4 + 1};
+Line(nbLines4 + 3) = {nbPts4 + 1, nbPts4 + 2};
+Line(nbLines4 + 4) = {nbPts4 + 2, nbPts4 + 3};
+Line(nbLines4 + 5) = {nbPts4 + 3, nbPts4 + 4};
+Line(nbLines4 + 6) = {nbPts4 + 4, nbPts2 + 1};
+
+Curve Loop(11) = {nbLines4 + 2: nbLines4 + 6, nbLines3 + 1: nbLines4 - 1, nbLines4 + 1, 26:nbLines2, 24, 19, 12:16, 9, 1:5, 7, 10, 17, 20, 21};
+Plane Surface(11) = {11};
+Physical Surface("BEM_domain_1", 6) = {11};
+
+Physical Curve("rest_of_outside", 7) = {nbLines4+1: nbLines4+6};
\ No newline at end of file
diff --git a/srcs/MEMS.geo b/srcs/MEMS.geo
index 7ec38557f6c53de26095d06899eb0353a7fb5ba6..a918f61c3068a787a1b17244848dfd096e19f79e 100644
--- a/srcs/MEMS.geo
+++ b/srcs/MEMS.geo
@@ -103,4 +103,5 @@ Physical Curve("dirichlet", 20) = {3};
 phi_top = 100;
 SetNumber("Boundary Conditions/mass/BEM_domain_1/dirichlet", 0);
 SetNumber("Boundary Conditions/dirichlet/BEM_domain_1/dirichlet", phi_top);
-SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
\ No newline at end of file
+SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
\ No newline at end of file
diff --git a/srcs/clampedMicroBeam.geo b/srcs/clampedMicroBeam.geo
new file mode 100644
index 0000000000000000000000000000000000000000..5e94f6d3570ef5bd1d8605fdd2833d07b4ee2f59
--- /dev/null
+++ b/srcs/clampedMicroBeam.geo
@@ -0,0 +1,86 @@
+scale = 1e-6;
+Lx_poutre = 25;
+Ly_poutre = 1;
+h_poutre = 1;
+h_tot = 5;
+width = 35;
+
+n = 6; // FEM MESH DENSITY
+
+// additional parameters given to the solver
+SetNumber("Boundary Conditions/left_edge/ux", 0.); 
+SetNumber("Boundary Conditions/left_edge/uy", 0);
+SetNumber("Materials/domain/Young", 150e9);
+SetNumber("Materials/domain/Poisson", 0.27);
+SetNumber("Materials/domain/rho",2300);
+SetNumber("Volumic Forces/FEM_domain/bx",0.);
+SetNumber("Volumic Forces/FEM_domain/by",0.); //set to -9.81 for gravity
+
+phi_top = 112; // à modifier valou
+SetNumber("Boundary Conditions/mass/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/BEM_FEM_boundary/BEM_domain_1/dirichlet", phi_top);
+SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+SetNumber("Non_linear_solver",1);
+
+Point(1) = {0, h_poutre*scale, 0, 2};
+Point(2) = {Lx_poutre*scale, h_poutre*scale, 0, 2};
+Point(3) = {Lx_poutre*scale, h_poutre*scale + Ly_poutre*scale, 0, 2};
+Point(4) = {0, h_poutre*scale + Ly_poutre*scale, 0, 2};
+
+Point(5) = {0, 0, 0, 2};
+Point(6) = {Lx_poutre*scale, 0, 0, 2};
+Point(7) = {width*scale, 0, 0, 2};
+Point(8) = {width*scale, h_tot*scale, 0, 2};
+Point(9) = {0, h_tot*scale, 0, 2};
+
+Line(1) = {2, 1};
+Line(2) = {3, 2};
+Line(3) = {4, 3};
+Line(4) = {1, 4};
+
+Line(5) = {1, 5};
+Line(6) = {9, 4};
+Line(7) = {8, 9};
+Line(8) = {7, 8};
+Line(9) = {6, 7};
+Line(10) = {5, 6};
+
+Curve Loop(1) = {4, 3, 2, 1};
+Plane Surface(1) = {1};
+
+Curve Loop(2) = {5, 10, 9, 8, 7, 6, 3, 2, 1};
+Plane Surface(2) = {2};
+
+Transfinite Curve {3, 1, 10} = Lx_poutre*n+1 Using Progression 1;
+Transfinite Curve {7} = width*n+1 Using Progression 1;
+Transfinite Curve {8} = h_tot*n+1 Using Progression 1;
+Transfinite Curve {2, 4} = Ly_poutre*n+1 Using Progression 1;
+Transfinite Curve {5} = h_poutre*n+1 Using Progression 1;
+Transfinite Curve {9} = (width-Lx_poutre)*n+1 Using Progression 1;
+Transfinite Curve {6} = (h_tot-h_poutre-Ly_poutre)*n+1 Using Progression 1;
+Transfinite Surface {1};
+
+//Transfinite Surface {2};
+
+Recombine Surface {1}; // quads instead of triangles
+//Recombine Surface {2};
+
+Mesh.ElementOrder = 1;
+
+Physical Curve("left_edge", 5) = {4};
+Physical Surface("FEM_domain", 6) = {1};
+Physical Curve("top_edge", 7) = {3};
+Physical Curve("right_edge", 8) = {2};
+Physical Point("fixed_node", 9) = {1};
+
+Physical Surface("BEM_domain_1", 10) = {2};
+
+// BEM geometry
+Physical Curve("BEM_FEM_boundary", 11) = {1,2,3};
+Physical Curve("mass", 12) = {10}; //lower electrode
+Physical Curve("rest_of_outside", 13) = {5,6,7,8,9};
+Physical Curve("Electrode", 15) = {1};
+//SetNumber("Boundary Conditions/bottom_edge/tx", 0);
+//SetNumber("Boundary Conditions/bottom_edge/ty", -25000);
\ No newline at end of file
diff --git a/srcs/coupling_validation.geo b/srcs/coupling_validation.geo
new file mode 100644
index 0000000000000000000000000000000000000000..e5510d1e2ee35de5eebe1b186d0f0be9839fefe1
--- /dev/null
+++ b/srcs/coupling_validation.geo
@@ -0,0 +1,65 @@
+scale = 1e-6;
+
+Lx = 5;
+Ly = 2;
+l = 3;
+
+n = 25;
+
+Point(1) = {0, 0, 0, 0.1};
+Point(2) = {Lx*scale, 0, 0, 0.1};
+Point(3) = {Lx*scale, Ly*scale, 0, 0.1};
+Point(4) = {0, Ly*scale, 0, 0.2};
+
+Point(5) = {Lx*scale + l*scale, 0, 0, 0.2};
+Point(6) = {Lx*scale + l*scale, Ly*scale, 0, 0.2};
+
+Line(1) = {2, 1};
+Line(2) = {3, 2};
+Line(3) = {4, 3};
+Line(4) = {1, 4};
+Curve Loop(1) = {4, 3, 2, 1};
+Plane Surface(1) = {1};
+
+Line(5) = {2, 5};
+Line(6) = {5, 6};
+Line(7) = {6, 3};
+Curve Loop(2) = {2, 5, 6, 7};
+Plane Surface(2) = {2};
+
+
+Transfinite Curve {3, 1} = n*Lx+1 Using Progression 1;
+Transfinite Curve {2, 4, 6} = n*Ly+1 Using Progression 1;
+Transfinite Curve {5, 7} = n*l+1 Using Progression 1;
+Transfinite Surface {1};
+Transfinite Surface {2};
+
+Recombine Surface {1}; // quads instead of triangles
+Recombine Surface {2};
+
+Mesh.ElementOrder = 1;
+
+Physical Curve("left_edge", 1) = {4};
+Physical Surface("FEM_domain", 2) = {1};
+Physical Point("fixed_node", 3) = {1};
+
+// additional parameters given to the solver
+SetNumber("Boundary Conditions/left_edge/ux", 0.); // HERE YOU DO NOT HAVE TO IMPOSE BOTH ux and uy simultaneously ! (permet aussi de simuler appuis à roulettes)
+//SetNumber("Boundary Conditions/left_edge/uy", 0.);
+SetNumber("Boundary Conditions/fixed_node/uy", 0.);
+SetNumber("Materials/FEM_domain/Young", 210e3);
+SetNumber("Materials/FEM_domain/Poisson", 0.3);
+SetNumber("Materials/FEM_domain/rho",7800); //volumic mass of acier
+
+Physical Curve("BEM_FEM_boundary", 4) = {2};
+Physical Surface("BEM_domain_1", 5) = {2};
+Physical Curve("right_BEM", 6) = {6};
+Physical Curve("homogeneous_field", 7) = {5, 7};
+
+phi = 30;
+SetNumber("Boundary Conditions/right_BEM/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/BEM_FEM_boundary/BEM_domain_1/dirichlet", phi);
+SetNumber("Boundary Conditions/homogeneous_field/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+SetNumber("Non_linear_solver", 0);
\ No newline at end of file
diff --git a/srcs/hybrid_geo.geo b/srcs/hybrid_geo.geo
index b7820f20b074ac8e4c74e22527cd72b928dae8e8..53ba5b7907d95934a50e77a778638bc84538074a 100644
--- a/srcs/hybrid_geo.geo
+++ b/srcs/hybrid_geo.geo
@@ -80,6 +80,7 @@ phi_top = 95;
 SetNumber("Boundary Conditions/mass/BEM_domain_1/dirichlet", 0);
 SetNumber("Boundary Conditions/BEM_FEM_boundary/BEM_domain_1/dirichlet", phi_top);
 SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
 //Physical Curve("BEM_boundary", 14) = {1,3,5,6,7,8,9,10,2};
 
 Physical Curve("Electrode", 15) = {1};
diff --git a/srcs/longitudinalCombDevice.geo b/srcs/longitudinalCombDevice.geo
new file mode 100644
index 0000000000000000000000000000000000000000..098922a6252baea88986052ff3e46fad2b5af584
--- /dev/null
+++ b/srcs/longitudinalCombDevice.geo
@@ -0,0 +1,301 @@
+scale = 2e-6;
+
+// USE WITH MINIMUM 2 FINS, else use longitudinal_comb.geo
+N_fins = 3; // number of fins on one side of the comb // MAX 12 si on change ps la longueur
+
+// WARNING: when using more fins the pull-in voltage decreases
+
+n = 1; // FEM elements density
+nBEM = 1; // BEM elements density
+
+// mechanical properties and boundary conditions
+SetNumber("Boundary Conditions/left/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/left/uy", 0);
+SetNumber("Boundary Conditions/right/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/right/uy", 0);
+SetNumber("Materials/FEM_domain/Young", 150e9);
+SetNumber("Materials/FEM_domain/Poisson", 0.27);
+SetNumber("Materials/FEM_domain/rho",2300); 
+SetNumber("Volumic Forces/FEM_domain/bx",0);
+SetNumber("Volumic Forces/FEM_domain/by",00); // acceleration of accelerometer
+
+// BEM properties in bottom domain
+phi_1 = 50;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_1/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_1/BEM_domain_1/dirichlet", phi_1);
+SetNumber("Boundary Conditions/outside_1/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+// BEM properties in top domain
+phi_2 = 0;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_2/BEM_domain_2/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_2/BEM_domain_2/dirichlet", phi_2);
+SetNumber("Boundary Conditions/outside_2/BEM_domain_2/neumann", 0);
+SetNumber("Materials/BEM_domain_2/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+h_tot = 30*scale;
+h_base = 0.4*scale;
+h_fin = 2.8*scale;
+h_space = 1*scale; // space between bout de l'electrode and base of the clamped beam of the comb
+h_fin_elec = 2.4*scale; // length of the fins of the electrode, can be longer than the classical fins
+// WARNING, abs(h_fin_elec - h_fin) must be lower than h_space
+
+//l_bord = 10*scale;
+//l_tot = 34.4*scale;
+l_tot = 40*scale;
+l_fin = 0.8*scale;
+l_space = 0.8*scale;
+t_electrode = 1*scale; // width of one electrode
+l_periodic = l_fin + 2*l_space + t_electrode; // distance between two fins
+//l_tot = 2*l_bord + l_fin + (N_fins-1)*l_periodic;
+l_bord = (l_tot - l_fin - (N_fins-1)*l_periodic)/2;
+
+unit_l = 0.2*scale; // reference for the transfinite curves
+
+// définition des points du contour
+Point(1) = {0, -h_base/2, 0, nBEM*scale};
+Point(2) = {0, -h_tot/2, 0, nBEM*scale};
+Point(3) = {l_tot, -h_tot/2, 0, nBEM*scale};
+Point(4) = {l_tot, -h_base/2, 0, nBEM*scale};
+Point(5) = {l_tot, h_base/2, 0, nBEM*scale};
+Point(6) = {l_tot, h_tot/2, 0, nBEM*scale};
+Point(7) = {0, h_tot/2, 0, nBEM*scale};
+Point(8) = {0, h_base/2, 0, nBEM*scale};
+// définition des lignes du contour
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {3, 4};
+Line(4) = {4, 5};
+Line(5) = {5, 6};
+Line(6) = {6, 7};
+Line(7) = {7, 8};
+Line(8) = {8, 1};
+Transfinite Curve {4,8} = (h_base/unit_l)*n+1 Using Progression 1;
+
+
+// définition des points des fins du bas
+offsetp1 = 8;
+For i In {1:N_fins}
+    Point(offsetp1+4*i-3) = {(i-1)*l_periodic + l_bord, -h_base/2, 0, 0.2*scale};
+    Point(offsetp1+4*i-2) = {(i-1)*l_periodic + l_bord, -h_base/2 - h_fin, 0, 0.2*scale};
+    Point(offsetp1+4*i-1) = {(i-1)*l_periodic + l_bord + l_fin, -h_base/2 - h_fin, 0, 0.2*scale};
+    Point(offsetp1+4*i) = {(i-1)*l_periodic + l_bord + l_fin, -h_base/2, 0, 0.2*scale};
+EndFor
+// définition des lignes des fins du bas
+Line(9) = {offsetp1+1, 1};
+Transfinite Curve {9} = (l_bord/unit_l)*n+1 Using Progression 1;
+offsetl1 = 9;
+For i In {1:N_fins-1}
+    Line(offsetl1+4*i-3) = {offsetp1+4*i-2, offsetp1+4*i-3};
+    Line(offsetl1+4*i-2) = {offsetp1+4*i-1, offsetp1+4*i-2};
+    Line(offsetl1+4*i-1) = {offsetp1+4*i, offsetp1+4*i-1};
+    Line(offsetl1+4*i) = {offsetp1+4*i+1, offsetp1+4*i};
+    Transfinite Curve {offsetl1+4*i-3, offsetl1+4*i-1} = (h_fin/unit_l)*n+1 Using Progression 1;
+    Transfinite Curve {offsetl1+4*i-2} = (l_fin/unit_l)*n+1 Using Progression 1;
+    Transfinite Curve {offsetl1+4*i} = ((l_periodic-l_fin)/unit_l)*n+1 Using Progression 1;
+EndFor
+Line(offsetl1+4*N_fins-3) = {offsetp1+4*N_fins-2, offsetp1+4*N_fins-3};
+Line(offsetl1+4*N_fins-2) = {offsetp1+4*N_fins-1, offsetp1+4*N_fins-2};
+Line(offsetl1+4*N_fins-1) = {offsetp1+4*N_fins, offsetp1+4*N_fins-1};
+Line(offsetl1+4*N_fins) = {4, offsetp1+4*N_fins};
+Transfinite Curve {offsetl1+4*N_fins-3, offsetl1+4*N_fins-1} = (h_fin/unit_l)*n+1 Using Progression 1;
+Transfinite Curve {offsetl1+4*N_fins-2} = (l_fin/unit_l)*n+1 Using Progression 1;
+Transfinite Curve {offsetl1+4*N_fins} = (l_bord/unit_l)*n+1 Using Progression 1;
+// définition des lignes entre les fins du bas et la poutre principale
+For i In{1:N_fins}
+    Line(offsetl1+4*N_fins+i) = {offsetp1+4*i-3, offsetp1+4*i};
+    Transfinite Curve {offsetl1+4*N_fins+i} = (l_fin/unit_l)*n+1 Using Progression 1;
+EndFor
+
+// définition des points des fins du haut
+offsetp2 = offsetp1 + 4*N_fins;
+For i In {1:N_fins}
+    Point(offsetp2+4*i-3) = {(i-1)*l_periodic + l_bord, h_base/2, 0, 0.2*scale};
+    Point(offsetp2+4*i-2) = {(i-1)*l_periodic + l_bord, h_base/2 + h_fin, 0, 0.2*scale};
+    Point(offsetp2+4*i-1) = {(i-1)*l_periodic + l_bord + l_fin, +h_base/2 + h_fin, 0, 0.2*scale};
+    Point(offsetp2+4*i) = {(i-1)*l_periodic + l_bord + l_fin, +h_base/2, 0, 0.2*scale};
+EndFor
+// définition des lignes des fins du haut
+offsetl2 = offsetl1 + 5*N_fins + 1;
+Line(offsetl2) = {8, offsetp2+1};
+Transfinite Curve {offsetl2} = (l_bord/unit_l)*n+1 Using Progression 1;
+For i In {1:N_fins-1}
+    Line(offsetl2+4*i-3) = {offsetp2+4*i-3, offsetp2+4*i-2};
+    Line(offsetl2+4*i-2) = {offsetp2+4*i-2, offsetp2+4*i-1};
+    Line(offsetl2+4*i-1) = {offsetp2+4*i-1, offsetp2+4*i};
+    Line(offsetl2+4*i) = {offsetp2+4*i, offsetp2+4*i+1};
+    Transfinite Curve {offsetl2+4*i-3, offsetl2+4*i-1} = (h_fin/unit_l)*n+1 Using Progression 1;
+    Transfinite Curve {offsetl2+4*i-2} = (l_fin/unit_l)*n+1 Using Progression 1;
+    Transfinite Curve {offsetl2+4*i} = ((l_periodic-l_fin)/unit_l)*n+1 Using Progression 1;
+EndFor
+Line(offsetl2+4*N_fins-3) = {offsetp2+4*N_fins-3, offsetp2+4*N_fins-2};
+Line(offsetl2+4*N_fins-2) = {offsetp2+4*N_fins-2, offsetp2+4*N_fins-1};
+Line(offsetl2+4*N_fins-1) = {offsetp2+4*N_fins-1, offsetp2+4*N_fins};
+Line(offsetl2+4*N_fins) = {offsetp2+4*N_fins, 5};
+Transfinite Curve {offsetl2+4*N_fins-3, offsetl2+4*N_fins-1} = (h_fin/unit_l)*n+1 Using Progression 1;
+Transfinite Curve {offsetl2+4*N_fins-2} = (l_fin/unit_l)*n+1 Using Progression 1;
+Transfinite Curve {offsetl2+4*N_fins} = (l_bord/unit_l)*n+1 Using Progression 1;
+// définition des lignes entre les fins du haut et la poutre principale
+For i In{1:N_fins}
+    Line(offsetl2+4*N_fins+i) = {offsetp2+4*i, offsetp2+4*i-3};
+    Transfinite Curve {offsetl2+4*N_fins+i} = (l_fin/unit_l)*n+1 Using Progression 1;
+EndFor
+
+// définition des lignes dans la poutre centrale pour définir sous-domaines
+offsetl3 = offsetl2 + 5*N_fins;
+For i In {1:N_fins}
+    Line(offsetl3+2*i-1) = {offsetp2+4*i-3, offsetp1+4*i-3};
+    Line(offsetl3+2*i) = {offsetp1+4*i, offsetp2+4*i};
+    Transfinite Curve {offsetl3+2*i-1, offsetl3+2*i} = (h_base/unit_l)*n+1 Using Progression 1;
+EndFor
+
+// définition des courbes et surfaces dans les fins du bas
+For i In {1:N_fins}
+    Curve Loop(i) = {offsetl1+4*i-1, offsetl1+4*i-2, offsetl1+4*i-3, offsetl1+4*N_fins+i};
+    Plane Surface(i) = {i};
+    Recombine Surface {i};
+EndFor
+
+// définition des courbes et surfaces dans les fins du haut
+offsets1 = N_fins;
+For i In {1:N_fins}
+    Curve Loop(offsets1 + i) = {offsetl2+4*i-3, offsetl2+4*i-2, offsetl2+4*i-1, offsetl2+4*N_fins+i};
+    Plane Surface(offsets1 + i) = {offsets1 + i};
+    Recombine Surface {offsets1 + i};
+EndFor
+
+// définition des courbes et surfaces dans la poutre centrale
+offsets2 = offsets1 + N_fins + 1;
+Curve Loop(offsets2) = {-8, offsetl2, offsetl3+1, offsetl1};
+Plane Surface(offsets2) = {offsets2};
+Recombine Surface {offsets2};
+For i In {1:N_fins-1}
+    Curve Loop(offsets2 + 2*i - 1) = {offsetl3+2*i-1, offsetl1+4*N_fins+i, offsetl3+2*i, offsetl2+4*N_fins+i};
+    Plane Surface(offsets2 + 2*i - 1) = {offsets2 + 2*i - 1};
+    Recombine Surface {offsets2 + 2*i - 1};
+    Curve Loop(offsets2 + 2*i) = {offsetl3+2*i, offsetl2+4*i, offsetl3+2*i+1, offsetl1+4*i};
+    Plane Surface(offsets2 + 2*i) = {offsets2 + 2*i};
+    Recombine Surface {offsets2 + 2*i};
+EndFor
+Curve Loop(offsets2 + 2*N_fins - 1) = {offsetl3+2*N_fins-1, offsetl1+4*N_fins+N_fins, offsetl3+2*N_fins, offsetl2+4*N_fins+N_fins};
+Plane Surface(offsets2 + 2*N_fins - 1) = {offsets2 + 2*N_fins - 1};
+Recombine Surface {offsets2 + 2*N_fins - 1};
+Curve Loop(offsets2 + 2*N_fins) = {offsetl3+2*N_fins, offsetl2+4*N_fins, -4, offsetl1+4*N_fins};
+Plane Surface(offsets2 + 2*N_fins) = {offsets2 + 2*N_fins};
+Recombine Surface {offsets2 + 2*N_fins};
+
+
+// mechanical physical surfaces
+Physical Curve("left", 1) = {8};
+Physical Curve("right", 2) = {4};
+
+Physical Surface("FEM_domain", 3) = {1:offsets2 + 2*N_fins};
+Transfinite Surface {1:offsets2 + 2*N_fins};
+Physical Curve("BEM_FEM_boundary", 4) = {offsetl1:offsetl1+4*N_fins, offsetl2:offsetl2+4*N_fins};
+
+// définition des points de la bottom electrode
+x0_e = l_bord - l_space - t_electrode; // pour faciliter le bazar
+y0_e = h_base/2 + h_space;
+offsetp3 = offsetp2 + 4*N_fins;
+Point(offsetp3 + 1) = {l_tot - x0_e - t_electrode, -y0_e - h_fin_elec, 0, nBEM*0.2*scale};
+Point(offsetp3 + 2) = {l_tot - x0_e - t_electrode, -y0_e, 0, nBEM*0.2*scale};
+Point(offsetp3 + 3) = {l_tot - x0_e, -y0_e, 0, nBEM*0.2*scale};
+Point(offsetp3 + 4) = {l_tot - x0_e, -y0_e - h_fin_elec - t_electrode, 0, nBEM*0.2*scale};
+Point(offsetp3 + 5) = {x0_e, -y0_e - h_fin_elec - t_electrode, 0, nBEM*0.2*scale};
+Point(offsetp3 + 6) = {x0_e, -y0_e, 0, nBEM*0.2*scale};
+Point(offsetp3 + 7) = {x0_e + t_electrode, -y0_e, 0, nBEM*0.2*scale};
+Point(offsetp3 + 8) = {x0_e + t_electrode, -y0_e - h_fin_elec, 0, nBEM*0.2*scale};
+
+offsetp4 = offsetp3 + 8;
+For i In {1:N_fins-1}
+    Point(offsetp4 + 4*i - 3) = {x0_e + l_periodic*i, -y0_e - h_fin_elec, 0, nBEM*0.2*scale};
+    Point(offsetp4 + 4*i - 2) = {x0_e + l_periodic*i, -y0_e, 0, nBEM*0.2*scale};
+    Point(offsetp4 + 4*i - 1) = {x0_e + l_periodic*i + t_electrode, -y0_e, 0, nBEM*0.2*scale};
+    Point(offsetp4 + 4*i) = {x0_e + l_periodic*i + t_electrode, -y0_e - h_fin_elec, 0, nBEM*0.2*scale};
+EndFor
+
+// définition des lignes générales (indépendantes de N_fins) de la bottom electrode
+offsetl4 = offsetl3 + N_fins*2;
+Line(offsetl4 + 1) = {offsetp3 + 1, offsetp3 + 2};
+Line(offsetl4 + 2) = {offsetp3 + 2, offsetp3 + 3};
+Line(offsetl4 + 3) = {offsetp3 + 3, offsetp3 + 4};
+Line(offsetl4 + 4) = {offsetp3 + 4, offsetp3 + 5};
+Line(offsetl4 + 5) = {offsetp3 + 5, offsetp3 + 6};
+Line(offsetl4 + 6) = {offsetp3 + 6, offsetp3 + 7};
+Line(offsetl4 + 7) = {offsetp3 + 7, offsetp3 + 8};
+Line(offsetl4 + 8) = {offsetp3 + 8, offsetp4 + 1};
+offsetl5 = offsetl4 + 8;
+// définition des lignes fins electrode du bas
+For i In {1:N_fins-2}
+    Line(offsetl5 + 4*i - 3) = {offsetp4 + 4*i - 3, offsetp4 + 4*i - 2};
+    Line(offsetl5 + 4*i - 2) = {offsetp4 + 4*i - 2, offsetp4 + 4*i - 1};
+    Line(offsetl5 + 4*i - 1) = {offsetp4 + 4*i - 1, offsetp4 + 4*i};
+    Line(offsetl5 + 4*i) = {offsetp4 + 4*i, offsetp4 + 4*i + 1};
+EndFor
+Line(offsetl5 + 4*(N_fins-1) - 3) = {offsetp4 + 4*(N_fins-1) - 3, offsetp4 + 4*(N_fins-1) - 2};
+Line(offsetl5 + 4*(N_fins-1) - 2) = {offsetp4 + 4*(N_fins-1) - 2, offsetp4 + 4*(N_fins-1) - 1};
+Line(offsetl5 + 4*(N_fins-1) - 1) = {offsetp4 + 4*(N_fins-1) - 1, offsetp4 + 4*(N_fins-1)};
+Line(offsetl5 + 4*(N_fins-1)) = {offsetp4 + 4*(N_fins-1), offsetp3+1};
+
+// définition des curve loop et surface du BEM_domain1
+offsets3 = offsets2 + 2*N_fins;
+Curve Loop(offsets3 + 1) = {offsetl1+4*N_fins:offsetl1:-1,1,2,3}; // exterior boundary of BEM_domain_1
+Curve Loop(offsets3 + 2) = {offsetl4 + 1 : offsetl5 + 4*(N_fins-1)};
+Plane Surface(offsets3 + 1) = {offsets3 + 1, offsets3 + 2};
+
+Physical Surface("BEM_domain_1", 5) = {offsets3 + 1};
+Physical Curve("BEM_FEM_boundary_1", 6) = {offsetl1+4*N_fins:offsetl1:-1};
+Physical Curve("electrode_1", 7) = {offsetl4 + 1 : offsetl5 + 4*(N_fins-1)};
+Physical Curve("outside_1", 8) = {1, 2, 3};
+
+// définition des points de la top electrode
+offsetp5 = offsetp4 + 4*(N_fins-1);
+Point(offsetp5 + 1) = {x0_e + t_electrode, y0_e + h_fin_elec, 0, nBEM*0.2*scale};
+Point(offsetp5 + 2) = {x0_e + t_electrode, y0_e, 0, nBEM*0.2*scale};
+Point(offsetp5 + 3) = {x0_e, y0_e, 0, nBEM*0.2*scale};
+Point(offsetp5 + 4) = {x0_e, y0_e + h_fin_elec + t_electrode, 0, nBEM*0.2*scale};
+Point(offsetp5 + 5) = {l_tot - x0_e, y0_e + h_fin_elec + t_electrode, 0, nBEM*0.2*scale};
+Point(offsetp5 + 6) = {l_tot - x0_e, y0_e, 0, nBEM*0.2*scale};
+Point(offsetp5 + 7) = {l_tot - x0_e - t_electrode, y0_e, 0, nBEM*0.2*scale};
+Point(offsetp5 + 8) = {l_tot - x0_e - t_electrode, y0_e + h_fin_elec, 0, nBEM*0.2*scale};
+
+offsetp6 = offsetp5 + 8;
+For i In {1:N_fins-1}
+    Point(offsetp6 + 4*i - 3) = {x0_e + l_periodic*i, y0_e + h_fin_elec, 0, nBEM*0.2*scale};
+    Point(offsetp6 + 4*i - 2) = {x0_e + l_periodic*i, y0_e, 0, nBEM*0.2*scale};
+    Point(offsetp6 + 4*i - 1) = {x0_e + l_periodic*i + t_electrode, y0_e, 0, nBEM*0.2*scale};
+    Point(offsetp6 + 4*i) = {x0_e + l_periodic*i + t_electrode, y0_e + h_fin_elec, 0, nBEM*0.2*scale};
+EndFor
+
+// définition des lignes générales (indépendantes de N_fins) de la top electrode
+offsetl6 = offsetl5 + 4*(N_fins-1);
+Line(offsetl6 + 1) = {offsetp5 + 1, offsetp5 + 2};
+Line(offsetl6 + 2) = {offsetp5 + 2, offsetp5 + 3};
+Line(offsetl6 + 3) = {offsetp5 + 3, offsetp5 + 4};
+Line(offsetl6 + 4) = {offsetp5 + 4, offsetp5 + 5};
+Line(offsetl6 + 5) = {offsetp5 + 5, offsetp5 + 6};
+Line(offsetl6 + 6) = {offsetp5 + 6, offsetp5 + 7};
+Line(offsetl6 + 7) = {offsetp5 + 7, offsetp5 + 8};
+Line(offsetl6 + 8) = {offsetp5 + 8, offsetp6 + 4*(N_fins-1)};
+offsetl7 = offsetl6 + 8;
+// définition des lignes fins electrode du haut
+Line(offsetl7 + 1) = {offsetp6 + 4 - 3, offsetp5 + 1};
+Line(offsetl7 + 2) = {offsetp6 + 4 - 2, offsetp6 + 4 - 3};
+Line(offsetl7 + 3) = {offsetp6 + 4 - 1, offsetp6 + 4 - 2};
+Line(offsetl7 + 4) = {offsetp6 + 4, offsetp6 + 4 - 1};
+For i In {2:N_fins-1}
+    Line(offsetl7 + 4*i - 3) = {offsetp6 + 4*i - 3, offsetp6 + 4*i - 4};
+    Line(offsetl7 + 4*i - 2) = {offsetp6 + 4*i - 2, offsetp6 + 4*i - 3};
+    Line(offsetl7 + 4*i - 1) = {offsetp6 + 4*i - 1, offsetp6 + 4*i - 2};
+    Line(offsetl7 + 4*i) = {offsetp6 + 4*i, offsetp6 + 4*i - 1};
+EndFor
+
+// définition des curve loop et surface du BEM_domain2
+Curve Loop(offsets3 + 3) = {offsetl2:offsetl2+4*N_fins,5,6,7}; // exterior boundary of BEM_domain_2
+Curve Loop(offsets3 + 4) = {offsetl6 + 1 : offsetl6 + 8, offsetl7 + 4*(N_fins-1):offsetl7+1:-1};
+Plane Surface(offsets3 + 2) = {offsets3 + 3, offsets3 + 4};
+
+Physical Surface("BEM_domain_2", 9) = {offsets3 + 2};
+Physical Curve("BEM_FEM_boundary_2", 10) = {offsetl2:offsetl2+4*N_fins};
+Physical Curve("electrode_2", 11) = {offsetl6 + 1 : offsetl6 + 8, offsetl7 + 4*(N_fins-1):offsetl7+1:-1};
+Physical Curve("outside_2", 12) = {5,6,7};
\ No newline at end of file
diff --git a/srcs/longitudinal_comb.geo b/srcs/longitudinal_comb.geo
new file mode 100644
index 0000000000000000000000000000000000000000..6c89eec081168abdcadd2fbd9403a00c051875fd
--- /dev/null
+++ b/srcs/longitudinal_comb.geo
@@ -0,0 +1,147 @@
+scale = 1e-5;
+
+h_tot = 20*scale;
+h_base = 1*scale;
+h_pin = 2.5*scale;
+h_space = 1.2*scale;
+
+l_tot = 20*scale;
+l_pin = 0.8*scale;
+l_space = 0.5*scale;
+
+t_electrode = 1*scale; // width of fixed electrodes
+// FEM domain
+Point(1) = {-l_tot/2, h_base/2, 0, 0.2*scale};
+Point(2) = {-l_pin/2, h_base/2, 0, 0.2*scale};
+Point(3) = {-l_pin/2, h_base/2 + h_pin, 0, 0.2*scale};
+Point(4) = {l_pin/2, h_base/2 + h_pin, 0, 0.2*scale};
+Point(5) = {l_pin/2, h_base/2, 0, 0.2*scale};
+Point(6) = {l_tot/2, h_base/2, 0, 0.2*scale};
+Point(7) = {l_tot/2, -h_base/2, 0, 0.2*scale};
+Point(8) = {l_pin/2, -h_base/2, 0, 0.2*scale};
+Point(9) = {l_pin/2, -(h_base/2 + h_pin), 0, 0.2*scale};
+Point(10) = {-l_pin/2, -(h_base/2 + h_pin), 0, 0.2*scale};
+Point(11) = {-l_pin/2, -h_base/2, 0, 0.2*scale};
+Point(12) = {-l_tot/2, -h_base/2, 0, 0.2*scale};
+
+// FEM domain
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {3, 4};
+Line(4) = {4, 5};
+Line(5) = {5, 6};
+Line(6) = {6, 7};
+Line(7) = {7, 8};
+Line(8) = {8, 9};
+Line(9) = {9, 10};
+Line(10) = {10, 11};
+Line(11) = {11, 12};
+Line(12) = {12, 1};
+
+Curve Loop(1) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+Plane Surface(1) = {1};
+
+Recombine Surface {1}; // quads instead of triangles
+
+Physical Curve("left", 1) = {12};
+Physical Curve("right", 2) = {6};
+
+Physical Surface("FEM_domain", 3) = {1};
+Physical Curve("BEM_FEM_boundary", 4) = {1, 2, 3, 4, 5, 7, 8, 9, 10, 11};
+
+// mechanical properties and boundary conditions
+SetNumber("Boundary Conditions/left/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/left/uy", 0);
+SetNumber("Boundary Conditions/right/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/right/uy", 0);
+SetNumber("Materials/domain/Young", 210e3); // A DETERMINER PRECISEMENT
+SetNumber("Materials/domain/Poisson", 0.3);
+SetNumber("Materials/domain/rho",7800); //volumic mass of acier
+SetNumber("Volumic Forces/FEM_domain/bx",0); // acceleration of accelerometer
+SetNumber("Volumic Forces/FEM_domain/by",-200.); 
+
+// BEM domain 1
+Point(13) = {-(l_pin/2 + l_space + t_electrode), -(h_base/2 + h_pin + h_space + t_electrode), 0, 0.2*scale}; // first fixed electrode
+Point(14) = {-(l_pin/2 + l_space + t_electrode), -(h_base/2 + h_space), 0, 0.2*scale};
+Point(15) = {-(l_pin/2 + l_space), -(h_base/2 + h_space), 0, 0.2*scale};
+Point(16) = {-(l_pin/2 + l_space), -(h_base/2 + h_pin + h_space), 0, 0.2*scale};
+Point(17) = {l_pin/2 + l_space, -(h_base/2 + h_pin + h_space), 0, 0.2*scale};
+Point(18) = {l_pin/2 + l_space, -(h_base/2 + h_space), 0, 0.2*scale};
+Point(19) = {l_pin/2 + l_space + t_electrode, -(h_base/2 + h_space), 0, 0.2*scale};
+Point(20) = {l_pin/2 + l_space + t_electrode, -(h_base/2 + h_pin + h_space + t_electrode), 0, 0.2*scale};
+
+Line(13) = {13, 14};
+Line(14) = {14, 15};
+Line(15) = {15, 16};
+Line(16) = {16, 17};
+Line(17) = {17, 18};
+Line(18) = {18, 19};
+Line(19) = {19, 20};
+Line(20) = {20, 13};
+
+Point(29) = {-l_tot/2, -h_tot/2, 0, 0.2*scale};
+Point(30) = {l_tot/2, -h_tot/2, 0, 0.2*scale};
+
+Line(29) = {12, 29};
+Line(30) = {29, 30};
+Line(31) = {30, 7};
+
+Curve Loop(2) = {29, 30, 31, 7, 8, 9, 10, 11};
+Curve Loop(3) = {13, 14, 15, 16, 17, 18, 19, 20};
+Plane Surface(2) = {2, 3};
+
+Physical Surface("BEM_domain_1", 5) = {2};
+Physical Curve("BEM_FEM_boundary_1", 6) = {7, 8, 9, 10, 11};
+Physical Curve("electrode_1", 7) = {13, 14, 15, 16, 17, 18, 19, 20};
+Physical Curve("outside_1", 8) = {29, 30, 31};
+
+phi_1 = 0.1;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_1/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_1/BEM_domain_1/dirichlet", phi_1);
+SetNumber("Boundary Conditions/outside_1/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+// BEM domain 2
+Point(21) = {-(l_pin/2 + l_space + t_electrode), h_base/2 + h_space, 0, 0.2*scale}; // second fixed electrode
+Point(22) = {-(l_pin/2 + l_space + t_electrode), h_base/2 + h_pin + h_space + t_electrode, 0, 0.2*scale}; 
+Point(23) = {l_pin/2 + l_space + t_electrode, h_base/2 + h_pin + h_space + t_electrode, 0, 0.2*scale};
+Point(24) = {l_pin/2 + l_space + t_electrode, h_base/2 + h_space, 0, 0.2*scale};
+Point(25) = {l_pin/2 + l_space, h_base/2 + h_space, 0, 0.2*scale};
+Point(26) = {l_pin/2 + l_space, h_base/2 + h_pin + h_space, 0, 0.2*scale};
+Point(27) = {-(l_pin/2 + l_space), h_base/2 + h_pin + h_space, 0, 0.2*scale};
+Point(28) = {-(l_pin/2 + l_space), h_base/2 + h_space, 0, 0.2*scale};
+
+
+Line(21) = {21, 22};
+Line(22) = {22, 23};
+Line(23) = {23, 24};
+Line(24) = {24, 25};
+Line(25) = {25, 26};
+Line(26) = {26, 27};
+Line(27) = {27, 28};
+Line(28) = {28, 21};
+
+Point(31) = {l_tot/2, h_tot/2, 0, 0.2*scale};
+Point(32) = {-l_tot/2, h_tot/2, 0, 0.2*scale};
+
+Line(32) = {6, 31};
+Line(33) = {31, 32};
+Line(34) = {32, 1};
+
+Curve Loop(4) = {1, 2, 3, 4, 5, 32, 33, 34};
+Curve Loop(5) = {21, 22, 23, 24, 25, 26, 27, 28};
+Plane Surface(3) = {4, 5};
+
+Physical Surface("BEM_domain_2", 9) = {3};
+Physical Curve("BEM_FEM_boundary_2", 10) = {1, 2, 3, 4, 5};
+Physical Curve("electrode_2", 11) = {21, 22, 23, 24, 25, 26, 27, 28};
+Physical Curve("outside_2", 12) = {32, 33, 34};
+
+phi_2 = 25;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_2/BEM_domain_2/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_2/BEM_domain_2/dirichlet", phi_2);
+SetNumber("Boundary Conditions/outside_2/BEM_domain_2/neumann", 0);
+SetNumber("Materials/BEM_domain_2/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+
+Mesh.Algorithm = 8;
\ No newline at end of file
diff --git a/srcs/main.cpp b/srcs/main.cpp
index e14a68ff713d1d4d4c8d0e2ab0e03695494e3c4c..1bacc6c05934e5e4f838becfe2b4f1a0f656bf6f 100644
--- a/srcs/main.cpp
+++ b/srcs/main.cpp
@@ -13,10 +13,11 @@ int main(int argc, char **argv)
         return 0;
     }
 
-    bool nonLinearSolver = true; // use non-linear solver or not
+    bool untangleMesh = false; // untangle geometry (deformed geometry, only available for nonLinear)
 
     // If compiled with OpenMP support, gmsh::initialize 
     // also sets the number of threads to "General.NumThreads".
+    double start = omp_get_wtime();
     int nthreads = omp_get_max_threads();
     gmsh::initialize();
     omp_set_num_threads(nthreads);
@@ -26,6 +27,9 @@ int main(int argc, char **argv)
 
     Eigen::initParallel();
 
+    // determine if non linear solver must be set
+    bool nonLinearSolver = getNonLinearParameter(); 
+
     if(nonLinearSolver)
     {
 
@@ -42,11 +46,10 @@ int main(int argc, char **argv)
 
         int viewTagU = gmsh::view::add("u"); // à modifier plus tard
         int viewTagF = gmsh::view::add("f");
-    
 
 
-        solverBEM(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, 1);
-        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, 1, viewTagU, viewTagF);
+        solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap, postProcessing, 1, false);
+        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, 1, viewTagU, viewTagF, false);
         
         std::vector<int> nodeTags(boundaryDisplacementMap.size());
         std::vector<double> displacements(boundaryDisplacementMap.size());
@@ -55,7 +58,7 @@ int main(int argc, char **argv)
 
         double relativeDisplacement;
         const double criticalNorm = 0.0000001;
-        const int maxNbIteration = 10; // à modifier
+        const int maxNbIteration = 50; // à modifier
 
         int i = 0;
         for(auto p : boundaryDisplacementMap)
@@ -67,8 +70,8 @@ int main(int argc, char **argv)
 
         for(iteration = 2; iteration <= maxNbIteration; iteration++)
         {        
-            solverBEM(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration);
-            solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF);
+            solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap, postProcessing, iteration, false);
+            solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF, false);
 
             i = 0;
             relativeDisplacement = 0;
@@ -87,54 +90,26 @@ int main(int argc, char **argv)
             }
             relativeDisplacement = sqrt(relativeDisplacement/i);
             //std::cout << iteration << ", " << relativeDisplacement << ";\n";
-            // std::cout << "Iteration: " << iteration << "\t-> Averaged relative displacement = " << relativeDisplacement << "\n";
+            std::cout << "Iteration: " << iteration << "\t-> Averaged relative displacement = " << relativeDisplacement << "\n";
             if(relativeDisplacement < criticalNorm)
                 break;
         }
 
 
         nbViews = 0;
+        solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap, postProcessing, iteration, false);
         postProcessing = true;
-        solverBEM(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration);
-        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF);
+        solverFEMnonLinear(electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF, untangleMesh);
 
-        /*--------get physical groups--------------*/
-        /*std::map<std::string, std::pair<int, int>> groups;
-        gmsh::vectorpair dimTags;
-        gmsh::model::getPhysicalGroups(dimTags);
-        for (std::size_t i = 0; i < dimTags.size(); ++i)
+        if(untangleMesh)
         {
-            int dim = dimTags[i].first;
-            int tag = dimTags[i].second;
-            std::string name;
-            gmsh::model::getPhysicalName(dim, tag, name);
-            groups[name] = {dim, tag};
+            std::map<int,std::pair<double,double>> boundaryDisplacementMap2;
+            solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap2, postProcessing, iteration, untangleMesh);
         }
-
-        std::string groupname = "BEM_domain";
-        int dim = groups[groupname].first;
-        int tag = groups[groupname].second;
-
-        std::vector<int> tags;
-        gmsh::model::getEntitiesForPhysicalGroup(dim, tag, tags);
-
-        gmsh::vectorpair dimTagsBis(tags.size());
-        for(size_t i = 0; i < tags.size(); i++)
+        else
         {
-            dimTagsBis[i] = std::pair<int,int>(dim, tags[i]);
+            solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap, postProcessing, iteration, false);
         }
-
-        for(auto &p:boundaryDisplacementMap)
-        {
-            std::vector<double> coord, parametricCoord;
-            int dim, tag;
-            gmsh::model::mesh::getNode(p.first, coord, parametricCoord, dim, tag);
-            std::vector<double> total_disp = {coord[0] + p.second.first, coord[1] + p.second.second, coord[2]};
-            gmsh::model::mesh::setNode(p.first, total_disp, {});
-        }
-        gmsh::model::mesh::optimize("UntangleMeshGeometry", false, 1, dimTagsBis);
-        std::map<int,std::pair<double,double>> boundaryDisplacementMap2;
-        solverBEM(argc, argv, electrostaticPressure, boundaryDisplacementMap2, nbViews, postProcessing, iteration);*/
     }
     else
     {
@@ -145,7 +120,7 @@ int main(int argc, char **argv)
 
         int nbViews = 0;
 
-        solverBEM(electrostaticPressure, boundaryDisplacementMap, nbViews, true, 1);
+        solverBEM(electrostaticPressure, nbViews, boundaryDisplacementMap, true, 1, false);
         solverFEM(electrostaticPressure, nbViews);
 
     }
@@ -153,130 +128,11 @@ int main(int argc, char **argv)
     //double fem_end = omp_get_wtime();
     //std::cout << "time for FEM: " << fem_end - bem_end << "\n";
 
+    double total_time = omp_get_wtime() - start;
+    std::cout << "total execution time: " << total_time << " [s]. \n";
+
     gmsh::fltk::run();
     
     gmsh::finalize();
     return 0;
-}
-
-
-
-
-
-
-// #include "functionsBEM.hpp"
-// #include "functionsFEM.hpp"
-
-// #include <gmsh.h>
-// #include <iostream>
-// #include <omp.h>
-
-// int main(int argc, char **argv)
-// {
-//     if (argc < 2)
-//     {
-//         std::cout << "Usage: " << argv[0] << " <geo_file>\n";
-//         return 0;
-//     }
-
-//     bool nonLinearSolver = true; // use non-linear solver or not
-
-//     // If compiled with OpenMP support, gmsh::initialize 
-//     // also sets the number of threads to "General.NumThreads".
-//     int nthreads = omp_get_max_threads();
-//     gmsh::initialize();
-//     omp_set_num_threads(nthreads);
-
-//     gmsh::open(argv[1]);
-//     gmsh::model::mesh::generate(2);
-
-//     Eigen::initParallel();
-
-//     if(nonLinearSolver)
-//     {
-
-//         bool postProcessing = 0; // pass it as an argument to the solver, only compute post processing at last iteration
-
-//         std::map<int, double> electrostaticPressure;
-//         std::map<int,std::pair<double,double>> boundaryDisplacementMap;
-
-//         int nbViews = 0;
-//         //double start = omp_get_wtime();
-
-//         int iteration;
-
-//         int viewTagU = gmsh::view::add("u"); // à modifier plus tard
-//         int viewTagF = gmsh::view::add("f");
-
-//         solverBEM(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, 1);
-//         solverFEMnonLinear(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, 1, viewTagU, viewTagF);
-        
-//         std::vector<int> nodeTags(boundaryDisplacementMap.size());
-//         std::vector<double> displacements(boundaryDisplacementMap.size());
-//         std::vector<double> previousDisplacements(boundaryDisplacementMap.size());
-//         std::vector<double> relativeDifference(boundaryDisplacementMap.size());
-
-//         double norm;
-//         const double criticalNorm = 0.0001;
-//         const int maxNbIteration = 40;
-
-//         int i = 0;
-//         for(auto p : boundaryDisplacementMap)
-//         {
-//             nodeTags[i] = p.first;
-//             displacements[i] = sqrt(p.second.first*p.second.first + p.second.second*p.second.second);
-//             i++;
-//         }
-
-//         for(iteration = 2; iteration <= maxNbIteration; iteration++)
-//         {        
-//             solverBEM(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration);
-//             solverFEMnonLinear(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF);
-
-//             i = 0;
-//             norm = 0;
-//             for(auto p : boundaryDisplacementMap)
-//             {
-//                 previousDisplacements[i] = displacements[i];
-//                 displacements[i] = sqrt(p.second.first*p.second.first + p.second.second*p.second.second);
-                
-//                 if(previousDisplacements[i] != 0.0)
-//                     relativeDifference[i] = abs( (displacements[i] - previousDisplacements[i]) / previousDisplacements[i] );
-//                 else
-//                     relativeDifference[i] = 0;
-                
-//                 norm += relativeDifference[i]*relativeDifference[i];
-//                 i++;
-//             }
-//             norm = sqrt(norm/i);
-//             std::cout << "Norm (iteration '" << iteration << "'): " << norm << "\n";
-//             if(norm < criticalNorm)
-//                 break;
-//         }
-
-//         postProcessing = true;
-//         solverBEM(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration);
-//         solverFEMnonLinear(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, postProcessing, iteration, viewTagU, viewTagF);
-//     }
-//     else
-//     {
-
-//         std::map<int, double> electrostaticPressure;
-
-//         std::map<int,std::pair<double,double>> boundaryDisplacementMap;
-
-//         int nbViews = 0;
-
-//         solverBEM(argc, argv, electrostaticPressure, boundaryDisplacementMap, nbViews, true, 1);
-//         solverFEM(argc, argv, electrostaticPressure, nbViews);
-
-//     }
-
-//     //double fem_end = omp_get_wtime();
-//     //std::cout << "time for FEM: " << fem_end - bem_end << "\n";
-
-//     gmsh::fltk::run();
-    
-//     gmsh::finalize();
-//     return 0;
-// }
+}
\ No newline at end of file
diff --git a/srcs/squeeze.geo b/srcs/squeeze.geo
index c5ec269c69880a8dcd24dc3a5edce4bf8e0dd808..ad1a4a9bd13f24d997c7c2e461eb74453df44709 100644
--- a/srcs/squeeze.geo
+++ b/srcs/squeeze.geo
@@ -96,3 +96,4 @@ phi_top = 20;
 SetNumber("Boundary Conditions/mass/BEM_domain_1/dirichlet", 0);
 SetNumber("Boundary Conditions/Electrode/BEM_domain_1/dirichlet", phi_top);
 SetNumber("Boundary Conditions/rest_of_outside/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
diff --git a/srcs/transverse_comb.geo b/srcs/transverse_comb.geo
new file mode 100644
index 0000000000000000000000000000000000000000..21122d65ca96ae9a77466cb6eb8c97cf2f302e65
--- /dev/null
+++ b/srcs/transverse_comb.geo
@@ -0,0 +1,157 @@
+scale = 1e-5;
+
+h_tot = 20*scale;
+h_base = 3*scale;
+h_pin = 2.5*scale;
+h_space = 1*scale;
+
+l_tot = 20*scale;
+l_base = 1*scale;
+l_pin = 0.8*scale;
+l_space = 1.2*scale;
+
+t_electrode = 1*scale; // width of fixed electrodes
+// FEM domain
+Point(1) = {-l_tot/2, -h_tot/2, 0, 0.2*scale};
+Point(2) = {-l_tot/2, h_tot/2, 0, 0.2*scale};
+Point(3) = {-(l_tot/2 - l_base), h_tot/2, 0, 0.2*scale};
+Point(4) = {-(l_tot/2 - l_base), h_base/2, 0, 0.2*scale};
+Point(5) = {-l_pin/2, h_base/2, 0, 0.2*scale};
+Point(6) = {-l_pin/2, h_base/2 + h_pin, 0, 0.2*scale};
+Point(7) = {l_pin/2, h_base/2 + h_pin, 0, 0.2*scale};
+Point(8) = {l_pin/2, h_base/2, 0, 0.2*scale};
+Point(9) = {(l_tot/2 - l_base), h_base/2, 0, 0.2*scale};
+Point(10) = {(l_tot/2 - l_base), h_tot/2, 0, 0.2*scale};
+Point(11) = {l_tot/2, h_tot/2, 0, 0.2*scale};
+Point(12) = {l_tot/2, -h_tot/2, 0, 0.2*scale};
+Point(13) = {(l_tot/2 - l_base), -h_tot/2, 0, 0.2*scale};
+Point(14) = {(l_tot/2 - l_base), -h_base/2, 0, 0.2*scale};
+Point(15) = {l_pin/2, -h_base/2, 0, 0.2*scale};
+Point(16) = {l_pin/2, -(h_base/2 + h_pin), 0, 0.2*scale};
+Point(17) = {-l_pin/2, -(h_base/2 + h_pin), 0, 0.2*scale};
+Point(18) = {-l_pin/2, -h_base/2, 0, 0.2*scale};
+Point(19) = {-(l_tot/2 - l_base), -h_base/2, 0, 0.2*scale};
+Point(20) = {-(l_tot/2 - l_base), -h_tot/2, 0, 0.2*scale};
+
+// FEM domain
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {3, 4};
+Line(4) = {4, 5};
+Line(5) = {5, 6};
+Line(6) = {6, 7};
+Line(7) = {7, 8};
+Line(8) = {8, 9};
+Line(9) = {9, 10};
+Line(10) = {10, 11};
+Line(11) = {11, 12};
+Line(12) = {12, 13};
+Line(13) = {13, 14};
+Line(14) = {14, 15};
+Line(15) = {15, 16};
+Line(16) = {16, 17};
+Line(17) = {17, 18};
+Line(18) = {18, 19};
+Line(19) = {19, 20};
+Line(20) = {20, 1};
+
+Curve Loop(1) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+Plane Surface(1) = {1};
+
+Recombine Surface {1}; // quads instead of triangles
+
+Physical Curve("bottom_left", 1) = {20};
+Physical Curve("top_left", 2) = {2};
+Physical Curve("top_right", 3) = {10};
+Physical Curve("bottom_right", 4) = {12};
+
+Physical Surface("FEM_domain", 5) = {1};
+Physical Curve("BEM_FEM_boundary", 6) = {3, 4, 5, 6, 7, 8, 9, 13, 14, 15, 16, 17, 18, 19};
+
+// mechanical properties and boundary conditions
+SetNumber("Boundary Conditions/bottom_left/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/bottom_left/uy", 0);
+SetNumber("Boundary Conditions/top_left/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/top_left/uy", 0);
+SetNumber("Boundary Conditions/top_right/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/top_right/uy", 0);
+SetNumber("Boundary Conditions/bottom_right/ux", 0.); // encastrement
+SetNumber("Boundary Conditions/bottom_right/uy", 0);
+SetNumber("Materials/domain/Young", 210e3); // A DETERMINER PRECISEMENT
+SetNumber("Materials/domain/Poisson", 0.3);
+SetNumber("Materials/domain/rho",7800); //volumic mass of acier
+SetNumber("Volumic Forces/FEM_domain/bx",50); // acceleration of accelerometer
+SetNumber("Volumic Forces/FEM_domain/by",0.); 
+
+// BEM domain 1
+Point(21) = {-(l_pin/2 + l_space + t_electrode), -(h_base/2 + h_pin + h_space + t_electrode), 0, 0.2*scale}; // first fixed electrode
+Point(22) = {-(l_pin/2 + l_space + t_electrode), -(h_base/2 + h_space), 0, 0.2*scale};
+Point(23) = {-(l_pin/2 + l_space), -(h_base/2 + h_space), 0, 0.2*scale};
+Point(24) = {-(l_pin/2 + l_space), -(h_base/2 + h_pin + h_space), 0, 0.2*scale};
+Point(25) = {l_pin/2 + l_space, -(h_base/2 + h_pin + h_space), 0, 0.2*scale};
+Point(26) = {l_pin/2 + l_space, -(h_base/2 + h_space), 0, 0.2*scale};
+Point(27) = {l_pin/2 + l_space + t_electrode, -(h_base/2 + h_space), 0, 0.2*scale};
+Point(28) = {l_pin/2 + l_space + t_electrode, -(h_base/2 + h_pin + h_space + t_electrode), 0, 0.2*scale};
+
+Line(21) = {21, 22};
+Line(22) = {22, 23};
+Line(23) = {23, 24};
+Line(24) = {24, 25};
+Line(25) = {25, 26};
+Line(26) = {26, 27};
+Line(27) = {27, 28};
+Line(28) = {28, 21};
+
+Line(37) = {20, 13};
+
+Curve Loop(2) = {37, 13, 14, 15, 16, 17, 18, 19};
+Curve Loop(3) = {21, 22, 23, 24, 25, 26, 27, 28};
+Plane Surface(2) = {2, 3};
+
+Physical Surface("BEM_domain_1", 7) = {2};
+Physical Curve("BEM_FEM_boundary_1", 8) = {13, 14, 15, 16, 17, 18, 19};
+Physical Curve("electrode_1", 9) = {21, 22, 23, 24, 25, 26, 27, 28};
+Physical Curve("outside_1", 10) = {37};
+
+phi_1 = 30;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_1/BEM_domain_1/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_1/BEM_domain_1/dirichlet", phi_1);
+SetNumber("Boundary Conditions/outside_1/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
+
+// BEM domain 2
+Point(29) = {-(l_pin/2 + l_space + t_electrode), h_base/2 + h_space, 0, 0.2*scale}; // second fixed electrode
+Point(30) = {-(l_pin/2 + l_space + t_electrode), h_base/2 + h_pin + h_space + t_electrode, 0, 0.2*scale}; 
+Point(31) = {l_pin/2 + l_space + t_electrode, h_base/2 + h_pin + h_space + t_electrode, 0, 0.2*scale};
+Point(32) = {l_pin/2 + l_space + t_electrode, h_base/2 + h_space, 0, 0.2*scale};
+Point(33) = {l_pin/2 + l_space, h_base/2 + h_space, 0, 0.2*scale};
+Point(34) = {l_pin/2 + l_space, h_base/2 + h_pin + h_space, 0, 0.2*scale};
+Point(35) = {-(l_pin/2 + l_space), h_base/2 + h_pin + h_space, 0, 0.2*scale};
+Point(36) = {-(l_pin/2 + l_space), h_base/2 + h_space, 0, 0.2*scale};
+
+
+Line(29) = {29, 30};
+Line(30) = {30, 31};
+Line(31) = {31, 32};
+Line(32) = {32, 33};
+Line(33) = {33, 34};
+Line(34) = {34, 35};
+Line(35) = {35, 36};
+Line(36) = {36, 29};
+
+Line(38) = {10, 3};
+
+Curve Loop(4) = {38, 3, 4, 5, 6, 7, 8, 9};
+Curve Loop(5) = {29, 30, 31, 32, 33, 34, 35, 36};
+Plane Surface(3) = {4, 5};
+
+Physical Surface("BEM_domain_2", 11) = {3};
+Physical Curve("BEM_FEM_boundary_2", 12) = {3, 4, 5, 6, 7, 8, 9};
+Physical Curve("electrode_2", 13) = {29, 30, 31, 32, 33, 34, 35, 36};
+Physical Curve("outside_2", 14) = {38};
+
+phi_2 = 30;
+SetNumber("Boundary Conditions/BEM_FEM_boundary_2/BEM_domain_2/dirichlet", 0);
+SetNumber("Boundary Conditions/electrode_2/BEM_domain_2/dirichlet", phi_2);
+SetNumber("Boundary Conditions/outside_2/BEM_domain_2/neumann", 0);
+SetNumber("Materials/BEM_domain_2/Epsilon", 8.8541878128e-12); // dielectric permittivity
\ No newline at end of file
diff --git a/srcs/two_BEM_test.geo b/srcs/two_BEM_test.geo
index 4b28915da7ee848fdd7038c28ee334b38467eb73..89926c27ade94d3510c858b0f78b71bc8ac2cc14 100644
--- a/srcs/two_BEM_test.geo
+++ b/srcs/two_BEM_test.geo
@@ -92,5 +92,7 @@ Physical Curve("bottom2", 18) = {10};
 Physical Curve("top2", 19) = {5};
 SetNumber("Boundary Conditions/left1/BEM_domain_1/neumann", 0);
 SetNumber("Boundary Conditions/right1/BEM_domain_1/neumann", 0);
+SetNumber("Materials/BEM_domain_1/Epsilon", 8.8541878128e-12); // dielectric permittivity
 SetNumber("Boundary Conditions/bottom2/BEM_domain_2/neumann", 0);
 SetNumber("Boundary Conditions/top2/BEM_domain_2/neumann", 0);
+SetNumber("Materials/BEM_domain_2/Epsilon", 8.8541878128e-12); // dielectric permittivity