Compare two structure with different atom order

Dear pymatgen users,

I have two structures converged with two distinct methods (DFT and MD) and I want to compute each atom’s 3D displacement when comparing the two structures. The problem is that computational code is writing the converged structure with atoms in a different order and for that reason when I’m trying to compare the distances, I’m not comparing the position of crystallographically equivalent atoms of the two structures.

Is there a way to solve this?

My code right now is the one below

dft = Structure.from_file('DFT_conv.cif')
md_298 = Structure.from_file('MD_298.cif')
dis = np.sum((dft.cart_coords - md_298.cart_coords)**2, axis =1)

Thanks
Carlos

1 Like

Welcome @CBornes!

What you’re looking for is StructureMatcher, see StructureMatcher.get_mapping() here: pymatgen.analysis.structure_matcher module — pymatgen 2022.01.09 documentation

There’s a lot of functionality within StructureMatcher but the intent is exactly what you’re looking for; to map between two equivalent structures that may be expressed either in different crystallographic settings, have small perturbations to their atomic positions and lattice parameters, or even a change in indices as in this case.

Let me know if that works, and if not we can try a more detailed example with your specific files.

Best,

Matt

2 Likes

Hi @mkhorton

Thank you for the answer. I was able to get an array with the code below. I had to increase the tolerances a lot.

StructureMatcher(ltol = 1.0, stol = 1.0, angle_tol = 10, primitive_cell = False, scale = False).get_mapping(dft, md_298)

result
array([ 6, 63, 112, 128, 102, 121, 140, 159, 190, 24, 34, 53, 88, 91, 7, 76, 1, 4, 77, 95, 107, 64, 92, 58, 61, 93, 71, 74, 113, 68, 66, 110, 69, 82, 85, 129, 79, 75, 126, 80, 134, 146, 103, 131, 97, 100, 132, 150, 153, 122, 147, 116, 119, 148, 166, 169, 141, 163, 135, 138, 164, 182, 185, 160, 170, 154, 157, 171, 177, 180, 191, 174, 162, 188, 175, 14, 17, 25, 11, 181, 22, 12, 39, 42, 35, 27, 29, 32, 28, 46, 57, 54, 43, 48, 51, 44, 89, 96, 72, 83, 144, 151, 167, 183, 178, 15, 40, 47, 5, 8, 90, 2, 0, 87, 3, 62, 65, 106, 59, 9, 94, 60, 111, 114, 73, 108, 67, 70, 109, 127, 130, 84, 115, 78, 81, 125, 101, 104, 145, 98, 86, 133, 99, 120, 123, 152, 117, 105, 149, 118, 139, 142, 168, 136, 124, 165, 137, 158, 161, 184, 155, 143, 172, 156, 189, 19, 179, 186, 173, 176, 187, 23, 26, 16, 20, 10, 13, 21, 33, 36, 41, 30, 18, 38, 31, 52, 55, 56, 49, 37, 45, 50, 197, 205, 428, 221, 229, 237, 245, 253, 470, 269, 277, 285, 294, 303, 312, 321, 330, 339, 348, 357, 366, 375, 382, 387, 572, 575, 413, 416, 198, 410, 192, 195, 411, 420, 423, 206, 417, 200, 203, 418, 212, 215, 429, 209, 306, 426, 210, 434, 437, 222, 431, 216, 219, 432, 441, 444, 230, 438, 224, 227, 439, 448, 451, 238, 445, 232, 235, 446, 455, 458, 246, 452, 240, 243, 453, 462, 465, 254, 459, 248, 251, 460, 260, 263, 471, 257, 360, 468, 258, 476, 479, 270, 473, 264, 267, 474, 483, 486, 278, 480, 272, 275, 481, 490, 493, 286, 487, 280, 283, 488, 497, 500, 295, 494, 289, 292, 495, 504, 507, 304, 501, 298, 301, 502, 511, 514, 313, 508, 307, 310, 509, 518, 521, 322, 515, 316, 319, 516, 525, 528, 331, 522, 325, 328, 523, 532, 535, 340, 529, 334, 337, 530, 539, 542, 349, 536, 343, 346, 537, 546, 549, 358, 543, 352, 355, 544, 553, 556, 367, 550, 361, 364, 551, 560, 563, 376, 557, 370, 373, 558, 565, 564, 379, 568, 567, 384, 391, 390, 408, 396, 395, 409, 414, 421, 213, 435, 442, 449, 456, 463, 261, 477, 484, 491, 498, 505, 512, 519, 526, 533, 540, 547, 554, 561, 566, 569, 392, 397, 196, 199, 415, 193, 288, 412, 194, 204, 207, 422, 201, 297, 419, 202, 427, 430, 214, 424, 208, 211, 425, 220, 223, 436, 217, 315, 433, 218, 228, 231, 443, 225, 324, 440, 226, 236, 239, 450, 233, 333, 447, 234, 244, 247, 457, 241, 342, 454, 242, 252, 255, 464, 249, 351, 461, 250, 469, 472, 262, 466, 256, 259, 467, 268, 271, 478, 265, 369, 475, 266, 276, 279, 485, 273, 378, 482, 274, 284, 287, 492, 281, 383, 489, 282, 293, 296, 499, 290, 388, 496, 291, 302, 305, 506, 299, 393, 503, 300, 311, 314, 513, 308, 398, 510, 309, 320, 323, 520, 317, 399, 517, 318, 329, 332, 527, 326, 400, 524, 327, 338, 341, 534, 335, 401, 531, 336, 347, 350, 541, 344, 402, 538, 345, 356, 359, 548, 353, 403, 545, 354, 365, 368, 555, 362, 404, 552, 363, 374, 377, 562, 371, 405, 559, 372, 381, 380, 406, 386, 385, 407, 571, 570, 389, 574, 573, 394])

Now how do I go about getting this mapping into the structure?

I’m not able to upload the structure (new user) but you can find it here in case that helps.
Carlos

Hi again @mkhorton

I was not able to get my head around the information provided by the get_mapping function so I’ve decided to look into the other function of structure_matcher function.

Using the StructureMatcher.get_s2_like_s1() I got a structure that seems similar but after visualization on Avogadro there seems to be some sort of geometry operation from the starting structure () to the new structure ().

Here is the code

dft = Structure.from_file('DFT_conv.cif')
md_298 = Structure.from_file('MD_298.cif')
new_md_298 = StructureMatcher(ltol = 1.0, stol = 0.6, angle_tol = 5, primitive_cell = False, scale = False).get_s2_like_s1(dft, md_298)
cif = CifWriter(new_md_298)
cif.write_file('new_MD_298.cif')

I also noticed that new_md_298.cart_coords shows all negative cartesian coordinates. Is that the problem?

Thanks
Carlos