PyPartMC 2.1.2__cp315-cp315-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. PyPartMC/_PyPartMC.pyd +0 -0
  2. PyPartMC/__generate_si.py +37 -0
  3. PyPartMC/__init__.py +78 -0
  4. PyPartMC/cmake/PyPartMCConfig.cmake +65 -0
  5. PyPartMC/include/PyPartMC/aero_binned.hpp +117 -0
  6. PyPartMC/include/PyPartMC/aero_data.hpp +283 -0
  7. PyPartMC/include/PyPartMC/aero_dist.hpp +85 -0
  8. PyPartMC/include/PyPartMC/aero_mode.hpp +359 -0
  9. PyPartMC/include/PyPartMC/aero_particle.hpp +275 -0
  10. PyPartMC/include/PyPartMC/aero_state.hpp +664 -0
  11. PyPartMC/include/PyPartMC/bin_grid.hpp +143 -0
  12. PyPartMC/include/PyPartMC/camp_core.hpp +31 -0
  13. PyPartMC/include/PyPartMC/condense.hpp +35 -0
  14. PyPartMC/include/PyPartMC/env_state.hpp +161 -0
  15. PyPartMC/include/PyPartMC/gas_data.hpp +105 -0
  16. PyPartMC/include/PyPartMC/gas_state.hpp +129 -0
  17. PyPartMC/include/PyPartMC/getters.hpp +55 -0
  18. PyPartMC/include/PyPartMC/input_guard.hpp +155 -0
  19. PyPartMC/include/PyPartMC/json_resource.hpp +363 -0
  20. PyPartMC/include/PyPartMC/output.hpp +96 -0
  21. PyPartMC/include/PyPartMC/photolysis.hpp +29 -0
  22. PyPartMC/include/PyPartMC/pmc_resource.hpp +42 -0
  23. PyPartMC/include/PyPartMC/rand.hpp +12 -0
  24. PyPartMC/include/PyPartMC/run_exact.hpp +34 -0
  25. PyPartMC/include/PyPartMC/run_exact_opt.hpp +46 -0
  26. PyPartMC/include/PyPartMC/run_part.hpp +110 -0
  27. PyPartMC/include/PyPartMC/run_part_opt.hpp +72 -0
  28. PyPartMC/include/PyPartMC/run_sect.hpp +34 -0
  29. PyPartMC/include/PyPartMC/run_sect_opt.hpp +54 -0
  30. PyPartMC/include/PyPartMC/scenario.hpp +220 -0
  31. PyPartMC/include/PyPartMC/si.hpp +118 -0
  32. PyPartMC/include/PyPartMC/util.hpp +22 -0
  33. PyPartMC/include/PyPartMC.hpp +28 -0
  34. PyPartMC/include/aero_data_parameters.hpp +27 -0
  35. PyPartMC/include/bpstd/detail/string_view.inl +925 -0
  36. PyPartMC/include/bpstd/string_view.hpp +498 -0
  37. PyPartMC/include/gas_data_parameters.hpp +14 -0
  38. PyPartMC/include/nanobind_json/nanobind_json.h +226 -0
  39. PyPartMC/include/nlohmann/adl_serializer.hpp +55 -0
  40. PyPartMC/include/nlohmann/byte_container_with_subtype.hpp +103 -0
  41. PyPartMC/include/nlohmann/detail/abi_macros.hpp +100 -0
  42. PyPartMC/include/nlohmann/detail/conversions/from_json.hpp +497 -0
  43. PyPartMC/include/nlohmann/detail/conversions/to_chars.hpp +1118 -0
  44. PyPartMC/include/nlohmann/detail/conversions/to_json.hpp +446 -0
  45. PyPartMC/include/nlohmann/detail/exceptions.hpp +257 -0
  46. PyPartMC/include/nlohmann/detail/hash.hpp +129 -0
  47. PyPartMC/include/nlohmann/detail/input/binary_reader.hpp +3009 -0
  48. PyPartMC/include/nlohmann/detail/input/input_adapters.hpp +492 -0
  49. PyPartMC/include/nlohmann/detail/input/json_sax.hpp +727 -0
  50. PyPartMC/include/nlohmann/detail/input/lexer.hpp +1633 -0
  51. PyPartMC/include/nlohmann/detail/input/parser.hpp +519 -0
  52. PyPartMC/include/nlohmann/detail/input/position_t.hpp +37 -0
  53. PyPartMC/include/nlohmann/detail/iterators/internal_iterator.hpp +35 -0
  54. PyPartMC/include/nlohmann/detail/iterators/iter_impl.hpp +751 -0
  55. PyPartMC/include/nlohmann/detail/iterators/iteration_proxy.hpp +242 -0
  56. PyPartMC/include/nlohmann/detail/iterators/iterator_traits.hpp +61 -0
  57. PyPartMC/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +130 -0
  58. PyPartMC/include/nlohmann/detail/iterators/primitive_iterator.hpp +132 -0
  59. PyPartMC/include/nlohmann/detail/json_custom_base_class.hpp +39 -0
  60. PyPartMC/include/nlohmann/detail/json_pointer.hpp +988 -0
  61. PyPartMC/include/nlohmann/detail/json_ref.hpp +78 -0
  62. PyPartMC/include/nlohmann/detail/macro_scope.hpp +482 -0
  63. PyPartMC/include/nlohmann/detail/macro_unscope.hpp +45 -0
  64. PyPartMC/include/nlohmann/detail/meta/call_std/begin.hpp +17 -0
  65. PyPartMC/include/nlohmann/detail/meta/call_std/end.hpp +17 -0
  66. PyPartMC/include/nlohmann/detail/meta/cpp_future.hpp +171 -0
  67. PyPartMC/include/nlohmann/detail/meta/detected.hpp +70 -0
  68. PyPartMC/include/nlohmann/detail/meta/identity_tag.hpp +21 -0
  69. PyPartMC/include/nlohmann/detail/meta/is_sax.hpp +159 -0
  70. PyPartMC/include/nlohmann/detail/meta/std_fs.hpp +29 -0
  71. PyPartMC/include/nlohmann/detail/meta/type_traits.hpp +795 -0
  72. PyPartMC/include/nlohmann/detail/meta/void_t.hpp +24 -0
  73. PyPartMC/include/nlohmann/detail/output/binary_writer.hpp +1838 -0
  74. PyPartMC/include/nlohmann/detail/output/output_adapters.hpp +147 -0
  75. PyPartMC/include/nlohmann/detail/output/serializer.hpp +988 -0
  76. PyPartMC/include/nlohmann/detail/string_concat.hpp +146 -0
  77. PyPartMC/include/nlohmann/detail/string_escape.hpp +72 -0
  78. PyPartMC/include/nlohmann/detail/value_t.hpp +118 -0
  79. PyPartMC/include/nlohmann/json.hpp +5258 -0
  80. PyPartMC/include/nlohmann/json_fwd.hpp +75 -0
  81. PyPartMC/include/nlohmann/ordered_map.hpp +359 -0
  82. PyPartMC/include/nlohmann/thirdparty/hedley/hedley.hpp +2045 -0
  83. PyPartMC/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +158 -0
  84. PyPartMC/include/output_parameters.hpp +25 -0
  85. PyPartMC/include/tcb/span.hpp +617 -0
  86. PyPartMC/include/tl/optional.hpp +2062 -0
  87. PyPartMC/lib/libpartmclib.a +0 -0
  88. pypartmc-2.1.2.dist-info/METADATA +494 -0
  89. pypartmc-2.1.2.dist-info/RECORD +91 -0
  90. pypartmc-2.1.2.dist-info/WHEEL +5 -0
  91. pypartmc-2.1.2.dist-info/licenses/LICENSE +674 -0
PyPartMC/_PyPartMC.pyd ADDED
Binary file
@@ -0,0 +1,37 @@
1
+ from collections import namedtuple
2
+
3
+
4
+ def __generate_si():
5
+ prefixes = {
6
+ "T": 1e12,
7
+ "G": 1e9,
8
+ "M": 1e6,
9
+ "k": 1e3,
10
+ "h": 1e2,
11
+ "da": 1e1,
12
+ "": 1e0,
13
+ "d": 1e-1,
14
+ "c": 1e-2,
15
+ "m": 1e-3,
16
+ "u": 1e-6,
17
+ "n": 1e-9,
18
+ "p": 1e-12,
19
+ }
20
+ units = {
21
+ "m": 1e0,
22
+ "g": 1e-3,
23
+ "s": 1e0,
24
+ "K": 1e0,
25
+ "Pa": 1e0,
26
+ "mol": 1e0,
27
+ "W": 1e0,
28
+ "J": 1e0,
29
+ "N": 1e0,
30
+ }
31
+ return namedtuple("SI", [prefix + unit for prefix in prefixes for unit in units])(
32
+ **{
33
+ prefix_k + unit_k: prefix_v * unit_v
34
+ for prefix_k, prefix_v in prefixes.items()
35
+ for unit_k, unit_v in units.items()
36
+ }
37
+ )
PyPartMC/__init__.py ADDED
@@ -0,0 +1,78 @@
1
+ """
2
+ .. include::../../README.md
3
+ """
4
+
5
+ # pylint: disable=invalid-name
6
+ import importlib.metadata
7
+ import inspect
8
+
9
+ # pylint: disable=invalid-name,wrong-import-position
10
+ import os
11
+ from contextlib import contextmanager
12
+ from pathlib import Path
13
+
14
+ import nanobind
15
+
16
+
17
+ # https://github.com/diegoferigo/cmake-build-extension/blob/master/src/cmake_build_extension/__init__.py
18
+ @contextmanager
19
+ def __build_extension_env():
20
+ cookies = []
21
+ # https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew
22
+ if hasattr(os, "add_dll_directory"):
23
+ basepath = os.path.dirname(os.path.abspath(__file__))
24
+ dllspath = os.path.join(basepath, "..")
25
+ os.environ["PATH"] = dllspath + os.pathsep + os.environ["PATH"]
26
+ for path in os.environ.get("PATH", "").split(os.pathsep):
27
+ if path and Path(path).is_absolute() and Path(path).is_dir():
28
+ cookies.append(os.add_dll_directory(path))
29
+ try:
30
+ yield
31
+ finally:
32
+ for cookie in cookies:
33
+ cookie.close()
34
+
35
+
36
+ from .__generate_si import __generate_si
37
+
38
+ si = __generate_si()
39
+ """ a utility namedtuple aimed at clrifying physics-related code by providing
40
+ SI-prefix-aware unit multipliers, resulting in e.g.: `p = 1000 * si.hPa`
41
+ notation. Note: no dimensional analysis is done! """
42
+
43
+ from ._PyPartMC import * # pylint: disable=import-error
44
+ from ._PyPartMC import ( # pylint: disable=import-error
45
+ __versions_of_build_time_dependencies__,
46
+ )
47
+
48
+ # Hacky workaround for missing docs in pdoc auto-generated documentation.
49
+ # After the switch to nanobind, the docs became empty despite "__doc__" being
50
+ # accessible in all of PyPartMC's objects. The code below manually populates
51
+ # the "__all__" atrribute of the package. Additionally, functions in the generated
52
+ # docs would be listed as nanobind objects with no additional documentation.
53
+ # To solve that, dummy functions of the same name are created, and their "__doc__"
54
+ # attribute is manually set to the "original" objects' "__doc__"
55
+ if os.getenv("PDOC_GENERATE_PYPARTMC_DOCS") == "1":
56
+ all_items = []
57
+ for name, obj in inspect.getmembers(
58
+ _PyPartMC # pylint: disable=undefined-variable
59
+ ):
60
+ if callable(obj):
61
+ if not inspect.isclass(obj):
62
+ exec(name + " = lambda : 0") # pylint: disable=exec-used
63
+ temp = "_PyPartMC." + name + ".__doc__"
64
+ setattr(eval(name), "__doc__", eval(temp)) # pylint: disable=eval-used
65
+ all_items.append(name)
66
+
67
+ __all__ = tuple([*all_items, "si"])
68
+
69
+ __version__ = importlib.metadata.version(__package__)
70
+
71
+ # workaround for MATLAB bindings
72
+ # pylint: disable=undefined-variable
73
+ setattr(nanobind, "nb_type_0", type(_PyPartMC.AeroData))
74
+
75
+
76
+ # Function that returns cmakes config file location
77
+ def cmake_dir() -> str:
78
+ return os.path.join(os.path.dirname(__file__), "cmake")
@@ -0,0 +1,65 @@
1
+ if(TARGET PyPartMC::PyPartMC)
2
+ return()
3
+ endif()
4
+
5
+ find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development)
6
+
7
+ set(PyPartMC_RUNTIME_LIBRARY "${PYPARTMC_LIB_FILE}")
8
+
9
+ execute_process(
10
+ COMMAND ${Python_EXECUTABLE} -c "import nanobind, PyPartMC, os; from PyPartMC import _PyPartMC; print(f'{os.path.dirname(PyPartMC.__file__)};{nanobind.include_dir()};{_PyPartMC.__file__}')"
11
+ OUTPUT_VARIABLE PY_PATHS
12
+ OUTPUT_STRIP_TRAILING_WHITESPACE
13
+ RESULT_VARIABLE res
14
+ )
15
+
16
+ if(res)
17
+ message(FATAL_ERROR "filed to find PyPartMC libraries")
18
+ endif()
19
+
20
+ list(GET PY_PATHS 0 PYPARTMC_DIR)
21
+ list(GET PY_PATHS 1 NANOBIND_INCLUDE_DIR)
22
+ list(GET PY_PATHS 2 PYPARTMC_LIB_FILE)
23
+
24
+ get_filename_component(VENV_PYPARTMC_DIR "${PYPARTMC_LIB_FILE}" DIRECTORY)
25
+
26
+ add_library(PyPartMC::PyPartMC INTERFACE IMPORTED)
27
+
28
+ add_library(PyPartMC::RuntimeCore UNKNOWN IMPORTED)
29
+ set_target_properties(PyPartMC::RuntimeCore PROPERTIES IMPORTED_LOCATION "${PYPARTMC_LIB_FILE}")
30
+
31
+ set(POTENTIAL_INCLUDE_DIRS
32
+ "${PYPARTMC_DIR}/include"
33
+ "${VENV_PYPARTMC_DIR}/include"
34
+ "${NANOBIND_INCLUDE_DIR}"
35
+ )
36
+
37
+ set(ACTUAL_INCLUDE_DIRS "")
38
+ foreach(DIR IN LISTS POTENTIAL_INCLUDE_DIRS)
39
+ if(EXISTS "${DIR}")
40
+ list(APPEND ACTUAL_INCLUDE_DIRS "${DIR}")
41
+ endif()
42
+ endforeach()
43
+
44
+ target_include_directories(PyPartMC::PyPartMC INTERFACE
45
+ ${ACTUAL_INCLUDE_DIRS}
46
+ ${Python_INCLUDE_DIRS}
47
+ )
48
+
49
+ target_link_libraries(PyPartMC::PyPartMC INTERFACE
50
+ "${VENV_PYPARTMC_DIR}/lib/libpartmclib.a"
51
+ PyPartMC::RuntimeCore
52
+ ${Python_LIBRARIES}
53
+ )
54
+
55
+ function(pypartmc_setup_runtime TARGET_NAME)
56
+ if(WIN32)
57
+ add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
58
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
59
+ "${PYPARTMC_LIB_FILE}"
60
+ $<TARGET_FILE_DIR:${TARGET_NAME}>
61
+ )
62
+ endif()
63
+ endfunction()
64
+
65
+ message(STATUS "Found PyPartMC: ${PYPARTMC_DIR}")
@@ -0,0 +1,117 @@
1
+ /*##################################################################################################
2
+ # This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3
+ # Copyright (C) 2025 University of Illinois Urbana-Champaign #
4
+ # Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5
+ ##################################################################################################*/
6
+
7
+ #pragma once
8
+
9
+ #include "pmc_resource.hpp"
10
+ #include "aero_data.hpp"
11
+ #include "bin_grid.hpp"
12
+ #include "aero_dist.hpp"
13
+
14
+ extern "C" void f_aero_binned_ctor(void *ptr) noexcept;
15
+ extern "C" void f_aero_binned_dtor(void *ptr) noexcept;
16
+ extern "C" void f_aero_binned_len(
17
+ const void *ptr, int *len
18
+ ) noexcept;
19
+ extern "C" void f_aero_binned_add_aero_dist(
20
+ void *ptr,
21
+ const void *aero_data,
22
+ const void *bin_grid,
23
+ const void *aero_dist
24
+ ) noexcept;
25
+ extern "C" void f_aero_binned_set_sizes(
26
+ void *ptr,
27
+ const void *aero_data,
28
+ const void *aero_binned
29
+ ) noexcept;
30
+ extern "C" void f_aero_binned_num_conc(
31
+ const void *ptr,
32
+ double *num_conc,
33
+ const int *len
34
+ ) noexcept;
35
+ extern "C" void f_aero_binned_species_vol_conc(
36
+ const void *ptr,
37
+ double *data,
38
+ const int *n_bins,
39
+ const int *i_spec
40
+ ) noexcept;
41
+
42
+ struct AeroBinned {
43
+ PMCResource ptr;
44
+ std::shared_ptr<AeroData> aero_data;
45
+ AeroBinned(std::shared_ptr<AeroData> aero_data) :
46
+ ptr(f_aero_binned_ctor, f_aero_binned_dtor),
47
+ aero_data(aero_data)
48
+ {
49
+ }
50
+
51
+ AeroBinned(std::shared_ptr<AeroData> aero_data, const BinGrid &bin_grid) :
52
+ ptr(f_aero_binned_ctor, f_aero_binned_dtor),
53
+ aero_data(aero_data)
54
+ {
55
+ f_aero_binned_set_sizes(
56
+ ptr.f_arg_non_const(),
57
+ aero_data->ptr.f_arg(),
58
+ bin_grid.ptr.f_arg()
59
+ );
60
+ }
61
+
62
+ static auto num_conc(const AeroBinned &self) {
63
+ int len;
64
+ f_aero_binned_len(
65
+ self.ptr.f_arg(),
66
+ &len
67
+ );
68
+ std::valarray<double> num_conc(len);
69
+
70
+ f_aero_binned_num_conc(
71
+ self.ptr.f_arg(),
72
+ begin(num_conc),
73
+ &len
74
+ );
75
+
76
+ return num_conc;
77
+ }
78
+
79
+ static auto vol_conc(const AeroBinned &self){
80
+
81
+ int len;
82
+ f_aero_binned_len(
83
+ self.ptr.f_arg(),
84
+ &len
85
+ );
86
+
87
+ int cols = len;
88
+ int rows;
89
+ f_aero_data_len(self.aero_data->ptr.f_arg(), &rows);
90
+
91
+ std::valarray<std::valarray<double>> vol_conc(rows);
92
+ std::valarray<double> vol_species(cols);
93
+ for (int i = 0; i < rows; i++) {
94
+ vol_conc[i] = std::valarray<double>(cols);
95
+ f_aero_binned_species_vol_conc(self.ptr.f_arg(), begin(vol_species), &cols, &i);
96
+ for (int j = 0; j < cols; ++j) {
97
+ vol_conc[i][j] = vol_species[j];
98
+ }
99
+ }
100
+
101
+ return vol_conc;
102
+
103
+ }
104
+
105
+ static void add_aero_dist(AeroBinned &self,
106
+ const BinGrid &bin_grid, const AeroDist &aero_dist)
107
+ {
108
+ f_aero_binned_add_aero_dist(
109
+ self.ptr.f_arg_non_const(),
110
+ bin_grid.ptr.f_arg(),
111
+ self.aero_data->ptr.f_arg(),
112
+ aero_dist.ptr.f_arg()
113
+ );
114
+ }
115
+
116
+ };
117
+
@@ -0,0 +1,283 @@
1
+ /*##################################################################################################
2
+ # This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3
+ # Copyright (C) 2022 University of Illinois Urbana-Champaign #
4
+ # Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5
+ ##################################################################################################*/
6
+
7
+ #pragma once
8
+
9
+ #include "pmc_resource.hpp"
10
+ #include "json_resource.hpp"
11
+ #include "getters.hpp"
12
+ #include "camp_core.hpp"
13
+ #include "aero_data_parameters.hpp"
14
+ #include "nanobind/nanobind.h"
15
+
16
+ extern "C" void f_aero_data_ctor(void *ptr) noexcept;
17
+ extern "C" void f_aero_data_dtor(void *ptr) noexcept;
18
+ extern "C" void f_aero_data_from_json(const void *ptr) noexcept;
19
+ extern "C" void f_aero_data_from_camp(const void *ptr, const void *camp_core_ptr) noexcept;
20
+ extern "C" void f_aero_data_spec_by_name(const void *ptr, int *value, const char *name_data, const int *name_size) noexcept;
21
+ extern "C" void f_aero_data_len(const void *ptr, int *len) noexcept;
22
+ extern "C" void f_aero_data_n_source(const void *ptr, int *len) noexcept;
23
+ extern "C" void f_aero_data_set_frac_dim(void *ptr, const double*) noexcept;
24
+ extern "C" void f_aero_data_get_frac_dim(const void *ptr, double*) noexcept;
25
+ extern "C" void f_aero_data_set_vol_fill_factor(void *ptr, const double*) noexcept;
26
+ extern "C" void f_aero_data_get_vol_fill_factor(const void *ptr, double*) noexcept;
27
+ extern "C" void f_aero_data_set_prime_radius(void *ptr, const double*) noexcept;
28
+ extern "C" void f_aero_data_get_prime_radius(const void *ptr, double*) noexcept;
29
+ extern "C" void f_aero_data_rad2vol(const void *ptr, const double*, double*) noexcept;
30
+ extern "C" void f_aero_data_vol2rad(const void *ptr, const double*, double*) noexcept;
31
+ extern "C" void f_aero_data_diam2vol(const void *ptr, const double*, double*) noexcept;
32
+ extern "C" void f_aero_data_vol2diam(const void *ptr, const double*, double*) noexcept;
33
+ extern "C" void f_aero_data_get_species_density(const void *ptr, const int *idx, double *val) noexcept;
34
+ extern "C" void f_aero_data_get_species_kappa(const void *ptr, const int *idx, double *val) noexcept;
35
+ extern "C" void f_aero_data_get_species_molecular_weight(const void *ptr, const int *idx, double *val) noexcept;
36
+ extern "C" void f_aero_data_source_name_by_index(const void *ptr, const int *i_source,
37
+ char *name_data) noexcept;
38
+ extern "C" void f_aero_data_spec_name_by_index(const void *ptr, const int *i_spec,
39
+ char *name_data) noexcept;
40
+
41
+ struct AeroData {
42
+ PMCResource ptr;
43
+
44
+ AeroData(
45
+ const CampCore &camp_core
46
+ ) :
47
+ ptr(f_aero_data_ctor, f_aero_data_dtor)
48
+ {
49
+ f_aero_data_from_camp(this->ptr.f_arg(), camp_core.ptr.f_arg());
50
+ }
51
+
52
+ AeroData(const nlohmann::ordered_json &json) :
53
+ ptr(f_aero_data_ctor, f_aero_data_dtor)
54
+ {
55
+ if (!InputJSONResource::unique_keys(json))
56
+ throw std::runtime_error("Species names must be unique");
57
+
58
+ JSONResourceGuard<InputJSONResource> guard(json);
59
+ f_aero_data_from_json(this->ptr.f_arg());
60
+ guard.check_parameters();
61
+ }
62
+
63
+ AeroData() :
64
+ ptr(f_aero_data_ctor, f_aero_data_dtor)
65
+ {}
66
+
67
+ static auto spec_by_name(const AeroData &self, const std::string &name) {
68
+ int value;
69
+ const int name_size = name.size();
70
+ f_aero_data_spec_by_name(
71
+ self.ptr.f_arg(),
72
+ &value,
73
+ name.c_str(),
74
+ &name_size
75
+ );
76
+ if (value==0)
77
+ throw std::runtime_error("Element not found.");
78
+ return value - 1;
79
+ }
80
+
81
+ static std::size_t __len__(const AeroData &self) {
82
+ return pypartmc::get_value<int>(self, f_aero_data_len);
83
+ }
84
+
85
+ static void set_frac_dim(AeroData &self, const double value) {
86
+ pypartmc::set_value(self, f_aero_data_set_frac_dim, value);
87
+ }
88
+
89
+ static auto get_frac_dim(const AeroData &self) {
90
+ return pypartmc::get_value(self, f_aero_data_get_frac_dim);
91
+ }
92
+
93
+ static void set_vol_fill_factor(AeroData &self, const double value) {
94
+ pypartmc::set_value(self, f_aero_data_set_vol_fill_factor, value);
95
+ }
96
+
97
+ static auto get_prime_radius(AeroData &self) {
98
+ return pypartmc::get_value(self, f_aero_data_get_prime_radius);
99
+ }
100
+
101
+ static void set_prime_radius(AeroData &self, const double value) {
102
+ f_aero_data_set_prime_radius(
103
+ self.ptr.f_arg_non_const(),
104
+ &value
105
+ );
106
+ }
107
+
108
+ static auto get_vol_fill_factor(const AeroData &self) {
109
+ return pypartmc::get_value(self, f_aero_data_get_vol_fill_factor);
110
+ }
111
+
112
+ static auto rad2vol(const AeroData &self, const double radius) {
113
+ double vol;
114
+ f_aero_data_rad2vol(
115
+ self.ptr.f_arg(),
116
+ &radius,
117
+ &vol
118
+ );
119
+ return vol;
120
+ }
121
+
122
+ static auto vol2rad(const AeroData &self, const double vol) {
123
+ double radius;
124
+ f_aero_data_vol2rad(
125
+ self.ptr.f_arg(),
126
+ &vol,
127
+ &radius
128
+ );
129
+ return radius;
130
+ }
131
+
132
+ static auto diam2vol(const AeroData &self, const double diam) {
133
+ double vol;
134
+ f_aero_data_diam2vol(
135
+ self.ptr.f_arg(),
136
+ &diam,
137
+ &vol
138
+ );
139
+ return vol;
140
+ }
141
+
142
+ static auto vol2diam(const AeroData &self, const double vol) {
143
+ double diam;
144
+ f_aero_data_vol2diam(
145
+ self.ptr.f_arg(),
146
+ &vol,
147
+ &diam
148
+ );
149
+ return diam;
150
+ }
151
+
152
+ static auto densities(const AeroData &self) {
153
+ int len;
154
+ f_aero_data_len(
155
+ self.ptr.f_arg(),
156
+ &len
157
+ );
158
+ std::valarray<double> data(len);
159
+
160
+ for (int idx = 0; idx < len; idx++) {
161
+ f_aero_data_get_species_density(
162
+ self.ptr.f_arg(),
163
+ &idx,
164
+ &data[idx]
165
+ );
166
+ }
167
+
168
+ return data;
169
+ }
170
+
171
+ static auto density(const AeroData &self, const std::string &name) {
172
+ int idx;
173
+ double data;
174
+ const int name_size = name.size();
175
+
176
+ f_aero_data_spec_by_name(
177
+ self.ptr.f_arg(),
178
+ &idx,
179
+ name.c_str(),
180
+ &name_size
181
+ );
182
+
183
+ if (idx==0)
184
+ throw std::runtime_error("Element not found.");
185
+
186
+ idx--;
187
+ f_aero_data_get_species_density(
188
+ self.ptr.f_arg(),
189
+ &idx,
190
+ &data
191
+ );
192
+
193
+ return data;
194
+ }
195
+
196
+ static std::size_t n_source(const AeroData &self) {
197
+ int len = pypartmc::get_value<int>(self, f_aero_data_n_source);
198
+ if (len == -1)
199
+ throw std::runtime_error("No sources defined.");
200
+ return len;
201
+ }
202
+
203
+ static auto sources(const AeroData &self) {
204
+
205
+ int len;
206
+ f_aero_data_n_source(
207
+ self.ptr.f_arg(),
208
+ &len
209
+ );
210
+
211
+ char name[AERO_SOURCE_NAME_LEN];
212
+ auto names = nanobind::list();
213
+ for (int idx = 0; idx < len; idx++) {
214
+ f_aero_data_source_name_by_index(
215
+ self.ptr.f_arg(),
216
+ &idx,
217
+ name
218
+ );
219
+ names.append(std::string(name));
220
+ }
221
+ return nanobind::tuple(names);
222
+ }
223
+
224
+ static auto names(const AeroData &self) {
225
+
226
+ int len;
227
+ f_aero_data_len(
228
+ self.ptr.f_arg(),
229
+ &len
230
+ );
231
+
232
+ char name[AERO_NAME_LEN];
233
+ auto names = nanobind::list();
234
+ for (int idx = 0; idx < len; idx++) {
235
+ f_aero_data_spec_name_by_index(
236
+ self.ptr.f_arg(),
237
+ &idx,
238
+ name
239
+ );
240
+ names.append(std::string(name));
241
+ }
242
+ return nanobind::tuple(names);
243
+ }
244
+
245
+ static auto kappa(const AeroData &self) {
246
+ int len;
247
+ f_aero_data_len(
248
+ self.ptr.f_arg(),
249
+ &len
250
+ );
251
+ std::valarray<double> data(len);
252
+
253
+ for (int idx = 0; idx < len; idx++) {
254
+ f_aero_data_get_species_kappa(
255
+ self.ptr.f_arg(),
256
+ &idx,
257
+ &data[idx]
258
+ );
259
+ }
260
+
261
+ return data;
262
+ }
263
+
264
+ static auto molecular_weights(const AeroData &self) {
265
+ int len;
266
+ f_aero_data_len(
267
+ self.ptr.f_arg(),
268
+ &len
269
+ );
270
+ std::valarray<double> data(len);
271
+
272
+ for (int idx = 0; idx < len; idx++) {
273
+ f_aero_data_get_species_molecular_weight(
274
+ self.ptr.f_arg(),
275
+ &idx,
276
+ &data[idx]
277
+ );
278
+ }
279
+
280
+ return data;
281
+ }
282
+ };
283
+
@@ -0,0 +1,85 @@
1
+ /*##################################################################################################
2
+ # This file is a part of PyPartMC licensed under the GNU General Public License v3 (LICENSE file) #
3
+ # Copyright (C) 2022 University of Illinois Urbana-Champaign #
4
+ # Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors #
5
+ ##################################################################################################*/
6
+
7
+ #pragma once
8
+
9
+ #include "pmc_resource.hpp"
10
+ #include "aero_mode.hpp"
11
+
12
+ extern "C" void f_aero_dist_ctor(
13
+ void *ptr
14
+ ) noexcept;
15
+
16
+ extern "C" void f_aero_dist_dtor(
17
+ void *ptr
18
+ ) noexcept;
19
+
20
+ extern "C" void f_aero_dist_n_mode(
21
+ const void *ptr,
22
+ int *n_mode
23
+ ) noexcept;
24
+
25
+ extern "C" void f_aero_dist_from_json(
26
+ void *ptr,
27
+ void *aero_data_ptr
28
+ ) noexcept;
29
+
30
+ extern "C" void f_aero_dist_total_num_conc(
31
+ const void *ptr,
32
+ double *total_num_conc
33
+ ) noexcept;
34
+
35
+ extern "C" void f_aero_dist_mode(
36
+ const void *ptr,
37
+ void *ptr_c,
38
+ const int *index
39
+ ) noexcept;
40
+
41
+ struct AeroDist {
42
+ PMCResource ptr;
43
+ std::shared_ptr<AeroData> aero_data;
44
+
45
+ AeroDist(
46
+ std::shared_ptr<AeroData> aero_data,
47
+ const nlohmann::ordered_json &json
48
+ ):
49
+ ptr(f_aero_dist_ctor, f_aero_dist_dtor),
50
+ aero_data(aero_data)
51
+ {
52
+ for (const auto &mode : json)
53
+ AeroMode::check_mode_json(mode.begin().value());
54
+
55
+ JSONResourceGuard<InputJSONResource> guard(json, "", "mode_name", 1);
56
+ f_aero_dist_from_json(ptr.f_arg_non_const(), aero_data->ptr.f_arg_non_const());
57
+ guard.check_parameters();
58
+ }
59
+
60
+ AeroDist() :
61
+ ptr(f_aero_dist_ctor, f_aero_dist_dtor)
62
+ {}
63
+
64
+ static auto get_n_mode(const AeroDist &self) {
65
+ int n_mode;
66
+ f_aero_dist_n_mode(self.ptr.f_arg(), &n_mode);
67
+ return n_mode;
68
+ }
69
+
70
+ static auto get_total_num_conc(const AeroDist &self) {
71
+ double total_num_conc;
72
+ f_aero_dist_total_num_conc(self.ptr.f_arg(), &total_num_conc);
73
+ return total_num_conc;
74
+ }
75
+
76
+ static AeroMode* get_mode(const AeroDist &self, const int &idx) {
77
+ if (idx < 0 || idx >= AeroDist::get_n_mode(self))
78
+ throw std::out_of_range("Index out of range");
79
+
80
+ AeroMode *ptr = new AeroMode();
81
+ f_aero_dist_mode(self.ptr.f_arg(), ptr, &idx);
82
+
83
+ return ptr;
84
+ }
85
+ };