diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ca0f0fb5e61c0ddc2c3d41a18c43820a93dd339b..105be729e3afc02495b8c5c36604a2412d0e5487 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -104,10 +104,7 @@ compile-cerngetdp:
     - md $CI_PROJECT_DIR/compiled_getdp
     - copy getdp.exe $CI_PROJECT_DIR/compiled_getdp
   tags:
-    - windows
-    - mpi
-  except:
-    - tags
+    - wingetdpmpi
   artifacts:
     paths:
       - $CI_PROJECT_DIR/compiled_getdp
@@ -155,7 +152,7 @@ test-cerngetdp:
 
 package-win64:
   stage: package
-  needs: ["compile-shared-lib-win64"]
+  needs: ["compile-shared-lib-win64", "compile-mex"]
   image: gitlab-registry.cern.ch/steam/ci-deployer-docker:latest
   script:
     - export RELEASE_NAME=$(expr match "$CI_COMMIT_TAG" '\(.*\)-release$')
diff --git a/README.md b/README.md
index 4c45c0f5a03532856ce7accb9dd20c24958735a3..bbbd11fd3b8956321373d48c33a328176a8a4e24 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,15 @@ https://steam-material-library.docs.cern.ch/
 
 Some of this documentation can also be accessed through the `docs` folder.
 
+## Adding a material function:
+
+- Add the c-function to the models/c/general folder.
+- Make sure it has 'return_test_yaml' and the 'eval' function inside of it.
+- Add the function name to the all_material_functions.csv file.
+- Make sure that testing and make_ref is set to TRUE -> this means that a reference file will be made and the output of the function will be tested against this rerefence file.
+- Run utils/generate_ref_data.py
+- Run tests/test_dll.py -> this will build a local dll library and will test all c-functions, it requires you to have installed CMake and its requirements.
+
 ## Implementation in CERN simulating interfaces
 
 ### CERNGetDP
diff --git a/bindings/python/src/steammaterials/STEAM_materials.py b/bindings/python/src/steammaterials/STEAM_materials.py
index 2328da346d4bac2b62f559e6127c72c949fd3478..6417678085599859f233cfdb6cd464a6d0ee685e 100644
--- a/bindings/python/src/steammaterials/STEAM_materials.py
+++ b/bindings/python/src/steammaterials/STEAM_materials.py
@@ -66,7 +66,10 @@ class STEAM_materials:
         :param numpy2d: Numpy array with number of columns corresponding to number of function arguments and points to evaluate in rows
         :return: Numpy array with values calculated by .dll function
         """
-        numpy2d = numpy2d.astype(np.float64)
+        if not isinstance(numpy2d, np.ndarray):
+            numpy2d = np.array(numpy2d, dtype=np.float64, order='C')
+        else:
+            numpy2d = np.ascontiguousarray(numpy2d, dtype=np.float64)
         inReal = (numpy2d.__array_interface__['data'][0] + np.arange(numpy2d.shape[0]) * numpy2d.strides[0]).astype(np.uintp)
         error_out = self.eval(self.func_name, self.n_arg, inReal, inReal, self.n_points, self.RealPtr, self.Int_Ptr)
         if error_out == 1:
diff --git a/requirements.txt b/requirements.txt
index 7a754c27f6d61ad0e652c3355946aaadaca31c47..1560f6e2e18d59ba97992674c446e575a46b8857 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-STEAM-materials~=2024.11.2
+STEAM-materials~=2024.11.3
 numpy==1.26.4
 pandas==2.2.3
 wget==3.2
diff --git a/utils/generate_ref_data.py b/utils/generate_ref_data.py
index d64b45f7273a9b7b56831a0a997e60f49abfac2e..f5db0a75cc2382445c5aeb0acfb14a6d1dc13c71 100644
--- a/utils/generate_ref_data.py
+++ b/utils/generate_ref_data.py
@@ -1,164 +1,66 @@
-import  itertools
-import  yaml
-import  numpy as np
-from 	steammaterials.STEAM_materials import STEAM_materials
-from    datetime import datetime
-from    pathlib import Path
-import  os
-import  pandas as pd
+#!/usr/bin/env python3
+import itertools
+import yaml
+import numpy as np
+from   steammaterials.STEAM_materials import STEAM_materials
+from   datetime import datetime
+from   pathlib import Path
+import os
+import sys
+import pandas as pd
 
 
-################ FILL THIS IN #################
-csv_file = pd.read_csv(Path('../all_material_functions.csv'))
+def create_all_ref_files(output_path=None):
+    repository_root = Path(os.path.dirname(__file__)).parent
+    if output_path is None:
+        output_path = repository_root / 'tests' / 'ref_data'
+    csv_file = pd.read_csv(repository_root / 'all_material_functions.csv')
+   
+    errors = 0
+    for i, row in csv_file.iterrows():
+        if row['make_ref']:
+            try:
+                create_ref_file(row, output_path)
+            except Exception as e:
+                print(f'Failed to generate reference file for {row["ref_name"]}')
+                print(f'Failed with error: {e}')
+                errors += 1
+    if errors:
+        print(f'!!! During generation, {errors} errors occurred !!!')
 
-for i in range(len(csv_file)):
-    if csv_file.iloc[i]['make_ref']:
-        input_parameters = int(csv_file.iloc[i]['input_parameters'])
-        gen_by = csv_file.iloc[i]['ref_generated_by']
-        ref_name = csv_file.iloc[i]['ref_name']
 
+def create_ref_file(row, output_path):
+    """
+    Creates a file to act as reference for the expected output of the given material function.
+    Expects a dictionary-like `row` containing the number of 'input_parameters', the material name
+    'ref_name', author 'ref_generated_by' and inputs with 'input{i}'.
+    """
+    parameter_count = int(row['input_parameters'])
+    ref_name = row['ref_name']
+    if parameter_count < 1:
+        raise ValueError('Incorrect number of input parameters for {ref_name}')
 
-        # you = 'Tim Mulder'
-        # # material_function = 'CFUN_rhoHast_v2'
-        # # input_parameters = 1
-        # material_function = 'CFUN_rhoCu_NIST_v2'
-        # input_parameters = 3
-        ###############################################
+    inputs = [eval(row[f'input{i+1}']) for i in range(parameter_count)]
+    input_mat = np.array(list(itertools.product(*inputs))).T
+    out = STEAM_materials(ref_name, input_mat.shape[0], input_mat.shape[1]).evaluate(input_mat)
 
-        if input_parameters == 1:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            numpy2d = input1.reshape((1, len(input1)))
-            input_list = np.array([[i] for i in input1])
-        elif input_parameters == 2:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input_list = np.array([i for i in itertools.product(input1, input2)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1]))
-        elif input_parameters == 3:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2]))
-        elif input_parameters == 4:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3]))
-        elif input_parameters == 5:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4]))
-        elif input_parameters == 6:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5]))
-        elif input_parameters == 7:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6]))
-        elif input_parameters == 8:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input8 = eval(csv_file.iloc[i]['input8'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7, input8)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6], input_list[:, 7]))
-        elif input_parameters == 9:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input8 = eval(csv_file.iloc[i]['input8'])
-            input9 = eval(csv_file.iloc[i]['input9'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7, input8, input9)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6], input_list[:, 7], input_list[:, 8]))
-        elif input_parameters == 10:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input8 = eval(csv_file.iloc[i]['input8'])
-            input9 = eval(csv_file.iloc[i]['input9'])
-            input10 = eval(csv_file.iloc[i]['input10'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7, input8, input9, input10)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6], input_list[:, 7], input_list[:, 8], input_list[:, 9]))
-        elif input_parameters == 11:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input8 = eval(csv_file.iloc[i]['input8'])
-            input9 = eval(csv_file.iloc[i]['input9'])
-            input10 = eval(csv_file.iloc[i]['input10'])
-            input11 = eval(csv_file.iloc[i]['input11'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7, input8, input9, input10, input11)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6], input_list[:, 7], input_list[:, 8], input_list[:, 9], input_list[:, 10]))
-        elif input_parameters == 12:
-            input1 = eval(csv_file.iloc[i]['input1'])
-            input2 = eval(csv_file.iloc[i]['input2'])
-            input3 = eval(csv_file.iloc[i]['input3'])
-            input4 = eval(csv_file.iloc[i]['input4'])
-            input5 = eval(csv_file.iloc[i]['input5'])
-            input6 = eval(csv_file.iloc[i]['input6'])
-            input7 = eval(csv_file.iloc[i]['input7'])
-            input8 = eval(csv_file.iloc[i]['input8'])
-            input9 = eval(csv_file.iloc[i]['input9'])
-            input10 = eval(csv_file.iloc[i]['input10'])
-            input11 = eval(csv_file.iloc[i]['input11'])
-            input12 = eval(csv_file.iloc[i]['input12'])
-            input_list = np.array([i for i in itertools.product(input1, input2, input3, input4, input5, input6, input7, input8, input9, input10, input11, input12)])
-            numpy2d = np.vstack((input_list[:, 0], input_list[:, 1], input_list[:, 2], input_list[:, 3], input_list[:, 4], input_list[:, 5], input_list[:, 6], input_list[:, 7], input_list[:, 8], input_list[:, 9], input_list[:, 10], input_list[:, 11]))
-        else:
-            print('Wrong amount of input parameters')
+    dictionary_output = {
+        'author': row['ref_generated_by'],
+        'date': datetime.today().strftime('%d.%m.%Y'),
+        'material_function': ref_name,
+        'input': input_mat.T.tolist(),
+        'output': [i.item() for i in out],
+        'input_parameters': parameter_count,
+    }
+    try:
+        with (output_path / f'{ref_name}.yaml').open("x") as f:
+            yaml.dump(dictionary_output, f, default_flow_style=False)
+    except FileExistsError:
+        print(f'Reference file for {ref_name} already exists. You cannot overwrite it.')
 
-        ###############################################
-        if input_parameters >= 1:
-            out = STEAM_materials(ref_name, numpy2d.shape[0], numpy2d.shape[1]).evaluate(numpy2d)
-        else:
-            print('Wrong amount of input parameters')
 
-        ############### Making the yaml ################
-        dictionary_output = {
-            'author': gen_by,
-            'date': datetime.today().strftime('%d.%m.%Y'),
-            'material_function': ref_name,
-            'input': [[i.item() for i in k] for k in input_list],
-            'output': [i.item() for i in out],
-            'input_parameters': input_parameters,
-        }
-        try:
-            with Path(os.path.dirname(os.path.dirname(__file__)) + os.sep + 'tests' + os.sep + 'ref_data' + os.sep + ref_name+".yaml").open("x") as f:
-                yaml.dump(dictionary_output, f, default_flow_style=False)
-        except:
-            print('Reference file for ' + ref_name + ' already excists. You cannot overwrite it.')
+if __name__ == '__main__':
+    if len(sys.argv) > 1:
+        create_all_ref_files(Path(sys.argv[1]))
+    else:
+        create_all_ref_files()