Calculates the distributed inductance and capacitance of a network of coils, wires, and electrodes of various shapes.Generates a Spice sub-circuit representing the coils and electrodes as a detailed LCR network.LCnetgen is open source and runs on all system supporting the gcc compiler - that means almost any computer from a Raspberry Pi to a Cray - with the exception of those running Windows. The program uses a quasi-static field approximation and is therefore applicable only when the dimensions of the system are small compared with the free-space wavelength of the highest frequency of interest. Applications include: Tesla coils; LF and VLF antennas; Loading coils and variometers; High voltage systems. |
|
|
|
|
|
|
Download the latest version, lcnetgen-0.4i.tgz. Unpack and descend into the source directory with
tar xzf lcnetgen-0.4i.tgz cd lcnetgen-0.4iThen compile the program with
makeThere should be no errors unless you have a very unusual system. There are no dependencies other than gcc and the usual C libraries.
Then, as the superuser, install into /usr/local/bin with
make installor edit the makefile to install the executable somewhere else in your execution path. Then the command
lcng -?should give you a summary of command line options.
To test the program, run
./testwhich exercises many of the functions of the program and checks for correct output. The script relies on you having ngspice installed.
lcng [options] system Output options: -o spice Generate spice sub-circuit -o list Output a listing of R, L and C -o tiles Generate a tiles file -o povray Generate an input file for povray -o gnuplot Display system interactively using gnuplot -o geda Output gEDA symbol (options for -o can be combined comma separated) -r dc Use DC resistance for coils -r ac Use AC resistance for coils (default) Mode options for capacitance solver: -m dir Use direct calculation for capacitance (default) -m fmm Use fast multipole method for capacitance -m cgm Conjugate gradient method (default with -m dir) -m gmres Generalised minimum residuals (default with -m fmm) -m ge Use Gaussian elimination (only with -m dir) Options available with -m fmm: -m depth=num Use fixed depth octree, 'num' gives depth (default 5) -m depth=auto Use fixed depth octree, automatically choose depth -m precon Enable preconditioning (only with -m fmm) -m degree=num Maximum degree of spherical harmonics (default 6) (options for -m can be combined comma separated) -t factor Scales the number of tiles by factor (default 1.0) -c cpus Use number of threads in parallel (maximum 64, default 1) -v Increase verbosity -NC Don't do capacitance calculation -NL Don't do inductance calculation -NR Don't do resistance calculationBy default, lcng only reports errors and is silent otherwise. A -v option produces some progress and info messages. -vv produces more detail, and -vvv is only useful for debuging the software.
The potential matrix is solved to obtain the capacitance matrix using the generalised minimum residuals method. This usually converges quite well. Using -m cgm switches to the conjugate gradient method which is a little slower but might converge better in some cases. Option -m ge abandons interative solution and switches to Gaussian elimination but this is very slow and is only useful for testing. If convergence is problematic then you probably need to reconsider the decomposition of electrodes and coils into tiles and sections. Convergence problems tend to occur when components interfere (overlap) or where components from different electrodes are very close to one another.
If the capacitance calculation is too large for available RAM, -m fmm must be used which invokes the fast multipole method. This is slower in most situations but will allow a very large number of tiles to be used.
Option -c specifies how many CPU threads to use. lcng makes efficient use of multi-core machines.
lcng specifies behavioral resistors for coil sections in the Spice sub-circuit in order to represent the frequency dependent AC resistance. Some versions of Spice may not work properly with this (or work very slowly). Option -r dc will switch to using the DC resistance for coil sections.
lcng expects an input file to describe the your system of coils, wires, and electrodes. This is a plain text file called system.in where 'system' is a name you give your project. The input file describes the position, size, and orientation of all the components.
Arithmetic expressions can be used for all the values. Standard arithmetic functions and operators are available and conventional operator precedence applies. Ternary operators provide conditionals and variables can be defined.
The file uses white-space separated tokens and is otherwise free format (you can put line breaks anywhere between tokens). A semicolon introduces a comment in the input file. The semicolon and everthing following it to end-of-line is ignored.
The input file consists of a list of electrode and coil descriptions, and possible ground plane and field descriptions:
electrode { ... } electrode { ... } coil { ... } ground { ... } field { ... }Electrodes and coils can be listed in any order and you can declare as many of each as you need.
A standard right-handed Cartesian coordinate system is used to specify points. A point is given by a comma separated triplet of expressions: x,y,z. If '+x' is considered to be 'east' then '+y' equates to 'north' and '+z' is the vertical direction.
Axes are given in polar coordinates with values in degrees. A comma separated pair of expressions pa,azim gives the polar angle and azimuth. pa gives the angle of the axis from the vertical towards the east (+x) and azim rotates the tilted axis anti-clockwise when looking down. Examples:
pa,azim = 0,0 ; Vertical axis (+z) pa,azim = 90,0 ; Axis points east (+x) pa,azim = -90,0 ; Axis points west (-x) pa,azim = 90,90 ; Axis points north (+y) pa,azim = 90,-90 ; Axis points south (-y) pa,azim = 60,45 ; Axis points north-east, ; 30 degrees to the horizontal
Objects can be moved and rotated using a transform clause:
transform { electrode { ... } coil { ... } coil { ... } rotate pa,azim angle shift x,y,z }rotate rotates all the objects previously declared in the transform clause around the axis given by pa,azim by angle degrees. The rotation is right handed and the axis passes through the origin.
shift moves all the objects by adding x,y,z to their coordinates.
Rotations and shifts are applied in the order in which they are specified. Normally you would rotate objects first, then shift them to their final position. It can be very confusing to do it the other way around because the rotation axes always pass through the origin.
Transformations are applied only to the objects already declared in the transform clause:
transform { coil { ... } ; Coil 1 shift 0,0,1 ; Raise coil 1 by 1 metre (+z) coil { ... } ; Coil 2 shift 1,0,0 ; Moves coil 1 and coil 2 by 1 metre along +x coil { ... } ; Coil 3, not transformed at all }Transforms also operate on the ground plane and fields. Transforms can be arbitrarily nested.
Transforms are used to simplify the construction of complicated electrodes and coils. The object is constructed in say, the xy plane centered at the origin, then rotated and shifted (in that order) into the desired position.
By default all measurements are in metres. You can specify other units by following an expression with cm, mm, in, or ft.
These can be useful to parameterise the tunable aspects of your design. Define variables outside of any electrode or coil clause using the syntax
name = expressionNames are case insensitive, should start with a letter, consist of letters, digits and underscore, and must be defined in the input file before they are used. Some variable names are reserved: field,coil,electrode,ground,shift,rotate,axis.
Variables are very useful when you want to move around a structure which consists of a bunch of components.
An electrode is built from an arbitrary list of the components defined below.
electrode { name your_label sphere { ... } disc { ... } ... }All the components specified with the electrode clause are considered to be electrically connected and all at the same potential. An optional name parameter can be used to label the electrode in the output files. Your name for the electrode is case sensitive and must not contain any spaces. If you don't supply a name, lcng will just number them 'E1', 'E2' and so on.
Your input file can specify any number of electrodes and each can contain any number of components. The order in which the components are defined does not matter. The available components and their syntax are described below.
A hollow sphere.
sphere { center x,y,z radius r tiles nt }center and radius give the position and size of the sphere. The optional tiles specifies how many tiles the sphere is decomposed into. The default is 200.
A thin disc
disc { center x,y,z radius1 r1 ; Inner radius radius2 r2 ; Outer radius axis pa,azim tiles nt uniform }If the disc is complete (no hole in the middle so that radius1 is zero) you can just specify the outer radius with
radius rThe optional tiles specifies how many tiles the disc is decomposed into. The default is 500.
By default, lcng will increase the tile density towards the inner and outer (or just the outer) rim. The optional keyword uniform turns this off to produce a uniform tiling of the disc.
A flat rectangular thin plate.
rectangle { center xc,yc,zc edge1 x1,y1,z1 edge2 x2,y2,z2 tiles nt uniform }center is the center of the plate and the points edge1 and edge2 locate the mid-points of two adjacent edges. lcng will complain if the three points are not coplanar.
The optional keyword uniform instructs lcng to produce a uniform tiling of the rectangle. By default it will increase the tile density towards the edges.
The optional tiles specifies how many tiles the rectangle is decomposed into. The default is 500.
A thin wire. Position and orientation can be given by fixing the two ends,
wire { end1 x1,y1,z1 end2 x2,y2,z2 wirad r tiles nt }or by fixing one end and giving a length and azis,
wire { end1 x1,y1,z1 length len axis pa,azim wirad r tiles nt }For this component the ratio of length to diameter should be 100:1 or more. For smaller length/diameter ratios, better results may be obtained with a cylinder component.
wirad is the conductor radius in metres. The value may be postfixed with awg or any of the other unit specifiers.
The optional tiles specifies how many tiles the wire is decomposed into. The default is 200.
toroid { center x,y,z inner_radius r1 outer_radius r2 axis pa,azim tiles nt }The optional tiles specifies how many tiles the toroid is decomposed into. The default is 500.
A cylinder or cone - any right circular frustum. Open at the ends. Position and orientation can be given by fixing the two ends,
cylinder { end1 x1,y1,z1 end2 x2,y2,z2 radius1 r1 ; Radius at end1 radius2 r2 ; Radius at end2 tiles nt uniform }or by fixing one end and giving a length and axis
cylinder { end1 x1,y1,z1 axis pa,azim length len radius1 r1 ; Radius at end1 radius2 r2 ; Radius at end2 tiles nt uniform }If the component is a straight sided cylinder (radius1 = radius2) you can just give the radius with
radius rThe optional tiles specifies how many tiles the cylinder is decomposed into. The default is 500.
The keyword uniform selects uniform tiling of the cylinder. By default it will increase the tile density towards the ends.
The cylinder component can be used with good accuracy from length:diameter ratio of 100:1 through to 1:100. It is still fairly good for ratios out to 1000 both ways,
plate { points { x1,y1,z1 } { x2,y2,z2 } ... ... { xn,yn,zn } tiles nt }You should not supply a closing repeat of the first point. The points should all be in the same plane. An optional tiles parameter alters the number of tiles from the default of 500.
A coil can be of any straight-sided shape with circular or arbitrary polygonal cross-section. This includes discs, cylinders and cones (any right frustum), loops, and planar coils. Coils are broken down into sections and the capacitance and inductance, mutual and self, of each is calculated. This allows resonances of the coils to be accurately represented if enough sections are used. Using 10 sections is usually enough to obtain the fundamental resonance to within 2%, the first overtone to within 5% and the second overtone to around 10% or so. |
Position and orientation can be given by fixing the two ends, or by fixing one end and giving a length and axis.
coil { name your_label wirad r turns t tap t1 tap t2 sections ns tiles nt ... }wirad is the conductor radius in metres. The value may be postfixed with awg or any of the other unit specifiers.
turns can be fractional and may be positive or negative - this specifies the winding direction. With positive turns, viewing the coil from end1, looking towards end2 and tracing the path of the wire from end1 to end2, the winding rotates clockwise. If turns is negative, the winding rotates anti-clockwise. Any number of taps can be specified. If turns is negative, the taps must all have negative values. Tap positions are given as number of turns from end1.
sections specifies how many sections the coil will be modelled in. The default is 10. You may need to use more for greater accuracy of higher order resonant frequencies. lcng may adjust the number of sections upwards slightly and vary their length in order to place the taps at section boundaries.
tiles specifies how many tiles each coil sections is represented by for capacitance calculation. Default is 200.
The remainder of the coil description depends on the type of coil, described in the sections below.
coil { ... end1 x1,y1,z1 end2 x2,y2,z2 radius r }or the coordinates of one end and a length and axis.
coil { ... end1 x1,y1,z1 axis pa,azim length len radius r }The solenoid is cylindrical if only one radius is given. To make a cone shaped solenoid (frustum), specify a radius for each end:
radius1 r1 ; Radius at end1 radius2 r2 ; Radius at end2
Polygonal solenoids are similar to circular solenoids above, but the center point of end one is replaced by a list of points which give the vertices of end one. For example a square solenoid with 1m sides in the xy plane centered at the origin would use
end1 { -0.5, -0.5, 0 } { -0.5, 0.5, 0 } { 0.5, 0.5, 0 } { 0.5, -0.5, 0 }An axis should not be given with polygonal coils, instead lcng works out the axis from the order of the points using the right hand rule. In the above example the axis is downwards (-z). Polygon cross-sections can be regular or irregular, convex or concave, but must not have any intersections of edges.
A cone shaped (frustum) solenoid with polygonal cross sections is specified by giving a second polygon to describe end two. Both polygons should have the same number of points and be parallel to each other.
The example below describes a conical hexagonal vertical solenoid
rb = 0.8/2 ; 80cm overall diameter at the base rt = 0.3/2 ; 30cm overall diameter at the top a = 2 * pi / 6 ; Angle step per vertex base = 0.1 ; Base of coil 10cm above xy plane len = 0.5 ; Length of coil is 50cm coil { name secondary turns 500 wirad 30 awg end1 { rb * sin(0*a), rb * cos(0*a), base } { rb * sin(1*a), rb * cos(1*a), base } { rb * sin(2*a), rb * cos(2*a), base } { rb * sin(3*a), rb * cos(3*a), base } { rb * sin(4*a), rb * cos(4*a), base } { rb * sin(5*a), rb * cos(5*a), base } end2 { rt * sin(0*a), rt * cos(0*a), base + len } { rt * sin(1*a), rt * cos(1*a), base + len } { rt * sin(2*a), rt * cos(2*a), base + len } { rt * sin(3*a), rt * cos(3*a), base + len } { rt * sin(4*a), rt * cos(4*a), base + len } { rt * sin(5*a), rt * cos(5*a), base + len } }To simplify constructing polygonal coils, it is often easiest to define the polygons in the xy plane, or parallel to it, then wrap the coil in a transform clause to tilt it to the required orientation and shift it into position.
Circular loops are specified by giving the coil a length of zero and specifying a single radius and only one end. lcng does not attempt to calculate the internal capacitance of the loop because this depends signficantly on just how the turns of the loop are bundled. Therefore self-resonant frequencies of loops will not be accurately modelled.
Below is a 1m diameter loop in the yz plane with axis in the +x direction.
coil { end1 0,0,2 axis 90, 0 radius 0.5 length 0 turns 5 wirad 22 awg }end1 locates the center of the loop.
If your loop has a flat winding rather than a bundle, then treat it as a solenoid (albeit a short one) by specifying a length for the winding.
Loops will be modelled with just one section (ignoring any sections statement), unless you specify taps.
Polygonal loops are similar to circular the circular loops above, but supply a polygon for end1. length is set to zero to indicate a loop and there is no radius specified.
The example below is an octoloop in the yz plane with axis in the +x direction.
r = 1/2 ; 1 metre overall diameter p = 2 * pi / 16 ; Starting angle to give horizonal top ; and bottom edges a = 2 * pi / 8 ; Angle step per vertex coil { turns 50 wirad 1e-3 length 0 end1 { r * sin(0*a + p), 0, r * cos(0*a + p) } { r * sin(1*a + p), 0, r * cos(1*a + p) } { r * sin(2*a + p), 0, r * cos(2*a + p) } { r * sin(3*a + p), 0, r * cos(3*a + p) } { r * sin(4*a + p), 0, r * cos(4*a + p) } { r * sin(5*a + p), 0, r * cos(5*a + p) } { r * sin(6*a + p), 0, r * cos(6*a + p) } { r * sin(7*a + p), 0, r * cos(7*a + p) } }
A circular planar coil is specified by setting length zero and giving two radii. end1 locates the center of the disc. An example of a circular disc coil with vertical axis is given below,
coil { turns 20 wirad 18 awg length 0 radius1 0.1 ; 10cm inner radius radius2 0.8 ; 80cm outer radius end1 2,3,4 ; Center of the coil axis 0,0 ; Vertical }
A polygonal planar coil is specified by giving coplanar polygons for end1 and end2.
ro = 0.8/2 ; 80cm overall outside diameter ri = 0.3/2 ; 30cm overall inner diameter a = 2 * pi / 6 ; Angle step per vertex plane = 0.1 ; Plane of the coil 10cm above xy plane coil { name primary turns 20 wirad 12 awg ; Inner end of the coil end1 { ri * sin(0*a), ri * cos(0*a), plane } { ri * sin(1*a), ri * cos(1*a), plane } { ri * sin(2*a), ri * cos(2*a), plane } { ri * sin(3*a), ri * cos(3*a), plane } { ri * sin(4*a), ri * cos(4*a), plane } { ri * sin(5*a), ri * cos(5*a), plane } ; Outer end of the coil end2 { ro * sin(0*a), ro * cos(0*a), plane } { ro * sin(1*a), ro * cos(1*a), plane } { ro * sin(2*a), ro * cos(2*a), plane } { ro * sin(3*a), ro * cos(3*a), plane } { ro * sin(4*a), ro * cos(4*a), plane } { ro * sin(5*a), ro * cos(5*a), plane } }
You can specify an infinite ground plane with
ground { center x,y,z axis pa,azim }center specifies an arbitrary point on the ground plane and axis gives the orientation of the normal vector and should point to the side of the ground plane away from the earth. All components must be on this side of the ground plane.
The ground plane can be placed anywhere with any orientation, but is commonly fixed at the xy plane with
ground { center 0,0,0 axis 0,0 }
Incident electric and magnetic fields are given by a field clause,
field { electric pa,azim magnetic pa,axim }If either field is missing, it defaults to zero. The input file specifies only the orientation of the field vector. The amplitude and phase of each field is given by an input signal to the Spice sub-circuit.
Generated with -o spice on the command line. lcng outputs a file called system.spice containing a Spice sub-circuit to represent your system. The sub-circuit has a separate terminal for each of your electrodes, and a terminal for both ends and every tap of each coil.
There is also a separate terminal for the potential at infinity. This provides the return path for all the self-capacitances. Normally you would connect this to node 0 (ground) within your Spice model, unless your Spice model requires the ground node to float to its own potential.
If a ground plane is specified, it is connected within the sub-circuit to the infinity terminal.
If fields have been specified, input terminals are provided so that the external circuit can specify the field amplitude. For electric fields, one volt on the input terminal produces a field of 1 V/m. For magnetic fields, one amp in the input terminal produces a 1 Tesla field.
View the sub-circuit as a text file,
less system.spiceand see from the comments how the terminals have been assigned.
The generated Spice sub-circuit includes the self inductance and DC resistance of each coil section, and the mutual inductance between all pairs of coil sections. It also includes mutual capacitance between all pairs of coil sections, self capacitance of each section, and mutual capacitance between each coil section and every electrode in the system.
Generated with the -o tiles option. An output file called system.tiles is produced which is 3-column space separated data file listing the x,y,z coordinates of every tile in the system.
You can use the tiles file to get a rough 3D view of your system using gnuplot. Generate a tiles file with
lcng -o tiles systemThen run gnuplot and give it the following commands
set terminal x11 set style data points set view equal xyz splot 'system.tiles' using 1:2:3You can move the image around with the mouse or arrow keys. The view is good enough as a sanity check on your input coordinates.
Output option -o gnuplot runs gnuplot to interactively display a view of the system, using commands similar to those described above for the tiles output.
Running
lcng -o povray systemproduces a file system.pov containing a POV-Ray scene description. Display this with, for example
povray +P +H720 +W1280 system.povThe scene is generated with a 16:9 aspect ratio with the camera pointing at the centroid. You will probably want to edit system.pov to adjust the view point, lighting, colours, textures, and so on.
You can manually edit the symbol to fine-adjust the layout with
gschem system.symbut make sure you don't modify the pinseq values. These numbers ensure that the correct connections to the sub-circuit are used in the Spice netlist. After editing the symbol you must run the option Edit -> Symbol Translate... and translate to zero offset before saving.
You may need to edit or create the file ~/.gEDA/gafrc and include your working directory in the search path for component symbols with the line
(component-library "/your/lcng/directory")After restarting gschem you should find system.sym in the component library. It needs two attributes setting: value=system and file=system.spice.
You don't need to regenerate the symbol if you alter the dimensions of the system. But if you add or remove any coils or electrodes, or change their order in the input file, then you must produce a new schematic symbol because the sequence and number of connections to the sub-circuit will have altered.
The shell script test provided in the distribution runs a series of test cases to check that everything is working properly. The script contains plenty of example input files for simple cases and systems.
Some more complete systems are given below as examples. The examples all use ngspice for modelling.
Pieter-Tjerk de Boer PA3FWM, Enschede, Netherlands;
Paul Nicholson, Todmorden, UK;
Bart Anderson, USA;
Marco Denicolai, Finland;
Renato Romero IK1QFK, Cumiana, Italy;
Markus Vester DF6NM, Nuernberg, Germany;