yu-mcal 0.1.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.
@@ -0,0 +1,91 @@
1
+ """Gaussian log file reader (2025/06/21)"""
2
+ import os
3
+ from pathlib import Path
4
+
5
+
6
+ def check_normal_termination(log_file: str) -> bool:
7
+ """Check if the calculation terminated normally.
8
+
9
+ Parameters
10
+ ----------
11
+ log_file : str
12
+ Path to the log file
13
+
14
+ Returns
15
+ -------
16
+ bool
17
+ True if the calculation terminated normally, False otherwise
18
+ """
19
+ if not Path(log_file).exists():
20
+ return False
21
+
22
+ with FileReader(log_file) as f:
23
+ line = f.reversed_readline()
24
+ if 'Normal termination' in line:
25
+ return True
26
+ else:
27
+ return False
28
+
29
+
30
+ class FileReader:
31
+ """File reader that reads line by line from the end.
32
+
33
+ Examples
34
+ --------
35
+ >>> with FileReader('sample.txt') as f:
36
+ ... while True:
37
+ ... line = f.reversed_readline()
38
+ ... if not line:
39
+ ... break
40
+ ... print(line)
41
+ """
42
+ def __init__(self, file_path, buffer_size=8192):
43
+ self.buffer_size = buffer_size
44
+ self.file = open(file_path, 'rb')
45
+ # ファイルポインタをファイルの末尾に移動
46
+ self.file.seek(0, os.SEEK_END)
47
+ self.file_size = self.file.tell()
48
+ # 最後のブロックの終了位置をファイルサイズに設定
49
+ self.reversed_block_end = self.file_size
50
+ # 最後のブロックの開始位置を計算(ファイル末尾からバッファサイズ分前、またはファイル先頭)
51
+ self.reversed_block_start = max(0, self.reversed_block_end - self.buffer_size)
52
+ self.lines = []
53
+
54
+ def __enter__(self):
55
+ return self
56
+
57
+ def __exit__(self, exc_type, exc_value, traceback):
58
+ self.close()
59
+
60
+ def close(self):
61
+ self.file.close()
62
+
63
+ def reversed_readline(self):
64
+ if not self.lines and self.reversed_block_end - self.reversed_block_start != 0:
65
+ # ファイルポインタを現在のブロックの開始位置に設定
66
+ self.file.seek(self.reversed_block_start)
67
+
68
+ block = self.file.read(self.reversed_block_end - self.reversed_block_start)
69
+ lines = block.splitlines(keepends=True)
70
+
71
+ # 現在のブロックがファイルの最初のブロックの場合
72
+ if self.reversed_block_start == 0:
73
+ # ブロックの終了位置を開始位置に設定して次の読み取りを防ぐ
74
+ self.reversed_block_end = self.reversed_block_start
75
+ else:
76
+ # 次のブロックの終了位置を更新(現在のブロックの最初の行の長さを加算)
77
+ self.reversed_block_end = max(0, self.reversed_block_start + len(lines[0]))
78
+
79
+ self.reversed_block_start = max(0, self.reversed_block_end - self.buffer_size)
80
+
81
+ # 末尾のブロックの場合、全行を読み取る
82
+ if self.reversed_block_end == 0:
83
+ self.lines = lines
84
+ else:
85
+ self.lines = lines[1:]
86
+
87
+ return self.lines.pop().decode('utf-8')
88
+ elif self.lines:
89
+ return self.lines.pop().decode('utf-8')
90
+ else:
91
+ return None
@@ -0,0 +1,267 @@
1
+ """ GjfMaker beta (2025/08/18)"""
2
+ import os
3
+ import warnings
4
+ from pathlib import Path
5
+ from typing import List, Optional, Tuple
6
+
7
+ import pandas as pd
8
+
9
+
10
+ class GjfMaker:
11
+ parent_dir = Path(os.path.abspath(__file__)).parent.parent
12
+ ELEMENT_PROP = pd.read_csv(f'{parent_dir}/constants/element_properties.csv')
13
+ ELEMENTS_NUM = ELEMENT_PROP[['symbol', 'number']].set_index('symbol').to_dict()['number']
14
+
15
+ def __init__(self, remove_radical_flag: bool = False) -> None:
16
+ """Initialize the GjfMaker class.
17
+
18
+ Parameters
19
+ ----------
20
+ remove_radical_flag : bool
21
+ If True, the radical is removed, by default False.
22
+ Not recommended to use this flag.
23
+ """
24
+ self.remove_radical_flag = remove_radical_flag
25
+
26
+ self._link_dict = {}
27
+ self._link_num = 0
28
+ self._cpu_num = '%NProcShared=9\n'
29
+ self._mem_num = '%Mem=40GB\n'
30
+ self._is_chk_file = False
31
+ self._is_rwf_file = False
32
+ self.is_detail = False
33
+ self._function = '# B3LYP/6-31G(d,p)\n'
34
+ self._root = []
35
+ self._title = '\nDefalut Title\n'
36
+ self._symbols = []
37
+ self._charge_spin = ''
38
+ self._coordinates = []
39
+
40
+ self._root_space = ' '
41
+
42
+ def add_link(self) -> None:
43
+ """Add the link of the gjf file."""
44
+ self.create_chk_file()
45
+ self._link_dict[self._link_num] = [self._cpu_num, self._mem_num, self._function, self._root]
46
+ self._link_num += 1
47
+ self._root = ['Geom=AllCheck\n', 'Guess=Read\n']
48
+
49
+ def add_root(self, root: str) -> None:
50
+ """Add the root of the gjf file."""
51
+ if root[0] == '#':
52
+ root = root[1:]
53
+ self._root.append(root + '\n')
54
+
55
+ def create_chk_file(self) -> None:
56
+ """Create the chk file."""
57
+ self._is_chk_file = True
58
+
59
+ def create_rwf_file(self) -> None:
60
+ """Create the rwf file."""
61
+ self._is_rwf_file = True
62
+
63
+ def export_gjf(
64
+ self,
65
+ file_name: str,
66
+ save_dir: str = '.',
67
+ chk_rwf_name: Optional[str] = None
68
+ ) -> None:
69
+ """Export the gjf file.
70
+
71
+ Parameters
72
+ ----------
73
+ file_name : str
74
+ Name of the gjf file.
75
+ save_dir : str
76
+ Directory to save the gjf file.
77
+ chk_rwf_name : Optional[str]
78
+ Name of the chk or rwf file.
79
+ """
80
+ if self.remove_radical_flag and self._check_radical():
81
+ print('This molecule is radical')
82
+ return
83
+
84
+ os.makedirs(save_dir, exist_ok=True)
85
+
86
+ self._link_dict[self._link_num] = [self._cpu_num, self._mem_num, self._function, self._root]
87
+
88
+ if self._is_chk_file:
89
+ if chk_rwf_name:
90
+ self._chk_file = f'%Chk={chk_rwf_name}.chk\n'
91
+ else:
92
+ self._chk_file = f'%Chk={save_dir}/{file_name}.chk\n'
93
+ else:
94
+ self._chk_file = ''
95
+
96
+ if self._is_rwf_file:
97
+ if chk_rwf_name:
98
+ self._rwf_file = f'%RWF={chk_rwf_name}.rwf\n'
99
+ else:
100
+ self._rwf_file = f'%RWF={save_dir}/{file_name}.rwf\n'
101
+ else:
102
+ self._rwf_file = ''
103
+
104
+ with open(f'{save_dir}/{file_name}.gjf', 'w') as f:
105
+ for i in range(self._link_num+1):
106
+ _cpn_num, _mem_num, _function, _root = self._link_dict[i]
107
+ if i > 0:
108
+ f.write(f'\n--Link{i}--\n')
109
+ f.write(_cpn_num)
110
+ f.write(_mem_num)
111
+ f.write(self._chk_file)
112
+ f.write(self._rwf_file)
113
+ f.write(_function)
114
+ for r in _root:
115
+ f.write(f'#{self._root_space}{r}')
116
+
117
+ if i == 0:
118
+ f.write(self._title)
119
+
120
+ if not self._charge_spin:
121
+ self._check_charge_spin()
122
+ f.write(self._charge_spin)
123
+
124
+ for sym, (x, y, z) in zip(self._symbols, self._coordinates):
125
+ x = f'{x:.8f}'.rjust(14, ' ')
126
+ y = f'{y:.8f}'.rjust(14, ' ')
127
+ z = f'{z:.8f}'.rjust(14, ' ')
128
+ f.write(f' {sym} {x} {y} {z}\n')
129
+ f.write('\n')
130
+
131
+ def opt(self, tight: bool = True) -> None:
132
+ """Set the optimization option of the gjf file.
133
+
134
+ Parameters
135
+ ----------
136
+ tight : bool
137
+ If True, the optimization is tight, by default True.
138
+ """
139
+ opt = 'Opt'
140
+ if tight:
141
+ opt = 'Opt=Tight'
142
+ self.add_root(opt)
143
+
144
+ def output_detail(self) -> None:
145
+ """Output the detail to log file."""
146
+ self.is_detail = True
147
+ _, function = self._function.split()
148
+ self._function = f'#P {function}\n'
149
+ self._root_space = ' '
150
+
151
+ def reset_variable(self) -> None:
152
+ """Reset the variables of the gjf file."""
153
+ self._root = []
154
+ self._symbols = []
155
+ self._coordinates = []
156
+ self._link_dict = {}
157
+ self._link_num = 0
158
+
159
+ def set_charge_spin(self, charge: int, spin: int) -> None:
160
+ """Set the charge and spin of the molecule.
161
+
162
+ Parameters
163
+ ----------
164
+ charge : int
165
+ Charge of the molecule.
166
+ spin : int
167
+ Spin of the molecule.
168
+ """
169
+ self._charge_spin = f'\n{charge} {spin}\n'
170
+
171
+ def set_coordinates(self, coordinates: List[Tuple[float, float, float]]) -> None:
172
+ """Set the coordinates of the molecule.
173
+
174
+ Parameters
175
+ ----------
176
+ coordinates : List[Tuple[float, float, float]]
177
+ Coordinates of the molecule.
178
+ """
179
+ self._coordinates.extend(coordinates)
180
+
181
+ def set_function(self, function: str) -> None:
182
+ """Set the function of the gjf file.
183
+
184
+ Parameters
185
+ ----------
186
+ function : str
187
+ Function of the gjf file.
188
+ """
189
+ detail = ''
190
+ if self.is_detail:
191
+ detail = 'P'
192
+
193
+ self._function = f'#{detail} {function}\n'
194
+
195
+ def set_resource(self, cpu_num: int, mem_num: int, mem_unit: str = 'GB') -> None:
196
+ """Set the number of cpu and memory.
197
+
198
+ Parameters
199
+ ----------
200
+ cpu_num : int
201
+ Number of cpu.
202
+ mem_num : int
203
+ Number of memory.
204
+ mem_unit : str
205
+ Unit of memory, by default 'GB'.
206
+ """
207
+ self._cpu_num = f'%NProcShared={cpu_num}\n'
208
+ self._mem_num = f'%Mem={mem_num}{mem_unit}\n'
209
+
210
+ def set_symbols(self, symbols: List[str]) -> None:
211
+ """Set the symbols of the molecule.
212
+
213
+ Parameters
214
+ ----------
215
+ symbols : List[str]
216
+ Symbols of the molecule.
217
+ """
218
+ self._symbols.extend(symbols)
219
+
220
+ def set_title(self, title: str) -> None:
221
+ """Set the title of the gjf file.
222
+
223
+ Parameters
224
+ ----------
225
+ title : str
226
+ Title of the gjf file.
227
+ """
228
+ self._title = f'\n{title}\n'
229
+
230
+ def _check_charge_spin(self) -> None:
231
+ """Check the charge and spin of the molecule."""
232
+ elements = 0
233
+
234
+ if not self._symbols:
235
+ self._charge_spin = ''
236
+ return
237
+
238
+ for symbol in self._symbols:
239
+ elements += self.ELEMENTS_NUM[symbol]
240
+
241
+ if elements % 2 == 0:
242
+ self._charge_spin = '\n0 1\n'
243
+ else:
244
+ self._charge_spin = '\n0 2\n'
245
+
246
+ def _check_radical(self) -> bool:
247
+ """Check if the molecule is radical.
248
+
249
+ Returns
250
+ -------
251
+ bool
252
+ True if the molecule is radical, False otherwise.
253
+
254
+ Warnings
255
+ --------
256
+ This radical check is incomplete. If the number of unpaired electrons is even, it is not considered a radical.
257
+ """
258
+ # FIXME: This radical check is incomplete. If the number of unpaired electrons is even, it is not considered a radical.
259
+ warnings.warn('This radical check is incomplete. If the number of unpaired electrons is even, it is not considered a radical.')
260
+ elements = 0
261
+ for symbol in self._symbols:
262
+ elements += self.ELEMENTS_NUM[symbol]
263
+
264
+ if elements % 2 == 0:
265
+ return False
266
+ else:
267
+ return True
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: yu-mcal
3
+ Version: 0.1.0
4
+ Summary: Program for the calculation of mobility tensor for organic semiconductor crystals
5
+ Author: Koki Ozawa
6
+ Author-email: Hiroyuki Matsui <h-matsui@yz.yamagata-u.ac.jp>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2025 Hiroyuki Matsui
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+ License-File: LICENSE
29
+ Keywords: mobility,mobility tensor,organic semiconductor,reorganization energy,transfer integral
30
+ Classifier: Development Status :: 4 - Beta
31
+ Classifier: Intended Audience :: Education
32
+ Classifier: Intended Audience :: Science/Research
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3.9
35
+ Classifier: Programming Language :: Python :: 3.10
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Classifier: Topic :: Scientific/Engineering
40
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
41
+ Classifier: Topic :: Scientific/Engineering :: Physics
42
+ Requires-Python: >=3.9
43
+ Requires-Dist: numpy>=2.0.2
44
+ Requires-Dist: pandas>=2.3.3
45
+ Description-Content-Type: text/markdown
46
+
47
+ # mcal: Program for the calculation of mobility tensor for organic semiconductor crystals
48
+ [![Python](https://img.shields.io/badge/python-3.9%20or%20newer-blue)](https://www.python.org)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
50
+
51
+ # Overview
52
+ `mcal.py` is a tool for calculating mobility tensors of organic semiconductors. It calculates transfer integrals and reorganization energy from crystal structures, and determines mobility tensors considering anisotropy and path continuity.
53
+
54
+ # Requirements
55
+ * Python 3.9 or newer
56
+ * NumPy
57
+ * Pandas
58
+ * Gaussian 09 or 16
59
+
60
+ # Important notice
61
+ * The path of the Gaussian must be set.
62
+
63
+ # Installation
64
+ ```bash
65
+ pip install yu-mcal
66
+ ```
67
+
68
+
69
+ ## Verify Installation
70
+
71
+ After installation, you can verify by running:
72
+
73
+ ```bash
74
+ mcal --help
75
+ ```
76
+
77
+ # mcal Usage Manual
78
+
79
+ ## Basic Usage
80
+
81
+ ```bash
82
+ mcal <cif_filename or pkl_filenname> <osc_type> [options]
83
+ ```
84
+
85
+ ### Required Arguments
86
+
87
+ - `cif_filename`: Path to the CIF file
88
+ - `pkl_filename`: Path to the pickle file
89
+ - `osc_type`: Organic semiconductor type
90
+ - `p`: p-type semiconductor (uses HOMO level)
91
+ - `n`: n-type semiconductor (uses LUMO level)
92
+
93
+ ### Basic Examples
94
+
95
+ ```bash
96
+ # Calculate as p-type semiconductor
97
+ mcal xxx.cif p
98
+
99
+ # Calculate as n-type semiconductor
100
+ mcal xxx.cif n
101
+ ```
102
+
103
+ ## Options
104
+
105
+ ### Calculation Settings
106
+
107
+ #### `-M, --method <method>`
108
+ Specify the calculation method used in Gaussian calculations.
109
+ - **Default**: `B3LYP/6-31G(d,p)`
110
+ - **Example**: `mcal xxx.cif p -M "B3LYP/6-31G(d)"`
111
+
112
+ #### `-c, --cpu <number>`
113
+ Specify the number of CPUs to use.
114
+ - **Default**: `4`
115
+ - **Example**: `mcal xxx.cif p -c 8`
116
+
117
+ #### `-m, --mem <memory>`
118
+ Specify the amount of memory in GB.
119
+ - **Default**: `10`
120
+ - **Example**: `mcal xxx.cif p -m 16`
121
+
122
+ #### `-g, --g09`
123
+ Use Gaussian 09 (default is Gaussian 16).
124
+ - **Example**: `mcal xxx.cif p -g`
125
+
126
+ ### Calculation Control
127
+
128
+ #### `-r, --read`
129
+ Read results from existing log files without executing Gaussian.
130
+ - **Example**: `mcal xxx.cif p -r`
131
+
132
+ #### `-rp, --read_pickle`
133
+ Read results from existing pickle file without executing calculations.
134
+ - **Example**: `mcal xxx_result.pkl p -rp`
135
+
136
+ #### `--resume`
137
+ Resume calculation using existing results if log files terminated normally.
138
+ - **Example**: `mcal xxx.cif p --resume`
139
+
140
+ #### `--fullcal`
141
+ Disable speedup processing using moment of inertia and distance between centers of weight, and calculate transfer integrals for all pairs.
142
+ - **Example**: `mcal xxx.cif p --fullcal`
143
+
144
+ #### `--cellsize <number>`
145
+ Specify the number of unit cells to expand in each direction around the central unit cell for transfer integral calculations.
146
+ - **Default**: `2` (creates 5×5×5 supercell)
147
+ - **Examples**:
148
+ - `mcal xxx.cif p --cellsize 1` (creates 3×3×3 supercell)
149
+ - `mcal xxx.cif p --cellsize 3` (creates 7×7×7 supercell)
150
+
151
+ ### Output Settings
152
+
153
+ #### `-p, --pickle`
154
+ Save calculation results to a pickle file.
155
+ - **Example**: `mcal xxx.cif p -p`
156
+
157
+ ### Diffusion Coefficient Calculation Methods
158
+
159
+ #### `--mc`
160
+ Calculate diffusion coefficient tensor using kinetic Monte Carlo method.
161
+ - **Example**: `mcal xxx.cif p --mc`
162
+
163
+ #### `--ode`
164
+ Calculate diffusion coefficient tensor using Ordinary Differential Equation method.
165
+ - **Example**: `mcal xxx.cif p --ode`
166
+
167
+ ## Practical Usage Examples
168
+
169
+ ### Basic Calculations
170
+ ```bash
171
+ # Calculate mobility of p-type xxx
172
+ mcal xxx.cif p
173
+
174
+ # Use 8 CPUs and 16GB memory
175
+ mcal xxx.cif p -c 8 -m 16
176
+ ```
177
+
178
+ ### High-Precision Calculations
179
+ ```bash
180
+ # Calculate transfer integrals for all pairs (high precision, time-consuming)
181
+ mcal xxx.cif p --fullcal
182
+
183
+ # Use larger supercell to widen transfer integral calculation range
184
+ mcal xxx.cif p --cellsize 3
185
+
186
+ # Use different basis set
187
+ mcal xxx.cif p -M "B3LYP/6-311G(d,p)"
188
+ ```
189
+
190
+ ### Reusing Results
191
+ ```bash
192
+ # Read from existing calculation results
193
+ mcal xxx.cif p -r
194
+
195
+ # Read from existing pickle file
196
+ mcal xxx_result.pkl p -rp
197
+
198
+ # Resume interrupted calculation
199
+ mcal xxx.cif p --resume
200
+
201
+ # Save results to pickle file
202
+ mcal xxx.cif p -p
203
+ ```
204
+
205
+ ### Comparing Diffusion Coefficients
206
+ ```bash
207
+ # Compare with normal calculation + kinetic Monte Carlo + ODE methods
208
+ mcal xxx.cif p --mc --ode
209
+ ```
210
+
211
+ ## Output
212
+
213
+ ### Standard Output
214
+ - Reorganization energy
215
+ - Transfer integrals for each pair
216
+ - Diffusion coefficient tensor
217
+ - Mobility tensor
218
+ - Eigenvalues and eigenvectors of mobility
219
+
220
+ ## Notes
221
+
222
+ 1. **Calculation Time**: Calculation time varies significantly depending on the number of molecules and cell size
223
+ 2. **Memory Usage**: Ensure sufficient memory for large systems
224
+ 3. **Gaussian Installation**: Gaussian 09 or Gaussian 16 is required
225
+ 4. **Dependencies**: Make sure all required Python libraries are installed
226
+
227
+ ## Troubleshooting
228
+
229
+ ### If calculation stops midway
230
+ ```bash
231
+ # Resume with --resume option
232
+ mcal xxx.cif p --resume
233
+ ```
234
+
235
+ ### Memory shortage error
236
+ ```bash
237
+ # Increase memory amount
238
+ mcal xxx.cif p -m 32
239
+ ```
240
+
241
+ ### To reduce calculation time
242
+ ```bash
243
+ # Enable speedup processing (default)
244
+ mcal xxx.cif p
245
+
246
+ # Use smaller supercell for faster calculation
247
+ mcal xxx.cif p --cellsize 1
248
+
249
+ # Increase number of CPUs
250
+ mcal xxx.cif p -c 16
251
+ ```
252
+
253
+ # Authors
254
+ [Matsui Laboratory, Research Center for Organic Electronics (ROEL), Yamagata University](https://matsui-lab.yz.yamagata-u.ac.jp/index-e.html)
255
+ Hiroyuki Matsui, Koki Ozawa
256
+ Email: h-matsui[at]yz.yamagata-u.ac.jp
257
+ Please replace [at] with @
@@ -0,0 +1,16 @@
1
+ mcal/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
2
+ mcal/mcal.py,sha256=eL57d_vm8Rf0kAZwVgRphRvIpEB9_u1NaBSPUs_wvlI,28648
3
+ mcal/calculations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ mcal/calculations/hopping_mobility_model.py,sha256=kjE_07nC4hbhWV5B37G0rtsgPqjBuHP0wsJ53rXoPOQ,13180
5
+ mcal/calculations/rcal.py,sha256=CH3iV18KTM8xU7M7zKR3e1m67GbJLH8zi0j50TsUXLE,13500
6
+ mcal/calculations/tcal.py,sha256=td09qG28PGDOxY_lQDwKk0W0iReh8RF6_dd3kjN62QE,39979
7
+ mcal/constants/element_properties.csv,sha256=_Yanl713VZQaAqPYoLNn-hXDdg01ZfkYsCLQ1SQSX8w,4073
8
+ mcal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ mcal/utils/cif_reader.py,sha256=nhvk7y8ix4yKhyKjDaw2Luotw6YFMGbGCaeBVP6Qd5E,22901
10
+ mcal/utils/gaus_log_reader.py,sha256=nNIgBae9hRUgpmNF7eIC5LOENSo6NQmuckMM4A3HAa8,3159
11
+ mcal/utils/gjf_maker.py,sha256=Kkh_gNcifFfhTikZar6SzoNJ7AyEBiCBXJTQkHxHX-0,8193
12
+ yu_mcal-0.1.0.dist-info/METADATA,sha256=oBAS8ZHFduaZrGTw-O9-reJlUGEn-VJNPxbl4iQvS7E,7630
13
+ yu_mcal-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ yu_mcal-0.1.0.dist-info/entry_points.txt,sha256=_0xZR3t9qvFSd9L6Iot03NixVLxXioEY19L6w3Fs1Ew,40
15
+ yu_mcal-0.1.0.dist-info/licenses/LICENSE,sha256=JP8vm7gYE73jLgnMFTOLNo_RnH88RrB4Goyh7H_muto,1072
16
+ yu_mcal-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcal = mcal.mcal:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Hiroyuki Matsui
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.