File: lattice_constant.rst

package info (click to toggle)
python-ase 3.26.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,484 kB
  • sloc: python: 148,112; xml: 2,728; makefile: 110; javascript: 47
file content (98 lines) | stat: -rw-r--r-- 2,550 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
.. _lattice_constant:

=========================================================
Finding lattice constants using EOS and the stress tensor
=========================================================

.. seealso::

   :ref:`eos`.


HCP
===

Let's try to find the `a` and `c` lattice constants for HCP nickel
using the :mod:`EMT <ase.calculators.emt>` potential.

First, we make a good initial guess for `a` and `c` using the FCC nearest
neighbor distance and the ideal `c/a` ratio:

.. literalinclude:: lattice_constant.py
   :start-after: creates:
   :end-before: literalinclude division line 1

and create a trajectory for the results:

.. literalinclude:: lattice_constant.py
   :start-after: literalinclude division line 1
   :end-before: literalinclude division line 2

Finally, we do the 9 calculations (three values for `a` and three for `c`):

.. literalinclude:: lattice_constant.py
   :start-after: literalinclude division line 2
   :end-before: literalinclude division line 3


Analysis
--------

Now, we need to extract the data from the trajectory.  Try this:

>>> from ase.build import bulk
>>> ni = bulk('Ni', 'hcp', a=2.5, c=4.0)
>>> ni.cell
array([[ 2.5  ,  0.   ,  0.   ],
       [-1.25 ,  2.165,  0.   ],
       [ 0.   ,  0.   ,  4.   ]])

So, we can get `a` and `c` from ``ni.cell[0, 0]`` and ``ni.cell[2,
2]``:

.. literalinclude:: lattice_constant.py
   :start-after: literalinclude division line 3
   :end-before: literalinclude division line 4

We fit the energy to this expression:

.. math:: p_0 + p_1 a + p_2 c + p_3 a^2 + p_4 ac + p_5 c^2

The best fit is found like this:

.. literalinclude:: lattice_constant.py
   :start-after: literalinclude division line 4
   :end-before: literalinclude division line 5

and we can find the minimum like this:

.. literalinclude:: lattice_constant.py
   :start-after: literalinclude division line 5

Results:

.. csv-table::
   :file: lattice_constant.csv
   :header: a, c


Using the stress tensor
=======================

One can also use the stress tensor to optimize the unit cell. For this we cannot use the EMT calculator.::

    from ase.optimize import BFGS
    from ase.constraints import StrainFilter
    from gpaw import GPAW, PW
    ni = bulk('Ni', 'hcp', a=a0,c=c0)
    calc = GPAW(mode=PW(200),xc='LDA',txt='Ni.out')
    ni.calc = calc
    sf = StrainFilter(ni)
    opt = BFGS(sf)
    opt.run(0.005)

If you want the optimization path in a trajectory, add these lines
before calling the ``run()`` method::

    traj = Trajectory('path.traj', 'w', ni)
    opt.attach(traj)