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()