Repository: fast-aircraft-design/FAST-OAD (language: python)

Issue:
Sub models
This PR implements the idea in #255, that is to provide a way of replacing only a part of a FAST-OAD module.

Usage is described [here](https://fast-oad.readthedocs.io/en/sub-models-complete/documentation/custom_modules/add_submodels.html).

I aimed at having the `RegisterSubModel` class sharing the same base as the existing `RegisterOpenMDAOSystem` and `RegisterPropulsion` classes, so all these classes have been reworked somehow.

Also, this PR has been the occasion to update some Sphinx settings.


Discussion / hints:

Fix patch:
diff --git a/src/fastoad/models/variable_descriptions.txt b/src/fastoad/models/variable_descriptions.txt
index c7c10ce89..6ad084d75 100644
--- a/src/fastoad/models/variable_descriptions.txt
+++ b/src/fastoad/models/variable_descriptions.txt
@@ -363,7 +363,6 @@ settings:weight:airframe:fuselage:mass:k_fus || correction coefficient: 1.00 if
 settings:weight:airframe:fuselage:mass:k_lg || correction coefficient: 1.05 if main landing gear under wing / 1.10 if main landing gear under fuselage
 settings:weight:airframe:landing_gear:front:weight_ratio || part of aircraft weight that is supported by front landing gear
 settings:weight:airframe:wing:mass:k_mvo || 1.39 for Airbus type aircrafts
-settings:weight:airframe:wing:mass:k_voil || 1.00 if 4 engines / 1.05 if 2 or 3 engines / 1.10 if engines on fuselage
 settings:weight:systems:power:mass:k_elec || electricity coefficient: 1.00 if 2 engines (A300, A310 type) / (1.02 if 2 engines (DC9, Caravelle type) / 1.03 if 3 engines (B727 type) / 1.05 if 3 engines (DC10, L1011 type) / 1.08 if 4 engines (B747 type)
 test:test_variable || for testing (do not remove, keep first)
 tuning:aerodynamics:aircraft:cruise:CD:compressibility:max_value  || maximum authorized value for compressibility drag. Allows to prevent the model from overestimating the compressibility effect, especially for aircraft models after year 2000.
diff --git a/src/fastoad/models/weight/cg/cg.py b/src/fastoad/models/weight/cg/cg.py
index a7a02bc06..f79570ecc 100644
--- a/src/fastoad/models/weight/cg/cg.py
+++ b/src/fastoad/models/weight/cg/cg.py
@@ -17,31 +17,56 @@
 import numpy as np
 import openmdao.api as om
 
-from fastoad.models.weight.cg.cg_components import (
-    ComputeControlSurfacesCG,
-    ComputeGlobalCG,
-    ComputeHTcg,
-    ComputeOthersCG,
-    ComputeTanksCG,
-    ComputeVTcg,
-    ComputeWingCG,
-    UpdateMLG,
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import (
+    SERVICE_FLIGHT_CONTROLS_CG,
+    SERVICE_HORIZONTAL_TAIL_CG,
+    SERVICE_OTHERS_CG,
+    SERVICE_TANKS_CG,
+    SERVICE_VERTICAL_TAIL_CG,
+    SERVICE_WING_CG,
+    SERVICE_GLOBAL_CG,
+    SERVICE_MLG_CG,
+    SERVICE_AIRCRAFT_CG,
 )
+from ..constants import SERVICE_CENTERS_OF_GRAVITY
 
 
+@RegisterSubmodel(SERVICE_CENTERS_OF_GRAVITY, "fastoad.submodel.weight.cg.legacy")
 class CG(om.Group):
     """ Model that computes the global center of gravity """
 
     def setup(self):
-        self.add_subsystem("ht_cg", ComputeHTcg(), promotes=["*"])
-        self.add_subsystem("vt_cg", ComputeVTcg(), promotes=["*"])
-        self.add_subsystem("compute_cg_wing", ComputeWingCG(), promotes=["*"])
-        self.add_subsystem("compute_cg_control_surface", ComputeControlSurfacesCG(), promotes=["*"])
-        self.add_subsystem("compute_cg_tanks", ComputeTanksCG(), promotes=["*"])
-        self.add_subsystem("compute_cg_others", ComputeOthersCG(), promotes=["*"])
-        self.add_subsystem("compute_cg", ComputeGlobalCG(), promotes=["*"])
-        self.add_subsystem("update_mlg", UpdateMLG(), promotes=["*"])
-        self.add_subsystem("aircraft", ComputeAircraftCG(), promotes=["*"])
+
+        self.add_subsystem(
+            "ht_cg", RegisterSubmodel.get_submodel(SERVICE_HORIZONTAL_TAIL_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "vt_cg", RegisterSubmodel.get_submodel(SERVICE_VERTICAL_TAIL_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "compute_cg_wing", RegisterSubmodel.get_submodel(SERVICE_WING_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "compute_cg_control_surface",
+            RegisterSubmodel.get_submodel(SERVICE_FLIGHT_CONTROLS_CG),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "compute_cg_tanks", RegisterSubmodel.get_submodel(SERVICE_TANKS_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "compute_cg_others", RegisterSubmodel.get_submodel(SERVICE_OTHERS_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "compute_cg", RegisterSubmodel.get_submodel(SERVICE_GLOBAL_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "update_mlg", RegisterSubmodel.get_submodel(SERVICE_MLG_CG), promotes=["*"]
+        )
+        self.add_subsystem(
+            "aircraft", RegisterSubmodel.get_submodel(SERVICE_AIRCRAFT_CG), promotes=["*"]
+        )
 
         # Solvers setup
         self.nonlinear_solver = om.NonlinearBlockGS()
@@ -52,6 +77,7 @@ def setup(self):
         self.linear_solver.options["iprint"] = 0
 
 
+@RegisterSubmodel(SERVICE_AIRCRAFT_CG, "fastoad.submodel.weight.cg.aircraft.legacy")
 class ComputeAircraftCG(om.ExplicitComponent):
     """ Compute position of aircraft CG from CG ratio """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/__init__.py b/src/fastoad/models/weight/cg/cg_components/__init__.py
index 41211db7f..e3f407dd0 100644
--- a/src/fastoad/models/weight/cg/cg_components/__init__.py
+++ b/src/fastoad/models/weight/cg/cg_components/__init__.py
@@ -2,7 +2,7 @@
 Estimation of centers of gravity
 """
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -13,18 +13,3 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-from .compute_cg_control_surfaces import ComputeControlSurfacesCG
-from .compute_cg_loadcase1 import ComputeCGLoadCase1
-from .compute_cg_loadcase2 import ComputeCGLoadCase2
-from .compute_cg_loadcase3 import ComputeCGLoadCase3
-from .compute_cg_loadcase4 import ComputeCGLoadCase4
-from .compute_cg_others import ComputeOthersCG
-from .compute_cg_ratio_aft import ComputeCGRatioAft
-from .compute_cg_tanks import ComputeTanksCG
-from .compute_cg_wing import ComputeWingCG
-from .compute_global_cg import ComputeGlobalCG
-from .compute_ht_cg import ComputeHTcg
-from .compute_max_cg_ratio import ComputeMaxCGratio
-from .compute_vt_cg import ComputeVTcg
-from .update_mlg import UpdateMLG
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_control_surfaces.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_control_surfaces.py
index ad4be296a..a6d78a82d 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_control_surfaces.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_cg_control_surfaces.py
@@ -1,7 +1,6 @@
 """
     Estimation of control surfaces center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,11 +13,18 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_FLIGHT_CONTROLS_CG
 
 
-class ComputeControlSurfacesCG(ExplicitComponent):
+@RegisterSubmodel(
+    SERVICE_FLIGHT_CONTROLS_CG, "fastoad.submodel.weight.cg.wing.control_surfaces.legacy"
+)
+class ComputeControlSurfacesCG(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Control surfaces center of gravity estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase1.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase1.py
deleted file mode 100644
index 9c7caa336..000000000
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase1.py
+++ /dev/null
@@ -1,66 +0,0 @@
-"""
-    Estimation of center of gravity for load case 1
-"""
-
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
-#  FAST is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
-
-
-class ComputeCGLoadCase1(ExplicitComponent):
-    # TODO: Document equations. Cite sources
-    """ Center of gravity estimation for load case 1 """
-
-    def setup(self):
-        self.add_input("data:geometry:wing:MAC:length", val=np.nan, units="m")
-        self.add_input("data:geometry:wing:MAC:at25percent:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:PAX:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:rear_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:front_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:TLAR:NPAX", val=np.nan)
-        self.add_input("data:weight:aircraft_empty:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:aircraft_empty:mass", val=np.nan, units="kg")
-
-        self.add_output("data:weight:aircraft:load_case_1:CG:MAC_position")
-
-    def setup_partials(self):
-        self.declare_partials("*", "*", method="fd")
-
-    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
-        l0_wing = inputs["data:geometry:wing:MAC:length"]
-        fa_length = inputs["data:geometry:wing:MAC:at25percent:x"]
-        cg_pax = inputs["data:weight:payload:PAX:CG:x"]
-        cg_rear_fret = inputs["data:weight:payload:rear_fret:CG:x"]
-        cg_front_fret = inputs["data:weight:payload:front_fret:CG:x"]
-        npax = inputs["data:TLAR:NPAX"]
-        x_cg_plane_aft = inputs["data:weight:aircraft_empty:CG:x"]
-        x_cg_plane_down = inputs["data:weight:aircraft_empty:mass"]
-        x_cg_plane_up = x_cg_plane_aft * x_cg_plane_down
-
-        # TODO: factorize the four load cases as they are relatively similar
-        weight_pax = npax * 80.0
-        weight_rear_fret = 1.0
-        weight_front_fret = 0.0
-        weight_pl = weight_pax + weight_rear_fret + weight_front_fret
-        x_cg_pl_1 = (
-            weight_pax * cg_pax
-            + weight_rear_fret * cg_rear_fret
-            + weight_front_fret * cg_front_fret
-        ) / weight_pl
-        x_cg_plane_pl_1 = (x_cg_plane_up + weight_pl * x_cg_pl_1) / (
-            x_cg_plane_down + weight_pl
-        )  # forward
-        cg_ratio_pl_1 = (x_cg_plane_pl_1 - fa_length + 0.25 * l0_wing) / l0_wing
-
-        outputs["data:weight:aircraft:load_case_1:CG:MAC_position"] = cg_ratio_pl_1
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase2.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase2.py
deleted file mode 100644
index 5b6dede41..000000000
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase2.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""
-    Estimation of center of gravity for load case 2
-"""
-
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
-#  FAST is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
-
-
-class ComputeCGLoadCase2(ExplicitComponent):
-    # TODO: Document equations. Cite sources
-    """ Center of gravity estimation for load case 2 """
-
-    def setup(self):
-        self.add_input("data:geometry:wing:MAC:length", val=np.nan, units="m")
-        self.add_input("data:geometry:wing:MAC:at25percent:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:PAX:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:rear_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:front_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:TLAR:NPAX", val=np.nan)
-        self.add_input("data:weight:aircraft:MFW", val=np.nan, units="kg")
-        self.add_input("data:weight:fuel_tank:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:aircraft_empty:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:aircraft_empty:mass", val=np.nan, units="kg")
-
-        self.add_output("data:weight:aircraft:load_case_2:CG:MAC_position")
-
-    def setup_partials(self):
-        self.declare_partials("*", "*", method="fd")
-
-    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
-        l0_wing = inputs["data:geometry:wing:MAC:length"]
-        fa_length = inputs["data:geometry:wing:MAC:at25percent:x"]
-        cg_pax = inputs["data:weight:payload:PAX:CG:x"]
-        cg_rear_fret = inputs["data:weight:payload:rear_fret:CG:x"]
-        cg_front_fret = inputs["data:weight:payload:front_fret:CG:x"]
-        npax = inputs["data:TLAR:NPAX"]
-        x_cg_plane_aft = inputs["data:weight:aircraft_empty:CG:x"]
-        x_cg_plane_down = inputs["data:weight:aircraft_empty:mass"]
-        x_cg_plane_up = x_cg_plane_aft * x_cg_plane_down
-        mfw = inputs["data:weight:aircraft:MFW"]
-        cg_tank = inputs["data:weight:fuel_tank:CG:x"]
-
-        weight_pax = npax * 90.0
-        weight_rear_fret = npax * 20
-        weight_front_fret = npax * 20
-        weight_pl = weight_pax + weight_rear_fret + weight_front_fret
-        x_cg_pl_2 = (
-            weight_pax * cg_pax
-            + weight_rear_fret * cg_rear_fret
-            + weight_front_fret * cg_front_fret
-        ) / (weight_pl)
-        x_cg_plane_pl_2 = (x_cg_plane_up + weight_pl * x_cg_pl_2 + mfw * cg_tank) / (
-            x_cg_plane_down + weight_pl + mfw
-        )  # forward
-        cg_ratio_pl_2 = (x_cg_plane_pl_2 - fa_length + 0.25 * l0_wing) / l0_wing
-
-        outputs["data:weight:aircraft:load_case_2:CG:MAC_position"] = cg_ratio_pl_2
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase3.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase3.py
deleted file mode 100644
index c09b749f4..000000000
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase3.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""
-    Estimation of center of gravity for load case 3
-"""
-
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
-#  FAST is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
-
-
-class ComputeCGLoadCase3(ExplicitComponent):
-    # TODO: Document equations. Cite sources
-    """ Center of gravity estimation for load case 3 """
-
-    def setup(self):
-        self.add_input("data:geometry:wing:MAC:length", val=np.nan, units="m")
-        self.add_input("data:geometry:wing:MAC:at25percent:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:PAX:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:rear_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:front_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:TLAR:NPAX", val=np.nan)
-        self.add_input("data:weight:aircraft_empty:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:aircraft_empty:mass", val=np.nan, units="kg")
-
-        self.add_output("data:weight:aircraft:load_case_3:CG:MAC_position")
-
-    def setup_partials(self):
-        self.declare_partials("*", "*", method="fd")
-
-    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
-        l0_wing = inputs["data:geometry:wing:MAC:length"]
-        fa_length = inputs["data:geometry:wing:MAC:at25percent:x"]
-        cg_pax = inputs["data:weight:payload:PAX:CG:x"]
-        cg_rear_fret = inputs["data:weight:payload:rear_fret:CG:x"]
-        cg_front_fret = inputs["data:weight:payload:front_fret:CG:x"]
-        npax = inputs["data:TLAR:NPAX"]
-        x_cg_plane_aft = inputs["data:weight:aircraft_empty:CG:x"]
-        x_cg_plane_down = inputs["data:weight:aircraft_empty:mass"]
-        x_cg_plane_up = x_cg_plane_aft * x_cg_plane_down
-
-        weight_pax = npax * 90.0
-        weight_rear_fret = npax * 10.0
-        weight_front_fret = 0.0
-        weight_pl = weight_pax + weight_rear_fret + weight_front_fret
-        x_cg_pl_3 = (
-            weight_pax * cg_pax
-            + weight_rear_fret * cg_rear_fret
-            + weight_front_fret * cg_front_fret
-        ) / weight_pl
-        x_cg_plane_pl_3 = (x_cg_plane_up + weight_pl * x_cg_pl_3) / (
-            x_cg_plane_down + weight_pl
-        )  # forward
-        cg_ratio_pl_3 = (x_cg_plane_pl_3 - fa_length + 0.25 * l0_wing) / l0_wing
-
-        outputs["data:weight:aircraft:load_case_3:CG:MAC_position"] = cg_ratio_pl_3
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase4.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase4.py
deleted file mode 100644
index 779b3a767..000000000
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_loadcase4.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""
-    Estimation of center of gravity for load case 4
-"""
-
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
-#  FAST is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#  You should have received a copy of the GNU General Public License
-#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
-import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
-
-
-class ComputeCGLoadCase4(ExplicitComponent):
-    # TODO: Document equations. Cite sources
-    """ Center of gravity estimation for load case 4 """
-
-    def setup(self):
-        self.add_input("data:geometry:wing:MAC:length", val=np.nan, units="m")
-        self.add_input("data:geometry:wing:MAC:at25percent:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:PAX:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:rear_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:payload:front_fret:CG:x", val=np.nan, units="m")
-        self.add_input("data:TLAR:NPAX", val=np.nan)
-        self.add_input("data:weight:aircraft_empty:CG:x", val=np.nan, units="m")
-        self.add_input("data:weight:aircraft_empty:mass", val=np.nan, units="kg")
-
-        self.add_output("data:weight:aircraft:load_case_4:CG:MAC_position")
-
-    def setup_partials(self):
-        self.declare_partials("*", "*", method="fd")
-
-    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
-        l0_wing = inputs["data:geometry:wing:MAC:length"]
-        fa_length = inputs["data:geometry:wing:MAC:at25percent:x"]
-        cg_pax = inputs["data:weight:payload:PAX:CG:x"]
-        cg_rear_fret = inputs["data:weight:payload:rear_fret:CG:x"]
-        cg_front_fret = inputs["data:weight:payload:front_fret:CG:x"]
-        npax = inputs["data:TLAR:NPAX"]
-        x_cg_plane_aft = inputs["data:weight:aircraft_empty:CG:x"]
-        x_cg_plane_down = inputs["data:weight:aircraft_empty:mass"]
-        x_cg_plane_up = x_cg_plane_aft * x_cg_plane_down
-
-        weight_pax = npax * 90.0
-        weight_rear_fret = npax * 30.0
-        weight_front_fret = npax * 10.0
-        weight_pl = weight_pax + weight_rear_fret + weight_front_fret
-        x_cg_pl_4 = (
-            weight_pax * cg_pax
-            + weight_rear_fret * cg_rear_fret
-            + weight_front_fret * cg_front_fret
-        ) / weight_pl
-        x_cg_plane_pl_4 = (x_cg_plane_up + weight_pl * x_cg_pl_4) / (
-            x_cg_plane_down + weight_pl
-        )  # forward
-        cg_ratio_pl_4 = (x_cg_plane_pl_4 - fa_length + 0.25 * l0_wing) / l0_wing
-
-        outputs["data:weight:aircraft:load_case_4:CG:MAC_position"] = cg_ratio_pl_4
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_others.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_others.py
index ab546ad1a..142dd3d07 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_others.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_cg_others.py
@@ -1,7 +1,6 @@
 """
-    Estimation of other components center of gravities
+    Estimation centers of gravity of other components
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,11 +13,16 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_OTHERS_CG
 
 
-class ComputeOthersCG(ExplicitComponent):
+@RegisterSubmodel(SERVICE_OTHERS_CG, "fastoad.submodel.weight.cg.others.legacy")
+class ComputeOthersCG(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Other components center of gravities estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_ratio_aft.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_ratio_aft.py
index 372d67e8a..571340521 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_ratio_aft.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_cg_ratio_aft.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_EMPTY_AIRCRAFT_CG
 
+
+@RegisterSubmodel(SERVICE_EMPTY_AIRCRAFT_CG, "fastoad.submodel.weight.cg.empty_aircraft.legacy")
 class ComputeCGRatioAft(om.Group):
     def setup(self):
         self.add_subsystem("cg_all", ComputeCG(), promotes=["*"])
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_tanks.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_tanks.py
index 5acc2263a..2c77f3738 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_tanks.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_cg_tanks.py
@@ -1,7 +1,6 @@
 """
     Estimation of tanks center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -18,13 +17,16 @@
 import math
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 from scipy import interpolate
 
 from fastoad.models.geometry.profiles import get_profile
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_TANKS_CG
 
 
-class ComputeTanksCG(ExplicitComponent):
+@RegisterSubmodel(SERVICE_TANKS_CG, "fastoad.submodel.weight.cg.tanks.legacy")
+class ComputeTanksCG(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Tanks center of gravity estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_cg_wing.py b/src/fastoad/models/weight/cg/cg_components/compute_cg_wing.py
index a1ca94c6f..40753db95 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_cg_wing.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_cg_wing.py
@@ -1,7 +1,6 @@
 """
     Estimation of wing center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,11 +13,16 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_WING_CG
 
 
-class ComputeWingCG(ExplicitComponent):
+@RegisterSubmodel(SERVICE_WING_CG, "fastoad.submodel.weight.cg.wing.legacy")
+class ComputeWingCG(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Wing center of gravity estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_global_cg.py b/src/fastoad/models/weight/cg/cg_components/compute_global_cg.py
index 52fb53572..7e5abe5cf 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_global_cg.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_global_cg.py
@@ -1,9 +1,8 @@
 """
     Estimation of global center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -15,24 +14,27 @@
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-from openmdao.api import Group
+import openmdao.api as om
 
-from fastoad.models.weight.cg.cg_components import ComputeCGLoadCase1
-from fastoad.models.weight.cg.cg_components.compute_cg_loadcase2 import ComputeCGLoadCase2
-from fastoad.models.weight.cg.cg_components.compute_cg_loadcase3 import ComputeCGLoadCase3
-from fastoad.models.weight.cg.cg_components.compute_cg_loadcase4 import ComputeCGLoadCase4
-from fastoad.models.weight.cg.cg_components.compute_cg_ratio_aft import ComputeCGRatioAft
-from fastoad.models.weight.cg.cg_components.compute_max_cg_ratio import ComputeMaxCGratio
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .compute_max_cg_ratio import ComputeMaxCGratio
+from ..constants import SERVICE_EMPTY_AIRCRAFT_CG, SERVICE_GLOBAL_CG, SERVICE_LOAD_CASES_CG
 
 
-class ComputeGlobalCG(Group):
+@RegisterSubmodel(SERVICE_GLOBAL_CG, "fastoad.submodel.weight.cg.global.legacy")
+class ComputeGlobalCG(om.Group):
     # TODO: Document equations. Cite sources
     """ Global center of gravity estimation """
 
     def setup(self):
-        self.add_subsystem("cg_ratio_aft", ComputeCGRatioAft(), promotes=["*"])
-        self.add_subsystem("cg_ratio_lc1", ComputeCGLoadCase1(), promotes=["*"])
-        self.add_subsystem("cg_ratio_lc2", ComputeCGLoadCase2(), promotes=["*"])
-        self.add_subsystem("cg_ratio_lc3", ComputeCGLoadCase3(), promotes=["*"])
-        self.add_subsystem("cg_ratio_lc4", ComputeCGLoadCase4(), promotes=["*"])
+        self.add_subsystem(
+            "cg_ratio_empty",
+            RegisterSubmodel.get_submodel(SERVICE_EMPTY_AIRCRAFT_CG),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "cg_ratio_load_cases",
+            RegisterSubmodel.get_submodel(SERVICE_LOAD_CASES_CG),
+            promotes=["*"],
+        )
         self.add_subsystem("cg_ratio_max", ComputeMaxCGratio(), promotes=["*"])
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_ht_cg.py b/src/fastoad/models/weight/cg/cg_components/compute_ht_cg.py
index 43cb786db..d6297d16d 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_ht_cg.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_ht_cg.py
@@ -1,7 +1,6 @@
 """
     Estimation of horizontal tail center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,13 +13,18 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import math
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_HORIZONTAL_TAIL_CG
 
 
-class ComputeHTcg(ExplicitComponent):
+@RegisterSubmodel(SERVICE_HORIZONTAL_TAIL_CG, "fastoad.submodel.weight.cg.horizontal_tail.legacy")
+class ComputeHTcg(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Horizontal tail center of gravity estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_max_cg_ratio.py b/src/fastoad/models/weight/cg/cg_components/compute_max_cg_ratio.py
index f2923dc4c..8e95868b0 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_max_cg_ratio.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_max_cg_ratio.py
@@ -1,7 +1,6 @@
 """
     Estimation of maximum center of gravity ratio
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,20 +13,18 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
 
-class ComputeMaxCGratio(ExplicitComponent):
+class ComputeMaxCGratio(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Maximum center of gravity ratio estimation """
 
     def setup(self):
         self.add_input("data:weight:aircraft:empty:CG:MAC_position", val=np.nan)
-        self.add_input("data:weight:aircraft:load_case_1:CG:MAC_position", val=np.nan)
-        self.add_input("data:weight:aircraft:load_case_2:CG:MAC_position", val=np.nan)
-        self.add_input("data:weight:aircraft:load_case_3:CG:MAC_position", val=np.nan)
-        self.add_input("data:weight:aircraft:load_case_4:CG:MAC_position", val=np.nan)
+        self.add_input("data:weight:aircraft:load_cases:CG:MAC_position:maximum", val=np.nan)
         self.add_input(
             "settings:weight:aircraft:CG:aft:MAC_position:margin",
             val=0.05,
@@ -43,10 +40,9 @@ def setup_partials(self):
     def compute(self, inputs, outputs):
         outputs["data:weight:aircraft:CG:aft:MAC_position"] = inputs[
             "settings:weight:aircraft:CG:aft:MAC_position:margin"
-        ] + max(
-            inputs["data:weight:aircraft:empty:CG:MAC_position"],
-            inputs["data:weight:aircraft:load_case_1:CG:MAC_position"],
-            inputs["data:weight:aircraft:load_case_2:CG:MAC_position"],
-            inputs["data:weight:aircraft:load_case_3:CG:MAC_position"],
-            inputs["data:weight:aircraft:load_case_4:CG:MAC_position"],
+        ] + np.nanmax(
+            [
+                inputs["data:weight:aircraft:empty:CG:MAC_position"],
+                inputs["data:weight:aircraft:load_cases:CG:MAC_position:maximum"],
+            ]
         )
diff --git a/src/fastoad/models/weight/cg/cg_components/compute_vt_cg.py b/src/fastoad/models/weight/cg/cg_components/compute_vt_cg.py
index a5a176e9e..7dc16fb2d 100644
--- a/src/fastoad/models/weight/cg/cg_components/compute_vt_cg.py
+++ b/src/fastoad/models/weight/cg/cg_components/compute_vt_cg.py
@@ -1,7 +1,6 @@
 """
     Estimation of vertical tail center of gravity
 """
-
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
 #  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
@@ -14,13 +13,18 @@
 #  GNU General Public License for more details.
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
 import math
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_VERTICAL_TAIL_CG
 
 
-class ComputeVTcg(ExplicitComponent):
+@RegisterSubmodel(SERVICE_VERTICAL_TAIL_CG, "fastoad.submodel.weight.cg.vertical_tail.legacy")
+class ComputeVTcg(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Vertical tail center of gravity estimation """
 
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/__init__.py b/src/fastoad/models/weight/cg/cg_components/load_cases/__init__.py
new file mode 100644
index 000000000..385ae0611
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/__init__.py
@@ -0,0 +1,12 @@
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase1.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase1.py
new file mode 100644
index 000000000..7a96c8dfc
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase1.py
@@ -0,0 +1,36 @@
+"""
+    Estimation of center of gravity for load case 1
+"""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .compute_cg_loadcase_base import ComputeCGLoadCase
+from .compute_cg_loadcases import SERVICE_LOAD_CASE_CG_PREFIX
+
+CASE_NUMBER = 1
+
+
+@RegisterSubmodel(
+    f"{SERVICE_LOAD_CASE_CG_PREFIX}.{CASE_NUMBER}",
+    f"fastoad.submodel.weight.cg.load_case.legacy.{CASE_NUMBER}",
+)
+class ComputeCGLoadCase1(ComputeCGLoadCase):
+    """ Center of gravity estimation for load case 1 """
+
+    def setup(self):
+        self.options["case_number"] = CASE_NUMBER
+        self.options["mass_per_pax"] = 80.0
+        self.options["mass_front_fret_per_pax"] = 0.0
+        self.options["mass_rear_fret_per_pax"] = 0.0
+        return super().setup()
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase2.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase2.py
new file mode 100644
index 000000000..f9180e598
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase2.py
@@ -0,0 +1,37 @@
+"""
+    Estimation of center of gravity for load case 2
+"""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .compute_cg_loadcase_base import ComputeCGLoadCase
+from .compute_cg_loadcases import SERVICE_LOAD_CASE_CG_PREFIX
+
+CASE_NUMBER = 2
+
+
+@RegisterSubmodel(
+    f"{SERVICE_LOAD_CASE_CG_PREFIX}.{CASE_NUMBER}",
+    f"fastoad.submodel.weight.cg.load_case.legacy.{CASE_NUMBER}",
+)
+class ComputeCGLoadCase2(ComputeCGLoadCase):
+    """ Center of gravity estimation for load case 3 """
+
+    def setup(self):
+        self.options["case_number"] = CASE_NUMBER
+        self.options["mass_per_pax"] = 90.0
+        self.options["mass_front_fret_per_pax"] = 20.0
+        self.options["mass_rear_fret_per_pax"] = 20.0
+        self.options["fuel_mass_variable"] = "data:weight:aircraft:MFW"
+        return super().setup()
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase3.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase3.py
new file mode 100644
index 000000000..7e9fb5bfc
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase3.py
@@ -0,0 +1,37 @@
+"""
+    Estimation of center of gravity for load case 3
+"""
+
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .compute_cg_loadcase_base import ComputeCGLoadCase
+from .compute_cg_loadcases import SERVICE_LOAD_CASE_CG_PREFIX
+
+CASE_NUMBER = 3
+
+
+@RegisterSubmodel(
+    f"{SERVICE_LOAD_CASE_CG_PREFIX}.{CASE_NUMBER}",
+    f"fastoad.submodel.weight.cg.load_case.legacy.{CASE_NUMBER}",
+)
+class ComputeCGLoadCase3(ComputeCGLoadCase):
+    """ Center of gravity estimation for load case 3 """
+
+    def setup(self):
+        self.options["case_number"] = CASE_NUMBER
+        self.options["mass_per_pax"] = 90.0
+        self.options["mass_front_fret_per_pax"] = 0.0
+        self.options["mass_rear_fret_per_pax"] = 10.0
+        return super().setup()
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase4.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase4.py
new file mode 100644
index 000000000..0d2d99765
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase4.py
@@ -0,0 +1,36 @@
+"""
+    Estimation of center of gravity for load case 4
+"""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .compute_cg_loadcase_base import ComputeCGLoadCase
+from .compute_cg_loadcases import SERVICE_LOAD_CASE_CG_PREFIX
+
+CASE_NUMBER = 4
+
+
+@RegisterSubmodel(
+    f"{SERVICE_LOAD_CASE_CG_PREFIX}.{CASE_NUMBER}",
+    f"fastoad.submodel.weight.cg.load_case.legacy.{CASE_NUMBER}",
+)
+class ComputeCGLoadCase4(ComputeCGLoadCase):
+    """ Center of gravity estimation for load case"""
+
+    def setup(self):
+        self.options["case_number"] = CASE_NUMBER
+        self.options["mass_per_pax"] = 90.0
+        self.options["mass_front_fret_per_pax"] = 10.0
+        self.options["mass_rear_fret_per_pax"] = 30.0
+        return super().setup()
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase_base.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase_base.py
new file mode 100644
index 000000000..6655f17b5
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcase_base.py
@@ -0,0 +1,101 @@
+"""CG calculation for load cases."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+import numpy as np
+import openmdao.api as om
+
+
+class ComputeCGLoadCase(om.ExplicitComponent):
+    """
+    Base class for computing load cases for CG calculations.
+    """
+
+    @property
+    def output_name(self):
+        """Builds name of the unique output from option "case_number"."""
+        return "data:weight:aircraft:load_case_%i:CG:MAC_position" % self.options["case_number"]
+
+    def initialize(self):
+        self.options.declare("case_number", 1, types=int)
+        self.options.declare("mass_per_pax", 80.0, types=float)
+        self.options.declare("mass_front_fret_per_pax", 0.0, types=float)
+        self.options.declare("mass_rear_fret_per_pax", 0.0, types=float)
+        self.options.declare("fuel_mass_variable", "", types=str, allow_none=True)
+
+    def setup(self):
+        self.add_input("data:geometry:wing:MAC:length", val=np.nan, units="m")
+        self.add_input("data:geometry:wing:MAC:at25percent:x", val=np.nan, units="m")
+        self.add_input("data:weight:payload:PAX:CG:x", val=np.nan, units="m")
+        self.add_input("data:weight:payload:rear_fret:CG:x", val=np.nan, units="m")
+        self.add_input("data:weight:payload:front_fret:CG:x", val=np.nan, units="m")
+        self.add_input("data:TLAR:NPAX", val=np.nan)
+        self.add_input("data:weight:aircraft_empty:CG:x", val=np.nan, units="m")
+        self.add_input("data:weight:aircraft_empty:mass", val=np.nan, units="kg")
+
+        if self.options["fuel_mass_variable"]:
+            self.add_input(self.options["fuel_mass_variable"], val=np.nan, units="kg")
+            self.add_input("data:weight:fuel_tank:CG:x", val=np.nan, units="m")
+
+        self.add_output(self.output_name)
+
+    def setup_partials(self):
+        self.declare_partials("*", "*", method="fd")
+
+    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
+        l0_wing = inputs["data:geometry:wing:MAC:length"]
+        fa_length = inputs["data:geometry:wing:MAC:at25percent:x"]
+        x_cg_aircraft_empty = inputs["data:weight:aircraft_empty:CG:x"]
+        mass_aircraft_empty = inputs["data:weight:aircraft_empty:mass"]
+
+        mass_payload, x_cg_payload = self._get_payload_mass_and_cg(inputs)
+
+        x_cg_aircraft_with_payload = (
+            mass_aircraft_empty * x_cg_aircraft_empty + mass_payload * x_cg_payload
+        ) / (mass_aircraft_empty + mass_payload)
+        cg_ratio_aircraft_with_payload = (
+            x_cg_aircraft_with_payload - fa_length + 0.25 * l0_wing
+        ) / l0_wing
+        outputs[self.output_name] = cg_ratio_aircraft_with_payload
+
+    def _get_payload_mass_and_cg(self, inputs):
+        """
+
+        :param inputs:
+        :return: tuple (payload mass, X-position of payload CG)
+        """
+
+        cg_pax = inputs["data:weight:payload:PAX:CG:x"]
+        cg_rear_fret = inputs["data:weight:payload:rear_fret:CG:x"]
+        cg_front_fret = inputs["data:weight:payload:front_fret:CG:x"]
+        npax = inputs["data:TLAR:NPAX"]
+
+        mass_pax = npax * self.options["mass_per_pax"]
+        mass_front_fret = inputs["data:TLAR:NPAX"] * self.options["mass_front_fret_per_pax"]
+        mass_rear_fret = inputs["data:TLAR:NPAX"] * self.options["mass_rear_fret_per_pax"]
+        if self.options["fuel_mass_variable"]:
+            mass_fuel = inputs[self.options["fuel_mass_variable"]]
+            cg_fuel = inputs["data:weight:fuel_tank:CG:x"]
+        else:
+            mass_fuel = 0.0
+            cg_fuel = 0.0
+
+        mass_payload = mass_pax + mass_rear_fret + mass_front_fret + mass_fuel
+        x_cg_payload = (
+            mass_pax * cg_pax
+            + mass_rear_fret * cg_rear_fret
+            + mass_front_fret * cg_front_fret
+            + mass_fuel * cg_fuel
+        ) / mass_payload
+
+        return mass_payload, x_cg_payload
diff --git a/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcases.py b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcases.py
new file mode 100644
index 000000000..8554b2812
--- /dev/null
+++ b/src/fastoad/models/weight/cg/cg_components/load_cases/compute_cg_loadcases.py
@@ -0,0 +1,78 @@
+"""Computes and aggregates CG ratios for load cases."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+from itertools import count
+
+import numpy as np
+from openmdao import api as om
+
+from fastoad.models.weight.cg.constants import SERVICE_LOAD_CASES_CG
+from fastoad.module_management.exceptions import FastNoSubmodelFoundError
+from fastoad.module_management.service_registry import RegisterSubmodel
+
+SERVICE_LOAD_CASE_CG_PREFIX = "service.cg.load_case"
+
+
+@RegisterSubmodel(SERVICE_LOAD_CASES_CG, "fastoad.submodel.weight.cg.load_cases.legacy")
+class CGRatiosForLoadCases(om.Group):
+    """Aggregation of CG ratios from load case calculations."""
+
+    def setup(self):
+
+        # We add in our group all the components for declared services that provide CG ratio
+        # for specific load_cases
+        for load_case_count in count():
+            try:
+                system = RegisterSubmodel.get_submodel(
+                    f"{SERVICE_LOAD_CASE_CG_PREFIX}.{load_case_count + 1}"
+                )
+            except FastNoSubmodelFoundError:
+                break
+            self.add_subsystem(f"cg_ratio_lc{load_case_count + 1}", system, promotes_inputs=["*"])
+
+        cg_ratio_aggregator = self.add_subsystem(
+            "cg_ratio_aggregator",
+            om.MuxComp(vec_size=load_case_count),
+            promotes=["data:weight:aircraft:load_cases:CG:MAC_position"],
+        )
+
+        # This part aggregates all CG ratios values in one vector variable.
+        cg_ratio_aggregator.add_var(
+            "data:weight:aircraft:load_cases:CG:MAC_position", shape=(1,), axis=0
+        )
+        for i in range(load_case_count):
+            self.connect(
+                f"cg_ratio_lc{i + 1}.data:weight:aircraft:load_case_{i + 1}:CG:MAC_position",
+                f"cg_ratio_aggregator.data:weight:aircraft:load_cases:CG:MAC_position_{i}",
+            )
+
+        self.add_subsystem("compute_max", MaxCGRatiosForLoadCases(), promotes=["*"])
+
+
+class MaxCGRatiosForLoadCases(om.ExplicitComponent):
+    """Maximum center of gravity ratio from load cases."""
+
+    def setup(self):
+        self.add_input(
+            "data:weight:aircraft:load_cases:CG:MAC_position", val=np.nan, shape_by_conn=True
+        )
+
+        self.add_output("data:weight:aircraft:load_cases:CG:MAC_position:maximum")
+
+    def setup_partials(self):
+        self.declare_partials("*", "*", method="fd")
+
+    def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
+        outputs["data:weight:aircraft:load_cases:CG:MAC_position:maximum"] = (
+            np.nanmax(inputs["data:weight:aircraft:load_cases:CG:MAC_position"]),
+        )
diff --git a/src/fastoad/models/weight/cg/cg_components/update_mlg.py b/src/fastoad/models/weight/cg/cg_components/update_mlg.py
index 9b4a0ffc3..ca01da60a 100644
--- a/src/fastoad/models/weight/cg/cg_components/update_mlg.py
+++ b/src/fastoad/models/weight/cg/cg_components/update_mlg.py
@@ -18,7 +18,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from ..constants import SERVICE_MLG_CG
 
+
+@RegisterSubmodel(SERVICE_MLG_CG, "fastoad.submodel.weight.cg.main_landing_gear")
 class UpdateMLG(om.ExplicitComponent):
     # TODO: Document equations. Cite sources
     """ Main landing gear center of gravity estimation """
diff --git a/src/fastoad/models/weight/cg/constants.py b/src/fastoad/models/weight/cg/constants.py
new file mode 100644
index 000000000..b4295907c
--- /dev/null
+++ b/src/fastoad/models/weight/cg/constants.py
@@ -0,0 +1,25 @@
+"""Constants for CG submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_HORIZONTAL_TAIL_CG = "service.cg.horizontal_tail"
+SERVICE_VERTICAL_TAIL_CG = "service.cg.vertical_tail"
+SERVICE_WING_CG = "service.cg.wing"
+SERVICE_FLIGHT_CONTROLS_CG = "service.cg.wing.control_surfaces"
+SERVICE_TANKS_CG = "service.cg.tanks"
+SERVICE_OTHERS_CG = "service.cg.others"
+SERVICE_GLOBAL_CG = "service.cg.global"
+SERVICE_MLG_CG = "service.cg.mlg"
+SERVICE_AIRCRAFT_CG = "service.cg.aircraft"
+SERVICE_EMPTY_AIRCRAFT_CG = "service.cg.empty_aircraft"
+SERVICE_LOAD_CASES_CG = "service.cg.load_cases"
diff --git a/src/fastoad/models/weight/constants.py b/src/fastoad/models/weight/constants.py
new file mode 100644
index 000000000..f83a5c83c
--- /dev/null
+++ b/src/fastoad/models/weight/constants.py
@@ -0,0 +1,17 @@
+"""Constants for weight submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+
+SERVICE_CENTERS_OF_GRAVITY = "service.weight.cg"
+SERVICE_MASS_BREAKDOWN = "service.weight.mass_breakdown"
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a1_wing_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a1_wing_weight.py
index 9195ea5df..f4d2595f7 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a1_wing_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a1_wing_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_WING_MASS
 
+
+@RegisterSubmodel(SERVICE_WING_MASS, "fastoad.submodel.weight.mass.airframe.wing.legacy")
 class WingWeight(om.ExplicitComponent):
     """
     Wing weight estimation
@@ -42,6 +46,8 @@ def setup(self):
         self.add_input("data:geometry:wing:root:chord", val=np.nan, units="m")
         self.add_input("data:geometry:wing:sweep_25", val=np.nan, units="rad")
         self.add_input("data:geometry:wing:outer_area", val=np.nan, units="m**2")
+        self.add_input("data:geometry:propulsion:engine:count", val=np.nan)
+        self.add_input("data:geometry:propulsion:layout", val=np.nan)
         self.add_input("data:weight:aircraft:MTOW", val=np.nan, units="kg")
         self.add_input("data:weight:aircraft:MLW", val=np.nan, units="kg")
         self.add_input("data:mission:sizing:cs25:sizing_load_1", val=np.nan, units="kg")
@@ -64,7 +70,6 @@ def setup(self):
         self.add_input(
             "tuning:weight:airframe:wing:secondary_parts:mass:offset", val=0.0, units="kg"
         )
-        self.add_input("settings:weight:airframe:wing:mass:k_voil", val=1.0)
         self.add_input("settings:weight:airframe:wing:mass:k_mvo", val=1.39)
 
         self.add_output("data:weight:airframe:wing:mass", units="kg")
@@ -87,6 +92,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
             inputs["data:mission:sizing:cs25:sizing_load_1"],
             inputs["data:mission:sizing:cs25:sizing_load_2"],
         )
+        engine_count = inputs["data:geometry:propulsion:engine:count"]
+        engine_on_fuselage = inputs["data:geometry:propulsion:layout"] == 2
+        if engine_on_fuselage:
+            k_voil = 1.1
+        elif engine_count >= 4:
+            k_voil = 1.0
+        else:
+            k_voil = 1.05
 
         # K factors
         k_a1 = inputs["tuning:weight:airframe:wing:mass:k"]
@@ -101,7 +114,6 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
         offset_a14 = inputs["tuning:weight:airframe:wing:reinforcements:mass:offset"]
         k_a15 = inputs["tuning:weight:airframe:wing:secondary_parts:mass:k"]
         offset_a15 = inputs["tuning:weight:airframe:wing:secondary_parts:mass:offset"]
-        k_voil = inputs["settings:weight:airframe:wing:mass:k_voil"]
         k_mvo = inputs["settings:weight:airframe:wing:mass:k_mvo"]
 
         toc_mean = (3 * toc_root + 2 * toc_kink + toc_tip) / 6
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a2_fuselage_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a2_fuselage_weight.py
index 4fdce0681..5c84abc60 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a2_fuselage_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a2_fuselage_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FUSELAGE_MASS
 
+
+@RegisterSubmodel(SERVICE_FUSELAGE_MASS, "fastoad.submodel.weight.mass.airframe.fuselage.legacy")
 class FuselageWeight(om.ExplicitComponent):
     """
     Fuselage weight estimation
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a3_empennage_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a3_empennage_weight.py
index b52559aa4..d177c7ece 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a3_empennage_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a3_empennage_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_EMPENNAGE_MASS
 
+
+@RegisterSubmodel(SERVICE_EMPENNAGE_MASS, "fastoad.submodel.weight.mass.airframe.empennage.legacy")
 class EmpennageWeight(om.ExplicitComponent):
     """
     Weight estimation for tail planes
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a4_flight_control_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a4_flight_control_weight.py
index 94e53b4a4..c7a07b3f5 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a4_flight_control_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a4_flight_control_weight.py
@@ -17,7 +17,13 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FLIGHT_CONTROLS_MASS
 
+
+@RegisterSubmodel(
+    SERVICE_FLIGHT_CONTROLS_MASS, "fastoad.submodel.weight.mass.airframe.flight_control.legacy",
+)
 class FlightControlsWeight(om.ExplicitComponent):
     """
     Flight controls weight estimation
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a5_landing_gear_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a5_landing_gear_weight.py
index 86e4461a5..3d602034c 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a5_landing_gear_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a5_landing_gear_weight.py
@@ -17,7 +17,13 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_LANDING_GEARS_MASS
 
+
+@RegisterSubmodel(
+    SERVICE_LANDING_GEARS_MASS, "fastoad.submodel.weight.mass.airframe.landing_gears.legacy",
+)
 class LandingGearWeight(om.ExplicitComponent):
     """
     Weight estimation for landing gears
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a6_pylons_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a6_pylons_weight.py
index e880e8a40..7768fadcd 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a6_pylons_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a6_pylons_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_PYLONS_MASS
 
+
+@RegisterSubmodel(SERVICE_PYLONS_MASS, "fastoad.submodel.weight.mass.airframe.pylons.legacy")
 class PylonsWeight(om.ExplicitComponent):
     """
     Weight estimation for pylons
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/a7_paint_weight.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/a7_paint_weight.py
index 3a401dd27..ee2e110a7 100644
--- a/src/fastoad/models/weight/mass_breakdown/a_airframe/a7_paint_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/a7_paint_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_PAINT_MASS
 
+
+@RegisterSubmodel(SERVICE_PAINT_MASS, "fastoad.submodel.weight.mass.airframe.paint.legacy")
 class PaintWeight(om.ExplicitComponent):
     """
     Weight estimation for paint
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/constants.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/constants.py
new file mode 100644
index 000000000..0e6447c5a
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/constants.py
@@ -0,0 +1,21 @@
+"""Constants for airframe mass submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_WING_MASS = "service.mass.airframe.wing"
+SERVICE_FUSELAGE_MASS = "service.mass.airframe.fuselage"
+SERVICE_EMPENNAGE_MASS = "service.mass.airframe.empennage"
+SERVICE_FLIGHT_CONTROLS_MASS = "service.mass.airframe.flight_controls"
+SERVICE_LANDING_GEARS_MASS = "service.mass.airframe.landing_gear"
+SERVICE_PYLONS_MASS = "service.mass.airframe.pylons"
+SERVICE_PAINT_MASS = "service.mass.airframe.paint"
diff --git a/src/fastoad/models/weight/mass_breakdown/a_airframe/sum.py b/src/fastoad/models/weight/mass_breakdown/a_airframe/sum.py
new file mode 100644
index 000000000..aec1c1e1e
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/a_airframe/sum.py
@@ -0,0 +1,89 @@
+"""Computation of airframe mass."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import (
+    SERVICE_EMPENNAGE_MASS,
+    SERVICE_FLIGHT_CONTROLS_MASS,
+    SERVICE_FUSELAGE_MASS,
+    SERVICE_LANDING_GEARS_MASS,
+    SERVICE_PAINT_MASS,
+    SERVICE_PYLONS_MASS,
+    SERVICE_WING_MASS,
+)
+from ..constants import SERVICE_AIRFRAME_MASS, SERVICE_GUST_LOADS
+
+
+@RegisterSubmodel(SERVICE_AIRFRAME_MASS, "fastoad.submodel.weight.mass.airframe.legacy")
+class AirframeWeight(om.Group):
+    """
+    Computes mass of airframe.
+    """
+
+    def setup(self):
+        # Airframe
+        self.add_subsystem(
+            "loads", RegisterSubmodel.get_submodel(SERVICE_GUST_LOADS), promotes=["*"]
+        )
+        self.add_subsystem(
+            "wing_weight", RegisterSubmodel.get_submodel(SERVICE_WING_MASS), promotes=["*"]
+        )
+        self.add_subsystem(
+            "fuselage_weight", RegisterSubmodel.get_submodel(SERVICE_FUSELAGE_MASS), promotes=["*"],
+        )
+        self.add_subsystem(
+            "empennage_weight",
+            RegisterSubmodel.get_submodel(SERVICE_EMPENNAGE_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "flight_controls_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FLIGHT_CONTROLS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "landing_gear_weight",
+            RegisterSubmodel.get_submodel(SERVICE_LANDING_GEARS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "pylons_weight", RegisterSubmodel.get_submodel(SERVICE_PYLONS_MASS), promotes=["*"]
+        )
+        self.add_subsystem(
+            "paint_weight", RegisterSubmodel.get_submodel(SERVICE_PAINT_MASS), promotes=["*"]
+        )
+
+        weight_sum = om.AddSubtractComp()
+        weight_sum.add_equation(
+            "data:weight:airframe:mass",
+            [
+                "data:weight:airframe:wing:mass",
+                "data:weight:airframe:fuselage:mass",
+                "data:weight:airframe:horizontal_tail:mass",
+                "data:weight:airframe:vertical_tail:mass",
+                "data:weight:airframe:flight_controls:mass",
+                "data:weight:airframe:landing_gear:main:mass",
+                "data:weight:airframe:landing_gear:front:mass",
+                "data:weight:airframe:pylon:mass",
+                "data:weight:airframe:paint:mass",
+            ],
+            units="kg",
+            desc="Mass of airframe",
+        )
+
+        self.add_subsystem(
+            "airframe_weight_sum", weight_sum, promotes=["*"],
+        )
diff --git a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b1_engine_weight.py b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b1_engine_weight.py
index 317af96bd..49be990bf 100644
--- a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b1_engine_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b1_engine_weight.py
@@ -15,11 +15,15 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_ENGINE_MASS
 
 
 # TODO:  this is also provided by class RubberEngine
-class EngineWeight(ExplicitComponent):
+@RegisterSubmodel(SERVICE_ENGINE_MASS, "fastoad.submodel.weight.mass.propulsion.engine.legacy")
+class EngineWeight(om.ExplicitComponent):
     """
     Engine weight estimation
 
diff --git a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b2_fuel_lines_weight.py b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b2_fuel_lines_weight.py
index 3b82e2f13..9bdea3c20 100644
--- a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b2_fuel_lines_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b2_fuel_lines_weight.py
@@ -15,10 +15,16 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FUEL_LINES_MASS
 
-class FuelLinesWeight(ExplicitComponent):
+
+@RegisterSubmodel(
+    SERVICE_FUEL_LINES_MASS, "fastoad.submodel.weight.mass.propulsion.fuel_lines.legacy"
+)
+class FuelLinesWeight(om.ExplicitComponent):
     """
     Weight estimation for fuel lines
 
diff --git a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b3_unconsumables_weight.py b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b3_unconsumables_weight.py
index 0592fe600..58978ea37 100644
--- a/src/fastoad/models/weight/mass_breakdown/b_propulsion/b3_unconsumables_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/b_propulsion/b3_unconsumables_weight.py
@@ -15,10 +15,16 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_UNCONSUMABLES_MASS
 
-class UnconsumablesWeight(ExplicitComponent):
+
+@RegisterSubmodel(
+    SERVICE_UNCONSUMABLES_MASS, "fastoad.submodel.weight.mass.propulsion.unconsumables.legacy"
+)
+class UnconsumablesWeight(om.ExplicitComponent):
     """
     Weight estimation for oil and unusable fuel
 
diff --git a/src/fastoad/models/weight/mass_breakdown/b_propulsion/constants.py b/src/fastoad/models/weight/mass_breakdown/b_propulsion/constants.py
new file mode 100644
index 000000000..6d41f4f48
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/b_propulsion/constants.py
@@ -0,0 +1,17 @@
+"""Constants for propulsion mass submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_ENGINE_MASS = "service.mass.propulsion.engine"
+SERVICE_FUEL_LINES_MASS = "service.mass.propulsion.fuel_lines"
+SERVICE_UNCONSUMABLES_MASS = "service.mass.propulsion.unconsumables"
diff --git a/src/fastoad/models/weight/mass_breakdown/b_propulsion/sum.py b/src/fastoad/models/weight/mass_breakdown/b_propulsion/sum.py
new file mode 100644
index 000000000..01d7d05ba
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/b_propulsion/sum.py
@@ -0,0 +1,58 @@
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+"""Computation of propulsion mass."""
+from openmdao import api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_ENGINE_MASS, SERVICE_FUEL_LINES_MASS, SERVICE_UNCONSUMABLES_MASS
+from ..constants import SERVICE_PROPULSION_MASS
+
+
+@RegisterSubmodel(SERVICE_PROPULSION_MASS, "fastoad.submodel.weight.mass.propulsion.legacy")
+class PropulsionWeight(om.Group):
+    """
+    Computes mass of propulsion.
+    """
+
+    def setup(self):
+        # Engine have to be computed before pylons
+        self.add_subsystem(
+            "engines_weight", RegisterSubmodel.get_submodel(SERVICE_ENGINE_MASS), promotes=["*"]
+        )
+        self.add_subsystem(
+            "fuel_lines_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FUEL_LINES_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "unconsumables_weight",
+            RegisterSubmodel.get_submodel(SERVICE_UNCONSUMABLES_MASS),
+            promotes=["*"],
+        )
+
+        weight_sum = om.AddSubtractComp()
+        weight_sum.add_equation(
+            "data:weight:propulsion:mass",
+            [
+                "data:weight:propulsion:engine:mass",
+                "data:weight:propulsion:fuel_lines:mass",
+                "data:weight:propulsion:unconsumables:mass",
+            ],
+            units="kg",
+            desc="Mass of the propulsion system",
+        )
+
+        self.add_subsystem(
+            "propulsion_weight_sum", weight_sum, promotes=["*"],
+        )
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c1_power_systems_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c1_power_systems_weight.py
index f26def0d2..ea6cced65 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c1_power_systems_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c1_power_systems_weight.py
@@ -15,10 +15,14 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_POWER_SYSTEMS_MASS
 
-class PowerSystemsWeight(ExplicitComponent):
+
+@RegisterSubmodel(SERVICE_POWER_SYSTEMS_MASS, "fastoad.submodel.weight.mass.systems.power.legacy")
+class PowerSystemsWeight(om.ExplicitComponent):
     """
     Weight estimation for power systems (generation and distribution)
 
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c2_life_support_systems_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c2_life_support_systems_weight.py
index 3b57344f5..2886bc24c 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c2_life_support_systems_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c2_life_support_systems_weight.py
@@ -15,12 +15,17 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_LIFE_SUPPORT_SYSTEMS_MASS
 
 
-class LifeSupportSystemsWeight(ExplicitComponent):
+@RegisterSubmodel(
+    SERVICE_LIFE_SUPPORT_SYSTEMS_MASS, "fastoad.submodel.weight.mass.systems.life_support.legacy"
+)
+class LifeSupportSystemsWeight(om.ExplicitComponent):
     """
     Weight estimation for life support systems
 
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c3_navigation_systems_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c3_navigation_systems_weight.py
index 2d878c270..268a43660 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c3_navigation_systems_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c3_navigation_systems_weight.py
@@ -15,12 +15,17 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_NAVIGATION_SYSTEMS_MASS
 
 
-class NavigationSystemsWeight(ExplicitComponent):
+@RegisterSubmodel(
+    SERVICE_NAVIGATION_SYSTEMS_MASS, "fastoad.submodel.weight.mass.systems.navigation.legacy"
+)
+class NavigationSystemsWeight(om.ExplicitComponent):
     """
     Weight estimation for navigation systems
 
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c4_transmissions_systems_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c4_transmissions_systems_weight.py
index 641d8b74c..e914fbe73 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c4_transmissions_systems_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c4_transmissions_systems_weight.py
@@ -18,8 +18,13 @@
 import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_TRANSMISSION_SYSTEMS_MASS
 
 
+@RegisterSubmodel(
+    SERVICE_TRANSMISSION_SYSTEMS_MASS, "fastoad.submodel.weight.mass.systems.transmission.legacy"
+)
 class TransmissionSystemsWeight(om.ExplicitComponent):
     """
     Weight estimation for transmission systems
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c5_fixed_operational_systems_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c5_fixed_operational_systems_weight.py
index 844f36049..4ae3f0660 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c5_fixed_operational_systems_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c5_fixed_operational_systems_weight.py
@@ -15,10 +15,17 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FIXED_OPERATIONAL_SYSTEMS_MASS
 
-class FixedOperationalSystemsWeight(ExplicitComponent):
+
+@RegisterSubmodel(
+    SERVICE_FIXED_OPERATIONAL_SYSTEMS_MASS,
+    "fastoad.submodel.weight.mass.systems.fixed_operational.legacy",
+)
+class FixedOperationalSystemsWeight(om.ExplicitComponent):
     """
     Weight estimation for fixed operational systems (weather radar, flight recorder, ...)
 
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/c6_flight_kit_weight.py b/src/fastoad/models/weight/mass_breakdown/c_systems/c6_flight_kit_weight.py
index f3a1f0ffc..03968abd3 100644
--- a/src/fastoad/models/weight/mass_breakdown/c_systems/c6_flight_kit_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/c6_flight_kit_weight.py
@@ -18,8 +18,11 @@
 import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FLIGHT_KIT_MASS
 
 
+@RegisterSubmodel(SERVICE_FLIGHT_KIT_MASS, "fastoad.submodel.weight.mass.systems.flight_kit.legacy")
 class FlightKitWeight(om.ExplicitComponent):
     """
     Weight estimation for flight kit (tools that are always on board)
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/constants.py b/src/fastoad/models/weight/mass_breakdown/c_systems/constants.py
new file mode 100644
index 000000000..d7d4769b3
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/constants.py
@@ -0,0 +1,20 @@
+"""Constants for systems mass submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_POWER_SYSTEMS_MASS = "service.mass.systems.power"
+SERVICE_LIFE_SUPPORT_SYSTEMS_MASS = "service.mass.systems.life_support"
+SERVICE_NAVIGATION_SYSTEMS_MASS = "service.mass.systems.navigation"
+SERVICE_TRANSMISSION_SYSTEMS_MASS = "service.mass.systems.transmissions"
+SERVICE_FIXED_OPERATIONAL_SYSTEMS_MASS = "service.mass.systems.fixed_operational"
+SERVICE_FLIGHT_KIT_MASS = "service.mass.systems.flight_kit"
diff --git a/src/fastoad/models/weight/mass_breakdown/c_systems/sum.py b/src/fastoad/models/weight/mass_breakdown/c_systems/sum.py
new file mode 100644
index 000000000..6646a39ec
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/c_systems/sum.py
@@ -0,0 +1,93 @@
+"""Computation of mass of systems."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from openmdao import api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import (
+    SERVICE_POWER_SYSTEMS_MASS,
+    SERVICE_LIFE_SUPPORT_SYSTEMS_MASS,
+    SERVICE_NAVIGATION_SYSTEMS_MASS,
+    SERVICE_TRANSMISSION_SYSTEMS_MASS,
+    SERVICE_FIXED_OPERATIONAL_SYSTEMS_MASS,
+    SERVICE_FLIGHT_KIT_MASS,
+)
+from ..constants import SERVICE_SYSTEMS_MASS
+
+
+@RegisterSubmodel(SERVICE_SYSTEMS_MASS, "fastoad.submodel.weight.mass.systems.legacy")
+class SystemsWeight(om.Group):
+    """
+    Computes mass of systems.
+    """
+
+    def setup(self):
+        self.add_subsystem(
+            "power_systems_weight",
+            RegisterSubmodel.get_submodel(SERVICE_POWER_SYSTEMS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "life_support_systems_weight",
+            RegisterSubmodel.get_submodel(SERVICE_LIFE_SUPPORT_SYSTEMS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "navigation_systems_weight",
+            RegisterSubmodel.get_submodel(SERVICE_NAVIGATION_SYSTEMS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "transmission_systems_weight",
+            RegisterSubmodel.get_submodel(SERVICE_TRANSMISSION_SYSTEMS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "fixed_operational_systems_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FIXED_OPERATIONAL_SYSTEMS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "flight_kit_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FLIGHT_KIT_MASS),
+            promotes=["*"],
+        )
+
+        weight_sum = om.AddSubtractComp()
+        weight_sum.add_equation(
+            "data:weight:systems:mass",
+            [
+                "data:weight:systems:power:auxiliary_power_unit:mass",
+                "data:weight:systems:power:electric_systems:mass",
+                "data:weight:systems:power:hydraulic_systems:mass",
+                "data:weight:systems:life_support:insulation:mass",
+                "data:weight:systems:life_support:air_conditioning:mass",
+                "data:weight:systems:life_support:de-icing:mass",
+                "data:weight:systems:life_support:cabin_lighting:mass",
+                "data:weight:systems:life_support:seats_crew_accommodation:mass",
+                "data:weight:systems:life_support:oxygen:mass",
+                "data:weight:systems:life_support:safety_equipment:mass",
+                "data:weight:systems:navigation:mass",
+                "data:weight:systems:transmission:mass",
+                "data:weight:systems:operational:radar:mass",
+                "data:weight:systems:operational:cargo_hold:mass",
+                "data:weight:systems:flight_kit:mass",
+            ],
+            units="kg",
+            desc="Mass of aircraft systems",
+        )
+
+        self.add_subsystem(
+            "systems_weight_sum", weight_sum, promotes=["*"],
+        )
diff --git a/src/fastoad/models/weight/mass_breakdown/constants.py b/src/fastoad/models/weight/mass_breakdown/constants.py
new file mode 100644
index 000000000..0510a3856
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/constants.py
@@ -0,0 +1,23 @@
+"""Constants for mass submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_OWE = "service.mass.owe"
+SERVICE_PAYLOAD_MASS = "service.mass.payload"
+SERVICE_AIRFRAME_MASS = "service.mass.airframe"
+SERVICE_PROPULSION_MASS = "service.mass.propulsion"
+SERVICE_SYSTEMS_MASS = "service.mass.systems"
+SERVICE_FURNITURE_MASS = "service.mass.furniture"
+SERVICE_CREW_MASS = "service.mass.crew"
+
+SERVICE_GUST_LOADS = "service.gust_loads"
diff --git a/src/fastoad/models/weight/mass_breakdown/cs25.py b/src/fastoad/models/weight/mass_breakdown/cs25.py
index 2d63b3113..dec9e9196 100644
--- a/src/fastoad/models/weight/mass_breakdown/cs25.py
+++ b/src/fastoad/models/weight/mass_breakdown/cs25.py
@@ -1,8 +1,8 @@
 """
 Computation of load cases
 """
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  This file is part of FAST : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -18,8 +18,11 @@
 from openmdao.core.explicitcomponent import ExplicitComponent
 
 from fastoad.model_base import Atmosphere
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_GUST_LOADS
 
 
+@RegisterSubmodel(SERVICE_GUST_LOADS, "fastoad.submodel.gust_loads")
 class Loads(ExplicitComponent):
     """
     Computes gust load cases
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/constants.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/constants.py
new file mode 100644
index 000000000..a6a21c8c2
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/constants.py
@@ -0,0 +1,19 @@
+"""Constants for systems mass submodels."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+SERVICE_CARGO_CONFIGURATION_MASS = "service.mass.furniture.cargo_configuration"
+SERVICE_PASSENGER_SEATS_MASS = "service.mass.furniture.passenger_seats"
+SERVICE_FOOD_WATER_MASS = "service.mass.furniture.food_water"
+SERVICE_SECURITY_KIT_MASS = "service.mass.furniture.security_kit"
+SERVICE_TOILETS_MASS = "service.mass.furniture.toilets"
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/d1_cargo_configuration_weight.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/d1_cargo_configuration_weight.py
index 4254b659b..c5bb7b399 100644
--- a/src/fastoad/models/weight/mass_breakdown/d_furniture/d1_cargo_configuration_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/d1_cargo_configuration_weight.py
@@ -17,7 +17,13 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_CARGO_CONFIGURATION_MASS
 
+
+@RegisterSubmodel(
+    SERVICE_CARGO_CONFIGURATION_MASS, "service.mass.furniture.cargo_configuration.legacy"
+)
 class CargoConfigurationWeight(om.ExplicitComponent):
     """
     Weight estimation for equipments for freight transport (applies only for freighters)
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/d2_passenger_seats_weight.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/d2_passenger_seats_weight.py
index 5dde17917..1ee2c2bf3 100644
--- a/src/fastoad/models/weight/mass_breakdown/d_furniture/d2_passenger_seats_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/d2_passenger_seats_weight.py
@@ -18,8 +18,11 @@
 import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_PASSENGER_SEATS_MASS
 
 
+@RegisterSubmodel(SERVICE_PASSENGER_SEATS_MASS, "service.mass.furniture.passenger_seats.legacy")
 class PassengerSeatsWeight(om.ExplicitComponent):
     """
     Weight estimation for passenger seats
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/d3_food_water_weight.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/d3_food_water_weight.py
index 1e8bf40ff..85e0bdb8a 100644
--- a/src/fastoad/models/weight/mass_breakdown/d_furniture/d3_food_water_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/d3_food_water_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_FOOD_WATER_MASS
 
+
+@RegisterSubmodel(SERVICE_FOOD_WATER_MASS, "service.mass.furniture.food_water.legacy")
 class FoodWaterWeight(om.ExplicitComponent):
     """
     Weight estimation for food and water
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/d4_security_kit_weight.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/d4_security_kit_weight.py
index 2f2ba44e4..b8c6268e1 100644
--- a/src/fastoad/models/weight/mass_breakdown/d_furniture/d4_security_kit_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/d4_security_kit_weight.py
@@ -17,7 +17,11 @@
 import numpy as np
 import openmdao.api as om
 
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_SECURITY_KIT_MASS
 
+
+@RegisterSubmodel(SERVICE_SECURITY_KIT_MASS, "service.mass.furniture.security_kit.legacy")
 class SecurityKitWeight(om.ExplicitComponent):
     """
     Weight estimation for security kit
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/d5_toilets_weight.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/d5_toilets_weight.py
index 39ed77d6f..c15e413da 100644
--- a/src/fastoad/models/weight/mass_breakdown/d_furniture/d5_toilets_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/d5_toilets_weight.py
@@ -18,8 +18,11 @@
 import openmdao.api as om
 
 from fastoad.constants import RangeCategory
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import SERVICE_TOILETS_MASS
 
 
+@RegisterSubmodel(SERVICE_TOILETS_MASS, "service.mass.furniture.toilets.legacy")
 class ToiletsWeight(om.ExplicitComponent):
     """
     Weight estimation for toilets
diff --git a/src/fastoad/models/weight/mass_breakdown/d_furniture/sum.py b/src/fastoad/models/weight/mass_breakdown/d_furniture/sum.py
new file mode 100644
index 000000000..420d92072
--- /dev/null
+++ b/src/fastoad/models/weight/mass_breakdown/d_furniture/sum.py
@@ -0,0 +1,70 @@
+"""Computation of furniture mass."""
+#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  FAST is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#  You should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+from openmdao import api as om
+
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import (
+    SERVICE_PASSENGER_SEATS_MASS,
+    SERVICE_FOOD_WATER_MASS,
+    SERVICE_SECURITY_KIT_MASS,
+    SERVICE_TOILETS_MASS,
+)
+from ..constants import SERVICE_FURNITURE_MASS
+
+
+@RegisterSubmodel(
+    SERVICE_FURNITURE_MASS, "fastoad.submodel.weight.mass.furniture.cargo_configuration.legacy"
+)
+class FurnitureWeight(om.Group):
+    """
+    Computes mass of furniture.
+    """
+
+    def setup(self):
+        self.add_subsystem(
+            "passenger_seats_weight",
+            RegisterSubmodel.get_submodel(SERVICE_PASSENGER_SEATS_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "food_water_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FOOD_WATER_MASS),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "security_kit_weight",
+            RegisterSubmodel.get_submodel(SERVICE_SECURITY_KIT_MASS, ""),
+            promotes=["*"],
+        )
+        self.add_subsystem(
+            "toilets_weight", RegisterSubmodel.get_submodel(SERVICE_TOILETS_MASS), promotes=["*"]
+        )
+
+        weight_sum = om.AddSubtractComp()
+        weight_sum.add_equation(
+            "data:weight:furniture:mass",
+            [
+                "data:weight:furniture:passenger_seats:mass",
+                "data:weight:furniture:food_water:mass",
+                "data:weight:furniture:security_kit:mass",
+                "data:weight:furniture:toilets:mass",
+            ],
+            units="kg",
+            desc="Mass of aircraft furniture",
+        )
+
+        self.add_subsystem(
+            "furniture_weight_sum", weight_sum, promotes=["*"],
+        )
diff --git a/src/fastoad/models/weight/mass_breakdown/e_crew/crew_weight.py b/src/fastoad/models/weight/mass_breakdown/e_crew/crew_weight.py
index 14fe1dd16..ac0b6b17e 100644
--- a/src/fastoad/models/weight/mass_breakdown/e_crew/crew_weight.py
+++ b/src/fastoad/models/weight/mass_breakdown/e_crew/crew_weight.py
@@ -15,10 +15,14 @@
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 import numpy as np
-from openmdao.core.explicitcomponent import ExplicitComponent
+import openmdao.api as om
 
+from fastoad.models.weight.mass_breakdown.constants import SERVICE_CREW_MASS
+from fastoad.module_management.service_registry import RegisterSubmodel
 
-class CrewWeight(ExplicitComponent):
+
+@RegisterSubmodel(SERVICE_CREW_MASS, "fastoad.submodel.weight.mass.crew.legacy")
+class CrewWeight(om.ExplicitComponent):
     """
     Weight estimation for aircraft crew
 
diff --git a/src/fastoad/models/weight/mass_breakdown/mass_breakdown.py b/src/fastoad/models/weight/mass_breakdown/mass_breakdown.py
index c1cd1ea5d..93039a2f5 100644
--- a/src/fastoad/models/weight/mass_breakdown/mass_breakdown.py
+++ b/src/fastoad/models/weight/mass_breakdown/mass_breakdown.py
@@ -15,35 +15,21 @@
 import openmdao.api as om
 
 from fastoad.models.constants import PAYLOAD_FROM_NPAX
-from .a_airframe import (
-    EmpennageWeight,
-    FlightControlsWeight,
-    FuselageWeight,
-    LandingGearWeight,
-    PaintWeight,
-    PylonsWeight,
-    WingWeight,
+from fastoad.module_management.service_registry import RegisterSubmodel
+from .constants import (
+    SERVICE_AIRFRAME_MASS,
+    SERVICE_CREW_MASS,
+    SERVICE_FURNITURE_MASS,
+    SERVICE_OWE,
+    SERVICE_PAYLOAD_MASS,
+    SERVICE_PROPULSION_MASS,
+    SERVICE_SYSTEMS_MASS,
 )
-from .b_propulsion import (
-    EngineWeight,
-    FuelLinesWeight,
-    UnconsumablesWeight,
-)
-from .c_systems import (
-    FixedOperationalSystemsWeight,
-    FlightKitWeight,
-    LifeSupportSystemsWeight,
-    NavigationSystemsWeight,
-    PowerSystemsWeight,
-    TransmissionSystemsWeight,
-)
-from .cs25 import Loads
-from .d_furniture import FoodWaterWeight, PassengerSeatsWeight, SecurityKitWeight, ToiletsWeight
-from .e_crew import CrewWeight
-from .payload import ComputePayload
 from .update_mlw_and_mzfw import UpdateMLWandMZFW
+from ..constants import SERVICE_MASS_BREAKDOWN
 
 
+@RegisterSubmodel(SERVICE_MASS_BREAKDOWN, "fastoad.submodel.weight.mass.legacy")
 class MassBreakdown(om.Group):
     """
     Computes analytically the mass of each part of the aircraft, and the resulting sum,
@@ -64,8 +50,10 @@ def initialize(self):
 
     def setup(self):
         if self.options[PAYLOAD_FROM_NPAX]:
-            self.add_subsystem("payload", ComputePayload(), promotes=["*"])
-        self.add_subsystem("owe", OperatingWeightEmpty(), promotes=["*"])
+            self.add_subsystem(
+                "payload", RegisterSubmodel.get_submodel(SERVICE_PAYLOAD_MASS), promotes=["*"]
+            )
+        self.add_subsystem("owe", RegisterSubmodel.get_submodel(SERVICE_OWE), promotes=["*"])
         self.add_subsystem("update_mzfw_and_mlw", UpdateMLWandMZFW(), promotes=["*"])
 
         # Solvers setup
@@ -77,164 +65,35 @@ def setup(self):
         self.linear_solver.options["iprint"] = 0
 
 
-class AirframeWeight(om.Group):
-    """
-    Computes mass of airframe.
-    """
-
-    def setup(self):
-        # Airframe
-        self.add_subsystem("loads", Loads(), promotes=["*"])
-        self.add_subsystem("wing_weight", WingWeight(), promotes=["*"])
-        self.add_subsystem("fuselage_weight", FuselageWeight(), promotes=["*"])
-        self.add_subsystem("empennage_weight", EmpennageWeight(), promotes=["*"])
-        self.add_subsystem("flight_controls_weight", FlightControlsWeight(), promotes=["*"])
-        self.add_subsystem("landing_gear_weight", LandingGearWeight(), promotes=["*"])
-        self.add_subsystem("pylons_weight", PylonsWeight(), promotes=["*"])
-        self.add_subsystem("paint_weight", PaintWeight(), promotes=["*"])
-
-        weight_sum = om.AddSubtractComp()
-        weight_sum.add_equation(
-            "data:weight:airframe:mass",
-            [
-                "data:weight:airframe:wing:mass",
-                "data:weight:airframe:fuselage:mass",
-                "data:weight:airframe:horizontal_tail:mass",
-                "data:weight:airframe:vertical_tail:mass",
-                "data:weight:airframe:flight_controls:mass",
-                "data:weight:airframe:landing_gear:main:mass",
-                "data:weight:airframe:landing_gear:front:mass",
-                "data:weight:airframe:pylon:mass",
-                "data:weight:airframe:paint:mass",
-            ],
-            units="kg",
-            desc="Mass of airframe",
-        )
-
-        self.add_subsystem(
-            "airframe_weight_sum", weight_sum, promotes=["*"],
-        )
-
-
-class PropulsionWeight(om.Group):
-    """
-    Computes mass of propulsion.
-    """
-
-    def setup(self):
-        # Engine have to be computed before pylons
-        self.add_subsystem("engines_weight", EngineWeight(), promotes=["*"])
-        self.add_subsystem("fuel_lines_weight", FuelLinesWeight(), promotes=["*"])
-        self.add_subsystem("unconsumables_weight", UnconsumablesWeight(), promotes=["*"])
-
-        weight_sum = om.AddSubtractComp()
-        weight_sum.add_equation(
-            "data:weight:propulsion:mass",
-            [
-                "data:weight:propulsion:engine:mass",
-                "data:weight:propulsion:fuel_lines:mass",
-                "data:weight:propulsion:unconsumables:mass",
-            ],
-            units="kg",
-            desc="Mass of the propulsion system",
-        )
-
-        self.add_subsystem(
-            "propulsion_weight_sum", weight_sum, promotes=["*"],
-        )
-
+@RegisterSubmodel(SERVICE_OWE, "fastoad.submodel.weight.mass.owe.legacy")
+class OperatingWeightEmpty(om.Group):
+    """Operating Empty Weight (OEW) estimation.
 
-class SystemsWeight(om.Group):
-    """
-    Computes mass of systems.
+    This group aggregates weight from all components of the aircraft.
     """
 
     def setup(self):
-        self.add_subsystem("power_systems_weight", PowerSystemsWeight(), promotes=["*"])
+        # Propulsion should be done before airframe, because it drives pylon mass.
         self.add_subsystem(
-            "life_support_systems_weight", LifeSupportSystemsWeight(), promotes=["*"]
+            "propulsion_weight",
+            RegisterSubmodel.get_submodel(SERVICE_PROPULSION_MASS),
+            promotes=["*"],
         )
-        self.add_subsystem("navigation_systems_weight", NavigationSystemsWeight(), promotes=["*"])
         self.add_subsystem(
-            "transmission_systems_weight", TransmissionSystemsWeight(), promotes=["*"]
+            "airframe_weight", RegisterSubmodel.get_submodel(SERVICE_AIRFRAME_MASS), promotes=["*"],
         )
         self.add_subsystem(
-            "fixed_operational_systems_weight", FixedOperationalSystemsWeight(), promotes=["*"]
-        )
-        self.add_subsystem("flight_kit_weight", FlightKitWeight(), promotes=["*"])
-
-        weight_sum = om.AddSubtractComp()
-        weight_sum.add_equation(
-            "data:weight:systems:mass",
-            [
-                "data:weight:systems:power:auxiliary_power_unit:mass",
-                "data:weight:systems:power:electric_systems:mass",
-                "data:weight:systems:power:hydraulic_systems:mass",
-                "data:weight:systems:life_support:insulation:mass",
-                "data:weight:systems:life_support:air_conditioning:mass",
-                "data:weight:systems:life_support:de-icing:mass",
-                "data:weight:systems:life_support:cabin_lighting:mass",
-                "data:weight:systems:life_support:seats_crew_accommodation:mass",
-                "data:weight:systems:life_support:oxygen:mass",
-                "data:weight:systems:life_support:safety_equipment:mass",
-                "data:weight:systems:navigation:mass",
-                "data:weight:systems:transmission:mass",
-                "data:weight:systems:operational:radar:mass",
-                "data:weight:systems:operational:cargo_hold:mass",
-                "data:weight:systems:flight_kit:mass",
-            ],
-            units="kg",
-            desc="Mass of aircraft systems",
+            "systems_weight", RegisterSubmodel.get_submodel(SERVICE_SYSTEMS_MASS), promotes=["*"]
         )
-
         self.add_subsystem(
-            "systems_weight_sum", weight_sum, promotes=["*"],
+            "furniture_weight",
+            RegisterSubmodel.get_submodel(SERVICE_FURNITURE_MASS),
+            promotes=["*"],
         )
-
-
-class FurnitureWeight(om.Group):
-    """
-    Computes mass of furniture.
-    """
-
-    def setup(self):
-        self.add_subsystem("passenger_seats_weight", PassengerSeatsWeight(), promotes=["*"])
-        self.add_subsystem("food_water_weight", FoodWaterWeight(), promotes=["*"])
-        self.add_subsystem("security_kit_weight", SecurityKitWeight(), promotes=["*"])
-        self.add_subsystem("toilets_weight", ToiletsWeight(), promotes=["*"])
-
-        weight_sum = om.AddSubtractComp()
-        weight_sum.add_equation(
-            "data:weight:furniture:mass",
-            [
-                "data:weight:furniture:passenger_seats:mass",
-                "data:weight:furniture:food_water:mass",
-                "data:weight:furniture:security_kit:mass",
-                "data:weight:furniture:toilets:mass",
-            ],
-            units="kg",
-            desc="Mass of aircraft furniture",
-        )
-
         self.add_subsystem(
-            "furniture_weight_sum", weight_sum, promotes=["*"],
+            "crew_weight", RegisterSubmodel.get_submodel(SERVICE_CREW_MASS), promotes=["*"]
         )
 
-
-class OperatingWeightEmpty(om.Group):
-    """Operating Empty Weight (OEW) estimation.
-
-    This group aggregates weight from all components of the aircraft.
-    """
-
-    def setup(self):
-        # Propulsion should be done before airframe, because it drives pylon mass.
-        self.add_subsystem("propulsion_weight", PropulsionWeight(), promotes=["*"])
-        self.add_subsystem("airframe_weight", AirframeWeight(), promotes=["*"])
-        self.add_subsystem("systems_weight", SystemsWeight(), promotes=["*"])
-        self.add_subsystem("furniture_weight", FurnitureWeight(), promotes=["*"])
-        self.add_subsystem("crew_weight", CrewWeight(), promotes=["*"])
-
         weight_sum = om.AddSubtractComp()
         weight_sum.add_equation(
             "data:weight:aircraft:OWE",
diff --git a/src/fastoad/models/weight/mass_breakdown/payload.py b/src/fastoad/models/weight/mass_breakdown/payload.py
index c336734a0..d03e20ab3 100644
--- a/src/fastoad/models/weight/mass_breakdown/payload.py
+++ b/src/fastoad/models/weight/mass_breakdown/payload.py
@@ -17,7 +17,11 @@
 import numpy as np
 from openmdao import api as om
 
+from fastoad.models.weight.mass_breakdown.constants import SERVICE_PAYLOAD_MASS
+from fastoad.module_management.service_registry import RegisterSubmodel
 
+
+@RegisterSubmodel(SERVICE_PAYLOAD_MASS, "fastoad.submodel.weight.mass.payload.legacy")
 class ComputePayload(om.ExplicitComponent):
     """ Computes payload from NPAX """
 
diff --git a/src/fastoad/models/weight/weight.py b/src/fastoad/models/weight/weight.py
index f5fd26c06..f859d57a8 100644
--- a/src/fastoad/models/weight/weight.py
+++ b/src/fastoad/models/weight/weight.py
@@ -1,8 +1,8 @@
 """
 Weight computation (mass and CG)
 """
-#  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
+#  This file is part of FAST : A framework for rapid Overall Aircraft Design
+#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -18,9 +18,8 @@
 
 from fastoad.models.constants import PAYLOAD_FROM_NPAX
 from fastoad.module_management.constants import ModelDomain
-from fastoad.module_management.service_registry import RegisterOpenMDAOSystem
-from .cg.cg import CG
-from .mass_breakdown import MassBreakdown
+from fastoad.module_management.service_registry import RegisterOpenMDAOSystem, RegisterSubmodel
+from .constants import SERVICE_CENTERS_OF_GRAVITY, SERVICE_MASS_BREAKDOWN
 
 
 @RegisterOpenMDAOSystem("fastoad.weight.legacy", domain=ModelDomain.WEIGHT)
@@ -47,9 +46,13 @@ def initialize(self):
         )
 
     def setup(self):
-        self.add_subsystem("cg", CG(), promotes=["*"])
+        self.add_subsystem(
+            "cg", RegisterSubmodel.get_submodel(SERVICE_CENTERS_OF_GRAVITY), promotes=["*"]
+        )
         self.add_subsystem(
             "mass_breakdown",
-            MassBreakdown(**{PAYLOAD_FROM_NPAX: self.options[PAYLOAD_FROM_NPAX]}),
+            RegisterSubmodel.get_submodel(
+                SERVICE_MASS_BREAKDOWN, {PAYLOAD_FROM_NPAX: self.options[PAYLOAD_FROM_NPAX]}
+            ),
             promotes=["*"],
         )


Test patch:
diff --git a/src/fastoad/models/geometry/tests/test_geometry_geom_comps.py b/src/fastoad/models/geometry/tests/test_geometry_geom_comps.py
index 8cf4d5e89..ba124a5e3 100644
--- a/src/fastoad/models/geometry/tests/test_geometry_geom_comps.py
+++ b/src/fastoad/models/geometry/tests/test_geometry_geom_comps.py
@@ -2,7 +2,7 @@
 Test module for geometry functions of cg components
 """
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -14,12 +14,13 @@
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
+# pylint: disable=redefined-outer-name  # needed for pytest fixtures
+
 import os.path as pth
 
 import pytest
 
 from fastoad.io import VariableIO
-from fastoad.models.weight.cg.cg_components import ComputeHTcg, ComputeVTcg, UpdateMLG
 from tests.testing_utilities import run_system
 from ..geom_components import ComputeTotalArea
 from ..geom_components.fuselage import (
@@ -28,18 +29,18 @@
 )
 from ..geom_components.fuselage.compute_cnbeta_fuselage import ComputeCnBetaFuselage
 from ..geom_components.ht.components import (
-    ComputeHTMAC,
     ComputeHTChord,
     ComputeHTClalpha,
+    ComputeHTMAC,
     ComputeHTSweep,
 )
 from ..geom_components.nacelle_pylons.compute_nacelle_pylons import ComputeNacelleAndPylonsGeometry
 from ..geom_components.vt.components import (
-    ComputeVTMAC,
     ComputeVTChords,
     ComputeVTClalpha,
-    ComputeVTSweep,
     ComputeVTDistance,
+    ComputeVTMAC,
+    ComputeVTSweep,
 )
 from ..geom_components.wing.components import (
     ComputeB50,
@@ -56,7 +57,6 @@
 )
 
 
-# pylint: disable=redefined-outer-name  # needed for pytest fixtures
 @pytest.fixture(scope="module")
 def input_xml() -> VariableIO:
     """
@@ -138,28 +138,6 @@ def test_compute_fuselage_basic(input_xml):
     assert pnc == pytest.approx(4, abs=1)
 
 
-def test_compute_ht_cg(input_xml):
-    """ Tests computation of the horizontal tail center of gravity """
-
-    input_list = [
-        "data:geometry:horizontal_tail:root:chord",
-        "data:geometry:horizontal_tail:tip:chord",
-        "data:geometry:horizontal_tail:MAC:at25percent:x:from_wingMAC25",
-        "data:geometry:horizontal_tail:span",
-        "data:geometry:wing:MAC:at25percent:x",
-        "data:geometry:horizontal_tail:sweep_25",
-        "data:geometry:horizontal_tail:MAC:length",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-    input_vars.add_output("data:geometry:horizontal_tail:MAC:at25percent:x:local", 1.656, units="m")
-
-    problem = run_system(ComputeHTcg(), input_vars)
-
-    cg_a31 = problem["data:weight:airframe:horizontal_tail:CG:x"]
-    assert cg_a31 == pytest.approx(34.58, abs=1e-2)
-
-
 def test_compute_ht_mac(input_xml):
     """ Tests computation of the horizontal tail mac """
 
@@ -263,31 +241,6 @@ def test_compute_fuselage_cnbeta(input_xml):
     assert cn_beta == pytest.approx(-0.117901, abs=1e-6)
 
 
-def test_compute_vt_cg(input_xml):
-    """ Tests computation of the vertical tail center of gravity """
-
-    input_list = [
-        "data:geometry:vertical_tail:root:chord",
-        "data:geometry:vertical_tail:tip:chord",
-        "data:geometry:vertical_tail:MAC:at25percent:x:from_wingMAC25",
-        "data:geometry:vertical_tail:span",
-        "data:geometry:wing:MAC:at25percent:x",
-        "data:geometry:vertical_tail:sweep_25",
-        "data:geometry:vertical_tail:MAC:length",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-
-    input_vars.add_output("data:geometry:vertical_tail:MAC:at25percent:x:local", 2.321, units="m")
-
-    component = ComputeVTcg()
-
-    problem = run_system(component, input_vars)
-
-    cg_a32 = problem["data:weight:airframe:vertical_tail:CG:x"]
-    assert cg_a32 == pytest.approx(34.265, abs=1e-3)
-
-
 def test_compute_vt_mac(input_xml):
     """ Tests computation of the vertical tail mac """
 
@@ -730,22 +683,3 @@ def test_geometry_total_area(input_xml):
 
     total_surface = problem["data:geometry:aircraft:wetted_area"]
     assert total_surface == pytest.approx(783.997, abs=1e-3)
-
-
-def test_geometry_update_mlg(input_xml):
-    """ Tests computation of the main landing gear """
-
-    input_list = [
-        "data:geometry:wing:MAC:length",
-        "data:geometry:wing:MAC:at25percent:x",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-
-    input_vars.add_output("data:weight:aircraft:CG:aft:MAC_position", 0.364924)
-    input_vars.add_output("data:weight:airframe:landing_gear:front:CG:x", 5.07)
-
-    problem = run_system(UpdateMLG(), input_vars)
-
-    cg_a51 = problem["data:weight:airframe:landing_gear:main:CG:x"]
-    assert cg_a51 == pytest.approx(18.00, abs=1e-2)
diff --git a/src/fastoad/models/weight/cg/tests/test_geometry_cg_components.py b/src/fastoad/models/weight/cg/tests/test_cg_components.py
similarity index 79%
rename from src/fastoad/models/weight/cg/tests/test_geometry_cg_components.py
rename to src/fastoad/models/weight/cg/tests/test_cg_components.py
index 6f0b9d43c..f1dc78f6a 100644
--- a/src/fastoad/models/weight/cg/tests/test_geometry_cg_components.py
+++ b/src/fastoad/models/weight/cg/tests/test_cg_components.py
@@ -2,7 +2,7 @@
 Test module for geometry functions of cg components
 """
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -14,6 +14,8 @@
 #  You should have received a copy of the GNU General Public License
 #  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
+# pylint: disable=redefined-outer-name  # needed for pytest fixtures
+
 import os.path as pth
 
 import pytest
@@ -21,20 +23,23 @@
 from fastoad.io import VariableIO
 from tests.testing_utilities import run_system
 from ..cg import ComputeAircraftCG
-from ..cg_components import ComputeCGLoadCase1
-from ..cg_components import ComputeCGLoadCase2
-from ..cg_components import ComputeCGLoadCase3
-from ..cg_components import ComputeCGLoadCase4
-from ..cg_components import ComputeCGRatioAft
-from ..cg_components import ComputeControlSurfacesCG
-from ..cg_components import ComputeGlobalCG
-from ..cg_components import ComputeMaxCGratio
-from ..cg_components import ComputeOthersCG
-from ..cg_components import ComputeTanksCG
-from ..cg_components import ComputeWingCG
+from ..cg_components.compute_cg_control_surfaces import ComputeControlSurfacesCG
+from ..cg_components.compute_cg_others import ComputeOthersCG
+from ..cg_components.compute_cg_ratio_aft import ComputeCGRatioAft
+from ..cg_components.compute_cg_tanks import ComputeTanksCG
+from ..cg_components.compute_cg_wing import ComputeWingCG
+from ..cg_components.compute_global_cg import ComputeGlobalCG
+from ..cg_components.compute_ht_cg import ComputeHTcg
+from ..cg_components.compute_max_cg_ratio import ComputeMaxCGratio
+from ..cg_components.compute_vt_cg import ComputeVTcg
+from ..cg_components.load_cases.compute_cg_loadcase1 import ComputeCGLoadCase1
+from ..cg_components.load_cases.compute_cg_loadcase2 import ComputeCGLoadCase2
+from ..cg_components.load_cases.compute_cg_loadcase3 import ComputeCGLoadCase3
+from ..cg_components.load_cases.compute_cg_loadcase4 import ComputeCGLoadCase4
+from ..cg_components.load_cases.compute_cg_loadcases import CGRatiosForLoadCases
+from ..cg_components.update_mlg import UpdateMLG
 
 
-# pylint: disable=redefined-outer-name  # needed for pytest fixtures
 @pytest.fixture(scope="module")
 def input_xml() -> VariableIO:
     """
@@ -45,7 +50,7 @@ def input_xml() -> VariableIO:
 
 
 def test_compute_cg_control_surfaces(input_xml):
-    """ Tests computation of control surfaces center of gravity """
+    """Tests computation of control surfaces center of gravity"""
 
     input_list = [
         "data:geometry:wing:MAC:leading_edge:x:local",
@@ -67,31 +72,8 @@ def test_compute_cg_control_surfaces(input_xml):
     assert x_cg_a4 == pytest.approx(19.24, abs=1e-2)
 
 
-def test_compute_cg_loadcase1(input_xml):
-    """ Tests computation of center of gravity for load case 1 """
-
-    input_list = [
-        "data:geometry:wing:MAC:length",
-        "data:geometry:wing:MAC:at25percent:x",
-        "data:weight:payload:PAX:CG:x",
-        "data:weight:payload:rear_fret:CG:x",
-        "data:weight:payload:front_fret:CG:x",
-        "data:TLAR:NPAX",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-
-    input_vars.add_output("data:weight:aircraft_empty:CG:x", 699570.01 / 40979.11)
-    input_vars.add_output("data:weight:aircraft_empty:mass", 40979.11)
-
-    problem = run_system(ComputeCGLoadCase1(), input_vars)
-
-    cg_ratio_lc1 = problem["data:weight:aircraft:load_case_1:CG:MAC_position"]
-    assert cg_ratio_lc1 == pytest.approx(0.364924, abs=1e-6)
-
-
-def test_compute_cg_loadcase2(input_xml):
-    """ Tests computation of center of gravity for load case 2 """
+def test_compute_cg_loadcases(input_xml):
+    """Tests computation of center of gravity for load case 2"""
 
     input_list = [
         "data:geometry:wing:MAC:length",
@@ -109,60 +91,29 @@ def test_compute_cg_loadcase2(input_xml):
     input_vars.add_output("data:weight:aircraft_empty:CG:x", 699570.01 / 40979.11)
     input_vars.add_output("data:weight:aircraft_empty:mass", 40979.11)
 
-    problem = run_system(ComputeCGLoadCase2(), input_vars)
+    # Testing each load case independently -------------
+    classes = [ComputeCGLoadCase1, ComputeCGLoadCase2, ComputeCGLoadCase3, ComputeCGLoadCase4]
+    cg_ratio_lc = [0.0]  # dummy first item to ensure cg_ratio_lc[i] is for load case i
+    for i, cg_class in enumerate(classes):
+        problem = run_system(cg_class(), input_vars)
+        cg_ratio_lc.append(problem[f"data:weight:aircraft:load_case_{i+1}:CG:MAC_position"])
 
-    cg_ratio_lc2 = problem["data:weight:aircraft:load_case_2:CG:MAC_position"]
-    assert cg_ratio_lc2 == pytest.approx(0.285139, abs=1e-6)
+    assert cg_ratio_lc[1] == pytest.approx(0.364907, abs=1e-6)
+    assert cg_ratio_lc[2] == pytest.approx(0.285139, abs=1e-6)
+    assert cg_ratio_lc[3] == pytest.approx(0.386260, abs=1e-6)
+    assert cg_ratio_lc[4] == pytest.approx(0.388971, abs=1e-6)
 
+    # Testing the aggregated load cases -------------
+    problem = run_system(CGRatiosForLoadCases(), input_vars)
+    cg_ratios = problem["data:weight:aircraft:load_cases:CG:MAC_position"]
+    max_cg_ratios = problem["data:weight:aircraft:load_cases:CG:MAC_position:maximum"]
 
-def test_compute_cg_loadcase3(input_xml):
-    """ Tests computation of center of gravity for load case 3 """
-
-    input_list = [
-        "data:geometry:wing:MAC:length",
-        "data:geometry:wing:MAC:at25percent:x",
-        "data:weight:payload:PAX:CG:x",
-        "data:weight:payload:rear_fret:CG:x",
-        "data:weight:payload:front_fret:CG:x",
-        "data:TLAR:NPAX",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-
-    input_vars.add_output("data:weight:aircraft_empty:CG:x", 699570.01 / 40979.11)
-    input_vars.add_output("data:weight:aircraft_empty:mass", 40979.11)
-
-    problem = run_system(ComputeCGLoadCase3(), input_vars)
-
-    cg_ratio_lc3 = problem["data:weight:aircraft:load_case_3:CG:MAC_position"]
-    assert cg_ratio_lc3 == pytest.approx(0.386260, abs=1e-6)
-
-
-def test_compute_cg_loadcase4(input_xml):
-    """ Tests computation of center of gravity for load case 4 """
-
-    input_list = [
-        "data:geometry:wing:MAC:length",
-        "data:geometry:wing:MAC:at25percent:x",
-        "data:weight:payload:PAX:CG:x",
-        "data:weight:payload:rear_fret:CG:x",
-        "data:weight:payload:front_fret:CG:x",
-        "data:TLAR:NPAX",
-    ]
-
-    input_vars = input_xml.read(only=input_list).to_ivc()
-
-    input_vars.add_output("data:weight:aircraft_empty:CG:x", 699570.01 / 40979.11)
-    input_vars.add_output("data:weight:aircraft_empty:mass", 40979.11)
-
-    problem = run_system(ComputeCGLoadCase4(), input_vars)
-
-    cg_ratio_lc4 = problem["data:weight:aircraft:load_case_4:CG:MAC_position"]
-    assert cg_ratio_lc4 == pytest.approx(0.388971, abs=1e-6)
+    assert cg_ratios == pytest.approx([0.364907, 0.285139, 0.386260, 0.388971], abs=1e-6)
+    assert max_cg_ratios == pytest.approx(0.388971, abs=1e-6)
 
 
 def test_compute_cg_others(input_xml):
-    """ Tests computation of other components center of gravity """
+    """Tests computation of other components center of gravity"""
 
     input_list = [
         "data:geometry:wing:MAC:leading_edge:x:local",
@@ -242,7 +193,7 @@ def test_compute_cg_others(input_xml):
 
 
 def test_compute_cg_ratio_aft(input_xml):
-    """ Tests computation of center of gravity with aft estimation """
+    """Tests computation of center of gravity with aft estimation"""
 
     input_list = [
         "data:weight:airframe:wing:CG:x",
@@ -322,7 +273,7 @@ def test_compute_cg_ratio_aft(input_xml):
 
 
 def test_compute_cg_tanks(input_xml):
-    """ Tests computation of tanks center of gravity """
+    """Tests computation of tanks center of gravity"""
 
     input_list = [
         "data:geometry:wing:spar_ratio:front:root",
@@ -354,7 +305,7 @@ def test_compute_cg_tanks(input_xml):
 
 
 def test_compute_cg_wing(input_xml):
-    """ Tests computation of wing center of gravity """
+    """Tests computation of wing center of gravity"""
 
     input_list = [
         "data:geometry:wing:kink:span_ratio",
@@ -387,7 +338,7 @@ def test_compute_cg_wing(input_xml):
 
 
 def test_compute_global_cg(input_xml):
-    """ Tests computation of global center of gravity """
+    """Tests computation of global center of gravity"""
 
     input_list = [
         "data:geometry:wing:MAC:length",
@@ -471,17 +422,14 @@ def test_compute_global_cg(input_xml):
 
 
 def test_compute_max_cg_ratio(input_xml):
-    """ Tests computation of maximum center of gravity ratio """
+    """Tests computation of maximum center of gravity ratio"""
 
     input_list = []
 
     input_vars = input_xml.read(only=input_list).to_ivc()
 
     input_vars.add_output("data:weight:aircraft:empty:CG:MAC_position", 0.387846)
-    input_vars.add_output("data:weight:aircraft:load_case_1:CG:MAC_position", 0.364924)
-    input_vars.add_output("data:weight:aircraft:load_case_2:CG:MAC_position", 0.285139)
-    input_vars.add_output("data:weight:aircraft:load_case_3:CG:MAC_position", 0.386260)
-    input_vars.add_output("data:weight:aircraft:load_case_4:CG:MAC_position", 0.388971)
+    input_vars.add_output("data:weight:aircraft:load_cases:CG:MAC_position:maximum", 0.388971)
 
     problem = run_system(ComputeMaxCGratio(), input_vars)
 
@@ -490,7 +438,7 @@ def test_compute_max_cg_ratio(input_xml):
 
 
 def test_compute_aircraft_cg(input_xml):
-    """ Tests computation of static margin """
+    """Tests computation of static margin"""
 
     input_list = [
         "data:geometry:wing:MAC:length",
@@ -504,3 +452,69 @@ def test_compute_aircraft_cg(input_xml):
 
     cg_global = problem["data:weight:aircraft:CG:aft:x"]
     assert cg_global == pytest.approx(17.1, abs=1e-1)
+
+
+def test_compute_ht_cg(input_xml):
+    """Tests computation of the horizontal tail center of gravity"""
+
+    input_list = [
+        "data:geometry:horizontal_tail:root:chord",
+        "data:geometry:horizontal_tail:tip:chord",
+        "data:geometry:horizontal_tail:MAC:at25percent:x:from_wingMAC25",
+        "data:geometry:horizontal_tail:span",
+        "data:geometry:wing:MAC:at25percent:x",
+        "data:geometry:horizontal_tail:sweep_25",
+        "data:geometry:horizontal_tail:MAC:length",
+    ]
+
+    input_vars = input_xml.read(only=input_list).to_ivc()
+    input_vars.add_output("data:geometry:horizontal_tail:MAC:at25percent:x:local", 1.656, units="m")
+
+    problem = run_system(ComputeHTcg(), input_vars)
+
+    cg_a31 = problem["data:weight:airframe:horizontal_tail:CG:x"]
+    assert cg_a31 == pytest.approx(34.58, abs=1e-2)
+
+
+def test_compute_vt_cg(input_xml):
+    """Tests computation of the vertical tail center of gravity"""
+
+    input_list = [
+        "data:geometry:vertical_tail:root:chord",
+        "data:geometry:vertical_tail:tip:chord",
+        "data:geometry:vertical_tail:MAC:at25percent:x:from_wingMAC25",
+        "data:geometry:vertical_tail:span",
+        "data:geometry:wing:MAC:at25percent:x",
+        "data:geometry:vertical_tail:sweep_25",
+        "data:geometry:vertical_tail:MAC:length",
+    ]
+
+    input_vars = input_xml.read(only=input_list).to_ivc()
+
+    input_vars.add_output("data:geometry:vertical_tail:MAC:at25percent:x:local", 2.321, units="m")
+
+    component = ComputeVTcg()
+
+    problem = run_system(component, input_vars)
+
+    cg_a32 = problem["data:weight:airframe:vertical_tail:CG:x"]
+    assert cg_a32 == pytest.approx(34.265, abs=1e-3)
+
+
+def test_geometry_update_mlg(input_xml):
+    """Tests computation of the main landing gear"""
+
+    input_list = [
+        "data:geometry:wing:MAC:length",
+        "data:geometry:wing:MAC:at25percent:x",
+    ]
+
+    input_vars = input_xml.read(only=input_list).to_ivc()
+
+    input_vars.add_output("data:weight:aircraft:CG:aft:MAC_position", 0.364924)
+    input_vars.add_output("data:weight:airframe:landing_gear:front:CG:x", 5.07)
+
+    problem = run_system(UpdateMLG(), input_vars)
+
+    cg_a51 = problem["data:weight:airframe:landing_gear:main:CG:x"]
+    assert cg_a51 == pytest.approx(18.00, abs=1e-2)
diff --git a/src/fastoad/models/weight/mass_breakdown/tests/test_mass_breakdown.py b/src/fastoad/models/weight/mass_breakdown/tests/test_mass_breakdown.py
index 70dac9c86..bc2c2fb37 100644
--- a/src/fastoad/models/weight/mass_breakdown/tests/test_mass_breakdown.py
+++ b/src/fastoad/models/weight/mass_breakdown/tests/test_mass_breakdown.py
@@ -2,7 +2,7 @@
 Test module for mass breakdown functions
 """
 #  This file is part of FAST-OAD : A framework for rapid Overall Aircraft Design
-#  Copyright (C) 2020  ONERA & ISAE-SUPAERO
+#  Copyright (C) 2021 ONERA & ISAE-SUPAERO
 #  FAST is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 #  the Free Software Foundation, either version 3 of the License, or
@@ -26,12 +26,12 @@
     EmpennageWeight,
     FlightControlsWeight,
     FuselageWeight,
+    LandingGearWeight,
     PaintWeight,
     PylonsWeight,
     WingWeight,
-    LandingGearWeight,
 )
-from ..b_propulsion import FuelLinesWeight, UnconsumablesWeight, EngineWeight
+from ..b_propulsion import EngineWeight, FuelLinesWeight, UnconsumablesWeight
 from ..c_systems import (
     FixedOperationalSystemsWeight,
     FlightKitWeight,
@@ -43,10 +43,10 @@
 from ..cs25 import Loads
 from ..d_furniture import (
     CargoConfigurationWeight,
-    PassengerSeatsWeight,
     FoodWaterWeight,
-    ToiletsWeight,
+    PassengerSeatsWeight,
     SecurityKitWeight,
+    ToiletsWeight,
 )
 from ..e_crew import CrewWeight
 from ..mass_breakdown import MassBreakdown, OperatingWeightEmpty
@@ -117,6 +117,8 @@ def test_compute_wing_weight():
         "data:geometry:wing:outer_area",
         "data:weight:aircraft:MTOW",
         "data:weight:aircraft:MLW",
+        "data:geometry:propulsion:engine:count",
+        "data:geometry:propulsion:layout",
         "tuning:weight:airframe:wing:mass:k",
         "tuning:weight:airframe:wing:mass:offset",
         "tuning:weight:airframe:wing:bending_sizing:mass:k",
@@ -129,7 +131,6 @@ def test_compute_wing_weight():
         "tuning:weight:airframe:wing:reinforcements:mass:offset",
         "tuning:weight:airframe:wing:secondary_parts:mass:k",
         "tuning:weight:airframe:wing:secondary_parts:mass:offset",
-        "settings:weight:airframe:wing:mass:k_voil",
         "settings:weight:airframe:wing:mass:k_mvo",
     ]