Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Execution Graph and Computation Optimization #27

Merged
merged 7 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Documentation and docstring improvements:
* Added speed benchmark for graph-based function evaluation to examples
* Added release notes
* Improved CircuitGraph class docstrings
  • Loading branch information
yuefan98 committed Jan 14, 2025
commit 2457aa165771b151431c71d78022af3fe7744d3a
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Todo: change to pydata_sphinx_theme
# html_theme = 'pydata_sphinx_theme'

# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
Expand Down
3 changes: 2 additions & 1 deletion docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Examples
:maxdepth: 1
:glob:

examples/nleis_example
examples/nleis_example
examples/graph_example
632 changes: 632 additions & 0 deletions docs/source/examples/graph_example.ipynb

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Welcome to :code:`nleis.py`'s documentation!
nleis_fitting
visualization
data-processing

release-notes


Indices and tables
==================
Expand Down
45 changes: 45 additions & 0 deletions docs/source/release-notes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
====================
Release Notes
====================

.. Version 0.2
.. ---------------------------


Version 0.1.1 (2025-01-06)
---------------------------
This is the official release for the JOSS paper.

**What's Changed**

- Documentation updates by @dt-schwartz and @yuefan98
- Bug fixes by @yuefan98 in https://github.com/yuefan98/nleis.py/pull/25

**Full Changelog**: https://github.com/yuefan98/nleis.py/compare/v0.1...v0.1.1

Version 0.1 (2024-09-26)
-------------------------
We are excited to announce the first official release of nleis.py! This release marks a significant step forward for nonlinear impedance analysis and will be submitted to JOSS for peer review.

**Key Features:**

- Simultaneous fitting and analysis of EIS and 2nd-NLEIS.
- Full support for nonlinear equivalent circuit (nECM) modeling and analysis.
- Various linear and nonlinear circuit element pairs derived from existing literature.
- Seamless integration with impedance.py for expanded impedance analysis capabilities.

**Improvements:**

- Comprehensive [documentation](https://nleispy.readthedocs.io/en/latest/), including a Getting Started guide and API reference.
- Improved documentation for supported circuit elements.
- Improved code handling for better performance and readability.

**Bug Fixes**

- Initial testing and issue resolution to ensure smooth functionality.

**New Contributors**

- Special thanks to @mdmurbach for joining the team and enhancing the package quality.

**Full Changelog**: https://github.com/yuefan98/nleis.py/commits/v0.1
33 changes: 33 additions & 0 deletions nleis/fitting.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,13 +613,18 @@ def extract_circuit_elements(circuit):


class CircuitGraph:
'''
A class to represent a circuit as a directed graph.
'''
# regular expression to find parallel and difference blocks
_parallel_difference_block_expression = re.compile(r'(?:p|d)\([^()]*\)')

# regular expression to remove whitespace
_whitespce = re.compile(r"\s+")

def __init__(self, circuit, constants=None):
'''
Initialize the CircuitGraph object.'''
# remove all whitespace from the circuit string
self.circuit = self._whitespce.sub("", circuit)
# parse the circuit string and initialize the graph
Expand All @@ -630,6 +635,9 @@ def __init__(self, circuit, constants=None):
self.constants = constants if constants is not None else dict()

def parse_circuit(self):
'''
Parse the circuit string and initialize the graph.
'''
# initialize the node counters for each type of block
self.snum = 1
self.pnum = 1
Expand Down Expand Up @@ -688,6 +696,9 @@ def parse_circuit(self):
# function to add series elements to the graph

def add_series_elements(self, elem):
'''
Add series elements to the graph.
'''
selem = elem.split("-")
if len(selem) > 1:
node = f"s{self.snum}"
Expand All @@ -702,11 +713,16 @@ def add_series_elements(self, elem):

# function to visualize the graph
def visualize_graph(self, **kwargs):
'''
Visualize the graph.'''
pos = nx.multipartite_layout(self.graph, subset_key="layer")
nx.draw_networkx(self.graph, pos=pos, **kwargs)

# function to compute the impedance of the circuit
def compute(self, f, *parameters):
'''
Compute the impedance of the circuit at the given frequencies.
'''
node_results = {}
pindex = 0
for node in self.execution_order:
Expand All @@ -733,6 +749,9 @@ def compute(self, f, *parameters):
# To enable comparision

def __eq__(self, other):
'''
Compare two CircuitGraph objects for equality.
'''
if not isinstance(other, CircuitGraph):
return False
# Compare the internal graph attributes
Expand All @@ -742,14 +761,25 @@ def __eq__(self, other):
# To enable direct calling

def __call__(self, f, *parameters):
'''
Compute the impedance of the circuit at the given frequencies.
And convert it to a long array for curve_fit.
'''
Z = self.compute(f, *parameters)
return np.hstack([Z.real, Z.imag])

def compute_long(self, f, *parameters):
'''
Compute the impedance of the circuit at the given frequencies.
And convert it to a long array for curve_fit.
'''
Z = self.compute(f, *parameters)
return np.hstack([Z.real, Z.imag])

def calculate_circuit_length(self):
'''
calculate the number of parameters in the circuit
'''
n_params = [
getattr(Zfunc, "num_params", 0)
for node, Zfunc in self.graph.nodes(data="Z")
Expand All @@ -758,4 +788,7 @@ def calculate_circuit_length(self):


def format_parameter_name(name, j, n_params):
'''
Format the parameter name for the given element.
'''
return f"{name}_{j}" if n_params > 1 else f"{name}"
3 changes: 3 additions & 0 deletions nleis/nleis_elements_pair.py
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,7 @@ def TDCn(p, f):
def A_matrices_TLMn(N, Rpore, Z12t):
"""
Construct the matrix `Ax` for the TLMn model

Parameters
----------
N : int
Expand All @@ -1087,10 +1088,12 @@ def A_matrices_TLMn(N, Rpore, Z12t):
Pore electrolyte resistance
Z12t : np.complex128
The single element impedance at 2ω

Returns
-------
Ax : np.ndarray
The matrix `Ax` for the TLMn model

"""

Ax = np.zeros((N, N), dtype=np.complex128)
Expand Down
Loading