From 2240c2fadbf522feb87c01f9e65fed3120b9d59d Mon Sep 17 00:00:00 2001 From: Emily Bourne Date: Mon, 29 Jul 2024 15:02:03 +0000 Subject: [PATCH] Merge branch 'ebourne_gysela_ddc_aliases' into 'main' New ddc aliases for Gysela See merge request gysela-developpers/gyselalibxx!537 --- bin/update_naming_conventions.py | 501 ++++++++++++++++++ .../testcollisions/testcollisions.cpp | 51 +- src/collisions/CollisionSpVparMu.hpp | 6 +- src/data_types/derivative_field_common.hpp | 2 +- src/geometry5D/geometry/geometry.hpp | 151 +++--- src/utils/ddc_aliases.hpp | 140 +++++ 6 files changed, 749 insertions(+), 102 deletions(-) create mode 100644 bin/update_naming_conventions.py create mode 100644 src/utils/ddc_aliases.hpp diff --git a/bin/update_naming_conventions.py b/bin/update_naming_conventions.py new file mode 100644 index 000000000..d3096a053 --- /dev/null +++ b/bin/update_naming_conventions.py @@ -0,0 +1,501 @@ +import argparse +from itertools import chain +from pathlib import Path +import re +import shutil +import subprocess + +HOME_DIR = Path(__file__).parent.parent + +def update_names(old_name, new_name, applicable_files, complete_word = True): + """ + Update the name of an object across the files. + + Parameters + ---------- + old_name : str + The current name found in the code. + new_name : str + The name which should be used instead. + applicable_files : list[Path] + A list of the files whose contents should be modified. + complete_word : bool, default=True + True if only complete words should be replaced, False for complex regex expressions. + """ + if complete_word: + old_name = rf'\<{old_name}\>' + subprocess.run(['sed', '-i', f's/{old_name}/{new_name}/g'] + applicable_files) + +key_map = {'<':'>', + '(':')', + '[':']', + '{':'}'} + +def find_argument(open_tag, expr): + """ + Find the arguments at the start of an expression. + + The arguments may be template arguments, function arguments etc. + The function takes a string beginning after the opening tag and + looks for the closing tag which matches the opening tag. It then + returns the arguments between the two tags. + """ + close_tag = key_map[open_tag] + opened = [None] + i = 0 + while len(opened): + if expr[i] == open_tag: + opened.append(i) + elif expr[i] == close_tag: + opened.pop() + + i+= 1 + return expr[:i] + +def get_new_Coord_name(alias_match): + """ + Get the new name of a coordinate from a regex describing a type alias (see remove_conflicting_names). + """ + groups = alias_match.groups() + if 'continuous_element_type' in groups[0]: + return 'Coord1D' + else: + tags = groups[2] + if '...' in tags: + return 'CoordND' + else: + ntags = tags.count(',')+1 + return f'Coord{ntags}D' + +def remove_conflicting_names(applicable_files): + """ + Remove names used in the code which conflict with the new gysela templated types. + The names are: + - Coord + + Parameters + ---------- + applicable_files : list[Path] + A list of the files whose contents should be modified. + """ + for file in applicable_files: + with open(file, 'r') as f: + code = f.read() + + type_aliases = list(re.finditer('using Coord = ((ddc::)?Coordinate<([a-zA-Z0-9_:, \.]+)>|[a-zA-Z0-9 ]+::continuous_element_type)', code)) + if not type_aliases: + continue + + if len(type_aliases) == 1: + new_name = get_new_Coord_name(type_aliases[0]) + code = re.sub(r'\bCoord\b(?!<)', new_name, code) + else: + alias_match = type_aliases[0] + while alias_match: + scope_start = code.rfind('{', 0, alias_match.start()) + scope_contents = find_argument('{', code[scope_start + 1:]) + scope_end = len(scope_contents) + scope_start + 1 + + new_name = get_new_Coord_name(alias_match) + code = code[:scope_start + 1] + re.sub(r'\bCoord\b(?!<)', new_name, scope_contents) \ + + code[scope_end:] + + alias_match = re.search('using Coord = ((ddc::)?Coordinate<([a-zA-Z0-9_:, \.]+)>|[a-zA-Z0-9 ]+::continuous_element_type)', code) + + with open(file, 'w') as f: + f.write(code) + if not code.endswith('\n'): + f.write('\n') + +def replace_array(old_name, new_name, code, memory_arg_position): + """ + Replace the name of an array-like object, inserting host_t if necessary. + + Parameters + ---------- + old_name : str + The current name found in the code. + new_name : str + The name which should be used instead. + code : str + The code to be modified. + memory_arg_position : int + The index indicating the position where the memory space is specified + in the template arguments. + """ + location = re.search(f'{old_name}<', code) + while location: + arg = find_argument('<', code[location.end():]) + if arg.count(',') < memory_arg_position: + code = code[:location.start()] + f'host_t<{new_name}<' + arg + '>' + code[location.end() + len(arg):] + else: + code = code[:location.start()] + f'{new_name}<' + arg + code[location.end() + len(arg):] + location = re.search(f'{old_name}<', code) + + return code + +def replace_device_array(old_name, new_name, code): + """ + Replace the name of an array-like object found on the device. + The device tag is removed as it is specified by default in Gysela naming conventions. + + Parameters + ---------- + old_name : str + The current name found in the code. + new_name : str + The name which should be used instead. + code : str + The code to be modified. + memory_arg_position : int + The index indicating the position where the memory space is specified + in the template arguments. + """ + location = re.search(rf'device_t<\s*{old_name}<', code) + while location: + arg = find_argument('<', code[location.end():]) + close_device = code.find('>', location.end() + len(arg)) + code = code[:location.start()] + f'{new_name}<' + arg + code[close_device+1:] + location = re.search(f'device_t<{old_name}<', code) + + return code + +def replace_memory_block(old_name, new_name, code, memory_arg_position): + """ + Replace the name of an array-like object, inserting and removing host_t/device_t if necessary. + + Parameters + ---------- + old_name : str + The current name found in the code. + new_name : str + The name which should be used instead. + code : str + The code to be modified. + memory_arg_position : int + The index indicating the position where the memory space is specified + in the template arguments. + """ + code = replace_device_array(old_name, new_name, code) + code = replace_array(old_name, new_name, code, memory_arg_position) + return re.sub(f'\<{old_name}\>', new_name, code) + +def replace_domain_variable_name(code): + """ + Replace the word domain or dom in the code. Only places where the word is + proceeded and succeeded by either an underscore or a space are modified. + + Parameters + ---------- + code : str + The code to be modified. + """ + code = re.sub('(_|\b)(dom)(_|\b)', r'\1idx_range\3', code) + + location = re.search('domain', code) + while location: + line_start_idx = code.rfind('\n', 0, location.start()) + last_comment_block_start = code.rfind('/*', 0, location.start()) + last_comment_block_end = code.rfind('*/', 0, location.start()) + in_comment = '//' in code[line_start_idx:location.start()] or \ + last_comment_block_start > last_comment_block_end + + new_text = 'index range' if in_comment else 'idx_range' + code = code[:location.start()] + new_text + code[location.end():] + + location = re.search(rf'domain', code) + + # Revert for bad renames + code = code.replace('@param index range', '@param idx_range') + code = code.replace('@param[in] index range', '@param[in] idx_range') + + # Revert for DDC names + code = code.replace('::get_idx_range', '::get_domain') + code = code.replace('discrete_idx_range_type', 'discrete_domain_type') + code = code.replace('template get_idx_range', 'template get_domain') + code = code.replace('batched_spline_idx_range', 'batched_spline_domain') + + return code.replace(' a index ', ' an index ') + +def update_names_using_context_clues(applicable_files): + """ + Update the names of objects when the new name is dependant on context clues. + + This must be done via parsing to find those clues. + The function updates the names of Chunks, Spans and Views. These require + context clues to handle memory spaces correctly. + It also updates variable names describing domains + """ + for fname in applicable_files: + with open(fname, 'r') as f: + orig_code = f.read() + + code = replace_memory_block('ddc::Chunk', 'FieldMem', orig_code, 2) + code = replace_memory_block('ddc::ChunkSpan', 'Field', code, 3) + code = replace_memory_block('ddc::ChunkView', 'ConstField', code, 3) + + code = replace_domain_variable_name(code) + + if code != orig_code: + with open(fname, 'w') as f: + f.write(code) + if not code.endswith('\n'): + f.write('\n') + +def get_geometry_name_shortcuts(geometry_file): + """ + Read the geometry.hpp file and look for all types/aliases that should be renamed to + follow the new conventions. + + Parameters + ---------- + geometry_file : str + The path to the geometry file. + + Returns + ------- + dict[str, str] + A dictionary whose keys are types to be renamed and whose values are the new + names. + """ + with open(geometry_file, 'r') as f: + code = f.read() + + structures = re.finditer('(struct|using|class) ([a-zA-Z0-9]+)', code) + + name_map = {} + + species_names = {'IdxSp', 'IdxRangeSp', 'IdxStepSp', 'FieldMemSp', 'DFieldMemSp', 'IFieldSp', 'ConstFieldSp', 'DConstFieldSp', 'FieldSp', 'DFieldSp'} + + for s in structures: + struct_name = s[2] + if struct_name in species_names: + continue + if struct_name == 'RDim': + name_map[struct_name] = 'Dim' + elif struct_name in ('DDim', 'IDim'): + name_map[struct_name] = 'Grid1D' + elif struct_name.startswith('RDim'): + new_name = struct_name[4:] + if not new_name[0].isalpha(): + new_name = 'Dim' + new_name + name_map[struct_name] = new_name + elif struct_name.startswith('IDim') or struct_name.startswith('DDim'): + name_map[struct_name] = 'Grid' + struct_name[4:] + elif struct_name.startswith('Index'): + name_map[struct_name] = 'Idx' + struct_name[5:] + elif struct_name.startswith('IVect'): + name_map[struct_name] = 'IdxStep' + struct_name[5:] + elif struct_name.startswith('DVec'): + name_map[struct_name] = 'IdxStep' + struct_name[4:] + elif struct_name.startswith('IDomain'): + name_map[struct_name] = 'IdxRange' + struct_name[7:] + elif struct_name.startswith('BSDomain'): + name_map[struct_name] = 'BSIdxRange' + struct_name[8:] + elif struct_name.endswith('Index'): + name_map[struct_name] = struct_name[:-5] + 'Idx' + elif struct_name.startswith('Field'): + name_map[struct_name] = 'FieldMem' + struct_name[5:] + elif struct_name.startswith('Span'): + name_map[struct_name] = 'Field' + struct_name[4:] + elif struct_name.startswith('View'): + name_map[struct_name] = 'ConstField' + struct_name[4:] + elif struct_name.startswith('DField'): + name_map[struct_name] = 'DFieldMem' + struct_name[6:] + elif struct_name.startswith('DSpan'): + name_map[struct_name] = 'DField' + struct_name[5:] + elif struct_name.startswith('DView'): + name_map[struct_name] = 'DConstField' + struct_name[5:] + elif 'DomainType' in struct_name: + name_map[struct_name] = struct_name.replace('DomainType', 'IdxRange') + elif 'Domain' in struct_name: + name_map[struct_name] = struct_name.replace('Domain', 'IdxRange') + elif 'DDom' in struct_name: + name_map[struct_name] = struct_name.replace('DDom', 'IdxRange') + elif 'ChunkSpan' in struct_name: + name_map[struct_name] = struct_name.replace('ChunkSpan', 'Field') + elif 'ChunkView' in struct_name: + name_map[struct_name] = struct_name.replace('ChunkView', 'ConstField') + elif 'Span' in struct_name: + name_map[struct_name] = struct_name.replace('Span', 'Field') + elif 'View' in struct_name: + name_map[struct_name] = struct_name.replace('View', 'ConstField') + elif struct_name.startswith('DElem'): + name_map[struct_name] = 'Idx' + struct_name[5:] + + return name_map + +def add_missing_include(): + """ + Add the include to get access to the new aliases in files that have been modified to use these aliases. + Additionally add the necessary linkage in the CMakeLists.txt file. + """ + p = subprocess.run(['git', 'diff', '--name-only'], capture_output=True, cwd=HOME_DIR, universal_newlines=True) + modified_files = [HOME_DIR / file for file in p.stdout.split() if file[-4:] in ('.hpp', '.cpp')] + for file in modified_files: + subprocess.run(['sed', '-i', '-e', "/#pragma once/a\\", '-e', '#include "ddc_aliases.hpp"', file]) + + folders = set(file.parent for file in modified_files) + try: + folders.remove(Path(HOME_DIR / 'src' / 'utils')) + except KeyError: + pass + + for f in folders: + cmake = f / 'CMakeLists.txt' + with open(cmake, 'r') as f: + code = f.read() + + key = 'target_link_libraries(' + key_len = len(key) + lib_loc = code.find(key) + while lib_loc != -1: + lib_loc += key_len + args = find_argument('(', code[lib_loc:]) + if 'gslx::utils' not in args: + last_gslx_lib = args.rfind('gslx::') + if last_gslx_lib == -1: + last_gslx_lib = args.rfind(' ')-1 + line_start = args.rfind('\n', 0, last_gslx_lib) + line_end = args.find('\n', last_gslx_lib) + code = code[:lib_loc] + args[:line_end] + args[line_start:last_gslx_lib] + \ + 'gslx::utils\n' + args[line_end:] + code[lib_loc+len(args):] + lib_loc = code.find(key, lib_loc) + + with open(cmake, 'w') as f: + f.write(code) + if not code.endswith('\n'): + f.write('\n') + +def introduce_get_idx_range(applicable_files): + """ + Replace calls to the DDC .domain() method with calls to get_idx_range. + + Parameters + ---------- + applicable_files : list[Path] + A list of the files whose contents should be modified. + """ + update_names(r'\([a-zA-Z0-9_.]\+\)\.spline_domain()', r'get_spline_idx_range(\1)', applicable_files, complete_word = False) + update_names(r'\([a-zA-Z0-9_.]\+\)\.domain()', r'get_idx_range(\1)', applicable_files, complete_word = False) + update_names(r'\([a-zA-Z0-9_.]\+\)\.domain<\([a-zA-Z0-9, .]*\)>()', r'get_idx_range<\2>(\1)', applicable_files, complete_word = False) + update_names(r'\([a-zA-Z0-9_.]\+\)\.get_domain()', r'get_idx_range(\1)', applicable_files, complete_word = False) + update_names(r'\([a-zA-Z0-9_.]\+\)\.get_domain<\([a-zA-Z0-9, .]*\)>()', r'get_idx_range<\2>(\1)', applicable_files, complete_word = False) + update_names(r'ddc::get_domain(\([a-zA-Z0-9_]\+\))', r'get_idx_range(\1)', applicable_files, complete_word = False) + update_names(r'ddc::get_domain<\([a-zA-Z0-9, .]*\)>(\([a-zA-Z0-9_]\+\))', r'get_idx_range<\1>(\2)', applicable_files, complete_word = False) + update_names(r'ddc::domain(\([a-zA-Z0-9_]\+\))', r'get_idx_range(\1)', applicable_files, complete_word = False) + update_names(r'ddc::domain<\([a-zA-Z0-9, .]*\)>(\([a-zA-Z0-9_]\+\))', r'get_idx_range<\1>(\2)', applicable_files, complete_word = False) + +def introduce_field_getters(applicable_files): + """ + Replace calls to the DDC .domain() method with calls to get_idx_range. + + Parameters + ---------- + applicable_files : list[Path] + A list of the files whose contents should be modified. + """ + update_names(r'\([a-zA-Z0-9_.]\+\)\.span_view()', r'get_field(\1)', applicable_files, complete_word = False) + update_names(r'\([a-zA-Z0-9_.]\+\)\.span_cview()', r'get_const_field(\1)', applicable_files, complete_word = False) + +def update_local_type_aliases(applicable_hpp_files, applicable_cpp_files): + """ + Loop over files to find type aliases which are local to classes or mains. + """ + treated_cpp_files = set() + for file in applicable_hpp_files: + name_map = get_geometry_name_shortcuts(file) + files_to_update = [file] + cpp_file = file.with_suffix('.cpp') + if cpp_file.exists(): + files_to_update.append(cpp_file) + treated_cpp_files.add(cpp_file) + + for old_name, new_name in name_map.items(): + update_names(old_name, new_name, files_to_update) + + for file in set(applicable_cpp_files).difference(treated_cpp_files): + name_map = get_geometry_name_shortcuts(file) + + for old_name, new_name in name_map.items(): + update_names(old_name, new_name, [file]) + +if __name__ == '__main__': + parser = argparse.ArgumentParser("A script to automatise some of the renaming. This script is not perfect so please check the changes and the compilation") + parser.add_argument('folders', type=Path, help='The folder where files should be renamed', nargs='+') + args = parser.parse_args() + + folders = [f.resolve().absolute() for f in args.folders] + for folder in folders: + assert HOME_DIR in folder.parents + + src_folder = (HOME_DIR / 'src') + test_folder = (HOME_DIR / 'tests') + simu_folder = (HOME_DIR / 'simulations') + + # Exclude the file which renames DDC aliases + hpp_files = [h for folder in folders for h in folder.glob(f'**/*.hpp') \ + if h.stem not in ('ddc_aliases', 'ddc_helper')] + main_files = [] + for folder in folders: + # Files which may contain a main + if folder in (test_folder, simu_folder) or test_folder in folder.parents or simu_folder in folder.parents: + main_files.extend(folder.glob('**/*.cpp')) + cpp_files = [h for folder in folders for h in folder.glob('**/*.cpp')] + files_to_update = hpp_files + cpp_files + + remove_conflicting_names(chain(hpp_files, main_files)) + + # Update basic names with no additional considerations + update_names('DiscreteSubDomain', 'IdxRangeSlice', files_to_update) + update_names('ddc::Coordinate', 'Coord', files_to_update) + update_names('ddc::DiscreteElement', 'Idx', files_to_update) + update_names('ddc::DiscreteVector', 'IdxStep', files_to_update) + update_names('ddc::DiscreteDomain', 'IdxRange', files_to_update) + update_names('ddc::NonUniformPointSampling', 'NonUniformGridBase', files_to_update) + update_names('ddc::UniformPointSampling', 'UniformGridBase', files_to_update) + update_names('IDimSp', 'Species', files_to_update) + update_names('discrete dimension', 'discretised dimension', files_to_update) + + introduce_get_idx_range(files_to_update) + introduce_field_getters(files_to_update) + + # Update chunk names taking memory space into consideration + update_names_using_context_clues(files_to_update) + + add_missing_include() + + name_map = get_geometry_name_shortcuts(HOME_DIR / 'src/speciesinfo/species_info.hpp') + + # Update species names + for old_name, new_name in name_map.items(): + update_names(old_name, new_name, files_to_update) + + for folder in folders: + for geom_file in folder.glob('**/geometry.hpp'): + name_map = get_geometry_name_shortcuts(geom_file) + + geom = geom_file.parents[1] + + # Get files associated with the geometry + files_to_update = list(chain(geom.glob('**/*.hpp'), geom.glob('**/*.cpp'), + (HOME_DIR / 'tests' / geom.stem).glob('**/*.hpp'), + (HOME_DIR / 'tests' / geom.stem).glob('**/*.cpp'), + (HOME_DIR / 'simulations' / geom.stem).glob('**/*.hpp'), + (HOME_DIR / 'simulations' / geom.stem).glob('**/*.cpp'), + )) + + # Update names within the geometry + for old_name, new_name in name_map.items(): + update_names(old_name, new_name, files_to_update) + + update_local_type_aliases([f for f in hpp_files if not set(f.parts).intersection({'data_types', 'geometry.hpp', 'species_info.hpp'})], cpp_files) + + clang_format = shutil.which('clang-format') + if not clang_format: + clang_format = Path('/data/gyselarunner/clang-format') + if not clang_format.exists(): + print("WARNING : Clang-format not found. Exiting without cleaning indenting") + + for f in chain(hpp_files, cpp_files): + subprocess.run([clang_format, '-i', f]) diff --git a/simulations/geometry5D/testcollisions/testcollisions.cpp b/simulations/geometry5D/testcollisions/testcollisions.cpp index 5a1d5bbd3..211cef6a0 100644 --- a/simulations/geometry5D/testcollisions/testcollisions.cpp +++ b/simulations/geometry5D/testcollisions/testcollisions.cpp @@ -136,32 +136,32 @@ int main(int argc, char** argv) PDI_INOUT, NULL); ddc::init_discrete_space(grid_tor1); - DDomTor1 dom_tor1(IdxTor1(0), DVecTor1(grid_tor1.size())); + IdxRangeTor1 dom_tor1(IdxTor1(0), IdxStepTor1(grid_tor1.size())); ddc::init_discrete_space(grid_tor2); - DDomTor2 dom_tor2(IdxTor2(0), DVecTor2(grid_tor2.size())); + IdxRangeTor2 dom_tor2(IdxTor2(0), IdxStepTor2(grid_tor2.size())); ddc::init_discrete_space(grid_tor3); - DDomTor3 dom_tor3(IdxTor3(0), DVecTor3(grid_tor3.size())); + IdxRangeTor3 dom_tor3(IdxTor3(0), IdxStepTor3(grid_tor3.size())); ddc::init_discrete_space(grid_vpar); - DDomVpar dom_vpar(IdxVpar(0), DVecVpar(grid_vpar.size())); + IdxRangeVpar dom_vpar(IdxVpar(0), IdxStepVpar(grid_vpar.size())); ddc::init_discrete_space(grid_mu); - DDomMu dom_mu(IdxMu(0), DVecMu(grid_mu.size())); + IdxRangeMu dom_mu(IdxMu(0), IdxStepMu(grid_mu.size())); IdxStepSp const kinspecies(charges.size()); IdxRangeSp const dom_kinsp(IdxSp(0), kinspecies); - DFieldTor1 field_grid_tor1(dom_tor1); - ddc::parallel_deepcopy(field_grid_tor1, DViewTor1(grid_tor1.data(), dom_tor1)); + DFieldMemTor1 field_grid_tor1(dom_tor1); + ddc::parallel_deepcopy(field_grid_tor1, DConstFieldTor1(grid_tor1.data(), dom_tor1)); auto field_grid_tor1_host = ddc::create_mirror_view_and_copy(field_grid_tor1.span_view()); - DFieldTor2 field_grid_tor2(dom_tor2); - ddc::parallel_deepcopy(field_grid_tor2, DViewTor2(grid_tor2.data(), dom_tor2)); + DFieldMemTor2 field_grid_tor2(dom_tor2); + ddc::parallel_deepcopy(field_grid_tor2, DConstFieldTor2(grid_tor2.data(), dom_tor2)); auto field_grid_tor2_host = ddc::create_mirror_view_and_copy(field_grid_tor2.span_view()); - DFieldTor3 field_grid_tor3(dom_tor3); - ddc::parallel_deepcopy(field_grid_tor3, DViewTor3(grid_tor3.data(), dom_tor3)); + DFieldMemTor3 field_grid_tor3(dom_tor3); + ddc::parallel_deepcopy(field_grid_tor3, DConstFieldTor3(grid_tor3.data(), dom_tor3)); auto field_grid_tor3_host = ddc::create_mirror_view_and_copy(field_grid_tor3.span_view()); - DFieldVpar field_grid_vpar(dom_vpar); - ddc::parallel_deepcopy(field_grid_vpar, DViewVpar(grid_vpar.data(), dom_vpar)); + DFieldMemVpar field_grid_vpar(dom_vpar); + ddc::parallel_deepcopy(field_grid_vpar, DConstFieldVpar(grid_vpar.data(), dom_vpar)); auto field_grid_vpar_host = ddc::create_mirror_view_and_copy(field_grid_vpar.span_view()); - DFieldMu field_grid_mu(dom_mu); - ddc::parallel_deepcopy(field_grid_mu, DViewMu(grid_mu.data(), dom_mu)); + DFieldMemMu field_grid_mu(dom_mu); + ddc::parallel_deepcopy(field_grid_mu, DConstFieldMu(grid_mu.data(), dom_mu)); auto field_grid_mu_host = ddc::create_mirror_view_and_copy(field_grid_mu.span_view()); FieldMemSp field_species(dom_kinsp); ddc::parallel_deepcopy(field_species, ConstFieldSp(species.data(), dom_kinsp)); @@ -184,7 +184,7 @@ int main(int argc, char** argv) cout << "nbiter = " << nbiter << " nbstep_diag = " << nbstep_diag << endl; // Poloidal cross-section of the 3 moments: density, temperature and Upar - DDomSpTorCS const dom_sp_torCS(dom_kinsp, dom_tor2, dom_tor1); + IdxRangeSpTorCS const dom_sp_torCS(dom_kinsp, dom_tor2, dom_tor1); DFieldSpTorCS_host density_torCS_host(dom_sp_torCS); DFieldSpTorCS_host temperature_torCS_host(dom_sp_torCS); DFieldSpTorCS_host Upar_torCS_host(dom_sp_torCS); @@ -194,7 +194,7 @@ int main(int argc, char** argv) .with("UparTorCS", Upar_torCS_host); // fdistribu - DDomSpTor3DV2D const + IdxRangeSpTor3DV2D const dom_sp_tor3D_v2D(dom_kinsp, dom_tor3, dom_tor2, dom_tor1, dom_vpar, dom_mu); DFieldSpTor3DV2D_host allfdistribu_host(dom_sp_tor3D_v2D); double time_saved; @@ -212,14 +212,14 @@ int main(int argc, char** argv) std::int8_t const collisions_interspecies = true; double const rpeak = 1.; double const q_rpeak = 1.; - DFieldTor1 safety_factor(dom_tor1); + DFieldMemTor1 safety_factor(dom_tor1); ddc::parallel_fill(safety_factor, 1.0); //ATTENTION: Must be changed - DDomTorCS dom_tor1_tor2(dom_tor2, dom_tor1); - DFieldTorCS B_norm(dom_tor1_tor2); + IdxRangeTorCS dom_tor1_tor2(dom_tor2, dom_tor1); + DFieldMemTorCS B_norm(dom_tor1_tor2); ddc::parallel_fill(B_norm, 1.0); - host_t const coeff_intdvpar_host + host_t const coeff_intdvpar_host = simpson_quadrature_coefficients_1d(allfdistribu.domain()); - host_t const coeff_intdmu_host + host_t const coeff_intdmu_host = simpson_quadrature_coefficients_1d(allfdistribu.domain()); auto coeff_intdvpar = ddc::create_mirror_view_and_copy( Kokkos::DefaultExecutionSpace(), @@ -235,7 +235,12 @@ int main(int argc, char** argv) q_rpeak, field_grid_tor1.span_cview(), safety_factor.span_cview()); - CollisionSpVparMu, DDomSpTor3DV2D, GridVpar, GridMu, DViewTorCS> + CollisionSpVparMu< + CollisionInfoRadial, + IdxRangeSpTor3DV2D, + GridVpar, + GridMu, + DConstFieldTorCS> collision_operator( collision_info, dom_sp_tor3D_v2D, diff --git a/src/collisions/CollisionSpVparMu.hpp b/src/collisions/CollisionSpVparMu.hpp index a7931d17f..cd139613d 100644 --- a/src/collisions/CollisionSpVparMu.hpp +++ b/src/collisions/CollisionSpVparMu.hpp @@ -184,7 +184,6 @@ class CollisionSpVparMu /* : public IRightHandSide */ , m_mug {"m_mug", ddc::select(fdistrib_domain)} , m_vparg {"m_vparg", ddc::select(fdistrib_domain)} { - using namespace collisions_dimensions; // Check that the distribution function is correctly ordered koliop_interface::DoCombMatComputation(m_comb_mat); @@ -213,8 +212,9 @@ class CollisionSpVparMu /* : public IRightHandSide */ std::size_t const n_mu = ddc::select(fdistrib_domain).size(); std::size_t const n_vpar = ddc::select(fdistrib_domain).size(); - std::size_t const n_r = get_idx_range(fdistrib_domain).size(); - std::size_t const n_theta = get_idx_range(fdistrib_domain).size(); + std::size_t const n_r = collisions_dimensions::get_idx_range(fdistrib_domain).size(); + std::size_t const n_theta + = collisions_dimensions::get_idx_range(fdistrib_domain).size(); std::size_t const n_sp = ddc::select(fdistrib_domain).size(); std::size_t const n_batch = fdistrib_domain.size() / (n_mu * n_vpar * n_r * n_theta * n_sp); diff --git a/src/data_types/derivative_field_common.hpp b/src/data_types/derivative_field_common.hpp index 9db638b81..5296f6373 100644 --- a/src/data_types/derivative_field_common.hpp +++ b/src/data_types/derivative_field_common.hpp @@ -64,7 +64,7 @@ class DerivFieldCommon> using discrete_domain_type = ddc::DiscreteDomain; /// @brief The DiscreteElement which can be used to index this object. - using discrete_element_type = typename ddc::DiscreteElement; + using discrete_element_type = ddc::DiscreteElement; protected: /// @brief The type of the memory block stored in the array internal_chunks diff --git a/src/geometry5D/geometry/geometry.hpp b/src/geometry5D/geometry/geometry.hpp index 1dee0bc26..52171b96e 100644 --- a/src/geometry5D/geometry/geometry.hpp +++ b/src/geometry5D/geometry/geometry.hpp @@ -1,10 +1,11 @@ #pragma once - #include #include #include +#include "ddc_aliases.hpp" + /* * @file geometry.hpp * @@ -71,138 +72,138 @@ struct Mu static bool constexpr PERIODIC = false; }; -using CoordTor1 = ddc::Coordinate; -using CoordTor2 = ddc::Coordinate; -using CoordTor3 = ddc::Coordinate; -using CoordTor3D = ddc::Coordinate; +using CoordTor1 = Coord; +using CoordTor2 = Coord; +using CoordTor3 = Coord; +using CoordTor3D = Coord; -using CoordVpar = ddc::Coordinate; -using CoordMu = ddc::Coordinate; -using CoordV2D = ddc::Coordinate; +using CoordVpar = Coord; +using CoordMu = Coord; +using CoordV2D = Coord; -struct GridTor1 : ddc::NonUniformPointSampling +struct GridTor1 : NonUniformGridBase { }; -struct GridTor2 : ddc::NonUniformPointSampling +struct GridTor2 : NonUniformGridBase { }; -struct GridTor3 : ddc::NonUniformPointSampling +struct GridTor3 : NonUniformGridBase { }; -struct GridVpar : ddc::NonUniformPointSampling +struct GridVpar : NonUniformGridBase { }; -struct GridMu : ddc::NonUniformPointSampling +struct GridMu : NonUniformGridBase { }; -using IdxTor1 = ddc::DiscreteElement; -using IdxTor2 = ddc::DiscreteElement; -using IdxTor3 = ddc::DiscreteElement; -using IdxVpar = ddc::DiscreteElement; -using IdxMu = ddc::DiscreteElement; +using IdxTor1 = Idx; +using IdxTor2 = Idx; +using IdxTor3 = Idx; +using IdxVpar = Idx; +using IdxMu = Idx; -using DVecTor1 = ddc::DiscreteVector; -using DVecTor2 = ddc::DiscreteVector; -using DVecTor3 = ddc::DiscreteVector; -using DVecVpar = ddc::DiscreteVector; -using DVecMu = ddc::DiscreteVector; +using IdxStepTor1 = IdxStep; +using IdxStepTor2 = IdxStep; +using IdxStepTor3 = IdxStep; +using IdxStepVpar = IdxStep; +using IdxStepMu = IdxStep; -using DDomTor1 = ddc::DiscreteDomain; -using DDomTor2 = ddc::DiscreteDomain; -using DDomTor3 = ddc::DiscreteDomain; -using DDomVpar = ddc::DiscreteDomain; -using DDomMu = ddc::DiscreteDomain; -using DDomTorCS = ddc::DiscreteDomain; -using DDomTor3D = ddc::DiscreteDomain; -using DDomV2D = ddc::DiscreteDomain; -using DDomSpTor3DV2D = ddc::DiscreteDomain; -using DDomSpTorCS = ddc::DiscreteDomain; +using IdxRangeTor1 = IdxRange; +using IdxRangeTor2 = IdxRange; +using IdxRangeTor3 = IdxRange; +using IdxRangeVpar = IdxRange; +using IdxRangeMu = IdxRange; +using IdxRangeTorCS = IdxRange; +using IdxRangeTor3D = IdxRange; +using IdxRangeV2D = IdxRange; +using IdxRangeSpTor3DV2D = IdxRange; +using IdxRangeSpTorCS = IdxRange; template -using FieldTor1 = device_t>; -using DFieldTor1 = FieldTor1; +using FieldMemTor1 = FieldMem; +using DFieldMemTor1 = FieldMemTor1; template -using FieldTor2 = device_t>; -using DFieldTor2 = FieldTor2; +using FieldMemTor2 = FieldMem; +using DFieldMemTor2 = FieldMemTor2; template -using FieldTor3 = device_t>; -using DFieldTor3 = FieldTor3; +using FieldMemTor3 = FieldMem; +using DFieldMemTor3 = FieldMemTor3; template -using FieldVpar = device_t>; -using DFieldVpar = FieldVpar; +using FieldMemVpar = FieldMem; +using DFieldMemVpar = FieldMemVpar; template -using FieldMu = device_t>; -using DFieldMu = FieldMu; +using FieldMemMu = FieldMem; +using DFieldMemMu = FieldMemMu; template -using FieldTorCS = device_t>; -using DFieldTorCS = FieldTorCS; +using FieldMemTorCS = FieldMem; +using DFieldMemTorCS = FieldMemTorCS; template -using FieldTor3D = device_t>; -using DFieldTor3D = FieldTor3D; +using FieldMemTor3D = FieldMem; +using DFieldMemTor3D = FieldMemTor3D; template -using FieldSpTor3DV2D_host = host_t>; +using FieldSpTor3DV2D_host = host_t>; using DFieldSpTor3DV2D_host = FieldSpTor3DV2D_host; template -using FieldSpTor3DV2D = device_t>; -using DFieldSpTor3DV2D = FieldSpTor3DV2D; +using FieldMemSpTor3DV2D = FieldMem; +using DFieldMemSpTor3DV2D = FieldMemSpTor3DV2D; template -using FieldSpTorCS_host = host_t>; +using FieldSpTorCS_host = host_t>; using DFieldSpTorCS_host = FieldSpTorCS_host; template -using FieldSpTorCS = device_t>; -using DFieldSpTorCS = FieldSpTorCS; +using FieldMemSpTorCS = FieldMem; +using DFieldMemSpTorCS = FieldMemSpTorCS; template -using SpanTorCS = device_t>; -using DSpanTorCS = SpanTorCS; +using FieldTorCS = Field; +using DFieldTorCS = FieldTorCS; template -using SpanTor3D = device_t>; -using DSpanTor3D = SpanTor3D; +using FieldTor3D = Field; +using DFieldTor3D = FieldTor3D; template -using SpanSpTor3DV2D = device_t>; -using DSpanSpTor3DV2D = SpanSpTor3DV2D; +using FieldSpTor3DV2D = Field; +using DFieldSpTor3DV2D = FieldSpTor3DV2D; template -using ViewTor1 = device_t>; -using DViewTor1 = ViewTor1; +using ConstFieldTor1 = ConstField; +using DConstFieldTor1 = ConstFieldTor1; template -using ViewTor2 = device_t>; -using DViewTor2 = ViewTor2; +using ConstFieldTor2 = ConstField; +using DConstFieldTor2 = ConstFieldTor2; template -using ViewTor3 = device_t>; -using DViewTor3 = ViewTor3; +using ConstFieldTor3 = ConstField; +using DConstFieldTor3 = ConstFieldTor3; template -using ViewVpar = device_t>; -using DViewVpar = ViewVpar; +using ConstFieldVpar = ConstField; +using DConstFieldVpar = ConstFieldVpar; template -using ViewMu = device_t>; -using DViewMu = ViewMu; +using ConstFieldMu = ConstField; +using DConstFieldMu = ConstFieldMu; template -using ViewTorCS = device_t>; -using DViewTorCS = ViewTorCS; +using ConstFieldTorCS = ConstField; +using DConstFieldTorCS = ConstFieldTorCS; template -using ViewTor3D = device_t>; -using DViewTor3D = ViewTor3D; +using ConstFieldTor3D = ConstField; +using DConstFieldTor3D = ConstFieldTor3D; template -using ViewSpTor3DV2D = device_t>; -using DViewSpTor3DV2D = ViewSpTor3DV2D; +using ConstFieldSpTor3DV2D = ConstField; +using DConstFieldSpTor3DV2D = ConstFieldSpTor3DV2D; diff --git a/src/utils/ddc_aliases.hpp b/src/utils/ddc_aliases.hpp new file mode 100644 index 000000000..d124135c9 --- /dev/null +++ b/src/utils/ddc_aliases.hpp @@ -0,0 +1,140 @@ +#pragma once + +#include + +/** + * This file contains aliases for DDC. The documentation for DDC can be found at . + * The names used in the DDC project are not always intuitive for mathematicians/physicists therefore + * Gysela has chosen to introduce this file to provide names that are hopefully more intuitive. + * The documentation for these concepts can be found in the Gysela documentation at: + * + */ + +/// An alias describing the type of a coordinate (e.g. a coordinate in phase-space (x, vx)). +template +using Coord = ddc::Coordinate; + +/// An alias describing the type of an index that is used to access the values of a field defined on a grid. +template +using Idx = ddc::DiscreteElement; + +/// An alias describing the type of a distance between two indexes. +template +using IdxStep = ddc::DiscreteVector; + +/// An alias describing the type of an index range describing the subsection of a grid on which a field is defined. +template +using IdxRange = ddc::DiscreteDomain; + +/// An alias describing the type of an object which will allocate memory for a field when it is created. +template < + class ElementType, + class IdxRange, + class Allocator + = ddc::KokkosAllocator> +using FieldMem = ddc::Chunk; + +/// An alias describing the type of an object which will allocate memory for a field of doubles when it is created. +template < + class IdxRange, + class Allocator = ddc::KokkosAllocator> +using DFieldMem = FieldMem; + +/// An alias describing the type of a field defined on a grid (e.g. the electric field defined on the grid @f${x_0, x_1, .., x_N}@f$) +template < + class ElementType, + class IdxRange, + class LayoutStridedPolicy = std::experimental::layout_right, + class MemorySpace = Kokkos::DefaultExecutionSpace::memory_space> +using Field = ddc::ChunkSpan; + +/// An alias describing the type of a field of doubles defined on a grid (e.g. the electric field defined on the grid @f${x_0, x_1, .., x_N}@f$) +template < + class IdxRange, + class LayoutStridedPolicy = std::experimental::layout_right, + class MemorySpace = Kokkos::DefaultExecutionSpace::memory_space> +using DField = Field; + +/// An alias describing the type of a constant field defined on a grid (e.g. the electric field defined on the grid @f${x_0, x_1, .., x_N}@f$) +template < + class ElementType, + class IdxRange, + class LayoutStridedPolicy = std::experimental::layout_right, + class MemorySpace = Kokkos::DefaultExecutionSpace::memory_space> +using ConstField = ddc::ChunkView; + +/// An alias describing the type of a constant field of doubles defined on a grid (e.g. the electric field defined on the grid @f${x_0, x_1, .., x_N}@f$) +template < + class IdxRange, + class LayoutStridedPolicy = std::experimental::layout_right, + class MemorySpace = Kokkos::DefaultExecutionSpace::memory_space> +using DConstField = ConstField; + +/// An alias describing the type from which a uniform grid must inherit. +template +using UniformGridBase = ddc::UniformPointSampling; + +/// An alias describing the type from which a non-uniform grid must inherit. +template +using NonUniformGridBase = ddc::NonUniformPointSampling; + +/** + * A function to get the range of valid indices that can be used to index this field. + * + * @param[in] field The field whose indices are of interest. + * + * @returns The index range. + */ +template +KOKKOS_INLINE_FUNCTION auto get_idx_range(FieldType const& field) noexcept +{ + static_assert(ddc::is_chunk_v, "Not a DDC field (ddc::ChunkSpan) type"); + if constexpr (sizeof...(QueryGrids) == 0) { + return field.domain(); + } else { + return field.template domain(); + } +} + +/** + * A function to get the range of valid indices that can be used to index a set of b-splines that are compatible with this spline builder. + * + * @param[in] builder The spline builder. + * + * @returns The index range. + */ +template +KOKKOS_INLINE_FUNCTION auto get_spline_idx_range(SplineBuilder const& builder) noexcept +{ + return builder.spline_domain(); +} + +/** + * A helper function to get a modifiable field from a FieldMem without allocating additional memory. + * + * @param[in] field The field memory object. + * @returns The modifiable field. + */ +template +inline auto get_field(FieldType& field) +{ + static_assert( + ddc::is_chunk_v, + "Not a Field or FieldMem (ddc::Chunk or ddc::ChunkSpan) type"); + return field.span_view(); +} + +/** + * A helper function to get a constant field from a FieldMem without allocating additional memory. + * + * @param[in] field The field memory object. + * @returns The constant field. + */ +template +inline auto get_const_field(FieldType const& field) +{ + static_assert( + ddc::is_chunk_v, + "Not a Field or FieldMem (ddc::Chunk or ddc::ChunkSpan) type"); + return field.span_cview(); +}