Open danieljfarrell opened 1 month ago
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.
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),
The netlist is solved over the specified voltage range and voltage step,
This returns a result object that can be queried or simply passed to helper functions to extract useful information.
There are also helpful functions to plot this information,
We can access 3D grid of node voltages using,
and then plot the surface voltage distribution (bias_index is the voltage corresponding to the maximum power point),
You can also make electroluminescence predictions (using generalised Planck scaling of the voltage distribution),
Examples
For more examples, see,
solcore/examples/cpv_grid_spice_example.py
, short and sweep script that shows how to call the new codesolcore/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. AHGridPattern
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,
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