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

Update to SPICE grid modelling #284

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

danieljfarrell
Copy link

@danieljfarrell danieljfarrell commented Oct 7, 2024

Hello developers and old friends!

I have made some changes to the SPICE Quasi3D code, particularly how the netlist is generated and executed. This was originally a refactor but things went ... a bit too far, you know how it is 😄. I have left the original code unchanged but added new modules in the solcore/spice directory.

Please let me know what remains to be done before you will accept the pull-request. The unit tests I run are passing locally but I see they are failing on GitHub, I think because the environment does not have SPICE installed and one of the tests called the solver.

Standalone simple Python interface

This code is standalone; it uses basic Python types to define the solar cell's junction rather than using Solcore's Junction class. Future changes may want to alter this, but I'm uncertain about the value that Junction offers; it seems to resemble an OrderedDict. Perhaps this would unlock useful integration with other Solcore features? I am not familiar enough with Solcore to make a proper judgement call here, so please let be know what you think.

A comment in passing - When starting to develop this is was quite hard to read the code to see how the example code works. In the end I needed to run the code and spend a long time with a debugger trying to understand things. This is because the code is so dynamic. Originally I thought the Junction object did something, rather than just being a bucket for values. The plugin nature was another reason following the execution was a little tricky; for example, when solving a solar cell the solver that is used is determined at run time. I guess these are simply the pros and cons of Python and you can call them a feature too if you like.

What I have tried to do with the code here is make it as readable as possible. I hope you can read the new files and get a feel for what the code does without running the new examples in the debugger.

A quick overview

You generate a netlist from a minimal number of inputs (keyword arguments are used here to specify resistivity and material parameters different from the default values),

netlist = generate_netlist(
    cell_grid,
    cell_illumination_map,
    cell_size,
    junctions
)

The netlist is solved over the specified voltage range and voltage step,

# From -0.1V to 1.5V in steps of 10mV
result = solve_netlist(netlist, temperature, -0.1, 1.5, 0.01)

This returns a result object that can be queried or simply passed to helper functions to extract useful information.

V, I = get_characterisic_curve(result)
vmax, pmax, maxidx = get_maximum_power_point(result)

There are also helpful functions to plot this information,

plot_characteristic_curve(V, I)

We can access 3D grid of node voltages using,

voltages = get_node_voltages(result)

and then plot the surface voltage distribution (bias_index is the voltage corresponding to the maximum power point),

plot_surface_voltages(voltages, bias_index=maxidx)

Layer_Voltages

You can also make electroluminescence predictions (using generalised Planck scaling of the voltage distribution),

pv_surface_voltages = voltages[:, :, 1, maxidx]
el = get_electroluminescence(pv_surface_voltages, is_metal=cell_grid.is_metal)
plot_electroluminescence(el)

EL_Prediction

Examples

For more examples, see,

  1. solcore/examples/cpv_grid_spice_example.py, short and sweep script that shows how to call the new code
  2. solcore/examples/cpv_grid_spice_example.ipynb, a much more detailed example with some discussion and ending in a script that uses solcore to calculate the short-circuit current of a solar cells and uses the new SPICE model to compute an efficiency verse concentration plot.

PySpice

The netlist is solved using PySpice. This removes the need for code in Solcore to kick off a simulation and process the result using text parsing. I have not looked too closely at the solcore code, but usually text parsers are quite brittle; changes to the netlist, naming conventions etc. can break it etc. Handing this over to PySpice improves this situation because essentially a different project is maintaining that code for you.

It also integrates nicely with the way solcore specifies that SPICE path.

This adds one dependency.

Grid Pattern

I added an class called Grid Pattern that defines an interface/API for rendering any metallisation pattern for the front surface of the solar cell. Subclassing, enables the creation of various grid types. The user needs to implement a function called draw() and use the pixie-python drawing API to render the desired grid pattern. A HGridPattern subclass has been implemented here. This class offers some useful functionality, such as being able to save the grid pattern to an image file, which uses pillow (PIL).

This adds two dependences.

For example,

bus_px = 10
fingers_px =  [4, 4, 4, 4, 4, 4]
offset_px = 3
nx, ny = 120, 120
grid = HGridPattern(bus_px, fingers_px, offset_px=offset_px, nx=nx, ny=ny)
plt.imshow(grid.as_array(), cmap="gray")

H grid

This uses the scheme that white = bus, grey = grid finger and black = no metal.

I think programmatic approach to grid generation might be quite useful in the future particularly if connecting it with optimisation algorithm to design metallisation.

Object orientated netlist construction

Take a look at solcore/spice/model.py and you will find objects for each sub-circuit in the distributed spice model: Metal, Bus, Device (junction), Diode (junction in the dark), Base, RearContact.

Before constructing the netlist we first arrange these object in a 3D grid (a numpy array) to define the structure of the solar cell we want to solve. We then process the 3D array and generate the netlist.

A nice result of this approach is the ease connecting the distributed sub-circuits together without the use of "wires". Moreover, because the spatial arrangement is known a priori and objects represent neighbouring circuits it becomes easy to label all of the nodes in the 3D mesh.

Also, this approach is quite testable. Unit tests define the required node naming conventions for each object.

Solution result object

A result object is passed around to helper functions to generate useful information such as the IV curve, maximum power point, voltages of the different layers, and electroluminescence prediction.

Background

The model seems more or less the same. It follows the methodology of Steiner et al. DOI:10.1002/pip.989 ( I did not go to the trouble of adding the perimeter recombination diode). Note, this model lacks shunt resistances because it targets concentrator solar cells, but adding them could broaden its application, I can do that if needed.

Documentation

I have updated the documentation by editing the existing Quasi3D document. Hope this was OK?

Looking forward to hearing from you!

Dan

We have refactored the netlist generation code to use model objects that
generate a netlist. The netlist is solved using PySpice. This removes
the need for code in Solcore to kick off a simulation and process the
result using text parsing. I have not looked too closely, but parser
code is usually quite brittle; changes to the net list can break it.
Handing this over to PySpice improves the situation.

A result object is passed around to helper functions to generate useful
information such as the IV curve, maximum power point, voltages of the
different layers, and electroluminescence prediction.

The distributed model closely aligns with the methodology of Steiner
et al. DOI:10.1002/pip.989, except for the absence of the perimeter
recombination diode. This model lacks shunt resistances, but adding them
could broaden its application beyond concentrator solar cells.

This code is standalone; it uses basic Python types to define the solar
cell's junction rather than using Solcore's Junction class. Future
changes may want to alter this, but I'm uncertain about the value that
Junction offers; it seems to resemble an OrderedDict. Perhaps this would
unlock useful integration with other Solcore features.

A nice feature of the code is a class for generating grid metalization
patterns: GridPattern. This offers a general interface for subclassing,
enabling the creation of various grid types. The user needs to implement
a function called `draw()` and use the pixie-python drawing API to
render the desired grid pattern. A HGridPattern subclass has been
implemented here. This class offers some useful functionality, such as
being able to save the grid pattern to an image file, which uses pillow
(PIL).

We have added a sparse example script. We have added a much more
detailed Python Notebook file that guides the user through the entire
process, from basic simulation to computing a concentration vs.
efficiency plot.
The netlist is solved using PySpice in the latest code, this
simplifies the code a bit and also allows this code to be moved
out of solcore (at a later date, if wanted).

The new GridPattern classes use a pixel drawing API from
Pixie (pixie-python module)
@phoebe-p
Copy link
Member

phoebe-p commented Oct 7, 2024

Hi Dan, I will have a more detailed look later, but re: the tests, all the environments (Windows, macOS, Ubuntu) should have ngspice installed, see the workflow file. I assume this mean that SPICE is also installed? I should probably know this but I have never really used either of them so I don't really even know what the difference is... Looking up the error thrown in the Ubuntu tests gives me this. You can try modifying the workflow file to get the tests running on at least one operating system; then we can always exclude them from the others using an approach similar to that used in test/test_optics.py which skips tests relating to S4 if it's not installed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants