jdhuang-csm / hybrid-drt

Probabilistic electrochemical analysis with the distribution of relaxation times (DRT)
BSD 3-Clause "New" or "Revised" License
8 stars 2 forks source link

Method to remove series inductance in dual_fit_eis? #6

Open GomaruSai opened 1 week ago

GomaruSai commented 1 week ago

Hi! Hybrid DRT has been great so far, thanks for your contribution to the community!

I have tried fitting my data using RQs using impedance.py and was able to get better fits as I do not use a series inductance parameter (I have negligible parasitic impedance) compared to dual_fit_eis using element_type set to 'RQ.' I believe removing this element will improve my fits and get me more accurate results. Is there a way to do this?

Hybrid DRT is much better than the other libraries I have used because of its robust and fast initial value and model prediction, the option for explicitly specifying custom ECMs (like R-RC-HN-RQ, for example) in dual_fit_eis in order to prevent overfitting and reduce the parameter space, would be greatly appreciated!

Thanks in advance!

jdhuang-csm commented 6 days ago

Hi, thanks for the kind feedback!

You can enable or disable inductance by setting the fit_inductance attribute, either at or after instantiation:

# At instantiation
drt = DRT(fit_inductance=False)
# After instantiation
drt.fit_inductance = False

Note: you can also toggle ohmic resistance and capacitance in the same way with the attributes fit_ohmic and fit_capacitance.

dual_fit_eis is intended primarily to provide a rough initial suggestion of circuit models that might be appropriate to describe your spectrum. You can specify the type of element to use to describe each identified DRT peak as described in issue #3. However, because dual_fit_eis attempts to identify many different candidate models, at the moment it is not possible to specify a custom model with different elements (because the custom model would need to have a different number of elements for each candidate identified) or automatically select the element type for each identified peak. Automatic element selection based on peak shape could be a nice future enhancement.

The good news is that you can take a conventional DRT estimate (obtained with fit_eis) and convert it to a custom discrete element model by using the DRT to identify initial parameter estimates and bounds. The code to do so:

from hydrt.models import DiscreteElementModel
# Estimate the DRT
drt.fit_eis(f, z)
# Create a DiscreteElementModel instance from the DRT, automatically identifying peaks 
# and using RQ elements to describe them
dem = DiscreteElementModel.from_drt(drt, drt_element=”RQ”)
# Alternatively, create a DiscreteElementModel instance from the DRT using a custom model
# In this case, the identified peaks must match the number of resistive-capacitive elements 
# in model_string (in this case, 3 elements, since the ohmic resistance does not contribute to the DRT).
# You can specify peak indices manually as shown below, where tau_grid is a grid of tau values at which
# the DRT is evaluated, and peak_indices are the indices of the tau_grid at which peaks appear.
dem = DiscreteElementModel.from_drt(drt, model_string=“R0-RC1-HN2-RQ3”, tau=tau_grid, peak_indices=[a, b, c])
# In either case: after creating the dem, you then need to fit it to the data
# Setting prior=True will apply a prior to favor parameter values that are close to the initial DRT estimate, 
# which can sometimes improve fit consistency. 
# Disable this if you just want to use the initial parameter estimates without any bias.
dem.fit_eis(f, z, from_drt=True, prior=True)

The DiscreteElementModel class is also a fully functional ECM fitting class that can be used without an initial DRT estimate. It uses analytical Jacobian calculations to improve fit accuracy and speed. For example:

dem = DiscreteElementModel(model_string=“R0-RC1-HN2-RQ3”)
# View the model parameters
dem.parameter_names
# Fit the model. You can provide initial bounds as a 1d array via init_values (same order as parameter_names).
# You can also set bounds prior to calling fit_eis using dem.set_bounds (see docstring)
dem.fit_eis(f, z, init_values=init)

hybrid-drt is in great need of improved documentation, but it has been very difficult to find the time as a postdoc working on other projects. I appreciate your patience :)