ACMI Mutual Inductance Calculator

ACMI: A program to compute Air Core Mutual Inductances.

    origin: http://abelian.org/acmi/
maintainer: Paul Nicholson, acmi1611@abelian.org

version: v0.8b, 1st March 2002

Those wishing to calculate coupling coefficients for Tesla coils may prefer to use MANDK, written by Mark Rzeszotarski, which is better documented, easier to use, and probably more accurate. See bottom of page for links.

Introduction

This program calculates the self and mutual inductances for coupled systems of air-cored concentric windings. Handles straight cylindrical solenoids, cones, flat spirals, anything so long as all turns are concentric.

It only does single layer windings. The program handles any number of windings.

IMPORTANT NOTE: This program only calculates inductances. At high frequencies, stray capacitance between windings can have a big effect on apparent inductance and coupling coefficients - ACMI does not calculate these.

Download

Unix: download acmi-0.8b.tgz and compile the program yourself according to your local C compiling conventions. A typical compiler command would be: cc -o acmi acmi.c -lm.

DOS and Windows: You can also compile the program as above, or instead, download acmi-0.8b.zip containing a pre-compiled DOS executable.

Both packages contain some sample input files:

      thor.in  (Tesla coil: Marco Denicolai's Thor system: primary, secondary, toroid)
      flat.in  (Flat transformer: Flat spiral primary, flat spiral secondary)
     helix.in  (CW Tesla coil: helical primary, helical secondary)
      cone.in  (Tesla coil: Cone primary, helical secondary
      dual.in  (dual primaries, secondary, toroid, and an extra feedback winding)
      xfmr.in  (Transformer: A closely coupled impedance matching transformer)
    sphere.in  (Nested spherical coils)
     parab.in  (Parabolic primary)
 helix-opt.in  (Optimum H/D for a helix)
  flat-opt.in  (Optimum shape for a spiral)
sphere-opt.in  (Optimising a spherical coil)
      test.in  (A thing to test ACMI input file interpretation)
The input files are just plain text files that you can modify with a text editor. They don't have to be .in, you can give them any name extension you like.

Quick Start

Run the program by piping the input file into the program, eg
   ./acmi < thor.in
If you're running from the MS-DOS command prompt, you don't need the ./ bit - that's just a unix thing. Results appear on standard output, unless you redirect it to a file with
   ./acmi < thor.in > thor.out
Command line options -csv and -html will change the output format from the default plain text, eg.
   ./acmi -html < thor.in > thor.html
Run
   ./acmi -help 
to get a full list of command line options.

The Input File

ACMI is a general purpose program and therefore requires an input file whose grammar and syntax is flexible enough to describe any combination of concentric circular windings. The rest of this document describes the input file.

Coil Descriptions

A coil is described by a name, following by an opening brace, a list of parameters, and then a closing brace, for example,
  primary {
     radius1 10
     radius2 10
     height1 0
     height2 5
     turns 500
     conductor 22 awg
  }
radius1 and height1 give the position of one (any) end of the winding; radius2 and height2 give the position of the other end. In this case, radius1 and radius2 are the same, so we have a cylindrical coil of 10 units radius and a height of 5 units. All the heights are relative, so the same coil could be described just as well with
   height1 42.7
   height2 47.7
The parameters can be written in any order within the braces, and you don't have to use this particular layout - you could for example write this coil as
  primary { radius1 10 radius2 10
            height1 0 height2 5
            turns 500 conductor 22 awg }
You can name the windings anything you want, and you can put in as many windings as you like. The program will compute the self inductance of each, and the mutual inductance between every pair. The order in which the windings appear in the input file doesn't affect the calculations, but it does determine the ordering of columns in the output tables.

Units

All the length measurements are in metres by default. You can specify inches with the statement units inches, following which, dimensions are assumed to be in inches, eg
  units inches

  primary {
      radius1 4
      radius2 4
      height1 10
      height2 20
      units metres
      conductor 0.1e-3
   }
will take the radius and height to be in inches, but the wire radius will be 0.1 mm.

If a winding has constant radius, you can specify

   radius 4
which is equivalent to
   radius1 4
   radius2 4
and similarly for the height if you have a flat horizontal winding.

The wire radius can be given in AWG by

   conductor 24 awg
or as a radius, eg
   conductor 0.25e-3

Temperature

The program assumes 25 degC when calculating winding resistances. This can be altered (globally) by specifying
   ambient 10    ; Use 10 degrees Centigrade instead of 25.
somewhere in the input file, but outside of any coil clauses.

Ranges

All dimensions can be given ranges, and the program will tabulate the self and mutual inductances for every combination, eg
   units inches
   secondary {
      radius 4
      height1 0
      height2 [from 10 to 20 step 2]
      turns 800
      conductor 20 awg
   }
calculates the inductance of a secondary with lengths 10", 12", 14", ... 20". You can specify as many ranges as you like, eg
   units inches
   secondary {
      radius [from 4 to 8 step 1]
      height1 0
      height2 [from 10 to 20 step 2]
      turns [from 200 to 1000 step 100]
      conductor [from 20 to 26 step 2] awg
   }
will compute the inductance of coils with 5 radii, 6 lengths, 4 conductor sizes, for turns of 200, 300, ... 1000, a total of 1080 coils.

Named Variables and Expressions

You can replace any of the numbers in a coil description (or a range) with an expression, and you can define named variables, for example,
   units inches

   min_diam = 4             ; define a variable min_diam to have the value 4
   max_diam = min_diam + 4  ; this sets a variable max_diam to 8
   my_steps = 5             ; and we define another variable called my_steps

   base = 0.5               ; etc, etc
   sec_length = 12

   secondary {
      radius [from min_diam to max_diam step (max_diam - min_diam)/my_steps]/2  
      height1 base 
      height2 base + sec_length
      turns 1000 conductor 22 awg
   }
Note the divide by 2 in the radius parameter. You can specify a range within a variable definition, for example, you can slide a fixed height cylindrical primary up and down with,
   units inches
   base = [from 0 to 5 step 1]
   
   primary {  radius 8
              height1 base
              height2 base + 10  ; 10" primary cylinder length
              turns 10 conductor 10 mm
           } 
In fact, you can make up arbitrary expressions for coil dimensions with any number of defined variables, and you can put a range [from .. to .. step ..] anywhere where a number would otherwise go. ACMI's grammar of expressions, variables, and ranges is completely general, so for example, the from and to values within a range can themselves be ranges, ie
   [from [from 0 to 5 step 2] to [from 40 to 50 step 2] step 1]
is legal, although not particularly meaningful. For example to compute for a wide range of closewound flat primaries, you could use
   units inches

   inner_radius = [from 5 to 30 step 1]
   outer_radius = [from inner_radius + 2 to 32 step 1]

   primary { height 0
             radius1 inner_radius
             radius2 outer_radius
             conductor 0.25 
             turns (outer_radius - inner_radius)/0.5
           }
which explores a range of primary widths greater than 2 inches, and computes a suitable number of turns for each to make the spiral coils closewound.

Non-uniform profiles

So far, all the coil examples have had a uniform profile of their cross-section through the axis. If a non-uniform profile is required, say for example a parabolic cross section, then the expressions for height and radius must be parameterised. The program will accept a dummy variable S which ranges from 0 to 1 linearly with the turns. Thus, for a parabolic winding of inner radius 10 and outer radius 20, inner height 5 and outer height 10, the description
  coil {
      radius 10 + S*10
      height 5 + S*S*5
      ...
  }
would have the desired effect, with the turns uniformly pitched in the horizontal direction, and with a quadratically increasing vertical pitch. If the same profile is required but with a uniform vertical pitch, you would instead use
  coil {
      radius 10 + sqrt(S)*10
      height 5 + S*5
      ...
  }
and an example of a spherical coil profile might be
  theta = S * 3.14159   ; Make theta vary from zero to PI linearly with the turns

  coil {
      radius  10 * sin( theta)
      height  10 - 10 * cos( theta) 
      ...
  }
which will produce a spherical coil of 10 units radius.

Of course, expressions involving the special variable S can contain named variables and ranges, just like any other ACMI expression.

Conditional Expressions

You can use the operators >, <, and = within ACMI expressions. These operators return the value 1 if the condition is true, otherwise 0. These may be employed in conditional expressions using a tertiary operator syntax identical to that of the 'C' language. For example
   r = S < 0.5 ? 0.1 : 0.1 + 0.9*2*(S - 0.5)
which describes the radius of a funnel shaped coil, with a stem of 0.1 radius, which expands above S = 0.5 to a radius of 1.0 at S = 1.0. The general format of the tertiary operator is
   conditional_expression ? true_expression : false_expression
The conditional_expression is evaluated, and if true, the whole expression takes on the value of true_expression, otherwise it takes the value of false_expression. These conditional expressions are useful for generating discontinuous coil profiles, for example, a double cone, base-to-base,
   max_radius = 0.2
   coil {
      radius max_radius * 2 * (S < 0.5 ? S : (1-S))
      height S
      ...
   }
By cunning use of conditionals, almost any discontinuous shape can be defined. Another use of conditionals is to delete undesired geometries in an optimisation expression, discussed later.

Output Statements

If the input file contains only coil descriptions, then ACMI will choose a predefined set of output columns. You can override this behaviour with the show statement.
   primary {  radius1 4.0  radius2 8.0  height 0 conductor 0.1 turns 10 }
   show self(primary)*1000 as "inductance" format "7.3 mH"
Here, the show command is requesting a column headed 'inductance', to contain the primary self inductance times 1000, and the data in this column will be formatted to 7 digits, with 3 digits after the decimal point.

You may specify your own text to follow the data, as with the mH after the 7.3

The general form of the show statement is

   show expression as "heading text" format "format specifier" 
The expression can be any ACMI expression, and you can put in as many show statements as you like.

If you use any show statements at all, then the default output of ACMI is turned off, and you will have to provide a show statement for every column that you want.

show statements must appear further down the input file than the coils they refer to. The heading and format specifiers must be quoted. Output column widths will be made wide enough to accomodate the heading and the data format, whichever is the greater. The output columns will be generated in the same order that the show statements appear in the input file.

The function self() is one of a number of coil data functions that you can use within show expressions, see the next section.

Coil Data Functions

There are several functions that you can use in expressions in the show command. Each function takes either one or two coil names as arguments.

self( coil) Returns the coil's self inductance in Henries
resistance( coil) Returns the coil's DC resistance, in Ohms
length( coil) Returns the coil's total wire length, in Metres
mutual( coil1, coil2) Returns the mutual inductance between the two coils, in Henries
coupling( coil1, coil2) Returns the coupling coefficient between the two coils

All these functions return a floating point value, which can be used in arbitrary expressions. For example, an ACMI input file to generate the calibration chart for a variable inductor formed from two series connected concentric solenoids,

   relative_height = [from 0 to 0.8 step 0.1]
   coil1 {
       radius 0.2
       height1 0
       height2 0.5
       conductor 21 awg turns 100
      }
   coil2 {
       radius 0.21
       height1 relative_height 
       height2 relative_height + 0.5
       conductor 21 awg turns 100
      }
     
   total_self = self(coil1) + self(coil2)
   total_mutual = 2 * mutual(coil1, coil2)
    
   show relative_height as "coil position"
   show (total_self + total_mutual)*1e3 as "Total L(+)" format "7.3 mH"
   show (total_self - total_mutual)*1e3 as "Total L(-)" format "7.3 mH"
ACMI will quite rightly object if you try to use one of these coil data functions within the coil's own description clause. For example,
   my_coil {  ...
             radius = length( my_coil)/(2*pi*turns)
          }
makes no sense and ACMI will reject it. However, you can refer to data from another coil, for example to choose the radius of my_coil to match the wirelength of my_coil with his_coil,
   his_coil {
       radius [from 0.1 to 0.3 step 0.1]
       height1 0 height2 0.5
       conductor 21 awg turns 100
   }
   
   my_turns = 50
   my_radius = length(his_coil)/(2 * pi * my_turns)
   my_coil {
       radius my_radius
       height1 0 height2 0.2
       conductor 21 awg turns my_turns
   }
has the desired effect.

Optimisation

ACMI can be made to automatically optimise a given expression, using the maximise and minimise statements. For example,
   primary {
       radius1 [from 2.0 to 3.0 step 0.1]
       radius2 [from 6.0 to 8.0 step 0.1]
       height 0 conductor 0.1 turns 10 
      }
  
   minimise abs( self(primary) - 950e-6)
will examine the given ranges of coil dimensions, and report the particular values which bring the self inductance closest to 950uH. Normal output is suppressed, and only a single row of data, corresponding to the optimum settings of the ranges, is generated. The available optimisation commands are minimise and maximise. Only one optimisation statement can appear in the input file.

Conditional expressions may be used to remove unwanted combinations from an optimisation expression. For example, if we wished to optimise the inductance of a coil, but we had to work with a maximum limit on the wire length, we could write

   maximise wirelength(coil) < available_length ? self(coil) : 0
which forces to zero, and therefore excludes, any geometry which exceeds our available length of wire.

For more examples of optimisation, see helix-opt.in, flat-opt.in, and sphere-opt.in

Profiling

It is often useful to know the distribution of induced voltage within a winding, and ACMI can provide this information using the profile command. For example, the input file statement
   profile coil2 from coil1
will generate a three column output describing the induced voltage distribution in coil2 resulting from a dI/dt of 1 Amp/Sec in coil1. The three columns of output are turn number, volts/turn, and accumulated voltage. The number of turns in coil2 is rounded to the nearest integer to provide the range of column 1. The first turn corresponds to the point specified by radius1, height1, or S=0, in coil2's description clause. Typically, the user will run acmi with -csv -heading options and pass the output data into a spreadsheet. The user will then multiply the two voltage columns by the factor 2*pi*frequency*coil1_current to find the actual induced voltages for a given current in coil1.

A profile statement must appear further down the input file than the coils it refers to.

Only one coil can be profiled on each run of acmi, and when a profile statement is given, the normal output of ACMI is suppressed. show and optimisation statements are ignored when profiling. At present, range variables are not allowed when profiling.

For Experts

The input file to ACMI is a declarative rather than a procedural language, so that a statement such as
  theta = S * 3.14159
means that theta is defined to be S * 3.14159, as opposed to a one-off assignment. This is true of all expressions in ACMI. Thus, if you have say, a system composed of two spherical coils, they can share the same declarations involving S, despite the fact that internally, two instances of S are involved - one for each coil, when computing the mutual inductances.

Forward references to variables and coils are not allowed. This is not a restriction, since the graph of expressions and ranges must remain acyclic (ie tree-like) to be meaningful - hence no recursive declarations - hence no forward references.

ACMI uses a very simple top-down recursive descent parser for the input file, a postfix internal representation for expressions, and a double-precision stack for expression evaluation. All this makes it very easy for the user to add to the program's semantics if required.

The built-in optimisations are very crude. For all but the simplest applications you will prefer to bury ACMI inside your own optimisation script. Use sh, awk, or pike, etc, to generate input files, pipe them through ACMI and iterate according to whatever scheme (gradient descent, Monte Carlo, etc) you are implementing. ACMI is coded as a pipeline filter with this in mind.

Program results are written to the standard output stream. Standard input is never read. Exit status is 0 following a successfull run. Error messages go to the standard error stream, and the program exits with status 1 if any any error occurs. Only the first syntax error in an input file will be reported - the program exits immediately.

Notes and Links

Thanks to Mark Rzeszotarski for suggesting the use of Grover's tables, and to Antonio Carlos M. de Queiroz for pointing out a serious bug in v0.1c.

Many thanks to Terry Fritz, Barton B. Anderson, and Bert Hickman, for their invaluable help in providing validation measurements.


   Maintainer Paul Nicholson, acmi0807@abelian.org.