|
8 | 8 |
|
9 | 9 | import numpy as np
|
10 | 10 |
|
| 11 | +from ase.units import Hartree |
11 | 12 | from ase.io.aims import write_aims, read_aims
|
12 | 13 | from ase.data import atomic_numbers
|
13 | 14 | from ase.calculators.calculator import FileIOCalculator, Parameters, kpts2mp, \
|
@@ -437,6 +438,179 @@ def read_convergence(self):
|
437 | 438 | converged = True
|
438 | 439 | return converged
|
439 | 440 |
|
| 441 | + def get_number_of_iterations(self): |
| 442 | + return self.read_number_of_iterations() |
| 443 | + |
| 444 | + def read_number_of_iterations(self): |
| 445 | + niter = None |
| 446 | + lines = open(self.out, 'r').readlines() |
| 447 | + for n, line in enumerate(lines): |
| 448 | + if line.rfind('| Number of self-consistency cycles') > -1: |
| 449 | + niter = int(line.split(':')[-1].strip()) |
| 450 | + return niter |
| 451 | + |
| 452 | + def get_electronic_temperature(self): |
| 453 | + return self.read_electronic_temperature() |
| 454 | + |
| 455 | + def read_electronic_temperature(self): |
| 456 | + width = None |
| 457 | + lines = open(self.out, 'r').readlines() |
| 458 | + for n, line in enumerate(lines): |
| 459 | + if line.rfind('Occupation type:') > -1: |
| 460 | + width = float(line.split('=')[-1].strip().split()[0]) |
| 461 | + return width |
| 462 | + |
| 463 | + def get_number_of_electrons(self): |
| 464 | + return self.read_number_of_electrons() |
| 465 | + |
| 466 | + def read_number_of_electrons(self): |
| 467 | + nelect = None |
| 468 | + lines = open(self.out, 'r').readlines() |
| 469 | + for n, line in enumerate(lines): |
| 470 | + if line.rfind('The structure contains') > -1: |
| 471 | + nelect = float(line.split()[-2].strip()) |
| 472 | + return nelect |
| 473 | + |
| 474 | + def get_number_of_bands(self): |
| 475 | + return self.read_number_of_bands() |
| 476 | + |
| 477 | + def read_number_of_bands(self): |
| 478 | + nband = None |
| 479 | + lines = open(self.out, 'r').readlines() |
| 480 | + for n, line in enumerate(lines): |
| 481 | + if line.rfind('Total number of basis functions') > -1: |
| 482 | + nband = int(line.split(':')[-1].strip()) |
| 483 | + return nband |
| 484 | + |
| 485 | + def get_k_point_weights(self): |
| 486 | + return self.read_kpts(mode='k_point_weights') |
| 487 | + |
| 488 | + def get_bz_k_points(self): |
| 489 | + raise NotImplementedError |
| 490 | + |
| 491 | + def get_ibz_k_points(self): |
| 492 | + return self.read_kpts(mode='ibz_k_points') |
| 493 | + |
| 494 | + def get_spin_polarized(self): |
| 495 | + return self.read_number_of_spins() |
| 496 | + |
| 497 | + def get_number_of_spins(self): |
| 498 | + return 1 + self.get_spin_polarized() |
| 499 | + |
| 500 | + def read_number_of_spins(self): |
| 501 | + spinpol = None |
| 502 | + lines = open(self.out, 'r').readlines() |
| 503 | + for n, line in enumerate(lines): |
| 504 | + if line.rfind('| Number of spin channels') > -1: |
| 505 | + spinpol = int(line.split(':')[-1].strip()) - 1 |
| 506 | + return spinpol |
| 507 | + |
| 508 | + def read_magnetic_moment(self): |
| 509 | + magmom = None |
| 510 | + if not self.get_spin_polarized(): |
| 511 | + magmom = 0.0 |
| 512 | + else: # only for spinpolarized system Magnetisation is printed |
| 513 | + for line in open(self.label + '.txt'): |
| 514 | + if line.find('Magnetisation') != -1: # last one |
| 515 | + magmom = float(line.split('=')[-1].strip()) |
| 516 | + return magmom |
| 517 | + |
| 518 | + def get_fermi_level(self): |
| 519 | + return self.read_fermi() |
| 520 | + |
| 521 | + def get_eigenvalues(self, kpt=0, spin=0): |
| 522 | + return self.read_eigenvalues(kpt, spin, 'eigenvalues') |
| 523 | + |
| 524 | + def get_occupations(self, kpt=0, spin=0): |
| 525 | + return self.read_eigenvalues(kpt, spin, 'occupations') |
| 526 | + |
| 527 | + def read_fermi(self): |
| 528 | + E_f = None |
| 529 | + lines = open(self.out, 'r').readlines() |
| 530 | + for n, line in enumerate(lines): |
| 531 | + if line.rfind('| Chemical potential (Fermi level) in eV') > -1: |
| 532 | + E_f = float(line.split(':')[-1].strip()) |
| 533 | + return E_f |
| 534 | + |
| 535 | + def read_kpts(self, mode='ibz_k_points'): |
| 536 | + """ Returns list of kpts weights or kpts coordinates. """ |
| 537 | + values = [] |
| 538 | + assert mode in ['ibz_k_points' , 'k_point_weights'], 'mode not in [\'ibz_k_points\' , \'k_point_weights\']' |
| 539 | + lines = open(self.out, 'r').readlines() |
| 540 | + kpts = None |
| 541 | + for n, line in enumerate(lines): |
| 542 | + if line.rfind('K-points in task') > -1: |
| 543 | + kpts = int(line.split(':')[-1].strip()) |
| 544 | + kptsstart = n |
| 545 | + break |
| 546 | + assert not kpts is None |
| 547 | + text = lines[kptsstart + 1:] |
| 548 | + values = [] |
| 549 | + for line in text[:kpts]: |
| 550 | + if mode == 'ibz_k_points': |
| 551 | + b = [float(c.strip()) for c in line.split()[4:7]] |
| 552 | + else: |
| 553 | + b = float(line.split()[-1]) |
| 554 | + values.append(b) |
| 555 | + if len(values) == 0: |
| 556 | + values = None |
| 557 | + return np.array(values) |
| 558 | + |
| 559 | + def read_eigenvalues(self, kpt=0, spin=0, mode='eigenvalues'): |
| 560 | + """ Returns list of last eigenvalues, occupations |
| 561 | + for given kpt and spin. """ |
| 562 | + values = [] |
| 563 | + assert mode in ['eigenvalues' , 'occupations'], 'mode not in [\'eigenvalues\' , \'occupations\']' |
| 564 | + lines = open(self.out, 'r').readlines() |
| 565 | + # number of kpts |
| 566 | + kpts = None |
| 567 | + for n, line in enumerate(lines): |
| 568 | + if line.rfind('K-points in task') > -1: |
| 569 | + kpts = int(line.split(':')[-1].strip()) |
| 570 | + break |
| 571 | + assert not kpts is None |
| 572 | + assert kpt + 1 <= kpts |
| 573 | + # find last (eigenvalues) |
| 574 | + eigvalstart = None |
| 575 | + for n, line in enumerate(lines): |
| 576 | + if line.rfind('Preliminary charge convergence reached') > -1: |
| 577 | + eigvalstart = n |
| 578 | + break |
| 579 | + assert not eigvalstart is None |
| 580 | + lines = lines[eigvalstart:] |
| 581 | + for n, line in enumerate(lines): |
| 582 | + if line.rfind('Writing Kohn-Sham eigenvalues') > -1: |
| 583 | + eigvalstart = n |
| 584 | + break |
| 585 | + assert not eigvalstart is None |
| 586 | + text = lines[eigvalstart + 1:] # remove first 1 line |
| 587 | + # find the requested k-point |
| 588 | + nbands = self.read_number_of_bands() |
| 589 | + sppol = self.get_spin_polarized() |
| 590 | + beg = (nbands + 4 + int(sppol)*1) * kpt * (sppol + 1) + 3 + sppol * 2 + kpt * sppol |
| 591 | + if self.get_spin_polarized(): |
| 592 | + if spin == 0: |
| 593 | + beg = beg |
| 594 | + end = beg + nbands |
| 595 | + else: |
| 596 | + beg = beg + nbands + 5 |
| 597 | + end = beg + nbands |
| 598 | + else: |
| 599 | + end = beg + nbands |
| 600 | + values = [] |
| 601 | + for line in text[beg:end]: |
| 602 | + # aims prints stars for large values ... |
| 603 | + line = line.replace('**************', ' 10000') |
| 604 | + b = [float(c.strip()) for c in line.split()[1:]] |
| 605 | + values.append(b) |
| 606 | + if mode == 'eigenvalues': |
| 607 | + values = [Hartree*v[1] for v in values] |
| 608 | + else: |
| 609 | + values = [v[0] for v in values] |
| 610 | + if len(values) == 0: |
| 611 | + values = None |
| 612 | + return np.array(values) |
| 613 | + |
440 | 614 |
|
441 | 615 | class AimsCube:
|
442 | 616 | "Object to ensure the output of cube files, can be attached to Aims object"
|
|
0 commit comments