Model¶
This is the most abstract part of the project. It is also the part where efficiency is most important. This includes both processing performance and memory usage. The model should never depend on the GUI, CLI, or file IO. There are multiple reasons for this:
This module might become its own library
It is the common denominator between the CLI and GUI and those should be separate. It is planned that these can be compiled separately.
The project is easier to maintain this way
Note
While we plan to make Ohmcha support nonlinear circuits and custom user circuits of any kind, only linear circuits are being implemented in the early stages. Everything that follows relates strictly to linear circuits.
Modelling a component¶
Everything that has at least a current and a voltage associated with it, is
represented as a component. A special case of a component is a branch.
Component is an abstract class. It contains a struct MetaInfo which
includes information about the component that is not needed for solving the
circuit, such as the component name.
For implementation details, see Component.
Modelling a branch¶
A Branch is a subclass of Component. While it is not an abstract class in C++ terminology, it is fairly abstract in that every two-terminal element and subcircuit can be represented as a branch. For example, a resistor and emf connected in series are to be represented as a single branch. Or, a single current source. Even parallel and combined connections can be represented this way, as long as that connection effectively has 2 terminals. It is advisable to combine connections into a single branch wherever possible, for increased performance.
In order to explain the model, an example is useful.
Example¶
Let’s look at an example that is used throughout the documentation:
Consider branch 1 in isolation – the branch number and the index of its current are identical in this representation.
The branch can be mathematically represented as:
We can rearrange this a bit:
or, in matrix form:
In fact, an arbitrary linear branch can be represented in this way:
where \(V_1\) is the voltage of the first node, and \(V_2\) of the second node this branch is connected to, and \(I\) is the current through. this branch. The order of these variables is determined using the following convention: current flows through a branch from node 1 to node 2. We will refer to this last equation as the constitutive relation of the branch.
For completeness, we will display the results for the other branches:
To sum up, the only things that an algorithm needs to know about this branch are: node 1, node 2, matrix \(\mathbf A\) and \(B\).
Note that by combining multiple components into a single branch, the branch itself does not retain information of each component that is part of it. For example, if a branch represents a series connection of a resistor and emf, you can use the algorithms to calculate the current through both of them, since it is a property of the branch. However, you can’t calculate the voltage drop on the resistor by merely knowing the mathematical model of the branch.
This is not a problem. Firstly, the algorithms don’t care. The algorithms’ only job is to find an explicit representation of the system. Secondly, since each component keeps a reference to its branch, by iterating through all components, one can find all variables, in a way that is less costly than the algorithms. Additionally, the user often won’t care about all the variables in the system. This is another performance boost.
Classes¶
Component¶
-
class
Ohmcha::Component Subclassed by Ohmcha::Branch, Ohmcha::CurrentSource, Ohmcha::Emf, Ohmcha::Node, Ohmcha::Resistor
Public Functions
-
Component *
copy() const = 0
-
void
setName(const std::string &name)
-
void
setPosition(Pos *position) Set the position of this component in the schematic. If position is null, the position is considered arbitrary.
-
void
setAngle(float angle)
-
void
setTextPos(const Pos &pos)
-
void
setTextAngle(float angle)
-
void
setTextOrientationIndependent(bool flag)
-
void
setTextAnchor(int anchor)
-
std::string
getName() const - Return
Name given by the user.
-
Pos *
getPosition() const See setPosition
-
float
getAngle() const
-
Pos
getTextPos() const
-
float
getTextAngle() const
-
bool
isTextOrientationIndependent() const
-
int
getTextAnchor() const
-
int
getTerminalCount() const = 0
Public Static Functions
Protected Attributes
-
MetaInfo *
metaInfo= nullptr
-
struct
MetaInfo Additional information that is not relevant for algorithms.
-
struct
Pos Public Members
-
float
x= 0
-
float
y= 0
-
float
-
Component *
Branch¶
-
class
Ohmcha::Branch: public Ohmcha::Component An electrical branch.
Public Functions
-
Branch() A default branch, equivalent to a short circuit.
-
Branch(const Branch &branch1, const Branch &branch2) Create a branch by merging two branches that contain a common node.
- Exceptions
TODO..if: they don’t have a common node
-
Branch(RowVector3f A, float B)
-
Component *
copy() const override
-
void
addComponent(Component *component, bool inverted = false)
-
void
setA(const RowVector3f &matrix)
-
void
setB(float x)
-
void
setNode1(Node &n)
-
void
setNode2(Node &n)
-
void
setNode1(Node *n)
-
void
setNode2(Node *n)
-
RowVector3f
getA() const
-
float
getB() const
-
Node *
getNode1() const
-
Node *
getNode2() const
-
int
getTerminalCount() const override
-
bool
hasNode(Node *node) const
Protected Attributes
-
Node *
node1= {} Current flows through this object from node 1 to node 2. Consequently, the reference voltage is positive if node 1 is at a higher potential than node 2.
-
Node *
node2= {}
-
RowVector3f
A A branch has three quantities: V1 (potential at node1), V2 (potential at node2), I (current from node1 to node2). to represent a linear branch, we require an equation A * transpose([ V1 V2 I ]) = B.
-
float
B
-
Resistor¶
-
class
Ohmcha::Resistor: public Ohmcha::Component Public Functions
-
Resistor()
-
Resistor(float resistance)
-
Component *
copy() const override
-
void
setResistance(float r)
-
int
getTerminalCount() const override
-
float
getResistance() const
-
Pos
getTextPos() const override
Private Members
-
float
resistance= 1
-
Custom Component¶
Custom user components are all represented as instances of CustomComponent. The attributes of this class are the number of terminals, the graphical representation (e.g. an image), and the mathematical model.
Todo
Custom user components are not implemented yet.