|
1 | 1 | import os
|
2 | 2 | import re
|
| 3 | +import warnings |
3 | 4 |
|
4 | 5 | import numpy as np
|
5 | 6 |
|
@@ -123,33 +124,79 @@ def get_energy(outlines):
|
123 | 124 | return Etot, False
|
124 | 125 |
|
125 | 126 |
|
126 |
| -def get_force(outlines, natoms): |
| 127 | +def collect_force(outlines): |
127 | 128 | force = []
|
128 |
| - force_inlines = get_block( |
129 |
| - outlines, "TOTAL-FORCE (eV/Angstrom)", skip=4, nlines=np.sum(natoms) |
130 |
| - ) |
131 |
| - if force_inlines is None: |
132 |
| - print( |
133 |
| - "TOTAL-FORCE (eV/Angstrom) is not found in OUT.XXX/running_scf.log. May be you haven't set 'cal_force 1' in the INPUT." |
134 |
| - ) |
| 129 | + for i, line in enumerate(outlines): |
| 130 | + if "TOTAL-FORCE (eV/Angstrom)" in line: |
| 131 | + value_pattern = re.compile( |
| 132 | + r"^\s*[A-Z][a-z]?[1-9][0-9]*\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$" |
| 133 | + ) |
| 134 | + j = i |
| 135 | + # find the first line of force |
| 136 | + noforce = False |
| 137 | + while not value_pattern.match(outlines[j]): |
| 138 | + j += 1 |
| 139 | + if ( |
| 140 | + j >= i + 10 |
| 141 | + ): # if can not find the first line of force in 10 lines, then stop |
| 142 | + warnings.warn("Warning: can not find the first line of force") |
| 143 | + noforce = True |
| 144 | + break |
| 145 | + if noforce: |
| 146 | + break |
| 147 | + |
| 148 | + force.append([]) |
| 149 | + while value_pattern.match(outlines[j]): |
| 150 | + force[-1].append([float(ii) for ii in outlines[j].split()[1:4]]) |
| 151 | + j += 1 |
| 152 | + return force # only return the last force |
| 153 | + |
| 154 | + |
| 155 | +def get_force(outlines, natoms): |
| 156 | + force = collect_force(outlines) |
| 157 | + if len(force) == 0: |
135 | 158 | return [[]]
|
136 |
| - for line in force_inlines: |
137 |
| - force.append([float(f) for f in line.split()[1:4]]) |
138 |
| - force = np.array(force) |
139 |
| - return force |
| 159 | + else: |
| 160 | + return np.array(force[-1]) # only return the last force |
140 | 161 |
|
141 | 162 |
|
142 |
| -def get_stress(outlines): |
| 163 | +def collect_stress(outlines): |
143 | 164 | stress = []
|
144 |
| - stress_inlines = get_block(outlines, "TOTAL-STRESS (KBAR)", skip=3, nlines=3) |
145 |
| - if stress_inlines is None: |
146 |
| - return None |
147 |
| - for line in stress_inlines: |
148 |
| - stress.append([float(f) for f in line.split()]) |
149 |
| - stress = np.array(stress) * kbar2evperang3 |
| 165 | + for i, line in enumerate(outlines): |
| 166 | + if "TOTAL-STRESS (KBAR)" in line: |
| 167 | + value_pattern = re.compile( |
| 168 | + r"^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s+[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$" |
| 169 | + ) |
| 170 | + j = i |
| 171 | + nostress = False |
| 172 | + while not value_pattern.match(outlines[j]): |
| 173 | + j += 1 |
| 174 | + if ( |
| 175 | + j >= i + 10 |
| 176 | + ): # if can not find the first line of stress in 10 lines, then stop |
| 177 | + warnings.warn("Warning: can not find the first line of stress") |
| 178 | + nostress = True |
| 179 | + break |
| 180 | + if nostress: |
| 181 | + break |
| 182 | + |
| 183 | + stress.append([]) |
| 184 | + while value_pattern.match(outlines[j]): |
| 185 | + stress[-1].append( |
| 186 | + list(map(lambda x: float(x), outlines[j].split()[0:3])) |
| 187 | + ) |
| 188 | + j += 1 |
150 | 189 | return stress
|
151 | 190 |
|
152 | 191 |
|
| 192 | +def get_stress(outlines): |
| 193 | + stress = collect_stress(outlines) |
| 194 | + if len(stress) == 0: |
| 195 | + return None |
| 196 | + else: |
| 197 | + return np.array(stress[-1]) * kbar2evperang3 # only return the last stress |
| 198 | + |
| 199 | + |
153 | 200 | def get_frame(fname):
|
154 | 201 | data = {
|
155 | 202 | "atom_names": [],
|
|
0 commit comments