Source code for ase2sprkkr.physics.lattice_data

"""
This module contains various crystalographics classifications,
and the LatticeData object, that provides various informations about a lattice.
"""

from collections import namedtuple

from ..common.decorators import cached_property
import numpy as np
from ase2sprkkr.bindings.spglib import spglib_dataset
from ase.units import Bohr
from scipy.optimize import linear_sum_assignment
from typing import Union


[docs] def reorder_matrix(target, source): # normalize vectors (rows) src_norm = source / np.linalg.norm(source, axis=1, keepdims=True) tgt_norm = target / np.linalg.norm(target, axis=1, keepdims=True) # compute similarity matrix (cosine similarity) sim = tgt_norm @ src_norm.T # shape (3,3) # convert to cost matrix (maximize similarity -> minimize negative similarity) cost = -sim # Hungarian algorithm row_ind, col_ind = linear_sum_assignment(cost) # reorder target rows to best match source reordered = target[row_ind[np.argsort(col_ind)]] return reordered
# Example S = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=float) T = np.array([[0, 0, 2], [3, 0, 0], [0, 5, 0]], dtype=float)
[docs] class Pearson( namedtuple( "Pearson", [ "pearson_symbol", "bravais_number", "family", "centering_type", "herman_mauguin", "shoenflies", # Shoenflies ], ) ): """This class holds informations about translation symmetry of a lattice with a given Pearson symbol."""
[docs] def xband_data(self): """Data used by Xband sysfile and SPRKKR to describe translation symmetry.""" return self[1:]
[docs] @staticmethod def from_symbol(pearson_symbol: str): """Return the Pearson symbol (describing the translation symmetry) that corresponds to the given Pearson symbol""" return Pearson.pearsons[Pearson.normalize_symbol(pearson_symbol)]
[docs] @staticmethod def normalize_symbol(pearson_symbol): """Normalize a Pearson symbol to its cannonical shape""" if pearson_symbol[1] in ("A", "B", "C"): pearson_symbol = pearson_symbol[0] + "S" return pearson_symbol
pearson = None """ Mapping of all possible Pearson symbols to Pearson objects"""
Pearson.pearsons = { i.pearson_symbol: i for i in [ Pearson("aP", 1, "triclinic", "primitive", "-1", "C_i"), Pearson("mP", 2, "monoclinic", "primitive", "2/m", "C_2h"), Pearson("mS", 3, "monoclinic", "primitive", "2/m", "C_2h"), Pearson("oP", 4, "orthorombic", "primitive", "mmm", "D_2h"), Pearson("oS", 5, "orthorombic", "base-centered", "mmm", "D_2h"), Pearson("oI", 6, "orthorombic", "body-centered", "mmm", "D_2h"), Pearson("oF", 7, "orthorombic", "face-centered", "mmm", "D_2h"), Pearson("tP", 8, "tetragonal", "primitive", "4/mmm", "D_4h"), Pearson("tI", 9, "tetragonal", "body-centered", "4/mmm", "D_4h"), Pearson("hR", 10, "trigonal", "primitive", "-3m", "D_3d"), Pearson("hP", 11, "hexagonal", "primitive", "6/mmm", "D_6h"), Pearson("cP", 12, "cubic", "primitive", "m3m", "O_h"), Pearson("cF", 13, "cubic", "face-centered", "m3m", "O_h"), Pearson("cI", 14, "cubic", "body-centered", "m3m", "O_h"), ] } #: Translation of international tables numbers to A. Perlovs numbering. international_numbers_to_AP = { 1: 1, 2: 2, 3: 3, 4: 5, 5: 7, 6: 13, 7: 15, 8: 21, 9: 27, 10: 39, 11: 41, 12: 43, 13: 50, 14: 55, 15: 61, 16: 73, 17: 74, 18: 77, 19: 80, 20: 81, 21: 84, 22: 87, 23: 88, 24: 89, 25: 90, 26: 93, 27: 99, 28: 102, 29: 108, 30: 114, 31: 120, 32: 126, 33: 129, 34: 135, 35: 138, 36: 145, 37: 147, 38: 150, 39: 156, 40: 162, 41: 168, 42: 174, 43: 177, 44: 180, 45: 183, 46: 186, 47: 192, 48: 193, 49: 195, 50: 198, 51: 204, 52: 210, 53: 216, 54: 222, 55: 228, 56: 231, 57: 234, 58: 240, 59: 247, 60: 249, 61: 255, 62: 257, 63: 263, 64: 269, 65: 275, 66: 278, 67: 281, 68: 287, 69: 299, 70: 300, 71: 302, 72: 303, 73: 306, 74: 308, 75: 314, 76: 315, 77: 316, 78: 317, 79: 318, 80: 319, 81: 320, 82: 321, 83: 322, 84: 323, 85: 324, 86: 326, 87: 328, 88: 329, 89: 331, 90: 332, 91: 333, 92: 334, 93: 335, 94: 336, 95: 337, 96: 338, 97: 339, 98: 340, 99: 341, 100: 342, 101: 343, 102: 344, 103: 345, 104: 346, 105: 347, 106: 348, 107: 349, 108: 350, 109: 351, 110: 352, 111: 353, 112: 354, 113: 355, 114: 356, 115: 357, 116: 358, 117: 359, 118: 360, 119: 361, 120: 362, 121: 363, 122: 364, 123: 365, 124: 366, 125: 368, 126: 370, 127: 371, 128: 372, 129: 374, 130: 376, 131: 377, 132: 378, 133: 380, 134: 382, 135: 383, 136: 384, 137: 386, 138: 388, 139: 389, 140: 390, 141: 392, 142: 394, 143: 396, 144: 398, 145: 400, 146: 401, 147: 404, 148: 405, 149: 407, 150: 408, 151: 409, 152: 410, 153: 411, 154: 412, 155: 414, 156: 415, 157: 416, 158: 417, 159: 418, 160: 419, 161: 422, 162: 423, 163: 424, 164: 425, 165: 426, 166: 428, 167: 430, 168: 431, 169: 432, 170: 433, 171: 434, 172: 435, 173: 436, 174: 437, 175: 438, 176: 439, 177: 440, 178: 441, 179: 442, 180: 443, 181: 444, 182: 445, 183: 446, 184: 447, 185: 448, 186: 449, 187: 450, 188: 451, 189: 452, 190: 453, 191: 454, 192: 455, 193: 456, 194: 457, 195: 458, 196: 459, 197: 460, 198: 461, 199: 462, 200: 463, 201: 465, 202: 466, 203: 468, 204: 469, 205: 470, 206: 471, 207: 472, 208: 473, 209: 474, 210: 475, 211: 476, 212: 477, 213: 478, 214: 479, 215: 480, 216: 481, 217: 482, 218: 483, 219: 484, 220: 485, 221: 486, 222: 488, 223: 489, 224: 491, 225: 492, 226: 493, 227: 494, 229: 498, 230: 499, } _CELL_SHAPE_AP_OVERRIDES = { 143: {"hP": 395, "hR": 396}, 144: {"hP": 397, "hR": 398}, 145: {"hP": 399, "hR": 400}, 147: {"hP": 403, "hR": 404}, } #: Xband AP numbers keyed by Hall number for the full Hall-number range 1..530. #: A few primitive trigonal space groups still need cell-shape overrides because #: spglib uses the same Hall number for both hexagonal and rhombohedral cells. hall_numbers_to_AP = { 1: 1, 2: 2, 3: 4, 4: 3, 5: 3, 6: 6, 7: 5, 8: 5, 9: 10, 10: 11, 11: 12, 12: 8, 13: 7, 14: 9, 15: 8, 16: 7, 17: 9, 18: 14, 19: 13, 20: 13, 21: 18, 22: 20, 23: 19, 24: 16, 25: 17, 26: 15, 27: 16, 28: 17, 29: 15, 30: 24, 31: 25, 32: 26, 33: 22, 34: 21, 35: 23, 36: 22, 37: 21, 38: 23, 39: 33, 40: 36, 41: 37, 42: 35, 43: 34, 44: 38, 45: 29, 46: 28, 47: 32, 48: 27, 49: 30, 50: 31, 51: 29, 52: 28, 53: 32, 54: 27, 55: 30, 56: 31, 57: 40, 58: 39, 59: 39, 60: 42, 61: 41, 62: 41, 63: 46, 64: 47, 65: 48, 66: 44, 67: 43, 68: 45, 69: 44, 70: 43, 71: 45, 72: 52, 73: 54, 74: 53, 75: 50, 76: 51, 77: 49, 78: 50, 79: 51, 80: 49, 81: 55, 82: 56, 83: 57, 84: 58, 85: 59, 86: 60, 87: 500, 88: 501, 89: 502, 90: 67, 91: 70, 92: 71, 93: 69, 94: 68, 95: 72, 96: 63, 97: 62, 98: 66, 99: 61, 100: 64, 101: 65, 102: 63, 103: 62, 104: 66, 105: 61, 106: 64, 107: 65, 108: 73, 109: 74, 110: 75, 111: 76, 112: 77, 113: 78, 114: 79, 115: 80, 116: 81, 117: 82, 118: 83, 119: 84, 120: 85, 121: 86, 122: 87, 123: 88, 124: 89, 125: 90, 126: 91, 127: 92, 128: 93, 129: 94, 130: 95, 131: 96, 132: 97, 133: 98, 134: 99, 135: 100, 136: 101, 137: 102, 138: 103, 139: 104, 140: 105, 141: 106, 142: 107, 143: 108, 144: 109, 145: 110, 146: 111, 147: 112, 148: 113, 149: 114, 150: 115, 151: 116, 152: 117, 153: 118, 154: 119, 155: 120, 156: 121, 157: 122, 158: 123, 159: 124, 160: 125, 161: 126, 162: 127, 163: 128, 164: 129, 165: 130, 166: 131, 167: 132, 168: 133, 169: 134, 170: 135, 171: 136, 172: 137, 173: 138, 174: 139, 175: 140, 176: 145, 177: 146, 178: 143, 179: 144, 180: 141, 181: 142, 182: 147, 183: 148, 184: 149, 185: 150, 186: 151, 187: 152, 188: 153, 189: 154, 190: 155, 191: 156, 192: 157, 193: 158, 194: 159, 195: 160, 196: 161, 197: 162, 198: 163, 199: 164, 200: 165, 201: 166, 202: 167, 203: 168, 204: 169, 205: 170, 206: 171, 207: 172, 208: 173, 209: 174, 210: 175, 211: 176, 212: 177, 213: 178, 214: 179, 215: 180, 216: 181, 217: 182, 218: 183, 219: 184, 220: 185, 221: 186, 222: 187, 223: 188, 224: 189, 225: 190, 226: 191, 227: 192, 228: 193, 229: 193, 230: 195, 231: 196, 232: 197, 233: 198, 234: 198, 235: 198, 236: 198, 237: 198, 238: 198, 239: 204, 240: 205, 241: 206, 242: 207, 243: 208, 244: 209, 245: 210, 246: 211, 247: 212, 248: 213, 249: 214, 250: 215, 251: 216, 252: 217, 253: 218, 254: 219, 255: 220, 256: 221, 257: 222, 258: 223, 259: 224, 260: 225, 261: 226, 262: 227, 263: 228, 264: 229, 265: 230, 266: 231, 267: 232, 268: 233, 269: 234, 270: 235, 271: 236, 272: 237, 273: 238, 274: 239, 275: 240, 276: 241, 277: 242, 278: 247, 279: 247, 280: 247, 281: 247, 282: 247, 283: 247, 284: 249, 285: 250, 286: 251, 287: 252, 288: 253, 289: 254, 290: 255, 291: 256, 292: 257, 293: 258, 294: 259, 295: 260, 296: 261, 297: 262, 298: 263, 299: 264, 300: 265, 301: 266, 302: 267, 303: 268, 304: 269, 305: 270, 306: 271, 307: 272, 308: 273, 309: 274, 310: 275, 311: 276, 312: 277, 313: 278, 314: 279, 315: 280, 316: 281, 317: 282, 318: 283, 319: 284, 320: 285, 321: 286, 322: 287, 323: 287, 324: 287, 325: 287, 326: 287, 327: 287, 328: 287, 329: 287, 330: 287, 331: 287, 332: 287, 333: 287, 334: 299, 335: 300, 336: 300, 337: 302, 338: 303, 339: 304, 340: 305, 341: 306, 342: 307, 343: 308, 344: 309, 345: 310, 346: 311, 347: 312, 348: 313, 349: 314, 350: 315, 351: 316, 352: 317, 353: 318, 354: 319, 355: 320, 356: 321, 357: 322, 358: 323, 359: 324, 360: 324, 361: 326, 362: 326, 363: 328, 364: 329, 365: 329, 366: 331, 367: 332, 368: 333, 369: 334, 370: 335, 371: 336, 372: 337, 373: 338, 374: 339, 375: 340, 376: 341, 377: 342, 378: 343, 379: 344, 380: 345, 381: 346, 382: 347, 383: 348, 384: 349, 385: 350, 386: 351, 387: 352, 388: 353, 389: 354, 390: 355, 391: 356, 392: 357, 393: 358, 394: 359, 395: 360, 396: 361, 397: 362, 398: 363, 399: 364, 400: 365, 401: 366, 402: 368, 403: 368, 404: 370, 405: 370, 406: 371, 407: 372, 408: 374, 409: 374, 410: 376, 411: 376, 412: 377, 413: 378, 414: 380, 415: 380, 416: 382, 417: 382, 418: 383, 419: 384, 420: 386, 421: 386, 422: 388, 423: 388, 424: 389, 425: 390, 426: 392, 427: 392, 428: 394, 429: 394, 430: 396, 431: 398, 432: 400, 433: 402, 434: 401, 435: 404, 436: 406, 437: 405, 438: 407, 439: 408, 440: 409, 441: 410, 442: 411, 443: 412, 444: 414, 445: 413, 446: 415, 447: 416, 448: 417, 449: 418, 450: 420, 451: 419, 452: 422, 453: 421, 454: 423, 455: 424, 456: 425, 457: 426, 458: 428, 459: 427, 460: 430, 461: 429, 462: 431, 463: 432, 464: 433, 465: 434, 466: 435, 467: 436, 468: 437, 469: 438, 470: 439, 471: 440, 472: 441, 473: 442, 474: 443, 475: 444, 476: 445, 477: 446, 478: 447, 479: 448, 480: 449, 481: 450, 482: 451, 483: 452, 484: 453, 485: 454, 486: 455, 487: 456, 488: 457, 489: 458, 490: 459, 491: 460, 492: 461, 493: 462, 494: 463, 495: 465, 496: 465, 497: 466, 498: 468, 499: 468, 500: 469, 501: 470, 502: 471, 503: 472, 504: 473, 505: 474, 506: 475, 507: 476, 508: 477, 509: 478, 510: 479, 511: 480, 512: 481, 513: 482, 514: 483, 515: 484, 516: 485, 517: 486, 518: 488, 519: 488, 520: 489, 521: 490, 522: 491, 523: 492, 524: 493, 525: 494, 526: 495, 527: 496, 528: 497, 529: 498, 530: 499, }
[docs] def ap_number_from_spacegroup(spacegroup_number: int, hall_number: Union[int, None] = None, cell=None) -> int: """Return the Xband A. Perlov number for a space-group setting. The trigonal space groups 143, 144, 145, and 147 need the cell shape to distinguish hP and hR settings. Other ambiguous groups are resolved by Hall number when it is available, otherwise the international-number fallback is used. """ if cell is not None: overrides = _CELL_SHAPE_AP_OVERRIDES.get(spacegroup_number) if overrides is not None: pearson_symbol = cell.get_bravais_lattice().pearson_symbol cell_shape_ap_number = overrides.get(pearson_symbol) if cell_shape_ap_number is not None: return cell_shape_ap_number if hall_number is not None and hall_number in hall_numbers_to_AP: return hall_numbers_to_AP[hall_number] return international_numbers_to_AP[spacegroup_number]
[docs] class LatticeData:
[docs] def __init__(self, atoms): cell = atoms.get_cell() bl = cell.get_bravais_lattice() sg = spglib_dataset(atoms) ps = bl.pearson_symbol self.pearson = Pearson.from_symbol(ps) self.basis = 0 self.sgno = sg.number self.apno = ap_number_from_spacegroup(sg.number, sg.hall_number, cell=cell) self.bravais = cell.get_bravais_lattice() self.boa = cell.cellpar()[1] / cell.cellpar()[0] self.coa = cell.cellpar()[2] / cell.cellpar()[0] self.alat = bl.a / Bohr self.blat = self.boa * self.alat self.clat = self.coa * self.alat self.alpha = cell.cellpar()[3] self.beta = cell.cellpar()[4] self.gamma = cell.cellpar()[5] self.sg = sg self.cell = cell
[docs] @cached_property def rbas(self): # self.rbas = sg.scaled_primitive_cell sg = self.sg out = sg.primitive_lattice.dot(np.linalg.inv(sg.std_lattice)) return reorder_matrix(out, self.cell)
@property def bravais_number(self): return self.pearson.bravais_number @property def shoenflies_symbol(self): return self.pearson.shoenflies