Advice on custom devices

Skip to first unread message

Aaron Goldstein

May 22, 2024, 4:37:18 PMMay 22
to xyce-users
Hello! I'm building a multi-physics program using Xyce, and I was hoping for some advice or suggestions on a way to architect custom device implementations in Xyce.

For some background an overall simulation may span T seconds (e.g. > 5000s), and is broken up into fixed t ms steps (100ms at smallest). For each step another program runs, then Xyce is called via simulateUntil as a transient simulation, where requested time is last time + t. There are a set of device primitives that conceptually exist within the other program and within Xyce, and parameters of those primitives in theory can only be changed at the scale of t; as in, before each simulateUntil call, the parameters for these primitives are updated.

For example some of those primitives are simple things like plain resistors; right now these just use the existing Xyce resistor model, and updates to its parameters (i.e. resistance) are handled by finding the associated DeviceInstance via getInstancePtrVec using the devices encoded name. For a resistor this isn't so bad since it shows up as a single device. But there are other primitives like a solar array; at the moment this is a SUBCKT with diodes/resistors with updatable effective illuminance - so updates to a single "Solar Array" require finding each and ever resistor and diode and updating their implied values accordingly.

I've separately implemented a Battery primitive as a genext/VectorComputeInterface. It was convenient to be able to implement my own parameter update function (e.g. updating a bias to series resistance), and although I don't mind the math I hit a roadblock getting the state of charge (SOC) DAE math implemented; the SOC impacts resistance/capacitance via an exponential, and I kept getting solution non-convergence errors (I think), which lead me to effectively keep the SOC constant within a given 100ms timestep.

As I'm reading more and more about Xyce I'm realizing there's a way to have more control over device implementation by writing a device plugin:

So I wanted to ask: between using SUBCKTs of existing devices, or implementing genext/VectorComputeInterface's, or this other device plugin approach - is there one you'd suggest using? I know for my scales Xyce is very much overkill, but I do very much appreciate the approachability and stability of the project in terms of customization.

Lastly, I'm happy to compensate for some advisory/consulting time, either directly or through Sandia (not sure what the rules are internally).


Tom Russo

May 22, 2024, 5:11:17 PMMay 22
to Aaron Goldstein, xyce-users
I can't answer your deeper query about the best way to model your system, but I would just like to point out that the general external interface as documented in the original 2018 app note was given a big update by another developer some years ago, but the documentation of that extension was never completed and published.  The publication of the updated app note was delayed because we never got around to crafting C++ examples using the updated capabilities the way we had generated examples for the simpler case, and then I retired before finishing the documentation.  However, I believe that the updated version of genext (which will require you to write some extra code) is precisely what you could use here.

The big update is that there is now a capability to write external device codes that support "voltage limiting."  The details of how voltage limiting works are in the Xyce Mathematical Formulation document, but it is exactly what is used in models such as the diode and bjt precisely because of the exponential terms in them.  I suspect that this technique is necessary for some of the types of devices you want to implement.

By using the "N_DEV_VectorComputeInterfaceWithLimiting.h" header instead of N_DEV_VectorComputeInterface.h" and implementing a somewhat augmented set of vector compute functions, you can detect that voltages have changed too much for your device to converge properly, and then compute the contributions of the device to a smaller change instead.  When you do this, you have to signal back to Xyce what you have done through additional vectors (very roughly speaking, you're returning an additional vector of the device Jacobian times the difference between the solution values you were given and the solution values you actually used).  

This is a standard SPICE trick, and was one of the things mentioned in the original GENEXT app note as something that had not yet been implemented at the time the original document was written.   It is unfortunate that we never finished writing it up after it got done.   The only things missing from the updated write up were actual usage examples, all the interface documentation and math documentation was completed.

Xyce team:  That incomplete document was still in the [non-public] Xyce_Docs repo when I left.  It'd be great to get it wrapped up and published, all it's missing is some example code.  A basic diode example would do (simpler than the one done in the Py-Mi regression test directory, which unfortunately includes some code (most of it commented out) that duplicates older versions of the Xyce diode that were removed in 2022 and makes it a little hard to follow and not suitable as a documentation tool).

At the moment, the only examples that use the vector compute interface with limiting are those associated with the Py-Mi project (a python-based capability that uses GENEXT).  Those examples are in the Xyce_Regression/Netlists/GenCoupAPI/models directory.  Py-Mi itself is documented in its own application note, but unfortunately I can't find it on the Xyce documentation page.  That should get fixed.  With a little digging, I found a copy here:   Sadly, it doesn't document the voltage limiting extensions, either.

You received this message because you are subscribed to the Google Groups "xyce-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
To view this discussion on the web visit

Tom Russo    KM5VY 
Tijeras, NM 

 echo "prpv_a'rfg_cnf_har_cvcr" | sed -e 's/_/ /g' | tr [a-m][n-z] [n-z][a-m]

Message has been deleted

Aaron Goldstein

May 23, 2024, 1:08:49 PMMay 23
to xyce-users
Thanks so much for the reply Tom - understood on all fronts. Although I did notice the comment about voltage limiting you mentioned in the GENEXT app note, I'll need to go through the Math Formulation doc again a few times before I fully comprehend. It's encouraging to hear it could work - I'll do some digging on my own on how to use N_DEV_VectorComputeInterfaceWithLimiting and in the meantime hope that incomplete doc gets published.

Thanks again!

Reply all
Reply to author
0 new messages