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.
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.
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.
./acmi < thor.inIf 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.outCommand line options -csv and -html will change the output format from the default plain text, eg.
./acmi -html < thor.in > thor.htmlRun
./acmi -helpto get a full list of command line options.
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.7The 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 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 4which is equivalent to
radius1 4 radius2 4and similarly for the height if you have a flat horizontal winding.
The wire radius can be given in AWG by
conductor 24 awgor as a radius, eg
conductor 0.25e-3
ambient 10 ; Use 10 degrees Centigrade instead of 25.somewhere in the input file, but outside of any coil clauses.
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.
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.
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.
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_expressionThe 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.
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.
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.
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) : 0which 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
profile coil2 from coil1will 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.
theta = S * 3.14159means 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.
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.