From 6cc47f39816b7dc6070667fa7d2a6187ecaf6eba Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Tue, 14 Apr 2026 05:27:28 +0700 Subject: [PATCH 1/5] redesign and track numba_types. black-skip scripts generated by code_factory --- mcdc/.gitignore | 1 - mcdc/code_factory/numba_objects_generator.py | 105 ++- .../neutron_inelastic_scattering_reaction.py | 12 +- mcdc/mcdc_set/electron_ionization_reaction.py | 4 +- mcdc/mcdc_set/element.py | 4 +- .../neutron_inelastic_scattering_reaction.py | 24 +- mcdc/mcdc_set/nuclide.py | 4 +- .../tabulated_energy_angle_distribution.py | 4 +- mcdc/numba_types.py | 864 ++++++++++++++++++ mcdc/object_/util.py | 4 + pyproject.toml | 9 + 11 files changed, 968 insertions(+), 67 deletions(-) delete mode 100644 mcdc/.gitignore create mode 100644 mcdc/numba_types.py diff --git a/mcdc/.gitignore b/mcdc/.gitignore deleted file mode 100644 index 765e2d89..00000000 --- a/mcdc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -numba_types.py diff --git a/mcdc/code_factory/numba_objects_generator.py b/mcdc/code_factory/numba_objects_generator.py index 25653afb..4d6a5794 100644 --- a/mcdc/code_factory/numba_objects_generator.py +++ b/mcdc/code_factory/numba_objects_generator.py @@ -323,42 +323,76 @@ def generate_numba_objects(simulation): ) for label in structures.keys(): + # Skip special types + if label in ["gpu_meta"] + bank_names + ["simulation"]: + continue + text += f"{label} = into_dtype([\n" structure = structures[label] - # GPU meta override - if label == "gpu_meta": - for item in structure: - if type(item[1]) != np.dtypes.VoidDType: - if isinstance(item[1], str): - dtype = f"'{item[1]}'" - elif item[1].__name__ == "uint64": - dtype = "uintp" - else: - dtype = item[1].__name__ - text += f" ('{item[0]}', {dtype}),\n" - text += "])\n\n" - continue + for item in structure: + text += decode_structure_item(item) + text += "])\n\n" + + # GPU meta + text += "gpu_meta = into_dtype([\n" + for item in structures["gpu_meta"]: + if item[0].endswith("pointer"): + text += f" ('{item[0]}', uintp),\n" + else: + text += decode_structure_item(item) + text += "])\n\n" + + # Particle banks + for label in bank_names: + structure = structures[label] + text += f"{label} = None\n" + text += f"def set_{label}(N: dict):\n" + text += f" global {label}\n" + text += f" {label} = into_dtype([\n" for item in structure: - if type(item[1]) != np.dtypes.VoidDType: - if isinstance(item[1], str): - dtype = f"'{item[1]}'" - else: - dtype = item[1].__name__ - if len(item) == 3: - text += f" ('{item[0]}', {dtype}, {item[2]}),\n" - else: - text += f" ('{item[0]}', {dtype}),\n" + if item[0] == "particle_data": + text += f" ('{item[0]}', {item[0]}, (N['{item[0]}'],)),\n" else: - if len(item) == 3: - text += f" ('{item[0]}', {plural_to_singular(item[0])}, {item[2]}),\n" - else: - text += f" ('{item[0]}', {item[0]}),\n" - text += "])\n\n" + text += decode_structure_item(item, " ") + text += " ])\n\n" + + # Simulation + text += f"simulation = None\n" + text += f"def set_simulation(N: dict):\n" + text += f" global simulation\n" + text += f" simulation = into_dtype([\n" + for item in structures['simulation']: + if type(item[1]) == np.dtypes.VoidDType and len(item) == 3: + singular_field = plural_to_singular(item[0]) + text += f" ('{item[0]}', {singular_field}, (N['{singular_field}'])),\n" + else: + text += decode_structure_item(item, " ") + text += " ])\n\n" f.write(text) + # ================================================================================== + # Set numba_types.py + # ================================================================================== + + import mcdc.numba_types as type_ + + # Particle banks + type_.set_bank_active({'particle_data': simulation.bank_active.size[0]}) + type_.set_bank_census({'particle_data': simulation.bank_census.size[0]}) + type_.set_bank_source({'particle_data': simulation.bank_source.size[0]}) + type_.set_bank_future({'particle_data': simulation.bank_future.size[0]}) + + # Simulation + N = {} + for item in structures['simulation']: + if type(item[1]) == np.dtypes.VoidDType and len(item) == 3: + singular_field = plural_to_singular(item[0]) + N[singular_field] = item[2] + type_.set_simulation(N) + # ================================================================================== # GPU preparation: Adapt transport functions, forward declare, and build program # ================================================================================== @@ -1206,3 +1240,20 @@ def singular_to_plural(word: str) -> str: parts[-1] = w + "s" return "_".join(parts) + + +def decode_structure_item(item, prefix=""): + if type(item[1]) != np.dtypes.VoidDType: + if isinstance(item[1], str): + dtype = f"'{item[1]}'" + else: + dtype = item[1].__name__ + if len(item) == 3: + return f"{prefix} ('{item[0]}', {dtype}, {item[2]}),\n" + else: + return f"{prefix} ('{item[0]}', {dtype}),\n" + else: + if len(item) == 3: + return f"{prefix} ('{item[0]}', {plural_to_singular(item[0])}, {item[2]}),\n" + else: + return f"{prefix} ('{item[0]}', {item[0]}),\n" diff --git a/mcdc/mcdc_get/neutron_inelastic_scattering_reaction.py b/mcdc/mcdc_get/neutron_inelastic_scattering_reaction.py index 1677db2b..5cf2f0dd 100644 --- a/mcdc/mcdc_get/neutron_inelastic_scattering_reaction.py +++ b/mcdc/mcdc_get/neutron_inelastic_scattering_reaction.py @@ -26,9 +26,7 @@ def spectrum_probability_grid_last(neutron_inelastic_scattering_reaction, data): @njit -def spectrum_probability_grid_chunk( - start, length, neutron_inelastic_scattering_reaction, data -): +def spectrum_probability_grid_chunk(start, length, neutron_inelastic_scattering_reaction, data): start += neutron_inelastic_scattering_reaction["spectrum_probability_grid_offset"] end = start + length return data[start:end] @@ -51,9 +49,7 @@ def spectrum_probability(index_1, index_2, neutron_inelastic_scattering_reaction @njit -def spectrum_probability_chunk( - start, length, neutron_inelastic_scattering_reaction, data -): +def spectrum_probability_chunk(start, length, neutron_inelastic_scattering_reaction, data): start += neutron_inelastic_scattering_reaction["spectrum_probability_offset"] end = start + length return data[start:end] @@ -82,9 +78,7 @@ def energy_spectrum_IDs_last(neutron_inelastic_scattering_reaction, data): @njit -def energy_spectrum_IDs_chunk( - start, length, neutron_inelastic_scattering_reaction, data -): +def energy_spectrum_IDs_chunk(start, length, neutron_inelastic_scattering_reaction, data): start += neutron_inelastic_scattering_reaction["energy_spectrum_IDs_offset"] end = start + length return data[start:end] diff --git a/mcdc/mcdc_set/electron_ionization_reaction.py b/mcdc/mcdc_set/electron_ionization_reaction.py index e818a401..0d281038 100644 --- a/mcdc/mcdc_set/electron_ionization_reaction.py +++ b/mcdc/mcdc_set/electron_ionization_reaction.py @@ -55,9 +55,7 @@ def subshell_product_IDs_last(electron_ionization_reaction, data, value): @njit -def subshell_product_IDs_chunk( - start, length, electron_ionization_reaction, data, value -): +def subshell_product_IDs_chunk(start, length, electron_ionization_reaction, data, value): start += electron_ionization_reaction["subshell_product_IDs_offset"] end = start + length data[start:end] = value diff --git a/mcdc/mcdc_set/element.py b/mcdc/mcdc_set/element.py index db63fcb8..6f696cc5 100644 --- a/mcdc/mcdc_set/element.py +++ b/mcdc/mcdc_set/element.py @@ -316,9 +316,7 @@ def electron_ionization_subshell_binding_energy_last(element, data, value): @njit -def electron_ionization_subshell_binding_energy_chunk( - start, length, element, data, value -): +def electron_ionization_subshell_binding_energy_chunk(start, length, element, data, value): start += element["electron_ionization_subshell_binding_energy_offset"] end = start + length data[start:end] = value diff --git a/mcdc/mcdc_set/neutron_inelastic_scattering_reaction.py b/mcdc/mcdc_set/neutron_inelastic_scattering_reaction.py index 65509585..81468be2 100644 --- a/mcdc/mcdc_set/neutron_inelastic_scattering_reaction.py +++ b/mcdc/mcdc_set/neutron_inelastic_scattering_reaction.py @@ -4,9 +4,7 @@ @njit -def spectrum_probability_grid( - index, neutron_inelastic_scattering_reaction, data, value -): +def spectrum_probability_grid(index, neutron_inelastic_scattering_reaction, data, value): offset = neutron_inelastic_scattering_reaction["spectrum_probability_grid_offset"] data[offset + index] = value @@ -28,18 +26,14 @@ def spectrum_probability_grid_last(neutron_inelastic_scattering_reaction, data, @njit -def spectrum_probability_grid_chunk( - start, length, neutron_inelastic_scattering_reaction, data, value -): +def spectrum_probability_grid_chunk(start, length, neutron_inelastic_scattering_reaction, data, value): start += neutron_inelastic_scattering_reaction["spectrum_probability_grid_offset"] end = start + length data[start:end] = value @njit -def spectrum_probability_vector( - index_1, neutron_inelastic_scattering_reaction, data, value -): +def spectrum_probability_vector(index_1, neutron_inelastic_scattering_reaction, data, value): offset = neutron_inelastic_scattering_reaction["spectrum_probability_offset"] stride = neutron_inelastic_scattering_reaction["N_spectrum"] start = offset + index_1 * stride @@ -48,18 +42,14 @@ def spectrum_probability_vector( @njit -def spectrum_probability( - index_1, index_2, neutron_inelastic_scattering_reaction, data, value -): +def spectrum_probability(index_1, index_2, neutron_inelastic_scattering_reaction, data, value): offset = neutron_inelastic_scattering_reaction["spectrum_probability_offset"] stride = neutron_inelastic_scattering_reaction["N_spectrum"] data[offset + index_1 * stride + index_2] = value @njit -def spectrum_probability_chunk( - start, length, neutron_inelastic_scattering_reaction, data, value -): +def spectrum_probability_chunk(start, length, neutron_inelastic_scattering_reaction, data, value): start += neutron_inelastic_scattering_reaction["spectrum_probability_offset"] end = start + length data[start:end] = value @@ -88,9 +78,7 @@ def energy_spectrum_IDs_last(neutron_inelastic_scattering_reaction, data, value) @njit -def energy_spectrum_IDs_chunk( - start, length, neutron_inelastic_scattering_reaction, data, value -): +def energy_spectrum_IDs_chunk(start, length, neutron_inelastic_scattering_reaction, data, value): start += neutron_inelastic_scattering_reaction["energy_spectrum_IDs_offset"] end = start + length data[start:end] = value diff --git a/mcdc/mcdc_set/nuclide.py b/mcdc/mcdc_set/nuclide.py index 7ec4beb2..257d6258 100644 --- a/mcdc/mcdc_set/nuclide.py +++ b/mcdc/mcdc_set/nuclide.py @@ -258,9 +258,7 @@ def neutron_inelastic_scattering_reaction_IDs_last(nuclide, data, value): @njit -def neutron_inelastic_scattering_reaction_IDs_chunk( - start, length, nuclide, data, value -): +def neutron_inelastic_scattering_reaction_IDs_chunk(start, length, nuclide, data, value): start += nuclide["neutron_inelastic_scattering_reaction_IDs_offset"] end = start + length data[start:end] = value diff --git a/mcdc/mcdc_set/tabulated_energy_angle_distribution.py b/mcdc/mcdc_set/tabulated_energy_angle_distribution.py index 97040280..e25747d1 100644 --- a/mcdc/mcdc_set/tabulated_energy_angle_distribution.py +++ b/mcdc/mcdc_set/tabulated_energy_angle_distribution.py @@ -171,9 +171,7 @@ def cosine_offset__last(tabulated_energy_angle_distribution, data, value): @njit -def cosine_offset__chunk( - start, length, tabulated_energy_angle_distribution, data, value -): +def cosine_offset__chunk(start, length, tabulated_energy_angle_distribution, data, value): start += tabulated_energy_angle_distribution["cosine_offset__offset"] end = start + length data[start:end] = value diff --git a/mcdc/numba_types.py b/mcdc/numba_types.py new file mode 100644 index 00000000..8ca7ba4f --- /dev/null +++ b/mcdc/numba_types.py @@ -0,0 +1,864 @@ +# The following is automatically generated by code_factory.py + +from numpy import bool_ +from numpy import float64 +from numpy import int64 +from numpy import uint64 +from numpy import uintp + +### + +from mcdc.code_factory.numba_objects_generator import into_dtype + +particle_data = into_dtype([ + ('x', float64), + ('y', float64), + ('z', float64), + ('t', float64), + ('ux', float64), + ('uy', float64), + ('uz', float64), + ('g', int64), + ('E', float64), + ('w', float64), + ('particle_type', int64), + ('rng_seed', uint64), +]) + +particle = into_dtype([ + ('cell_ID', int64), + ('material_ID', int64), + ('surface_ID', int64), + ('alive', bool), + ('fresh', bool), + ('event', int64), + ('x', float64), + ('y', float64), + ('z', float64), + ('t', float64), + ('ux', float64), + ('uy', float64), + ('uz', float64), + ('g', int64), + ('E', float64), + ('w', float64), + ('particle_type', int64), + ('rng_seed', uint64), +]) + +cell = into_dtype([ + ('name', 'U32'), + ('fill_translated', bool), + ('fill_rotated', bool), + ('translation', float64, (3,)), + ('rotation', float64, (3,)), + ('region_RPN_tokens_offset', int64), + ('region_RPN_tokens_length', int64), + ('N_surface', int64), + ('surface_IDs_offset', int64), + ('N_tally', int64), + ('tally_IDs_offset', int64), + ('fill_type', int64), + ('fill_ID', int64), + ('ID', int64), +]) + +lattice = into_dtype([ + ('name', 'U32'), + ('x0', float64), + ('dx', float64), + ('Nx', int64), + ('y0', float64), + ('dy', float64), + ('Ny', int64), + ('z0', float64), + ('dz', float64), + ('Nz', int64), + ('universe_IDs_offset', int64), + ('universe_IDs_length', int64), + ('ID', int64), +]) + +material = into_dtype([ + ('name', 'U32'), + ('fissionable', bool), + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +tally = into_dtype([ + ('name', 'U32'), + ('scores_offset', int64), + ('scores_length', int64), + ('filter_direction', bool), + ('filter_energy', bool), + ('filter_time', bool), + ('mu_offset', int64), + ('mu_length', int64), + ('azi_offset', int64), + ('azi_length', int64), + ('polar_reference', float64, (3,)), + ('energy_offset', int64), + ('energy_length', int64), + ('time_offset', int64), + ('time_length', int64), + ('bin_offset', int64), + ('bin_length', int64), + ('bin_sum_offset', int64), + ('bin_sum_length', int64), + ('bin_sum_square_offset', int64), + ('bin_sum_square_length', int64), + ('bin_shape_offset', int64), + ('bin_shape_length', int64), + ('stride_mu', int64), + ('stride_azi', int64), + ('stride_energy', int64), + ('stride_time', int64), + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +universe = into_dtype([ + ('name', 'U32'), + ('N_cell', int64), + ('cell_IDs_offset', int64), + ('ID', int64), +]) + +data = into_dtype([ + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +none_data = into_dtype([ + ('ID', int64), + ('parent_ID', int64), +]) + +polynomial_data = into_dtype([ + ('coefficients_offset', int64), + ('coefficients_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +table_data = into_dtype([ + ('x_offset', int64), + ('x_length', int64), + ('y_offset', int64), + ('y_length', int64), + ('interpolation', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +distribution = into_dtype([ + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +evaporation_distribution = into_dtype([ + ('nuclear_temperature_ID', int64), + ('restriction_energy', float64), + ('ID', int64), + ('parent_ID', int64), +]) + +kalbach_mann_distribution = into_dtype([ + ('energy_offset', int64), + ('energy_length', int64), + ('offset_offset', int64), + ('offset_length', int64), + ('energy_out_offset', int64), + ('energy_out_length', int64), + ('pdf_offset', int64), + ('pdf_length', int64), + ('cdf_offset', int64), + ('cdf_length', int64), + ('precompound_factor_offset', int64), + ('precompound_factor_length', int64), + ('angular_slope_offset', int64), + ('angular_slope_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +level_scattering_distribution = into_dtype([ + ('C1', float64), + ('C2', float64), + ('ID', int64), + ('parent_ID', int64), +]) + +maxwellian_distribution = into_dtype([ + ('nuclear_temperature_ID', int64), + ('restriction_energy', float64), + ('ID', int64), + ('parent_ID', int64), +]) + +multi_table_distribution = into_dtype([ + ('grid_offset', int64), + ('grid_length', int64), + ('offset_offset', int64), + ('offset_length', int64), + ('value_offset', int64), + ('value_length', int64), + ('pdf_offset', int64), + ('pdf_length', int64), + ('cdf_offset', int64), + ('cdf_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +nbody_distribution = into_dtype([ + ('value_offset', int64), + ('value_length', int64), + ('pdf_offset', int64), + ('pdf_length', int64), + ('cdf_offset', int64), + ('cdf_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +none_distribution = into_dtype([ + ('ID', int64), + ('parent_ID', int64), +]) + +pmf_distribution = into_dtype([ + ('value_offset', int64), + ('value_length', int64), + ('pmf_offset', int64), + ('pmf_length', int64), + ('cmf_offset', int64), + ('cmf_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +tabulated_distribution = into_dtype([ + ('value_offset', int64), + ('value_length', int64), + ('pdf_offset', int64), + ('pdf_length', int64), + ('cdf_offset', int64), + ('cdf_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +tabulated_energy_angle_distribution = into_dtype([ + ('energy_offset', int64), + ('energy_length', int64), + ('offset_offset', int64), + ('offset_length', int64), + ('energy_out_offset', int64), + ('energy_out_length', int64), + ('pdf_offset', int64), + ('pdf_length', int64), + ('cdf_offset', int64), + ('cdf_length', int64), + ('cosine_offset__offset', int64), + ('cosine_offset__length', int64), + ('cosine_offset', int64), + ('cosine_length', int64), + ('cosine_pdf_offset', int64), + ('cosine_pdf_length', int64), + ('cosine_cdf_offset', int64), + ('cosine_cdf_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +electron_reaction = into_dtype([ + ('MT', int64), + ('xs_offset', int64), + ('xs_length', int64), + ('xs_offset_', int64), + ('reference_frame', int64), + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +electron_bremsstrahlung_reaction = into_dtype([ + ('eloss_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +electron_elastic_scattering_reaction = into_dtype([ + ('mu_cut', float64), + ('xs_large_ID', int64), + ('mu_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +electron_excitation_reaction = into_dtype([ + ('eloss_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +electron_ionization_reaction = into_dtype([ + ('N_subshell', int64), + ('N_subshell_x', int64), + ('subshell_x_IDs_offset', int64), + ('N_subshell_product', int64), + ('subshell_product_IDs_offset', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +element = into_dtype([ + ('name', 'U32'), + ('atomic_weight_ratio', float64), + ('atomic_number', int64), + ('electron_xs_energy_grid_offset', int64), + ('electron_xs_energy_grid_length', int64), + ('electron_total_xs_offset', int64), + ('electron_total_xs_length', int64), + ('electron_ionization_xs_offset', int64), + ('electron_ionization_xs_length', int64), + ('electron_elastic_xs_offset', int64), + ('electron_elastic_xs_length', int64), + ('electron_excitation_xs_offset', int64), + ('electron_excitation_xs_length', int64), + ('electron_bremsstrahlung_xs_offset', int64), + ('electron_bremsstrahlung_xs_length', int64), + ('N_electron_ionization_reaction', int64), + ('electron_ionization_reaction_IDs_offset', int64), + ('N_electron_elastic_scattering_reaction', int64), + ('electron_elastic_scattering_reaction_IDs_offset', int64), + ('N_electron_excitation_reaction', int64), + ('electron_excitation_reaction_IDs_offset', int64), + ('N_electron_bremsstrahlung_reaction', int64), + ('electron_bremsstrahlung_reaction_IDs_offset', int64), + ('electron_ionization_subshell_binding_energy_offset', int64), + ('electron_ionization_subshell_binding_energy_length', int64), + ('ID', int64), +]) + +native_material = into_dtype([ + ('N_nuclide', int64), + ('nuclide_IDs_offset', int64), + ('N_element', int64), + ('element_IDs_offset', int64), + ('nuclide_densities_offset', int64), + ('nuclide_densities_length', int64), + ('element_densities_offset', int64), + ('element_densities_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +multigroup_material = into_dtype([ + ('G', int64), + ('J', int64), + ('mgxs_speed_offset', int64), + ('mgxs_speed_length', int64), + ('mgxs_decay_rate_offset', int64), + ('mgxs_decay_rate_length', int64), + ('mgxs_capture_offset', int64), + ('mgxs_capture_length', int64), + ('mgxs_scatter_offset', int64), + ('mgxs_scatter_length', int64), + ('mgxs_fission_offset', int64), + ('mgxs_fission_length', int64), + ('mgxs_total_offset', int64), + ('mgxs_total_length', int64), + ('mgxs_nu_s_offset', int64), + ('mgxs_nu_s_length', int64), + ('mgxs_nu_p_offset', int64), + ('mgxs_nu_p_length', int64), + ('mgxs_nu_d_offset', int64), + ('mgxs_nu_d_length', int64), + ('mgxs_nu_d_total_offset', int64), + ('mgxs_nu_d_total_length', int64), + ('mgxs_nu_f_offset', int64), + ('mgxs_nu_f_length', int64), + ('mgxs_chi_s_offset', int64), + ('mgxs_chi_s_length', int64), + ('mgxs_chi_p_offset', int64), + ('mgxs_chi_p_length', int64), + ('mgxs_chi_d_offset', int64), + ('mgxs_chi_d_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +nuclide = into_dtype([ + ('name', 'U32'), + ('temperature', float64), + ('atomic_number', int64), + ('atomic_weight_ratio', float64), + ('fissionable', bool), + ('excitation_level', int64), + ('neutron_xs_energy_grid_offset', int64), + ('neutron_xs_energy_grid_length', int64), + ('neutron_total_xs_offset', int64), + ('neutron_total_xs_length', int64), + ('neutron_elastic_xs_offset', int64), + ('neutron_elastic_xs_length', int64), + ('neutron_capture_xs_offset', int64), + ('neutron_capture_xs_length', int64), + ('neutron_inelastic_xs_offset', int64), + ('neutron_inelastic_xs_length', int64), + ('neutron_fission_xs_offset', int64), + ('neutron_fission_xs_length', int64), + ('N_neutron_elastic_scattering_reaction', int64), + ('neutron_elastic_scattering_reaction_IDs_offset', int64), + ('N_neutron_capture_reaction', int64), + ('neutron_capture_reaction_IDs_offset', int64), + ('N_neutron_inelastic_scattering_reaction', int64), + ('neutron_inelastic_scattering_reaction_IDs_offset', int64), + ('N_neutron_fission_reaction', int64), + ('neutron_fission_reaction_IDs_offset', int64), + ('neutron_fission_prompt_multiplicity_ID', int64), + ('neutron_fission_delayed_multiplicity_ID', int64), + ('N_neutron_fission_delayed_precursor', int64), + ('neutron_fission_delayed_fractions_offset', int64), + ('neutron_fission_delayed_fractions_length', int64), + ('neutron_fission_delayed_decay_rates_offset', int64), + ('neutron_fission_delayed_decay_rates_length', int64), + ('N_neutron_fission_delayed_spectrum', int64), + ('neutron_fission_delayed_spectrum_IDs_offset', int64), + ('ID', int64), +]) + +mesh = into_dtype([ + ('name', 'U32'), + ('N_bin', int64), + ('Nx', int64), + ('Ny', int64), + ('Nz', int64), + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +structured_mesh = into_dtype([ + ('x_offset', int64), + ('x_length', int64), + ('y_offset', int64), + ('y_length', int64), + ('z_offset', int64), + ('z_length', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +uniform_mesh = into_dtype([ + ('x0', float64), + ('dx', float64), + ('Nx', int64), + ('y0', float64), + ('dy', float64), + ('Ny', int64), + ('z0', float64), + ('dz', float64), + ('Nz', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +neutron_reaction = into_dtype([ + ('MT', int64), + ('xs_offset', int64), + ('xs_length', int64), + ('xs_offset_', int64), + ('reference_frame', int64), + ('q_value', float64), + ('ID', int64), + ('child_type', int64), + ('child_ID', int64), +]) + +neutron_capture_reaction = into_dtype([ + ('ID', int64), + ('parent_ID', int64), +]) + +neutron_elastic_scattering_reaction = into_dtype([ + ('mu_table_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +neutron_fission_reaction = into_dtype([ + ('angle_type', int64), + ('mu_ID', int64), + ('spectrum_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +neutron_inelastic_scattering_reaction = into_dtype([ + ('multiplicity', int64), + ('angle_type', int64), + ('mu_ID', int64), + ('N_spectrum_probability_bin', int64), + ('N_spectrum', int64), + ('spectrum_probability_grid_offset', int64), + ('spectrum_probability_grid_length', int64), + ('spectrum_probability_offset', int64), + ('spectrum_probability_length', int64), + ('N_energy_spectrum', int64), + ('energy_spectrum_IDs_offset', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +collision_data = into_dtype([ + ('energy_deposition', float64), +]) + +particle_bank = into_dtype([ + ('size', int64, (1,)), + ('tag', 'U32'), +]) + +settings = into_dtype([ + ('N_particle', int64), + ('N_batch', int64), + ('rng_seed', int64), + ('N_inactive', int64), + ('N_active', int64), + ('N_cycle', int64), + ('k_init', float64), + ('use_gyration_radius', bool), + ('gyration_radius_type', int64), + ('use_source_file', bool), + ('source_file_name', 'U32'), + ('time_boundary', float64), + ('output_name', 'U32'), + ('use_progress_bar', bool), + ('N_census', int64), + ('census_time_offset', int64), + ('census_time_length', int64), + ('use_census_based_tally', bool), + ('census_tally_frequency', int64), + ('save_particle', bool), + ('active_bank_buffer', int64), + ('census_bank_buffer_ratio', float64), + ('source_bank_buffer_ratio', float64), + ('future_bank_buffer_ratio', float64), + ('neutron_transport', bool), + ('electron_transport', bool), + ('proton_transport', bool), + ('neutron_multigroup_mode', bool), + ('neutron_eigenvalue_mode', bool), + ('gpu_strategy', int64), + ('gpu_async_type', int64), + ('gpu_storage', int64), +]) + +implicit_capture = into_dtype([ + ('active', bool), +]) + +population_control = into_dtype([ + ('active', bool), +]) + +weight_roulette = into_dtype([ + ('weight_threshold', float64), + ('weight_target', float64), +]) + +weighted_emission = into_dtype([ + ('active', bool), + ('weight_target', float64), +]) + +source = into_dtype([ + ('name', 'U32'), + ('point_source', bool), + ('point', float64, (3,)), + ('x', float64, (2,)), + ('y', float64, (2,)), + ('z', float64, (2,)), + ('isotropic_direction', bool), + ('mono_direction', bool), + ('white_direction', bool), + ('direction', float64, (3,)), + ('polar_cosine', float64, (2,)), + ('azimuthal', float64, (2,)), + ('mono_energetic', bool), + ('energy_group', int64), + ('energy', float64), + ('energy_group_pmf_ID', int64), + ('energy_pdf_ID', int64), + ('discrete_time', bool), + ('time', float64), + ('time_range', float64, (2,)), + ('particle_type', int64), + ('probability', float64), + ('moving', bool), + ('N_move', int64), + ('N_move_grid', int64), + ('move_velocities_offset', int64), + ('move_velocities_length', int64), + ('move_durations_offset', int64), + ('move_durations_length', int64), + ('move_time_grid_offset', int64), + ('move_time_grid_length', int64), + ('move_translations_offset', int64), + ('move_translations_length', int64), + ('ID', int64), +]) + +surface = into_dtype([ + ('type', int64), + ('name', 'U32'), + ('boundary_condition', int64), + ('A', float64), + ('B', float64), + ('C', float64), + ('D', float64), + ('E', float64), + ('F', float64), + ('G', float64), + ('H', float64), + ('I', float64), + ('J', float64), + ('R', float64), + ('r', float64), + ('linear', bool), + ('nx', float64), + ('ny', float64), + ('nz', float64), + ('moving', bool), + ('N_move', int64), + ('N_move_grid', int64), + ('move_velocities_offset', int64), + ('move_velocities_length', int64), + ('move_durations_offset', int64), + ('move_durations_length', int64), + ('move_time_grid_offset', int64), + ('move_time_grid_length', int64), + ('move_translations_offset', int64), + ('move_translations_length', int64), + ('N_tally', int64), + ('tally_IDs_offset', int64), + ('ID', int64), +]) + +surface_tally = into_dtype([ + ('surface_ID', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +collision_tally = into_dtype([ + ('spatial_filter_type', int64), + ('spatial_filter_ID', int64), + ('spatial_filter_subtype', int64), + ('mesh_stride_z', int64), + ('mesh_stride_y', int64), + ('mesh_stride_x', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +tracklength_tally = into_dtype([ + ('spatial_filter_type', int64), + ('spatial_filter_ID', int64), + ('spatial_filter_subtype', int64), + ('mesh_stride_z', int64), + ('mesh_stride_y', int64), + ('mesh_stride_x', int64), + ('ID', int64), + ('parent_ID', int64), +]) + +gpu_meta = into_dtype([ + ('state_pointer', uintp), + ('program_pointer', uintp), + ('simulation_pointer', uintp), + ('data_pointer', uintp), +]) + +bank_active = None +def set_bank_active(N: dict): + global bank_active + bank_active = into_dtype([ + ('size', int64, (1,)), + ('tag', 'U32'), + ('particle_data', particle_data, (N['particle_data'],)), + ]) + +bank_census = None +def set_bank_census(N: dict): + global bank_census + bank_census = into_dtype([ + ('size', int64, (1,)), + ('tag', 'U32'), + ('particle_data', particle_data, (N['particle_data'],)), + ]) + +bank_source = None +def set_bank_source(N: dict): + global bank_source + bank_source = into_dtype([ + ('size', int64, (1,)), + ('tag', 'U32'), + ('particle_data', particle_data, (N['particle_data'],)), + ]) + +bank_future = None +def set_bank_future(N: dict): + global bank_future + bank_future = into_dtype([ + ('size', int64, (1,)), + ('tag', 'U32'), + ('particle_data', particle_data, (N['particle_data'],)), + ]) + +simulation = None +def set_simulation(N: dict): + global simulation + simulation = into_dtype([ + ('data', data, (N['data'])), + ('N_data', int64), + ('none_data', none_data, (N['none_data'])), + ('N_none_data', int64), + ('polynomial_data', polynomial_data, (N['polynomial_data'])), + ('N_polynomial_data', int64), + ('table_data', table_data, (N['table_data'])), + ('N_table_data', int64), + ('distributions', distribution, (N['distribution'])), + ('N_distribution', int64), + ('evaporation_distributions', evaporation_distribution, (N['evaporation_distribution'])), + ('N_evaporation_distribution', int64), + ('kalbach_mann_distributions', kalbach_mann_distribution, (N['kalbach_mann_distribution'])), + ('N_kalbach_mann_distribution', int64), + ('level_scattering_distributions', level_scattering_distribution, (N['level_scattering_distribution'])), + ('N_level_scattering_distribution', int64), + ('maxwellian_distributions', maxwellian_distribution, (N['maxwellian_distribution'])), + ('N_maxwellian_distribution', int64), + ('multi_table_distributions', multi_table_distribution, (N['multi_table_distribution'])), + ('N_multi_table_distribution', int64), + ('nbody_distributions', nbody_distribution, (N['nbody_distribution'])), + ('N_nbody_distribution', int64), + ('none_distributions', none_distribution, (N['none_distribution'])), + ('N_none_distribution', int64), + ('pmf_distributions', pmf_distribution, (N['pmf_distribution'])), + ('N_pmf_distribution', int64), + ('tabulated_distributions', tabulated_distribution, (N['tabulated_distribution'])), + ('N_tabulated_distribution', int64), + ('tabulated_energy_angle_distributions', tabulated_energy_angle_distribution, (N['tabulated_energy_angle_distribution'])), + ('N_tabulated_energy_angle_distribution', int64), + ('materials', material, (N['material'])), + ('N_material', int64), + ('native_materials', native_material, (N['native_material'])), + ('N_native_material', int64), + ('multigroup_materials', multigroup_material, (N['multigroup_material'])), + ('N_multigroup_material', int64), + ('elements', element, (N['element'])), + ('N_element', int64), + ('electron_reactions', electron_reaction, (N['electron_reaction'])), + ('N_electron_reaction', int64), + ('electron_bremsstrahlung_reactions', electron_bremsstrahlung_reaction, (N['electron_bremsstrahlung_reaction'])), + ('N_electron_bremsstrahlung_reaction', int64), + ('electron_elastic_scattering_reactions', electron_elastic_scattering_reaction, (N['electron_elastic_scattering_reaction'])), + ('N_electron_elastic_scattering_reaction', int64), + ('electron_excitation_reactions', electron_excitation_reaction, (N['electron_excitation_reaction'])), + ('N_electron_excitation_reaction', int64), + ('electron_ionization_reactions', electron_ionization_reaction, (N['electron_ionization_reaction'])), + ('N_electron_ionization_reaction', int64), + ('nuclides', nuclide, (N['nuclide'])), + ('N_nuclide', int64), + ('neutron_reactions', neutron_reaction, (N['neutron_reaction'])), + ('N_neutron_reaction', int64), + ('neutron_capture_reactions', neutron_capture_reaction, (N['neutron_capture_reaction'])), + ('N_neutron_capture_reaction', int64), + ('neutron_elastic_scattering_reactions', neutron_elastic_scattering_reaction, (N['neutron_elastic_scattering_reaction'])), + ('N_neutron_elastic_scattering_reaction', int64), + ('neutron_fission_reactions', neutron_fission_reaction, (N['neutron_fission_reaction'])), + ('N_neutron_fission_reaction', int64), + ('neutron_inelastic_scattering_reactions', neutron_inelastic_scattering_reaction, (N['neutron_inelastic_scattering_reaction'])), + ('N_neutron_inelastic_scattering_reaction', int64), + ('sources', source, (N['source'])), + ('N_source', int64), + ('cells', cell, (N['cell'])), + ('N_cell', int64), + ('lattices', lattice, (N['lattice'])), + ('N_lattice', int64), + ('surfaces', surface, (N['surface'])), + ('N_surface', int64), + ('universes', universe, (N['universe'])), + ('N_universe', int64), + ('meshes', mesh, (N['mesh'])), + ('N_mesh', int64), + ('structured_meshes', structured_mesh, (N['structured_mesh'])), + ('N_structured_mesh', int64), + ('uniform_meshes', uniform_mesh, (N['uniform_mesh'])), + ('N_uniform_mesh', int64), + ('tallies', tally, (N['tally'])), + ('N_tally', int64), + ('surface_tallies', surface_tally, (N['surface_tally'])), + ('N_surface_tally', int64), + ('collision_tallies', collision_tally, (N['collision_tally'])), + ('N_collision_tally', int64), + ('tracklength_tallies', tracklength_tally, (N['tracklength_tally'])), + ('N_tracklength_tally', int64), + ('settings', settings), + ('implicit_capture', implicit_capture), + ('weighted_emission', weighted_emission), + ('weight_roulette', weight_roulette), + ('population_control', population_control), + ('gpu_meta', gpu_meta), + ('bank_future', bank_future), + ('bank_source', bank_source), + ('bank_census', bank_census), + ('bank_active', bank_active), + ('idx_work', int64), + ('idx_cycle', int64), + ('idx_census', int64), + ('idx_batch', int64), + ('dd_idx', int64), + ('dd_N_local_source', int64), + ('dd_local_rank', int64), + ('k_eff', float64), + ('k_cycle_offset', int64), + ('k_cycle_length', int64), + ('k_avg', float64), + ('k_sdv', float64), + ('n_avg', float64), + ('n_sdv', float64), + ('n_max', float64), + ('C_avg', float64), + ('C_sdv', float64), + ('C_max', float64), + ('k_avg_running', float64), + ('k_sdv_running', float64), + ('gyration_radius_offset', int64), + ('gyration_radius_length', int64), + ('cycle_active', bool), + ('eigenvalue_tally_nuSigmaF', float64, (1,)), + ('eigenvalue_tally_n', float64, (1,)), + ('eigenvalue_tally_C', float64, (1,)), + ('mpi_size', int64), + ('mpi_rank', int64), + ('mpi_master', bool), + ('mpi_work_start', int64), + ('mpi_work_size', int64), + ('mpi_work_size_total', int64), + ('mpi_work_iter', int64, (1,)), + ('runtime_total', float64), + ('runtime_preparation', float64), + ('runtime_simulation', float64), + ('runtime_output', float64), + ('runtime_bank_management', float64), + ('source_seed', int64), + ]) + diff --git a/mcdc/object_/util.py b/mcdc/object_/util.py index 4f104562..19243753 100644 --- a/mcdc/object_/util.py +++ b/mcdc/object_/util.py @@ -554,3 +554,7 @@ def move_object(object_, velocities, durations): object_.move_translations[n + 1] = ( trans_start + object_.move_velocities[n] * object_.move_durations[n] ) + + +def subtype_size(main_list, subtype: str): + return len([x for x in main_list if x.label == subtype]) diff --git a/pyproject.toml b/pyproject.toml index 85e482e9..6e7c6304 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,3 +88,12 @@ Homepage = "https://cement-psaap.github.io/" Repository = "https://github.com/CEMeNT-PSAAP/MCDC" Documentation = "https://mcdc.readthedocs.io/en/latest/" Issues = "https://github.com/CEMeNT-PSAAP/MCDC/issues" + +[tool.black] +force-exclude = ''' +( + mcdc/numba_types\.py + | mcdc/mcdc_get/ + | mcdc/mcdc_set/ +) +''' From 766e2a64a7c974db25d2c56bca369983707fdb4e Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Tue, 14 Apr 2026 05:37:15 +0700 Subject: [PATCH 2/5] update black-lint workflow --- .github/workflows/black_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/black_lint.yml b/.github/workflows/black_lint.yml index a526643a..366d1174 100644 --- a/.github/workflows/black_lint.yml +++ b/.github/workflows/black_lint.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.13" + python-version: "3.14" cache: pip - name: Install Black From 1665cfeb436d0225df7945af9092732155a1b4fe Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Tue, 14 Apr 2026 05:44:29 +0700 Subject: [PATCH 3/5] back in black --- mcdc/code_factory/numba_objects_generator.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/mcdc/code_factory/numba_objects_generator.py b/mcdc/code_factory/numba_objects_generator.py index 4d6a5794..1fb6c393 100644 --- a/mcdc/code_factory/numba_objects_generator.py +++ b/mcdc/code_factory/numba_objects_generator.py @@ -353,7 +353,9 @@ def generate_numba_objects(simulation): text += f" {label} = into_dtype([\n" for item in structure: if item[0] == "particle_data": - text += f" ('{item[0]}', {item[0]}, (N['{item[0]}'],)),\n" + text += ( + f" ('{item[0]}', {item[0]}, (N['{item[0]}'],)),\n" + ) else: text += decode_structure_item(item, " ") text += " ])\n\n" @@ -363,7 +365,7 @@ def generate_numba_objects(simulation): text += f"def set_simulation(N: dict):\n" text += f" global simulation\n" text += f" simulation = into_dtype([\n" - for item in structures['simulation']: + for item in structures["simulation"]: if type(item[1]) == np.dtypes.VoidDType and len(item) == 3: singular_field = plural_to_singular(item[0]) text += f" ('{item[0]}', {singular_field}, (N['{singular_field}'])),\n" @@ -378,16 +380,16 @@ def generate_numba_objects(simulation): # ================================================================================== import mcdc.numba_types as type_ - - # Particle banks - type_.set_bank_active({'particle_data': simulation.bank_active.size[0]}) - type_.set_bank_census({'particle_data': simulation.bank_census.size[0]}) - type_.set_bank_source({'particle_data': simulation.bank_source.size[0]}) - type_.set_bank_future({'particle_data': simulation.bank_future.size[0]}) + + # Particle banks + type_.set_bank_active({"particle_data": simulation.bank_active.size[0]}) + type_.set_bank_census({"particle_data": simulation.bank_census.size[0]}) + type_.set_bank_source({"particle_data": simulation.bank_source.size[0]}) + type_.set_bank_future({"particle_data": simulation.bank_future.size[0]}) # Simulation N = {} - for item in structures['simulation']: + for item in structures["simulation"]: if type(item[1]) == np.dtypes.VoidDType and len(item) == 3: singular_field = plural_to_singular(item[0]) N[singular_field] = item[2] From bab9fb356dcda7fb41b430a77579d71b87da21d6 Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Tue, 14 Apr 2026 12:11:51 +0700 Subject: [PATCH 4/5] slight update on regtest workflows --- .github/workflows/docker.yml | 12 ++++++------ .github/workflows/regression_test.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3505a528..73c1906e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -112,20 +112,20 @@ jobs: - Numba-MPI include: - mode: Python-Serial - run_cmd: "python run.py --include_native_physics" + run_cmd: "python run.py" timeout: 10 - mode: Python-MPI run_cmd: | - python run.py --include_native_physics --mpiexec=4 - python run.py --include_native_physics --mpiexec=16 --name=slab_reed_dd_3d + python run.py --mpiexec=4 + python run.py --mpiexec=16 --name=slab_reed_dd_3d timeout: 20 - mode: Numba-Serial - run_cmd: "python run.py --include_native_physics --mode numba" + run_cmd: "python run.py --mode numba" timeout: 120 - mode: Numba-MPI run_cmd: | - python run.py --include_native_physics --mode numba --mpiexec=4 - python run.py --include_native_physics --mode numba --mpiexec=16 --name=slab_reed_dd_3d + python run.py --mode numba --mpiexec=4 + python run.py --mode numba --mpiexec=16 --name=slab_reed_dd_3d timeout: 120 steps: diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 1932cf43..8c190485 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -63,24 +63,24 @@ jobs: if: matrix.mode == 'Python-Serial' working-directory: test/regression run: | - python run.py --include_native_physics + python run.py - name: Run regression tests (${{ matrix.mode }}) if: matrix.mode == 'Python-MPI' working-directory: test/regression run: | - python run.py --include_native_physics --mpiexec=4 - python run.py --include_native_physics --mpiexec=16 --name=slab_reed_dd_3d + python run.py --mpiexec=4 + python run.py --mpiexec=16 --name=slab_reed_dd_3d - name: Run regression tests (${{ matrix.mode }}) if: matrix.mode == 'Numba-Serial' working-directory: test/regression run: | - python run.py --include_native_physics --mode numba + python run.py --mode numba - name: Run regression tests (${{ matrix.mode }}) if: matrix.mode == 'Numba-MPI' working-directory: test/regression run: | - python run.py --include_native_physics --mode numba --mpiexec=4 - python run.py --include_native_physics --mode numba --mpiexec=16 --name=slab_reed_dd_3d + python run.py --mode numba --mpiexec=4 + python run.py --mode numba --mpiexec=16 --name=slab_reed_dd_3d From d035f762cc61d12102375bf6c862f8712970243c Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Tue, 14 Apr 2026 12:48:53 +0700 Subject: [PATCH 5/5] add docstring --- mcdc/code_factory/numba_objects_generator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mcdc/code_factory/numba_objects_generator.py b/mcdc/code_factory/numba_objects_generator.py index 1fb6c393..d07da87a 100644 --- a/mcdc/code_factory/numba_objects_generator.py +++ b/mcdc/code_factory/numba_objects_generator.py @@ -1245,6 +1245,10 @@ def singular_to_plural(word: str) -> str: def decode_structure_item(item, prefix=""): + """ + A structure item is a list describing a member field in the structure. + The list contains [field name, field type, size]. + """ if type(item[1]) != np.dtypes.VoidDType: if isinstance(item[1], str): dtype = f"'{item[1]}'"