diff --git a/esmvalcore/cmor/tables/custom/CMOR_ctotal.dat b/esmvalcore/cmor/tables/custom/CMOR_ctotal.dat
new file mode 100644
index 000000000..a7a2ea11f
--- /dev/null
+++ b/esmvalcore/cmor/tables/custom/CMOR_ctotal.dat
@@ -0,0 +1,21 @@
+SOURCE: CMIP5
+!============
+variable_entry:    ctotal
+!============
+modeling_realm:    land
+!----------------------------------
+! Variable attributes:
+!----------------------------------
+standard_name:
+units:             kg m-2
+cell_methods:      time: mean area: mean
+cell_measures:     area: areacella
+long_name:         Total Carbon Mass in Ecosystem
+!----------------------------------
+! Additional variable information:
+!----------------------------------
+dimensions:        longitude latitude time
+out_name:          ctotal
+type:              real
+!----------------------------------
+!
diff --git a/esmvalcore/preprocessor/_derive/ctotal.py b/esmvalcore/preprocessor/_derive/ctotal.py
new file mode 100644
index 000000000..76e539e89
--- /dev/null
+++ b/esmvalcore/preprocessor/_derive/ctotal.py
@@ -0,0 +1,31 @@
+"""Derivation of variable `ctotal`."""
+
+from iris import Constraint
+
+from ._baseclass import DerivedVariableBase
+
+
+class DerivedVariable(DerivedVariableBase):
+    """Derivation of variable `ctotal`."""
+
+    # Required variables
+    required = [
+        {
+            'short_name': 'cVeg'
+        },
+        {
+            'short_name': 'cSoil'
+        },
+    ]
+
+    @staticmethod
+    def calculate(cubes):
+        """Compute total ecosystem carbon storage."""
+        c_soil_cube = cubes.extract_strict(
+            Constraint(name='soil_carbon_content'))
+        c_veg_cube = cubes.extract_strict(
+            Constraint(name='vegetation_carbon_content'))
+        c_total_cube = c_soil_cube + c_veg_cube
+        c_total_cube.standard_name = None
+        c_total_cube.long_name = 'Total Carbon Stock'
+        return c_total_cube

derivation of total carbon stock over land
The CMIP5 variables do not include the total carbon mass content over land. This is often derived as the sum of the individual components. This normally should be the sum of cVeg and cSoil. But, checks are often necessary to ensure that all the smaller components have been considered. This leads to having a different set of components of mass content stocks for different models.

diff --git a/tests/unit/preprocessor/_derive/test_ctotal.py b/tests/unit/preprocessor/_derive/test_ctotal.py
new file mode 100644
index 000000000..d3f8189ce
--- /dev/null
+++ b/tests/unit/preprocessor/_derive/test_ctotal.py
@@ -0,0 +1,30 @@
+"""Test derivation of `ctotal`."""
+import iris
+import numpy as np
+import pytest
+from cf_units import Unit
+
+import esmvalcore.preprocessor._derive.ctotal as ctotal
+
+
+@pytest.fixture
+def cubes():
+    c_soil_cube = iris.cube.Cube([[1.0, 2.0],
+                                  [0.0, 20.0]],
+                                 units='kg m-2',
+                                 standard_name='soil_carbon_content')
+
+    c_veg_cube = iris.cube.Cube([[10.0, 20.0],
+                                 [50.0, 100.0]],
+                                units='kg m-2',
+                                standard_name='vegetation_carbon_content')
+    return iris.cube.CubeList([c_soil_cube, c_veg_cube])
+
+
+def test_ctotal_calculation(cubes):
+    derived_var = ctotal.DerivedVariable()
+    out_cube = derived_var.calculate(cubes)
+    np.testing.assert_allclose(
+        out_cube.data, np.array([[11.0, 22.0],
+                                 [50.0, 120.0]]))
+    assert out_cube.units == Unit('kg m-2')

environment.yml
pip install -e .[develop]
parse_log_pytest
environment.yml
pytest pytest-cov pytest-env pytest-flake8 pytest-html pytest-metadata
apt-get update apt-get install -y gcc
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
antlr4-python3-runtime @ file:///home/conda/feedstock_root/build_artifacts/antlr-python-runtime_1636143373368/work
astroid==2.15.8
attrs==24.2.0
Babel==2.14.0
build==0.10.0
Cartopy @ file:///home/conda/feedstock_root/build_artifacts/cartopy_1642060950241/work
certifi @ file:///home/conda/feedstock_root/build_artifacts/certifi_1725278078093/work/certifi
cf-units @ file:///home/conda/feedstock_root/build_artifacts/cf-units_1640986232540/work
cftime @ file:///home/conda/feedstock_root/build_artifacts/cftime_1663606412550/work
charset-normalizer==3.4.1
click==8.1.8
click-plugins==1.1.1
cligj==0.7.2
cloudpickle @ file:///home/conda/feedstock_root/build_artifacts/cloudpickle_1674202310934/work
colorama==0.4.6
coverage==7.2.7
cycler @ file:///home/conda/feedstock_root/build_artifacts/cycler_1635519461629/work
Cython @ file:///home/conda/feedstock_root/build_artifacts/cython_1659101942790/work
dask @ file:///home/conda/feedstock_root/build_artifacts/dask-core_1644602974678/work
dill==0.3.7
docutils==0.17.1
dodgy==0.2.1
easytest==0.1.5
ESMPy==8.2.0
-e git+https://github.com/ESMValGroup/ESMValCore.git@c6d3cced049c16728b3f798b0685ba96eba35e7f#egg=ESMValCore
exceptiongroup==1.2.2
fiona==1.9.6
flake8==5.0.4
flake8-polyfill==1.0.2
fonttools @ file:///home/conda/feedstock_root/build_artifacts/fonttools_1666389892786/work
fsspec @ file:///home/conda/feedstock_root/build_artifacts/fsspec_1674184942191/work
gitdb==4.0.12
GitPython==3.1.44
idna==3.10
imagesize==1.4.1
importlib-metadata==4.2.0
iniconfig==2.0.0
isodate==0.6.1
isort==5.11.5
Jinja2 @ file:///home/conda/feedstock_root/build_artifacts/jinja2_1715127149914/work
kiwisolver @ file:///home/conda/feedstock_root/build_artifacts/kiwisolver_1657953088445/work
lazy-object-proxy==1.9.0
llvmlite==0.39.1
locket @ file:///home/conda/feedstock_root/build_artifacts/locket_1650660393415/work
lxml==5.3.1
MarkupSafe @ file:///home/conda/feedstock_root/build_artifacts/markupsafe_1648737551960/work
matplotlib @ file:///home/conda/feedstock_root/build_artifacts/matplotlib-suite_1661439848456/work
mccabe==0.7.0
mock==5.2.0
mpi4py @ file:///home/conda/feedstock_root/build_artifacts/mpi4py_1660326262210/work
munkres==1.1.4
nc-time-axis==1.4.1
netCDF4 @ file:///home/conda/feedstock_root/build_artifacts/netcdf4_1661987221388/work
networkx==2.6.3
nose==1.3.7
numba==0.56.4
numpy @ file:///home/conda/feedstock_root/build_artifacts/numpy_1649806299270/work
olefile @ file:///home/conda/feedstock_root/build_artifacts/olefile_1701735466804/work
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1696202382185/work
partd @ file:///home/conda/feedstock_root/build_artifacts/partd_1695667515973/work
pathspec==0.11.2
pep8-naming==0.10.0
Pillow @ file:///tmp/build/80754af9/pillow_1625655818400/work
platformdirs==4.0.0
pluggy==1.2.0
prospector==1.10.3
prov==2.0.1
psutil==7.0.0
py==1.11.0
pycodestyle==2.9.1
pydocstyle==6.3.0
pydot==2.0.0
pyflakes==2.5.0
Pygments==2.17.2
pylint==2.17.7
pylint-celery==0.3
pylint-django==2.5.3
pylint-flask==0.6
pylint-plugin-utils==0.7
pyparsing @ file:///home/conda/feedstock_root/build_artifacts/pyparsing_1724616129934/work
pyproj @ file:///home/conda/feedstock_root/build_artifacts/pyproj_1636547699801/work
pyproject_hooks==1.2.0
pyroma==4.2
pyshp @ file:///home/conda/feedstock_root/build_artifacts/pyshp_1659002966020/work
pytest==7.4.4
pytest-cov==4.1.0
pytest-env==1.0.1
pytest-flake8==1.1.3
pytest-html==3.2.0
pytest-metadata==3.0.0
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1709299778482/work
pytz==2025.2
PyYAML @ file:///home/conda/feedstock_root/build_artifacts/pyyaml_1648757092905/work
rdflib==6.3.2
requests==2.31.0
requirements-detector==1.2.2
scipy @ file:///home/conda/feedstock_root/build_artifacts/scipy_1637806658031/work
scitools-iris @ file:///home/conda/feedstock_root/build_artifacts/iris_1637936208876/work
semver==3.0.4
setoptconf-tmp==0.3.1
Shapely @ file:///home/conda/feedstock_root/build_artifacts/shapely_1637399855493/work
six @ file:///home/conda/feedstock_root/build_artifacts/six_1620240208055/work
smmap==5.0.2
snowballstemmer==2.2.0
Sphinx==4.3.2
sphinx-rtd-theme==1.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
stratify @ file:///home/conda/feedstock_root/build_artifacts/python-stratify_1620938361732/work
toml==0.10.2
tomli==2.0.1
tomlkit==0.12.5
toolz @ file:///home/conda/feedstock_root/build_artifacts/toolz_1706112571092/work
trove-classifiers==2025.3.19.19
typed-ast==1.5.5
typing_extensions @ file:///home/conda/feedstock_root/build_artifacts/typing_extensions_1688315532570/work
unicodedata2 @ file:///home/conda/feedstock_root/build_artifacts/unicodedata2_1649111917568/work
urllib3==2.0.7
vmprof==0.4.18.1
wrapt==1.16.0
xxhash @ file:///home/conda/feedstock_root/build_artifacts/python-xxhash_1649442453935/work
yamale==4.0.4
yamllint==1.32.0
yapf==0.43.0
zipp==3.15.0

name: ESMValCore
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=2_gnu
  - antlr-python-runtime=4.7.2=py37h89c1867_1003
  - atk-1.0=2.38.0=h04ea711_2
  - binutils_impl_linux-64=2.43=h4bf12b8_4
  - binutils_linux-64=2.43=h4852527_4
  - brotli=1.1.0=hb9d3cd8_2
  - brotli-bin=1.1.0=hb9d3cd8_2
  - bzip2=1.0.8=h4bc722e_7
  - c-ares=1.34.4=hb9d3cd8_0
  - ca-certificates=2025.1.31=hbcca054_0
  - cairo=1.18.0=h3faef2a_0
  - cartopy=0.20.2=py37h9a08e6e_0
  - certifi=2024.8.30=pyhd8ed1ab_0
  - cf-units=3.0.1=py37hb1e94ed_2
  - cftime=1.6.2=py37hc105733_0
  - cloudpickle=2.2.1=pyhd8ed1ab_0
  - curl=8.8.0=he654da7_1
  - cycler=0.11.0=pyhd8ed1ab_0
  - cython=0.29.32=py37hd23a5d3_0
  - dask-core=2022.2.0=pyhd8ed1ab_0
  - esmf=8.2.0=mpi_mpich_h5a1934d_102
  - esmpy=8.2.0=mpi_mpich_py37h7352969_101
  - expat=2.6.4=h5888daf_0
  - font-ttf-dejavu-sans-mono=2.37=hab24e00_0
  - font-ttf-inconsolata=3.000=h77eed37_0
  - font-ttf-source-code-pro=2.038=h77eed37_0
  - font-ttf-ubuntu=0.83=h77eed37_3
  - fontconfig=2.14.2=h14ed4e7_0
  - fonts-conda-ecosystem=1=0
  - fonts-conda-forge=1=0
  - fonttools=4.38.0=py37h540881e_0
  - freetype=2.12.1=h267a509_2
  - fribidi=1.0.10=h36c2ea0_0
  - fsspec=2023.1.0=pyhd8ed1ab_0
  - gcc_impl_linux-64=14.2.0=hdb7739f_2
  - gcc_linux-64=14.2.0=h5910c8f_8
  - gdk-pixbuf=2.42.10=h5eee18b_1
  - geos=3.10.1=h9c3ff4c_1
  - glib=2.80.2=hf974151_0
  - glib-tools=2.80.2=hb6ce0ca_0
  - graphite2=1.3.13=h59595ed_1003
  - graphviz=9.0.0=h78e8752_1
  - gtk2=2.24.33=h280cfa0_4
  - gts=0.7.6=h977cf35_4
  - harfbuzz=8.5.0=hfac3d4d_0
  - hdf4=4.2.15=h9772cbc_5
  - hdf5=1.12.2=mpi_mpich_h5d83325_1
  - icu=73.2=h59595ed_0
  - iris=3.1.0=pyhd8ed1ab_3
  - jinja2=3.1.4=pyhd8ed1ab_0
  - jpeg=9e=h0b41bf4_3
  - kernel-headers_linux-64=3.10.0=he073ed8_18
  - keyutils=1.6.1=h166bdaf_0
  - kiwisolver=1.4.4=py37h7cecad7_0
  - krb5=1.21.3=h659f571_0
  - lcms2=2.14=h6ed2654_0
  - ld_impl_linux-64=2.43=h712a8e2_4
  - lerc=4.0.0=h27087fc_0
  - libaec=1.1.3=h59595ed_0
  - libblas=3.9.0=20_linux64_openblas
  - libbrotlicommon=1.1.0=hb9d3cd8_2
  - libbrotlidec=1.1.0=hb9d3cd8_2
  - libbrotlienc=1.1.0=hb9d3cd8_2
  - libcblas=3.9.0=20_linux64_openblas
  - libcurl=8.8.0=hca28451_1
  - libdeflate=1.14=h166bdaf_0
  - libedit=3.1.20250104=pl5321h7949ede_0
  - libev=4.33=hd590300_2
  - libexpat=2.6.4=h5888daf_0
  - libffi=3.4.6=h2dba641_0
  - libgcc=14.2.0=h767d61c_2
  - libgcc-devel_linux-64=14.2.0=h9c4974d_102
  - libgcc-ng=14.2.0=h69a702a_2
  - libgd=2.3.3=h695aa2c_1
  - libgfortran=14.2.0=h69a702a_2
  - libgfortran-ng=14.2.0=h69a702a_2
  - libgfortran5=14.2.0=hf1ad2bd_2
  - libglib=2.80.2=hf974151_0
  - libgomp=14.2.0=h767d61c_2
  - libiconv=1.18=h4ce23a2_1
  - liblapack=3.9.0=20_linux64_openblas
  - liblzma=5.6.4=hb9d3cd8_0
  - liblzma-devel=5.6.4=hb9d3cd8_0
  - libnetcdf=4.8.1=mpi_mpich_hcd871d9_6
  - libnghttp2=1.58.0=h47da74e_1
  - libnsl=2.0.1=hd590300_0
  - libopenblas=0.3.25=pthreads_h413a1c8_0
  - libpng=1.6.43=h2797004_0
  - librsvg=2.58.0=hadf69e7_1
  - libsanitizer=14.2.0=hed042b8_2
  - libsqlite=3.46.0=hde9e2c9_0
  - libssh2=1.11.0=h0841786_0
  - libstdcxx=14.2.0=h8f9b012_2
  - libstdcxx-ng=14.2.0=h4852527_2
  - libtiff=4.4.0=h82bc61c_5
  - libudunits2=2.2.28=h40f5838_3
  - libunwind=1.7.2=he02047a_0
  - libuuid=2.38.1=h0b41bf4_0
  - libwebp-base=1.5.0=h851e524_0
  - libxcb=1.15=h0b41bf4_0
  - libxml2=2.12.7=hc051c1a_1
  - libzip=1.10.1=h2629f0a_3
  - libzlib=1.2.13=h4ab18f5_6
  - locket=1.0.0=pyhd8ed1ab_0
  - markupsafe=2.1.1=py37h540881e_1
  - matplotlib-base=3.5.3=py37hf395dca_2
  - mpi=1.0=mpich
  - mpi4py=3.1.3=py37h52370cb_2
  - mpich=4.0.3=h846660c_100
  - munkres=1.1.4=pyh9f0ad1d_0
  - ncurses=6.5=h2d0b736_3
  - netcdf-fortran=4.6.0=mpi_mpich_h1e13492_2
  - netcdf4=1.6.0=nompi_py37h7187172_102
  - numpy=1.21.6=py37h976b520_0
  - olefile=0.47=pyhd8ed1ab_0
  - openjpeg=2.5.0=h7d73246_1
  - openssl=3.4.1=h7b32b05_0
  - packaging=23.2=pyhd8ed1ab_0
  - pango=1.54.0=h84a9a3c_0
  - partd=1.4.1=pyhd8ed1ab_0
  - pcre2=10.43=hcad00b1_0
  - pillow=8.3.1=py37h2c7a002_0
  - pip=24.0=pyhd8ed1ab_0
  - pixman=0.44.2=h29eaf8c_0
  - proj=8.2.0=h277dcde_0
  - pthread-stubs=0.4=hb9d3cd8_1002
  - pyparsing=3.1.4=pyhd8ed1ab_0
  - pyproj=3.2.1=py37hb589d83_5
  - pyshp=2.3.1=pyhd8ed1ab_0
  - python=3.7.12=hf930737_100_cpython
  - python-dateutil=2.9.0=pyhd8ed1ab_0
  - python-stratify=0.1.1=py37h6f94858_1004
  - python-xxhash=3.0.0=py37h540881e_1
  - python_abi=3.7=4_cp37m
  - pyyaml=6.0=py37h540881e_4
  - readline=8.2=h8c095d6_2
  - scipy=1.7.3=py37hf2a6cf1_0
  - setuptools=69.0.3=pyhd8ed1ab_0
  - shapely=1.8.0=py37h9b0f7a3_4
  - six=1.16.0=pyh6c4a22f_0
  - sqlite=3.46.0=h6d4b2fc_0
  - sysroot_linux-64=2.17=h0157908_18
  - tk=8.6.13=noxft_h4845f30_101
  - toolz=0.12.1=pyhd8ed1ab_0
  - typing-extensions=4.7.1=hd8ed1ab_0
  - typing_extensions=4.7.1=pyha770c72_0
  - tzdata=2025b=h78e105d_0
  - udunits2=2.2.28=h40f5838_3
  - unicodedata2=14.0.0=py37h540881e_1
  - wheel=0.42.0=pyhd8ed1ab_0
  - xorg-kbproto=1.0.7=hb9d3cd8_1003
  - xorg-libice=1.1.2=hb9d3cd8_0
  - xorg-libsm=1.2.6=he73a12e_0
  - xorg-libx11=1.8.9=h8ee46fc_0
  - xorg-libxau=1.0.12=hb9d3cd8_0
  - xorg-libxdmcp=1.1.5=hb9d3cd8_0
  - xorg-libxext=1.3.4=h0b41bf4_2
  - xorg-libxrender=0.9.11=hd590300_0
  - xorg-renderproto=0.11.1=hb9d3cd8_1003
  - xorg-xextproto=7.3.0=hb9d3cd8_1004
  - xorg-xproto=7.0.31=hb9d3cd8_1008
  - xxhash=0.8.0=h7f98852_3
  - xz=5.6.4=hbcc6ac9_0
  - xz-gpl-tools=5.6.4=hbcc6ac9_0
  - xz-tools=5.6.4=hb9d3cd8_0
  - yaml=0.2.5=h7f98852_2
  - zlib=1.2.13=h4ab18f5_6
  - zstd=1.5.6=ha6fb4c9_0
  - pip:
      - alabaster==0.7.13
      - astroid==2.15.8
      - attrs==24.2.0
      - babel==2.14.0
      - build==0.10.0
      - charset-normalizer==3.4.1
      - click==8.1.8
      - click-plugins==1.1.1
      - cligj==0.7.2
      - colorama==0.4.6
      - coverage==7.2.7
      - dill==0.3.7
      - docutils==0.17.1
      - dodgy==0.2.1
      - easytest==0.1.5
      - exceptiongroup==1.2.2
      - fiona==1.9.6
      - flake8==5.0.4
      - flake8-polyfill==1.0.2
      - gitdb==4.0.12
      - gitpython==3.1.44
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.2.0
      - iniconfig==2.0.0
      - isodate==0.6.1
      - isort==5.11.5
      - lazy-object-proxy==1.9.0
      - llvmlite==0.39.1
      - lxml==5.3.1
      - mccabe==0.7.0
      - mock==5.2.0
      - nc-time-axis==1.4.1
      - networkx==2.6.3
      - nose==1.3.7
      - numba==0.56.4
      - pathspec==0.11.2
      - pep8-naming==0.10.0
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - prospector==1.10.3
      - prov==2.0.1
      - psutil==7.0.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pydocstyle==6.3.0
      - pydot==2.0.0
      - pyflakes==2.5.0
      - pygments==2.17.2
      - pylint==2.17.7
      - pylint-celery==0.3
      - pylint-django==2.5.3
      - pylint-flask==0.6
      - pylint-plugin-utils==0.7
      - pyproject-hooks==1.2.0
      - pyroma==4.2
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - pytest-env==1.0.1
      - pytest-flake8==1.1.3
      - pytest-html==3.2.0
      - pytest-metadata==3.0.0
      - pytz==2025.2
      - rdflib==6.3.2
      - requests==2.31.0
      - requirements-detector==1.2.2
      - semver==3.0.4
      - setoptconf-tmp==0.3.1
      - smmap==5.0.2
      - snowballstemmer==2.2.0
      - sphinx==4.3.2
      - sphinx-rtd-theme==1.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - toml==0.10.2
      - tomli==2.0.1
      - tomlkit==0.12.5
      - trove-classifiers==2025.3.19.19
      - typed-ast==1.5.5
      - urllib3==2.0.7
      - vmprof==0.4.18.1
      - wrapt==1.16.0
      - yamale==4.0.4
      - yamllint==1.32.0
      - yapf==0.43.0
      - zipp==3.15.0
prefix: /opt/conda/envs/ESMValCore

tests/unit/preprocessor/_derive/test_ctotal.py::flake-8::FLAKE8
tests/unit/preprocessor/_derive/test_ctotal.py::test_ctotal_calculation
esmvalcore/preprocessor/_derive/ctotal.py esmvalcore/cmor/tables/custom/CMOR_ctotal.dat
esmvalcore/preprocessor/_derive/ctotal.py esmvalcore/cmor/tables/custom/CMOR_ctotal.dat