2015 3.016 Problem Set 6

Electrochemical Impedance

Electrochemical Cell: A device consisting of two half-cells (electrode and electrolyte) which generate electrical energy from chemical reactions (or vice versa)
Impedance: The ability of a circuit element to resist the flow of electric current

Objectives

Understand Impedance

Understand factors that contribute to the impedance of an electrochemical cell

Understand Nyquist and Bode Plots, and how they can be used to calculate cell impedance

1. Introduction to Impedence

Impedance: The ability of a circuit element to resist the flow of electric current
Resistor: Two terminal circuit element used to implement electrical resistance (reduce current flow)

Most people are familiar with Ohm’s Law, which relates voltage (E) to current (I) and a ciruit resistor’s resistance (R):

E = I R

The above relationship is only true, however, for an ideal resistor, which has with it the following assumptions:
I) Ohm’s Law is followed at all currents and voltages
II) Resistance is independent of frequency
III) AC voltage and current signals through the resistor are in phase

Resistance is thus a specific form of impedance. Beyond the ideal resistor, however, most circuit elements do not have these simplifying properties.

Electrochemical impedance is generally measured using a small excitation signal with a sinusoidal potential:

(Subscript[E, t]) = (Subscript[E, 0]) sin(ωt)

Where (Subscript[E, t]) is the potential at a given time (t), (Subscript[E, 0]) is the amplitude of the signal, and ω is the frequency. This outputs a sinusoidal current that is phase shifted by ϕ:

(Subscript[I, t]) = (Subscript[I, 0]) sin(ωt + ϕ)

Using Ohm’s Law (isolated for resistance), R = (V/I), as an analog, we can find the impedance (Subscript[Z, t]):

(Subscript[Z, t])= ((Subscript[E, t])/(Subscript[I, t])) =  (((Subscript[E, 0])sin(ωt))/((Subscript[I, 0])sin(ωt+ϕ))) =  (Subscript[Z, 0])((sin(ωt))/(sin(ωt+ϕ)))

For a resistor, with the assumption of no phase shift, we get an impedance of:

(Subscript[Z, resistor])=(((Subscript[E, 0])sin(ωt))/((Subscript[I, 0])sin(ωt))) =  R

A resitor’s resistance is also it’s impedance, independant of frequency (an assumption we made earlier that is seen here)

We can use Euler’s relationship:

(e^(iθ)) = cos(θ) + i sin(θ)

to convert the previously defined potential and current equations into complex ones:

(Subscript[E, t]) = (Subscript[E, 0]) (e^(i ω t)) 
(Subscript[I, t]) = (Subscript[I, 0]) (e^(i (ω t-ϕ)))

Resulting in a new equation for impedance:

(Subscript[Z, t])= ((Subscript[E, t])/(Subscript[I, t])) =  (((Subscript[E, 0]) (e^(i ω t)) )/((Subscript[I, 0]) (e^(i (ω t-ϕ))) )) = ((Subscript[E, 0])/(Subscript[I, 0]))(e^(i(ω t- (ω t-ϕ)))  = (Subscript[Z, 0]) (e^(iϕ)) = (Subscript[Z, 0]) (cos(ϕ) + i sin(ϕ))

This accounts for a phase difference between current and voltage. Impedance thus generally both has a magnitude and ‘direction’ (if imagined as a vector in polar space).

Capacitor: Two terminal circuit element used to temporarily store energy in an electric field
Inductor: Two terminal circuit element used to temporarily store energy in a magnetic field, inducing a voltage

The aforementioned circuit elements have respective properties, capacitance and inductance, that quantify their ability to store energy/resist changes in current.

Capacitance: C = (q/E)

Taking the derivative with respect to time, we can obtain a relationship between voltage and current:

EC = q
(dE/dt)C = (dq/dt)
(dE/dt)C = I

To find the impedance, we first substitute potential (E) with the sinusoidal potental:

I = C(dE/dt)= C((d(Subscript[E, 0])sin(ωt))/dt)
I = C((d(Subscript[E, 0])sin(ωt))/dt)= C ω (Subscript[E, 0])cos(ωt)

Dividing input potential by the output sinusoidal current, we get:

(Subscript[Z, capacitor]) = (E/I)
(Subscript[Z, capacitor]) = (((Subscript[E, 0])sin(ωt))/(Cω(Subscript[E, 0])cos(ωt))) = (1/(C ω))((sin(ωt))/(cos(ωt)))

Since the cosine function can be thought of as a sine function phase shifted by (( π)/2), we get (with Euler’s form):

(Subscript[Z, capacitor]) = (1/(C ω))((sin(ωt))/(sin(ωt+(( π)/2))))
(Subscript[Z, capacitor]) =  (Subscript[Z, 0]) (cos(ϕ) + i sin(ϕ)) = (1/(C ω)) (cos(-(π/2)) + i sin(-(π/2))) = -(i/(C ω))

Inductors induce an electromotive force due to the current flowing through them:

Inductance: E = L (dI/dt)

This time we can substitute for current to find an expression for the electromotive force (or potential)

E = L (dI/dt) = L (((Subscript[dI, 0])sin(ωt))/dt)
E = L(((Subscript[dI, 0])sin(ωt))/dt)= L ω (Subscript[I, 0])cos(ωt)

Dividing input potential by the output sinusoidal current, we get:

(Subscript[Z, inductor]) = (E/I)
(Subscript[Z, inductor]) = ((Lω(Subscript[I, 0])cos(ωt))/((Subscript[I, 0])sin(ωt))) =  Lω((cos(ωt))/(sin(ωt)))

Following the same method as done with the capacitor:

(Subscript[Z, inductor]) = Lω((sin(ωt+(π/2)))/(sin(ωt)))
(Subscript[Z, inductor]) =  (Subscript[Z, 0]) (cos(ϕ) + i sin(ϕ)) = Lω (cos((π/2)) + i sin((π/2))) = iω L

Impedance: The ability of a circuit element to resist the flow of electric current

(Subscript[Z, resistor])=  R 
(Subscript[Z, capacitor]) = (1/(i C ω))
(Subscript[Z, inductor]) = iω L

Comparing these three forms of impedance, we see that:
1) Impedance of a resistor is independant of frequency and there is no phase shift
II) Impedance of a capacitor decreases with capacitance
The greater the abililty to store energy, the lower the resistance to current flow
III) Impedance of an inductor increases with inductance
The greater the induced voltage from a given current, the higher the resistance to current flow

II. Additional Circuit Factors

This is the resistance of the electrolyte in which the electrodes are situated.

(Subscript[R, solution]) = ρ (l/A)

where ρ is the solution resistivity, A and l are the area and length, respectively, in which the current is carried.

In an electrochemical cell there is capicitance that does not derive from an additional circuit element. Between an electrode and it’s surrounding electrolyte there is an electrical double layer. This is formed as ions from the solution stick on to the electrode surface (a form of adsorbtion). The charged electrode is separated from the charged ions, forming a capacitor (two charged surfaces separated by an insulator).

When a metal substrate and an electrolyte are in contact, the metal can dissolve into the electrolytic solvent:

Me ⟺ (Me^(2+)) + n (SuperMinus[e])

The metal can transfer from its reduced state to its oxidized state and vice-versa. When metal ions enter the electrolyte, they transfer charge. The current experiences a resistance in the circuit due to this transfer, and this is the charge transfer resistance.

To understand the rate of charge transfer, we may make use of the Butler-Volmer equation. This equation characterizes electrical current on an electrode as a result of electrode potential. This is useful because the current is a measure of charge transfer. For an electrochemical system in equilibrium, we have:

(Subscript[R, ct]) = (RT/(Subscript[nFi, 0]))

Where R is the gas constant, T is the temperature, n is the number of electrons, F is Faraday’s constant, and (Subscript[i, 0])is the exchange current density.

For an ideal circuit capacitor, we established that impedance is:

(Subscript[Z, capacitor]) = (1/(i C ω))

Capacitors in electrochemical cells do not exhibit this idealized behaviour. “Constant phase element” is the name given to a circuit element that models an imperfect behaviour. The equation becomes:

(Subscript[Z, CPE]) = (1/((((iω))^α) C))

where α is an empirically determined constant less than 1.

Double layer capacitors typically behave like CPEs rather than perfect capacitors.

Diffusion in the double layer can create an impedance known as a Warburg impedance, which depends on the frequency. The higher the frequency, the less that diffusing reactants have to move, and vice versa.

(Subscript[Z, W]) = ((Subscript[A, W])/(Sqrt[ω]))+ i((Subscript[A, W])/(Sqrt[ω]))

Where (Subscript[A, W]) is the Warburg coefficient (which involves the surface area of the electrode, diffusion coefficients of the oxidant and reaction, and number of electrons)
This has a constant phase of (45^o) (as seen by the equal magnitude of the two terms).
There is no specific circuit element that models the Warburg impedance.

III. Nyquist and Bode Plots

Nyquist Plot: Polar (Imaginary vs. real space) plot of a frequency response of a linear system (voltage vs. current is linear)

We can examine plots of the imaginary vs. real components of impedence at different frequencies (ω).
Each point on the Nyquist plot represents an impedance at a given frequency (which cannot be determined solely by the graph). The magnitude of the impedance can be measured by drawing a vector from the origin to the point, with argument (the angle between the vector and the X-axis) being the “phase angle”

As an example, we shall take an arbitrary frequency function:

f(iω) = (1/(iω+1))

and determine the Nyquist plot. Firstly, we separate the real and imaginary components:

f(iω) = (1/(iω+1))× ((-iω+1)/(-iω+1))= ((1-iω)/(1+(ω^2)))
Re[f(iω)]=(1/(1+(ω^2)))
Im[f(iω)]=((-ω)/(1+(ω^2)))

To reiterate, the imaginary part is the vertical component and the real part is the horizontal component of any given point on the Nyquist plot. This must be parametrically plotted for all values of ω. Below is such a plot, with a toggle button to look at an individual frequency:

Manipulate[Show[NyquistPlot[1/(ω+1),{0,1000},PlotLabel->"Nyquist Plot"],ListLinePlot[{{0,0},{(1/(1+(x^2))),((-x)/(1+(x^2)))}},PlotRange->{{-2,2},{-2,2}},ColorFunction->"Rainbow"]],{x,0,15},{{x,300,"Frequency"},0,15,Appearance->"Open",AppearanceElements->"InputField"}]

Toggling the button shows that higher frequencies are to the right (a higher real component). Additionally, it takes a very small increase in frequency to already get close to 0.

Bode Plot: Two plots, both with frequency as x-axis, used to show amplitude and phase of frequency response

These plots, in conjunction with the Nyquist Plot, provide greater detail about the system. Amplitude vs. frequency shows the prevalency of different frequencies (essentially a Fourier transform), allowing a general range of frequencies to be determined. Phase vs. frequency can be used side by side with the Nyquist Plot to match an impedance with a frequency.

Taking the same frequency function as above, we can generate the Bode plot using the mathematica function named BodePlot:

BodePlot[1/(ω+1),Frame->True, FrameStyle->Gray,FrameLabel->{"Frequency","Frequency"},PlotLabel->{"Amplitude vs. Frequency","Phase vs. Frequency"},ImageSize->Medium,PlotRange->{{0,-30},{0,-100}}]

Looking at just the Nyquist plot, we saw that higher frequencies were closer to the  origin. Looking at the amplitude vs. frequency graph, we see that amplitude decreases as frequency increases, coroborating with our initial observation.

Electrochemical Impedence Spectroscopy: Measures impedence through supplying AC current of a known frequency

We will examine data collected from the following circuit:

The goal is to use a model for the impedence of this system and fit it with the data to determine various system quantities (solution resistance, Warburg constant, charge transfer resistance, number of electrons, initial charge).

This system contains a resister in series with a parallel system of a double layer capacitor (which we assume behaves like a CPE) and a series with a resistor and Warburg element. We can model the total impedance of the system, knowing that:

In Series: (Subscript[Z, eq])=  (Subscript[Z, 1]) +  (Subscript[Z, 2])
In Parallel: (1/(Subscript[Z, eq]))= (1/(Subscript[Z, 1])) + (1/(Subscript[Z, 2]))

model[ω_,{rS_,aW_,rCT_,n_,q0_}]:=rS+((aW+rCT (Sqrt[I ω]))/((Sqrt[I ω])+(E^((I n π)/2)) q0 (aW+rCT (Sqrt[I ω])) (ω^n)))

where:
rS = Solution resistance
aW = Warburg constant
rCT = Charge transfer resistance
n = number of electrons
q0 = initial charge

To find a fit, the module zDataComplexNorm is used to calculate the sum of the squared residuals (SSR) between the data and the model.

zDataComplexNorm[data_,f_,{rS_,aW_,rCT_,n_,q0_}]:=Sum[((data[[j,5]]-Re[f[data[[j,1]], {rS,aW,rCT,n,q0}]])^2+(data[[j,6]]-Im[f[data[[j,1]], {rS,aW,rCT,n,q0}]])^2),{j,1,Length[data]}]

This then is placed in a minimizing function (with initial guesses to keep the process timely) to find the best fit

params = {rS,aW,rCT,n,q0};

initialGuesses={{rS,750},{aW,300},{rCT,17500},{n,0.9},{q0,1.2682`*^-5}};

testFit2=FindMinimum[zDataComplexNorm[zData,model,params],initialGuesses]

nyquistPlot1=DynamicModule[
{
dataPlot=ListPlot[Transpose[{zData[[All,5]],-zData[[All,6]]}]],
vals,
wLower,wUpper,
colorFunction,
frequencyColoredPlotMarkers
},
{wLower,wUpper} = Through[{Min,Max}[First/@zData] ];
colorFunction[ω_]:= ColorData["AvocadoColors"][Rescale[Clip[Log[10,ω],{wLower,wUpper}],{0,1}]];
frequencyColoredPlotMarkers = 
{PointSize[0.02],
Table[{colorFunction[zData[[i,1]]],Disk[{zData[[i,5]],-zData[[i,6]]},Scaled[0.01]]},{i,1,Length[zData]}]};
dataPlot=ListPlot[Transpose[{zData[[All,5]],-zData[[All,6]]}],
Epilog-> frequencyColoredPlotMarkers];
Manipulate[
Show[dataPlot,
ParametricPlot[{1,-1}Through[{Re,Im}[model[w,{rSval,aWval,rCTval,nval,q0val}]]],{w,wLower,wUpper},PlotStyle-> Thick,
ColorFunction-> Function[{x,y,w},colorFunction[w]],
ColorFunctionScaling-> False,
Frame->True,BaseStyle-> Large,FrameLabel-> {{"-Im[Z]",None},{"Re[Z]",Style[Text["Nyquist with (Subscript[R, CT])="<>ToString[rCTval]<>" (Subscript[R, Ω])="<>ToString[rSval]],FontSize->20,FontColor->Blue]}}
,ImageSize-> Large,PlotPoints->50,MaxRecursion->15]
],
{{rSval,750,"Solution Resistance (Ohm)"},0,1000,Appearance->"Open",AppearanceElements->"InputField"},{{aWval,300,"Warburg (Ohm (s^(-1/2)))"},0,1000,Appearance->"Open",AppearanceElements->"InputField"},
{{rCTval,17500,"Charge-Transfer Resistance (Ohm)"},2000,20000,Appearance->"Open",AppearanceElements->"InputField"},
{{nval,0.9,"CPE exponent"},0,1,Appearance->"Open",AppearanceElements->"InputField"},
{{q0val,0.000012682`,"CPE Capacitance (F)"},0.000001,0.00002,Appearance->"Open",AppearanceElements->"InputField"},
Dynamic[Style[Text["Norm Distance = "<>ToString[PaddedForm[zDataComplexNorm[zData,model,{rSval,aWval,rCTval,nval,q0val}],
{8,3}]]],FontColor-> Red,FontSize-> 10]
],
Control[Button["click find nearest solution",vals ={rSval,aWval,rCTval,nval,q0val} ={rS,aW,rCT,n,q0}/.useApproximationToGetFit[rSval,aWval,rCTval,nval,q0val]]],
SaveDefinitions->True
]
]

Toggling with each of the different constants we can make some qualitative observations about the impact of various factors on this electrochemical cell’s impedance:
Solution resistance (in the given scale), does not drastically influence

Comments about code

GRAPHICS
ListPlot[Transpose[{zData[[All,5]],-zData[[All,6]]}]] is the calculated impedance from the data
Color function “AvocadoColors” used to show change in frequency - darker tone means higher frequency
Options Appearance->”Open” and AppearanceElements->”InputField” used to show toggle sliders for each constant that also show value they are currently at.
“click to find nearest solution” button utilizes previously discussed useApproximationToGetFit function to find best fit.

Expanding this idea to model for the Bode Plot, we can plot all the plots in conjunction to get a better understanding of the system:

IV. Conclusions

Electrochemical cell not merely a battery connected to a resistor
EIS data can be fit to a model to calculate quantities pertaining to certain circuit elements (solution resistance, CPE capacitance, etc.)
Futher considerations: Plot which allows switching of model, to examine different fits, closer examination of how changing each factor affects Nyquist/Bode Plots

References

[1] Source code supplied by W. Craig Carter provided data set, modules for fit finding, plots

[2] Background on Impedence adapted from:
https://www.gamry.com/application-notes/EIS/basics-of-electrochemical-impedance-spectroscopy/

[3] Wikipedia articles used for definitions
url[term_] := https://en.wikipedia.org/wiki/term

[4] Circuit Building code adapted from StackExchange:
http://mathematica.stackexchange.com/questions/8614/circuit-drawing-in-mathematica

[5] Background on Nyquist plots
http://www.facstaff.bucknell.edu/mastascu/econtrolhtml/Freq/Freq6.html

Acknowledgements

I’d like to thank Prof. Carter, George, and Mary Beth for all of their support and guidance. It has been a real pleasure learning the ways of the Mathematica Jedi under their tutelage. I hope that one day I can move on from the rank of Padawan.

Initialization Code

Goal: Create functions for various circuit elements. These elements can be placed in a grid to construct circuits.
First, construct wire ‘connect’ and ‘gap’ elements:

connect[pointList_]:={Line[pointList],Map[Text[Style["\!\(\*AdjustmentBox[\(•\),\nBoxBaselineShift->0.24615384615384617`,\nBoxMargins->{{0., 0.}, {-0.24615384615384617`, 0.24615384615384617`}}]\)",FontSize->18],#]&,pointList[[{1,-1}]]]}

gap[l_: 1]:=Line[l {{{0,0},{1/3,0}},{{2/3,0},{1,0}}}]

Then, construct circuit elements

resistor[l_: 1,n_: 3]:=Line[Table[{i l/(4 n),1/3 Sin[i Pi/2]},{i,0,4 n}]]

inductor[l_: 1,n_: 3]:=Module[{scale=l/(5/16 n+1/2),pts={{0,0},{0,1},{1/2,1},{1/2,0},{1/2,-1},{5/16,-1},{5/16,0}}},Append[Table[BezierCurve[scale Map[{d 5/16,0}+#&,pts]],{d,0,n-1}],BezierCurve[scale Map[{5/16 n,0}+#&,pts[[1;;4]]]]]]

capacitor[l_: 1]:={gap[l],Line[l {{{1/3,-1},{1/3,1}},{{2/3,-1},{2/3,1}}}]}

battery[l_: 1]:={gap[l],{Rectangle[l {1/3,-(2/3)},l {1/3+1/9,2/3}],Line[l {{2/3,-1},{2/3,1}}]}}

contact[l_: 1]:={gap[l],Map[{EdgeForm[Directive[Thick,Black]],FaceForm[White],Disk[#,l/30]}&,l {{1/3,0},{2/3,0}}]}

circle[l_: 1]:={Line[{{0,0},{1/10,0}}],Line[{{9/10,0},{1,0}}],{EdgeForm[Directive[Black]],FaceForm[White],Disk[{l/2,0},2/5 l]}}

warburg[l_: 1]:={circle[]//at[{0,0}],label["W",Black]//at[{l/2,0}]}

Create ‘connect’ function to combine elements:

Options[display]={Frame->True,FrameTicks->None,PlotRange->All,GridLines->Automatic,GridLinesStyle->Directive[Orange,Dashed],AspectRatio->Automatic};
display[d_,opts:OptionsPattern[]]:=Graphics[Style[d,Thick],Join[FilterRules[{opts},Options[Graphics]],Options[display]]]

at[position_,angle_: 0][obj_]:=GeometricTransformation[obj,Composition[TranslationTransform[position],RotationTransform[angle]]]

label[s_String,color_: RGBColor[.3,.5,.8]]:=Text@Style[s,FontColor->color,FontFamily->"Geneva",FontSize->Large];

Example circuit with battery, resistor, and capacitor in series:

display[{battery[]//at[{0,0},Pi/2],connect[{{0,1},{0,2},{2,2}}],resistor[]//at[{2,2}],connect[{{3,2},{4,2},{4,1}}],inductor[]//at[{4,0},Pi/2],connect[{{4,0},{4,-1},{3,-1}}],capacitor[]//at[{2,-1}],connect[{{2,-1},{0,-1},{0,0}}]}]

Resistors in series:

display[{connect[{{0,0},{1,0}}],resistor[]//at[{1,0}],connect[{{2,0},{3,0}}],connect[{{3,0},{4,0}}],resistor[]//at[{4,0}],connect[{{5,0},{6,0}}],label["(Subscript[R, 1])"]//at[{2.2,0.3}],label["(Subscript[R, 2])"]//at[{5.2,0.3}]},GridLines->None,Frame->False]

Capacitors in series:

display[{connect[{{0,0},{1,0}}],capacitor[]//at[{1,0}],connect[{{2,0},{3,0}}],connect[{{3,0},{4,0}}],resistor[]//at[{4,0}],connect[{{5,0},{6,0}}],label["(Subscript[C, 1])"]//at[{2.1,0.3}],label["(Subscript[R, 1])"]//at[{5.3,0.3}]},GridLines->None,Frame->False]

Inductors in series:

display[{connect[{{0,0},{1,0}}],inductor[]//at[{1,0}],connect[{{2,0},{3,0}}],connect[{{3,0},{4,0}}],inductor[]//at[{4,0}],connect[{{5,0},{6,0}}],label["(Subscript[L, 1])"]//at[{2.3,0.3}],label["(Subscript[L, 2])"]//at[{5.3,0.3}]},GridLines->None,Frame->False]

Randles Cell

display[{connect[{{0,0},{1,0}}],resistor[]//at[{1,0}],connect[{{2,0},{3,0}}],connect[{{3,0},{3,1}}],connect[{{3,0},{3,-1}}],connect[{{3,1},{5,1}}],connect[{{3,-1},{4,-1}}],resistor[]//at[{4,-1}],capacitor[]//at[{5,1}],connect[{{6,1},{8,1}}],warburg[]//at[{6,-1}],connect[{{5,-1},{6,-1}}],connect[{{7,-1},{8,-1}}],connect[{{8,1},{8,0}}],connect[{{8,-1},{8,0}}],connect[{{8,0},{9,0}}],label["(Subscript[R, s])",Black]//at[{1.3,0.8}],label["(Subscript[R, ct])",Black]//at[{4.3,-0.2}],label["CPE",Black]//at[{4.6,1.4}]},GridLines->None]

display[{connect[{{2,0},{3,0}}],connect[{{3,0},{3,1}}],connect[{{3,0},{3,-1}}],connect[{{3,1},{5,1}}],connect[{{3,-1},{5,-1}}],resistor[]//at[{5,-1}],resistor[]//at[{5,1}],connect[{{6,1},{8,1}}],connect[{{6,-1},{8,-1}}],connect[{{8,1},{8,0}}],connect[{{8,-1},{8,0}}],connect[{{8,0},{9,0}}],label["(Subscript[R, 2])",Black]//at[{4.6,-0.5}],label["(Subscript[R, 1])",Black]//at[{4.6,1.4}]},GridLines->None]

Data Set (very large - copied data set into notebook to avoid import errors)

zData = {{1.`*^6,0.01`,2.2998`,7.093001`,93.612`,2421.4`,1.0037`*^-7,0,20306},{794328.`,0.01`,2.2998`,8.171`,242.65`,2189.5`,1.009`*^-7,0,20306},{630957.`,0.01`,2.2998`,9.234001`,362.41`,1911.`,1.0011`*^-7,0,20306},{501187.`,0.01`,2.2998`,10.296`,459.54`,1658.5`,1.0024`*^-7,0,20306},{398107.`,0.01`,2.2998`,11.359`,520.12`,1356.9`,1.0002`*^-7,0,20306},{316228.`,0.01`,2.2998`,12.406`,584.26`,1105.2`,1.0007`*^-7,0,20306},{251189.`,0.01`,2.2998`,13.468`,628.98`,890.52`,9.979`*^-8,0,20306},{199526.`,0.01`,2.2998`,14.531`,659.57`,715.09`,9.9076`*^-8,0,20306},{158489.`,0.01`,2.2998`,15.609`,680.9`,571.92`,9.858`*^-8,0,20306},{125893.`,0.01`,2.2998`,16.671`,695.59`,454.61`,9.8709`*^-8,0,20306},{100000.`,0.01`,2.2998`,17.734`,704.54`,360.73`,1.0091`*^-7,0,20306},{79433.`,0.01`,2.2998`,18.796`,710.08`,285.82`,1.0022`*^-7,0,20306},{63096.`,0.01`,2.2998`,19.875`,713.71`,225.39`,9.8015`*^-8,0,20306},{50119.`,0.01`,2.2998`,20.937`,716.19`,176.83`,9.7256`*^-8,0,20306},{39811.`,0.01`,2.2998`,22.`,717.69`,137.48`,9.7411`*^-8,0,20306},{31623.`,0.01`,2.2998`,23.062`,718.88`,105.32`,9.7635`*^-8,0,20306},{25119.`,0.01`,2.2998`,24.156`,720.07`,78.912`,9.6917`*^-8,0,20306},{19953.`,0.01`,2.2998`,25.218`,721.16`,56.882`,9.9718`*^-8,0,20306},{15849.`,0.01`,2.2998`,26.281`,722.48`,38.158`,1.0075`*^-7,0,20306},{12589.`,0.01`,2.2998`,27.343`,724.18`,21.902`,9.6509`*^-8,0,20306},{10000.`,0.01`,2.2998`,28.421`,726.02`,7.3522`,3.9433`*^-6,0,20306},{7943.3`,0.01`,2.2998`,29.484`,728.34`,-6.2042`,2.5106`*^-6,0,20306},{6309.6`,0.01`,2.2998`,30.546`,731.3`,-19.204`,9.656`*^-8,0,20306},{5011.9`,0.01`,2.2998`,31.609`,734.62`,-32.207`,9.4881`*^-8,0,20306},{3981.1`,0.01`,2.2998`,32.687`,738.63`,-45.702`,9.537`*^-8,0,20306},{3162.3`,0.01`,2.2998`,33.734`,743.53`,-60.079`,9.485`*^-8,0,20306},{2511.9`,0.01`,2.2998`,34.812`,749.13`,-75.85`,9.5554`*^-8,0,20306},{1995.3`,0.01`,2.2998`,35.875`,755.71`,-93.607`,9.6703`*^-8,0,20306},{1584.9`,0.01`,2.2998`,36.937`,763.35`,-113.88`,9.5109`*^-8,0,20306},{1258.9`,0.01`,2.2998`,38.`,772.04`,-137.3`,9.4937`*^-8,0,20306},{1000.`,0.01`,2.2998`,39.078`,781.77`,-164.87`,9.4784`*^-8,0,20306},{794.33`,0.01`,2.2998`,40.171`,792.88`,-197.53`,9.4365`*^-8,0,20306},{630.96`,0.01`,2.2998`,41.234`,805.19`,-236.62`,9.5576`*^-8,0,20306},{501.19`,0.01`,2.2998`,42.296`,818.89`,-283.87`,9.1245`*^-8,0,20306},{398.11`,0.01`,2.2998`,43.359`,834.3`,-341.57`,1.0068`*^-7,0,20306},{316.23`,0.01`,2.2998`,44.421`,851.77`,-412.26`,9.4019`*^-8,0,20306},{251.19`,0.01`,2.2998`,45.5`,872.02`,-499.46`,9.6004`*^-8,0,20306},{199.53`,0.01`,2.2998`,46.562`,896.3`,-607.29`,9.1759`*^-8,0,20306},{158.49`,0.01`,2.2998`,47.625`,926.64`,-740.71`,1.0229`*^-7,0,20306},{125.89`,0.01`,2.2998`,48.687`,965.53`,-905.73`,9.919`*^-8,0,20306},{100.`,0.01`,2.2998`,49.765`,1016.2`,-1107.8`,9.603`*^-8,0,20306},{79.433`,0.01`,2.2998`,50.828`,1084.7`,-1357.`,1.0204`*^-7,0,20306},{63.096`,0.01`,2.2998`,51.89`,1178.`,-1660.`,1.1504`*^-7,0,20306},{50.119`,0.01`,2.2998`,52.953`,1309.`,-2029.`,8.8996`*^-8,0,20306},{39.811`,0.01`,2.2998`,54.015`,1487.9`,-2471.1`,1.1785`*^-7,0,20306},{31.623`,0.01`,2.2998`,55.093`,1739.7`,-2997.3`,9.9777`*^-8,0,20306},{25.119`,0.01`,2.2998`,56.218`,2082.5`,-3624.3`,9.2742`*^-8,0,20306},{19.953`,0.01`,2.2998`,57.281`,2568.3`,-4306.7`,1.0755`*^-7,0,20306},{15.849`,0.01`,2.2998`,58.343`,3218.3`,-5060.`,1.0792`*^-7,0,20306},{12.589`,0.01`,2.2998`,59.468`,4065.4`,-5853.3`,1.02`*^-7,0,20306},{10.`,0.01`,2.2998`,60.531`,5209.7`,-6582.9`,1.0861`*^-7,0,20306},{7.9433`,0.01`,2.2998`,61.656`,6575.1`,-7214.8`,1.1437`*^-7,0,20306},{6.3096`,0.01`,2.2998`,62.89`,8083.8`,-7580.1`,1.0904`*^-7,0,20306},{5.0119`,0.01`,2.2998`,64.125`,9737.5`,-7720.5`,1.047`*^-7,0,20306},{3.9811`,0.01`,2.2998`,65.25`,11369.`,-7497.9`,9.953`*^-8,0,20306},{3.1623`,0.01`,2.2998`,66.64`,12842.`,-6987.2`,1.4832`*^-7,0,20306},{2.5119`,0.01`,2.2998`,67.984`,14124.`,-6384.8`,1.0917`*^-7,0,20306},{1.9953`,0.01`,2.2998`,69.171`,15156.`,-5573.7`,9.8689`*^-8,0,20306},{1.5849`,0.01`,2.2998`,70.687`,15983.`,-4836.9`,1.3594`*^-7,0,20306},{1.2589`,0.01`,2.2998`,72.593`,16463.`,-4230.6`,1.2502`*^-7,0,20306},{1.`,0.01`,2.2998`,73.984`,16930.`,-3455.7`,3.2841`*^-8,0,20306},{0.794328`,0.01`,2.2998`,75.781`,17279.`,-2888.9`,1.5274`*^-7,0,20306},{0.630957`,0.01`,2.2998`,77.984`,17596.`,-2438.9`,1.6398`*^-8,0,20306},{0.501187`,0.01`,2.2998`,80.75`,17601.`,-2008.2`,1.0292`*^-7,0,20306},{0.398107`,0.01`,2.2998`,84.281`,17757.`,-1711.7`,1.4724`*^-7,0,20306},{0.316228`,0.01`,2.2998`,88.703`,17977.`,-1336.`,8.8738`*^-8,0,20306},{0.251189`,0.01`,2.2998`,94.281`,17843.`,-1267.2`,7.2326`*^-8,0,20306},{0.199526`,0.01`,2.2998`,101.234`,17884.`,-836.07`,3.4045`*^-7,0,20306},{0.158489`,0.01`,2.2998`,110.062`,17909.`,-1017.9`,2.1784`*^-7,0,20306},{0.125893`,0.01`,2.2998`,121.156`,18136.`,-838.7`,4.4451`*^-7,0,20306},{0.1`,0.01`,2.2998`,135.171`,18236.`,-612.38`,2.4244`*^-7,0,20306}};

Nyquist + Bode Plots

nyquistBodePlots=DynamicModule[
{dataPlot=ListPlot[Transpose[{zData[[All,5]],-zData[[All,6]]}],Frame->True,BaseStyle-> Large,FrameLabel-> {"Re[Z}","-Im[Z]"},ImageSize-> Large],
bodeZPlot=ListPlot[Transpose[{zData[[All,1]],Sqrt[zData[[All,5]]^2 + zData[[All,6]]^2]}],
Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","|Z|"},ImageSize-> Large],bodePhiPlot=ListLogLinearPlot[Transpose[{zData[[All,1]],(360/(2π)) ArcTan[-zData[[All,6]]/zData[[All,5]]]}],Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","ϕ (°)"},ImageSize-> Large],
vals,
wLower,wUpper,
colorFunction,
frequencyColoredPlotMarkersNyquist,frequencyColoredPlotMarkersBodeZ,frequencyColoredPlotMarkersBodePhi

},
{wLower,wUpper} = Through[{Min,Max}[First/@zData] ];
colorFunction[omega_]:= ColorData["AvocadoColors"][Rescale[Clip[Log[10,omega],{wLower,wUpper}],{0,1}]];
frequencyColoredPlotMarkersNyquist = 
{PointSize[0.02],Opacity[0.5],
Table[{colorFunction[zData[[i,1]]],Point[{zData[[i,5]],-zData[[i,6]]}]},{i,1,Length[zData]}]};
frequencyColoredPlotMarkersBodeZ = 
{PointSize[0.02],Opacity[0.5],
Table[{colorFunction[zData[[i,1]]],Point[{Log@zData[[i,1]],Log@Sqrt[zData[[i,5]]^2 + zData[[i,6]]^2]}]},{i,1,Length[zData]}]};
frequencyColoredPlotMarkersBodePhi = 
{PointSize[0.02],Opacity[0.5],
Table[{colorFunction[zData[[i,1]]],Point[{Log@zData[[i,1]],(360/(2π)) ArcTan[-zData[[i,6]]/zData[[i,5]]]}]},{i,1,Length[zData]}]};
dataPlot=ListPlot[Transpose[{zData[[All,5]],-zData[[All,6]]}],
Epilog-> frequencyColoredPlotMarkersNyquist,Frame->True,BaseStyle-> Large,FrameLabel-> {"Re[Z]","-Im[Z]"},ImageSize-> Large];
bodeZPlot=ListLogLogPlot[Transpose[{zData[[All,1]],Sqrt[zData[[All,5]]^2 + zData[[All,6]]^2]}],
Epilog-> frequencyColoredPlotMarkersBodeZ,Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","|Z|"},ImageSize-> Large];
bodePhiPlot=ListLogLinearPlot[Transpose[{zData[[All,1]],(360/(2π)) ArcTan[-zData[[All,6]]/zData[[All,5]]]}],Epilog-> frequencyColoredPlotMarkersBodePhi,Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","ϕ (°)"},ImageSize-> Large];
Manipulate[Grid[{
{
Show[dataPlot,
ParametricPlot[{1,-1}Through[{Re,Im}[model[w,{rSval,aWval,rCTval,nval,(10^(-6)) q0val}]]],{w,wLower,wUpper},PlotStyle-> Thick,
ColorFunction-> Function[{x,y,w},colorFunction[w]],
ColorFunctionScaling-> False,
Frame->True,BaseStyle-> Large,FrameLabel-> {"Re[Z]","-Im[Z]"}
,ImageSize-> Large,PlotPoints->50,MaxRecursion->15]
],
Show[bodeZPlot,LogLogPlot[Abs@model[w,{rSval,aWval,rCTval,nval,(10^(-6)) q0val}],{w,wLower,wUpper},PlotStyle-> Thick,
ColorFunction-> Function[{w,y},colorFunction[w]],
ColorFunctionScaling-> False,
Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","|Z|"}
,ImageSize-> Large,PlotPoints->50,MaxRecursion->15]]},{
Show[bodePhiPlot,LogLinearPlot[-(360/(2π)) Arg@model[w,{rSval,aWval,rCTval,nval,(10^(-6)) q0val}],{w,wLower,wUpper},PlotStyle-> Thick,
ColorFunction-> Function[{w,y},colorFunction[w]],
ColorFunctionScaling-> False,
Frame->True,BaseStyle-> Large,FrameLabel-> {"Frequency","ϕ (°)"}
,ImageSize-> Large,PlotPoints->50,MaxRecursion->15]],
Column[
{
Style[Text["(Subscript[Log, 10]) Norm Distance = "<>ToString[PaddedForm[Log[zDataComplexNorm[zData,model,{rSval,aWval,rCTval,nval,(10^(-6)) q0val}],10],
{8,3}]]],FontWeight-> Bold,FontColor->RGBColor[0.5,0,0],FontSize-> 14],
Style[Text["Solution Resistance = "<>ToString[PaddedForm[rSval,
{8,3}]]],FontColor-> Darker[Green],FontSize-> 16],
Style[Text["Warburg (Ohm (s^(-1/2))) "<>ToString[PaddedForm[aWval,
{8,3}]]],FontColor-> Darker[Green],FontSize-> 16],
Style[Text["Charge-Transfer Resistance (Ohm)"<>ToString[PaddedForm[rCTval,
{8,3}]]],FontColor-> Darker[Green],FontSize-> 16],
Style[Text["CPE exponent"<>ToString[PaddedForm[nval,
{8,3}]]],FontColor-> Darker[Green],FontSize-> 16],
Style[Text["CPE Capacitance (μF)"<>ToString[PaddedForm[  q0val,
{8,3}]]],FontColor-> Darker[Green],FontSize-> 16]
}
]

}}],
Style[Text["ImpedanceMatcher"],FontSize->24,FontWeight-> Bold],
Delimiter,
Dynamic[
Row[
{
OpenerView[
{Style[Text["Electrode Parameters"],FontSize->18,FontWeight-> Bold],
Grid[
{
{
Control[{{rSval,750,"Solution Resistance (Ohm)"},0,1000,Appearance->"Open",AppearanceElements->"InputField"}]
,Control[{{aWval,300,"Warburg (Ohm (s^(-1/2)))"},0,1000,Appearance->"Open",AppearanceElements->"InputField"}]
},
{
Control[{{rCTval,17500,"Charge-Transfer Resistance (Ohm)"},2000,20000,Appearance->"Open",AppearanceElements->"InputField"}],
Control[{{nval,0.9,"CPE exponent"},0,1,Appearance->"Open",AppearanceElements->"InputField"}]
},
{
Control[{{q0val,13,"CPE Capacitance (μF)"},1,20,Appearance->"Open",AppearanceElements->"InputField"}]

}
}
,Frame-> All
]
}

],
OpenerView[{Style[Text["Find Best Fit"],FontSize->18,FontWeight-> Bold],Button["click find nearest solution",{rSval,aWval,rCTval,nval,q0val} =N@{1,1,1,1,10^6}{rS,aW,rCT,n,q0}/.useApproximationToGetFit[rSval,aWval,rCTval,nval,(10^(-6) )q0val]]}]
}

,Spacer[48]
]
],
Delimiter,
(*Dynamic[
OpenerView[
{
Style[Text["Optimizing"],FontSize->18,FontWeight-> Bold],
Control[Button["click find nearest solution",vals ={rSval,aWval,rCTval,nval,q0val} ={rS,aW,rCT,n,q0}/.useApproximationToGetFit[rSval,aWval,rCTval,nval,q0val]]]
}
]
],*)
(*,
{{rSval,750,"Solution Resistance (Ohm)"},0,1000,Appearance->"Open",AppearanceElements->"InputField"},{{aWval,300,"Warburg (Ohm (s^(-1/2)))"},0,1000,Appearance->"Open",AppearanceElements->"InputField"},
{{rCTval,17500,"Charge-Transfer Resistance (Ohm)"},2000,20000,Appearance->"Open",AppearanceElements->"InputField"},
{{nval,0.9,"CPE exponent"},0,1,Appearance->"Open",AppearanceElements->"InputField"},
{{q0val,0.000012682`,"CPE Capacitance (F)"},0.000001,0.00002,Appearance->"Open",AppearanceElements->"InputField"},*)
(*Dynamic[Style[Text["(Subscript[Log, 10]) Norm Distance = "<>ToString[PaddedForm[Log[zDataComplexNorm[zData,model,{rSval,aWval,rCTval,nval,q0val}],10],
{8,3}]]],FontWeight-> Bold,FontColor->RGBColor[0.5,0,0],FontSize-> 14]
]*)
(*Control[Button["click find nearest solution",vals ={rSval,aWval,rCTval,nval,q0val} ={rS,aW,rCT,n,q0}/.useApproximationToGetFit[rSval,aWval,rCTval,nval,q0val]]],*)
SaveDefinitions->True
]]