orochi.pdfsim 4.0.0__py3-none-any.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 (34) hide show
  1. orochi/__init__.py +22 -0
  2. orochi/pdfsim/__init__.py +4 -0
  3. orochi/pdfsim/_old/no_q_depend.py +84 -0
  4. orochi/pdfsim/_old/q_depend.py +123 -0
  5. orochi/pdfsim/gr_histogram/_old/cpu.py +313 -0
  6. orochi/pdfsim/gr_histogram/_old/epf.py +60 -0
  7. orochi/pdfsim/gr_histogram/_old/gpu.py +58 -0
  8. orochi/pdfsim/gr_histogram/histogram/cpu.py +86 -0
  9. orochi/pdfsim/gr_histogram/histogram/pdf_no_q_depend_gpu.py +194 -0
  10. orochi/pdfsim/gr_histogram/histogram/pdf_q_depend_cpu.py +187 -0
  11. orochi/pdfsim/gr_histogram/profile/cpu.py +274 -0
  12. orochi/pdfsim/io/save.py +11 -0
  13. orochi/pdfsim/io/xyz.py +13 -0
  14. orochi/pdfsim/macro/structural_analysis_with_predictor.py +17 -0
  15. orochi/pdfsim/params/default.py +147 -0
  16. orochi/pdfsim/params/spring8_bl22xu_fpd.py +17 -0
  17. orochi/pdfsim/restraint/correlation.py +33 -0
  18. orochi/pdfsim/restraint/penalty.py +49 -0
  19. orochi/pdfsim/shape/spheroid.py +12 -0
  20. orochi/pdfsim/simulator.py +1456 -0
  21. orochi/pdfsim/submodules/explain/params.py +64 -0
  22. orochi/pdfsim/submodules/explain/reasoning.py +113 -0
  23. orochi/pdfsim/submodules/explain/scoring.py +93 -0
  24. orochi/pdfsim/submodules/explain/visualize.py +77 -0
  25. orochi/pdfsim/submodules/lang_model.py +41 -0
  26. orochi/pdfsim/submodules/phase_update.py +28 -0
  27. orochi/pdfsim/submodules/refinement.py +488 -0
  28. orochi/pdfsim/submodules/subgroup.py +216 -0
  29. orochi/pdfsim/version.py +23 -0
  30. orochi_pdfsim-4.0.0.dist-info/METADATA +256 -0
  31. orochi_pdfsim-4.0.0.dist-info/RECORD +34 -0
  32. orochi_pdfsim-4.0.0.dist-info/WHEEL +5 -0
  33. orochi_pdfsim-4.0.0.dist-info/licenses/LICENSE.rst +682 -0
  34. orochi_pdfsim-4.0.0.dist-info/top_level.txt +1 -0
orochi/__init__.py ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python
2
+ ##############################################################################
3
+ #
4
+ # (c) 2025 National Institute for Materials Science (NIMS).
5
+ # All rights reserved.
6
+ #
7
+ # File coded by: Tominaka Laboratory members and community contributors.
8
+ #
9
+ # See GitHub contributions for a more detailed list of contributors.
10
+ # https://github.com/Tominaka-Laboratory/orochi.pdf-simulator/graphs/contributors
11
+ #
12
+ # See LICENSE.rst for license information.
13
+ #
14
+ ##############################################################################
15
+ """Blank namespace package for module orochi."""
16
+
17
+
18
+ from pkgutil import extend_path
19
+
20
+ __path__ = extend_path(__path__, __name__)
21
+
22
+ # End of file
@@ -0,0 +1,4 @@
1
+ from .simulator import Simulator
2
+
3
+ __all__ = ["Simulator"]
4
+
@@ -0,0 +1,84 @@
1
+ #old one before refactoring
2
+
3
+ # import numpy as np
4
+ # from numpy.typing import NDArray
5
+
6
+ # def calc_gij(self, aij: NDArray[np.int64]) -> NDArray[np.float64]:
7
+ # """
8
+ # Calculates the scattering factor product g_ij (Q-independent).
9
+
10
+ # This function calculates the scattering factor product g_ij, assuming that
11
+ # the atomic scattering factors are independent of the scattering vector Q.
12
+ # This simplification is often used for simpler models or when Q-dependence
13
+ # is not significant. The calculation uses the atomic numbers (zi) to
14
+ # approximate the scattering factors.
15
+
16
+ # Parameters
17
+ # ----------
18
+ # self : Simulator
19
+ # The Simulator object, which must contain the atomic numbers (zi)
20
+ # and atomic symbols.
21
+ # aij : NDArray[np.int64]
22
+ # A 2D array representing the atomic pairs. Each row contains the indices
23
+ # of the two atoms in a pair.
24
+
25
+ # Returns
26
+ # -------
27
+ # numpy.ndarray
28
+ # A 1D NumPy array representing g_ij, the scattering factor product
29
+ # for each atomic pair.
30
+
31
+ # Notes
32
+ # -----
33
+ # The function performs the following steps:
34
+ # 1. Retrieves the atomic numbers zi for each unique atom.
35
+ # 2. Assigns the corresponding zi to each atom in the pairs defined by aij.
36
+ # 3. Calculates the product of the atomic numbers for each pair.
37
+ # 4. Normalizes the product by the square of the average atomic number,
38
+ # weighted by the atomic occupancies.
39
+ # """
40
+ # symbols_all = self.phase.model["symbol"]
41
+ # occ = self.phase.model["occ"]
42
+
43
+ # sfs = np.ones_like(symbols_all).astype(float)
44
+ # fij = np.ones_like(aij).astype(float)
45
+
46
+ # symbols = np.unique(symbols_all)
47
+ # for atom in symbols:
48
+ # zi = self.zi[atom]
49
+ # sfs[np.where(symbols_all == atom)] = zi
50
+ # fij[np.where(aij == atom)] = zi
51
+
52
+ # gij = np.abs(fij[:, 0] * fij[:, 1])
53
+ # gij /= np.square(np.average(sfs * occ)) # fij/<cf>2
54
+ # return gij
55
+
56
+
57
+
58
+ # def calc_scattering_factors(self) -> NDArray[np.float64]:
59
+ # """
60
+ # Calculates the atomic scattering factors (Q-independent approximation).
61
+
62
+ # This function calculates the atomic scattering factors f(Q) using the
63
+ # approximation that they are equal to the atomic numbers (zi). This
64
+ # is a simplification that neglects the Q-dependence of the scattering factors.
65
+
66
+ # Parameters
67
+ # ----------
68
+ # self : Simulator
69
+ # The Simulator object, which must contain the atomic symbols and
70
+ # atomic numbers (zi).
71
+
72
+ # Returns
73
+ # -------
74
+ # numpy.ndarray
75
+ # A 1D NumPy array of the atomic scattering factors f(Q) for each atom
76
+ # in the structure.
77
+ # """
78
+ # symbols_all = self.phase.model["symbol"]
79
+ # sfs = np.ones_like(symbols_all).astype(float)
80
+ # symbols = np.unique(symbols_all)
81
+ # for atom in symbols:
82
+ # zi = self.zi[atom]
83
+ # sfs[np.where(symbols_all == atom)] = zi
84
+ # return sfs
@@ -0,0 +1,123 @@
1
+ # import numpy as np
2
+ # from scipy.fft import dct
3
+ # import scipy.interpolate as intp
4
+ # from numpy.typing import NDArray
5
+
6
+ # def calc_gij(self, aij: NDArray[np.int64]) -> NDArray[np.complex128]:
7
+ # """
8
+ # Calculates the scattering factor product g_ij(Q) with Q-dependence.
9
+
10
+ # This function calculates the scattering factor product g_ij(Q), which accounts for
11
+ # the Q-dependence of the atomic scattering factors. This is important for accurate
12
+ # PDF calculations, especially when dealing with materials containing elements with
13
+ # significant differences in their scattering factors. The calculation involves
14
+ # obtaining the atomic scattering factors f0, f1, and f2, and then performing
15
+ # a discrete cosine transform (DCT) to obtain the real-space representation.
16
+
17
+ # Parameters
18
+ # ----------
19
+ # self : Simulator
20
+ # The Simulator object, which must contain the atomic scattering factors
21
+ # (f0s, f1f2s), atomic symbols, and relevant parameters (qmax, number_scf_function, pad).
22
+ # aij : NDArray[np.int64]
23
+ # A 2D array representing the atomic pairs. Each row contains the indices
24
+ # of the two atoms in a pair.
25
+
26
+ # Returns
27
+ # -------
28
+ # NDArray[np.complex128]
29
+ # A 2D NumPy array representing g_ij(r), the scattering factor product
30
+ # in real space. The shape is (n_pairs, n_r_points).
31
+
32
+ # Notes
33
+ # -----
34
+ # The function performs the following steps:
35
+ # 1. Creates a Q-space vector.
36
+ # 2. Retrieves atomic scattering factors f0, f1, f2 for each unique atom.
37
+ # 3. Calculates the scattering factor product for each atomic pair.
38
+ # 4. Calculates the average scattering factor.
39
+ # 5. Normalizes the scattering factor product.
40
+ # 6. Applies a Discrete Cosine Transform (DCT) to obtain the real-space
41
+ # representation.
42
+ # 7. Interpolates the result to match the desired r-space grid.
43
+ # """
44
+ # q = np.linspace(0, self["qmax"], self["number_scf_function"])
45
+ # symbols_all = self.phase.model["symbol"]
46
+ # sfs = np.zeros((symbols_all.size, q.size)) + 0.0j
47
+ # fij = np.ones(np.append(aij.shape, q.size)).astype(float) + 0.0j
48
+
49
+ # symbols = np.unique(symbols_all)
50
+ # for atom in symbols:
51
+ # f0 = self.f0s[atom](q)
52
+ # f1, f2 = self.f1f2s[atom](self["energy"])
53
+ # sf = f0 + f1 + 1.0j * f2
54
+ # sfs[np.where(symbols_all == atom)] = sf
55
+ # fij[np.where(aij == atom)] = sf
56
+
57
+ # gij = fij[:, 0] * fij[:, 1]
58
+ # occ = self.phase.model["occ"]
59
+ # ave = np.average(sfs * occ[:, np.newaxis], axis=0)
60
+ # gij /= np.square(ave) # fij/<cf>2
61
+ # gij = np.abs(gij)
62
+
63
+ # number_scf_function = self["number_scf_function"] * self["pad"]
64
+ # gij = dct(gij, n=number_scf_function, type=2, norm=None, axis=1) / (
65
+ # 2.0 * number_scf_function
66
+ # )
67
+
68
+ # if (self.r[1] - self.r[1]) != (self["qmax"] * np.float64(self["pad"])):
69
+ # r = (
70
+ # np.arange(0, np.float64(number_scf_function), 1.0)
71
+ # * np.pi
72
+ # / (self["qmax"] * np.float64(self["pad"]))
73
+ # )
74
+ # r_new = np.arange(r[0], r[-1], self.r[1] - self.r[0])
75
+ # gij_new = np.empty((0, r_new.size))
76
+
77
+ # for g in gij:
78
+ # gn = intp.interp1d(r, g, fill_value=0.0)(r_new)
79
+ # gij_new = np.append(gij_new, gn.reshape(1, -1), axis=0)
80
+
81
+ # norm = np.sum(gij, axis=-1)
82
+ # gij = gij_new
83
+ # norm2 = np.sum(gij, axis=-1)
84
+ # gij = gij / norm2[:, np.newaxis] * norm[:, np.newaxis]
85
+
86
+ # gij = np.append(gij[:, :0:-1], gij, axis=-1)
87
+ # return gij
88
+
89
+
90
+
91
+ # def calc_scattering_factors(self) -> NDArray[np.complex128]:
92
+ # """
93
+ # Calculates the atomic scattering factors with Q-dependence.
94
+
95
+ # This function calculates the atomic scattering factors f(Q) for all unique atomic
96
+ # symbols in the Phase object. It combines the contributions from the
97
+ # normal scattering factor (f0) and the anomalous scattering factors (f1, f2),
98
+ # which are energy-dependent.
99
+
100
+ # Parameters
101
+ # ----------
102
+ # self : Simulator
103
+ # The Simulator object, which must contain the atomic symbols,
104
+ # the Q-values, and the functions to calculate f0, f1, and f2
105
+ # (self.f0s, self.f1f2s).
106
+
107
+ # Returns
108
+ # -------
109
+ # numpy.ndarray
110
+ # A 2D NumPy array of the atomic scattering factors f(Q) for each atom.
111
+ # The shape is (n_atoms, n_q_points). The values are complex.
112
+ # """
113
+ # symbols = np.unique(self.symbols)
114
+ # q = np.linspace(0, self["qmax"], self["number_scf_function"])
115
+ # sfs = np.zeros((self.symbols.size, q.size)) + 0.0j
116
+
117
+ # for atom in symbols:
118
+ # f0 = self.f0s[atom](q)
119
+ # f1, f2 = self.f1f2s[atom](self["energy"])
120
+ # sf = f0 + f1 + 1.0j * f2
121
+ # sfs[np.where(self.symbols == atom)] = sf
122
+
123
+ # return sfs
@@ -0,0 +1,313 @@
1
+ #old one before refactoring
2
+
3
+ # import numpy as np
4
+
5
+
6
+ # def calc_gr_histogram(self, q_dependence=False):
7
+ # """
8
+ # Prepares for the pair distribution function g(r) histogram calculation using CPU.
9
+
10
+ # This function prepares the histogram for calculating the pair distribution
11
+ # function (PDF) g(r). It groups pair data to enhance computational
12
+ # efficiency by performing similar calculations in batches. Based on the
13
+ # `q_dependence` parameter, it selects the appropriate structure factor
14
+ # and PDF calculation functions.
15
+
16
+ # Parameters
17
+ # ----------
18
+ # self : Calculator
19
+ # An instance of the Calculator class for PDF calculation.
20
+ # q_dependence : bool, optional
21
+ # A flag indicating whether to consider Q-dependent structure factors.
22
+ # Defaults to False.
23
+
24
+ # Returns
25
+ # -------
26
+ # r : numpy.ndarray
27
+ # Array of radial distances r.
28
+ # gr : numpy.ndarray
29
+ # The calculated histogram of the pair distribution function g(r).
30
+
31
+ # Notes
32
+ # -----
33
+ # This function calculates the histogram through the following steps:
34
+
35
+ # 1. Determines the range of pair data to be used for calculation using
36
+ # the `set_r_range` function.
37
+ # 2. Groups the pair data using the `grouping` function.
38
+ # 3. Selects the appropriate structure factor and PDF calculation functions
39
+ # based on the `q_dependence` parameter.
40
+ # 4. Calculates the histogram of g(r) using the selected functions.
41
+ # 5. Normalizes the histogram if necessary.
42
+
43
+ # """
44
+ # # data_in_r_range = set_r_range(self)
45
+ # ai = self.pairs["symbol"][:, 0]
46
+ # aj = self.pairs["symbol"][:, 1]
47
+ # rij = self.pairs["distance"]
48
+ # sij = self.pairs["adp"]
49
+ # cij = self.pairs["occ"]
50
+ # r = self.r
51
+ # r_pair = self.r_pair
52
+
53
+
54
+ # grouped_pairs = grouping(self, rij, cij, sij, ai, aj, r)
55
+ # rij = grouped_pairs["rij"]
56
+ # cij = grouped_pairs["cij"]
57
+ # sij = grouped_pairs["sij"]
58
+ # bin_min = grouped_pairs["bin_min"]
59
+ # bin_max = grouped_pairs["bin_max"]
60
+ # same_aij_groups = grouped_pairs["same_aij_groups"]
61
+ # same_uij_groups = grouped_pairs["same_uij_groups"]
62
+ # unique_aij = grouped_pairs["unique_aij"]
63
+
64
+ # if q_dependence:
65
+ # from ..structure_factor.q_depend import calc_gij
66
+ # from .histogram.pdf_q_depend_cpu import calc_pdf
67
+ # else:
68
+ # from ..structure_factor.no_q_depend import calc_gij
69
+ # from .histogram.pdf_no_q_depend_cpu import calc_pdf
70
+
71
+ # gij = calc_gij(self, unique_aij)
72
+ # gr = calc_pdf(
73
+ # r,
74
+ # rij,
75
+ # cij,
76
+ # sij,
77
+ # gij,
78
+ # same_aij_groups,
79
+ # same_uij_groups,
80
+ # bin_min,
81
+ # bin_max,
82
+ # r_pair,
83
+ # )
84
+
85
+ # if not q_dependence:
86
+ # gr /= r
87
+
88
+ # gr *= (self["qmax"] * self["pad"]) / np.pi
89
+ # gr /= self.phase.model["occ"].size
90
+ # return r, gr
91
+
92
+
93
+ # def calc_simulation_range(self, r_pair):
94
+ # """
95
+ # Calculates the simulation range.
96
+
97
+ # This function determines the range of data to be used for PDF calculation
98
+ # based on the provided `r_pair`. The calculation range is determined by the
99
+ # minimum and maximum values of `self.r` extended by the range of `r_pair`.
100
+
101
+ # Parameters
102
+ # ----------
103
+ # self : Calculator
104
+ # An instance of the Calculator class for PDF calculation.
105
+ # r_pair : numpy.ndarray
106
+ # Array of pair distances r_ij.
107
+
108
+ # Returns
109
+ # -------
110
+ # numpy.ndarray
111
+ # An array of indices representing the simulation range.
112
+ # """
113
+ # eval_min = self.r[0] - r_pair[-1]
114
+ # eval_max = self.r[-1] + r_pair[-1]
115
+
116
+ # if eval_min <= 0:
117
+ # eval_min = 0
118
+ # simulation_range = np.where((self.rij > eval_min) & (self.rij < eval_max))
119
+ # return simulation_range[0]
120
+
121
+
122
+ # def make_bins(self, r, rij):
123
+ # """
124
+ # Generates histogram bins.
125
+
126
+ # This function generates histogram bins based on the provided arrays of
127
+ # radial distances `r` and pair distances `rij`. It calculates which bins
128
+ # each `rij` value contributes to and returns the minimum and maximum
129
+ # bin indices for each pair.
130
+
131
+ # Parameters
132
+ # ----------
133
+ # self : Calculator
134
+ # An instance of the Calculator class for PDF calculation.
135
+ # r : numpy.ndarray
136
+ # Array of radial distances r.
137
+ # rij : numpy.ndarray
138
+ # Array of pair distances r_ij.
139
+
140
+ # Returns
141
+ # -------
142
+ # bin_min : numpy.ndarray
143
+ # Array of minimum bin indices for each rij value.
144
+ # bin_max : numpy.ndarray
145
+ # Array of maximum bin indices for each rij value.
146
+ # """
147
+ # rstep = r[1] - r[0]
148
+ # shift = (rij - r[0]) // rstep + 1
149
+ # rmax_id = r.size - 1
150
+
151
+ # n = self.num_p_peak - 1
152
+ # bin_min = shift - n
153
+ # bin_max = shift + n
154
+
155
+ # bin_min[bin_min > rmax_id] = -1
156
+ # bin_min[bin_min < 0] = 0
157
+ # bin_max[bin_max < 0] = 1
158
+ # return bin_min.flatten(), bin_max.flatten()
159
+
160
+
161
+ # # def grouping(self, rij, cij, sij, ai, aj, r):
162
+ # # """
163
+ # # Groups pair data.
164
+
165
+ # # This function groups pair data based on the atomic pair type (ai, aj) and
166
+ # # the mean-square relative displacement (sij) to enhance the efficiency of
167
+ # # PDF calculation. It organizes the data so that similar calculations can
168
+ # # be performed together.
169
+
170
+ # # Parameters
171
+ # # ----------
172
+ # # self : Calculator
173
+ # # An instance of the Calculator class for PDF calculation.
174
+ # # rij : numpy.ndarray
175
+ # # Array of pair distances r_ij.
176
+ # # cij : numpy.ndarray
177
+ # # Array of coherence lengths c_ij.
178
+ # # sij : numpy.ndarray
179
+ # # Array of mean-square relative displacements u_ij.
180
+ # # ai : numpy.ndarray
181
+ # # Array of indices for atom i.
182
+ # # aj : numpy.ndarray
183
+ # # Array of indices for atom j.
184
+ # # r : numpy.ndarray
185
+ # # Array of radial distances r.
186
+
187
+ # # Returns
188
+ # # -------
189
+ # # grouped_pairs : dict
190
+ # # A dictionary containing the grouped pair data.
191
+ # # Keys include 'rij', 'cij', 'sij', 'bin_min', 'bin_max',
192
+ # # 'same_aij_groups', 'same_uij_groups', and 'unique_aij'.
193
+ # # """
194
+ # # grouped_pairs = {}
195
+
196
+ # # # order the aij array
197
+ # # aij = self.pair["symbol"]
198
+ # # aij = np.sort(aij, axis=-1)
199
+ # # self.pair_name = aij[:, 0].astype(object) + aij[:, 1].astype(object)
200
+ # # self.pair_order = np.argsort(self.pair_name)
201
+ # # aij = aij[self.pair_order]
202
+
203
+ # # unique_aij, index_aij, counts_aij = np.unique(
204
+ # # aij, return_index=True, return_counts=True, axis=0
205
+ # # )
206
+
207
+ # # index_sort = np.argsort(index_aij)
208
+ # # index_aij = index_aij[index_sort]
209
+ # # counts_aij = counts_aij[index_sort]
210
+ # # self.pair_group_bounds = index_aij + counts_aij
211
+
212
+
213
+
214
+ # # rij = self.pairs["distance"][sort]
215
+ # # cij = self.pairs["occ"][sort]
216
+ # # sij = self.pairs["adp"][sort]
217
+
218
+
219
+ # # # find unique aij for scattering_factors
220
+
221
+
222
+ # # rij = np.split(rij, same_aij_groups[:-1])
223
+ # # cij = np.split(cij, same_aij_groups[:-1])
224
+ # # sij = np.split(sij, same_aij_groups[:-1])
225
+
226
+ # # bin_min = np.split(bin_min, same_aij_groups[:-1])
227
+ # # bin_max = np.split(bin_max, same_aij_groups[:-1])
228
+
229
+ # # rearrange the par by sorting them on the basis of simga values (adps)
230
+ # # number_of_unique_aij = len(rij)
231
+ # # same_uij_groups = np.array([])
232
+
233
+ # # for x in range(number_of_unique_aij):
234
+ # # order_in_local_sigma = np.argsort(sij[x])
235
+ # # sorted_local_sigma = sij[x][order_in_local_sigma]
236
+ # # unique_local_sigma, counts = np.unique(
237
+ # # sorted_local_sigma, return_counts=True, axis=0
238
+ # # )
239
+
240
+ # # rij[x] = rij[x][order_in_local_sigma]
241
+ # # cij[x] = cij[x][order_in_local_sigma]
242
+ # # sij[x] = sorted_local_sigma
243
+ # # # bin_min[x] = bin_min[x][order_in_local_sigma]
244
+ # # # bin_max[x] = bin_max[x][order_in_local_sigma]
245
+
246
+ # # same_uij_groups = np.concatenate([same_uij_groups, counts], axis=0)
247
+
248
+ # # rij = np.concatenate(rij, axis=0)
249
+ # # cij = np.concatenate(cij, axis=0)
250
+ # # sij = np.concatenate(sij, axis=0)
251
+ # # bin_min = np.concatenate(bin_min, axis=0)
252
+ # # bin_max = np.concatenate(bin_max, axis=0)
253
+
254
+
255
+
256
+ # # grouped_pairs["rij"] = rij
257
+ # # grouped_pairs["cij"] = cij
258
+ # # grouped_pairs["sij"] = sij
259
+ # # grouped_pairs["bin_min"] = bin_min
260
+ # # grouped_pairs["bin_max"] = bin_max
261
+ # # grouped_pairs["same_aij_groups"] = same_aij_groups
262
+ # # # grouped_pairs["same_uij_groups"] = same_uij_groups
263
+ # # # grouped_pairs["unique_aij"] = unique_aij
264
+
265
+ # # return grouped_pairs
266
+
267
+
268
+ # # def set_r_range(self):
269
+ # # """
270
+ # # Sets the range of radial distances r to be used for calculation.
271
+
272
+ # # This function determines the range of radial distances r to be used for
273
+ # # PDF calculation. The range is calculated based on the specified r range
274
+ # # and the width of the Gaussian function. It also calls the
275
+ # # `calc_simulation_range` function to limit the calculation range.
276
+
277
+ # # Parameters
278
+ # # ----------
279
+ # # self : Calculator
280
+ # # An instance of the Calculator class for PDF calculation.
281
+
282
+ # # Returns
283
+ # # -------
284
+ # # data_in_r_range : dict
285
+ # # A dictionary containing the range of radial distances r to be used
286
+ # # for calculation, along with related pair data.
287
+ # # Keys include 'ai', 'aj', 'rij', 'sij', 'cij', 'r', and 'r_pair'.
288
+ # # """
289
+ # # # calculate evaluation range (from r[0] to r[-1] + gaussian width)
290
+
291
+ # # # data_in_r_range = {}
292
+
293
+ # # # rstep = self.r[1] - self.r[0]
294
+ # # # r_extension = self.num_p_peak / self["qmax"] * 2.0
295
+ # # # r_pair = np.arange(0.0, self.num_p_peak / self["qmax"], rstep)
296
+ # # # r_pair = np.append(-r_pair[:0:-1], r_pair)
297
+
298
+ # # r = np.arange(self.r[0], self.r[-1] + rstep + r_extension, rstep)
299
+
300
+ # # # limit simulation_range
301
+ # # sr = calc_simulation_range(self, r_pair)
302
+
303
+ # # data_in_r_range["ai"] = self.ai[sr]
304
+ # # data_in_r_range["aj"] = self.aj[sr]
305
+ # # data_in_r_range["rij"] = self.rij[sr]
306
+
307
+ # # sij = self.sij * self.peak_width
308
+ # # data_in_r_range["sij"] = sij[sr]
309
+ # # data_in_r_range["cij"] = self.cij[sr]
310
+ # # data_in_r_range["r"] = r
311
+ # # data_in_r_range["r_pair"] = r_pair
312
+
313
+ # # return data_in_r_range
@@ -0,0 +1,60 @@
1
+ # This is for future work
2
+
3
+
4
+ def read_phase_for_epf(self):
5
+ self.read_phase_lattice()
6
+ self.read_phase_shape()
7
+ self.calc_translational_vector()
8
+
9
+
10
+ def calc_gr_epf(self):
11
+ r, gr = self.calc_gr_histogram_for_epf()
12
+ gr *= (self["qmax"] * self["pad"]) / np.pi
13
+
14
+ density = self.calc_density(gr, r)
15
+ gr = self.convolution_with_q(gr, r, self["qmax"])
16
+ self.gr = intp.interp1d(r, gr, fill_value="extrapolate")(self.r)
17
+ self.density = intp.interp1d(r, density, fill_value="extrapolate")(self.r)
18
+
19
+
20
+ def calc_gr_histogram_for_epf(self):
21
+ xyz = self["phase"]["map", "xyz"].reshape(-1, 3)
22
+ xyz = np.dot(self.g, xyz.T).T
23
+
24
+ map = self["phase"]["map", "value"]
25
+ map = map.flatten()
26
+ self.Np = np.sum(map)
27
+
28
+ rstep = self.r[1] - self.r[0]
29
+ r_extension = self.num_p_peak / self["qmax"]
30
+ r = np.arange(0, self.r[-1] + rstep + r_extension, rstep)
31
+
32
+ tvs = self.translational_vectors.reshape(-1, 3)
33
+
34
+ if self["sampling_probability"] != 1.0:
35
+ probability = self["sampling_probability"]
36
+ rand = np.random.rand(map.size)
37
+ use = np.where((rand < probability) | (map > np.amax(map) / 100.0))
38
+ xyz = xyz[use]
39
+ ratio = np.sum(map[use]) / np.sum(map)
40
+ map = map[use]
41
+ # self.par.logger.info("sampling probability: " + str(probability))
42
+
43
+ if self["simulation_type"] == "epf":
44
+ if self["processor_type"] == "cpu":
45
+ from orochi.pdfsim.calculator.epf_cpu import calc_epf_cpu
46
+
47
+ gr = calc_epf_cpu(map, xyz, tvs, r)
48
+ return r, gr / ratio**2.0
49
+
50
+ else:
51
+ from orochi.pdfsim.calculator.epf_gpu import calc_epf_gpu
52
+
53
+ gr = calc_epf_gpu(map, xyz, tvs, r)
54
+ return r, gr / ratio**2.0
55
+
56
+ elif self["simulation_type"] == "partial_epf":
57
+ from orochi.pdfsim.calculator.epf_partial import calc_partial_epf
58
+
59
+ origin = np.dot(self.g, np.array(self["partial_epf_origin"]))
60
+ return r, calc_partial_epf(map, xyz, tvs, r, origin)
@@ -0,0 +1,58 @@
1
+ import numpy as np
2
+
3
+
4
+ def calc_gr_histogram(self):
5
+ """
6
+ Calculates the pair distribution function g(r) histogram using GPU.
7
+
8
+ This function calculates the pair distribution function g(r) histogram
9
+ using GPU acceleration. It performs a direct calculation using CUDA without
10
+ the grouping strategy employed in the CPU version.
11
+
12
+ Parameters
13
+ ----------
14
+ self : Calculator
15
+ An instance of the Calculator class for PDF calculation.
16
+
17
+ Returns
18
+ -------
19
+ r : numpy.ndarray
20
+ Array of radial distances r.
21
+ gr : numpy.ndarray
22
+ The calculated histogram of the pair distribution function g(r).
23
+
24
+ Notes
25
+ -----
26
+ This function performs the following steps:
27
+
28
+ 1. Calculates the radial distances `r` and `r_rij`.
29
+ 2. Calculates the scattering factors using `calc_scattering_factors`.
30
+ 3. Obtains atomic coordinates, translational vectors, occupancies, and
31
+ atomic displacement parameters.
32
+ 4. Calls the CUDA-accelerated `calc_pdf` function to compute the histogram.
33
+ 5. Normalizes the resulting histogram.
34
+ """
35
+ rstep = self.r[1] - self.r[0]
36
+ r_extension = self.num_p_peak / 2.0 / self["qmax"]
37
+ r = np.arange(self.r[0], self.r[-1] + rstep + r_extension, rstep)
38
+
39
+ r_rij = np.arange(0.0, r_extension, rstep)
40
+ r_rij = np.append(-r_rij[:0:-1], r_rij)
41
+
42
+ from ..structure_factor.no_q_depend import calc_scattering_factors
43
+ from .histogram.pdf_no_q_depend_gpu import calc_pdf
44
+
45
+ sf = calc_scattering_factors(self)
46
+
47
+ xyz = self.phase.model["xyz"]
48
+ occ = self.phase.model["occ"]
49
+ adp = self.phase.model["adp"]
50
+ g = self.phase.model["lattice_vector"].T
51
+ xyz = np.dot(g, xyz.T).T
52
+ tvs = self.translational_vectors
53
+
54
+ gr = calc_pdf(xyz, tvs, occ, sf, adp, r, r_rij)
55
+ gr /= r
56
+ gr *= (self["qmax"] * self["pad"]) / np.pi
57
+ gr /= occ.size
58
+ return r, gr