6. Other System Functions in NC and User Defined Functions

(To create your own functions, please see User Defined Functions below .)

Notice that when you wrote the function call to create a feed point:

voltageFeed( drivenElement, 1.0, 0.0 ) ;

you are simply attaching a voltage source to the center of a wire element that is called drivenElement. This wire element is assigned to the wire() function

drivenElement = wire( 0, -length, ...

and drivenElement itself declared as a wire element in the declaration

element drivenElement ;

What if you want to offset feed a wire? You simply construct the wire in two pieces that share a connection point. Wires that are close enough will be connected by NEC-2. This is what the NEC-2 manual has to say about how wires connect:


... segments that are electrically connected
must have coincident end points. If segments intersect other than at their
ends, the NEC code will not allow current to flow from one segment to the
other. Segments will be treated as connected if the separation of their ends
is less than about 0.001
times the length of the shortest segment.



For example, if you wish to feed an 8 meter long wire at a point 25% from one end, you can model the wire as,


element fedWire ;

fedWire = wire( 0, 0, height, 0, 4.0, height, #14, 21 ) ;
wire( 0, 4.0, height, 0, 8.0, height, #14, 21 ) ;
voltageFeed( fedWire, 1.0, 0.0 ) ;



Notice from the above example that you do not need to assign a name to every call to the function wire. You need to only do it if you want to add other properties, such as a voltage feed, to that wire. You can always assign a name to a wire and not reference it again, as a documentation to remind yourself what that wire is being used for.

You can also use a double slash to add your own comments. All characters from the double slash until the end of a line are ignored by NC. For example, the above could be written as:


element fedWire ;

// 8 metre wire made up of two 4m pieces
fedWire = wire( 0, 0, height, 0, 4.0, height, #14, 21 ) ;
wire( 0, 4.0, height, 0, 8.0, height, #14, 21 ) ; // this piece is not fed
voltageFeed( fedWire, 1.0, 0.0 ) ;




Current Feeds

With antennas, such as phased arrays that have multiple feed points, it is often more useful to specify the excitations in terms of currents rather than as voltages. This is because it is phase relationships of antenna currents that directly determine the antenna patterns.

NEC-2 has no facility to directly define current feeds. cocoaNEC has built in an auxiliary mechanism to provide a convenient "current feed". This is done in cocoaNEC by creating a short piece of wire that is placed far away from the main wire structures. When multiple current feeds are created, the short wires are positioned so that they do not touch one another. Each of these auxiliary wires is then voltage fed using the standard NEC-2 mechanism. A NEC-2 two-port network with admittance matrix of (y11 = y22 = 0, y12 = y21 = -i, where i is the square root of minus 1) is placed between the auxiliary wire and the desired feed point. A 90 degree phase shift is also applied to the voltage feed to the auxiliary wire to undo the phase shift in the two-port network.

To use a current feed instead of a voltage feed, you simply have to use the statement:

currentFeed( fedWire, 1.0, 0.0 ) ;

If you would like a current of 3 amps and a phase shift of 45 degrees, you can for example write


magnitude = 3.0 ;
currentFeed( fedWire, magnitude*cosd(45), magnitude*sind(45) ) ;



As you can see, NC will take arithmetic operations. You can add subtract, negate, multiply and divide using the standard precedence orders. You can nest formulas with parenthesis modify the standard order, e.g.

x = ( 1.0 + y )*sinh( pi) ;


Trigonometric and Mathematical Functions and Constants

In the current feed example just above, notice that there is a call to the system function cosd. The following are trigonometric functions that are supported in NC (those who use C or FORTRAN will be familiar with these):

sin( theta ) - sine of an angle in radians
cos( theta ) - cosine of an angle in radians
tan( theta ) - tangent of an angle in radians
asin( x ) - arc sine of a value, result in radians
acos( x ) - arc cosine of a value, result in radians
atan( y/x ) - arc trangent of a value, result in radians
atan2( y, x ) - arc tangent of a two dimension coordinate, result in radians with 4 quardants

NC follows the standard trigonometric formulas by using radians instead of degrees (2π radians is 360 degrees). For convenience, especially when dealing with phase angles, NC provides a mirror to the standard trig functions, but with degrees as arguments. The functions have a "d" at the end of the names, e.g.

sind( angle )
cosd( angle )
tand( angle )
asind( x )
acosd( x )
atand( y/x )
atan2d( y, x )

With the "d" functions, the arguments of the forward functions are in degrees and the returned values of the inverse functions are in degrees.

NC also provides the following mathematical functions

sqrt( x ) - square root of x
pow( y, x ) - y to the power of x
exp( x ) - exponent of x
ln( x ) - natural log of x. I.e., inverse of exp(x)
log10( x ) - log base 10 of x
log( x ) - same as ln(x)
abs( x ) - the absolute value of an int
fabs( x ) - the absolute value of a real number

NC also provides the following hyperbolic functions for real arguments:

sinh( arg ) - hyperbolic sine
cosh( arg ) - hyperbolic cosine
tanh( arg ) - hyperbolic tangent
asinh( arg ) - inverse hyperbolic sine
acosh( arg ) - inverse hyperbolic cosine
atanh( arg ) - inverse hyperbolic tangent

NC provides a couple of convenient global constants (you can therefore not use these as variable names):

pi - ratio of circumference to diameter of a circle, i.e., 3.141592653589793...
c - speed of light in kilometers per millisecond, i.e., 299.7924... (frequency in MHz = c divided by wavelength in meters)


Element Loading

In a similar manner as the excitation function calls, you can add a load to the center of a wire element (yes, you can add a load at the same location as a feed).

The loads are attached to a wire element with the following NC calls:

impedanceLoad( element, R, X ) ;
lumpedSeriesLoad( element, R, L, C ) ;
lumpedParallelLoad( element, R, L, C ) ;
distributedSeriesLoad( element, R, L, C ) ;
distributedParalelLoad( element, R, L, C ) ;
conductivity( element, sigma ) ;


Like the voltageFeed and currentFeed function calls, the loading function calls take as the first argument the wire element variable.

The impedanceLoad function call will place a complex impedance (R is the resistive part and X is the reactance part, both in Ohms) at the center of the wire element. This is a quick and convenient way to model a load resistor for a rhombic or a flag antenna, for example.

The lumpedSeriesLoad function call will place a series resistor, inductor and capacitor combination at the center of the wire element. The resistance is expressed in Ohms, inductance is expressed in Henries, and capacitance is expressed in Farads.

The lumpedParallelLoad function call will place a parallel resistor, inductor and capacitor combination at the center of the wire element. The resistance is expressed in Ohms, inductance is expressed in Henries, and capacitance is expressed in Farads.

The distributedSeriesLoad function call is similar to the lumpedSeriesLoad call, but it places a lumped RLC element at each of the segments in the wire.

The distributedParallelLoad function call is similar to the lumpedParallelLoad call, but it places a lumped RLC element at each of the segments in the wire.

The conductivity call sets the conductivity of the wire (expressed in mhos/meter) for every segment of the wire element. This is especially useful for modeling real wires or aluminum tubing that have losses.


Network and Transmission Lines

We have already mentioned the functions to generate two port networks and transmission lines in a previous chapter. Note that you will need to use necRadials when modeling ground mounted vertical antennas.


Functions for generating Grounds and Radials

We have already mentioned the functions to generate various grounds and radials in a previous chapter. Note that you will need to use necRadials when modeling ground mounted vertical antennas.


Other Functions

If you look at the NC window, you will notice that there is a tab button to open an Output Console. You can send text to the console by using the printf function. The implementation of printf is very similar to the printf statement in the Unix stdio library (in fact NC implements its printf by using vsprintf in the stdio library).

With printf, you can print out values of the int and real variables. For example,

int index ;
real length ;

printf( "using length of %10.2f for element number %d", length, index ) ;


The %d format will is used for int variables and %f format is used for real variables. You can modify the default formats by specifying sizes. %5d will generate an integer output with 5 digit positions. A %10f will generate a real number output with 10 digit positions. A %10.2 format, shown above, will print the real number with two decimal places within a field of 10 digit positions.

NC also has a pause function that you can add as a statement to your program. The pause function takes a single real number as the argument and NC will pause the MacOS X thread it is running in for that number (or fraction thereof) of seconds. Its main utility is to slow down the computation so you can watch a slowed down animation when running models in a loop.

pause( 1.25 ) ;

You can ask NEC-2 to use the extended thin-wire kernel approximation. With the standard thin-wire approximation, the segment lengths used in the antenna models need to be more than 8 times the wire radius. You can turn extended thin-wire on or off by the statement

useExtendedKernel( state ) ;

If state is 0, the standard approximation is used. The default is with extended thin-wire approximation off.


Special Functions

There are some other special functions that are used in the control function. We will discuss them in the Optimizing chapter.


6.1 User Defined Functions

In addition to the built-in functions, you can create your own functions. User defined functions are useful for example, for describing a fundamental geometry that is repeated with a simple translation or rotation of the geometry. A function can describe a Yagi-Uda antenna with the height above ground as a function argument. The function can then be called multiple times, with different heights as the function argument, to create a vertical stack of the Yagi-Uda antennas.

A function that returns a real or integer number can be used to calculate a mathematical formula.

For details, please refer to the User Defined Function page of the NC Reference Manual.

Next: NC Syntax...