yu-mcal 0.1.6__py3-none-any.whl → 0.2.1__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.
- mcal/mcal.py +131 -18
- {yu_mcal-0.1.6.dist-info → yu_mcal-0.2.1.dist-info}/METADATA +11 -1
- {yu_mcal-0.1.6.dist-info → yu_mcal-0.2.1.dist-info}/RECORD +6 -6
- {yu_mcal-0.1.6.dist-info → yu_mcal-0.2.1.dist-info}/WHEEL +0 -0
- {yu_mcal-0.1.6.dist-info → yu_mcal-0.2.1.dist-info}/entry_points.txt +0 -0
- {yu_mcal-0.1.6.dist-info → yu_mcal-0.2.1.dist-info}/licenses/LICENSE +0 -0
mcal/mcal.py
CHANGED
|
@@ -6,6 +6,9 @@ from pathlib import Path
|
|
|
6
6
|
from time import time
|
|
7
7
|
from typing import Dict, List, Literal, Optional, Tuple, Union
|
|
8
8
|
|
|
9
|
+
import matplotlib
|
|
10
|
+
matplotlib.use('Agg')
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
9
12
|
import numpy as np
|
|
10
13
|
from numpy.typing import NDArray
|
|
11
14
|
from tcal import Tcal
|
|
@@ -33,40 +36,41 @@ def main():
|
|
|
33
36
|
--------
|
|
34
37
|
Basic usage:
|
|
35
38
|
- Calculate p-type mobility for xxx crystal\n
|
|
36
|
-
$
|
|
39
|
+
$ mcal xxx.cif p
|
|
37
40
|
|
|
38
41
|
- Calculate n-type mobility for xxx crystal\n
|
|
39
|
-
$
|
|
42
|
+
$ mcal xxx.cif n
|
|
40
43
|
|
|
41
44
|
With resource options:
|
|
42
45
|
- Use 8 CPUs and 16GB memory\n
|
|
43
|
-
$
|
|
46
|
+
$ mcal xxx.cif p -c 8 -m 16
|
|
44
47
|
|
|
45
48
|
- Use different calculation method (default is B3LYP/6-31G(d,p))\n
|
|
46
|
-
$
|
|
49
|
+
$ mcal xxx.cif p -M "B3LYP/6-311G(d,p)"
|
|
47
50
|
|
|
48
51
|
High-precision calculation:
|
|
49
52
|
- Calculate all transfer integrals without speedup using moment of inertia and distance between centers of weight\n
|
|
50
|
-
$
|
|
51
|
-
|
|
52
|
-
- Expand calculation range to 3x3x3 supercell\n
|
|
53
|
-
$ python hop_mcal.py xxx.cif p --cellsize 1
|
|
53
|
+
$ mcal xxx.cif p --fullcal
|
|
54
54
|
|
|
55
55
|
- Expand calculation range to 5x5x5 supercell to widen transfer integral calculation range\n
|
|
56
|
-
$
|
|
56
|
+
$ mcal xxx.cif p --cellsize 2
|
|
57
57
|
|
|
58
58
|
Resume and save results:
|
|
59
59
|
- Resume from existing calculations\n
|
|
60
|
-
$
|
|
60
|
+
$ mcal xxx.cif p --resume
|
|
61
61
|
|
|
62
62
|
- Save results to pickle file\n
|
|
63
|
-
$
|
|
63
|
+
$ mcal xxx.cif p --pickle
|
|
64
64
|
|
|
65
65
|
- Read results from existing pickle file\n
|
|
66
|
-
$
|
|
66
|
+
$ mcal xxx_result.pkl p -rp
|
|
67
67
|
|
|
68
68
|
- Read results from existing log files without running Gaussian\n
|
|
69
|
-
$
|
|
69
|
+
$ mcal xxx.cif p -r
|
|
70
|
+
|
|
71
|
+
Plot mobility tensor in 2D plane:
|
|
72
|
+
- Plot mobility tensor in 2D plane (Examples: ab, ac, ba, bc, ca, cb (default is ab))\n
|
|
73
|
+
$ python hop_mcal.py xxx.cif p --plot-plane ab
|
|
70
74
|
|
|
71
75
|
Compare calculation methods:
|
|
72
76
|
- Compare results using kinetic Monte Carlo and ODE methods\n
|
|
@@ -119,6 +123,13 @@ def main():
|
|
|
119
123
|
help='use Ordinary Differential Equation method to calculate diffusion coefficient',
|
|
120
124
|
action='store_true',
|
|
121
125
|
)
|
|
126
|
+
parser.add_argument(
|
|
127
|
+
'--plot-plane',
|
|
128
|
+
help='plot mobility tensor in 2D plane (Examples: ab, ac, ba, bc, ca, cb (default is ab))',
|
|
129
|
+
type=str,
|
|
130
|
+
default=None,
|
|
131
|
+
choices=['ab', 'ac', 'ba', 'bc', 'ca', 'cb'],
|
|
132
|
+
)
|
|
122
133
|
parser.add_argument(
|
|
123
134
|
'--resume',
|
|
124
135
|
help='resume calculation',
|
|
@@ -140,11 +151,11 @@ def main():
|
|
|
140
151
|
cif_path_without_ext = f'{directory}/{filename}'
|
|
141
152
|
|
|
142
153
|
print('----------------------------------------')
|
|
143
|
-
print(' mcal 0.1
|
|
154
|
+
print(' mcal 0.2.1 (2026/01/29) by Matsui Lab. ')
|
|
144
155
|
print('----------------------------------------')
|
|
145
156
|
|
|
146
157
|
if args.read_pickle:
|
|
147
|
-
read_pickle(args.file)
|
|
158
|
+
read_pickle(args.file, args.plot_plane)
|
|
148
159
|
exit()
|
|
149
160
|
|
|
150
161
|
print(f'\nCalculate as {args.osc_type}-type organic semiconductor.')
|
|
@@ -352,6 +363,14 @@ def main():
|
|
|
352
363
|
'mobility_vector': vector
|
|
353
364
|
}, f)
|
|
354
365
|
|
|
366
|
+
if args.plot_plane:
|
|
367
|
+
plot_mobility_2d(
|
|
368
|
+
Path(f'{cif_path_without_ext}_result.pkl'),
|
|
369
|
+
mu,
|
|
370
|
+
cif_reader.lattice,
|
|
371
|
+
args.plot_plane
|
|
372
|
+
)
|
|
373
|
+
|
|
355
374
|
Tcal.print_timestamp()
|
|
356
375
|
end_time = time()
|
|
357
376
|
elapsed_time = end_time - start_time
|
|
@@ -720,6 +739,82 @@ def create_ti_gjf(
|
|
|
720
739
|
gjf_maker.export_gjf(file_name=gjf_basename, save_dir=save_dir)
|
|
721
740
|
|
|
722
741
|
|
|
742
|
+
def plot_mobility_2d(
|
|
743
|
+
save_path: Path,
|
|
744
|
+
mobility_tensor: NDArray[np.float64],
|
|
745
|
+
lattice: NDArray[np.float64],
|
|
746
|
+
plane: Literal['ab', 'ac', 'ba', 'bc', 'ca', 'cb'] = 'ab'
|
|
747
|
+
) -> None:
|
|
748
|
+
"""Plot mobility tensor in 2D plane.
|
|
749
|
+
|
|
750
|
+
Parameters
|
|
751
|
+
----------
|
|
752
|
+
save_path : Path
|
|
753
|
+
Path to save the plot
|
|
754
|
+
mobility_tensor : NDArray[np.float64]
|
|
755
|
+
Mobility tensor
|
|
756
|
+
lattice : NDArray[np.float64]
|
|
757
|
+
Lattice vectors [Å]
|
|
758
|
+
plane : Literal['ab', 'ac', 'ba', 'bc', 'ca', 'cb']
|
|
759
|
+
Plane to plot, by default 'ab'
|
|
760
|
+
"""
|
|
761
|
+
print(f"Plot mobility in {plane} plane.")
|
|
762
|
+
angle_list = np.arange(0, 360, 1)
|
|
763
|
+
mobility_values = []
|
|
764
|
+
|
|
765
|
+
a_vec = lattice[0]
|
|
766
|
+
b_vec = lattice[1]
|
|
767
|
+
c_vec = lattice[2]
|
|
768
|
+
if plane == 'ab':
|
|
769
|
+
v1, v2, = a_vec, b_vec
|
|
770
|
+
elif plane == 'ba':
|
|
771
|
+
v1, v2, = b_vec, a_vec
|
|
772
|
+
elif plane == 'bc':
|
|
773
|
+
v1, v2, = b_vec, c_vec
|
|
774
|
+
elif plane == 'cb':
|
|
775
|
+
v1, v2, = c_vec, b_vec
|
|
776
|
+
elif plane == 'ac':
|
|
777
|
+
v1, v2, = a_vec, c_vec
|
|
778
|
+
elif plane == 'ca':
|
|
779
|
+
v1, v2 = c_vec, a_vec
|
|
780
|
+
|
|
781
|
+
# Angle between the two specified crystal axes
|
|
782
|
+
second_axis_angle = np.rad2deg(np.arccos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))))
|
|
783
|
+
print('Crystal axis directions in the plotted plane:')
|
|
784
|
+
print(f'{plane[0]}-axis: 0.0 deg')
|
|
785
|
+
print(f'{plane[1]}-axis: {second_axis_angle:.1f} deg')
|
|
786
|
+
print()
|
|
787
|
+
|
|
788
|
+
# Gram–Schmidt orthonormalization
|
|
789
|
+
e1 = v1 / np.linalg.norm(v1)
|
|
790
|
+
e2 = v2 - np.dot(v2, e1) * e1
|
|
791
|
+
e2 = e2 / np.linalg.norm(e2)
|
|
792
|
+
|
|
793
|
+
for angle in angle_list:
|
|
794
|
+
phi = np.deg2rad(angle)
|
|
795
|
+
direction = np.cos(phi) * e1 + np.sin(phi) * e2
|
|
796
|
+
mobility_value = direction @ mobility_tensor @ direction
|
|
797
|
+
mobility_values.append(mobility_value)
|
|
798
|
+
|
|
799
|
+
plt.rcParams['font.size'] = 12
|
|
800
|
+
width_cm, height_cm = 20, 8
|
|
801
|
+
width_inch, height_inch = width_cm / 2.54, height_cm / 2.54
|
|
802
|
+
|
|
803
|
+
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, tight_layout=True, figsize=(width_inch, height_inch))
|
|
804
|
+
ax.set_theta_zero_location('E')
|
|
805
|
+
ax.grid(True, linestyle='--', linewidth=0.5)
|
|
806
|
+
ax.plot(np.deg2rad(angle_list), mobility_values, linewidth=2)
|
|
807
|
+
|
|
808
|
+
ax.set_rlim(bottom=0)
|
|
809
|
+
ax.set_xticks(np.arange(0, 2*np.pi, np.pi/6))
|
|
810
|
+
ax.tick_params(axis="x", pad=5)
|
|
811
|
+
ax.set_ylabel(R'Mobility [$\mathrm{cm}^2 \mathrm{V}^{-1} \mathrm{s}^{-1}$]')
|
|
812
|
+
ax.yaxis.set_label_coords(-0.2, 0.5)
|
|
813
|
+
ax.set_rlabel_position(90)
|
|
814
|
+
plt.savefig(save_path.parent / f"{save_path.stem}_{plane}.png", dpi=300, bbox_inches='tight')
|
|
815
|
+
plt.close()
|
|
816
|
+
|
|
817
|
+
|
|
723
818
|
def print_mobility(value: NDArray[np.float64], vector: NDArray[np.float64], sim_type: Literal['MC', 'ODE'] = ''):
|
|
724
819
|
"""Print mobility and mobility vector
|
|
725
820
|
|
|
@@ -811,14 +906,24 @@ def print_transfer_integral(osc_type: Literal['p', 'n'], transfer: float):
|
|
|
811
906
|
print(f'{mol_orb[osc_type]}: {transfer:12.6g} eV\n')
|
|
812
907
|
|
|
813
908
|
|
|
814
|
-
def read_pickle(
|
|
909
|
+
def read_pickle(
|
|
910
|
+
file_name: str,
|
|
911
|
+
plot_plane: Optional[Literal['ab', 'ac', 'ba', 'bc', 'ca', 'cb']] = None
|
|
912
|
+
) -> None:
|
|
913
|
+
"""Read pickle file and plot mobility tensor in 2D plane.
|
|
914
|
+
|
|
915
|
+
Parameters
|
|
916
|
+
----------
|
|
917
|
+
file_name : str
|
|
918
|
+
Path to the pickle file
|
|
919
|
+
plot_plane : Optional[Literal['ab', 'ac', 'ba', 'bc', 'ca', 'cb']]
|
|
920
|
+
Plane to plot, by default None
|
|
921
|
+
"""
|
|
815
922
|
print(f'\nInput File Name: {file_name}')
|
|
816
923
|
|
|
817
924
|
with open(file_name, 'rb') as f:
|
|
818
925
|
results = pickle.load(f)
|
|
819
926
|
|
|
820
|
-
# print(results)
|
|
821
|
-
|
|
822
927
|
print(f'\nCalculate as {results["osc_type"]}-type organic semiconductor.')
|
|
823
928
|
|
|
824
929
|
print_reorg_energy(results['osc_type'], results['reorganization'])
|
|
@@ -834,6 +939,14 @@ def read_pickle(file_name: str):
|
|
|
834
939
|
|
|
835
940
|
print_mobility(results['mobility_value'], results['mobility_vector'])
|
|
836
941
|
|
|
942
|
+
if plot_plane:
|
|
943
|
+
plot_mobility_2d(
|
|
944
|
+
Path(file_name).with_suffix(''),
|
|
945
|
+
results['mobility_tensor'],
|
|
946
|
+
results['lattice'],
|
|
947
|
+
plot_plane,
|
|
948
|
+
)
|
|
949
|
+
|
|
837
950
|
|
|
838
951
|
class OSCTypeError(Exception):
|
|
839
952
|
"""Exception for semiconductor type"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yu-mcal
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Program for the calculation of mobility tensor for organic semiconductor crystals
|
|
5
5
|
Author: Koki Ozawa
|
|
6
6
|
Author-email: Hiroyuki Matsui <h-matsui@yz.yamagata-u.ac.jp>
|
|
@@ -40,6 +40,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
40
40
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
41
41
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
42
42
|
Requires-Python: >=3.9
|
|
43
|
+
Requires-Dist: matplotlib>=3.9.4
|
|
43
44
|
Requires-Dist: numpy>=2.0.2
|
|
44
45
|
Requires-Dist: pandas>=2.3.3
|
|
45
46
|
Requires-Dist: yu-tcal==3.1.0
|
|
@@ -57,6 +58,7 @@ Description-Content-Type: text/markdown
|
|
|
57
58
|
* Python 3.9 or newer
|
|
58
59
|
* NumPy
|
|
59
60
|
* Pandas
|
|
61
|
+
* Matplotlib
|
|
60
62
|
* yu-tcal==3.1.0
|
|
61
63
|
* Gaussian 09 or 16
|
|
62
64
|
|
|
@@ -157,6 +159,14 @@ Specify the number of unit cells to expand in each direction around the central
|
|
|
157
159
|
Save calculation results to a pickle file.
|
|
158
160
|
- **Example**: `mcal xxx.cif p -p`
|
|
159
161
|
|
|
162
|
+
#### `--plot-plane <plane>`
|
|
163
|
+
Plot mobility tensor as a 2D polar plot on specified crystallographic plane.
|
|
164
|
+
- **Available planes**: `ab`, `ac`, `ba`, `bc`, `ca`, `cb`
|
|
165
|
+
- **Default**: None (no plot generated)
|
|
166
|
+
- **Examples**:
|
|
167
|
+
- `mcal xxx.cif p --plot-plane ab` (plot on ab-plane)
|
|
168
|
+
- `mcal xxx.cif p --plot-plane bc` (plot on bc-plane)
|
|
169
|
+
|
|
160
170
|
### Diffusion Coefficient Calculation Methods
|
|
161
171
|
|
|
162
172
|
#### `--mc`
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
mcal/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
2
|
-
mcal/mcal.py,sha256=
|
|
2
|
+
mcal/mcal.py,sha256=1XkovOZTkSlBlyOuWjZ85BTU2VvU30gU5Zf0hgfZk_o,32816
|
|
3
3
|
mcal/calculations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
mcal/calculations/hopping_mobility_model.py,sha256=eD9doesa1yVDQxzBYW0N41OyjikZb77S69I_mIMbL2g,13180
|
|
5
5
|
mcal/calculations/rcal.py,sha256=CH3iV18KTM8xU7M7zKR3e1m67GbJLH8zi0j50TsUXLE,13500
|
|
@@ -8,8 +8,8 @@ mcal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
8
8
|
mcal/utils/cif_reader.py,sha256=QAV6xXMd3nfKLpJqBncA6fbGJ5kgYKDeKIx-sK_4P_M,24532
|
|
9
9
|
mcal/utils/gaus_log_reader.py,sha256=nNIgBae9hRUgpmNF7eIC5LOENSo6NQmuckMM4A3HAa8,3159
|
|
10
10
|
mcal/utils/gjf_maker.py,sha256=Kkh_gNcifFfhTikZar6SzoNJ7AyEBiCBXJTQkHxHX-0,8193
|
|
11
|
-
yu_mcal-0.1.
|
|
12
|
-
yu_mcal-0.1.
|
|
13
|
-
yu_mcal-0.1.
|
|
14
|
-
yu_mcal-0.1.
|
|
15
|
-
yu_mcal-0.1.
|
|
11
|
+
yu_mcal-0.2.1.dist-info/METADATA,sha256=OtLCHoL8h1mqApWdTlB9-34BWqey1Spgcp8N-0m6YPA,8270
|
|
12
|
+
yu_mcal-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
13
|
+
yu_mcal-0.2.1.dist-info/entry_points.txt,sha256=_0xZR3t9qvFSd9L6Iot03NixVLxXioEY19L6w3Fs1Ew,40
|
|
14
|
+
yu_mcal-0.2.1.dist-info/licenses/LICENSE,sha256=JP8vm7gYE73jLgnMFTOLNo_RnH88RrB4Goyh7H_muto,1072
|
|
15
|
+
yu_mcal-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|