File: kktrans.py

package info (click to toggle)
python-qmix 1.0.6-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,460 kB
  • sloc: python: 4,312; makefile: 215
file content (76 lines) | stat: -rw-r--r-- 1,874 bytes parent folder | download
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
""" This sub-module contains functions to generate the Kramers-Kronig 
transform of DC I-V data.

Used to find the real component of the response function from the DC I-V 
curve.

"""

import numpy as np
from scipy.signal import hilbert


def kk_trans(v, i, n=50):
    """Calculate the Kramers-Kronig transform from DC I-V data.

    Note: 

        Voltage spacing must be constant!

    Args:
        v (ndarray): normalized voltage (DC I-V curve)
        i (ndarray): normalized current (DC I-V curve)
        n (int): padding for Hilbert transform

    Returns:
        ndarray: kk transform

    """

    npts = v.shape[0]

    # Ensure v has (roughly) even spacing
    assert np.abs((v[1] - v[0]) - (v[1:] - v[:-1])).max() < 1e-5

    # Subtract v to make kk defined at v=infinity
    ikk = -(hilbert(i - v, N=npts * n)).imag
    ikk = ikk[:npts]

    return ikk


def kk_trans_trapz(v, i):
    """Calculate the Kramers-Kronig transform using a simple trapezoidal 
    summation.

    This function isn't used anymore, but it is nice to use it to
    compare against qmix.mathfn.kktrans.kk_trans.

    Note: 

        Voltage spacing must be constant!

    This function is (much!) slower than the Hilbert transform version (i.e., 
    qmix.mathfn.kktrans.kk_trans). It also has problems with how it is 
    calculated around the singularity.

    Args:
        v (ndarray): normalized voltage (DC I-V curve)
        i (ndarray): normalized current (DC I-V curve)

    Returns:
        ndarray: kk transform

    """

    # Ensure v has even spacing
    assert ((v[1:] - v[:-1]) - (v[1] - v[0])).max() < 1e-5

    # very crude integration
    ikk = []
    for a in range(len(v)):
        v_prime, i_prime = np.delete(v, a), np.delete(i, a)
        ikk.append(np.trapz((i_prime - v_prime) / (v_prime - v[a]), x=v_prime))
    ikk = np.array(ikk) / np.pi

    return ikk