Spice# Flow
The main structure of Spice# revolves around entities, behaviors, simulations and their simulation states.
When running a simulation, that simulation will ask for each entity to create behaviors for the simulation (the entity can add its behaviors to the simulation's IEntityBehaviorCollection). These behaviors are then called on by the simulation when they are needed.
These behaviors implement specific parts of the algorithm and is specific to the entity. For example, a Transient simulation requires several types of behaviors that a component might want to implement. The behaviors would then implement one or more of these interfaces:
- An ITemperatureBehavior that describes a method that tells the behavior that the temperature might have changed. The entity should recalculate anything that might have changed.
- An IBiasingBehavior that contains methods that are called each iteration in order to build up the Y-matrix and right-hand side vector.
- An IConvergenceBehavior that allows some influence over deciding whether or not a new iteration should be computed.
- An ITimeBehavior that gets called when it's okay to make time-dependent states that can be integrated.
Once all behaviors have been created by all entities, the simulation no longer has a need for any entities, and will continue to work with just behaviors.
Entities
An entity implements the IEntity interface. The main job of the entity is to create behaviors for simulations, at which point they are allowed to search for other entities that they are linked to (like a mutual inductance that searches for its inductors, or a component/instance that searches for its model). Each entity also has a name and can contain parameters.
In all Spice-based simulators the distinction is made between instances and models. Both are considered entities in Spice#, however the instance entity will ask the simulation for the model behaviors by using the model's name, allowing the model behaviors to be created first by the model entity. The instance entity can then use these model behaviors to create the instance behaviors. An instance entity in Spice# has been implemented through the IComponent interface.
Parameters and properties
Entities can contain one or more IParameterSet's that can be used by behaviors. They are usually simple classes with properties that contain information that needs to be passed down to the behaviors, like the resistance of a resistor or DC voltage of a voltage source, but they can just as well be used to describe anything. These parameters can be set directly by accessing the entity's members or, when implemented, they can also be set using their Spice "name". The name of a parameter is nothing more than a shorthand notation used by most Spice simulators to identify the parameter.
For example, the parameters of a resistor are defined in Parameters.
Property name | Names | Description | Remarks |
---|---|---|---|
Resistance | "resistance" or "r" | Resistance (ohms) | If not specified, the model is used to determine the resistance. |
TemperatureCelsius | "temp" | Instance operating temperature (degrees Celsius) | |
Width | "w" | Width (m) | Optional parameter that is only used if a model is specified. |
Length | "l" | Length (m) | Optional parameter that is only used if a model is specified. |
ParallelMultiplier | "m" | Number of resistors in parallel | |
SeriesMultiplier | "n" | Number of resistors in series |
It is possible to set the resistance of the resistor simply by using any of the following methods:
// Set resistance straight from the constructor to 1kOhm
var resistor = new Resistor("R1", "a", "b", 1e3);
// Set resistance using the property directly to 2kOhm
resistor.Parameters.Resistance = 2.0e3;
// Set resistance using the name of the parameter using reflection to 3kOhm
// Note: if you use 3e3 instead of 3.0e3, then this method will try to find
// a parameter of type "int" so make sure to specify a double!
resistor.Parameters.SetParameter("r", 3.0e3);
Entity collections
Entities can be grouped into collections using IEntityCollection. The name of each entity should be uniquely defined within that collection. The most used implementation of such a collection is Circuit.
Simulations
Simulations will manipulate behaviors in a way that is useful for modeling reality, like doing a transient simulation. In order for behaviors to work together, they can all gain access to shared simulation states. A simulation state can contain the current iteration solution's node voltages and branch currents for biasing simulations, but just as well the noise quantities for noise simulations, or the integration method used by a transient simulation.
Behaviors
Once behaviors are created, they should be self-sufficient. This means that any properties that you wish to be able to retrieve (even those defined in the entity) will need to be referenced or redefined in the behavior.
Simulation states
Simulation states are usually just classes that are only exposed through some interface that implements ISimulationState. They can come in many forms, but the most common one will probably be the IBiasingSimulationState. This simulation state contains the Y-matrix and right-hand side vector needed to iterate to a solution of the whole circuit.
Code in behaviors should be written in a way that is compatible with the simulation. Unforunately this takes some knowledge, but to help you along you can follow the section about custom components.