Little bitty capacitor model

24Nov06

By Josh Adams.

Here’s some code I wrote to model capacitor circuits. It passes all my tests so far, and it’s such concise code it’s hard to imagine it breaking…

First, some unit tests. A refresher on the physics, full I’m sure of flaws and misconceptions: A capacitor is rated at a voltage and capacitance. A pair of capacitors in series acts like a single capacitor whose voltage=cap1.voltage+cap2.voltage, and whose capacitance-1=(cap1.capacitance)-1+(cap2.capacitance)-1.

If it doesn’t make sense, skip ahead to the (better documented) class itself.

--- capacitor_test.rb ---

require 'test/unit'
require 'capacitor'

class CapacitorTest < Test::Unit::TestCase
  DELTA_TOLERANCE = 5e-15

  def setup
    @cap = Capacitor.new(3.3e-8, 1_200) # A 0.03 uF capacitor that can handle 1.2kV
  end
  def test_series_capacitance
    assert_equal 1.65e-8, (@cap*@cap).capacitance
  end
  def test_series_voltage
    assert_equal 2_400, (@cap*@cap).voltage
  end
  def test_exponentiation
    assert_equal Capacitor, (@cap**(2)).class
    assert_equal 2_400, (@cap**2).voltage
  end
  def test_parallel_capacitance
    assert_equal 6.6e-8, (@cap/@cap).capacitance
  end
  # For some reason I can't just assert_equal, because these values differ by some tiny amount.  Hence the delta stuff.
  def test_big_array_of_caps
    @string = @cap**10 # string 10 capacitors up in series configuration
    assert_in_delta 3.3e-9, @string.capacitance, DELTA_TOLERANCE
    @grid = @string%8    # string 8 of the series-strings up in parallel configuration
    assert_in_delta 2.64e-8, @grid.capacitance, DELTA_TOLERANCE
    assert_in_delta 12_000, @grid.voltage, DELTA_TOLERANCE
  end
end

Now, a bit of really basic abstract algebra. A boolean operation is an operation that takes a pair of elements of a set into a single element in the same set. So integer multiplication is a boolean operation because 2*3=6, where 2, 3, and 6 are all in the set Z (the integers). That is, *(2,3) maps to the integer 6.

Think of series wiring as a boolean operation. That is, a pair of capacitors maps to a capacitor with the same properties as the circuit itself. In this case, it makes perfect sense to just override a couple of boolean operators. It’s coming.


--- capacitor.rb ---
class Capacitor
  attr_accessor :capacitance, :voltage

  def initialize(cap, volt)
    @capacitance = cap
    @voltage = volt
  end

Just setting some basic attributes. Capacitors have a capacitance and a voltage, right? I’m expecting SI standard base units, so capacitance should be in Farads and voltage in Volts. So to instantiate a .033uF (.033 microfarad, or 33 nanofarad, or 3.3e-8 farad) capacitor that can take 1,200 volts, we would say @cap1=Capacitor.new(3.3e-8,1_200).

Now, to the binary operations! I’m defining * and / as ‘wired in series’ and ‘wired in parallel,’ respectively. Similarly, ** is exponentiation in the expected sense (using the * operator), so (@cap1**3) represents three identical capacitors wired in series. Similarly, again, I’ve defined % as the inverse of that exponentiation, so (@cap1 % 3) would represent three of the same capacitor wired in parallel.


  def *(cap2)
    Capacitor.new(1/((1/(capacitance))+(1/cap2.capacitance)), voltage+cap2.voltage) # Here I've just embedded the appropriate behavior for
                                                                                    # series capacitor behavior into the operator
  end
  def /(cap2)
    Capacitor.new((capacitance + cap2.capacitance), voltage)
  end
  def **(power)
    c=self
    (power-1).times{c=c*self}
    c
  end
  def %(power)
    c=self
    (power-1).times{c=c/self}
    c
  end
end

That’s all the code it takes to end up with a really rich fake-DSL 🙂

I can now do something like this (haven’t tried it, but I don’t feel that I need to :))


(@cap * @cap * @cap * @cap) /
(@cap * @cap * @cap * @cap) /
(@cap * @cap * @cap * @cap) /

This would represent, in a very (imnshobbqhax) pleasant and visually graspable way, a circuit with three strings of capacitors wired in parallel, each string consisting of four capacitors wired in series. This could be represented more succinctly, though it’s less visually analogous to reality:


(@cap**4)%3

Hope someone enjoyed that. Let me know if you see a place I could improve this, of course. Also, I’d like to figure out a nice way to represent circuits more fully. I can see an easy way to model resistors similarly, and use a case statement to determine what the circuit’s representation would be for each operation…but that case statement would probably be wrapped up in the * and / methods of some CircuitElement class that handled all the various interconnects. I don’t know, let me know if this was a decent read…

There’s a Google Code project set up right here.

Advertisements


No Responses Yet to “Little bitty capacitor model”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: