TB2J 0.9.10.1__py3-none-any.whl → 0.9.12.17__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.
Potentially problematic release.
This version of TB2J might be problematic. Click here for more details.
- TB2J/.gitignore +5 -0
- TB2J/Jdownfolder.py +43 -19
- TB2J/MAEGreen.py +78 -60
- TB2J/__init__.py +3 -1
- TB2J/anisotropy.py +2 -2
- TB2J/basis.py +0 -3
- TB2J/contour.py +3 -2
- TB2J/exchange.py +335 -48
- TB2J/exchangeCL2.py +289 -51
- TB2J/exchange_params.py +25 -1
- TB2J/gpaw_wrapper.py +0 -3
- TB2J/green.py +58 -33
- TB2J/interfaces/wannier90_interface.py +4 -4
- TB2J/io_exchange/io_espins.py +276 -0
- TB2J/io_exchange/io_exchange.py +53 -12
- TB2J/io_exchange/io_txt.py +9 -8
- TB2J/io_exchange/io_uppasd.py +0 -1
- TB2J/io_exchange/io_vampire.py +3 -1
- TB2J/magnon/magnon3.py +76 -28
- TB2J/magnon/plot_magnon_dos_cli.py +115 -3
- TB2J/myTB.py +11 -11
- TB2J/pauli.py +32 -2
- TB2J/plot.py +8 -7
- TB2J/rotate_atoms.py +10 -7
- TB2J/scripts/TB2J_downfold.py +97 -0
- TB2J/scripts/TB2J_eigen.py +49 -0
- TB2J/scripts/TB2J_magnon.py +117 -0
- TB2J/scripts/TB2J_magnon2.py +78 -0
- TB2J/scripts/TB2J_magnon_dos.py +5 -0
- TB2J/scripts/TB2J_merge.py +49 -0
- TB2J/scripts/TB2J_plot_magnon_bands.py +22 -0
- TB2J/scripts/TB2J_rotate.py +29 -0
- TB2J/scripts/TB2J_rotateDM.py +21 -0
- TB2J/scripts/__init__.py +0 -0
- TB2J/scripts/abacus2J.py +61 -0
- TB2J/scripts/siesta2J.py +78 -0
- TB2J/scripts/wann2J.py +101 -0
- TB2J/spinham/hamiltonian.py +0 -1
- TB2J/symmetrize_J.py +2 -2
- TB2J/tensor_rotate.py +1 -2
- TB2J/versioninfo.py +3 -0
- TB2J/wannier/w90_tb_parser.py +0 -2
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/METADATA +7 -7
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/RECORD +48 -33
- tb2j-0.9.12.17.dist-info/entry_points.txt +15 -0
- tb2j-0.9.10.1.dist-info/entry_points.txt +0 -16
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/WHEEL +0 -0
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/licenses/LICENSE +0 -0
- {tb2j-0.9.10.1.dist-info → tb2j-0.9.12.17.dist-info}/top_level.txt +0 -0
TB2J/.gitignore
ADDED
TB2J/Jdownfolder.py
CHANGED
|
@@ -35,6 +35,7 @@ class JR_model:
|
|
|
35
35
|
|
|
36
36
|
class JDownfolder:
|
|
37
37
|
def __init__(self, JR, Rlist, iM, iL, qmesh, iso_only=False):
|
|
38
|
+
self.nxyz = 1 if iso_only else 3
|
|
38
39
|
self.model = JR_model(JR, Rlist)
|
|
39
40
|
self.Rlist = Rlist
|
|
40
41
|
self.nR = len(Rlist)
|
|
@@ -46,15 +47,15 @@ class JDownfolder:
|
|
|
46
47
|
self.qmesh = qmesh
|
|
47
48
|
self.qpts = monkhorst_pack(qmesh)
|
|
48
49
|
self.nqpt = len(self.qpts)
|
|
49
|
-
self.nMn = self.nM *
|
|
50
|
-
self.nLn = self.nL *
|
|
50
|
+
self.nMn = self.nM * self.nxyz
|
|
51
|
+
self.nLn = self.nL * self.nxyz
|
|
51
52
|
self.iso_only = iso_only
|
|
52
53
|
|
|
53
54
|
def get_JR(self):
|
|
54
55
|
JR_downfolded = np.zeros((self.nR, self.nMn, self.nMn), dtype=float)
|
|
55
56
|
Jq_downfolded = np.zeros((self.nqpt, self.nMn, self.nMn), dtype=complex)
|
|
56
|
-
self.iMn = ind_to_indn(self.iM, n=
|
|
57
|
-
self.iLn = ind_to_indn(self.iL, n=
|
|
57
|
+
self.iMn = ind_to_indn(self.iM, n=self.nxyz)
|
|
58
|
+
self.iLn = ind_to_indn(self.iL, n=self.nxyz)
|
|
58
59
|
for iq, q in enumerate(self.qpts):
|
|
59
60
|
Jq = self.model.get_Jq(q)
|
|
60
61
|
Jq_downfolded[iq] = self.downfold_oneq(Jq)
|
|
@@ -79,12 +80,13 @@ class PWFDownfolder:
|
|
|
79
80
|
MagnonWrapper,
|
|
80
81
|
)
|
|
81
82
|
|
|
82
|
-
model = MagnonWrapper(JR, Rlist, atoms)
|
|
83
|
+
model = MagnonWrapper(JR, Rlist, atoms, align_evecs=not iso_only)
|
|
83
84
|
wann = MagnonDownfolder(model)
|
|
84
85
|
# Downfold the band structure.
|
|
85
86
|
index_basis = []
|
|
87
|
+
self.nxyz = 1 if iso_only else 3
|
|
86
88
|
for i in iM:
|
|
87
|
-
index_basis += list(range(i *
|
|
89
|
+
index_basis += list(range(i * self.nxyz, i * self.nxyz + self.nxyz))
|
|
88
90
|
params = dict(
|
|
89
91
|
method="projected",
|
|
90
92
|
# method="maxprojected",
|
|
@@ -93,8 +95,10 @@ class PWFDownfolder:
|
|
|
93
95
|
selected_basis=index_basis,
|
|
94
96
|
# anchors={(0, 0, 0): (-1, -2, -3, -4)},
|
|
95
97
|
# anchors={(0, 0, 0): ()},
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
+
# weight_func="Gauss",
|
|
99
|
+
# weight_func_params=(-0.143, 0.04),
|
|
100
|
+
use_proj=True,
|
|
101
|
+
enhance_Amn=0.0,
|
|
98
102
|
)
|
|
99
103
|
params.update(kwargs)
|
|
100
104
|
wann.set_parameters(**params)
|
|
@@ -118,7 +122,7 @@ class PWFDownfolder:
|
|
|
118
122
|
marker="o",
|
|
119
123
|
ax=None,
|
|
120
124
|
savefig="downfold_band.png",
|
|
121
|
-
show=
|
|
125
|
+
show=False,
|
|
122
126
|
)
|
|
123
127
|
self.JR_downfolded = ewf.HwannR
|
|
124
128
|
self.Rlist = ewf.Rlist
|
|
@@ -176,7 +180,19 @@ class JDownfolder_pickle:
|
|
|
176
180
|
self.nsite = self.nM + self.nL
|
|
177
181
|
|
|
178
182
|
def _downfold(self, **kwargs):
|
|
179
|
-
|
|
183
|
+
if self.iso_only:
|
|
184
|
+
JR2 = self.exc.get_full_Jtensor_for_Rlist(
|
|
185
|
+
order="ij", asr=True, DMI=False, Jani=False
|
|
186
|
+
)
|
|
187
|
+
# magmoms = self.exc.magmoms
|
|
188
|
+
# magmoms of magnetic atoms (metal + ligand)
|
|
189
|
+
# mmagmoms = magmoms[self.iM + self.iL]
|
|
190
|
+
# sqrt_magmoms = np.sqrt(np.abs(mmagmoms))
|
|
191
|
+
# magmoms_mat = np.outer(sqrt_magmoms, sqrt_magmoms)
|
|
192
|
+
# JR2 = JR2 / magmoms_mat
|
|
193
|
+
else:
|
|
194
|
+
JR2 = self.exc.get_full_Jtensor_for_Rlist(order="i3j3_2D", asr=True)
|
|
195
|
+
|
|
180
196
|
if self.method.lower() == "lowdin":
|
|
181
197
|
d = JDownfolder(
|
|
182
198
|
JR2,
|
|
@@ -199,6 +215,8 @@ class JDownfolder_pickle:
|
|
|
199
215
|
**kwargs,
|
|
200
216
|
)
|
|
201
217
|
Jd, Rlist = d.get_JR()
|
|
218
|
+
# metal_sqrt_magmoms = np.sqrt(np.abs(self.exc.magmoms[self.iM]))
|
|
219
|
+
# Jd = Jd * np.outer(metal_sqrt_magmoms, metal_sqrt_magmoms)
|
|
202
220
|
return Jd, Rlist
|
|
203
221
|
|
|
204
222
|
def _Jd_to_exchange(self, Jd, Rlist):
|
|
@@ -217,15 +235,21 @@ class JDownfolder_pickle:
|
|
|
217
235
|
for j, jspin in enumerate(self.index_spin):
|
|
218
236
|
if ispin >= 0 and jspin >= 0:
|
|
219
237
|
if not (tuple(R) == (0, 0, 0) and ispin == jspin):
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
238
|
+
if self.iso_only:
|
|
239
|
+
J = Jd[iR, ispin, jspin]
|
|
240
|
+
self.DMIdict = None
|
|
241
|
+
self.Janidict = None
|
|
242
|
+
self.Jdict[(tuple(R), ispin, jspin)] = J.real
|
|
243
|
+
else:
|
|
244
|
+
J33 = Jd[
|
|
245
|
+
iR,
|
|
246
|
+
ispin * 3 : ispin * 3 + 3,
|
|
247
|
+
jspin * 3 : jspin * 3 + 3,
|
|
248
|
+
]
|
|
249
|
+
J, DMI, Jani = decompose_J_tensor(J33)
|
|
250
|
+
self.Jdict[(tuple(R), ispin, jspin)] = J.real
|
|
251
|
+
self.DMIdict[(tuple(R), ispin, jspin)] = DMI.real
|
|
252
|
+
self.Janidict[(tuple(R), ispin, jspin)] = Jani.real
|
|
229
253
|
|
|
230
254
|
io = SpinIO(
|
|
231
255
|
atoms=self.atoms,
|
TB2J/MAEGreen.py
CHANGED
|
@@ -51,7 +51,7 @@ class MAEGreen(ExchangeNCL):
|
|
|
51
51
|
|
|
52
52
|
nangles = len(self.thetas)
|
|
53
53
|
self.es = np.zeros(nangles, dtype=complex)
|
|
54
|
-
self.
|
|
54
|
+
self.es_matrix = np.zeros((nangles, self.natoms, self.natoms), dtype=complex)
|
|
55
55
|
self.es_atom_orb = DefaultDict(lambda: 0)
|
|
56
56
|
|
|
57
57
|
def set_angles_xyz(self):
|
|
@@ -153,9 +153,8 @@ class MAEGreen(ExchangeNCL):
|
|
|
153
153
|
Hsoc_k = self.tbmodel.get_Hk_soc(self.G.kpts)
|
|
154
154
|
na = len(thetas)
|
|
155
155
|
dE_angle = np.zeros(na, dtype=complex)
|
|
156
|
-
|
|
156
|
+
dE_angle_matrix = np.zeros((na, self.natoms, self.natoms), dtype=complex)
|
|
157
157
|
# dE_angle_orbitals = np.zeros((na, self.natoms, self.norb, self.norb), dtype=complex)
|
|
158
|
-
# dE_angle_orbitals = DefaultDict(lambda: 0)
|
|
159
158
|
dE_angle_atom_orb = DefaultDict(lambda: 0)
|
|
160
159
|
for iangle, (theta, phi) in enumerate(zip(thetas, phis)):
|
|
161
160
|
for ik, dHk in enumerate(Hsoc_k):
|
|
@@ -179,23 +178,30 @@ class MAEGreen(ExchangeNCL):
|
|
|
179
178
|
# dE_angle[iangle] += np.trace(GdH@GdH) * self.G.kweights[ik]
|
|
180
179
|
# dE_angle[iangle] += np.trace(GdH@G0K[ik].T.conj()@dHi ) * self.G.kweights[ik]
|
|
181
180
|
dE_angle[iangle] += dG2sum * self.G.kweights[ik]
|
|
181
|
+
|
|
182
|
+
# Calculate atom-atom matrix interactions
|
|
182
183
|
for iatom in range(self.natoms):
|
|
183
184
|
iorb = self.iorb(iatom)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
185
|
+
for jatom in range(self.natoms):
|
|
186
|
+
jorb = self.iorb(jatom)
|
|
187
|
+
# Calculate cross terms between atoms i and j
|
|
188
|
+
dE_ij_orb = dG2[np.ix_(iorb, jorb)] * self.G.kweights[ik]
|
|
189
|
+
dE_ij_orb = (
|
|
190
|
+
dE_ij_orb[::2, ::2]
|
|
191
|
+
+ dE_ij_orb[1::2, 1::2]
|
|
192
|
+
+ dE_ij_orb[1::2, ::2]
|
|
193
|
+
+ dE_ij_orb[::2, 1::2]
|
|
194
|
+
)
|
|
195
|
+
dE_ij = np.sum(dE_ij_orb)
|
|
196
|
+
# Transform to local orbital basis
|
|
197
|
+
mmat_i = self.mmats[iatom]
|
|
198
|
+
mmat_j = self.mmats[jatom]
|
|
199
|
+
dE_ij_orb = mmat_i.T @ dE_ij_orb @ mmat_j
|
|
200
|
+
dE_angle_matrix[iangle, iatom, jatom] += dE_ij
|
|
201
|
+
# Store orbital-resolved data for diagonal terms
|
|
202
|
+
if iatom == jatom:
|
|
203
|
+
dE_angle_atom_orb[(iangle, iatom)] += dE_ij_orb
|
|
204
|
+
return dE_angle, dE_angle_matrix, dE_angle_atom_orb
|
|
199
205
|
|
|
200
206
|
def get_perturbed_R(self, e, thetas, phis):
|
|
201
207
|
self.tbmodel.set_so_strength(0.0)
|
|
@@ -233,16 +239,16 @@ class MAEGreen(ExchangeNCL):
|
|
|
233
239
|
npole = len(self.contour.path)
|
|
234
240
|
results = map(func, tqdm.tqdm(self.contour.path, total=npole))
|
|
235
241
|
for i, result in enumerate(results):
|
|
236
|
-
dE_angle,
|
|
242
|
+
dE_angle, dE_angle_matrix, dE_angle_atom_orb = result
|
|
237
243
|
self.es += dE_angle * self.contour.weights[i]
|
|
238
|
-
self.
|
|
244
|
+
self.es_matrix += dE_angle_matrix * self.contour.weights[i]
|
|
239
245
|
for key, value in dE_angle_atom_orb.items():
|
|
240
246
|
self.es_atom_orb[key] += (
|
|
241
247
|
dE_angle_atom_orb[key] * self.contour.weights[i]
|
|
242
248
|
)
|
|
243
249
|
|
|
244
250
|
self.es = -np.imag(self.es) / (2 * np.pi)
|
|
245
|
-
self.
|
|
251
|
+
self.es_matrix = -np.imag(self.es_matrix) / (2 * np.pi)
|
|
246
252
|
for key, value in self.es_atom_orb.items():
|
|
247
253
|
self.es_atom_orb[key] = -np.imag(value) / (2 * np.pi)
|
|
248
254
|
|
|
@@ -260,6 +266,7 @@ class MAEGreen(ExchangeNCL):
|
|
|
260
266
|
Path(output_path).mkdir(exist_ok=True)
|
|
261
267
|
fname = f"{output_path}/MAE.dat"
|
|
262
268
|
fname_orb = f"{output_path}/MAE_orb.dat"
|
|
269
|
+
fname_matrix = f"{output_path}/MAE_matrix.dat"
|
|
263
270
|
# fname_tensor = f"{output_path}/MAE_tensor.dat"
|
|
264
271
|
# if figure3d is not None:
|
|
265
272
|
# fname_fig3d = f"{output_path}/{figure3d}"
|
|
@@ -270,24 +277,32 @@ class MAEGreen(ExchangeNCL):
|
|
|
270
277
|
if with_eigen:
|
|
271
278
|
fname_eigen = f"{output_path}/MAE_eigen.dat"
|
|
272
279
|
with open(fname_eigen, "w") as f:
|
|
273
|
-
f.write("# theta, phi, MAE(total)
|
|
274
|
-
for i, (theta, phi, e
|
|
275
|
-
zip(self.thetas, self.phis, self.es2
|
|
280
|
+
f.write("# theta, phi, MAE(total) Unit: meV\n")
|
|
281
|
+
for i, (theta, phi, e) in enumerate(
|
|
282
|
+
zip(self.thetas, self.phis, self.es2)
|
|
276
283
|
):
|
|
277
|
-
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}
|
|
278
|
-
for ea in es:
|
|
279
|
-
f.write(f"{ea*1e3:.8f} ")
|
|
280
|
-
f.write("\n")
|
|
284
|
+
f.write(f"{theta:.5f} {phi:.5f} {e*1e3:.8f}\n")
|
|
281
285
|
|
|
282
286
|
with open(fname, "w") as f:
|
|
283
|
-
f.write("# theta (rad), phi(rad), MAE(total)
|
|
284
|
-
for i, (theta, phi, e
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
287
|
+
f.write("# theta (rad), phi(rad), MAE(total) Unit: meV\n")
|
|
288
|
+
for i, (theta, phi, e) in enumerate(zip(self.thetas, self.phis, self.es)):
|
|
289
|
+
f.write(f"{theta%np.pi:.5f} {phi%(2*np.pi):.5f} {e*1e3:.8f}\n")
|
|
290
|
+
|
|
291
|
+
# Write matrix data to MAE_matrix.dat
|
|
292
|
+
with open(fname_matrix, "w") as fmat:
|
|
293
|
+
fmat.write("# MAE atom-atom interaction matrices\n")
|
|
294
|
+
fmat.write("# Format: angle_index theta phi atom_i atom_j MAE_ij(meV)\n")
|
|
295
|
+
fmat.write("# Units: theta and phi in radians, MAE in meV\n")
|
|
296
|
+
for iangle, (theta, phi) in enumerate(zip(self.thetas, self.phis)):
|
|
297
|
+
for iatom in range(self.natoms):
|
|
298
|
+
for jatom in range(self.natoms):
|
|
299
|
+
mae_ij = (
|
|
300
|
+
self.es_matrix[iangle, iatom, jatom] * 1e3
|
|
301
|
+
) # Convert to meV
|
|
302
|
+
fmat.write(
|
|
303
|
+
f"{iangle:4d} {theta:.5f} {phi:.5f} {iatom:4d} {jatom:4d} {mae_ij:.8f}\n"
|
|
304
|
+
)
|
|
305
|
+
fmat.write("\n") # Empty line between angles for readability
|
|
291
306
|
|
|
292
307
|
# self.ani = self.fit_anisotropy_tensor()
|
|
293
308
|
# with open(fname_tensor, "w") as f:
|
|
@@ -313,34 +328,37 @@ class MAEGreen(ExchangeNCL):
|
|
|
313
328
|
for orb in self.orbital_names[iatom]:
|
|
314
329
|
f.write(f"{orb} ")
|
|
315
330
|
f.write("\n")
|
|
316
|
-
for i, (theta, phi, e
|
|
317
|
-
zip(self.thetas, self.phis, self.es, self.es_atom)
|
|
318
|
-
):
|
|
331
|
+
for i, (theta, phi, e) in enumerate(zip(self.thetas, self.phis, self.es)):
|
|
319
332
|
f.write("-" * 60 + "\n")
|
|
320
333
|
f.write(f"Angle {i:03d}: theta={theta:.5f} phi={phi:.5f} \n ")
|
|
321
334
|
f.write(f"E: {e*1e3:.8f} \n")
|
|
322
|
-
for iatom
|
|
323
|
-
f.write(f"Atom {iatom:03d}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
eorb_diff = eorb - self.es_atom_orb[(0, iatom)]
|
|
335
|
-
f.write("Diference to the first angle: ")
|
|
336
|
-
f.write(
|
|
337
|
-
np.array2string(
|
|
338
|
-
eorb_diff * 1e3,
|
|
339
|
-
precision=4,
|
|
340
|
-
separator=",",
|
|
341
|
-
suppress_small=True,
|
|
335
|
+
for iatom in range(self.natoms):
|
|
336
|
+
f.write(f"Atom {iatom:03d} orbital matrix:\n")
|
|
337
|
+
if (i, iatom) in self.es_atom_orb:
|
|
338
|
+
eorb = self.es_atom_orb[(i, iatom)]
|
|
339
|
+
# write numpy matrix to file
|
|
340
|
+
f.write(
|
|
341
|
+
np.array2string(
|
|
342
|
+
eorb * 1e3,
|
|
343
|
+
precision=4,
|
|
344
|
+
separator=",",
|
|
345
|
+
suppress_small=True,
|
|
346
|
+
)
|
|
342
347
|
)
|
|
343
|
-
|
|
348
|
+
f.write("\n")
|
|
349
|
+
|
|
350
|
+
if (0, iatom) in self.es_atom_orb:
|
|
351
|
+
eorb_diff = eorb - self.es_atom_orb[(0, iatom)]
|
|
352
|
+
f.write("Difference to the first angle: ")
|
|
353
|
+
f.write(
|
|
354
|
+
np.array2string(
|
|
355
|
+
eorb_diff * 1e3,
|
|
356
|
+
precision=4,
|
|
357
|
+
separator=",",
|
|
358
|
+
suppress_small=True,
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
f.write("\n")
|
|
344
362
|
f.write("\n")
|
|
345
363
|
|
|
346
364
|
def run(self, output_path="TB2J_anisotropy", with_eigen=False):
|
TB2J/__init__.py
CHANGED
TB2J/anisotropy.py
CHANGED
|
@@ -339,8 +339,8 @@ class Anisotropy:
|
|
|
339
339
|
# print(X_max, Y_max, X_min, Y_min)
|
|
340
340
|
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
|
341
341
|
# ax.scatter(X_min, Y_min, color="b", marker="o")
|
|
342
|
-
ax.set_xlabel("$\theta$ (degree)")
|
|
343
|
-
ax.set_ylabel("$\phi$ degree")
|
|
342
|
+
ax.set_xlabel(r"$\theta$ (degree)")
|
|
343
|
+
ax.set_ylabel(r"$\phi$ degree")
|
|
344
344
|
# ax.scatter(X_max, Y_max, color="r", marker="o")
|
|
345
345
|
# ax.scatter(X_min, Y_min, color="r", marker="o")
|
|
346
346
|
|
TB2J/basis.py
CHANGED
TB2J/contour.py
CHANGED
|
@@ -27,8 +27,9 @@ class Contour:
|
|
|
27
27
|
integrate f along the path
|
|
28
28
|
"""
|
|
29
29
|
ret = 0
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
ret = np.einsum("i...,i->...", values, self.weights)
|
|
31
|
+
# for i in range(len(values)):
|
|
32
|
+
# ret += values[i] * self.weights[i]
|
|
32
33
|
return ret
|
|
33
34
|
|
|
34
35
|
def build_path_semicircle(self, npoints, endpoint=True):
|