impedance.py icon indicating copy to clipboard operation
impedance.py copied to clipboard

insert a boundary in the frequency of RC and RQ elements

Open nicmazza opened this issue 2 years ago • 1 comments

Is there a way to constrain the peak frequency value of RQ and RC circuits?

I've used this package for the last couple of years and I am loving it! And I love that you can specify bounds for each circuit element. However, from what I can see I think it is only possible to introduce boundaries on R, Q and n when it comes to CPE elements, and not their peak frequency. Is this the case or did I not notice the functionality?

Possible solution: I imagine the easiest solution would be to write a second fitting function that expects R, f and n as initial guesses for CPE, and then insert boundaries on those. Or define another circuit element, RQfreq, that has those initial parameters which can be costrained as usual. I did not look too deep into it as I am not sure if the functionality already exists Edit: it'd probably be necessary to write a RQ element where we specify the peak frequency, but I guess it'd need to return R Q and n.

Why I would want this: Recently I have began to also look into DRT to treat my data, as there's a ton of overlapping features in it, but I have some doubts on how precise the quantification is. A workaround would be to estimate the peak frequencies of each component via DRT (or even just a Bode plot...) and then run a standard ECM fit with strong constraints on the peak frequencies of RC and CPE elements. So far I have provided a guess of each R, and then have the script calculate the corresponding C to get the frequency I'd want, and use it as starting guess, but I am not sure how much it actually helped when two features are overlapping.

Thanks!

nicmazza avatar Aug 02 '22 07:08 nicmazza

Follow up, this might be the RQ

def RQ(p, f):
    """ defines an RQ element using R and peak frequency as inputs
    Notes
    -----
    .. math::

        Z = \\frac{R}{1+ R \\times Q \\times (d \\times j 2 \\pi f )^\\alpha}

    where :math:`Q` is obtained from  :math:`R` = p[0],  :math:`peak_freq` = p[1] and :math:`\\alpha` = p[2].
    """
    omega = 2*np.pi*np.array(f)
    R, peak_freq, alpha = p[0], p[1], p[2]
    Q = float((1/R)*(2*np.pi*peak_freq)**-alpha)	
    Z = R/(1+R*Q*(omega*1j)**alpha)
    return Z


but I think it would need to returnZ as a function of R, Q and alpha in order to work with the current fitting method, and from what I understand curve_fit can't use a constraint like 1/(2piR1*Q1) = 1000 but it can only accept lower and upper values for R1 and Q1. Therefore, it would not be possible to introduce a constraint on the peak frequency.... But I am very much a beginner so feel free to correct me :) From what I read, lmfit should make it possible to introduce such a constraint, but it would require rewriting the fitting function?

nicmazza avatar Aug 10 '22 15:08 nicmazza