home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / tools / prp.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  621.2 KB  |  20,333 lines

  1. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2. --TYPES
  3. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4. Package TYPES is
  5. --
  6. -- TYPES Package of PROP_LINK Version 1.0,  February 16, 1985.
  7. --
  8. -- This TYPES Package declares several types which are used in the 
  9. -- CONSTANTS package and throughout PROPLINK.
  10. --
  11. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  12. -- radio frequency propagation prediction code.
  13. --
  14. -- PROP_LINK has been developed for the Department of Defense under
  15. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  16. -- Systems Inc. (Jim Conrad).
  17. --
  18. --
  19. -- TYPES:
  20.       Type NODE_TYPES is (NOTDEFINED, FIXED, MOVING, SATELLITE);
  21.       type NODE_ARRAY is array(1..100) of NODE_TYPES;
  22.       Type BAND_TYPES is (UNDEFINED,HARD_WIRED,ELF,VLF,LF,MF,HF,VHF,
  23.                           UHF,SHF,EHF);
  24.       type BAND_ARRAY is array(1..100) of BAND_TYPES;
  25.       Type COMMAND is (READ,WRITE,PRINT,VIEW,STOP,GO,ADD,DEL,MODIFY);
  26.       Type ENTITY is  (RECEIVER,TRANSMITTER,NODE,ENTITY_ERROR);
  27.       type I_ARRAY is array (integer range <>) of integer;
  28.       type L_ARRAY is array (integer range <>) of long_integer;
  29.       type F_ARRAY is array (integer range <>) of float;
  30.       type IARRAY_TYPE is array (integer range 1..80) of integer;
  31.       type SND1 is array (integer range 1..6,
  32.                              integer range 1..100) of float;
  33.       type SND2 is array (integer range 1..4,
  34.                              integer range 1..10,
  35.                              integer range 1..100) of float;
  36.       type SND3 is array (integer range 1..2,
  37.                              integer range 1..15,
  38.                              integer range 1..100) of long_integer;
  39. end TYPES;
  40. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  41. --CONSTANT3
  42. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  43. With TYPES; use TYPES;
  44. Package CONSTANT3 is
  45. --
  46. -- CONSTANT3 Package of PROP_LINK Version 1.0,  February 16, 1985.
  47. --
  48. -- This Package declares two arrays which were to large to include in
  49. -- the CONSTANTS package.
  50. --
  51. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  52. -- radio frequency propagation prediction code.
  53. --
  54. -- PROP_LINK has been developed for the Department of Defense under
  55. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  56. -- Systems Inc. (Jim Conrad).
  57. --
  58. IRCSND:SND3;   -- Receiver integerized names and classes at each node.
  59. IXTSND:SND3;   -- Transmitter integerized names and class at each node.
  60. end CONSTANT3;
  61. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  62. --CONSTANT2
  63. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  64. With TYPES; use TYPES;
  65. Package CONSTANT2 is
  66. --
  67. -- CONSTANT2 Package of PROP_LINK Version 1.0,  February 16, 1985.
  68. --
  69. -- This Package declares two arrays which were to large to include in
  70. -- the CONSTANTS package.
  71. --
  72. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  73. -- radio frequency propagation prediction code.
  74. --
  75. -- PROP_LINK has been developed for the Department of Defense under
  76. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  77. -- Systems Inc. (Jim Conrad).
  78. --
  79. XPSSND:SND2;    -- Location data for each node.
  80. EPHSND:SND1;    -- Ephemeride data for each node.
  81. end CONSTANT2;
  82. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  83. --CONSTANTS
  84. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  85. With TYPES; use TYPES;
  86. With Text_io; Use Text_io;
  87. Package CONSTANTS is
  88. --
  89. -- CONSTANTS Package of PROP_LINK Version 1.0,  February 16, 1985.
  90. --
  91. -- This CONSTANTS Package sets up variables and constants for the
  92. -- entire PROPLINK program.
  93. --
  94. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  95. -- radio frequency propagation prediction code.
  96. --
  97. -- PROP_LINK has been developed for the Department of Defense under
  98. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  99. -- Systems Inc. (Jim Conrad).
  100. --
  101. --
  102. -- VARIABLES: 
  103. --
  104.       MAXNOD: constant integer:=100; -- Size of all arrays for nodes
  105.       MAXRNT: constant integer:=99;  -- Size of all arrays for transmitters
  106.                                      --    and receivers
  107. --NODE VARIABLES:
  108.       NUMNOD: integer;               -- Number of nodes
  109.       NAMNOD: L_ARRAY(1..MAXNOD);    -- Node name array
  110.       ITYSND: NODE_ARRAY;            -- Node types
  111.       NLSND:  I_ARRAY(1..MAXNOD);    -- Number of locations (moving nodes)
  112.       NRSND:  I_ARRAY(1..MAXNOD);    -- Number of receivers at node 
  113.       NXSND:  I_ARRAY(1..MAXNOD);    -- Number of transmitters at node
  114.       IPTNOD: I_ARRAY(1..MAXNOD);    -- Pointers into the data structure
  115. --
  116. --RECEIVER VARIABLES:
  117.       NUMREC: integer;               -- Number of receiver classes
  118.       NAMREC: L_ARRAY(1..MAXRNT);    -- Integerized names
  119.       ITPREC: BAND_ARRAY;            -- Band type 
  120.       IATREC: I_ARRAY(1..MAXRNT);    -- Antenna type
  121.       FREREC: F_ARRAY(1..MAXRNT);    -- Frequency
  122.       GTREC:  F_ARRAY(1..MAXRNT);    -- Gain/Temp
  123.       BWREC:  F_ARRAY(1..MAXRNT);    -- Band Width
  124.       RLLREC: F_ARRAY(1..MAXRNT);    -- Line Loss
  125.       ANTGNR: F_ARRAY(1..MAXRNT);    -- Antenna Gain
  126.       ANTHTR: F_ARRAY(1..MAXRNT);    -- Antenna Height
  127.       ANTLNR: F_ARRAY(1..MAXRNT);    -- Antenna Length
  128.       ANTTAR: F_ARRAY(1..MAXRNT);    -- Antenna Tilt Angle
  129. --
  130.    --TRANSMITTER VARIABLES:
  131.       NUMXMT: integer;               -- Number of Transmitter classes
  132.       NAMXMT: L_ARRAY(1..MAXRNT);    -- Integerized names
  133.       ITPXMT: BAND_ARRAY;            -- Band type
  134.       BWXMT:  F_ARRAY(1..MAXRNT);    -- Band Width
  135.       TRPXMT: F_ARRAY(1..MAXRNT);    -- Radiated Power
  136.       FREXMT: F_ARRAY(1..MAXRNT);    -- Frequency
  137.       IATXMT: I_ARRAY(1..MAXRNT);    -- Antenna type
  138.       ANTGNX: F_ARRAY(1..MAXRNT);    -- Antenna Gain
  139.       ANTHTX: F_ARRAY(1..MAXRNT);    -- Antenna Height
  140.       ANTLNX: F_ARRAY(1..MAXRNT);    -- Antenna Length
  141.       ANTTAX: F_ARRAY(1..MAXRNT);    -- Antenna Tilt Angle
  142. --
  143. --      PI: constant float := 3.141592654; -- used math lib Pi instead
  144.       TWOPI: constant float := 6.283185308;
  145.       HALFPI: constant float := 1.570796327;
  146.       PI3: constant float := 1.047197551;
  147.       PI4: constant float := 0.7853981635; 
  148.       PI6: constant float := 0.5235987757;
  149.       PI9: constant float := 0.3490658504;
  150.       PI12: constant float := 0.2617993878;
  151.       PI20: constant float := 0.1570796327;
  152.       PI29: constant float := 0.6981317009;
  153.       PI43: constant float := 4.188790207;
  154.       PI2365: constant float := 1.7214206E-2;
  155.       PI4365: constant float := 3.4428412E-2;
  156.       RADIANS_PER_DEGREE: constant float := 1.7453292E-2;
  157.       DEGREES_PER_RADIAN: constant float := 57.29577951;
  158.       RADIUS_OF_EARTH_IN_KM: constant float := 6364.0;
  159.  
  160. -- GEOMAGNETIC/GEOGRAPHIC CONVERSION CONSTANTS FOLLOW:
  161.       SINPOL: constant float := 0.9803;  
  162.       COSPOL: constant float := 0.1977;
  163.       WMERID: constant float := 1.218;
  164.       DIPOLE: constant float := 0.31;
  165. --
  166. --GENERAL PURPOSE VARIABLES:
  167.       CURRENT_COMMAND: COMMAND;
  168.       CURRENT_ENTITY: ENTITY;
  169.       CURRENT_NOISE_SEASON: integer := 0;
  170.       DATABASE_HAS_BEEN_MODIFIED: boolean := FALSE;
  171.       DATA_HAS_NOT_YET_BEEN_WRITTEN: boolean := TRUE;
  172.       CURRENT_NODE_INDEX: integer := 0;
  173.       ENTITY_BUFFER: string (1..80);
  174.       NUMBER_OF_RECEIVERS: integer := 0;
  175.       NUMBER_OF_NODES: integer := 0;
  176.       NUMBER_OF_TRANSMITTERS: integer := 0;
  177.       PRINT_LEVEL: integer := 0;
  178.       CURRENT_TIME: float := 0.0;
  179.       REFERENCE_TIME: float := 0.0;
  180.       MONTH: integer := 10;
  181.       NSEAS: integer;
  182.       AVERAGE_SUN_SPOT_NUMBER: integer := 70;
  183.       NUMBER_OF_VARIABLES_TO_EXTRACT: integer;
  184.       NUMBER_OF_VARIABLES_EXTRACTED: integer;
  185.       FILE_NAME, OPTION: string(1..80);
  186.       PRINTER_OUTPUT_FILE: file_type;
  187.       MAX: integer range 0..80;
  188.       XARRAY: array (integer range 1..80) of float;
  189.       IARRAY: L_ARRAY(1..MAXNOD);
  190.       INPUT_BUFFER: string (1..80);
  191.       ARGUMENT_BUFFER: string (1..80);
  192.       TITLE: string (1..80);
  193. end CONSTANTS;
  194. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  195. --HELPS
  196. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  197. With Text_io;
  198. Package HELPS is
  199.       Function HELP_CHECK(BUFFER:string) return boolean;
  200.       Function BLANK_CHECK(BUFFER:string) return boolean; 
  201.       Procedure SHIFT_LEFT(BUFFER: in out string) ;
  202.       End HELPS;
  203. Package body HELPS is
  204. Use Text_io;
  205.       Function HELP_CHECK(BUFFER:string) return boolean is
  206. --
  207. --PURPOSE: HELP_CHECK determines if the help command has been requested.
  208. --
  209. --AUTHOR:  J. Conrad
  210. --
  211. --TYPE:    Data Checking.
  212. --
  213. --PARAMETER DESCRIPTIONS:
  214. --IN        BUFFER = The buffer that is examined.
  215. --
  216. --OUT       HELP_CHECK  = True if H, h, HELP or help is found, otherwise false.
  217. --
  218. --CALLED BY:
  219. --          ANTENNA_CHECK
  220. --          ENTITY_DATA
  221. --          EVENT_ADD
  222. --          EVENT_DATA
  223. --          COMMAND_LINE_PROCESSOR
  224. --          INTERPRET_ENTITY, 
  225. --          LOCATION_DATA 
  226. --          MESSAGE_DATA
  227. --          NODE_ADD
  228. --          NODE_DATA
  229. --          NODE_FETCH
  230. --          RECEIVER_ADD
  231. --          RECEIVER_DATA
  232. --          TRANSMITTER_ADD
  233. --          TRANSMITTER_DATA
  234. --
  235. --CALLS TO:
  236. --          SHIFT_LEFT
  237. --
  238. --TECHNICAL DESCRIPTION:
  239. --          HELP_CHECK examines the character buffer BUFFER and determines if
  240. --          the next non-blank character string is "H", or "h"
  241. --          in which case the function is true.  If anything
  242. --          else is found then the value is false.  A simple left shift
  243. --          and compare technique is used.
  244. --
  245.       SCRATCH: string(1..80);
  246.       Begin
  247. --
  248. --SET UP WORKING ARRAY AND FIND FIRST NON-BLANK CHARACTER.
  249.       SCRATCH(1..BUFFER'LENGTH) := BUFFER;
  250.       For I in BUFFER'RANGE Loop
  251.          If SCRATCH(1) = ' ' then
  252.             SHIFT_LEFT(SCRATCH);
  253.          elsif
  254.             SCRATCH(1) = 'h' or SCRATCH(1) = 'H' then
  255.                if I=BUFFER'LENGTH or SCRATCH(1..4)="help" or
  256.                   SCRATCH(1..4)="HELP" then
  257.                   return TRUE;
  258.                else
  259.                   return FALSE;
  260.                end if;
  261.          else
  262.             return FALSE;
  263.          End If; 
  264.       End Loop;
  265.       Return FALSE;
  266. --
  267.       End HELP_CHECK;
  268. --
  269.       Procedure SHIFT_LEFT(BUFFER: in out string) is
  270. --
  271. --PURPOSE: SHIFT_LEFT shifts the data in the array BUFFER one place to the left.
  272. --
  273. --AUTHOR:  J. Conrad
  274. --
  275. --TYPE:    Shift
  276. --
  277. --PARAMETER DESCRIPTIONS:
  278. --IO        BUFFER  = The array that is to be shifted
  279. --
  280. --CALLED BY:
  281. --          CONVERT_ALPHA_TO_NUMERIC
  282. --          COMMAND_LINE_PROCESSOR
  283. --          INTERPRET_ENTITY
  284. --          HELP_CHECK 
  285. --          LIKE 
  286. --          PARSE
  287. --
  288. --CALLS TO:
  289. --          'NONE'
  290. --
  291. --TECHNICAL DESCRIPTION:
  292. --         SHIFT_LEFT shifts the data in BUFFER one place to the left,
  293. --         throwing out the value in BUFFER(1) and putting a blank
  294. --         in BUFFER(BUFFER'LENGTH).
  295. --
  296.       I: integer;
  297. --
  298.       Begin
  299.       For I in 1..(BUFFER'LENGTH-1) Loop
  300.          BUFFER(I) := BUFFER(I+1);
  301.       End Loop;
  302.       BUFFER(BUFFER'LENGTH) := ' ';
  303. --
  304.       End SHIFT_LEFT;
  305. --
  306.       Function BLANK_CHECK(BUFFER:string) return boolean is
  307. --
  308. --PURPOSE: BLANK_CHECK determines if the array is empty.
  309. --
  310. --AUTHOR:  J. Conrad
  311. --
  312. --TYPE:    Array Test
  313. --
  314. --PARAMETER DESCRIPTIONS:
  315. --IN        BUFFER = The 80 element buffer containing alpha
  316. --                   information.
  317. --OUT       BLANK_CHECK = True if the buffer is all alpha blanks,
  318. --                   otherwise BLANK_CHECK is false
  319. --
  320. --CALLED BY:
  321. --          ANTENNA_CHECK
  322. --          ENTITY_DATA
  323. --          INTERPRET_ENTITY
  324. --          LOCATION_DATA
  325. --          NODE_ADD
  326. --          NODE_DATA
  327. --          NODE_HANDLER
  328. --          PARSE
  329. --          RECEIVER_ADD
  330. --          RECEIVER_DATA 
  331. --          RECEIVER_FETCH
  332. --          RECEIVER_HANDLER
  333. --          TRANSMITTER_ADD
  334. --          TRANSMITTER_DATA
  335. --          TRANSMITTER_FETCH
  336. --          TRANSMITTER_HANDLER
  337. --
  338. --CALLS TO:
  339. --          'NONE'
  340. --
  341. --TECHNICAL DESCRIPTION:
  342. --          BLANK_CHECK searches the input buffer specified as BUFFER
  343. --          looking for non-blank characters.  If the array
  344. --          is blank the value of BLANK_CHECK is set to true,
  345. --          and vice versa.
  346. --
  347.       I: integer;
  348. --
  349.       Begin
  350.       For I in BUFFER'RANGE Loop
  351.          If BUFFER(I) /= ' ' Then 
  352.             Return FALSE;
  353.          End If;
  354.       End Loop;
  355.       Return TRUE;
  356. --
  357.       End BLANK_CHECK;
  358. End HELPS;
  359. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  360. --MATHLIB
  361. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  362. with TEXT_IO;
  363. package MATHLIB is
  364.  
  365. package FLOATING_CHARACTERISTICS is
  366.  
  367.     IBETA : INTEGER;
  368.     IT : INTEGER;
  369.     IRND : INTEGER;
  370.     NGRD : INTEGER;
  371.     MACHEP : INTEGER;
  372.     NEGEP : INTEGER;
  373.     IEXP : INTEGER;
  374.     MINEXP : INTEGER;
  375.     MAXEXP : INTEGER;
  376.     EPS : FLOAT;
  377.     EPSNEG : FLOAT;
  378.     XMIN : FLOAT;
  379.     XMAX : FLOAT;
  380.  
  381.   subtype EXPONENT_TYPE is INTEGER;    --  should be derived  ##########
  382.   subtype MANTISSA_TYPE is FLOAT;     --   range -1.0..1.0;
  383.   MANTISSA_DIVISOR_2 : constant FLOAT := 2.0;
  384.   MANTISSA_DIVISOR_3 : constant FLOAT := 3.0;
  385.   MANTISSA_HALF : constant MANTISSA_TYPE := 0.5;
  386.  
  387.  
  388.   procedure DEFLOAT(X : in FLOAT;
  389.                     N : out EXPONENT_TYPE; F : out MANTISSA_TYPE);
  390.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE; 
  391.                                                    X : out FLOAT);
  392.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT;
  393.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT;
  394. end FLOATING_CHARACTERISTICS;
  395.  
  396.  
  397. package NUMERIC_IO is
  398.   use TEXT_IO;
  399.  
  400.   procedure GET(FILE : in FILE_TYPE; ITEM : out INTEGER);
  401.   procedure GET(ITEM : out INTEGER);
  402.   procedure GET(FILE : in FILE_TYPE; ITEM : out FLOAT);
  403.   procedure GET(ITEM : out FLOAT);
  404.   procedure PUT(FILE : in FILE_TYPE; ITEM : in INTEGER);
  405.   procedure PUT(ITEM : in INTEGER; WIDTH : in FIELD);
  406.   procedure PUT(ITEM : in INTEGER);
  407.   procedure PUT(FILE : in FILE_TYPE; ITEM : in FLOAT);
  408.   procedure PUT(ITEM : in FLOAT);
  409. end NUMERIC_IO;
  410.  
  411.  
  412.  
  413. use FLOATING_CHARACTERISTICS;
  414. package NUMERIC_PRIMITIVES is
  415.  
  416.   ZERO  : FLOAT;
  417.   ONE   : FLOAT;
  418.   TWO   : FLOAT;
  419.   THREE : FLOAT;
  420.   HALF  : FLOAT;
  421.  
  422.   PI            : FLOAT;
  423.   ONE_OVER_PI   : FLOAT;
  424.   TWO_OVER_PI   : FLOAT;
  425.   PI_OVER_TWO   : FLOAT;
  426.   PI_OVER_THREE : FLOAT;
  427.   PI_OVER_FOUR  : FLOAT;
  428.   PI_OVER_SIX   : FLOAT;
  429.  
  430.  
  431.   function SIGN(X, Y : FLOAT) return FLOAT;
  432.     --  Returns the value of X with the sign of Y
  433.   function AMAX1(X, Y :  FLOAT) return FLOAT;
  434.     --  Returns the algebraicly larger of X and Y
  435.   function AMIN1(X, Y :  FLOAT) return FLOAT;
  436.     --  Returns the algebraicly smaller of X and Y
  437.   function MAX(X, Y :  INTEGER) return INTEGER;
  438.     --  Returns the algebraicly larger of X and Y
  439.   function MIN(X, Y :  INTEGER) return INTEGER;
  440.     --  Returns the algebraicly smaller of X and Y
  441.   function TRUNCATE(X : FLOAT) return FLOAT;
  442.     --  Returns the floating value of the integer no larger than X
  443.     --  AINT(X)
  444.   function ROUND(X : FLOAT) return FLOAT;
  445.     --  Returns the floating value nearest X
  446.     --  AINTRND(X)
  447.   function RAN return FLOAT;
  448.   function AMOD(X, Y : FLOAT) return FLOAT;
  449.     --  Returns the remainder of X/Y
  450. end NUMERIC_PRIMITIVES;
  451.  
  452.  
  453. use FLOATING_CHARACTERISTICS;
  454. package CORE_FUNCTIONS is
  455.  
  456.   EXP_LARGE : FLOAT;
  457.   EXP_SMALL : FLOAT;
  458.  
  459.   function SQRT(X : FLOAT) return FLOAT;
  460.   function CBRT(X : FLOAT) return FLOAT;
  461.   function LOG(X : FLOAT) return FLOAT;
  462.   function LOG10(X : FLOAT) return FLOAT;
  463.   function EXP(X : FLOAT) return FLOAT;
  464.   function "**"(X, Y : FLOAT) return FLOAT;
  465.  
  466. end CORE_FUNCTIONS;
  467.  
  468.  
  469.  
  470. package TRIG_FUNCTIONS is
  471.   function SIN(X : FLOAT) return FLOAT;
  472.   function COS(X : FLOAT) return FLOAT;
  473.   function TAN(X : FLOAT) return FLOAT;
  474.   function COT(X : FLOAT) return FLOAT;
  475.   function ASIN(X : FLOAT) return FLOAT;
  476.   function ACOS(X : FLOAT) return FLOAT;
  477.   function ATAN(X : FLOAT) return FLOAT;
  478.   function ATAN2(V, U : FLOAT) return FLOAT;
  479.   function SINH(X : FLOAT) return FLOAT;
  480.   function COSH(X : FLOAT) return FLOAT;
  481.   function TANH(X : FLOAT) return FLOAT;
  482. end TRIG_FUNCTIONS;
  483. end MATHLIB;
  484.  
  485.  
  486.  
  487.  
  488. with TEXT_IO; use TEXT_IO;
  489. package body MATHLIB is
  490.  
  491. package body FLOATING_CHARACTERISTICS is
  492.  
  493.     A, B, Y, Z : FLOAT;
  494.     I, K, MX, IZ : INTEGER;
  495.     BETA, BETAM1, BETAIN : FLOAT;
  496.     ONE : FLOAT := 1.0;
  497.     ZERO : FLOAT := 0.0;
  498.  
  499.   procedure DEFLOAT(X : in FLOAT;
  500.                     N : out EXPONENT_TYPE; F : out MANTISSA_TYPE) is
  501.     EXPONENT_LENGTH : INTEGER := IEXP;
  502.     M : EXPONENT_TYPE;
  503.     W, Y, Z : FLOAT;
  504.   begin
  505.     N := 0;
  506.     F := 0.0;
  507.     Y := ABS(X);
  508.     if Y = 0.0  then
  509.       return;
  510.     elsif Y < 0.5  then
  511.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  512.         M := EXPONENT_TYPE(2 ** J);
  513.         Z := 1.0 / (2.0**M);
  514.         W := Y / Z;
  515.         if W < 1.0  then
  516.           Y := W;
  517.           N := N - M;
  518.         end if;
  519.       end loop;
  520.     else
  521.       for J in reverse 0..(EXPONENT_LENGTH - 2)  loop
  522.         M := EXPONENT_TYPE(2 ** J);
  523.         Z := 2.0**M;
  524.         W := Y / Z;
  525.         if W >= 0.5  then
  526.           Y := W;
  527.           N := N + M;
  528.         end if;
  529.       end loop;
  530.     end if;
  531.     while Y < 0.5  loop
  532.       Y := Y * 2.0;
  533.       N := N - 1;
  534.     end loop;
  535.     while Y >= 1.0  loop
  536.       Y := Y / 2.0;
  537.       N := N + 1;
  538.     end loop;
  539.     F := MANTISSA_TYPE(Y);
  540.     if X < 0.0  then
  541.       F := -F;
  542.     end if;
  543.     return;
  544.   exception
  545.   when others =>
  546.     N := 0;
  547.     F := 0.0;
  548.     return;
  549.   end DEFLOAT;
  550.  
  551.  
  552.   procedure REFLOAT(N : in EXPONENT_TYPE; F : in MANTISSA_TYPE; 
  553.                                                    X : out FLOAT) is
  554.     M : INTEGER;
  555.     Y : FLOAT;
  556.   begin
  557.     if F = 0.0  then
  558.       X := ZERO;
  559.       return;
  560.     end if;
  561.     M := INTEGER(N);
  562.     Y := ABS(FLOAT(F));
  563.     while Y < 0.5  loop
  564.       M := M - 1;
  565.       if M < MINEXP  then
  566.         X := ZERO;
  567.       end if;
  568.       Y := Y + Y;
  569.       exit when M <= MINEXP;
  570.     end loop;
  571.     if M = MAXEXP  then
  572.       M := M - 1;
  573.       X := Y * 2.0**M;
  574.       X := X * 2.0;
  575.     elsif M <= MINEXP + 2  then
  576.       M := M + 3;
  577.       X := Y * 2.0**M;
  578.       X := ((X / 2.0) / 2.0) / 2.0;
  579.     else
  580.       X := Y * 2.0**M;
  581.     end if;
  582.     if F < 0.0  then
  583.       X := -X;
  584.     end if;
  585.     return;
  586.   end REFLOAT;
  587.  
  588.   function CONVERT_TO_FLOAT(K : INTEGER) return FLOAT is
  589.   begin
  590.     return FLOAT(K);
  591.   end CONVERT_TO_FLOAT;
  592.  
  593.   function CONVERT_TO_FLOAT(N : EXPONENT_TYPE) return FLOAT is
  594.   begin
  595.     return FLOAT(N);
  596.   end CONVERT_TO_FLOAT;
  597.  
  598.   function CONVERT_TO_FLOAT(F : MANTISSA_TYPE) return FLOAT is
  599.   begin
  600.     return FLOAT(F);
  601.   end CONVERT_TO_FLOAT;
  602.  
  603.  
  604. begin --  Initialization for the VAX with values derived by MACHAR
  605.  
  606.     IBETA :=    2;
  607.     IT :=    24;
  608.     IRND :=    1;
  609.     NEGEP :=    -24;
  610.     EPSNEG :=    5.9604644E-008;
  611.     MACHEP :=    -24;
  612.     EPS :=    5.9604644E-008;
  613.     NGRD :=    0;
  614.     XMIN := 5.9E-39;
  615.     MINEXP :=    -126;
  616.     IEXP :=    8;
  617.     MAXEXP :=    127;
  618.     XMAX :=    8.5E37 * 2.0;
  619. end FLOATING_CHARACTERISTICS;
  620.  
  621.  
  622.  
  623.  
  624. package body NUMERIC_IO is
  625. use INTEGER_IO; use FLOAT_IO;
  626.  
  627.   procedure GET(FILE : in FILE_TYPE; ITEM : out INTEGER) is
  628.   begin
  629. INTEGER_IO.GET(FILE, ITEM);
  630.   end GET;
  631.  
  632.   procedure GET(ITEM : out INTEGER) is
  633.   begin
  634. INTEGER_IO.GET(ITEM);
  635.   end GET;
  636.  
  637.   procedure GET(FILE : in FILE_TYPE; ITEM : out FLOAT) is
  638.   begin
  639. FLOAT_IO.GET(FILE, ITEM);
  640.   end GET;
  641.  
  642.   procedure GET(ITEM : out FLOAT) is
  643.   begin
  644. FLOAT_IO.GET(ITEM);
  645.   end GET;
  646.  
  647.   procedure PUT(FILE : in FILE_TYPE; ITEM : in INTEGER) is
  648.   begin
  649. INTEGER_IO.PUT(FILE, ITEM);
  650.   end PUT;
  651.  
  652.   procedure PUT(ITEM : in INTEGER; WIDTH : in FIELD) is
  653.     J, K, M : INTEGER := 0;
  654.   begin
  655.     if WIDTH = 1  then
  656.       case ITEM is
  657.         when 0  => TEXT_IO.PUT('0');
  658.         when 1  => TEXT_IO.PUT('1');
  659.         when 2  => TEXT_IO.PUT('2');
  660.         when 3  => TEXT_IO.PUT('3');
  661.         when 4  => TEXT_IO.PUT('4');
  662.         when 5  => TEXT_IO.PUT('5');
  663.         when 6  => TEXT_IO.PUT('6');
  664.         when 7  => TEXT_IO.PUT('7');
  665.         when 8  => TEXT_IO.PUT('8');
  666.         when 9  => TEXT_IO.PUT('9');
  667.         when others  => TEXT_IO.PUT('*');
  668.       end case;
  669.     else
  670.       if ITEM < 0  then
  671.         TEXT_IO.PUT('-');
  672.         J := -ITEM;
  673.       else
  674.         TEXT_IO.PUT(' ');
  675.         J := ITEM;
  676.       end if;
  677.       for I in 1..WIDTH-1  loop
  678.         M := 10**(WIDTH - 1 - I);
  679.         K := J / M;
  680.         J := J - K*M;
  681.         NUMERIC_IO.PUT(K, 1);
  682.       end loop;
  683.     end if;
  684.   end PUT;
  685.  
  686.   procedure PUT(ITEM : in INTEGER) is
  687.   begin
  688. INTEGER_IO.PUT(ITEM);
  689.   end PUT;
  690.  
  691.   procedure PUT(FILE : in FILE_TYPE; ITEM : in FLOAT) is
  692.   begin
  693. FLOAT_IO.PUT(FILE, ITEM);
  694.   end PUT;
  695.  
  696.   procedure PUT(ITEM : in FLOAT) is
  697.   begin
  698. FLOAT_IO.PUT(ITEM);
  699.   end PUT;
  700.  
  701. end NUMERIC_IO;
  702. use FLOATING_CHARACTERISTICS;
  703. package body NUMERIC_PRIMITIVES is
  704.  
  705.  
  706.   function SIGN(X, Y : FLOAT) return FLOAT is
  707.     --  Returns the value of X with the sign of Y
  708.   begin
  709.     if Y >= 0.0  then
  710.       return X;
  711.     else
  712.       return -X;
  713.     end if;
  714.   end SIGN;
  715.  
  716.   function AMAX1(X, Y : FLOAT) return FLOAT is
  717.   begin
  718.     if X >= Y  then
  719.       return X;
  720.     else
  721.       return Y;
  722.     end if;
  723.   end AMAX1;
  724.  
  725.   function AMIN1(X, Y : FLOAT) return FLOAT is
  726.   begin
  727.     if X < Y  then
  728.       return X;
  729.     else
  730.       return Y;
  731.     end if;
  732.   end AMIN1;
  733.  
  734.   function MAX(X, Y : INTEGER) return INTEGER is
  735.   begin
  736.     if X >= Y  then
  737.       return X;
  738.     else
  739.       return Y;
  740.     end if;
  741.   end MAX;
  742.  
  743.   function MIN(X, Y : INTEGER) return INTEGER is
  744.   begin
  745.     if X < Y  then
  746.       return X;
  747.     else
  748.       return Y;
  749.     end if;
  750.   end MIN;
  751.  
  752.   function TRUNCATE(X : FLOAT) return FLOAT is
  753.   --  Optimum code depends on how the system rounds at exact halves
  754.   begin
  755.     if FLOAT(INTEGER(X)) = X  then
  756.       return X;
  757.     end if;
  758.     if X > ZERO  then
  759.       return FLOAT(INTEGER(X - HALF));
  760.     elsif X = ZERO  then
  761.       return ZERO;
  762.     else
  763.       return FLOAT(INTEGER(X + HALF));
  764.     end if;
  765.   end TRUNCATE;
  766.  
  767.   function ROUND(X : FLOAT) return FLOAT is
  768.   begin
  769.     return FLOAT(INTEGER(X));
  770.   end ROUND;
  771.  
  772.  
  773.   package KEY is
  774.     X : INTEGER := 10_001;
  775.     Y : INTEGER := 20_001;
  776.     Z : INTEGER := 30_001;
  777.   end KEY;
  778.  
  779.   function RAN return FLOAT is
  780.     W : FLOAT;
  781.   begin
  782.  
  783.     KEY.X := 171 * (KEY.X mod 177 - 177) -  2 * (KEY.X / 177);
  784.     if KEY.X < 0  then
  785.       KEY.X := KEY.X + 30269;
  786.     end if;
  787.  
  788.     KEY.Y := 172 * (KEY.Y mod 176 - 176) - 35 * (KEY.Y / 176);
  789.     if KEY.Y < 0  then
  790.       KEY.Y := KEY.Y + 30307;
  791.     end if;
  792.  
  793.     KEY.Z := 170 * (KEY.Z mod 178 - 178) - 63 * (KEY.Z / 178);
  794.     if KEY.Z < 0  then
  795.       KEY.Z := KEY.Z + 30323;
  796.     end if;
  797.  
  798.     W :=     CONVERT_TO_FLOAT(KEY.X)/30269.0
  799.            + CONVERT_TO_FLOAT(KEY.Y)/30307.0
  800.            + CONVERT_TO_FLOAT(KEY.Z)/30323.0;
  801.  
  802.     return  W - CONVERT_TO_FLOAT(INTEGER(W - 0.5));
  803.  
  804.   end RAN;
  805.  
  806.   function AMOD (X,Y : FLOAT) return FLOAT is
  807.   -- returns remainder of X/Y
  808.   begin
  809.      return X-Y * TRUNCATE(X/Y);
  810.   end AMOD;
  811.  
  812.  
  813. begin
  814.  
  815.   ZERO  := CONVERT_TO_FLOAT(INTEGER(0));
  816.   ONE   := CONVERT_TO_FLOAT(INTEGER(1));
  817.   TWO   := ONE + ONE;
  818.   THREE := ONE + ONE + ONE;
  819.   HALF  := ONE / TWO;
  820.  
  821.   PI            := CONVERT_TO_FLOAT(INTEGER(3)) +
  822.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.14159_26535_89793_23846));
  823.   ONE_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.31830_98861_83790_67154));
  824.   TWO_OVER_PI   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.63661_97723_67581_34308));
  825.   PI_OVER_TWO   := CONVERT_TO_FLOAT(INTEGER(1)) +
  826.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.57079_63267_94896_61923));
  827.   PI_OVER_THREE := CONVERT_TO_FLOAT(INTEGER(1)) +
  828.                    CONVERT_TO_FLOAT(MANTISSA_TYPE(0.04719_75511_96597_74615));
  829.   PI_OVER_FOUR  := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.78539_81633_97448_30962));
  830.   PI_OVER_SIX   := CONVERT_TO_FLOAT(MANTISSA_TYPE(0.52359_87755_98298_87308));
  831.  
  832. end NUMERIC_PRIMITIVES;
  833.  
  834. package body CORE_FUNCTIONS is
  835.   use TEXT_IO;
  836.   use FLOATING_CHARACTERISTICS;
  837.   use NUMERIC_IO;
  838.   use NUMERIC_PRIMITIVES;
  839.  
  840.  
  841.   function SQRT(X : FLOAT) return FLOAT is
  842.     M, N : EXPONENT_TYPE;
  843.     F, Y : MANTISSA_TYPE;
  844.     RESULT : FLOAT;
  845.  
  846.     subtype INDEX is INTEGER range 0..100;    --  #########################
  847.     SQRT_L1 : INDEX := 3;
  848.     --  Could get away with SQRT_L1 := 2 for 28 bits
  849.     --  Using the better Cody-Waite coeficients overflows MANTISSA_TYPE
  850.     SQRT_C1 : MANTISSA_TYPE := 8#0.3317777777#;
  851.     SQRT_C2 : MANTISSA_TYPE := 8#0.4460000000#;
  852.     SQRT_C3 : MANTISSA_TYPE := 8#0.55202_36314_77747_36311_0#;
  853.  
  854.   begin
  855.     if X = ZERO  then
  856.       RESULT := ZERO;
  857.       return RESULT;
  858.     elsif X = ONE  then            --  To get exact SQRT(1.0)
  859.       RESULT := ONE;
  860.       return RESULT;
  861.     elsif X < ZERO  then
  862.       NEW_LINE;
  863.       PUT("CALLED SQRT FOR NEGATIVE ARGUMENT   ");
  864.       PUT(X);
  865.       PUT("   USED ABSOLUTE VALUE");
  866.       NEW_LINE;
  867.       RESULT := SQRT(ABS(X));
  868.       return RESULT;
  869.     else
  870.       DEFLOAT(X, N, F);
  871.       Y := SQRT_C1 + MANTISSA_TYPE(SQRT_C2 * F);
  872.       for J in 1..SQRT_L1  loop
  873.         Y := Y/MANTISSA_DIVISOR_2 + MANTISSA_TYPE((F/MANTISSA_DIVISOR_2)/Y);
  874.       end loop;
  875.       if (N mod 2) /= 0  then
  876.         Y := MANTISSA_TYPE(SQRT_C3 * Y);
  877.         N := N + 1;
  878.       end if;
  879.       M := N/2;
  880.       REFLOAT(M,Y,RESULT);
  881.       return RESULT;
  882.     end if;
  883.   exception
  884.   when others =>
  885.     NEW_LINE; PUT(" EXCEPTION IN SQRT, X = "); PUT(X);
  886.     PUT("  RETURNED 1.0"); NEW_LINE;
  887.     return ONE;
  888.   end SQRT;
  889.  
  890.  
  891.   function CBRT(X : FLOAT) return FLOAT is
  892.     M, N : EXPONENT_TYPE;
  893.     F, Y : MANTISSA_TYPE;
  894.     RESULT : FLOAT;
  895.  
  896.     subtype INDEX is INTEGER range 0..100;    
  897.     CBRT_L1 : INDEX := 3;
  898.     CBRT_C1 : MANTISSA_TYPE := 0.5874009;
  899.     CBRT_C2 : MANTISSA_TYPE := 0.4125990;
  900.     CBRT_C3 : MANTISSA_TYPE := 0.62996_05249;
  901.     CBRT_C4 : MANTISSA_TYPE := 0.79370_05260;
  902.  
  903.   begin
  904.     if X = ZERO then
  905.       RESULT := ZERO;
  906.       return RESULT;
  907.     else
  908.       DEFLOAT(X, N, F);
  909.       F := ABS(F);
  910.       Y := CBRT_C1 + MANTISSA_TYPE(CBRT_C2 * F);
  911.       for J in 1 .. CBRT_L1 loop
  912.         Y :=     Y
  913.             - (  Y/MANTISSA_DIVISOR_3 
  914.                - MANTISSA_TYPE((F/MANTISSA_DIVISOR_3) / MANTISSA_TYPE(Y*Y)) );
  915.       end loop;
  916.       case (N mod 3) is
  917.         when 0 =>
  918.           null;
  919.         when 1 =>
  920.           Y := MANTISSA_TYPE(CBRT_C3 * Y);
  921.           N := N + 2;
  922.         when 2 =>
  923.           Y := MANTISSA_TYPE(CBRT_C4 * Y);
  924.           N := N + 1;
  925.         when others =>
  926.           null;
  927.       end case;
  928.       M := N/3;
  929.       if X < ZERO  then
  930.         Y := -Y;
  931.       end if;
  932.       REFLOAT(M, Y, RESULT);
  933.       return RESULT;
  934.     end if;
  935.   exception
  936.     when others =>
  937.       RESULT := ONE;
  938.       if X < ZERO then
  939.       RESULT := - ONE;
  940.       end if;
  941.       NEW_LINE; PUT("EXCEPTION IN CBRT, X = "); PUT(X);
  942.       PUT("  RETURNED  "); PUT(RESULT); NEW_LINE;
  943.       return RESULT;
  944.   end CBRT;
  945.  
  946.     function LOG(X : FLOAT) return FLOAT is
  947.  
  948.     RESULT : FLOAT;
  949.     N : EXPONENT_TYPE;
  950.     XN : FLOAT;
  951.     Y : FLOAT;
  952.     F : MANTISSA_TYPE;
  953.     Z, ZDEN, ZNUM : MANTISSA_TYPE;
  954.  
  955.     C0 : constant MANTISSA_TYPE := 0.20710_67811_86547_52440;
  956.                                                --  SQRT(0.5) - 0.5
  957.     C1 : constant FLOAT := 8#0.543#;
  958.     C2 : constant FLOAT :=-2.12194_44005_46905_82767_9E-4;
  959.  
  960.     function R(Z : MANTISSA_TYPE) return MANTISSA_TYPE is
  961.       A0 : constant MANTISSA_TYPE := 0.04862_85276_587;
  962.       B0 : constant MANTISSA_TYPE := 0.69735_92187_803;
  963.       B1 : constant MANTISSA_TYPE :=-0.125;
  964.       C  : constant MANTISSA_TYPE := 0.01360_09546_862;
  965.     begin
  966.       return Z + MANTISSA_TYPE(Z * 
  967.           MANTISSA_TYPE(MANTISSA_TYPE(Z * Z) * (C +
  968.           MANTISSA_TYPE(A0/(B0 + MANTISSA_TYPE(B1 * MANTISSA_TYPE(Z * Z)))))));
  969.     end R;
  970.  
  971.   begin
  972.  
  973.     if X < ZERO      then
  974.       NEW_LINE;
  975.       PUT("CALLED LOG FOR NEGATIVE ");
  976.       PUT(X);
  977.       PUT("   USE ABS => ");
  978.       RESULT := LOG(ABS(X));
  979.       PUT(RESULT);
  980.       NEW_LINE;
  981.     elsif X = ZERO  then
  982.       NEW_LINE;
  983.       PUT("CALLED LOG FOR ZERO ARGUMENT, RETURNED ");
  984.       RESULT := -XMAX;      --  SUPPOSED TO BE -LARGE
  985.       PUT(RESULT);
  986.       NEW_LINE;
  987.     else
  988.       DEFLOAT(X,N,F);
  989.       ZNUM := F - MANTISSA_HALF;
  990.       Y := CONVERT_TO_FLOAT(ZNUM);
  991.       ZDEN := ZNUM / MANTISSA_DIVISOR_2 + MANTISSA_HALF;
  992.       if ZNUM > C0  then
  993.         Y := Y - MANTISSA_HALF;
  994.         ZNUM := ZNUM - MANTISSA_HALF;
  995.         ZDEN := ZDEN + MANTISSA_HALF/MANTISSA_DIVISOR_2;
  996.       else
  997.         N := N -1;
  998.       end if;
  999.       Z    := MANTISSA_TYPE(ZNUM / ZDEN);
  1000.       RESULT := CONVERT_TO_FLOAT(R(Z));
  1001.       if N /= 0  then
  1002.         XN := CONVERT_TO_FLOAT(N);
  1003.         RESULT := (XN * C2 + RESULT) + XN * C1;
  1004.       end if;
  1005.     end if;
  1006.     return RESULT;
  1007.  
  1008.   exception
  1009.   when others =>
  1010.     NEW_LINE; PUT(" EXCEPTION IN LOG, X = "); PUT(X);
  1011.     PUT("  RETURNED 0.0"); NEW_LINE;
  1012.     return ZERO;
  1013.   end LOG;
  1014.  
  1015.  
  1016.   function LOG10(X : FLOAT) return FLOAT is
  1017.     LOG_10_OF_2 : constant FLOAT :=
  1018.              CONVERT_TO_FLOAT(MANTISSA_TYPE(8#0.33626_75425_11562_41615#));
  1019.   begin
  1020.     return LOG(X) * LOG_10_OF_2;
  1021.   end LOG10;
  1022.  
  1023.   function EXP(X : FLOAT) return FLOAT is
  1024.  
  1025.     RESULT : FLOAT;
  1026.     N : EXPONENT_TYPE;
  1027.     XG, XN, X1, X2 : FLOAT;
  1028.     F, G : MANTISSA_TYPE;
  1029.  
  1030.     BIGX : FLOAT := EXP_LARGE;
  1031.     SMALLX : FLOAT := EXP_SMALL;
  1032.  
  1033.     ONE_OVER_LOG_2 : constant FLOAT :=  1.4426_95040_88896_34074;
  1034.     C1 : constant FLOAT :=  0.69335_9375;
  1035.     C2 : constant FLOAT := -2.1219_44400_54690_58277E-4;
  1036.  
  1037.     function R(G : MANTISSA_TYPE) return MANTISSA_TYPE is
  1038.       Z , GP, Q : MANTISSA_TYPE;
  1039.  
  1040.       P0 : constant MANTISSA_TYPE :=  0.24999_99999_9992;
  1041.       P1 : constant MANTISSA_TYPE :=  0.00595_04254_9776;
  1042.       Q0 : constant MANTISSA_TYPE :=  0.5;
  1043.       Q1 : constant MANTISSA_TYPE :=  0.05356_75176_4522;
  1044.       Q2 : constant MANTISSA_TYPE :=  0.00029_72936_3682;
  1045.     begin
  1046.       Z  := MANTISSA_TYPE(G * G);
  1047.       GP := MANTISSA_TYPE( (MANTISSA_TYPE(P1 * Z) + P0) * G );
  1048.       Q  := MANTISSA_TYPE( (MANTISSA_TYPE(Q2 * Z) + Q1) * Z ) + Q0;
  1049.       return MANTISSA_HALF + MANTISSA_TYPE( GP /(Q - GP) );
  1050.     end R;
  1051.  
  1052.  
  1053.   begin
  1054.  
  1055.     if X > BIGX  then
  1056.       NEW_LINE;
  1057.       PUT("  EXP CALLED WITH TOO BIG A POSITIVE ARGUMENT, ");
  1058.           PUT(X); PUT("   RETURNED XMAX");
  1059.       NEW_LINE;
  1060.       RESULT := XMAX;
  1061.     elsif X < SMALLX  then
  1062.       NEW_LINE;
  1063.       PUT("  EXP CALLED WITH TOO BIG A NEGATIVE ARGUMENT,  ");
  1064.           PUT(X); PUT("    RETURNED ZERO");
  1065.       NEW_LINE;
  1066.       RESULT := ZERO;
  1067.     elsif ABS(X) < EPS  then
  1068.       RESULT := ONE;
  1069.     else
  1070.       N  := EXPONENT_TYPE(X * ONE_OVER_LOG_2);
  1071.       XN := CONVERT_TO_FLOAT(N);
  1072.       X1 := ROUND(X);
  1073.       X2 := X - X1;
  1074.       XG := ( (X1 - XN * C1) + X2 ) - XN * C2;
  1075.       G  := MANTISSA_TYPE(XG);
  1076.       N  := N + 1;
  1077.       F := R(G);
  1078.       REFLOAT(N, F, RESULT);
  1079.     end if;
  1080.     return RESULT;
  1081.  
  1082.   exception
  1083.   when others =>
  1084.     NEW_LINE; PUT(" EXCEPTION IN EXP, X = "); PUT(X);
  1085.     PUT("  RETURNED 1.0"); NEW_LINE;
  1086.     return ONE;
  1087.   end EXP;
  1088.  
  1089. function "**" (X, Y : FLOAT) return FLOAT is
  1090.   M, N : EXPONENT_TYPE;
  1091.   G : MANTISSA_TYPE;
  1092.   P, TEMP, IW1, I : INTEGER;
  1093.   RESULT, Z, V, R, U1, U2, W, W1, W2, W3, Y1, Y2 : FLOAT;
  1094.  
  1095.   K : constant FLOAT := 0.44269_50408_88963_40736;
  1096.   IBIGX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMAX) - 1.0));
  1097.   ISMALLX : constant INTEGER := INTEGER(TRUNCATE(16.0 * LOG(XMIN) + 1.0));
  1098.  
  1099.   P1 : constant FLOAT := 0.83333_32862_45E-1;
  1100.   P2 : constant FLOAT := 0.12506_48500_52E-1;
  1101.  
  1102.   Q1 : constant FLOAT := 0.69314_71805_56341;
  1103.   Q2 : constant FLOAT := 0.24022_65061_44710;
  1104.   Q3 : constant FLOAT := 0.55504_04881_30765E-1;
  1105.   Q4 : constant FLOAT := 0.96162_06595_83789E-2;
  1106.   Q5 : constant FLOAT := 0.13052_55159_42810E-2;
  1107.  
  1108.   A1 : array (1 .. 17) of FLOAT:=
  1109.      (  8#1.00000_0000#,        
  1110.         8#0.75222_5750#,        
  1111.         8#0.72540_3067#,        
  1112.         8#0.70146_3367#,        
  1113.         8#0.65642_3746#,        
  1114.         8#0.63422_2140#,        
  1115.         8#0.61263_4520#,        
  1116.         8#0.57204_2434#,        
  1117.         8#0.55202_3631#,        
  1118.         8#0.53254_0767#,        
  1119.         8#0.51377_3265#,        
  1120.         8#0.47572_4623#,        
  1121.         8#0.46033_7602#,        
  1122.         8#0.44341_7233#,        
  1123.         8#0.42712_7017#,        
  1124.         8#0.41325_3033#,        
  1125.         8#0.40000_0000#  );        
  1126.                 
  1127.   A2 : array (1 .. 8) of FLOAT :=
  1128.      (  8#0.00000_00005_22220_66302_61734_72062#,
  1129.         8#0.00000_00003_02522_47021_04062_61124#,
  1130.         8#0.00000_00005_21760_44016_17421_53016#,
  1131.         8#0.00000_00007_65401_41553_72504_02177#,
  1132.         8#0.00000_00002_44124_12254_31114_01243#,
  1133.         8#0.00000_00000_11064_10432_66404_42174#,
  1134.         8#0.00000_00004_72542_16063_30176_55544#,
  1135.         8#0.00000_00001_74611_03661_23056_22556#  );
  1136.        
  1137.  
  1138.   function REDUCE (V : FLOAT) return FLOAT is
  1139.   begin
  1140.     return FLOAT(INTEGER(16.0 * V)) * 0.0625;
  1141.   end REDUCE;
  1142.  
  1143.   begin
  1144.     if X <= ZERO then
  1145.       if X < ZERO then
  1146.         RESULT := (ABS(X))**Y;
  1147. --        NEW_LINE;
  1148. --        PUT("X**Y CALLED WITH X = "); PUT(X); PUT("  Y= "); PUT(Y); NEW_LINE;
  1149. --        PUT("USED ABS, RETURNED "); PUT(RESULT); NEW_LINE;
  1150.       else
  1151.         if Y <= ZERO then
  1152.           if Y = ZERO then
  1153.             RESULT := ZERO;
  1154.           else
  1155.             RESULT := XMAX;
  1156.           end if;
  1157.           NEW_LINE;
  1158.           PUT("X**Y CALLED WITH X = 0, Y = "); PUT(Y); NEW_LINE;
  1159.           PUT("RETURNED "); PUT(RESULT); NEW_LINE;
  1160.         else
  1161.           RESULT := ZERO;
  1162.         end if;
  1163.       end if;
  1164.     else
  1165.       DEFLOAT(X, M, G);
  1166.       P := 1;
  1167.       if G <= A1(9) then
  1168.         P := 9;
  1169.       end if;
  1170.       if G <= A1(P+4) then
  1171.         P := P + 4;
  1172.       end if;
  1173.       if G <= A1(P+2) then
  1174.         P := P + 2;
  1175.       end if;
  1176.       Z := ((G - A1(P+1)) - A2((P+1)/2))/(G + A1(P+1));
  1177.       Z := Z + Z;
  1178.       V := Z * Z;
  1179.       R := (P2 * V + P1) * V * Z;
  1180.       R := R + K * R;
  1181.       U2 := (R + Z * K) + Z;
  1182.       U1 := FLOAT(INTEGER(M) * 16 - P) * 0.0625;
  1183.       Y1 := REDUCE(Y);
  1184.       Y2 := Y - Y1;
  1185.       W := U2 * Y + U1 * Y2;
  1186.       W1 := REDUCE(W);
  1187.       W2 := W - W1;
  1188.       W := W1 + U1 * Y1;
  1189.       W1 := REDUCE(W);
  1190.       W2 := W2 + (W - W1);
  1191.       W3 := REDUCE(W2);
  1192.       IW1 := INTEGER(TRUNCATE(16.0 * (W1 + W3)));
  1193.       W2 := W2 - W3;
  1194.       if W > FLOAT(IBIGX) then
  1195.         RESULT := XMAX;
  1196.         PUT("X**Y CALLED  X ="); PUT(X); PUT("   Y ="); PUT(Y);
  1197.         PUT("   TOO LARGE  RETURNED "); PUT(RESULT); NEW_LINE;
  1198.       elsif W < FLOAT(ISMALLX) then
  1199.         RESULT := ZERO;
  1200.         PUT("X**Y CALLED  X ="); PUT(X); PUT("   Y ="); PUT(Y);
  1201.         PUT("   TOO SMALL  RETURNED "); PUT(RESULT); NEW_LINE;
  1202.       else
  1203.         if W2 > ZERO then
  1204.           W2 := W2 - 0.0625;
  1205.           IW1 := IW1 + 1;
  1206.         end if;
  1207.         if IW1 < INTEGER(ZERO) then
  1208.           I := 0;
  1209.         else 
  1210.           I := 1;
  1211.         end if;
  1212.         M := EXPONENT_TYPE(I + IW1/16);
  1213.         P := 16 * INTEGER(M) - IW1;
  1214.         Z := ((((Q5 * W2 + Q4) * W2 + Q3) * W2 + Q2) * W2 + Q1) * W2;
  1215.         Z := A1(P+1) + (A1(P+1) * Z);  
  1216.  
  1217.         REFLOAT(M, Z, RESULT);
  1218.       end if;
  1219.     end if;
  1220.     return RESULT;
  1221.   end "**";
  1222.  
  1223. begin
  1224.   EXP_LARGE := LOG(XMAX) * (ONE - EPS);
  1225.   EXP_SMALL := LOG(XMIN) * (ONE - EPS);
  1226. end CORE_FUNCTIONS;
  1227.  
  1228. package body TRIG_FUNCTIONS is
  1229.   use TEXT_IO;
  1230.   use FLOATING_CHARACTERISTICS;
  1231.   use NUMERIC_IO;
  1232.   use NUMERIC_PRIMITIVES;
  1233.   use CORE_FUNCTIONS;
  1234.  
  1235.  
  1236.  
  1237.   function SIN(X : FLOAT) return FLOAT is
  1238.     SGN, Y : FLOAT;
  1239.     N : INTEGER;
  1240.     XN : FLOAT;
  1241.     F, G, X1, X2 : FLOAT;
  1242.     RESULT : FLOAT;
  1243.  
  1244.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2)));
  1245.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1246.     EPSILON : FLOAT := BETA ** (-IT/2);
  1247.  
  1248.     C1 : constant FLOAT :=  3.140625;
  1249.     C2 : constant FLOAT :=  9.6765_35897_93E-4;
  1250.  
  1251.     function R(G : FLOAT) return FLOAT is
  1252.       R1 : constant FLOAT := -0.16666_66660_883;
  1253.       R2 : constant FLOAT :=  0.83333_30720_556E-2;
  1254.       R3 : constant FLOAT := -0.19840_83282_313E-3;
  1255.       R4 : constant FLOAT :=  0.27523_97106_775E-5;
  1256.       R5 : constant FLOAT := -0.23868_34640_601E-7;
  1257.     begin
  1258.       return ((((R5*G + R4)*G + R3)*G + R2)*G + R1)*G;
  1259.     end R;
  1260.  
  1261.   begin
  1262.     if X < ZERO  then
  1263.       SGN := -ONE;
  1264.       Y := -X;
  1265.     else
  1266.       SGN := ONE;
  1267.       Y := X;
  1268.     end if;
  1269.  
  1270.     if Y > YMAX  then
  1271.       NEW_LINE;
  1272.       PUT(" SIN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1273.       PUT(X); NEW_LINE;
  1274.     end if;
  1275.  
  1276.     N := INTEGER(Y * ONE_OVER_PI);
  1277.     XN := CONVERT_TO_FLOAT(N);
  1278.     if N mod 2 /= 0  then
  1279.       SGN := -SGN;
  1280.     end if;
  1281.     X1 := TRUNCATE(ABS(X));
  1282.     X2 := ABS(X) - X1;
  1283.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1284.     if ABS(F) < EPSILON  then
  1285.       RESULT := F;
  1286.     else
  1287.       G := F * F;
  1288.       RESULT := F + F*R(G);
  1289.     end if;
  1290.     return (SGN * RESULT);
  1291.   end SIN;
  1292.  
  1293.  
  1294.   function COS(X : FLOAT) return FLOAT is
  1295.     SGN, Y : FLOAT;
  1296.     N : INTEGER;
  1297.     XN : FLOAT;
  1298.     F, G, X1, X2 : FLOAT;
  1299.     RESULT : FLOAT;
  1300.  
  1301.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2)));
  1302.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1303.     EPSILON : FLOAT := BETA ** (-IT/2);
  1304.  
  1305.     C1 : constant FLOAT :=  3.140625;
  1306.     C2 : constant FLOAT :=  9.6765_35897_93E-4;
  1307.  
  1308.     function R(G : FLOAT) return FLOAT is
  1309.       R1 : constant FLOAT := -0.16666_66660_883;
  1310.       R2 : constant FLOAT :=  0.83333_30720_556E-2;
  1311.       R3 : constant FLOAT := -0.19840_83282_313E-3;
  1312.       R4 : constant FLOAT :=  0.27523_97106_775E-5;
  1313.       R5 : constant FLOAT := -0.23868_34640_601E-7;
  1314.     begin
  1315.       return ((((R5*G + R4)*G + R3)*G + R2)*G + R1)*G;
  1316.     end R;
  1317.  
  1318.   begin
  1319.     SGN := 1.0;
  1320.     Y := ABS(X) + PI_OVER_TWO;
  1321.  
  1322.     if Y > YMAX  then
  1323.       NEW_LINE;
  1324.       PUT(" COS CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1325.       PUT(X); NEW_LINE;
  1326.     end if;
  1327.  
  1328.     N := INTEGER(Y * ONE_OVER_PI);
  1329.     XN := CONVERT_TO_FLOAT(N);
  1330.     if N mod 2 /= 0  then
  1331.       SGN := -SGN;
  1332.     end if;
  1333.     XN := XN - 0.5;          -- TO FORM COS INSTEAD OF SIN
  1334.     X1 := TRUNCATE(ABS(X));
  1335.     X2 := ABS(X) - X1;
  1336.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1337.     if ABS(F) < EPSILON  then
  1338.       RESULT := F;
  1339.     else
  1340.       G := F * F;
  1341.       RESULT := F + F*R(G);
  1342.     end if;
  1343.     return (SGN * RESULT);
  1344.   end COS;
  1345.  
  1346.  
  1347.   function TAN(X : FLOAT) return FLOAT is
  1348.     SGN, Y : FLOAT;
  1349.     N : INTEGER;
  1350.     XN : FLOAT;
  1351.     F, G, X1, X2 : FLOAT;
  1352.     RESULT : FLOAT;
  1353.  
  1354.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2))) /2.0;
  1355.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1356.     EPSILON : FLOAT := BETA ** (-IT/2);
  1357.  
  1358.     C1 : constant FLOAT :=  8#1.444#;
  1359.     C2 : constant FLOAT :=  4.8382_67948_97E-4;
  1360.  
  1361.     function R(G : FLOAT) return FLOAT is
  1362.       P0 : constant FLOAT :=  1.0;
  1363.       P1 : constant FLOAT := -0.11136_14403_566;
  1364.       P2 : constant FLOAT :=  0.10751_54738_488E-2;
  1365.       Q0 : constant FLOAT :=  1.0;
  1366.       Q1 : constant FLOAT := -0.44469_47720_281;
  1367.       Q2 : constant FLOAT :=  0.15973_39213_300E-1;
  1368.     begin
  1369.       return ((P2*G + P1)*G*F + F) / (((Q2*G + Q1)*G +0.5) + 0.5);
  1370.     end R;
  1371.  
  1372.   begin
  1373.     Y := ABS(X);
  1374.     if Y > YMAX  then
  1375.       NEW_LINE;
  1376.       PUT(" TAN CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1377.       PUT(X); NEW_LINE;
  1378.     end if;
  1379.  
  1380.     N := INTEGER(X * TWO_OVER_PI);
  1381.     XN := CONVERT_TO_FLOAT(N);
  1382.     X1 := TRUNCATE(X);
  1383.     X2 := X - X1;
  1384.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1385.     if ABS(F) < EPSILON  then
  1386.       RESULT := F;
  1387.     else
  1388.       G := F * F;
  1389.       RESULT := R(G);
  1390.     end if;
  1391.     if N mod 2 = 0  then
  1392.       return RESULT;
  1393.     else
  1394.       return -1.0/RESULT;
  1395.     end if;
  1396.   end TAN;
  1397.  
  1398.   function COT(X : FLOAT) return FLOAT is
  1399.     SGN, Y : FLOAT;
  1400.     N : INTEGER;
  1401.     XN : FLOAT;
  1402.     F, G, X1, X2 : FLOAT;
  1403.     RESULT : FLOAT;
  1404.  
  1405.  
  1406.     YMAX : FLOAT := FLOAT(INTEGER(PI * TWO**(IT/2))) /2.0;
  1407.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1408.     EPSILON : FLOAT := BETA ** (-IT/2);
  1409.     EPSILON1 : FLOAT :=  1.0/XMAX;
  1410.  
  1411.     C1 : constant FLOAT :=  8#1.444#;
  1412.     C2 : constant FLOAT :=  4.8382_67948_97E-4;
  1413.  
  1414.     function R(G : FLOAT) return FLOAT is
  1415.       P0 : constant FLOAT :=  1.0;
  1416.       P1 : constant FLOAT := -0.11136_14403_566;
  1417.       P2 : constant FLOAT :=  0.10751_54738_488E-2;
  1418.       Q0 : constant FLOAT :=  1.0;
  1419.       Q1 : constant FLOAT := -0.44469_47720_281;
  1420.       Q2 : constant FLOAT :=  0.15973_39213_300E-1;
  1421.     begin
  1422.       return ((P2*G + P1)*G*F + F) / (((Q2*G + Q1)*G +0.5) + 0.5);
  1423.     end R;
  1424.  
  1425.   begin
  1426.     Y := ABS(X);
  1427.     if Y < EPSILON1  then
  1428.       NEW_LINE;
  1429.       PUT(" COT CALLED WITH ARGUMENT TOO NEAR ZERO ");
  1430.       PUT(X); NEW_LINE;
  1431.       if X < 0.0  then
  1432.         return -XMAX;
  1433.       else
  1434.         return XMAX;
  1435.       end if;
  1436.     end if;
  1437.     if Y > YMAX  then
  1438.       NEW_LINE;
  1439.       PUT(" COT CALLED WITH ARGUMENT TOO LARGE FOR ACCURACY ");
  1440.       PUT(X); NEW_LINE;
  1441.     end if;
  1442.  
  1443.     N := INTEGER(X * TWO_OVER_PI);
  1444.     XN := CONVERT_TO_FLOAT(N);
  1445.     X1 := TRUNCATE(X);
  1446.     X2 := X - X1;
  1447.     F := ((X1 - XN*C1) + X2) - XN*C2;
  1448.     if ABS(F) < EPSILON  then
  1449.       RESULT := F;
  1450.     else
  1451.       G := F * F;
  1452.       RESULT := R(G);
  1453.     end if;
  1454.     if N mod 2 /= 0  then
  1455.       return -RESULT;
  1456.     else
  1457.       return 1.0/RESULT;
  1458.     end if;
  1459.   end COT;
  1460.  
  1461.  
  1462.   function ASIN(X : FLOAT) return FLOAT is
  1463.     G, Y : FLOAT;
  1464.     RESULT : FLOAT;
  1465.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1466.     EPSILON : FLOAT := BETA ** (-IT/2);
  1467.  
  1468.     function R(G : FLOAT) return FLOAT is
  1469.     P1 : constant FLOAT := -0.27516_55529_0596E1;
  1470.     P2 : constant FLOAT :=  0.29058_76237_4859E1;
  1471.     P3 : constant FLOAT := -0.59450_14419_3246;
  1472.     Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1473.     Q1 : constant FLOAT :=  0.24864_72896_9164E2;
  1474.     Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1475.     Q3 : constant FLOAT :=  1.0;
  1476.     begin
  1477.       return (((P3*G + P2)*G + P1)*G) / (((G + Q2)*G + Q1)*G + Q0);
  1478.     end R;
  1479.  
  1480.   begin
  1481.     Y := ABS(X);
  1482.  
  1483.     if Y > HALF  then
  1484.       if Y > 1.0  then
  1485.         NEW_LINE; PUT(" ASIN CALLED FOR "); PUT(X);
  1486.             PUT(" (> 1)  TRUNCATED TO 1, CONTINUED"); NEW_LINE;
  1487.         Y := 1.0;
  1488.       end if;
  1489.       G := ((0.5 - Y) + 0.5) / 2.0;
  1490.       Y := -2.0 * SQRT(G);
  1491.       RESULT := Y + Y * R(G);
  1492.       RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1493.     else
  1494.       if Y < EPSILON  then
  1495.         RESULT := Y;
  1496.       else
  1497.         G := Y * Y;
  1498.         RESULT := Y + Y * R(G);
  1499.       end if;
  1500.     end if;
  1501.     if X < 0.0  then
  1502.       RESULT := -RESULT;
  1503.     end if;
  1504.  
  1505.     return RESULT;
  1506.   end ASIN;
  1507.  
  1508.   function ACOS(X : FLOAT) return FLOAT is
  1509.     G, Y : FLOAT;
  1510.     RESULT : FLOAT;
  1511.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1512.     EPSILON : FLOAT := BETA ** (-IT/2);
  1513.  
  1514.     function R(G : FLOAT) return FLOAT is
  1515.     P1 : constant FLOAT := -0.27516_55529_0596E1;
  1516.     P2 : constant FLOAT :=  0.29058_76237_4859E1;
  1517.     P3 : constant FLOAT := -0.59450_14419_3246;
  1518.     Q0 : constant FLOAT := -0.16509_93320_2424E2;
  1519.     Q1 : constant FLOAT :=  0.24864_72896_9164E2;
  1520.     Q2 : constant FLOAT := -0.10333_86707_2113E2;
  1521.     Q3 : constant FLOAT :=  1.0;
  1522.     begin
  1523.       return (((P3*G + P2)*G + P1)*G) / (((G + Q2)*G + Q1)*G + Q0);
  1524.     end R;
  1525.  
  1526.   begin
  1527.     Y := ABS(X);
  1528.  
  1529.     if Y > HALF  then
  1530.       if Y > 1.0  then
  1531.         NEW_LINE; PUT(" ACOS CALLED FOR "); PUT(X);
  1532.             PUT(" (> 1)  TRUNCATED TO 1, CONTINUED"); NEW_LINE;
  1533.         Y := 1.0;
  1534.       end if;
  1535.       G := ((0.5 - Y) + 0.5) / 2.0;
  1536.       Y := -2.0 * SQRT(G);
  1537.       RESULT := Y + Y * R(G);
  1538.       if X < 0.0  then
  1539.         RESULT := (PI_OVER_TWO + RESULT) + PI_OVER_TWO;
  1540.       else
  1541.         RESULT := -RESULT;
  1542.       end if;
  1543.  
  1544.     else
  1545.       if Y < EPSILON  then
  1546.         RESULT := Y;
  1547.       else
  1548.         G := Y * Y;
  1549.         RESULT := Y + Y * R(G);
  1550.       end if;
  1551.       if X < 0.0  then
  1552.         RESULT := (PI_OVER_FOUR + RESULT) + PI_OVER_FOUR;
  1553.       else
  1554.         RESULT := (PI_OVER_FOUR - RESULT) + PI_OVER_FOUR;
  1555.       end if;
  1556.     end if;
  1557.  
  1558.     return RESULT;
  1559.   end ACOS;
  1560.  
  1561.  
  1562.   function ATAN(X : FLOAT) return FLOAT is
  1563.     F, G : FLOAT;
  1564.     subtype REGION is INTEGER range 0..3;    --  ##########
  1565.     N : REGION;
  1566.     RESULT : FLOAT;
  1567.  
  1568.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1569.  
  1570.     EPSILON : FLOAT := BETA ** (-IT/2);
  1571.  
  1572.     SQRT_3           : constant FLOAT :=  1.73205_08075_68877_29353;
  1573.     SQRT_3_MINUS_1   : constant FLOAT :=  0.73205_08075_68877_29353;
  1574.     TWO_MINUS_SQRT_3 : constant FLOAT :=  0.26794_91924_31122_70647;
  1575.  
  1576.     function R(G : FLOAT) return FLOAT is
  1577.       P0 : constant FLOAT := -0.14400_83448_74E1;
  1578.       P1 : constant FLOAT := -0.72002_68488_98;
  1579.       Q0 : constant FLOAT :=  0.43202_50389_19E1;
  1580.       Q1 : constant FLOAT :=  0.47522_25845_99E1;
  1581.       Q2 : constant FLOAT :=  1.0;
  1582.     begin
  1583.       return ((P1*G + P0)*G) / ((G + Q1)*G + Q0);
  1584.     end R;
  1585.  
  1586.   begin
  1587.     F := ABS(X);
  1588.  
  1589.     if F > 1.0  then
  1590.       F := 1.0 / F;
  1591.       N := 2;
  1592.     else
  1593.       N := 0;
  1594.     end if;
  1595.  
  1596.     if F > TWO_MINUS_SQRT_3  then
  1597.       F := (((SQRT_3_MINUS_1 * F - 0.5) - 0.5) + F) / (SQRT_3 + F);
  1598.       N := N + 1;
  1599.     end if;
  1600.  
  1601.     if ABS(F) < EPSILON  then
  1602.       RESULT := F;
  1603.     else
  1604.       G := F * F;
  1605.       RESULT := F + F * R(G);
  1606.     end if;
  1607.  
  1608.     if N > 1  then
  1609.       RESULT := - RESULT;
  1610.     end if;
  1611.  
  1612.     case N is
  1613.     when 0  =>
  1614.       RESULT := RESULT;
  1615.     when 1  =>
  1616.       RESULT := PI_OVER_SIX + RESULT;
  1617.     when 2  =>
  1618.       RESULT := PI_OVER_TWO + RESULT;
  1619.     when 3  =>
  1620.       RESULT := PI_OVER_THREE + RESULT;
  1621.     end case;
  1622.  
  1623.     if X < 0.0  then
  1624.       RESULT := - RESULT;
  1625.     end if;
  1626.  
  1627.     return RESULT;
  1628.  
  1629.   end ATAN;
  1630.  
  1631.  
  1632.  
  1633.   function ATAN2(V, U : FLOAT) return FLOAT is
  1634.     X, RESULT : FLOAT;
  1635.  
  1636.   begin
  1637.  
  1638.     if U = 0.0  then
  1639.       if V = 0.0  then
  1640.         RESULT := 0.0;
  1641.         NEW_LINE;
  1642.         PUT(" ATAN2 CALLED WITH 0/0   RETURNED "); PUT(RESULT);
  1643.         NEW_LINE;
  1644.       elsif V > 0.0  then
  1645.         RESULT := PI_OVER_TWO;
  1646.       else
  1647.         RESULT := - PI_OVER_TWO;
  1648.       end if;
  1649.  
  1650.     else
  1651.       X := ABS(V/U);
  1652.       --  If underflow or overflow is detected, go to the exception
  1653.       RESULT := ATAN(X);
  1654.       if U < 0.0  then
  1655.         RESULT := PI - RESULT;
  1656.       end if;
  1657.       if V < 0.0  then
  1658.         RESULT := - RESULT;
  1659.       end if;
  1660.     end if;
  1661.     return RESULT;
  1662.   exception
  1663.   when NUMERIC_ERROR  =>
  1664.     if ABS(V) > ABS(U)  then
  1665.       RESULT := PI_OVER_TWO;
  1666.       if V < 0.0  then
  1667.         RESULT := - RESULT;
  1668.       end if;
  1669.     else
  1670.       RESULT := 0.0;
  1671.       if U < 0.0  then
  1672.         RESULT := PI - RESULT;
  1673.       end if;
  1674.     end if;
  1675.     return RESULT;
  1676.   end ATAN2;
  1677.  
  1678.  
  1679.   function SINH(X : FLOAT) return FLOAT is
  1680.     G, W, Y, Z : FLOAT;
  1681.     RESULT : FLOAT;
  1682.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1683.     EPSILON : FLOAT := BETA ** (-IT/2);
  1684.  
  1685.     YBAR : FLOAT := EXP_LARGE;
  1686.     LN_V : FLOAT := 8#0.542714#;
  1687.     V_OVER_2_MINUS_1 : FLOAT :=  0.13830_27787_96019_02638E-4;
  1688.     WMAX : FLOAT := YBAR - LN_V + 0.69;
  1689.  
  1690.     function R(G : FLOAT) return FLOAT is
  1691.     P0 : constant FLOAT :=  0.10622_28883_7151E4;
  1692.     P1 : constant FLOAT :=  0.31359_75645_6058E2;
  1693.     P2 : constant FLOAT :=  0.34364_14035_8506;
  1694.     Q0 : constant FLOAT :=  0.63733_73302_1822E4;
  1695.     Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1696.     Q2 : constant FLOAT :=  1.0;
  1697.     begin
  1698.       return (((P2*G + P1)*G + P0)*G) / ((G + Q1)*G + Q0);
  1699.     end R;
  1700.  
  1701.   begin
  1702.     Y := ABS(X);
  1703.  
  1704.     if Y <= 1.0  then
  1705.       if Y < EPSILON  then
  1706.         RESULT := X;
  1707.       else
  1708.         G := X * X;
  1709.         RESULT := X + X * R(G);
  1710.       end if;
  1711.  
  1712.     else
  1713.       if Y <= YBAR  then
  1714.         Z := EXP(Y);
  1715.         RESULT := (Z - 1.0/Z) / 2.0;
  1716.       else
  1717.         W := Y - LN_V;
  1718.         if W > WMAX  then
  1719.           NEW_LINE;
  1720.           PUT(" SINH CALLED WITH TOO LARGE ARGUMENT  "); PUT(X);
  1721.           PUT(" RETURN BIG"); NEW_LINE;
  1722.           W := WMAX;
  1723.         end if;
  1724.         Z := EXP(W);
  1725.         RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1726.       end if;
  1727.       if X < 0.0  then
  1728.         RESULT := -RESULT;
  1729.       end if;
  1730.  
  1731.     end if;
  1732.     return RESULT;
  1733.   end SINH;
  1734.  
  1735.  
  1736.   function COSH(X : FLOAT) return FLOAT is
  1737.     G, W, Y, Z : FLOAT;
  1738.     RESULT : FLOAT;
  1739.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1740.     EPSILON : FLOAT := BETA ** (-IT/2);
  1741.  
  1742.     YBAR : FLOAT := EXP_LARGE;
  1743.     LN_V : FLOAT := 8#0.542714#;
  1744.     V_OVER_2_MINUS_1 : FLOAT :=  0.13830_27787_96019_02638E-4;
  1745.     WMAX : FLOAT := YBAR - LN_V + 0.69;
  1746.  
  1747.     function R(G : FLOAT) return FLOAT is
  1748.     P0 : constant FLOAT :=  0.10622_28883_7151E4;
  1749.     P1 : constant FLOAT :=  0.31359_75645_6058E2;
  1750.     P2 : constant FLOAT :=  0.34364_14035_8506;
  1751.     Q0 : constant FLOAT :=  0.63733_73302_1822E4;
  1752.     Q1 : constant FLOAT := -0.13051_01250_9199E3;
  1753.     Q2 : constant FLOAT :=  1.0;
  1754.     begin
  1755.       return (((P2*G + P1)*G + P0)*G) / ((G + Q1)*G + Q0);
  1756.     end R;
  1757.  
  1758.   begin
  1759.     Y := ABS(X);
  1760.  
  1761.     if Y <= YBAR  then
  1762.       Z := EXP(Y);
  1763.       RESULT := (Z + 1.0/Z) / 2.0;
  1764.     else
  1765.       W := Y - LN_V;
  1766.       if W > WMAX  then
  1767.         NEW_LINE;
  1768.         PUT(" COSH CALLED WITH TOO LARGE ARGUMENT  "); PUT(X);
  1769.         PUT(" RETURN BIG"); NEW_LINE;
  1770.         W := WMAX;
  1771.       end if;
  1772.       Z := EXP(W);
  1773.       RESULT := Z + V_OVER_2_MINUS_1 * Z;
  1774.     end if;
  1775.  
  1776.     return RESULT;
  1777.   end COSH;
  1778.  
  1779.  
  1780.   function TANH(X : FLOAT) return FLOAT is
  1781.     G, W, Y, Z : FLOAT;
  1782.     RESULT : FLOAT;
  1783.     BETA : FLOAT := CONVERT_TO_FLOAT(IBETA);
  1784.     EPSILON : FLOAT := BETA ** (-IT/2);
  1785.  
  1786.     XBIG : FLOAT := (LOG(2.0) + CONVERT_TO_FLOAT(IT + 1) * LOG(BETA))/2.0;
  1787.     LN_3_OVER_2 : FLOAT :=  0.54930_61443_34054_84570;
  1788.  
  1789.     function R(G : FLOAT) return FLOAT is
  1790.     P0 : constant FLOAT := -0.21063_95800_0245E2;
  1791.     P1 : constant FLOAT := -0.93363_47565_2401;
  1792.     Q0 : constant FLOAT :=  0.63191_87401_5582E2;
  1793.     Q1 : constant FLOAT :=  0.28077_65347_0471E2;
  1794.     Q2 : constant FLOAT :=  1.0;
  1795.     begin
  1796.       return ((P1*G + P0)*G) / ((G + Q1)*G + Q0);
  1797.     end R;
  1798.  
  1799.   begin
  1800.     Y := ABS(X);
  1801.  
  1802.     if Y > XBIG  then
  1803.       RESULT := 1.0;
  1804.     else
  1805.       if Y > LN_3_OVER_2  then
  1806.         RESULT := 0.5 - 1.0 / (EXP(Y + Y) + 1.0);
  1807.         RESULT := RESULT + RESULT;
  1808.       else
  1809.         if Y < EPSILON  then
  1810.           RESULT := Y;
  1811.         else
  1812.           G := Y * Y;
  1813.           RESULT := Y + Y * R(G);
  1814.         end if;
  1815.       end if;
  1816.     end if;
  1817.     if X < 0.0  then
  1818.       RESULT := - RESULT;
  1819.     end if;
  1820.  
  1821.     return RESULT;
  1822.   end TANH;
  1823.  
  1824.  
  1825. begin
  1826.   null;
  1827. end TRIG_FUNCTIONS;
  1828.  
  1829. end MATHLIB;
  1830. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1831. --ENTITYUTI
  1832. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  1833. With Debugger; Use Debugger;
  1834. With Text_IO; use Text_io,float_io,integer_io;
  1835. With Mathlib; use Mathlib,core_functions;
  1836. With Types; Use Types;
  1837. With Constants; Use Constants;
  1838. With HELPS; use HELPS;
  1839. Package ENTITYUTI is
  1840. --
  1841.       Procedure ALPHA_TO_INTEGER(BUFFER: in string;
  1842.                                  NUMERIC_VALUE: out float);
  1843.       Procedure ALPHA_TO_INTEGERIZED_ALPHA(BUFFER: in out string;
  1844.                                          INTEGERIZED_ALPHA: out long_integer);
  1845.       Procedure ALPHA_TO_NUMERIC(BUFFER: in out string;
  1846.                                  NREP: out integer;
  1847.                                  NUMERIC_VALUE: out float);
  1848.       Procedure ANTENNA_CHECK(IATYP: in integer;
  1849.                               NFREQ: in BAND_TYPES; 
  1850.                               GAIN: in out float;
  1851.                               HEIGHT: in out float;
  1852.                               ALNGTH: in out float;
  1853.                               TLTANG: in out float;
  1854.                               IERR: out integer);
  1855.       Function DIGIT_CHECK(MCHAR: character) return boolean;
  1856.       Procedure INTEGER_TO_ALPHA(INTEGERIZED_ALPHA: in long_integer;
  1857.                                  BUFFER: out string);
  1858.       Procedure NEW_TITLE_CHECK;
  1859.       Procedure PARSE(BUFFER: in out string);
  1860. --
  1861. End ENTITYUTI;
  1862. -- 
  1863. Package body ENTITYUTI is
  1864. --
  1865. -- ENTITYUTI Package of PROP_LINK Version 1.0, February 5, 1985
  1866. --
  1867. -- This ENTITY_UTILITIES Package contains all general purpose utilities
  1868. -- that support the subject of entity (e.g., Nodes, Transmitters and
  1869. -- Receivers) handling.
  1870. --
  1871. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  1872. -- radio frequency propagation prediction code.
  1873. --
  1874. -- PROP_LINK has been developed for the Department of Defense under
  1875. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  1876. -- Systems Inc. (Jim Conrad).
  1877. --
  1878. --
  1879. -- CONSTANTS:
  1880.       CHAR_UPPER: string(1..38) := " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789*";
  1881.       CHAR_LOWER: string(1..27) := " abcdefghijklmnopqrstuvwxyz";
  1882. --
  1883. -- TYPES:
  1884. --
  1885. -- VARIABLES:
  1886.       BUFFER: array (integer range 1..6) of character;
  1887.       INTEGERIZED_ALPHA: long_integer;
  1888.       HEIGHT:float;
  1889. --
  1890. --
  1891. Procedure ALPHA_TO_INTEGER(BUFFER: in string;
  1892.                            NUMERIC_VALUE: out float) is
  1893. --
  1894. --PURPOSE: ALPHA_TO_INTEGER converts the string of digits in the input 
  1895. --         string to an integer number with a positive sign.
  1896. --
  1897. --AUTHOR:  J. Conrad
  1898. --
  1899. --TYPE:    Digit Manipulation
  1900. --
  1901. --PARAMETER DESCRIPTIONS:
  1902. --IN       BUFFER  = The string containing the sequential digits to be 
  1903. --                  converted
  1904. --OUT      NUMERIC_VALUE    = The resultant float number
  1905. --
  1906. --CALLED BY:
  1907. --         ALPHA_TO_NUMERIC
  1908. --
  1909. --CALLS TO:
  1910. --         'NONE'
  1911. --
  1912. --TECHNICAL DESCRIPTION:
  1913. --         ALPHA_TO_INTEGER converts the string of digits in the input 
  1914. --         string to a float number with a positive sign.  The technique
  1915. --         used raises the base of the number 10 to the individual
  1916. --         value of each digit as input and sums the results.
  1917. --
  1918.       J: integer;
  1919.       LIM: integer;
  1920.       IEXP: integer;
  1921. --
  1922.       Begin
  1923. --
  1924.       NUMERIC_VALUE := 0.0;
  1925.       LIM := 1;
  1926.       IEXP := -1;
  1927. --
  1928. --COUNT THE DIGITS.
  1929.       For J in 1..81 Loop
  1930.          If J = 81 Then
  1931.             Return;
  1932.          End If;
  1933.          LIM := J;
  1934.          If BUFFER(J) = ' ' Then
  1935.             Exit;
  1936.           End If;
  1937.       End Loop;
  1938. --
  1939.       Loop
  1940.          LIM := LIM - 1;
  1941.          IEXP := IEXP + 1;
  1942.          If LIM = 0 Then
  1943.             Exit;
  1944.          End If;
  1945.          For J in 28..38 Loop
  1946.             If J = 38 Then
  1947.                New_line;
  1948.                Put("WARNING...Improper number field.");
  1949.                Return;
  1950.             End If;
  1951.             If BUFFER(LIM) = CHAR_UPPER(J) Then
  1952.                NUMERIC_VALUE := NUMERIC_VALUE + FLOAT((J-28)) * 10.0**IEXP;
  1953.                Exit; 
  1954.             End If;
  1955.          End Loop;
  1956.       End Loop;
  1957.       Return;
  1958. --
  1959.       End ALPHA_TO_INTEGER; 
  1960. --
  1961. --
  1962. Procedure ALPHA_TO_INTEGERIZED_ALPHA (BUFFER: in out string;
  1963.                             INTEGERIZED_ALPHA: out long_integer) is
  1964. --
  1965. --PURPOSE: ALPHA_TO_INTEGERIZED_ALPHA converts an alphanumeric input of up to six
  1966. --         characters to a unique integer representation.
  1967. --
  1968. --AUTHOR:  J. Conrad
  1969. --
  1970. --TYPE:    Conversion Module
  1971. --
  1972. --PARAMETER DESCRIPTIONS:
  1973. --IO        BUFFER = The six element string containing the alphanumeric
  1974. --                   data to be converted.
  1975. --OUT       INTEGERIZED_ALPHA = The integer representation of the input data.
  1976. --
  1977. --CALLED BY:
  1978. --          PARSE
  1979. --
  1980. --CALLS TO:
  1981. --         'NONE'
  1982. --
  1983. --TECHNICAL DESCRIPTION:
  1984. --         This procedure accepts up to six alphanumeric characters, the
  1985. --         first of which must be alpha, and converts them to an
  1986. --         unique integer representation for internal use.  Allowable
  1987. --         characters are A-Z, 0-9.  The result is left justified and
  1988. --         blank filled to six characters.  An integer base of 37 is
  1989. --         used which results in integer values between 71270178 and
  1990. --         1943557016.  Lower case letters are first converted to
  1991. --         upper case.
  1992. --
  1993.       I,J: integer;
  1994. --
  1995.       Begin
  1996. --
  1997.       INTEGERIZED_ALPHA := 0;
  1998. --
  1999.       For I in 1..6 Loop
  2000. --
  2001.       --CONVERT ANY LOWER CASE TO UPPER CASE.
  2002.          For J in CHAR_LOWER'RANGE Loop
  2003.             If BUFFER(I) = CHAR_LOWER(J) Then
  2004.                BUFFER(I) := CHAR_UPPER(J);
  2005.                Exit;
  2006.             End If;
  2007.          End Loop;
  2008. --
  2009.       --CONVERT ALPHANUMERIC TO INTEGER.
  2010.          For J in CHAR_UPPER'RANGE Loop
  2011.             If J = 38 Then
  2012.                New_line;
  2013.                Put("WARNING...Improper alphanumeric field.");
  2014.                Return;
  2015.             End If;
  2016.             If BUFFER(I) = CHAR_UPPER(J) Then
  2017.                INTEGERIZED_ALPHA := INTEGERIZED_ALPHA + (long_integer(J) *
  2018.                                     long_integer (37)**(6-I));
  2019.                Exit;
  2020.             End If;
  2021.          End Loop;
  2022. --
  2023.       End Loop;
  2024. --
  2025.       Return;
  2026.       End ALPHA_TO_INTEGERIZED_ALPHA;
  2027. --
  2028. Procedure ALPHA_TO_NUMERIC (BUFFER: in out string;
  2029.                             NREP: out integer;
  2030.                             NUMERIC_VALUE: out float) is
  2031. --
  2032. --PURPOSE: ALPHA_TO_NUMERIC converts the alphanumeric digits and data 
  2033. --         to the proper number for arithmetic use.  It can handle
  2034. --         integer, float, and exponential type notations as well as
  2035. --         negative numbers.
  2036. --
  2037. --AUTHOR:  J. Conrad
  2038. --
  2039. --TYPE:    Conversion Module
  2040. --
  2041. --PARAMETER DESCRIPTIONS:
  2042. --IO       BUFFER        = The 80 element string containing the alphanumeric
  2043. --                         data to be converted.
  2044. --OUT      NREP          = The number of repetitions
  2045. --OUT      NUMERIC_VALUE = The numeric representation of the number
  2046. --
  2047. --CALLED BY:
  2048. --         PARSE
  2049. --
  2050. --CALLS TO:
  2051. --         DIGIT_CHECK
  2052. --         ALPHA_TO_INTEGER
  2053. --         SHIFT_LEFT
  2054. --
  2055. --TECHNICAL DESCRIPTION:
  2056. --         ALPHA_TO_NUMERIC converts the alphanumeric digits and data to the
  2057. --         proper number for arithmetic use.  It can handle integer, float, 
  2058. --         and exponential type notations as well as negative numbers.  
  2059. --         ALPHA_TO_NUMERIC can also handle * as an input symbol.
  2060. --         The technique employed is one of shifting and examining the
  2061. --         characters as input, one at a time, and then making the
  2062. --         appropriate conversion.
  2063. --
  2064.       KTEMP: string(1..80);
  2065.       VAL2: float;
  2066.       IFL22: integer;
  2067.       ISIGN: integer;
  2068.       J,M: integer;
  2069. --
  2070.       Begin
  2071. --
  2072. --INITIALIZATION.
  2073.       IFL22 := 0;
  2074.       ISIGN := 1;
  2075.       NUMERIC_VALUE := 0.0;
  2076.       NREP := 1;
  2077. <<THE_BEGINNING>>
  2078. --
  2079. --BLANK OUT THE KTEMP ARRAY.
  2080.       For J in KTEMP'RANGE Loop
  2081.          KTEMP(J) :=  ' ';
  2082.       End Loop;
  2083. --
  2084. --SHIFT LEFT UNTIL NON-BLANK CHARACTER FOUND.
  2085.       For J in 1..81 Loop
  2086.          If J = 81 Then
  2087.             Return;
  2088.          End If;
  2089.          If BUFFER(1) /= ' ' Then
  2090.             Exit;
  2091.          End If;
  2092.          SHIFT_LEFT(BUFFER);
  2093.       End Loop;
  2094. --
  2095. --PICK UP THE SIGN OF THE NUMBER.
  2096.       If BUFFER(1) = '-' Then
  2097.          ISIGN := -1;
  2098.          SHIFT_LEFT(BUFFER);
  2099.       End If;
  2100.       M := 0;
  2101.       If BUFFER(1) = '+' Then
  2102.          SHIFT_LEFT(BUFFER);
  2103.       End If;
  2104. --
  2105. --PICK OFF INTEGER PORTION.
  2106.       If BUFFER(1) = '.' Then
  2107.          Goto PERIOD_CHECK;
  2108.       End If;
  2109.       For J in 1..81 Loop
  2110.          If J = 81 Then
  2111.             Return;
  2112.          End If;
  2113.          If BUFFER(1) = '.'  or  BUFFER(1) = ' '  or
  2114.             BUFFER(1) = 'E'  or  BUFFER(1) = '+'  or
  2115.             BUFFER(1) = 'e'  or  BUFFER(1) = 'D'  or
  2116.             BUFFER(1) = 'd'  or  BUFFER(1) = '-'  or  
  2117.             BUFFER(1) = '*'  or  BUFFER(1) = ','  or  
  2118.             BUFFER(1) = '/'  or BUFFER(1) = '$' Then
  2119.             Exit;
  2120.          End If;
  2121.          M := M + 1;
  2122.          KTEMP(M) := BUFFER(1);
  2123.          SHIFT_LEFT(BUFFER);
  2124.       End Loop;
  2125.       ALPHA_TO_INTEGER(KTEMP,NUMERIC_VALUE);
  2126. --
  2127. --PROCESS REPETITION FACTOR.
  2128.       If BUFFER(1) = '*' Then
  2129.          NREP := INTEGER(NUMERIC_VALUE);
  2130.          SHIFT_LEFT(BUFFER);
  2131.          Goto THE_BEGINNING;
  2132.       End If;
  2133. --
  2134. --SKIP PAST ANY PERIOD.
  2135.       If BUFFER(1) /= '.' Then
  2136.          Goto ADD_SIGN;
  2137.       End If;
  2138. <<PERIOD_CHECK>>
  2139.       SHIFT_LEFT(BUFFER);
  2140.       If BUFFER(1) = ' ' Then
  2141.          Goto ADD_SIGN;
  2142.       End If;
  2143. --
  2144. --PICK UP DIGITS UNTIL THE NEXT SPECIAL CHARACTER.
  2145.       For J in KTEMP'RANGE Loop
  2146.          KTEMP(J) := ' ';
  2147.       End Loop;
  2148.       M := 0;
  2149.       For J in 1..81 Loop
  2150.          If J = 81 Then
  2151.             Return;
  2152.          End If;
  2153.          IFL22 := 0;
  2154.          If BUFFER(1) = ' '  or  BUFFER(1) = ','  or
  2155.             BUFFER(1) = '/'  or  BUFFER(1) = '$' Then
  2156.             Exit;
  2157.          End If;
  2158.          IFL22 := 1;
  2159.          If BUFFER(1) = '+' or BUFFER(1) = '-' or
  2160.             BUFFER(1) = 'E' or BUFFER(1) = 'e' or
  2161.             BUFFER(1) = 'D' or BUFFER(1) = 'd' Then
  2162.             Exit;
  2163.          End If;
  2164.          M := M + 1;
  2165.          KTEMP(M) := BUFFER(1);
  2166.          SHIFT_LEFT(BUFFER);
  2167.       End Loop;
  2168.       ALPHA_TO_INTEGER(KTEMP,VAL2);
  2169.       NUMERIC_VALUE := NUMERIC_VALUE + VAL2 / 10.0**M;
  2170. <<ADD_SIGN>>
  2171.       NUMERIC_VALUE := NUMERIC_VALUE * FLOAT(ISIGN);
  2172.       If IFL22 /= 1 and
  2173.          BUFFER(1) /= 'E' and BUFFER(1) /= '+' and
  2174.          BUFFER(1) /= 'e' and BUFFER(1) /= '-' and
  2175.          BUFFER(1) /= 'D' and BUFFER(1) /= 'd' Then
  2176.          Return;
  2177.       End If;
  2178.       If BUFFER(1) = 'E' or BUFFER(1) = 'e' or
  2179.          BUFFER(1) = 'D' or BUFFER(1) = 'd' Then
  2180.          SHIFT_LEFT(BUFFER);
  2181.       End If;
  2182.       ISIGN := 1;
  2183.       If BUFFER(1) = '-' Then
  2184.          ISIGN := -1;
  2185.       End If;
  2186.       IF (not DIGIT_CHECK(BUFFER(1))) Then
  2187.          SHIFT_LEFT(BUFFER);
  2188.       End If;
  2189.       ALPHA_TO_INTEGER(BUFFER,VAL2);
  2190.       If ISIGN = 1 Then
  2191.          NUMERIC_VALUE := NUMERIC_VALUE * (10.0**VAL2);
  2192.       Else
  2193.          NUMERIC_VALUE := NUMERIC_VALUE * (10.0**(-VAL2));
  2194.       End If;
  2195.       Return;
  2196. --
  2197.       End ALPHA_TO_NUMERIC;
  2198. --
  2199. --
  2200. Procedure ANTENNA_CHECK(IATYP: in integer;
  2201.                         NFREQ: in BAND_TYPES; 
  2202.                         GAIN: in out float;
  2203.                         HEIGHT: in out float;
  2204.                         ALNGTH: in out float;
  2205.                         TLTANG: in out float;
  2206.                         IERR: out integer) is
  2207. --
  2208. --PURPOSE: ANTENNA_CHECK verifies that the antenna type input is appropriate
  2209. --         to the frequency class.
  2210. --
  2211. --AUTHOR:  B. Perry and J. Conrad
  2212. --
  2213. --PARAMETER DESCRIPTIONS:
  2214. --IN       IATYPE =  antenna type
  2215. --         NFREQ  =  frequency class
  2216. --IO       GAIN   =  antenna gain
  2217. --         HEIGHT =  antenna height
  2218. --         TLTANG =  antenna tilt angle
  2219. --         INPUT_BUFFER, IARRAY, XARRAY  = tempory strings used for input
  2220. --                                         (Declared in EXECUTIVE Package)
  2221. --OUT      IERR = returns 0 if all O.K.
  2222. --                returns 1 IF A = was encountered
  2223. --                returns 2 if IATYP not valid
  2224. --
  2225. --CALLED BY:
  2226. --         RECEIVER_DATA
  2227. --         TRANSMITTER_DATA
  2228. --
  2229. --CALLS TO:
  2230. --         BLANK_CHECK
  2231. --         HELP_CHECK
  2232. --         PARSE
  2233. --
  2234. --TECHNICAL DESCRIPTION:
  2235. --         ANTENNA_CHECK first tests the input frequency class to insure 
  2236. --         that it is within the bounds between LF(4) and EHF(10).  
  2237. --         A branch is then taken based on the frequency class and the
  2238. --         appropriate antenna data for that frequency class is echoed
  2239. --         for acceptance/modification.
  2240. --
  2241.       Procedure ANTDATA (S: string; D: in out FLOAT) is
  2242.       begin
  2243.          loop
  2244.             New_line;
  2245.             Put("Antenna "); Put(S); Put(": "); Put(D); New_line;
  2246.             Get_line(INPUT_BUFFER, MAX);
  2247.             If INPUT_BUFFER(1) = '=' Then
  2248.                IERR := 1;
  2249.                Return;
  2250.             End If;
  2251.             If not HELP_CHECK(INPUT_BUFFER(1..MAX)) Then exit; end if;
  2252.             New_line;
  2253.             Put("Enter the antenna "); Put(S); Put(".");
  2254.          End loop;
  2255.          If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  2256.             Return;
  2257.          End If;
  2258.          NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  2259.          PARSE (INPUT_BUFFER(1..MAX));
  2260.          If NUMBER_OF_VARIABLES_TO_EXTRACT = 
  2261.                    NUMBER_OF_VARIABLES_EXTRACTED Then
  2262.             NEW_TITLE_CHECK;
  2263.             D:= XARRAY(1);
  2264.          End If;
  2265.       end ANTDATA;
  2266. --      
  2267.       Begin
  2268. --
  2269.       IERR := 0;
  2270.       Case NFREQ is
  2271. --
  2272.     --CHECK ANTENNA TYPE FOR LF.
  2273.          When LF =>
  2274.             New_line;
  2275.             If not (IATYP = 1 or IATYP = 2) Then
  2276.                Put("Expected antenna type 1 or 2, not ");
  2277.                Put(IATYP);
  2278.                IERR := 2;
  2279.             End If;
  2280.     --CHECK ANTENNA TYPE FOR MF,HF.
  2281.          When MF|HF => New_line;
  2282.             Case IATYP is
  2283.                When 5 =>
  2284.                   ANTDATA("gain in dB", GAIN);
  2285.                When 6 =>
  2286.                   ANTDATA("tilt angle in degrees",TLTANG);
  2287.                   If IERR=1 then return; end if;
  2288.                   ANTDATA("height in meters",HEIGHT);
  2289.                   If IERR=1 then return; end if;
  2290.                   ANTDATA("length in meters", ALNGTH);
  2291.                When 7 =>
  2292.                   ANTDATA("length in meters", ALNGTH);
  2293.                When 8 =>
  2294.                   ANTDATA("height in meters",HEIGHT);
  2295.                When others =>
  2296.                   Put("Expected antenna type 5, 6, 7 or 8, not ");
  2297.                   Put(IATYP);
  2298.                   IERR := 2;
  2299.             End Case;
  2300.     --CHECK ANTENNA TYPE FOR VHF,UHF,SHF,EHF.
  2301.          When VHF..EHF => New_line;
  2302.             If not (IATYP = 3 or IATYP = 4) Then
  2303.                Put("Expected antenna type 3 or 4, not ");
  2304.                Put(IATYP);
  2305.                IERR := 2;
  2306.             End If;
  2307.          When Others => Null;
  2308.       End Case; 
  2309. --
  2310.       End ANTENNA_CHECK;
  2311. --
  2312. --
  2313. Function DIGIT_CHECK(MCHAR: character) return boolean is
  2314. --
  2315. --PURPOSE: DIGIT_CHECK determines if the input character is a numerical
  2316. --         digit (i.e. 0 - 9).
  2317. --
  2318. --AUTHOR:  J. Conrad
  2319. --
  2320. --TYPE:    Digit Test
  2321. --
  2322. --PARAMETER DESCRIPTIONS:
  2323. --IN       MCHAR        = The input character to be tested 
  2324. --OUT      DIGIT_CHECK  = True if the input character is a digit,
  2325. --                        otherwise it will be false.
  2326. --
  2327. --CALLED BY:
  2328. --           ALPHA_TO_NUMERIC
  2329. --
  2330. --CALLS TO:
  2331. --         'NONE'
  2332. --
  2333. --TECHNICAL DESCRIPTION:
  2334. --         DIGIT_CHECK determines if the input character is a numerical
  2335. --         digit (i.e. 0 - 9).  If it is, DIGIT_CHECK will be true.
  2336. --         If the character is blank or alphabetic or a special
  2337. --         character, the value of DIGIT_CHECK will be false.
  2338. --         A simple Loop and comparison with all possible digits
  2339. --         is employed.
  2340. --
  2341.       I: integer;
  2342. --
  2343.       Begin
  2344. --
  2345.       For I in 28..37 Loop
  2346.          If MCHAR = CHAR_UPPER(I) Then
  2347.             Return TRUE;
  2348.          End If;
  2349.       End Loop;
  2350. --
  2351.       Return FALSE;
  2352. --
  2353.       End DIGIT_CHECK;
  2354. --
  2355. --
  2356. Procedure INTEGER_TO_ALPHA(INTEGERIZED_ALPHA: in long_integer;
  2357.                            BUFFER: out string) is
  2358. --
  2359. --PURPOSE: INTEGER_TO_ALPHA converts alphanumeric data from an internal
  2360. --         integer format to a six character alphanumeric string format.
  2361. --
  2362. --AUTHOR:  J. Conrad
  2363. --
  2364. --TYPE:    Conversion Module
  2365. --
  2366. --PARAMETER DESCRIPTIONS:
  2367. --IN       INTERGERIZED_ALPHA = The internal integer representation of
  2368. --                              alphanumeric data
  2369. --OUT      BUFFER             = The six character string containing the
  2370. --                              converted alphanumeric data
  2371. --
  2372. --CALLED BY:
  2373. --         ENTITY_DATA
  2374. --         NODE_DATA    
  2375. --         NODE_DISPLAY
  2376. --         NODE_FIND
  2377. --         NODE_HANDLER
  2378. --         RECEIVER_ADD
  2379. --         RECEIVER_DISPLAY
  2380. --         RECEIVER_FETCH
  2381. --         RECEIVER_HANDLER
  2382. --         RECEIVER_REMOVE
  2383. --         TRANSMITTER_ADD
  2384. --         TRANSMITTER_DISPLAY
  2385. --         TRANSMITTER_FETCH
  2386. --         TRANSMITTER_HANDLER
  2387. --         TRANSMITTER_REMOVE
  2388. --
  2389. --CALLS TO:
  2390. --         'NONE'
  2391. --
  2392. --TECHNICAL DESCRIPTION:
  2393. --         Alphanumeric data that has been converted by Procedure
  2394. --         ALPHA_TO_INTEGERIZED_ALPHA to an integer value between 71270178 and
  2395. --         1943557016 is converted back to alphanumeric string format.
  2396. --         If input is zero, a string of blanks is returned.
  2397. --
  2398. --
  2399.       ITEST: array (integer range 1..5) of long_integer;
  2400.       INPUT: long_integer;
  2401.       I,II: integer;
  2402. --
  2403.       Begin
  2404. --
  2405.       ITEST(1):=1926221;
  2406.       ITEST(2):=52060;
  2407.       ITEST(3):=1407;
  2408.       ITEST(4):=38;
  2409.       ITEST(5):=1;
  2410.       INPUT := INTEGERIZED_ALPHA;
  2411.       IF INPUT = 0 Then
  2412.          For I in BUFFER'RANGE Loop
  2413.             BUFFER(I) := CHAR_UPPER(1);
  2414.          End Loop;
  2415.          Return;
  2416.       End If;
  2417.       For I in 1..5 Loop
  2418.          II := integer(INPUT / (long_integer(37)**(6-I)));
  2419.          BUFFER(I) := CHAR_UPPER(II);
  2420.          INPUT := INPUT - (long_integer(II)*(long_integer(37)**(6-I)));
  2421.          If INPUT < ITEST(I) Then
  2422.             II := II - 1;
  2423.             BUFFER(I) := CHAR_UPPER(II);
  2424.             INPUT := INPUT + long_integer(37)**(6-I);
  2425.          End If;
  2426.       End Loop;
  2427.       BUFFER(6) := CHAR_UPPER(integer(INPUT));
  2428.       Return;
  2429. --
  2430.       End INTEGER_TO_ALPHA;
  2431. --
  2432. --
  2433. Procedure NEW_TITLE_CHECK is
  2434. --
  2435. --PURPOSE: NEW_TITLE_CHECK gets a new case title.
  2436. --
  2437. --AUTHOR:  J. Conrad
  2438. --
  2439. --TYPE:    Input
  2440. --
  2441. --PARAMETER DESCRIPTIONS:
  2442. --IO       DATABASE_HAS_BEEN_MODIFIED is assumed to be visible from EXECUTIVE
  2443. --IO       TITLE is assumed to be visible from EXECUTIVE
  2444. --IO       INPUT_BUFFER is assumed to be visible from EXECUTIVE
  2445. --
  2446. --CALLED BY:
  2447. --         ANTENNA_CHECK
  2448. --         ENTITY_DATA
  2449. --         LOCATION_DATA
  2450. --         NODE_ADD
  2451. --         NODE_REMOVE
  2452. --         RECEIVER_ADD
  2453. --         RECEIVER_DATA
  2454. --         RECEIVER_REMOVE
  2455. --         TRANSMITTER_ADD
  2456. --         TRANSMITTER_DATA
  2457. --         TRANSMITTER_REMOVE     
  2458. --
  2459. --CALLS TO:
  2460. --         'NONE'
  2461. --
  2462. --TECHNICAL DESCRIPTION:
  2463. --         NEW_TITLE_CHECK gets a new case title.
  2464. -- 
  2465.       Begin
  2466. --
  2467.       If DATABASE_HAS_BEEN_MODIFIED = TRUE Then
  2468.          Return;
  2469.       End If;
  2470.       New_line;
  2471.       Put("Old case name was:");
  2472.       New_line;
  2473.       Put(TITLE);
  2474.       New_line;
  2475.       Put("Enter new case name or empty <CR> to keep old name:");
  2476.       New_line;
  2477.       For I in 1..80 loop
  2478.          INPUT_BUFFER(I):=' ';
  2479.       end loop;
  2480.       Get_Line(INPUT_BUFFER, MAX);
  2481.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) = FALSE Then
  2482.          TITLE := INPUT_BUFFER;
  2483.       End If;
  2484.       DATABASE_HAS_BEEN_MODIFIED := TRUE;
  2485.       Return;
  2486. --
  2487.       End NEW_TITLE_CHECK;
  2488. --
  2489. --
  2490. Procedure PARSE(BUFFER: in out string) is
  2491. --
  2492. --PURPOSE: PARSE changes the specified number of alphnumeric
  2493. --         elements in the input buffer to the corresponding
  2494. --         numeric values.
  2495. --
  2496. --AUTHOR:  J. Conrad
  2497. --
  2498. --TYPE:    Conversion
  2499. --
  2500. --PARAMETER DESCRIPTIONS:
  2501. --IN        BUFFER = The input buffer containing alphnumeric information
  2502. --
  2503. --   Note that all of the following parameters are assumed globally visible.
  2504. --
  2505. --IN        NUMBER_OF_VARIABLES_TO_EXTRACT
  2506. --OUT       NUMBER_OF_VARIABLES_EXTRACTED
  2507. --OUT       XARRAY = The array into which the converted values are placed
  2508. --
  2509. --CALLED BY:
  2510. --         ANTENNA_CHECK
  2511. --         ENTITY_DATA
  2512. --         LOCATION_DATA
  2513. --         NODE_FETCH
  2514. --         NODE_HANDLER
  2515. --         RECEIVER_DATA
  2516. --         RECEIVER_FETCH
  2517. --         RECEIVER_HANDLER
  2518. --         TRANSMITTER_ADD
  2519. --         TRANSMITTER_DATA
  2520. --         TRANSMITTER_FETCH
  2521. --         TRANSMITTER_HANDLER
  2522. --
  2523. --CALLS TO:
  2524. --         ALPHA_TO_INTEGERIZED_ALPHA
  2525. --         ALPHA_TO_NUMERIC
  2526. --         BLANK_CHECK 
  2527. --         SHIFT_LEFT
  2528. --
  2529. --TECHNICAL DESCRIPTION:
  2530. --         PARSE changes the specified number of alphabetic
  2531. --         elements in the input buffer to the corresponding
  2532. --         numeric values.  Valid delimeters between elements
  2533. --         are spaces, commas, $, or slashes.
  2534. --
  2535.       I: integer;
  2536.       MN: integer;
  2537.       MAXFND: integer;
  2538.       BUFFER2: string(1..80);
  2539.       NREP: integer;
  2540. --
  2541.       Begin
  2542. --
  2543. --INITIALIZE.
  2544.       NUMBER_OF_VARIABLES_EXTRACTED := 0;
  2545.       MAXFND := ABS(NUMBER_OF_VARIABLES_TO_EXTRACT);
  2546.       For I in 1..MAXFND Loop
  2547.          XARRAY(I) := 0.0;
  2548.          IARRAY(I) := 71270178;
  2549.       End Loop;
  2550. --
  2551.       Loop
  2552. --
  2553. --SKIP OVER BLANKS.
  2554.          If BLANK_CHECK (BUFFER) Then
  2555.             Return;
  2556.          End If;
  2557.          For I in 1..81 Loop
  2558.             If I = 81 Then
  2559.                Return;
  2560.             End If;
  2561.             If BUFFER (1) /= ' ' and BUFFER (1) /= ',' and
  2562.                BUFFER (1) /= '$' and BUFFER (1) /= '/' Then
  2563.                Exit;
  2564.             End If;
  2565.             SHIFT_LEFT (BUFFER);
  2566.          End Loop;
  2567. --
  2568.          MN := 0;
  2569.          For I in BUFFER2'RANGE Loop
  2570.              BUFFER2(I) := ' ';
  2571.          End Loop;
  2572. --
  2573. --LOAD AND SHIFT BUFFER2.
  2574.          For I in BUFFER'RANGE Loop
  2575.             If BUFFER (1) = ' ' or BUFFER (1) = ',' or
  2576.                BUFFER (1) = '$' or BUFFER (1) = '/' Then
  2577.                Exit;
  2578.             End If;
  2579.             MN := MN + 1;
  2580.             BUFFER2(MN) := BUFFER(1);
  2581.             SHIFT_LEFT (BUFFER);
  2582.          End Loop;
  2583. --
  2584. --TEST FOR ALPHA OR NUMERIC TYPE OF DATA.
  2585.          NUMBER_OF_VARIABLES_EXTRACTED := NUMBER_OF_VARIABLES_EXTRACTED + 1;
  2586.          If BUFFER2(1) in 'A'..'Z' or BUFFER2(1) in 'a'..'z' Then
  2587.   --CONVERT ALPHA DATA.
  2588.             ALPHA_TO_INTEGERIZED_ALPHA(BUFFER2, 
  2589.                                        IARRAY(NUMBER_OF_VARIABLES_EXTRACTED));
  2590.          Else  --CONVERT NUMERIC DATA.
  2591.             ALPHA_TO_NUMERIC(BUFFER2, NREP, 
  2592.                              XARRAY(NUMBER_OF_VARIABLES_EXTRACTED));
  2593.             If NREP > 1 Then
  2594.                For I in 2..NREP Loop
  2595.                   NUMBER_OF_VARIABLES_EXTRACTED := 
  2596.                      NUMBER_OF_VARIABLES_EXTRACTED + 1;
  2597.                   XARRAY(NUMBER_OF_VARIABLES_EXTRACTED) := 
  2598.                      XARRAY(NUMBER_OF_VARIABLES_EXTRACTED - 1);
  2599.                End Loop;
  2600.             End If;
  2601.          End If;
  2602. --
  2603.          If NUMBER_OF_VARIABLES_EXTRACTED >= MAXFND Then
  2604.             Return;
  2605.          End If;
  2606. --
  2607.       End Loop;
  2608. --
  2609.       End PARSE;
  2610. --
  2611. --
  2612. End ENTITYUTI;
  2613.  
  2614. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2615. --PROPCNSTS
  2616. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2617. With Types;
  2618. Package PROPAGATION_CONSTANTS is
  2619. --
  2620. -- PROPAGATION_CONSTANTS Package of PROP_LINK Version 1.0
  2621. --
  2622. -- This Package declares many variables and constants used in 
  2623. -- the propagation packages package.
  2624. --
  2625. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  2626. -- radio frequency propagation prediction code.
  2627. --
  2628. -- PROP_LINK has been developed for the Department of Defense under
  2629. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  2630. -- Systems Inc. (Jim Conrad).
  2631. --
  2632. --TYPES:
  2633.       Type DAY_OR_NIGHT is (DAY, NIGHT);
  2634.  
  2635. --VARIABLES:
  2636.       IDNT, IDNR: DAY_OR_NIGHT;
  2637.       BRNG1, BRNG2, DPATH: float;
  2638.       DISDAY, DISNIT, TERLAT, TERLON, DISTOT, TRBRNG, RTBRNG: float;
  2639.       TERP, FREQ, GNX, HTX, LNX, TAX, BW, GOT, RLL, GNR, HTR, LNR, TAR: float;
  2640.       TLAT, TLON, TALT, RLAT, RLON, RALT: float;
  2641.       TIMSEC, FREQKC, FREQMC: float;
  2642.       IATYPT, IATYPR: integer;
  2643.       NLTYP: TYPES.BAND_TYPES;
  2644.       SIGNAL, SIGNOS: float;
  2645.  
  2646. --RF PROPAGATION SPECIFIC CONSTANTS:
  2647. --
  2648.       --DATA TO SET COEFFICIENTS FOR PROCEDURE GRWAVE:
  2649. --
  2650.       G: array (integer range 1..48) of float
  2651.       :=(-0.99877100, -0.99353017, -0.98412458, -0.97059159, -0.95298770,
  2652.          -0.93138669, -0.90587913, -0.87657202, -0.84358826, -0.80706620,
  2653.          -0.76715903, -0.72403413, -0.67787237, -0.62886739, -0.57722472,
  2654.          -0.52316097, -0.46690290, -0.40868648, -0.34875588, -0.28736248,
  2655.          -0.22476379, -0.16122235, -0.09700469, -0.03238017,  0.03238017,
  2656.           0.09700469,  0.16122235,  0.22476379,  0.28736248,  0.34875588,
  2657.           0.40868648,  0.46690290,  0.52316097,  0.57722472,  0.62886739,
  2658.           0.67787237,  0.72403413,  0.76715903,  0.80706620,  0.84358826,
  2659.           0.87657202,  0.90587913,  0.93138669,  0.95298770,  0.97059159,
  2660.           0.98412458,  0.99353017,  0.99877100);
  2661.       W: array (integer range 1..48) of float
  2662.       :=( 0.00315334,  0.00732755,  0.01147723,  0.01557931,  0.01961616,
  2663.           0.02357076,  0.02742650,  0.03116722,  0.03477722,  0.03824135,
  2664.           0.04154508,  0.04467456,  0.04761665,  0.05035903,  0.05289018,
  2665.           0.05519950,  0.05727729,  0.05911483,  0.06070443,  0.06203942,
  2666.           0.06311419,  0.06392423,  0.06446616,  0.06473769,  0.06473769,
  2667.           0.06446616,  0.06392423,  0.06311419,  0.06203942,  0.06070443,
  2668.           0.05911483,  0.05727729,  0.05519950,  0.05289018,  0.05035903,
  2669.           0.04761665,  0.04467456,  0.04154508,  0.03824135,  0.03477722,
  2670.           0.03116722,  0.02742650,  0.02357076,  0.01961616,  0.01557931,
  2671.           0.01147723,  0.00732755,  0.00315334);
  2672. --
  2673.       --THIS SETS THE IONOSPHERIC HEIGHTS FOR REFLECTION CALCULATIONS:
  2674.       HP: array (integer range 1..20) of float
  2675.       :=(5.0,  10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0,
  2676.          55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 85.0, 90.0, 95.0, 100.0);
  2677.       PTS: array (integer range 1..5) of float
  2678.       :=(0.5, 0.125, 0.3, 0.7, 0.875);
  2679.       NHOP: integer :=5;
  2680. --
  2681.       --THESE VARIABLES APPEAR IN SEVERAL OF THE RF PROCEDURES:
  2682. --
  2683.       NYEAR: integer := 1977;
  2684.       NDAY: integer := 1;
  2685.       NSEC: integer := 0;
  2686.       T90: float := 183.0;
  2687.       T0: float := 300.0;
  2688.       ISD: integer := 0;
  2689. --
  2690.       --THESE VARIABLES ARE USED IN MF/HF PROPAGATION:
  2691.            --THE 1ST COLUMN OF IHFMD IS THE  #E HOPS.
  2692.            --THE 2ND COLUMN OF IHMFD IS THE  #F HOPS.
  2693. --
  2694.       IHFMD: array (integer range 1..20, integer range 1..9) of integer
  2695.       :=((1,0,0,0,0,0,0,0,0), (2,0,0,0,0,0,0,0,0),
  2696.          (3,0,0,0,0,0,0,0,0), (4,0,0,0,0,0,0,0,0),
  2697.          (5,0,0,0,0,0,0,0,0), (0,1,0,0,0,0,0,0,0),
  2698.          (0,2,0,0,0,0,0,0,0), (0,3,0,0,0,0,0,0,0),
  2699.          (0,4,0,0,0,0,0,0,0), (0,5,0,0,0,0,0,0,0),
  2700.          (1,1,0,0,0,0,0,0,0), (2,1,0,0,0,0,0,0,0),
  2701.          (3,1,0,0,0,0,0,0,0), (4,1,0,0,0,0,0,0,0),
  2702.          (1,2,0,0,0,0,0,0,0), (2,2,0,0,0,0,0,0,0),
  2703.          (3,2,0,0,0,0,0,0,0), (1,3,0,0,0,0,0,0,0),
  2704.          (2,3,0,0,0,0,0,0,0), (1,4,0,0,0,0,0,0,0));
  2705. --
  2706.           -- IJTMD DETERMINES THE MODE NUMBER FROM I+1, J+1.
  2707.           -- E.G. FOR 1E/0F, LOCATION 2,1 SAYS THE MODE NUMBER
  2708.           -- IS 1.  FOR 2E/3F, LOCATION 3,4 SAYS THE MODE
  2709.           -- NUMBER IS 19.
  2710. --
  2711.       IJTMD: array (integer range 1..6, integer range 1..6) of integer
  2712.       :=((0,  6,  7,  8,  9, 10),
  2713.          (1, 11, 15, 18, 20,  0),
  2714.          (2, 12, 16, 19,  0,  0),
  2715.          (3, 13, 17,  0,  0,  0),
  2716.          (4, 14,  0,  0,  0,  0),
  2717.          (5, 0,  0,  0,  0,  0));
  2718. --
  2719. --
  2720. end PROPAGATION_CONSTANTS;
  2721. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2722. --COMPLEX
  2723. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  2724. with MATHLIB; use MATHLIB, NUMERIC_PRIMITIVES, TRIG_FUNCTIONS, CORE_FUNCTIONS;
  2725. package COMPLEX_NUMBERS is
  2726.  
  2727.    type COMPLEX is private;
  2728.    function "+"(X,Y: COMPLEX) return COMPLEX;
  2729.    function "+"(X: float; Y: COMPLEX) return COMPLEX;
  2730.    function "+"(X: COMPLEX; Y: float) return COMPLEX;
  2731.    function "-"(X,Y: COMPLEX) return COMPLEX;
  2732.    function "-"(X: float; Y: COMPLEX) return COMPLEX;
  2733.    function "-"(X: COMPLEX; Y: float) return COMPLEX;
  2734.    function "-"(X: COMPLEX) return COMPLEX;
  2735.    function "*"(X,Y: COMPLEX) return COMPLEX;
  2736.    function "*"(X: float; Y: COMPLEX) return COMPLEX;
  2737.    function "*"(X: COMPLEX; Y: float) return COMPLEX;
  2738.    function "/"(X,Y: COMPLEX) return COMPLEX;
  2739.    function "/"(X: float; Y: COMPLEX) return COMPLEX;
  2740.    function "/"(X: COMPLEX; Y: Float) return COMPLEX;
  2741.    function CMPLX(X: Float; Y: Float) return COMPLEX;
  2742.    function AREAL(C: COMPLEX) return FLOAT;
  2743.    function AIMAG(C: COMPLEX) return FLOAT;
  2744.    function CEXP (C: COMPLEX) return COMPLEX;
  2745.    function CLOG (C: COMPLEX) return COMPLEX;
  2746.    function CSQRT(C: COMPLEX) return COMPLEX;
  2747.    function CABS (C: COMPLEX) return float;
  2748.    function "**" (C: COMPLEX; N: integer) return COMPLEX;
  2749.    function "**" (C: COMPLEX; W: float) return COMPLEX;
  2750.    function CONJG(C: COMPLEX) return COMPLEX;
  2751. private
  2752.    type COMPLEX is
  2753.       record
  2754.          RL, IM: float:=0.0;
  2755.       end record;
  2756.    I: constant COMPLEX:= (0.0,1.0);
  2757.    R, THETA: float;
  2758.    procedure CONVERT (X,Y: in float; R,THETA: out float);
  2759. end COMPLEX_NUMBERS;
  2760.  
  2761. package body COMPLEX_NUMBERS is
  2762. --
  2763. -- COMPLEX_NUMBERS package of PROPLINK Version 1.0, September 19, 1985.
  2764. --
  2765. -- This COMPLEX_NUMBERS package contains many complex number functions,
  2766. -- the operators for complex numbers as well as facilities
  2767. -- for creating and separating complex numbers.  A private type
  2768. -- is used to control access to the real and imaginary components of the
  2769. -- numbers outside the package.  CEXP, CSQRT, CABS, "**", and CLOG
  2770. -- were based on "Collected Algorithms of the CACM" (algorithms 46, 312, 
  2771. -- 312, 106, and 243 respectively) and tested against
  2772. -- their FORTRAN 77 counterparts.  
  2773. --
  2774. -- The package was written by Bruce Perry of IWG Corp., 
  2775. -- 975 Hornblend St., Suite C, San Diego, CA 92126.
  2776. -- Proplink has been developed for the Department
  2777. -- of Defense under contract N66001-85-C-0042 by IWG Corp.
  2778. --
  2779. -- 
  2780.    function "+"(X,Y: COMPLEX) return COMPLEX is
  2781.    begin
  2782.       return (X.RL+Y.RL, X.IM+Y.IM);
  2783.    end "+";
  2784.  
  2785.    function "+"(X: float; Y: COMPLEX) return COMPLEX is
  2786.    begin
  2787.       return (X+Y.RL, Y.IM);
  2788.    end "+";
  2789.  
  2790.    function "+"(X: COMPLEX; Y: float) return COMPLEX is
  2791.    begin
  2792.       return (X.RL+Y, X.IM);
  2793.    end "+";
  2794.  
  2795.    function "-"(X,Y: COMPLEX) return COMPLEX is
  2796.    begin
  2797.       return (X.RL-Y.RL,X.IM-Y.IM);
  2798.    end "-";
  2799.   
  2800.    function "-"(X: float; Y: COMPLEX) return COMPLEX is
  2801.    begin
  2802.       return (X-Y.RL,-Y.IM);
  2803.    end "-";
  2804.   
  2805.    function "-"(X: COMPLEX; Y:float) return COMPLEX is
  2806.    begin
  2807.       return (X.RL-Y,X.IM);
  2808.    end "-";
  2809.   
  2810.    function "-"(X: COMPLEX) return COMPLEX is
  2811.    begin
  2812.       return (-X.RL,-X.IM);
  2813.    end "-";
  2814.   
  2815.    function "*"(X,Y: COMPLEX) return COMPLEX is
  2816.    begin
  2817.       return (X.RL*Y.RL-X.IM*Y.IM,X.RL*Y.IM+X.IM*Y.RL);
  2818.    end "*";
  2819.  
  2820.    function "*"(X: float; Y:COMPLEX) return COMPLEX is
  2821.    begin
  2822.       return (X*Y.RL,X*Y.IM);
  2823.    end "*";
  2824.  
  2825.    function "*"(X: COMPLEX; Y:float) return COMPLEX is
  2826.    begin
  2827.       return (X.RL*Y,X.IM*Y);
  2828.    end "*";
  2829.  
  2830.    function "/"(X,Y: COMPLEX) return COMPLEX is
  2831.       D:float:=Y.RL**2+Y.IM**2;
  2832.       trl, tim: float;
  2833.    begin
  2834.       trl:=(X.RL*Y.RL+X.IM*Y.IM)/D;
  2835.       tim:=(X.IM*Y.RL-X.RL*Y.IM)/D;
  2836.       return (trl,tim);
  2837.    end "/";
  2838.  
  2839.    function "/"(X: float; Y:COMPLEX) return COMPLEX is
  2840.       D:float:=Y.RL**2+Y.IM**2;
  2841.       trl, tim: float;
  2842.    begin
  2843.       trl:=(X*Y.RL)/D;
  2844.       tim:=(-X*Y.IM)/D;
  2845.       return (trl,tim);
  2846.    end "/";
  2847.  
  2848.    function "/"(X:COMPLEX; Y:float) return COMPLEX is
  2849.    begin
  2850.       return (X.RL/Y, X.IM/Y);
  2851.    end "/";
  2852.  
  2853.    function CMPLX(X,Y: Float) return COMPLEX is
  2854.    begin
  2855.       return (X,Y);
  2856.    end CMPLX;
  2857.  
  2858.    function AREAL(C: COMPLEX) return FLOAT is
  2859.    begin
  2860.       return (C.RL);
  2861.    end AREAL;
  2862.  
  2863.    function AIMAG(C:COMPLEX) return FLOAT is
  2864.    begin
  2865.       return (C.IM);
  2866.    end AIMAG;
  2867.  
  2868.    function CEXP(C:COMPLEX) return COMPLEX is
  2869.       R: float;
  2870.    begin
  2871.       R := exp(C.RL);
  2872.       return (R*cos(C.IM),R*sin(C.IM));
  2873.    end CEXP;
  2874.  
  2875.    procedure CONVERT (X,Y: in float; R,THETA: out float) is
  2876.    begin
  2877.       THETA:=ATAN(Y/X);
  2878.       R:=SQRT(X**2+Y**2);
  2879.    end CONVERT;
  2880.  
  2881.    function CLOG(C:COMPLEX) return COMPLEX is
  2882.       E, F, G, H, S: float;
  2883.    begin
  2884.       E := 0.5*C.RL; 
  2885.       F := 0.5*C.IM;
  2886.       if ABS(E)<0.5 and ABS(F)<0.5 then
  2887.          G := ABS(2.0*C.RL)+ABS(2.0*C.IM);
  2888.          H := 8.0*(C.RL/G)*C.RL+8.0*(C.IM/G)*C.IM; 
  2889.          G := 0.5*(LOG(G)+LOG(H))-1.03972077084;
  2890.       else
  2891.          G := ABS(0.5*E)+ABS(0.5*F);
  2892.          H := 0.5*(E/G)*E+0.5*(F/G)*F; 
  2893.          G := 0.5*(LOG(G)+LOG(H))+1.03972077084;
  2894.       end if;
  2895.       if C.RL /= 0.0 and ABS(e)>=ABS(F) then
  2896.          if C.RL >= 0.0 then
  2897.             S := 0.0;
  2898.          elsif C.IM >= 0.0 then
  2899.             S := 3.14159265359;
  2900.          else
  2901.             S := -3.14159265359;
  2902.          end if;
  2903.          H := ATAN(C.IM/C.RL)+S;
  2904.       else
  2905.          H := -ATAN(C.RL/C.IM)+1.57079632679*SIGN(1.0,C.IM);
  2906.       end if;
  2907.       return (G, H);
  2908.    end CLOG;
  2909.  
  2910.    function CSQRT(C: COMPLEX) return COMPLEX is
  2911.      A, B, X, Y: float;
  2912.    begin   
  2913.       X := C.RL; Y := C.IM;
  2914.       if X=0.0 and Y=0.0 then
  2915.          A := 0.0 ; B := 0.0;
  2916.       else
  2917.          A := SQRT ((ABS(X)+CABS(C))*0.5);
  2918.          if X>=0.0 then
  2919.             B := Y/(A+A);
  2920.          else
  2921.             if Y<0.0 then
  2922.                B := -A;
  2923.             else
  2924.                B := A;
  2925.             end if;
  2926.             A := Y/(B+B);
  2927.          end if;
  2928.       end if;
  2929.       return (A,B);
  2930.    end CSQRT;
  2931.  
  2932.    function CABS(C:COMPLEX) return float is
  2933.       X, Y, R: float;
  2934.    begin
  2935.       X := ABS(C.RL); Y := ABS(C.IM);
  2936.       if X = 0.0 then
  2937.          R := Y;
  2938.       elsif Y = 0.0 then
  2939.          R := X;
  2940.       else
  2941.          if X > Y then
  2942.             R := X*SQRT(1.0+(Y/X)**2);
  2943.          else
  2944.             R := Y*SQRT(1.0+(X/Y)**2);
  2945.          end if;
  2946.       end if;
  2947.       return R;
  2948.    end;
  2949.  
  2950.    function "**" (C: COMPLEX; N: integer) return COMPLEX is
  2951.       X, Y, W, A, B, PHI, THETA: float;
  2952.    begin
  2953.       X := C.RL; Y := C.IM; W := float(N);
  2954.       A := 0.0; B := 0.0;
  2955.       if not (X=0.0 and Y=0.0) then
  2956.          if X>0.0 then
  2957.             PHI := ATAN(Y/X);
  2958.          elsif X<0.0 then
  2959.             if Y>=0.0 then
  2960.                THETA := 3.1415927;
  2961.             else
  2962.                THETA := -3.1415927;
  2963.             end if;
  2964.             PHI := ATAN(Y/X)+THETA;
  2965.          else
  2966.             if Y>0.0 then
  2967.                PHI := 1.5707963;
  2968.             else
  2969.                PHI := -1.5707963;
  2970.             end if;
  2971.          end if;
  2972.          R := SQRT(X*X+Y*Y);
  2973.          R := EXP(W*LOG(R));
  2974.          A := R * COS(W*PHI);
  2975.          B := R * SIN(W*PHI);
  2976.       end if;
  2977.       return (A,B);
  2978.    end "**"; 
  2979.  
  2980.    function "**" (C: COMPLEX; W: float) return COMPLEX is
  2981.       X, Y, A, B, PHI, THETA: float;
  2982.    begin
  2983.       X := C.RL; Y := C.IM; 
  2984.       A := 0.0; B := 0.0;
  2985.       if not (X=0.0 and Y=0.0) then
  2986.          if X>0.0 then
  2987.             PHI := ATAN(Y/X);
  2988.          elsif X<0.0 then
  2989.             if Y>=0.0 then
  2990.                THETA := 3.1415927;
  2991.             else
  2992.                THETA := -3.1415927;
  2993.             end if;
  2994.             PHI := ATAN(Y/X)+THETA;
  2995.          else
  2996.             if Y>0.0 then
  2997.                PHI := 1.5707963;
  2998.             else
  2999.                PHI := -1.5707963;
  3000.             end if;
  3001.          end if;
  3002.          R := SQRT(X*X+Y*Y);
  3003.          R := EXP(W*LOG(R));
  3004.          A := R * COS(W*PHI);
  3005.          B := R * SIN(W*PHI);
  3006.       end if;
  3007.       return (A,B);
  3008.    end "**"; 
  3009.  
  3010.    function CONJG(C: COMPLEX) return COMPLEX is
  3011.    begin
  3012.    return (C.RL,-C.IM);
  3013.    end CONJG;
  3014.  
  3015. end COMPLEX_NUMBERS;
  3016.  
  3017. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3018. --NODELOC
  3019. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3020. With Types; use Types;
  3021. With Constants; use Constants;
  3022. With Constant2; use Constant2;
  3023. With Constant3; use Constant3;
  3024. With Mathlib; use Mathlib, numeric_primitives, 
  3025.                            core_functions, trig_functions;
  3026. Package NODELOC is
  3027. --
  3028. --
  3029.       Procedure LOCEAN (TSP: in Float;
  3030.                         RATIO: in Float;
  3031.                         ECCEN: in Float;
  3032.                         IERR: out integer;
  3033.                         EANOM: out float);
  3034.       Procedure LOCGRB (XLA1: in float;
  3035.                         XLO1: in float;
  3036.                         XLA2: in float;
  3037.                         XLO2: in float;
  3038.                         BRNG1: out float;
  3039.                         BRNG2: out float;
  3040.                         DISTANCE: out float);
  3041.       Procedure LOCNEW (STALA: in float;
  3042.                         STALO: in float;
  3043.                         BRNGD: in float;
  3044.                         DR: in float;
  3045.                         XLA: out float;
  3046.                         XLO: out float);
  3047.       Procedure LOCSAT (EPH: in F_ARRAY;
  3048.                         SATLAT: out float;
  3049.                         SATLON: out float;
  3050.                         SATALT: out float);
  3051.       Procedure LOCTAN (ECCEN: in float; 
  3052.                         EANOM: in float;
  3053.                         TANOM: out float);
  3054.       Procedure LOCUPD (NUM: in integer; 
  3055.                         YLAT: out float;
  3056.                         YLON: out float;
  3057.                         YALT: out float);
  3058. --
  3059. --
  3060. End NODELOC;
  3061. --
  3062. Package body NODELOC is
  3063. --
  3064. -- NODELOC Package of PROP_LINK Version 1.0,  February 18, 1985.
  3065. --
  3066. -- This NODELOC Package contains all of the procedures that
  3067. -- are used to compute node locations.
  3068. --
  3069. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  3070. -- radio frequency propagation prediction code.
  3071. --
  3072. -- PROP_LINK has been developed for the Department of Defense under
  3073. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  3074. -- Systems Inc. (Jim Conrad).
  3075. --
  3076. --
  3077. --
  3078.       Procedure LOCEAN (TSP: in float;
  3079.                         RATIO: in float;
  3080.                         ECCEN: in float;
  3081.                         IERR: out integer;
  3082.                         EANOM: out float) is
  3083. --
  3084. --#PURPOSE: LOCEAN calculates the eccentric anomaly of an orbit and
  3085. --          determines whether of not it converges.
  3086. --
  3087. --#AUTHOR:  J. Conrad
  3088. --
  3089. --#TYPE:    Orbit Calculation.
  3090. --
  3091. --#PARAMETER DESCRIPTIONS:
  3092. --IN        TSP    = time since perigee (mins).
  3093. --IN        RATIO  = period of orbit (mins) divided by 2*PI.
  3094. --IN        ECCEN  = eccentricity of orbit ellipse.
  3095. --OUT       IERR   = index for convergence of eccentric anomaly
  3096. --                    = 0, converges,
  3097. --                    = 1, does not converge.
  3098. --          EANOM  = eccentric anomaly (radians).
  3099. --
  3100. --#CALLED BY:
  3101. --          LOCSAT
  3102. --
  3103. --#CALLS TO:
  3104. --          'NONE'
  3105. --
  3106. --#TECHNICAL DESCRIPTION:
  3107. --          This routine first computes the ratio, in modulo two PI,
  3108. --          of the time since perigee (TSP) to the period of orbit
  3109. --          (divided by two PI).  If this ratio is 0 or two PI, then
  3110. --          the eccentricity anomaly converges and EANOM is returned as
  3111. --          the ratio in modulo two PI.  Otherwise, a convergence test
  3112. --          is set up.
  3113. --
  3114.       DELTAE: float;
  3115.       AANOM: float;
  3116.       I: integer;
  3117. --
  3118.       Begin
  3119. --
  3120. --COMPUTE MEAN ANOMALY.
  3121.       IERR := 0;
  3122.       AANOM := TSP/RATIO;
  3123.       AANOM := AMOD (AANOM, TWOPI);
  3124. --
  3125. --ITERATE TO COMPUTE TRUE ANOMALY.
  3126.       EANOM := AANOM;
  3127.       If SIN(EANOM) = 0.0 Then
  3128.          Return;
  3129.       End If;
  3130.       For I in 1..100 Loop
  3131.          DELTAE := (AANOM - EANOM + ECCEN*SIN(EANOM)) /
  3132.                    (1.0 - ECCEN*COS(EANOM));
  3133.          EANOM := EANOM + DELTAE;
  3134.          If DELTAE/EANOM < 1.0E-8 Then
  3135.             Return;
  3136.          End If;
  3137.       End Loop;
  3138. --
  3139. --NO CONVERGENCE.
  3140.       IERR := 1;
  3141.       Return;
  3142. --
  3143.       End LOCEAN;
  3144. --
  3145. --
  3146.       Procedure LOCGRB (XLA1: in float;
  3147.                         XLO1: in float;
  3148.                         XLA2: in float;
  3149.                         XLO2: in float;
  3150.                         BRNG1: out float;
  3151.                         BRNG2: out float;
  3152.                         DISTANCE: out float) is
  3153. --
  3154. --#PURPOSE: Given the latitude and longitude of two points, LOCGRB
  3155. --          determines the ground range between them and the bearing
  3156. --          from each point to the other.
  3157. --
  3158. --#AUTHOR:  J. Conrad
  3159. --
  3160. --#TYPE:    Spherical Trigonometry.
  3161. --
  3162. --#PARAMETER DESCRIPTIONS:
  3163. --IN        XLA1   = latitude (degs) of point 1 (+north).
  3164. --IN        XLO1   = longitude (degs) of point 1 (+east).
  3165. --IN        XLA2   = latitude (degs) of point 2 (+north).
  3166. --IN        XLO2   = longitude (degs) of point 2 (+east).
  3167. --OUT       BRNG1  = bearing (degs) of point 2 from point 1
  3168. --                   (clockwise from north).
  3169. --OUT       BRNG2  = bearing (degs) of point 1 from point 2
  3170. --                   (clockwise from north).
  3171. --OUT       DISTANCE  = ground range (km) between points 1 and 2.
  3172. --
  3173. --#CALLED BY:
  3174. --          ALDAY
  3175. --          ALNITE
  3176. --          IONCAL
  3177. --          LOCUPD
  3178. --          NOISY 
  3179. --          RF_PROPAGATION_HANDLER
  3180. --          SIGLNK
  3181. --
  3182. --#CALLS TO:
  3183. --          'NONE'
  3184. --
  3185. --#TECHNICAL DESCRIPTION:
  3186. --
  3187. --     LOCGRB computes the great circle range and bearings between two
  3188. --     points that are specified in terms of their latitude and longitude
  3189. --     coordinates. The procedure employed is one of spherical trigo-
  3190. --     nometry using two basic formulae:
  3191. --
  3192. --     DISTANCE = R*ACOS( SIN(LAT1)*SIN(LAT2) + COS(LAT1)*COS(LAT2)*COS(D))
  3193. --
  3194. --     Where:
  3195. --            DISTANCE  = Great circle distance between points in kilometers
  3196. --            R      = Radius of the earth := 6364.0 kilometers
  3197. --            LAT1   = Latitude of point 1 in radians
  3198. --            LAT2   = Latitude of point 2 in radians
  3199. --            D      = Difference in longitude between points in radians
  3200. --
  3201. --     And,
  3202. --            BRNG   = ACOS((SIN(LAT2 - SIN(LAT1)*COS(PHI)) /
  3203. --                     COS(LAT1)*SIN(PHI))
  3204. --
  3205. --     Where:
  3206. --            BRNG   = Bearing of point 2 from point 1 in radians
  3207. --            PHI    = Central earth angle in radians = DISTANCE/R
  3208. --
  3209. --     ***** IT SHOULD BE NOTED THAT ALL BEARINGS BECOME COUNTER
  3210. --           CLOCKWISE IF LONGITUDES ARE IN DEGREES + WEST        *****
  3211. --
  3212. --
  3213.       YLO1, YLO2, DIF1, DIF2, DL: float;
  3214.       KK: integer;
  3215.       A, B, AB, BA, AA, BB, YY, A1, B1: float;
  3216.       CSA, SNA, CSB, SNB, X, Y, XAR, YAR: float; 
  3217.       DEL: constant float := 3.490659E-2;
  3218.       EPS: constant float := 8.726646E-3;
  3219. --
  3220.       Begin
  3221. --
  3222.       YLO1 := XLO1*RADIANS_PER_DEGREE;
  3223.       If XLO1 < 0.0 Then
  3224.          YLO1 := TWOPI + YLO1;
  3225.       End If;
  3226.       YLO2 := XLO2*RADIANS_PER_DEGREE;
  3227.       If  XLO2 < 0.0 Then
  3228.          YLO2 := TWOPI + YLO2;
  3229.       End If;
  3230. --
  3231.       DIF1 := YLO2 - YLO1;
  3232.       DIF2 := -DIF1;
  3233.       If DIF1 > 0.0 Then
  3234.          If DIF1 > PI Then
  3235.             DL := TWOPI - DIF1;
  3236.             KK := 0;
  3237.          Else
  3238.             DL := DIF1;
  3239.             KK := 1;
  3240.          End If;
  3241.       Else
  3242.          If DIF2 < PI Then
  3243.             DL := DIF2;
  3244.             KK := 0;
  3245.          Else
  3246.             DL := TWOPI - DIF2;
  3247.             KK := 1;
  3248.          End If;
  3249.       End If;
  3250. --
  3251.       B := HALFPI - XLA1*RADIANS_PER_DEGREE;
  3252.       A := HALFPI - XLA2*RADIANS_PER_DEGREE;
  3253.       If ABS(A - HALFPI) <= EPS and ABS(B - HALFPI) <= EPS Then
  3254.          DISTANCE := DL;
  3255.          AA := HALFPI;
  3256.          BB := HALFPI;
  3257.          Goto ADJUST_UNITS;
  3258.       End If;
  3259.       AB := A - B;
  3260.       BA := B - A;
  3261.       If DL <= EPS  Then
  3262.          If BA < 0.0 and AB > DEL Then
  3263.             BB := 0.0;
  3264.             AA := PI;
  3265.             DISTANCE := AB;
  3266.             Goto ADJUST_UNITS;
  3267.          End If;
  3268.          If BA > DEL Then
  3269.             BB := PI;
  3270.             AA := 0.0;
  3271.             DISTANCE := BA;
  3272.             Goto ADJUST_UNITS;
  3273.          End If;
  3274.       Else
  3275.          If B <= EPS and A <= EPS Then
  3276.             DISTANCE := AMAX1( (A*A + B*B - 2.0*A*B*COS(DL)), 0.0);
  3277.             DISTANCE := SQRT(DISTANCE);
  3278.             YY    := A/DISTANCE*SIN(DL);
  3279.             If ABS(YY) > RADIANS_PER_DEGREE Then
  3280.                AA := HALFPI;
  3281.                BB := HALFPI - DL;
  3282.                Goto ADJUST_UNITS;
  3283.             End If;
  3284.             A1 := B*B + DISTANCE*DISTANCE - A*A;
  3285.             If A1 > 0.0 Then
  3286.                AA := PI - ASIN(YY);
  3287.             Else
  3288.                AA := ASIN(YY);
  3289.             End If;
  3290.             BB := PI - AA + DL;
  3291.             Goto ADJUST_UNITS;
  3292.          End If;
  3293.       End If;
  3294. --
  3295.       CSA := COS(A);
  3296.       SNA := SIN(A);
  3297.       CSB := COS(B);
  3298.       SNB := SIN(B);
  3299.       X := CSA*CSB + SNA*SNB*COS(DL);
  3300.       X := SIGN (AMIN1 (ABS(X), 1.0), X);
  3301.       A1 := CSA - X*CSB;
  3302.       B1 := CSB - X*CSA;
  3303.       DISTANCE := ACOS(X);
  3304.       If ABS(DISTANCE - PI) <= EPS Then
  3305.          AA := 0.001*RADIANS_PER_DEGREE;
  3306.          BB := AA;
  3307.          Goto ADJUST_UNITS;
  3308.       End If;
  3309.       Y := 0.0;
  3310.       If DISTANCE /= 0.0 Then
  3311.          Y := SIN(DL)/SIN(DISTANCE);
  3312.       End If;
  3313. --
  3314.       XAR := Y*SNA;
  3315.       If ABS(XAR) >= 0.9999 Then
  3316.          AA := HALFPI;
  3317.       Else
  3318.          AA := ASIN(Y*SNA);
  3319.          If A1 <= 0.0 Then
  3320.             AA := PI - AA;
  3321.          End If;
  3322.       End If;
  3323. --
  3324.       YAR := Y*SNB;
  3325.       If ABS(YAR) >= 0.9999 Then
  3326.          BB := HALFPI;
  3327.       Else
  3328.          BB := ASIN(Y*SNB);
  3329.          If B1 <= 0.0 Then
  3330.             BB := PI - BB;
  3331.          End If;
  3332.       End If;
  3333. --
  3334. <<ADJUST_UNITS>>
  3335.       If KK <= 0 Then
  3336.          BRNG1 := TWOPI - AA;
  3337.          BRNG2 := BB;
  3338.       Else
  3339.          BRNG2 := TWOPI - BB;
  3340.          BRNG1 := AA;
  3341.       End If;
  3342. --
  3343.       DISTANCE := DISTANCE*RADIUS_OF_EARTH_IN_KM;
  3344.       BRNG1 := BRNG1*DEGREES_PER_RADIAN;
  3345.       BRNG2 := BRNG2*DEGREES_PER_RADIAN;
  3346. --
  3347.       Return;
  3348. --
  3349.       End LOCGRB;
  3350. --
  3351. --
  3352.       Procedure LOCNEW (STALA: in float;
  3353.                         STALO: in float;
  3354.                         BRNGD: in float;
  3355.                         DR: in float;
  3356.                         XLA: out float;
  3357.                         XLO: out float) is
  3358. --
  3359. --#PURPOSE: LOCNEW calculates a new position (latitude and longitude)
  3360. --          given a starting position, a bearing and a ground range.
  3361. --
  3362. --#AUTHOR:  J. Conrad
  3363. --
  3364. --#TYPE:    Spherical Trigonometry.
  3365. --
  3366. --#PARAMETER DESCRIPTIONS:
  3367. --IN        STALA  = latitude of starting point (degs, + north).
  3368. --IN        STALO  = longitude of starting point (degs, + east).
  3369. --IN        BRNGD  = bearing of starting point (degs, measured
  3370. --                   clockwise from north to the point).
  3371. --IN        DR     = ground range between points (km).
  3372. --OUT       XLA    = latitude of new point (degs, + north).
  3373. --OUT       XLO    = longitude of new point (degs, + east).
  3374. --
  3375. --#CALLED BY:
  3376. --          ALDAY
  3377. --          ALNITE
  3378. --          DNTR
  3379. --          ELF
  3380. --          HFNACP
  3381. --          HFNORM
  3382. --          HIGHTF
  3383. --          IONDAT 
  3384. --          LFPROP
  3385. --          LOCUPD
  3386. --          MMMUF
  3387. --
  3388. --#CALLS TO:
  3389. --          'NONE'
  3390. --
  3391. --#TECHNICAL DESCRIPTION:
  3392. --     LOCNEW computes the the latitude and longitude of a point given
  3393. --     the latitude and longitude of an initial point as well as the
  3394. --     bearing of the second point from the first using spherical trigo-
  3395. --     nometric formulae.
  3396. --
  3397. --     ***** IT SHOULD BE NOTED THAT THE BEARING IS COUNTER
  3398. --           CLOCKWISE IF THE LONGITUDES ARE IN DEGREES + WEST *****
  3399. --
  3400.       XLA1, XLA2, XLO1, XLO2, BRNG: float;
  3401.       BASE, THETA1, A1, A2: float;
  3402.       TERM1, TERM2, TERM3, TERM4, TERM5: float;
  3403.       TEST, RATIO, DLON: float;
  3404.       KK: integer;
  3405. --
  3406.       Begin
  3407. --
  3408.       XLA1 := STALA*RADIANS_PER_DEGREE;
  3409.       XLO1 := STALO*RADIANS_PER_DEGREE;
  3410.       BRNG := BRNGD*RADIANS_PER_DEGREE;
  3411.       If XLO1 < 0.0 Then
  3412.          XLO1 := XLO1 + TWOPI;
  3413.       End If;
  3414.       KK := 1;
  3415.       If BRNG <= PI Then
  3416.          KK := 0;
  3417.       End If;
  3418. --
  3419.       BASE := DR/RADIUS_OF_EARTH_IN_KM;
  3420.       THETA1 := AMIN1 (BRNG, TWOPI - BRNG);
  3421.       A1 := HALFPI - XLA1;
  3422. --
  3423.       TERM1 := COS(A1);
  3424.       TERM2 := COS(BASE);
  3425.       TERM3 := SIN(A1);
  3426.       TERM4 := SIN(BASE);
  3427.       TERM5 := COS(THETA1);
  3428.       A2 := ACOS (TERM1*TERM2 + TERM3*TERM4*TERM5);
  3429. --
  3430.       XLA2 := HALFPI - A2;
  3431.       TEST := COS(BASE) - COS(A1)*COS(A2);
  3432.       RATIO := 0.0;
  3433.       If A2 /= 0.0 Then
  3434.          RATIO := TERM4*SIN(THETA1)/SIN(A2);
  3435.       End If;
  3436.       DLON := ASIN( SIGN( AMIN1( ABS(RATIO), 1.0), RATIO));
  3437.       If TEST <= 0.0 Then
  3438.          DLON := PI - DLON;
  3439.       End If;
  3440. --
  3441.       XLO2 := AMOD (XLO1 + TWOPI - DLON, TWOPI);
  3442.       If KK = 0 Then
  3443.          XLO2 := AMOD (XLO1 + DLON, TWOPI);
  3444.       End If;
  3445.       XLO := XLO2*DEGREES_PER_RADIAN;
  3446.       If XLO2 > PI Then
  3447.          XLO := (XLO2 - TWOPI)*DEGREES_PER_RADIAN;
  3448.       End If;
  3449.       XLA := XLA2*DEGREES_PER_RADIAN;
  3450. --
  3451.       Return;
  3452. --
  3453.       End LOCNEW;
  3454. --
  3455. --
  3456.       Procedure LOCSAT (EPH: in F_ARRAY;
  3457.                         SATLAT: out float;
  3458.                         SATLON: out float;
  3459.                         SATALT: out float) is
  3460. --
  3461. --#PURPOSE: LOCSAT computes a satellite's position based on the ephemeris data.
  3462. --
  3463. --#AUTHOR:  J. Conrad
  3464. --
  3465. --#TYPE:    Orbit Calculation.
  3466. --
  3467. --#PARAMETER DESCRIPTIONS:
  3468. --IN        EPH    = 6-element input ephemerous data array, where
  3469. --                   1,  semi-major axis of the ellipse (km),
  3470. --                   2,  eccentricity of the ellipse,
  3471. --                   3,  inclination angle (deg),
  3472. --                   4,  argument of perigee (deg),
  3473. --                   5,  longitude of the ascending node (deg),
  3474. --                   6,  time since perigee (min).
  3475. --OUT       SATLAT = satellite latitude (deg north),
  3476. --OUT       SATLON = satellite longitude (deg east),
  3477. --OUT       SATALT = satellite altitude (km).
  3478. --
  3479. --#CALLED BY:
  3480. --          LOCUPD
  3481. --
  3482. --#CALLS TO:
  3483. --          LOCEAN
  3484. --          LOCTAN
  3485. --
  3486. --#TECHNICAL DESCRIPTION:
  3487. --          LOCSAT computes a satellite's position based on
  3488. --          the ephemeris data.  Standard formulae based on Kepler
  3489. --          orbit state vectors are employed in the computation.
  3490. --
  3491.       XMU: constant float:= 0.0055674;
  3492.       OMEGAE: constant float:= 4.375269E-3;
  3493.       SMAJAX, ECCEN, ANGINC, ARGPER, ANLONG, TP: float;
  3494.       RATIO, SANGIN, CANGIN, TSP: float;
  3495.       RTOSAT, CENTRL, SCENT, CCENT, DSLON: float;
  3496.       EANOM, TANOM: float;
  3497.       IERR: integer;
  3498. --
  3499.       Begin
  3500. --
  3501. --CONVERT INPUT EPHEMERIDES TO STATE VECTOR FORMAT.
  3502.       SMAJAX := EPH(1)/RADIUS_OF_EARTH_IN_KM;
  3503.       ECCEN  := EPH(2);
  3504.       ANGINC := EPH(3)*RADIANS_PER_DEGREE;
  3505.       ARGPER := EPH(4)*RADIANS_PER_DEGREE;
  3506.       ANLONG := EPH(5)*RADIANS_PER_DEGREE;
  3507.       TP     := EPH(6);
  3508. --
  3509.       RATIO  := SMAJAX*SQRT(SMAJAX/XMU);
  3510.       SANGIN := SIN(ANGINC);
  3511.       CANGIN := COS(ANGINC);
  3512. --
  3513. --TIME SINCE PERIGEE.
  3514.       TSP := TP + CURRENT_TIME;
  3515. --
  3516. --CALCULATE ECCENTRIC ANOMALY.
  3517.       LOCEAN (TSP, RATIO, ECCEN, IERR, EANOM);
  3518. --
  3519. --ALTITUDE OF SATELLITE.
  3520.       RTOSAT := SMAJAX*(1.0 - ECCEN*COS(EANOM));
  3521.       SATALT := RADIUS_OF_EARTH_IN_KM*(RTOSAT - 1.0);
  3522. --
  3523. --TRUE ANOMALY.
  3524.       LOCTAN (ECCEN, EANOM, TANOM);
  3525. --
  3526. --ANGLE TO SATELLITE FROM ASCENDING NODE.
  3527.       CENTRL := ARGPER + TANOM;
  3528.       CENTRL := AMOD (CENTRL, TWOPI);
  3529. --
  3530. --DETERMINE GEOCENTRIC LATITUDE OF SATELLITE.
  3531.       SCENT := SIN(CENTRL);
  3532.       CCENT := COS(CENTRL);
  3533.       SATLAT := ASIN (SANGIN*SCENT)*DEGREES_PER_RADIAN;
  3534. --
  3535. --DIFFERENCE IN LONGITUDE FROM ASCENDING NODE.
  3536.       DSLON := ATAN2 (SCENT*CANGIN, CCENT);
  3537. --
  3538. --DETERMINE LONGITUDE OF SATELLITE.
  3539.       SATLON := ANLONG + DSLON - OMEGAE*CURRENT_TIME;
  3540.       SATLON := AMOD (SATLON, TWOPI);
  3541.       If SATLON > PI Then
  3542.          SATLON := SATLON - TWOPI;
  3543.       End If;
  3544.       SATLON := SATLON*DEGREES_PER_RADIAN;
  3545.       If SATLON <= -180.0 Then
  3546.          SATLON := SATLON + 360.0;
  3547.       End If;
  3548.       If SATLON > 180.0 Then
  3549.          SATLON := 360.0 - SATLON;
  3550.       End If;
  3551. --
  3552.       Return;
  3553. --
  3554.       End LOCSAT;
  3555. --
  3556. --
  3557.       Procedure LOCTAN (ECCEN: in float; 
  3558.                         EANOM: in float;
  3559.                         TANOM: out float) is
  3560. --
  3561. --#PURPOSE: LOCTAN calculates the true anomaly of an orbit as a
  3562. --          function of the eccentricity of the orbit and the
  3563. --          eccentric anomaly.
  3564. --
  3565. --#AUTHOR:  J. Conrad
  3566. --
  3567. --#TYPE:    Orbit Calculation.
  3568. --
  3569. --#PARAMETER DESCRIPTIONS:
  3570. --IN        ECCEN  := the eccentricity of orbit ellipse.
  3571. --IN        EANOM  := the eccentric anomaly (radians).
  3572. --OUT       TANOM  := the true anomaly (radians).
  3573. --
  3574. --#CALLED BY:
  3575. --          LOCSAT
  3576. --
  3577. --#CALLS TO:
  3578. --          'NONE'
  3579. --
  3580. --#TECHNICAL DESCRIPTION:
  3581. --          LOCTAN calculates the true anomaly of an orbit as a
  3582. --          function of the eccentricity of the orbit and the
  3583. --          eccentric anomaly.  Standard formulae based on Kepler
  3584. --          orbit state vectors are employed in the computation.
  3585. --
  3586.       EAN, EA2, EAT, TANEA2, COSEA2, ARG1: float;
  3587. --
  3588.       Begin
  3589. --
  3590.       EAN := AMOD (EANOM, TWOPI);
  3591.       EA2 := EAN*0.5;
  3592.       EAT := ABS (ABS(EA2) - HALFPI);
  3593.       If EAT >= 0.001 Then
  3594.          TANEA2 := 0.0;
  3595.          COSEA2 := COS(EA2);
  3596.          If COSEA2 /= 0.0 Then
  3597.             TANEA2 := SIN(EA2)/COSEA2;
  3598.          End If;
  3599.          ARG1 := SQRT ((1.0 + ECCEN)/(1.0 - ECCEN))*TANEA2;
  3600.          TANOM := 2.0*ATAN (ARG1);
  3601.       Else
  3602.          TANOM := SIGN (PI, EAN);
  3603.       End If;
  3604. --
  3605.       TANOM := TANOM + SIGN (PI, 1.0) - SIGN (PI, TANOM);
  3606. --
  3607.       Return;
  3608. --
  3609.       End LOCTAN;
  3610. --
  3611. --
  3612.       Procedure LOCUPD (NUM: in integer; 
  3613.                         YLAT: out float;
  3614.                         YLON: out float;
  3615.                         YALT: out float) is
  3616. --
  3617. --#PURPOSE: LOCUPD computes a node's location at a given time based on
  3618. --          the type of node (fixed, moving, or satellite) and the 
  3619. --          associated position generation data.
  3620. --
  3621. --#AUTHOR:  J. Conrad
  3622. --
  3623. --#TYPE:    Geometry.
  3624. --
  3625. --#PARAMETER DESCRIPTIONS:
  3626. --IN        NUM    = position of the node in the data structure.
  3627. --OUT       YLAT   = node latitude (deg. north).
  3628. --OUT       YLON   = node longitude (deg. east).
  3629. --OUT       YALT   = node altitude (km).
  3630. --
  3631. --#CALLED BY:
  3632. --          RF_PROPAGATION_HANDLER
  3633. --
  3634. --#CALLS TO:
  3635. --          LOCGRB
  3636. --          LOCNEW
  3637. --          LOCSAT
  3638. --
  3639. --#TECHNICAL DESCRIPTION:
  3640. --
  3641. --     LOCUPD updates a node's location based on its type in terms of fixed, 
  3642. --     moving or satellite. The procedure followed is to first determine 
  3643. --     whether the node is fixed, moving or a satellite type.  If fixed, 
  3644. --     nothing is done to update the location.  If moving or satellite, an 
  3645. --     interpolated position update is performed prior to returning to the 
  3646. --     calling routine.
  3647. --
  3648.       XTIM, XLAT, XLON, XALT, YTIM: float;
  3649.       ZTIM, ZLAT, ZLON, ZALT: float;
  3650.       FRAC: float;
  3651.       EPH: F_ARRAY(1..6);
  3652.       BRNG1, BRNG2, DISTANCE: float;
  3653. --
  3654.       Begin
  3655. --
  3656.       Case ITYSND(NUM) is
  3657. --FIXED.
  3658.          When FIXED =>
  3659.             YTIM := XPSSND(1,1,NUM);
  3660.             YLAT := XPSSND(2,1,NUM);
  3661.             YLON := XPSSND(3,1,NUM);
  3662.             YALT := XPSSND(4,1,NUM);
  3663. --
  3664. --MOVING.
  3665.          When MOVING =>
  3666.             XTIM := XPSSND(1,1,NUM);
  3667.             XLAT := XPSSND(2,1,NUM);
  3668.             XLON := XPSSND(3,1,NUM);
  3669.             XALT := XPSSND(4,1,NUM);
  3670.             If NLSND(NUM) < 2 Then
  3671.                YTIM := XTIM;
  3672.                YLAT := XLAT;
  3673.                YLON := XLON;
  3674.                YALT := XALT;
  3675.             Else
  3676.                For I in 2..NLSND(NUM) Loop
  3677.                   ZTIM := XTIM;
  3678.                   ZLAT := XLAT;
  3679.                   ZLON := XLON;
  3680.                   ZALT := XALT;
  3681.                   XTIM := XPSSND(1,I,NUM);
  3682.                   XLAT := XPSSND(2,I,NUM);
  3683.                   XLON := XPSSND(3,I,NUM);
  3684.                   XALT := XPSSND(4,I,NUM);
  3685.                   Exit When XTIM > CURRENT_TIME;
  3686.                   IF XTIM = CURRENT_TIME Then
  3687.                      YTIM := XTIM;
  3688.                      YLAT := XLAT;
  3689.                      YLON := XLON;
  3690.                      YALT := XALT;
  3691.                      Return;
  3692.                   End If;
  3693.                End Loop;
  3694.         --
  3695.         --INTERPOLATION.
  3696.                FRAC := (CURRENT_TIME - ZTIM)/(XTIM - ZTIM);
  3697.         --
  3698.         --DETERMINE GROUND RANGE BETWEEN POINTS.
  3699.                LOCGRB (ZLAT, ZLON, XLAT, XLON, BRNG1, BRNG2, DISTANCE);
  3700.                DISTANCE := DISTANCE*FRAC;
  3701.         --
  3702.         --COMPUTE NEW LOCATION.
  3703.                LOCNEW (ZLAT, ZLON, BRNG1, DISTANCE, YLAT, YLON);
  3704.                YALT := ZALT + (XALT - ZALT)*FRAC;
  3705.             End If;
  3706. --
  3707. --SATELLITE.
  3708.          When SATELLITE =>
  3709.             For I in 1..6 Loop
  3710.                EPH(I) := EPHSND(I,NUM);
  3711.             End Loop;
  3712.             LOCSAT (EPH, YLAT, YLON, YALT);
  3713. --
  3714.          When others =>
  3715.             null;
  3716.          End Case;
  3717.          Return;
  3718. --
  3719.       End LOCUPD;
  3720. --
  3721. --
  3722. End NODELOC;
  3723.  
  3724. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3725. --FARKLER
  3726. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3727. package FARKLER is
  3728.       FARKLE: array (integer range 1..5, 
  3729.                      integer range 1..73,
  3730.                      integer range 1..2) of float :=
  3731.        ((( 80.60,  129.00),
  3732.        (   80.20,  130.50),
  3733.        (   79.90,  131.80),
  3734.        (   79.60,  133.30),
  3735.        (   79.20,  135.00),
  3736.        (   79.00,  136.90),
  3737.        (   78.70,  138.70),
  3738.        (   78.50,  140.60),
  3739.        (   78.20,  142.60),
  3740.        (   78.00,  144.90),
  3741.        (   77.90,  147.00),
  3742.        (   77.70,  149.20),
  3743.        (   77.50,  151.50),
  3744.        (   77.40,  153.80),
  3745.        (   77.30,  156.20),
  3746.        (   77.20,  158.60),
  3747.        (   77.10,  161.00),
  3748.        (   77.00,  163.60),
  3749.        (   77.00,  166.10),
  3750.        (   76.90,  168.60),
  3751.        (   76.90,  171.10),
  3752.        (   76.90,  173.60),
  3753.        (   76.90,  176.00),
  3754.        (   76.90,  178.50),
  3755.        (   76.90,  180.90),
  3756.        (   76.90,  183.40),
  3757.        (   77.00,  185.70),
  3758.        (   77.10,  188.00),
  3759.        (   77.20,  190.20),
  3760.        (   77.30,  192.40),
  3761.        (   77.40,  194.50),
  3762.        (   77.60,  196.60),
  3763.        (   77.70,  198.60),
  3764.        (   77.90,  200.60),
  3765.        (   78.20,  202.40),
  3766.        (   78.40,  204.20),
  3767.        (   78.70,  205.80),
  3768.        (   79.00,  207.40),
  3769.        (   79.40,  208.90),
  3770.        (   79.70,  210.20),
  3771.        (   80.10,  211.30),
  3772.        (   80.50,  212.40),
  3773.        (   80.90,  213.40),
  3774.        (   81.40,  214.20),
  3775.        (   81.90,  214.70),
  3776.        (   82.30,  214.80),
  3777.        (   82.80,  214.80),
  3778.        (   83.30,  214.50),
  3779.        (   83.90,  213.50),
  3780.        (   84.40,  212.10),
  3781.        (   84.90,  210.00),
  3782.        (   85.30,  207.20),
  3783.        (   85.80,  203.40),
  3784.        (   86.20,  196.50),
  3785.        (   86.50,  189.60),
  3786.        (   86.70,  181.40),
  3787.        (   86.80,  172.30),
  3788.        (   86.80,  162.90),
  3789.        (   86.60,  153.90),
  3790.        (   86.30,  146.00),
  3791.        (   86.00,  139.40),
  3792.        (   85.60,  134.40),
  3793.        (   85.10,  130.70),
  3794.        (   84.60,  128.10),
  3795.        (   84.20,  126.40),
  3796.        (   83.70,  126.30),
  3797.        (   83.20,  125.50),
  3798.        (   82.70,  125.20),
  3799.        (   82.30,  125.40),
  3800.        (   81.80,  126.40),
  3801.        (   81.40,  127.00),
  3802.        (   81.00,  127.90),
  3803.        (   80.60,  129.00)),
  3804.        ((  41.60,   77.50),
  3805.        (   40.90,   81.50),
  3806.        (   40.40,   85.60),
  3807.        (   40.00,   89.70),
  3808.        (   39.70,   93.80),
  3809.        (   39.50,   98.00),
  3810.        (   39.30,  102.30),
  3811.        (   39.30,  106.70),
  3812.        (   39.40,  111.20),
  3813.        (   39.50,  115.80),
  3814.        (   39.60,  120.50),
  3815.        (   39.70,  125.30),
  3816.        (   39.80,  130.10),
  3817.        (   39.90,  135.10),
  3818.        (   40.00,  140.00),
  3819.        (   40.00,  145.00),
  3820.        (   40.00,  150.00),
  3821.        (   40.00,  155.10),
  3822.        (   40.00,  160.10),
  3823.        (   40.00,  165.20),
  3824.        (   39.90,  170.30),
  3825.        (   39.90,  175.40),
  3826.        (   39.70,  180.60),
  3827.        (   39.50,  185.70),
  3828.        (   39.20,  190.80),
  3829.        (   38.90,  195.70),
  3830.        (   38.50,  200.60),
  3831.        (   38.20,  205.40),
  3832.        (   37.80,  210.00),
  3833.        (   37.50,  214.40),
  3834.        (   37.30,  218.70),
  3835.        (   37.20,  222.80),
  3836.        (   37.30,  226.90),
  3837.        (   37.50,  230.90),
  3838.        (   37.80,  234.90),
  3839.        (   38.30,  238.90),
  3840.        (   38.90,  242.90),
  3841.        (   39.60,  247.00),
  3842.        (   40.30,  251.10),
  3843.        (   41.20,  255.40),
  3844.        (   42.00,  259.70),
  3845.        (   43.00,  264.10),
  3846.        (   43.90,  268.60),
  3847.        (   44.90,  273.20),
  3848.        (   45.90,  277.80),
  3849.        (   47.00,  282.60),
  3850.        (   48.00,  287.50),
  3851.        (   49.20,  292.60),
  3852.        (   50.30,  297.80),
  3853.        (   51.40,  303.30),
  3854.        (   52.50,  309.00),
  3855.        (   53.60,  315.00),
  3856.        (   54.60,  321.30),
  3857.        (   55.50,  327.90),
  3858.        (   56.30,  334.80),
  3859.        (   56.80,  342.00),
  3860.        (   57.10,  349.40),
  3861.        (   57.20,   -3.10),
  3862.        (   56.90,    4.30),
  3863.        (   56.40,   11.60),
  3864.        (   55.70,   18.60),
  3865.        (   54.70,   25.20),
  3866.        (   53.60,   31.50),
  3867.        (   52.30,   37.40),
  3868.        (   50.90,   42.80),
  3869.        (   49.50,   47.90),
  3870.        (   48.20,   52.60),
  3871.        (   46.80,   57.10),
  3872.        (   45.50,   61.40),
  3873.        (   44.40,   65.50),
  3874.        (   43.30,   69.60),
  3875.        (   42.40,   73.60),
  3876.        (   41.60,   77.50)),
  3877.        ((  -6.00,   70.80),
  3878.        (   -7.10,   75.50),
  3879.        (   -7.90,   80.20),
  3880.        (   -8.40,   85.00),
  3881.        (   -8.70,   89.80),
  3882.        (   -8.60,   94.80),
  3883.        (   -8.20,   99.70),
  3884.        (   -7.70,  104.70),
  3885.        (   -8.10,  109.80),
  3886.        (   -6.40,  114.80),
  3887.        (   -5.70,  119.90),
  3888.        (   -5.10,  124.90),
  3889.        (   -4.70,  129.90),
  3890.        (   -4.60,  134.80),
  3891.        (   -4.70,  139.70),
  3892.        (   -4.90,  144.70),
  3893.        (   -5.20,  149.60),
  3894.        (   -5.30,  154.70),
  3895.        (   -5.30,  159.60),
  3896.        (   -5.20,  164.70),
  3897.        (   -5.00,  169.80),
  3898.        (   -4.70,  174.80),
  3899.        (   -4.00,  179.80),
  3900.        (   -3.90,  184.70),
  3901.        (   -3.20,  189.60),
  3902.        (   -2.90,  194.50),
  3903.        (   -2.90,  199.40),
  3904.        (   -2.90,  204.40),
  3905.        (   -3.00,  209.30),
  3906.        (   -3.00,  214.30),
  3907.        (   -2.80,  219.20),
  3908.        (   -2.40,  224.40),
  3909.        (   -1.90,  229.30),
  3910.        (   -1.00,  234.30),
  3911.        (    0.00,  239.30),
  3912.        (    1.00,  244.10),
  3913.        (    2.00,  249.10),
  3914.        (    2.90,  254.10),
  3915.        (    3.70,  258.90),
  3916.        (    4.30,  263.80),
  3917.        (    4.90,  269.00),
  3918.        (    5.40,  273.90),
  3919.        (    5.90,  278.80),
  3920.        (    6.30,  283.70),
  3921.        (    6.60,  288.60),
  3922.        (    7.00,  293.60),
  3923.        (    7.40,  298.50),
  3924.        (    7.80,  303.40),
  3925.        (    8.30,  308.30),
  3926.        (    8.80,  313.10),
  3927.        (    9.50,  317.90),
  3928.        (   10.40,  322.80),
  3929.        (   11.30,  327.70),
  3930.        (   12.50,  332.60),
  3931.        (   13.70,  337.70),
  3932.        (   14.90,  342.90),
  3933.        (   16.00,  348.30),
  3934.        (   16.80,   -6.10),
  3935.        (   17.40,   -0.40),
  3936.        (   17.40,    5.30),
  3937.        (   17.00,   11.10),
  3938.        (   16.10,   16.90),
  3939.        (   14.60,   22.50),
  3940.        (   12.80,   28.00),
  3941.        (   10.60,   33.20),
  3942.        (    8.10,   38.30),
  3943.        (    5.60,   43.10),
  3944.        (    3.20,   47.90),
  3945.        (    0.80,   52.50),
  3946.        (   -1.30,   57.00),
  3947.        (   -3.10,   61.60),
  3948.        (   -4.70,   66.20),
  3949.        (   -6.00,   70.80)),
  3950.        (( -44.80,   55.30),
  3951.        (  -45.90,   60.10),
  3952.        (  -47.00,   65.00),
  3953.        (  -47.90,   70.00),
  3954.        (  -48.70,   74.90),
  3955.        (  -49.50,   79.90),
  3956.        (  -50.10,   84.90),
  3957.        (  -50.70,   89.70),
  3958.        (  -51.30,   94.50),
  3959.        (  -51.80,   99.30),
  3960.        (  -52.40,  104.00),
  3961.        (  -53.10,  108.80),
  3962.        (  -53.70,  113.60),
  3963.        (  -54.50,  118.50),
  3964.        (  -55.30,  123.60),
  3965.        (  -56.10,  129.00),
  3966.        (  -56.90,  134.60),
  3967.        (  -57.70,  140.60),
  3968.        (  -58.40,  146.80),
  3969.        (  -59.00,  153.30),
  3970.        (  -59.40,  160.00),
  3971.        (  -59.80,  166.90),
  3972.        (  -60.00,  174.00),
  3973.        (  -60.00,  181.00),
  3974.        (  -60.00,  188.10),
  3975.        (  -59.80,  195.10),
  3976.        (  -59.50,  202.00),
  3977.        (  -59.10,  208.80),
  3978.        (  -58.50,  215.60),
  3979.        (  -57.90,  222.20),
  3980.        (  -57.20,  228.60),
  3981.        (  -56.40,  234.90),
  3982.        (  -55.50,  241.00),
  3983.        (  -54.60,  246.90),
  3984.        (  -53.60,  252.60),
  3985.        (  -52.60,  258.20),
  3986.        (  -51.50,  263.60),
  3987.        (  -50.40,  268.80),
  3988.        (  -49.40,  273.90),
  3989.        (  -48.30,  279.00),
  3990.        (  -47.30,  283.90),
  3991.        (  -46.20,  288.80),
  3992.        (  -45.20,  293.60),
  3993.        (  -44.20,  298.40),
  3994.        (  -43.30,  303.10),
  3995.        (  -42.30,  307.80),
  3996.        (  -41.30,  312.50),
  3997.        (  -40.40,  317.20),
  3998.        (  -39.40,  321.80),
  3999.        (  -38.40,  326.40),
  4000.        (  -37.40,  330.80),
  4001.        (  -36.40,  335.20),
  4002.        (  -35.40,  339.50),
  4003.        (  -34.40,  343.60),
  4004.        (  -33.50,  347.60),
  4005.        (  -32.70,  351.40),
  4006.        (  -32.00,  355.10),
  4007.        (  -31.40,   -1.30),
  4008.        (  -31.10,    2.10),
  4009.        (  -31.00,    5.40),
  4010.        (  -31.10,    8.70),
  4011.        (  -31.50,   12.00),
  4012.        (  -32.10,   15.40),
  4013.        (  -32.90,   18.70),
  4014.        (  -34.00,   22.20),
  4015.        (  -35.20,   25.80),
  4016.        (  -36.50,   29.50),
  4017.        (  -37.90,   33.40),
  4018.        (  -39.30,   37.40),
  4019.        (  -40.70,   41.60),
  4020.        (  -42.10,   46.00),
  4021.        (  -43.50,   50.60),
  4022.        (  -44.80,   55.30)),
  4023.        (( -71.60,   26.40),
  4024.        (  -71.80,   27.10),
  4025.        (  -72.10,   27.90),
  4026.        (  -72.40,   28.50),
  4027.        (  -72.70,   29.10),
  4028.        (  -73.00,   29.70),
  4029.        (  -73.30,   30.10),
  4030.        (  -73.60,   30.50),
  4031.        (  -74.00,   30.90),
  4032.        (  -74.30,   31.10),
  4033.        (  -74.60,   31.20),
  4034.        (  -75.00,   31.20),
  4035.        (  -75.30,   31.00),
  4036.        (  -75.60,   30.80),
  4037.        (  -76.00,   30.60),
  4038.        (  -76.30,   30.10),
  4039.        (  -76.60,   29.40),
  4040.        (  -76.90,   28.60),
  4041.        (  -77.10,   27.70),
  4042.        (  -77.40,   26.60),
  4043.        (  -77.60,   25.40),
  4044.        (  -77.80,   24.00),
  4045.        (  -77.90,   22.60),
  4046.        (  -78.10,   21.10),
  4047.        (  -78.10,   19.50),
  4048.        (  -78.20,   17.90),
  4049.        (  -78.20,  376.30),
  4050.        (  -78.10,  374.70),
  4051.        (  -78.10,  373.20),
  4052.        (  -77.90,  371.70),
  4053.        (  -77.80,  370.30),
  4054.        (  -77.60,  368.50),
  4055.        (  -77.40,  367.50),
  4056.        (  -77.20,  366.50),
  4057.        (  -76.90,  365.60),
  4058.        (  -76.60,  364.90),
  4059.        (  -76.30,  364.30),
  4060.        (  -76.00,  363.40),
  4061.        (  -75.60,  363.20),
  4062.        (  -75.30,  363.00),
  4063.        (  -74.90,  362.90),
  4064.        (  -74.60,  362.90),
  4065.        (  -74.20,  363.10),
  4066.        (  -73.90,  363.40),
  4067.        (  -73.50,  363.40),
  4068.        (  -73.20,  363.80),
  4069.        (  -72.90,  364.30),
  4070.        (  -72.60,  364.90),
  4071.        (  -72.30,  365.50),
  4072.        (  -72.00,  366.10),
  4073.        (  -71.70,  366.80),
  4074.        (  -71.50,  367.60),
  4075.        (  -71.20,  368.20),
  4076.        (  -71.00,  369.00),
  4077.        (  -70.80,  369.90),
  4078.        (  -70.70,  370.80),
  4079.        (  -70.50,  371.70),
  4080.        (  -70.40,   12.60),
  4081.        (  -70.30,   13.60),
  4082.        (  -70.30,   14.50),
  4083.        (  -70.20,   15.40),
  4084.        (  -70.20,   16.40),
  4085.        (  -70.20,   17.40),
  4086.        (  -70.20,   18.30),
  4087.        (  -70.30,   19.20),
  4088.        (  -70.40,   20.30),
  4089.        (  -70.50,   21.20),
  4090.        (  -70.60,   22.10),
  4091.        (  -70.80,   23.00),
  4092.        (  -70.90,   23.90),
  4093.        (  -71.10,   24.80),
  4094.        (  -71.30,   25.60),
  4095.        (  -71.60,   26.40)));
  4096. --
  4097. END FARKLER;
  4098.  
  4099. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4100. --HFATMOS
  4101. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  4102. With Mathlib; Use Mathlib, numeric_primitives, core_functions, trig_functions;
  4103. With Nodeloc;
  4104. With Text_IO;
  4105. With Constants; use Constants;
  4106. With Propagation_constants; Use Propagation_constants;
  4107. With Farkler; 
  4108. With Debugger2; Use Debugger2;
  4109. Package HF_ATMOSPHERICS is
  4110. --
  4111. --
  4112.       Procedure AMBION (CLAT: in float;
  4113.                         ELON: in float;
  4114.                         PHI: in float;
  4115.                         TMO: in float;
  4116.                         RZUR: in float;
  4117.                         EMAX: out float;
  4118.                         HEMAX: out float;
  4119.                         THICKE: out float;
  4120.                         F1MAX: out float;
  4121.                         HF1MAX: out float;
  4122.                         THIKF1: out float;
  4123.                         F2MAX: out float; 
  4124.                         HF2MAX: out float;
  4125.                         THIKF2: out float);
  4126.  
  4127.       Procedure CGMCS;
  4128.  
  4129.       Procedure CLOCKS (SLAT: in float;
  4130.                         SLON: in float;
  4131.                         COSCHI: out float); 
  4132.  
  4133.  
  4134.       Procedure DENS (TINF: in float;
  4135.                       ALT: in float;
  4136.                       TEMP: out float;
  4137.                       AVH: out float);
  4138.  
  4139.       Procedure ECALC (TM: in float;
  4140.                        F0E: out float;
  4141.                        HME: out float);
  4142.  
  4143.       Function EDAT return float;
  4144.  
  4145.       Function EPHT (EDX: float) return float;
  4146.  
  4147.       Function EXOT (FBAR: float;
  4148.                      F: float;
  4149.                      SOLDEC: float;
  4150.                      GLATR: float;
  4151.                      HA: float) return float;
  4152.  
  4153.       Function F0F2FN (GMT: float;
  4154.                        THRL: float) return float;
  4155.  
  4156.       Procedure F1CALC (F0F1: out float;
  4157.                         HMF1: out float);
  4158.  
  4159.       Procedure FETCH (XP: in float;
  4160.                        YP: in float;
  4161.                        FF: out float;
  4162.                        GG: out float);
  4163.  
  4164.       Function HMF2FN (TIME: float) return float;
  4165.  
  4166.       Procedure IONDAT (IENTER: in integer;
  4167.                         NHOPS: in integer;
  4168.                         EHT: out float;
  4169.                         FHT: out float;
  4170.                         F0EMAX: out float;
  4171.                         F0EMIN: out float;
  4172.                         F0FMAX: out float;
  4173.                         F0FMIN: out float);
  4174.  
  4175.       Procedure IONFT1 (ZMAX: out float;
  4176.                         EMAX: out float;
  4177.                         THICK: out float;
  4178.                         LAYER: in integer;
  4179.                         RZUR: in float;
  4180.                         PHI: in float;
  4181.                         TMO: in float;
  4182.                         RLT: in float;
  4183.                         RLTM: in float;
  4184.                         RLGM: in float;
  4185.                         DIP: in float);
  4186.  
  4187.       Procedure MAGNET (H: in float;
  4188.                         COLAT: in float;
  4189.                         ELONG: in float;
  4190.                         BFELD: out float;
  4191.                         SINDIP: out float;
  4192.                         SINDEC: out float;
  4193.                         COSDEC: out float;
  4194.                         COSMAG: out float;
  4195.                         ELONMG: out float);
  4196.  
  4197.       Procedure POLAR (PLAT: in float;
  4198.                        PLONG: in float;
  4199.                        F0E: out float;
  4200.                        HME: out float;
  4201.                        F0F1: out float;
  4202.                        HMF1: out float;
  4203.                        F0F2: out float;
  4204.                        HMF2: out float);
  4205.  
  4206.       Function POLR (RLTM: float;
  4207.                      RLGM: float;
  4208.                      R: float;
  4209.                      PHI: float;
  4210.                      TMO: float) return float;
  4211.  
  4212.       Procedure SCALHT (FBAR: in float;
  4213.                         F: in float;
  4214.                         SOLDEC: in float;
  4215.                         GLATR: in float;
  4216.                         HA: in float;
  4217.                         HEIGHT: in float;
  4218.                         TATR: out float;
  4219.                         SMULT: out float);
  4220.  
  4221.       Function TABINT (K: integer;
  4222.                        I: integer;
  4223.                        J: integer) return float;
  4224.  
  4225.       Function TATRFN (TINF: float; HEIGHT: float) return float;
  4226.  
  4227.       Function TVARF2 (RLTM: float;
  4228.                        RLGM: float;
  4229.                        DIP: float;
  4230.                        R: float;
  4231.                        PHI: float;
  4232.                        TMO: float;
  4233.                        DEC: float;
  4234.                        CLTM: float;
  4235.                        SLTM: float) return float;
  4236.  
  4237.       Function TVEF1 (A: float;
  4238.                       B: float;
  4239.                       C: float;
  4240.                       D: float;
  4241.                       RLT: float;
  4242.                       R: float;
  4243.                       PHI: float;
  4244.                       DEC: float) return float;
  4245.  
  4246.       Function YONII (RLTM: float;
  4247.                       RF: float;
  4248.                       R: float;
  4249.                       PHI: float;
  4250.                       TMO: float;
  4251.                       DEC: float;
  4252.                       CLTM: float;
  4253.                       SLTM: float) return float;
  4254.  
  4255. --
  4256. --
  4257. --
  4258. End HF_ATMOSPHERICS;
  4259. --
  4260. Package body HF_ATMOSPHERICS is
  4261. --
  4262. -- HF_ATMOSPHERICS Package of PROP_LINK 
  4263. -- Version 1.0,  March 13, 1985.
  4264. --
  4265. -- This HF_ATMOSPHERICS Package contains all of the procedures that are used 
  4266. -- to compute the behavior of the ionosphere for HF propagation.
  4267. --
  4268. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  4269. -- radio frequency propagation prediction code.
  4270. --
  4271. -- PROP_LINK has been developed for the Department of Defense under
  4272. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  4273. -- Systems Inc. (Jim Conrad).
  4274. --
  4275. -- Instantiate integer and floating point IO.
  4276. --      Package IO_INTEGER is new INTEGER_IO(INTEGER);
  4277. --      Package IO_FLOAT is new FLOAT_IO(FLOAT);
  4278. --      Use IO_INTEGER,IO_FLOAT;
  4279. --
  4280.    pragma source_info(on);
  4281. --
  4282. --TYPES:
  4283. --
  4284. --VARIABLES THAT ARE TO VISIBLE TO ALL ROUTINES WITHIN THIS PACKAGE ONLY:
  4285.       SD, CD, SSL, Q, DTDR, DTDT: float;
  4286.       NJ: integer;
  4287.       JD, ED, FD: float;
  4288.       GLONG, GLAT, HRMT, SECCHI, GMLAT, GMLONG: float;
  4289.       NYEAR: integer := 1977;
  4290.       NDAY: integer := 1;
  4291.       NHOUR, MIN, NSEC: integer := 0;
  4292.       UTIME: float;
  4293.       AP, PMA, R, SOLFX: float;
  4294.       T0: float := 300.0;
  4295.       T90: float := 183.0;
  4296.       TB, TX, GX, TR: float;
  4297.       F0HT: array (1..15, 1..4) of float;
  4298.       CDATA: array (integer range 1..5, integer range 1..6) of float;
  4299. --
  4300. --
  4301.       Procedure AMBION (CLAT: in float;
  4302.                         ELON: in float;
  4303.                         PHI: in float;
  4304.                         TMO: in float;
  4305.                         RZUR: in float;
  4306.                         EMAX: out float;
  4307.                         HEMAX: out float;
  4308.                         THICKE: out float;
  4309.                         F1MAX: out float;
  4310.                         HF1MAX: out float;
  4311.                         THIKF1: out float;
  4312.                         F2MAX: out float; 
  4313.                         HF2MAX: out float;
  4314.                         THIKF2: out float) is
  4315. --
  4316. --#PURPOSE: AMBION determines the ionospheric parameters for the
  4317. --          ambient ionosphere for HF reflection calculations.
  4318. --
  4319. --#AUTHOR:  J. Conrad
  4320. --
  4321. --#TYPE:    Numerical Analysis
  4322. --
  4323. --#PARAMETER DESCRIPTIONS:
  4324. --IN        CLAT   = Degrees Latitude (North)
  4325. --IN        ELON   = Degrees Longitude (East)
  4326. --IN        PHI    = Time of day in radians (1 day = 2 pi radians)
  4327. --IN        TMO    = Month (0-12; starting from December 15;
  4328. --                          e.g., June 1 := 6.5)
  4329. --IN        RZUR   = Smoothed Zurich Sunspot number
  4330. --OUT       EMAX   = Maximum electron density of E layer
  4331. --OUT       HEMAX  = Height of maximum electron density of E layer
  4332. --OUT       THICKE = Thickness of E layer
  4333. --OUT       F1MAX  = Maximum electron density of F1 layer
  4334. --OUT       HF1MAX = Height of maximum electron density of F1 layer
  4335. --OUT       THIKF1 = Thickness of F1 layer
  4336. --OUT       F2MAX  = Maximum electron density of F2 layer
  4337. --OUT       HF2MAX = Height of maximum electron density of F2 layer
  4338. --OUT       THIKF2 = Thickness of F2 layer
  4339. --
  4340. --#CALLED BY:
  4341. --          IONDAT
  4342. --
  4343. --#CALLS TO:
  4344. --          IONFT1
  4345. --          MAGNET
  4346. --
  4347. --#TECHNICAL DESCRIPTION:
  4348. --          AMBION is the driver module for Procedures employed
  4349. --          to calculate the ambient ionospheric parameters using a
  4350. --          three parabola fit to the Aerospace Model.
  4351. --          These Procedures were adapted from the Mission Research HFNET 
  4352. --          FORTRAN Subroutines.
  4353. --
  4354.       H: float := 0.0;
  4355.       CLATR, ELONR, RLT, RLTM, DIP: float;
  4356.       ZMAX, VMAX, THICK, BF, SINDIP, COSMAG, ELONMG: float;
  4357.       LAYER: integer;
  4358.       VLMAX, HLMAX: array (integer range 1..3) of float;
  4359.       THICKL: array (integer range 1..33) of float;
  4360. --
  4361.       Begin
  4362. --
  4363.       CLATR := (90.0 - CLAT)*RADIANS_PER_DEGREE;
  4364.       ELONR := ELON*RADIANS_PER_DEGREE;
  4365.       For LAYER in 1..3 Loop
  4366.          MAGNET (H, CLATR, ELONR, BF, SINDIP, SD, CD, COSMAG, ELONMG);
  4367.          RLT := HALFPI - CLATR;
  4368.          RLTM := ASIN(COSMAG);
  4369.          DIP := ASIN(SINDIP);
  4370.          IONFT1 (ZMAX, VMAX, THICK, LAYER, RZUR, PHI, TMO, RLT,
  4371.                  RLTM, ELONMG, DIP);
  4372.          VLMAX(LAYER) := VMAX;
  4373.          HLMAX(LAYER) := ZMAX*1.0E5;
  4374.          THICKL(LAYER) := THICK*1.0E5;
  4375.       End Loop;
  4376. --
  4377.       EMAX := VLMAX(1);
  4378.       HEMAX := HLMAX(1);
  4379.       THICKE := THICKL(1);
  4380.       F1MAX := VLMAX(2);
  4381.       HF1MAX := HLMAX(2);
  4382.       THIKF1 := THICKL(2);
  4383.       F2MAX := VLMAX(3);
  4384.       HF2MAX := HLMAX(3);
  4385.       THIKF2 :=THICKL(3);
  4386. --
  4387.       Return;
  4388. --
  4389.       End AMBION;
  4390. --
  4391. --
  4392.       Procedure CGMCS is
  4393. --
  4394. --#PURPOSE:CGMCS converts from geographic coordinates to geomagnetic.
  4395. --
  4396. --#AUTHOR:  J. Conrad
  4397. --
  4398. --#TYPE:    Computational Procedure
  4399. --
  4400. --#PARAMETER DESCRIPTIONS:
  4401. --         'NONE'
  4402. --
  4403. --#CALLED BY:
  4404. --          POLAR
  4405. --
  4406. --#CALLS TO:
  4407. --          FETCH
  4408. --
  4409. --#TECHNICAL DESCRIPTION:
  4410. --          CGMCS converts geographic coordinates to geomagnetic
  4411. --          coordinates by first computing the colatitude of the
  4412. --          point and then calling Procedure FETCH.  The returned
  4413. --          longitude is then tested to ensure that it is within
  4414. --          the interval of 0 to +360 degrees.
  4415. --
  4416.       YP, XP, FF, GG: float;
  4417. --
  4418.       Begin
  4419. --
  4420.       YP := GLONG;
  4421.       XP := 90.0 - GLAT;
  4422.       FETCH(XP, YP, FF, GG);
  4423.       GMLAT := FF;
  4424.       GMLONG := GG;
  4425.       If GMLONG < 0.0 Then
  4426.          GMLONG := GMLONG + 360.0;
  4427.       End If;
  4428.       If GMLONG >= 360.0 Then
  4429.          GMLONG := GMLONG - 360.0;
  4430.       End If;
  4431. --
  4432.       Return;
  4433. --
  4434.       End CGMCS;
  4435. --
  4436. --
  4437.       Procedure CLOCKS (SLAT: in float;
  4438.                         SLON: in float;
  4439.                         COSCHI: out float) is
  4440. --
  4441. --#PURPOSE: CLOCKS determines the solar zenith angle.
  4442. --
  4443. --#AUTHOR:  J. Conrad
  4444. --
  4445. --#TYPE:    Computational Procedure
  4446. --
  4447. --#PARAMETER DESCRIPTIONS:
  4448. --IN        SLAT   = Latitude (degrees north)
  4449. --IN        SLON   = Longitude (degrees east)
  4450. --OUT       COSCHI = Cosine of zenith angle
  4451. --
  4452. --#CALLED BY:
  4453. --          F1CALC
  4454. --
  4455. --#CALLS TO:
  4456. --          EDAT
  4457. --          EPHT
  4458. --
  4459. --#TECHNICAL DESCRIPTION:
  4460. --          CLOCKS determines the solar zenith angle through the use
  4461. --          of a purely geometrical analysis of the sun's position in
  4462. --          relation to a point on the earth at a specified time.
  4463. --
  4464.       ETIM0: float := -1.0E20;
  4465.       ARG, ETIME, SLONG, HA: float;
  4466. --
  4467.       Begin
  4468. --
  4469.       ETIME := EDAT;
  4470.       If ETIME /= ETIM0 Then
  4471.          SLONG := EPHT(ETIME);
  4472.       End If;
  4473.       ARG := SLAT*RADIANS_PER_DEGREE;
  4474.       HA := SLON - SSL;
  4475.       COSCHI := SD*SIN(ARG) + CD*COS(ARG)*COS(HA*RADIANS_PER_DEGREE);
  4476. --
  4477.       Return;
  4478. --
  4479.       End CLOCKS;
  4480. --
  4481. --
  4482.       Procedure DENS (TINF: in float;
  4483.                       ALT: in float;
  4484.                       TEMP: out float;
  4485.                       AVH: out float) is
  4486. --
  4487. --#PURPOSE: DENS determines atmospheric parameters.
  4488. --
  4489. --#AUTHOR:  J. Conrad
  4490. --
  4491. --#TYPE:    Computational Procedure
  4492. --
  4493. --#PARAMETER DESCRIPTIONS:
  4494. --IN        TINF   = Exospheric (550 - 60,000 km) temperature
  4495. --IN        ALT    = Altitude
  4496. --OUT       TEMP   = Temperature
  4497. --OUT       AVH    = Average height
  4498. --
  4499. --#CALLED BY:
  4500. --          SCALHT
  4501. --
  4502. --#CALLS TO:
  4503. --          TATRFN
  4504. --
  4505. --#TECHNICAL DESCRIPTION:
  4506. --          DENS determines atmospheric parameters based on a three
  4507. --          parabolic approximation to a model known as the Aerospace
  4508. --          model.  This model is semi-empirical in nature in that it
  4509. --          is based on ionospheric measurements taken only at the
  4510. --          low and mid latitudes and may not be reliable at higher
  4511. --          latitudes where auroral effects, extended days/nights, ect.,
  4512. --          influence ionospheric behavior.
  4513. --
  4514.       DEN: array (integer range 1..5) of float;
  4515.       H: array (integer range 1..5) of float;
  4516.       MASS: array (integer range 1..5) of float :=
  4517.          (28.0134, 31.9988, 15.9994, 4.00260, 39.9480);
  4518.       QO: array (integer range 1..4) of float :=
  4519.          (0.7811, 0.20955, 0.0093432, 6.1471E-6);
  4520.       DENB: array (integer range 1..5) of float :=
  4521.          (0.0, 0.0, 0.0, 0.0, 0.0);
  4522.       XMIL: float := 1.0E-3;
  4523.       HKM: float := 1000.0;
  4524.       RTM90: float := 21.965E-6;
  4525.       Z100: float := 100.0;
  4526.       Z90: float := 90.0;
  4527.       B0: float := 28.82678;
  4528.       B1: float := -7.40066E-2;
  4529.       B2: float := -1.19407E-2;
  4530.       B3: float := 4.51103E-4;
  4531.       B4: float := -8.21895E-6;
  4532.       B5: float := 1.07561E-5;
  4533.       B6: float := -6.97444E-7;
  4534.       AN: float := 6.02257E+26;
  4535.       AVM0: float := 28.960;
  4536.       RO: float := 6356766.0;
  4537.       RB: float := 6481766.0;
  4538.       GMB: float := 1.134449;
  4539.       FOF90: float := 0.1806478;
  4540.       ALPHA: float := -0.38;
  4541.       AMU: float := 1.6605313E-27;
  4542.       H1: float := 125.0;
  4543.       DZA: float := 6.25;
  4544.       HEIGHT: float := 0.0;
  4545.       TEX: float := 0.0;
  4546.       F2: float := 0.0;
  4547.       FB: float := 0.0;
  4548.       TB: float := 0.0;
  4549.       IEXIT, J: integer;
  4550.       DZX, F0, F1, DZI, RBR, AVM, AV2, DENM, XNM, DENT, DEN0, DMDR,
  4551.          DNDR, DZZ, RAT, FI: float;
  4552. --
  4553.       Begin
  4554. --
  4555.       IEXIT := 0;
  4556.       If TINF /= TEX or HEIGHT < Z100 or ALT <= Z100 Then
  4557.          DZX := 5.0;
  4558.          If ALT <= Z100 Then
  4559.             DZX := 0.5*(ALT - Z90);
  4560.             IEXIT := 1;
  4561.          End If;
  4562.          F0 := FOF90;
  4563.          F1 := FOF90;
  4564.          F2 := FOF90;
  4565.          FB := 0.0;
  4566.          HEIGHT := Z90;
  4567.          For J in 1..2 Loop 
  4568.             F1 := F2;
  4569.             HEIGHT := HEIGHT + DZX;
  4570.             DZI := HEIGHT - Z90;
  4571.             RBR := RB/(HKM*HEIGHT + RO);
  4572.             TEMP := TATRFN(TINF,HEIGHT);
  4573.             F2 := GMB*RBR*RBR/TEMP;
  4574.             If HEIGHT >= Z90 Then
  4575.                AVM := B0 + DZI*(B1 + DZI*(B2 + DZI*(B3 + DZI*(B4 + DZI*
  4576.                       (B5 + DZI*B6)))));
  4577.             Else
  4578.                AVM := B0 + DZI*B1;
  4579.                If AVM > AVM0 Then
  4580.                   AVM := AVM0;
  4581.                End If;
  4582.             End If;
  4583.             F2 := AVM*F2;
  4584.          End Loop;
  4585.          FB := FB + (F0 + 4.0*F1 + F2)*DZX/3.0;
  4586. --
  4587.          AVH := DZI/FB;
  4588.          AV2 := 1.0/F2;
  4589.          DENM := (RTM90*AVM/TEMP)*EXP(-FB);
  4590.          XNM := AN*DENM;
  4591.          DENT := XNM/AVM;
  4592.          DEN0 := XNM/AVM0;
  4593.          XNM := DENT - DEN0;
  4594.          DMDR := B1 + DZI*(2.0*B2 + DZI*(3.0*B3 + DZI*(4.0*B4 + DZI*
  4595.                  (5.0*B5 + DZI*6.0*B6))));
  4596.          DNDR := -XMIL*DENM*(F2 + DTDR/TEMP + DMDR/AVM);
  4597.          For J in 1..4 Loop
  4598.             DEN(J) := QO(J)*DEN0;
  4599.          End Loop;
  4600.          DEN(5) := DEN(3);
  4601.          DEN(3) := XNM + XNM;
  4602.          DEN(2) := DEN(2) - XNM;
  4603.          For J in 1..5 Loop
  4604.             H(J) := AVM*AV2/MASS(J);
  4605.             DENB(J) := DEN(J)*TEMP;
  4606.          End Loop;       
  4607. --
  4608.          TB := TEMP;
  4609.          FB := 0.0;
  4610.          F2 := F2/AVM;
  4611.          If IEXIT = 1 Then
  4612.             TEX := TINF;
  4613.             Return;
  4614.          End If;
  4615.       End If;
  4616. --
  4617.       DZX := DZA;
  4618.       If ALT < HEIGHT Then
  4619.          DZX := -DZA;
  4620.       End If;
  4621. --
  4622.       Loop
  4623.          DZZ := 0.5*(ALT - HEIGHT);
  4624.          If DZX*DZX >= DZZ*DZZ Then
  4625.             DZX := DZZ;
  4626.             IEXIT := 1;
  4627.          End If;
  4628.          F0 := F2;
  4629.          For J in 1..2 Loop
  4630.             F1 := F2;
  4631.             HEIGHT := HEIGHT + DZX;
  4632.             RBR := RB/(HKM*HEIGHT + RO);
  4633.             TEMP := TATRFN(TINF,HEIGHT);
  4634.             F2 := GMB*RBR*RBR/TEMP;
  4635.          End Loop;
  4636.          FB := FB + (F0 + 4.0*F1 + F2)*DZX/3.0;
  4637.          RAT := 100.0*TEMP/TINF - 50.0;
  4638.          If RAT <= DZA or HEIGHT <= H1 Then
  4639.             RAT := DZA;
  4640.          End If;
  4641.          If DZZ < 0.0 Then
  4642.             RAT := -RAT;
  4643.          End If;
  4644.          DZX := RAT;
  4645.          Exit When IEXIT /= 0;
  4646.       End Loop;
  4647.       DENT := 0.0;
  4648.       DENM := 0.0;
  4649.       DNDR := 0.0;
  4650.       For J in 1..5 Loop
  4651.          FI := FB*MASS(J);
  4652.          H(J) := 1.0/(F2*MASS(J));
  4653.          DEN(J) := (DENB(J)/TEMP)*EXP(-FI);
  4654.          If J = 4 Then
  4655.             DEN(J) := DEN(J)*((TB/TEMP)**ALPHA);
  4656.          End If;
  4657.          DENT := DENT + DEN(J);
  4658.          DENM := DENM + DEN(J)*MASS(J);
  4659.          DNDR := DNDR - DEN(J)*MASS(J)/H(J);
  4660.       End Loop;
  4661.       AVM := DENM/DENT;
  4662.       DZI := HEIGHT - Z100;
  4663.       AVH := DZI/(FB*AVM);
  4664.       AV2 := 1.0/(AVM*F2);
  4665.       DNDR := AMU*XMIL*(DNDR + DENM*DTDR/TEMP);
  4666.       DENM := DENM*AMU;
  4667.       TEX := TINF;
  4668. --
  4669.       Return;
  4670. --
  4671.       End DENS;
  4672. --
  4673. --
  4674.       Procedure ECALC (TM: in float;
  4675.                        F0E: out float;
  4676.                        HME: out float) is
  4677. --
  4678. --#PURPOSE: ECALC calculates critical frequency and height of E layer.
  4679. --
  4680. --#AUTHOR:  J. Conrad
  4681. --
  4682. --#TYPE:    Computational Procedure
  4683. --
  4684. --#PARAMETER DESCRIPTIONS:
  4685. --IN        TM     = Corrected geomagnetic time (hours)
  4686. --OUT       F0E    = Critical frequency (MHz) for E layer
  4687. --OUT       HME    = Height of maximum electron density for E layer (Km)
  4688. --
  4689. --#CALLED BY:
  4690. --          POLAR
  4691. --
  4692. --#CALLS TO:
  4693. --          'NONE'
  4694. --
  4695. --#TECHNICAL DESCRIPTION:
  4696. --          ECALC calculates E layer atmospheric parameters based on
  4697. --          the revised RADC-POLAR model as obtained from Mission
  4698. --          Research Corp.
  4699. --
  4700.       TOL, AMO, COSARG, DEC, ARG, HA, COSCHI, PHI1, PHI2, PHIA, PHIB,
  4701.          SPMD, SPUP, SPLO, ZSPMD, ZSPUP, ZSPLO, A1, A2, A3, A4, A5, A6, 
  4702.          A7, A8, A, B, C, D, AMP, EMM, EMAXMD, ZMAXMD, F0ES, F0, ALONG,
  4703.          ALT, AE1, AE2: float;
  4704. --
  4705.       Begin
  4706. --
  4707.       TOL := 0.000001;
  4708.       AMO := FLOAT(MIN - 3)*PI3;
  4709.       COSARG := COS(AMO);
  4710.       If GLAT > 89.8 Then
  4711.          GLAT := 89.8;
  4712.       End If;
  4713.       DEC := -0.409*COS(PI/182.5*(FLOAT(NJ)+8.0));
  4714.       ARG := GLAT*RADIANS_PER_DEGREE;
  4715.       HA := GLONG - GMLAT;
  4716.       COSCHI := SIN(DEC)*SIN(ARG) + COS(DEC)*COS(ARG)*
  4717.                                     COS(HA*RADIANS_PER_DEGREE);
  4718.       SECCHI := 1.0/COSCHI;
  4719.       PHI1 := 71.0 - 2.5*PMA*COS(PI12*(TM - 1.0));
  4720.       PHI2 := 78.0 - 2.5*PMA;
  4721.       PHIA := PHI2;
  4722.       If TM < 6.0 or TM > 18.0 Then
  4723.          PHIA := PHI1;
  4724.       End If;
  4725.       PHIB :=  PHIA + 4.0 *(1.0 + 0.25*PMA);
  4726. --
  4727.       Loop
  4728.          If GMLAT >= PHIB Then   --........REGION I VALUES FOLLOW
  4729.             SPMD := 3.9 - 0.1*PMA;
  4730.             SPUP := 7.8 - 0.4*PMA;
  4731.             SPLO := 2.0;
  4732.             Exit;
  4733.          Elsif GMLAT >= PHIA Then  --........REGION II VALUES FOLLOW
  4734.             SPMD := 4.0 + 0.05*PMA;
  4735.             SPUP := 6.6 + 0.2*PMA;
  4736.             SPLO := 2.2 + 0.03*PMA;
  4737.             Exit;
  4738.          Else                      --........REGION III VALUES FOLLOW
  4739.             SPMD := 3.0;
  4740.             SPUP := 5.3;
  4741.             SPLO := 1.6;
  4742.             Exit;
  4743.          End If;
  4744.       End Loop;
  4745. --
  4746.       ZSPMD := 117.0 - 1.13*SPMD;
  4747.       ZSPUP := 117.0 - 1.13*SPUP;
  4748.       ZSPLO := 117.0 - 1.13*SPLO;
  4749. --.....FOES MODEL.....
  4750.       A1 := 3.62 + 0.00596*R;
  4751.       A2 := 0.143 + 0.000567*R;
  4752.       A3 := -0.0041 - 3.9*R*1.0E-05;
  4753.       A4 := -0.00195;
  4754.       A5 := 0.293 + 0.00045*R;
  4755.       A6 := 0.01;
  4756.       A7 := -0.00062 - 0.81*R*1.0E-05;
  4757.       A8 := -0.000668 - 2.5*R*1.0E-06;
  4758.       A := A1 + A2*COSARG;
  4759.       B := A3 + A4*COSARG;
  4760.       C := A5 + A6*COSARG;
  4761.       D := A7 + A8*COSARG;
  4762.       AMP := A + B*GLAT;
  4763.       EMM := C + D*GLAT;
  4764.       EMAXMD := 0.00001;
  4765.       ZMAXMD := 0.00001;
  4766.       F0ES := 0.0;
  4767.       F0 := 0.0;
  4768.       If COSCHI >= TOL Then
  4769.          If COSCHI > 0.00001 Then
  4770.             F0 := AMP*(COSCHI**EMM);
  4771.          End If;
  4772.          ALONG := GLONG;
  4773.          If GLONG > 180.0 Then
  4774.             ALONG := GLONG - 360.0;
  4775.          End If;
  4776.          ALT := UTIME + ALONG/15.0;
  4777.          If ALT < 0.0 Then
  4778.             ALT := 12.0 + ALT;
  4779.          End If;
  4780.          If ALT > 24.0 Then
  4781.             ALT := ALT - 24.0;
  4782.          End If;
  4783.          F0ES := F0*(1.0 - 0.0038*(12.0 - ALT) - 0.00013*AP);
  4784. --.....F0ES HAS NOW BEEN FULLY DEFINED.....
  4785.          EMAXMD := F0ES;
  4786.          ZMAXMD := 100.0 + 20.0*LOG(1.0/COSCHI);
  4787.       End If;
  4788.       AE1 := EMAXMD*EMAXMD;
  4789.       AE2 := SPMD*SPMD;
  4790.       If EMAXMD >= 0.1 Then
  4791.          F0E := SQRT(SQRT(1.5*AE2*AE2 + AE1*AE1));
  4792.       Else
  4793.          F0E := SPMD;
  4794.       End If;
  4795.       HME := (ZMAXMD*AE1 + ZSPMD*AE2)/(AE1 + AE2);
  4796. --
  4797.       Return;
  4798. --
  4799.       End ECALC;
  4800. --
  4801. --
  4802.       Function EDAT return float is
  4803. --
  4804. --#PURPOSE: EDAT calculates elapsed time in days from 1900 January
  4805. --          1, 12 hours, for consistent dating routines CLOCKS and
  4806. --          POLAR.
  4807. --
  4808. --#AUTHOR:  J. Conrad
  4809. --
  4810. --#TYPE:    Computational Procedure
  4811. --
  4812. --#PARAMETER DESCRIPTIONS:
  4813. --          
  4814. --OUT       EDAT   := Elapsed time in days from Jan 1, 1900
  4815. --
  4816. --#CALLED BY:
  4817. --          CLOCKS
  4818. --          POLAR
  4819. --
  4820. --#CALLS TO:
  4821. --          'NONE'
  4822. --
  4823. --#TECHNICAL DESCRIPTION:
  4824. --          EDAT calculates elapsed time in days from 1900 January
  4825. --          1, 12 hours, for consistent dating in routines CLOCKS and
  4826. --          POLAR.  The technique employed is simply to convert all
  4827. --          input time specifications into a common set of units and to
  4828. --          then compute the time difference in days.
  4829. --
  4830.       L1, L2, L3, L4, LY: boolean;
  4831.       MONDAY: array (integer range 1..13) of integer :=
  4832.          (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365);
  4833.       N1, N2, N3, NX: integer;
  4834. --
  4835.       Begin
  4836. --
  4837. --COMPUTE: JD = JULIAN DAY OF DATE
  4838. --         NJ = DAY OF YEAR
  4839. --         ED = ELAPSED TIME IN DAYS FROM January, 1900, 0 Days, 12 Hours 
  4840. --              TO DATE
  4841. --
  4842.       N1 := NYEAR/4;
  4843.       If (NYEAR - 4*N1) = 0 Then
  4844.          L1 := TRUE;
  4845.       Else
  4846.          L1 := FALSE;
  4847.       End If;
  4848.       N2 := NYEAR/100;
  4849.       If (NYEAR - 100*N2) /= 0 Then
  4850.          L2 := TRUE;
  4851.       Else
  4852.          L2 := FALSE;
  4853.       End If;
  4854.       N3 := NYEAR/400;
  4855.       If (NYEAR - 400*N3) = 0 Then
  4856.          L3 := TRUE;
  4857.       Else
  4858.          L3 := FALSE;
  4859.       End If;
  4860.       N1 := Integer(long_integer(365)*long_integer(NYEAR)-693961) + 
  4861.                        N1 - N2 + N3 + MONDAY(MONTH) + NDAY;
  4862.       LY := (L1 and L2) or L3;
  4863.       If MONTH <= 2 Then
  4864.          L4 := TRUE;
  4865.       Else
  4866.          L4 := FALSE;
  4867.       End If;
  4868.       If (LY and L4) Then
  4869.          N1 := N1 - 1;
  4870.       End If;
  4871.       If MONTH = 2 Then
  4872.          L4 := TRUE;
  4873.       Else
  4874.          L4 := FALSE;
  4875.       End If;
  4876. --
  4877.       Loop
  4878.          NX := MONDAY(MONTH + 1) - MONDAY(MONTH);
  4879.          If (LY and L4) Then
  4880.             NX := NX + 1;
  4881.          End If;
  4882.          Exit When NDAY <= NX;
  4883.          MONTH := MONTH + 1;
  4884.          NDAY := NDAY - NX;
  4885.       End Loop;
  4886. --
  4887.       JD := float(N1) + 2.41502E6;
  4888.       NJ := MONDAY(MONTH) + NDAY;
  4889.       If MONTH >= 2 Then
  4890.          L4 := TRUE;
  4891.       Else
  4892.          L4 := FALSE;
  4893.       End If;
  4894.       If (LY and L4) Then
  4895.          NJ := NJ + 1;
  4896.       End If;
  4897.       ED := FLOAT(N1) + 0.5;
  4898.       FD := FLOAT(NHOUR*3600 + MIN*60 + NSEC);
  4899.       FD := FD/86400.0;
  4900.       ED := ED + FD;
  4901. --
  4902.       Return ED;
  4903. --
  4904.       End EDAT;
  4905. --
  4906. --
  4907.       Function EPHT (EDX: float) return float is
  4908. --
  4909. --#PURPOSE: EPHT determines solar orbital parameters.
  4910. --
  4911. --#AUTHOR:  J. Conrad
  4912. --
  4913. --#TYPE:    Computational Function
  4914. --
  4915. --#PARAMETER DESCRIPTIONS:
  4916. --IN        EDX    = Elapsed time in days from Jan. 1, 1900
  4917. --OUT       EPHT   = Ephemerial time
  4918. --
  4919. --#CALLED BY:
  4920. --          CLOCKS
  4921. --          POLAR
  4922. --
  4923. --#CALLS TO:
  4924. --          'NONE'
  4925. --
  4926. --#TECHNICAL DESCRIPTION:
  4927. --          EPHT determines solar orbital parameters.
  4928. --          The technique employed is an extrapolation of the Kepler
  4929. --          orbital state vector as computed for January 1, 1900.
  4930. --
  4931.       PH: array (integer range 1..14) of float;
  4932.       PCON: array (integer range 1..17) of float
  4933.        :=(2.267E-13, 0.98564734, 279.69668, 1.93434E-14, 6.57098224E-2,
  4934.           6.6460655, -1.23E-15, -3.5626E-7, 23.452294, 3.39E-13,
  4935.           4.70684E-5, 281.22084, -9.4E-17, -1.1444E-9, 0.01675104,
  4936.           1.03E-20, 7.0E-20);
  4937.       EDLAST: float := 1.0E6;
  4938.       C15: float := 15.0;
  4939.       C24: float := 24.0;
  4940.       C360: float := 360.0;
  4941.       HIP: float := 3.8197786;
  4942.       E2, E3, UT, O, X, X1, X2, U, PIR, SO, COLOC, PM, SL, CL, E, SM, CM,
  4943.          P, PQ, SE, CE, W, V, Y, Z, RH2, RH1, B: float;
  4944.       K, KK, KKK, NGM, N1, J: integer;
  4945.       KSTEPS: array (integer range 1..5) of integer := (1, 3, 5, 7, 9);
  4946. --
  4947.       Begin
  4948. --
  4949. --
  4950.       If EDX = EDLAST Then
  4951.          Return Q;
  4952.       End If;
  4953.       E2 := EDX*EDX;
  4954.       E3 := E2*EDX;
  4955.       UT := FD*C24;
  4956. --
  4957. --     COMPUTE SOLAR ORBITAL ELEMENTS
  4958. --
  4959.       K := 1;
  4960.       For KKK in 1..5 Loop
  4961.          KK := KSTEPS(KKK);
  4962.          PH(KK) := PCON(K)*E2 + PCON(K + 1)*EDX + PCON(K + 2);
  4963.          K := K + 3;
  4964.       End Loop;
  4965.       PH(5) := PCON(16)*E3 + PH(5);
  4966.       PH(7) := PCON(17)*E3 + PH(7);
  4967.       O := PH(3) + UT;
  4968.       NGM := INTEGER(O/C24);
  4969.       X := FLOAT(NGM*24);
  4970.       O := O - X;
  4971.       If O < 0.0 Then
  4972.          O := O + C24;
  4973.       End If;
  4974.       X1 := PH(1);
  4975.       N1 := INTEGER(X1/C360);
  4976.       X2 := FLOAT(N1*360);
  4977.       X1 := X1 - X2;
  4978.       If X1 < 0.0 Then
  4979.          X1 := X1 + C360;
  4980.       End If;
  4981.       PH(6) := X1;
  4982.       U := PH(7);
  4983.       PH(8) := PH(6) - PH(7);
  4984.       For J in 5..8 Loop
  4985.          PH(J) := PH(J)*RADIANS_PER_DEGREE;
  4986.       End Loop;
  4987.       PIR := PH(5);
  4988.       SO := SIN(PIR);
  4989.       COLOC := COS(PIR);
  4990.       PM := PH(8);
  4991.       SL := SIN(PM);
  4992.       CL := COS(PM);
  4993.       E := PH(9);
  4994. --
  4995. --     COMPUTE TRUE ANOMALY (P),SOLAR LONGITUDE (Q),RIGHT ASCENSION (B),
  4996. --             AND DECLINATION (D).
  4997. --
  4998.       SM := E*SL;
  4999.       CM := E*CL;
  5000.       PH(10) := PH(8) + 2.0*SM + 2.5*SM*CM + 3.0*E*E*SM - (13.0/3.0)*SM*SM*SM;
  5001.       PH(11) := PH(10) + PH(7);
  5002.       P := PH(10)*DEGREES_PER_RADIAN;
  5003.       Q := P + U;
  5004.       If Q >= C360 Then
  5005.          Q := Q - C360;
  5006.       End If;
  5007.       If Q < 0.0 Then
  5008.          Q := Q + C360;
  5009.       End If;
  5010.       PQ := PH(11);
  5011.       SE := SIN(PQ);
  5012.       CE := COS(PQ);
  5013.       W := CE;
  5014.       V := SE;
  5015.       X := W;
  5016.       Y := COLOC*V;
  5017.       Z := SO*V;
  5018.       RH2 := X*X + Y*Y;
  5019.       RH1 := SQRT(RH2);
  5020.       B := ATAN2(Y,X);
  5021.       B := B*HIP;
  5022.       If B < 0.0 Then
  5023.          B := B + C24;
  5024.       End If;
  5025.       SD := Z;
  5026.       CD := RH1;
  5027.       SSL := B - O;
  5028.       SSL := SSL*C15;
  5029.       If SSL < 0.0 Then
  5030.          SSL := SSL + C360;
  5031.       End If;
  5032. --
  5033.       Return Q;
  5034. --
  5035.       End EPHT;
  5036. --
  5037. --
  5038.       Function EXOT (FBAR: float;
  5039.                      F: float;
  5040.                      SOLDEC: float;
  5041.                      GLATR: float;
  5042.                      HA: float) return float is
  5043. --
  5044. --#PURPOSE: EXOT computes exospheric temprature.
  5045. --
  5046. --#AUTHOR:  J. Conrad
  5047. --
  5048. --#TYPE:    Computational Procedure
  5049. --
  5050. --#PARAMETER DESCRIPTIONS:
  5051. --IN        FBAR   = Average daily 10.7 cm. solar flux over 3
  5052. --                   solar rotations
  5053. --IN        F      = 10.7 cm. solar flux the previous day
  5054. --IN        SOLDEC = Solar declination (radians)
  5055. --IN        GLATR  = Geographic latitude (radians)
  5056. --IN        HA     = Solar angle (radians)
  5057. --OUT       EXOT   = Exospheric temperature
  5058. --
  5059. --#CALLED BY:
  5060. --          SCALHT
  5061. --
  5062. --#CALLS TO:
  5063. --          'NONE'
  5064. --
  5065. --#TECHNICAL DESCRIPTION:
  5066. --          EXOT computes exospheric temprature.  The exosphere is that
  5067. --          region above the earth between 550 and 60,000 kilometers.
  5068. --          The technique employed is a curve-fit to tabular data.
  5069. --
  5070.       R, XM, XN, B, P, G, TC1, TC2, TC3, DT1, DT0, HLF, T0, T0R, CSD,
  5071.          SSD, CGL, SGL, PROCOS, PROSIN, SIN2TH, COS2ET, T2, T1, DT3,
  5072.          TAU, COSTAU, XTAU: float;
  5073. --
  5074.       Begin
  5075. --
  5076.       R := 0.30;
  5077.       XM := 1.10;
  5078.       XN := 1.50;
  5079.       B := -0.6487;
  5080.       P := 0.1047;
  5081.       G := 0.7504;
  5082.       TC1 := 379.0;
  5083.       TC2 := 3.24;
  5084.       TC3 := 1.3;
  5085.       DT1 := 28.0;
  5086.       DT0 := 0.03;
  5087.       HLF := 0.5;
  5088.       T0 := TC1 + TC2*FBAR + TC3*(F - FBAR);
  5089.       T0R := T0*R;
  5090.       CSD := COS(SOLDEC);
  5091.       SSD := SIN(SOLDEC);
  5092.       CGL := COS(GLATR);
  5093.       SGL := SIN(GLATR);
  5094.       PROCOS := CSD*CGL;
  5095.       PROSIN := SSD*SGL;
  5096.       SIN2TH := HLF*(1.0 - PROCOS + PROSIN);
  5097.       COS2ET := HLF*(1.0 + PROCOS + PROSIN);
  5098.       T2 := T0R*COS2ET**XM;
  5099.       T1 := T0R*SIN2TH**XM;
  5100.       DT3 := HLF*P*SIN(HA + G);
  5101.       TAU := HLF*(HA + B) + DT3;
  5102.       COSTAU := COS(TAU);
  5103.       XTAU := (COSTAU*COSTAU)**XN;
  5104. --
  5105.       Return (T0 + T1 + (T2 - T1)*XTAU) + (DT1*PMA + DT0*EXP(PMA));
  5106. --
  5107.       End EXOT;
  5108. --
  5109. --
  5110.       Function F0F2FN (GMT: float;
  5111.                        THRL: float) return float is
  5112. --
  5113. --#PURPOSE: F0F2FN determines the critical frequency of the F2 layer.
  5114. --
  5115. --#AUTHOR:  J. Conrad
  5116. --
  5117. --#TYPE:    Computational Function
  5118. --
  5119. --#PARAMETER DESCRIPTIONS:
  5120. --IN        GMT    = Corrected geomagnetic time (hours)
  5121. --IN        THRL   = Local time in hours
  5122. --OUT       F0F2FN = Critical frequency for F2 layer in Mhz.
  5123. --
  5124. --#CALLED BY:
  5125. --          POLAR
  5126. --
  5127. --#CALLS TO:
  5128. --          FOURS
  5129. --          GFUNC
  5130. --
  5131. --#TECHNICAL DESCRIPTION:
  5132. --          F0F2FN determines the critical frequency of the F2 layer.
  5133. --          This routine is based on the RADC-POLAR model of the ionosphere.
  5134. --
  5135.       type ROMANS is array (1..4) of float;
  5136.       type GREEKS is array (1..3) of float;
  5137.       A: ROMANS;
  5138.       AL: array (integer range 1..6) of float
  5139.          :=(0.0, -0.0439, 0.00386, -0.424, 0.739, 0.44);
  5140.       C: array (integer range 1..6) of float
  5141.          :=(4.8, 0.42, 0.6, 1.0, 0.008, -2.6E-5);
  5142.       PHI: GREEKS;
  5143.       CNST: array (integer range 1..2, integer range 1..5) of float
  5144.          :=((10.521, -0.0347, 0.000316, -0.133E-5, 0.142E-8),
  5145.             (0.0963, -0.0101, 0.000198, -0.853E-6, 0.106E-8));
  5146.       ROMAN: array (integer range 1..6) of ROMANS
  5147.          :=((1.368, 0.589, 0.0449, 0.0468), 
  5148.             (0.2784, 0.1263, 0.06422, 0.03222),
  5149.             (0.1149, 0.04306, 0.01186, 0.01739), 
  5150.             (15.57, 0.6066, 0.2784, 0.2574),
  5151.             (-0.1236, 1.112, 0.2338, 0.2562), 
  5152.             (1.511, 1.325, 0.3508, 0.2319));
  5153.       GREEK: array (integer range 1..6) of GREEKS
  5154.          :=((-1.139, 113.0, 41.08), 
  5155.             (-15.25, -5.563, -1.458),
  5156.             (-19.86, 97.99, 51.45), 
  5157.             (176.5, 17.32, 68.02),
  5158.             (1.379, 7.242, 59.09), 
  5159.             (2.221, 102.4, 2.9));
  5160.       PMAVAL: array (integer range 1..6) of float
  5161.          :=(0.3, 1.3, 2.3, 3.3, 4.3, 6.3);
  5162.       RHO: float := 10.0;
  5163.       PSI: float := -105.0;
  5164.       DATE, H, PMAI, G, FIS, B, F0F2N, F0F2D, DELTAX, CFN, CFD, BETA: float;
  5165.       I, II, J: integer;
  5166. --
  5167.       Function FOURS (ROMAN: ROMANS;
  5168.                       GREEK: GREEKS;
  5169.                       FACTOR: float;
  5170.                       VAR: float) return float is
  5171. --
  5172. --#PURPOSE: FOURS calculates a Fourier cosine series.
  5173. --
  5174. --#AUTHOR:  J. Conrad
  5175. --
  5176. --#TYPE:    Computational Function
  5177. --
  5178. --#PARAMETER DESCRIPTIONS:
  5179. --IN        ROMAN  = Fourier parameters
  5180. --IN        GREEK  = Fourier parameters
  5181. --IN        FACTOR = Fourier parameters
  5182. --IN        VAR    = Fourier parameters
  5183. --OUT       FOURS  = Fourier series
  5184. --
  5185. --#CALLED BY:
  5186. --          F0F2FN
  5187. --
  5188. --#CALLS TO:
  5189. --          'NONE'
  5190. --
  5191. --#TECHNICAL DESCRIPTION:
  5192. --          FOURS calculates a Fourier cosine series using the
  5193. --          Fourier parameters passed as calling arguments.
  5194. --
  5195.       N: integer;
  5196.       RESULT: float;
  5197. --
  5198.       Begin
  5199. --
  5200.       RESULT := 0.0;
  5201.       For N in 1..3 Loop
  5202.          RESULT := RESULT + ROMAN(N+1)*COS(FLOAT(N)*FACTOR
  5203.                    *(VAR + GREEK(N)));
  5204.       End Loop;
  5205.       RESULT := ROMAN(1) + 2.0*RESULT;
  5206. --
  5207.       Return RESULT;
  5208. --
  5209.       End FOURS;
  5210. --
  5211. --
  5212.       Function GFUNC (GMLAT: float;
  5213.                       PMAI: float;
  5214.                       DATE: float) return float is
  5215. --
  5216. --#PURPOSE: GFUNC is one of the Fourier fits used in F0F2 calculation.
  5217. --
  5218. --#AUTHOR:  J. Conrad
  5219. --
  5220. --#TYPE:    Numerical Analysis
  5221. --
  5222. --#PARAMETER DESCRIPTIONS:
  5223. --IN        GMLAT  = Geomagnetic latitude
  5224. --IN        PHAI   = Planetary magnetic activity index parameter
  5225. --IN        DATE   = Day of the year (1 - 366)
  5226. --OUT       GFUNC  = Fourier fit used in F0F2 calculation
  5227. --
  5228. --#CALLED BY:
  5229. --          F0F2FN
  5230. --
  5231. --#CALLS TO:
  5232. --          'NONE'
  5233. --
  5234. --#TECHNICAL DESCRIPTION:
  5235. --          This routine is a component of the F0F2FN calculation
  5236. --          based in the ARCON model of the polar ionosphere.
  5237. --          It has no significance by itself.
  5238. --
  5239.       Q: array (integer range 1..5) of float
  5240.          :=(88.5, -2.5, 5.0, 55.0, 2.0);
  5241.       R: array (integer range 1..4) of float
  5242.          :=(3.2, -4.4, -1.0E-5, 1.5E-5);
  5243.       THETA1: float := -182.5;
  5244.       THETA2: float := -90.0;
  5245.       PX, P1, P2, A0LMIN, A0LMAX, X, S: float;
  5246. --
  5247.       Begin
  5248. --
  5249.       PX := COS(PI4365*(DATE - THETA2));
  5250.       P1 := R(1) + R(2)*PX;
  5251.       P2 := R(3) + R(4)*PX;
  5252.       A0LMIN := Q(1) + Q(2)*PMAI + Q(3)
  5253.                 *COS(PI4365*(DATE + THETA1));
  5254.       A0LMAX := Q(4) + Q(5)*COS(PI4365*DATE);
  5255.       X := A0LMIN*A0LMAX;
  5256.       S := A0LMIN + A0LMAX;
  5257.       Return P1 + P2*GMLAT*(3.0*X + GMLAT*(GMLAT - 1.5*S));
  5258. --
  5259.       End GFUNC;
  5260. --
  5261.       Begin
  5262. --
  5263.       DATE := FLOAT(NJ);
  5264.       For I in 1..3 Loop
  5265.          A(I+1) := FOURS (ROMAN(I), GREEK(I), PI2365, DATE);
  5266.          PHI(I) := FOURS (ROMAN(I+3), GREEK(I+3), PI2365, DATE);
  5267.       End Loop;
  5268.       If GLAT > 58.0 Then
  5269.          A(2) := A(2)*(90.0 - GLAT)/32.0;
  5270.       End If;
  5271.       H := 0.0;
  5272.       If GLONG <= 165.0 Then
  5273.          Goto TEN;
  5274.       End If;
  5275.       If GLONG <= 195.0 Then
  5276.          Goto THIRTY_FIVE;
  5277.       End If;
  5278.       I := 1;
  5279.       If GLONG <= 345.0 Then
  5280.          Goto TWENTY;
  5281.       End If;
  5282. <<TEN>>
  5283.       I := 2;
  5284. <<TWENTY>>
  5285.       H := CNST(I,1);
  5286.       For J in 2..5 Loop
  5287.          H := H + CNST(I,J)*DATE**(J-1);
  5288.       End Loop;
  5289. <<THIRTY_FIVE>>
  5290.       For II in 1..7 Loop
  5291.          I := II;
  5292.          Exit When I = 7;
  5293.          Exit When PMA < PMAVAL(I);
  5294.       End Loop;
  5295.       PMAI := FLOAT(I);
  5296.       G := GFUNC (GMLAT, PMAI, DATE);
  5297.       A(1) := AL(1) + AL(2)*GLAT + AL(3)*GLAT*
  5298.            COS( PI2365*2.0*( DATE + PSI))
  5299.            + AL(4)*PMAI + AL(5)*G + AL(6)*H;
  5300.       FIS := C(4) + R*(C(5) + R*C(6));
  5301.       B := C(3)*COS(PI2365*(DATE + RHO));
  5302.       If R < 100.0 Then
  5303.          B := -B;
  5304.       End If;
  5305.       F0F2N := B + FIS*(C(1) + C(2)*FOURS (A, PHI, PI12, 0.0));
  5306.       F0F2D := B + FIS*(C(1) + C(2)*FOURS (A, PHI, PI12, 12.0));
  5307. --
  5308. --.....AURORAL OVAL CORRECTION
  5309. --
  5310.       If GMT < 18.0 and GMT >= 6.0 Then 
  5311.          DELTAX := 80.0 - 1.2*PMA;
  5312.          CFN := 1.0 - 0.175*COS(PI12*(0.0 - PHI(1)))*
  5313.                 (1.0 + COS(PI2365*(DATE + 8.0)));
  5314.          CFD := 1.0 - 0.175*COS(PI12*(12.0 - PHI(1)))*
  5315.                 (1.0 + COS(PI2365*(DATE + 8.0)));
  5316.          F0F2N := F0F2N*(1.0 - (1.0 - CFN)*
  5317.                   EXP(( -(GMLAT - DELTAX )**2)/6.0));
  5318.          F0F2D := F0F2D*(1.0 - (1.0 - CFD)*
  5319.                   EXP(( -( GMLAT - DELTAX )**2)/6.0));
  5320.       Else
  5321.          BETA := 72.0 - 1.8*PMA + 5.1*COS(PI12*(GMT - 1.0));
  5322.          F0F2N := F0F2N +
  5323.                   COS(PI12*GMT)*EXP( -((GMLAT - BETA)**2)/6.0)*PMA/4.0;
  5324.          F0F2D := F0F2D +
  5325.                   COS(PI12*GMT)*EXP( -((GMLAT - BETA)**2)/6.0)*PMA/4.0;
  5326.       End If;
  5327. --
  5328.       Return F0F2N + (F0F2D - F0F2N)*SIN((PI*THRL)/24.0);
  5329. --
  5330.       End F0F2FN;
  5331. --
  5332. --
  5333.       Procedure F1CALC (F0F1: out float;
  5334.                         HMF1: out float) is
  5335. --
  5336. --#PURPOSE: F1CALC determines the critical frequency and height of F1 layer.
  5337. --
  5338. --#AUTHOR:  J. Conrad
  5339. --
  5340. --#TYPE:    Computational Procedure
  5341. --
  5342. --#PARAMETER DESCRIPTIONS:
  5343. --OUT       F0F1   = Critical frequency (MHz)
  5344. --OUT       HMF1   = Height (Km)
  5345. --
  5346. --#CALLED BY:
  5347. --          POLAR
  5348. --
  5349. --#CALLS TO:
  5350. --          CLOCKS
  5351. --
  5352. --#TECHNICAL DESCRIPTION:
  5353. --          F1CALC determines the critical frequency and height of
  5354. --          F1 layer.  This routine is based on the RADC-POLAR model.
  5355. --
  5356.       TOL, A1, UUT, A2, A3, A4, A5, A6, COSCHI, TEMP, CHI, AA, BB, CC,
  5357.          DD, AMP, EMM, F0, ALT, GCOLAT, SL: float;    
  5358.       ID, LLL, MMM, NNN: integer;
  5359. --
  5360.       Begin
  5361. --
  5362.       TOL := 0.000001;
  5363.       A1 := UTIME - 0.2;
  5364.       ID := NDAY;
  5365.       If A1 < 0.0 Then
  5366.          UUT := 24.0 + UTIME;
  5367.          A1 := UUT - 0.2;
  5368.          ID := NDAY - 1;
  5369.       End If;
  5370.       LLL := INTEGER(A1);
  5371.       A2 := FLOAT(LLL);
  5372.       A3 := A1 - A2;
  5373.       A4 := A3*60.0 + TOL;
  5374.       MMM := INTEGER(A4);
  5375.       A5 := FLOAT(MMM);
  5376.       A6 := A4 - A5;
  5377.       NNN := INTEGER(A6*60.0 + TOL);
  5378.       CLOCKS (GLAT,GLONG,COSCHI);
  5379.       F0F1 := 0.0;
  5380.       TEMP := COSCHI;
  5381.       CHI := ACOS(COSCHI);
  5382. --     F0F1 GOES TO ZERO IN 5 DEG IN CHI
  5383.       If COSCHI >= 0.30071 Then
  5384.          If COSCHI <= 0.38268 Then
  5385.             COSCHI := 0.38268;
  5386.          End If;
  5387.          AA := 4.13 + 0.0111*R;
  5388.          BB := 0.00057 - 0.000044*R;
  5389.          CC := 0.106 + 0.000083*R;
  5390.          DD := (2.23*1.0E-06)*R + 0.0007714;
  5391.          AMP := AA + BB*GLAT;
  5392.          EMM := CC + DD*GLAT;
  5393.          F0 := AMP*(COSCHI**EMM);
  5394.          ALT := UTIME + GLONG/15.0;
  5395.          If ALT < 0.0 Then
  5396.             ALT := 12.0 + ALT;
  5397.          End If;
  5398.          If ALT > 24.0 Then 
  5399.             ALT := ALT - 24.0;
  5400.          End If;
  5401.          F0F1 := F0*(1.0 - 0.005*(12.0 - ALT) - 0.0011*AP);
  5402.          If CHI >= 1.17810 Then
  5403.             F0F1 := F0F1*(1.265366 - CHI)/0.087266;
  5404.          End If;
  5405.          COSCHI := TEMP;
  5406.       End If;
  5407.       GCOLAT := 90.0 - GLAT;
  5408.       If F0F1 >= 0.1 Then
  5409.          SL := LOG(1.0/COSCHI);
  5410.          HMF1 := 156.0 + 0.15*R + 45.0*SL;
  5411.          Return;
  5412.       End If;
  5413.       F0F1 := 0.0;
  5414.       HMF1 := 0.0;
  5415. --
  5416.       Return;
  5417. --
  5418.       End F1CALC;
  5419. --
  5420. --
  5421.       Procedure FETCH (XP: in float;
  5422.                        YP: in float;
  5423.                        FF: out float;
  5424.                        GG: out float) is
  5425. --
  5426. --#PURPOSE: FETCH determines geomagnetic coordinates given geographic.
  5427. --
  5428. --#AUTHOR:  J. Conrad
  5429. --
  5430. --#TYPE:    Tabular Procedure
  5431. --
  5432. --#PARAMETER DESCRIPTIONS:
  5433. --IN        XP     = Geographic latitude (degrees north)
  5434. --IN        YP     = Geographic longitude (degrees east)
  5435. --OUT       FF     = Corrected geomagnetic latitude (degrees north)
  5436. --OUT       GG     = Corrected geomagnetic longitude (degrees east)
  5437. --
  5438. --#CALLED BY:
  5439. --          CGMCS
  5440. --
  5441. --#CALLS TO:
  5442. --          TABINT
  5443. --
  5444. --#TECHNICAL DESCRIPTION:
  5445. --          FETCH looks up geomagnetic parameters using tables.
  5446. --
  5447.       XX, YY, DX, DY, DZ, FX, GX, FY, GY, FZ, GZ: float;  
  5448.       I, J: integer;
  5449. --
  5450.       Begin
  5451. --
  5452.       XX := XP;
  5453.       YY := YP;
  5454.       DX := XX*0.5;
  5455.       I := INTEGER(DX);
  5456.       DX := DX - FLOAT(I);
  5457.       I := I + 1;
  5458.       DY := YY*0.2;
  5459.       J := INTEGER(DY);
  5460.       DY := DY - FLOAT(J);
  5461.       J := J + 1;
  5462.       DZ := DX*DY;
  5463.       If J <= 0 Then
  5464.          J := -J;
  5465.       End If;
  5466.       FF := TABINT(1, I, J);
  5467.       GG := TABINT(2, I, J);
  5468.       FX := TABINT(1, I + 1, J) - FF;
  5469.       GX := TABINT(2, I + 1, J) - GG;
  5470.       FY := TABINT(1, I, J + 1) - FF;
  5471.       GY := TABINT(2, I, J + 1) - GG;
  5472.       FZ := TABINT(1, I + 1, J + 1) - FF - FX - FY;
  5473.       GZ := TABINT(2, I + 1, J + 1) - GG - GX - GY;
  5474. --
  5475. --     MODIFY PATHOLOGICAL CASES
  5476. --
  5477.       If J = 23 Then
  5478.          Goto ZERO;
  5479.       End If;
  5480.       If J = 57 Then
  5481.          Goto THIRTY;
  5482.       End If;
  5483.       Goto SIXTY;
  5484. <<ZERO>>
  5485.       If I-85 < 0 Then
  5486.          Goto SIXTY;
  5487.       Elsif I-85 = 0 Then
  5488.          Goto TEN;
  5489.       Else 
  5490.          Goto TWENTY;
  5491.       End If;
  5492. <<TEN>>
  5493.       GZ := GZ - 360.0;
  5494.       Goto SIXTY;
  5495. <<TWENTY>>
  5496.       GY := GY - 360.0;
  5497.       Goto SIXTY;
  5498. <<THIRTY>>
  5499.       If I-6 < 0 Then
  5500.          Goto SIXTY;
  5501.       Elsif I-6 = 0 Then
  5502.          Goto FORTY;
  5503.       Else
  5504.          Goto FIFTY;
  5505.       End If;
  5506. <<FORTY>>
  5507.       GZ := GZ + 360.0;
  5508.       Goto SIXTY;
  5509. <<FIFTY>>
  5510.       GY := GY + 360.0;
  5511. <<SIXTY>>
  5512.       If I = 1 Then
  5513.          FY := DX*FZ;
  5514.          GY := DX*GZ;
  5515.       End If;
  5516.       FF := FF + FX*DX + FY*DY + FZ*DZ;
  5517.       GG := GG + GX*DX + GY*DY + GZ*DZ;
  5518. --
  5519.       Return;
  5520. --
  5521.       End FETCH;
  5522. --
  5523. --
  5524.       Function HMF2FN (TIME: float) return float is
  5525. --
  5526. --#PURPOSE: HMF2FN determines the height of the maximum electron density
  5527. --          of the F2 layer.
  5528. --
  5529. --#AUTHOR:  J. Conrad
  5530. --
  5531. --#TYPE:    Computational Function
  5532. --
  5533. --#PARAMETER DESCRIPTIONS:
  5534. --IN        TIME   = Local time (hours)
  5535. --OUT       HMF2FN = Height of F2 layer (Km)
  5536. --
  5537. --#CALLED BY:
  5538. --          POLAR
  5539. --
  5540. --#CALLS TO:
  5541. --          SCALHT
  5542. --
  5543. --#TECHNICAL DESCRIPTION:
  5544. --          HMF2FN computes the height of the F2 layer in terms of the
  5545. --          maximum electron density.  This routine is based on the
  5546. --          RADC-POLAR model.
  5547. --
  5548.       CSSZ: array (integer range 1..3) of float :=(-0.2, 0.052, 0.208);
  5549.       ZACONS: array (integer range 1..5) of float;
  5550.       I: integer;
  5551.       GLATR, GMLATR, DATE, DEC, SDEC, CDEC, SAT, CAT, TP, AA, H12, H24, 
  5552.          BTA1, BTA2, SP1, TATR, SMULT: float;
  5553. --
  5554.       Begin
  5555. --
  5556. --  GLATR  = GEOGRAPHIC LATITUDE IN RADIANS. = GLAT  IN DEG.
  5557. --  GMLATR = CORRECTED GEOMAGNETIC LATITUDE IN RADIANS. = GMLAT IN DEG.
  5558.       GLATR  := GLAT*RADIANS_PER_DEGREE;
  5559.       GMLATR  := GMLAT*RADIANS_PER_DEGREE;
  5560. --  NJ := DAY OF YEAR
  5561. --  CSSZ IS COS VECTOR FOR ANGLES   102,87,78 DEGREES
  5562. --
  5563.       DATE := FLOAT(NJ);
  5564.       For I in 1..5 Loop
  5565.          ZACONS(I) := 0.0;
  5566.       End Loop;
  5567.       DEC := - 0.409*COS(PI/182.5*FLOAT(NJ + 8));
  5568.       SDEC := SIN(DEC);
  5569.       CDEC := COS(DEC);
  5570.       SAT := SIN(GLATR);
  5571.       CAT := COS(GLATR);
  5572. --
  5573. --  COS OF ZENITH ANGLE AT NOON LOCAL TIME
  5574.       ZACONS(1) := SDEC*SAT + CDEC*CAT;
  5575. --  COS OF ZENITH ANGLE AT MIDNIGHT LOCAL TIME
  5576.       ZACONS(2) := SDEC*SAT - CDEC*CAT;
  5577.       For I in 1..3 Loop
  5578.          TP := (CSSZ(I) - SDEC*SAT)/(CDEC*CAT);
  5579.          TP := - TP;
  5580.          If TP < - 1.0 Then
  5581.             TP := - 1.0;
  5582.          End If;
  5583.          If TP > 1.0 Then
  5584.             TP := 1.0;
  5585.          End If;
  5586.          TP := ACOS(TP);
  5587. --
  5588. --  TIME AT WHICH COS OF ZENITH ANGLE IS CSSZ(I)
  5589.          ZACONS(2 + I) := 12.0*TP/PI;
  5590.       End Loop;
  5591.       AA := 0.55*(GMLAT - 45.0);
  5592.       H12 := (197.0 + 0.79*R - 0.0011*R**2 + AA);
  5593.       H24 := (297.0 + 0.603*R + AA);
  5594. --  H24 := (297.0 + 0.603*R - AA)
  5595.       If ZACONS(2) >= CSSZ(1) Then  --  CASE IA
  5596.          Return H12;
  5597.       End If;
  5598.       If ZACONS(1) <= CSSZ(1) Then  --  CASE IB
  5599.          SCALHT(SOLFX,SOLFX,DEC,GLATR,0.524,1000.0,TATR,SMULT);
  5600.          BTA1 := GMLAT;
  5601.          BTA2 := 67.0 - 2.0*PMA;
  5602.          Return H24 + 0.08*TATR*EXP(-(BTA1 - BTA2)**2/20.0);
  5603.       End If;
  5604. --
  5605. --     CASE II - IV TIME LT T(102DEG)
  5606.       If TIME < ZACONS(3) Then      -- Actually CASE IB again
  5607.          SCALHT(SOLFX,SOLFX,DEC,GLATR,0.524,1000.0,TATR,SMULT);
  5608.          BTA1 := GMLAT;
  5609.          BTA2 := 67.0 - 2.0*PMA;
  5610.          Return H24 + 0.08*TATR*EXP(-(BTA1 - BTA2)**2/20.0);
  5611.       End If;
  5612. --
  5613.       If ZACONS(1) <= CSSZ(2) Then  --    CASE II TIME GE T(102DEG)
  5614.          If TIME <= 12.0 Then       --    CASE II  T(102DEG) LT TIME LE 12.0
  5615.             SP1 := (H24 - H12)/(12.0 - ZACONS(3));
  5616.             Return H24 - SP1*(TIME - ZACONS(3));
  5617.          Else                       --     CASE II   12.0 LT TIME LE 24.0
  5618.             SP1 := (H24 - H12)/12.0;
  5619.             Return H12 + SP1*(TIME - 12.0);
  5620.          End If;
  5621.       End If;
  5622. --  CASES III AND IV   T(102DEG) LE TIME
  5623.       If ZACONS(1) >= CSSZ(3) Then   --     REDIFINE H12 FOR CASE IV
  5624.          H12 := H12 - (H24 - H12)*(12.0 - ZACONS(5))/12.0;
  5625.       End If;
  5626. --  CASES III AND IV
  5627.       If TIME <= ZACONS(4) Then      
  5628. --          CASES III AND IV  T(102DEG) LT TIME LE T(87DEG)
  5629.          SP1 := (H24 - H12)/(ZACONS(4) - ZACONS(3));
  5630.          Return H24 - SP1*(TIME - ZACONS(3));
  5631.       End If;
  5632.       If TIME <= ZACONS(5) Then
  5633. --          CASES III AND IV   T(87DEG) LT TIME LE T(78DEG)
  5634.          Return H12;
  5635.       End If;
  5636. --  CASES III AND IV   T(78DEG) LT TIME LE 24.0
  5637.       SP1 := (H24 - H12)/(24.0 - ZACONS(5));
  5638.       Return H12 + SP1*(TIME - ZACONS(5));
  5639. --
  5640.       End HMF2FN;
  5641. --
  5642. --
  5643.       Procedure IONDAT (IENTER: in integer;
  5644.                         NHOPS: in integer;
  5645.                         EHT: out float;
  5646.                         FHT: out float;
  5647.                         F0EMAX: out float;
  5648.                         F0EMIN: out float;
  5649.                         F0FMAX: out float;
  5650.                         F0FMIN: out float) is
  5651. --
  5652. --#PURPOSE: IONDAT calculates ionospheric layer data relative to the
  5653. --          number of hops of an HF signal.
  5654. --
  5655. --#AUTHOR:  J. Conrad
  5656. --
  5657. --#TYPE:    Numerical Analysis
  5658. --
  5659. --#PARAMETER DESCRIPTIONS:
  5660. --IN        IENTER = Entry code.
  5661. --IN        NHOPS  = Number of hops.
  5662. --OUT       EHT    = Average E-layer height in kilometers.
  5663. --OUT       FHT    = Average F-layer height in kilometers.
  5664. --OUT       FOEMAX = Maximum frequency for E-layer hops in MHz/secant.
  5665. --OUT       FOEMIN = Minimum frequency for E-layer hops in MHz/secant.
  5666. --OUT       FOFMAX = Maximum frequency for F-layer hops in MHz/secant.
  5667. --OUT       FOFMIN = Minimum frequency for F-layer hops in MHz/secant.
  5668. --
  5669. --#CALLED BY:
  5670. --          HFNORM
  5671. --
  5672. --#CALLS TO:
  5673. --          AMBION
  5674. --          LOCGRB
  5675. --          LOCNEW
  5676. --          POLAR
  5677. --
  5678. --#TECHNICAL DESCRIPTION:
  5679. --     IONDAT calculates the heights of the various layers of the
  5680. --     ionosphere. Specifically, it computes the average, minimum and
  5681. --     maximum heights of the E-layer and F-layer for each of the possibl
  5682. --     path/hop geometries. This routine is basically a data distribution
  5683. --     routine with the majority of the actual ionospheric computations
  5684. --     being performed in Procedures AMBION and POLAR.
  5685. --
  5686.       ISTRTM: array (integer range 1..5) of integer := (1, 2, 4, 7, 11);
  5687.       IENDM: array (integer range 1..5) of integer := (1, 3, 6, 10, 15);
  5688.       PLAT, PLON, PTIME: array (integer range 1..15) of float;
  5689. --      F0HT: array (integer range 1..15, integer range 1..4) of float;
  5690. --
  5691. --  F0HT CONTAINS THE FOLLOWING
  5692. --     COL 1 := F0E
  5693. --     COL 2 := HTE
  5694. --     COL 3 := F0F2
  5695. --     COL 4 := HTF2
  5696. --
  5697. --  CDATA CONTAINS THE FOLLOWING
  5698. --     COL 1 := #
  5699. --     COL 2 := #
  5700. --     COL 3 := #
  5701. --     COL 4 := #
  5702. --     COL 5 := #
  5703. --     COL 6 := #
  5704. --
  5705.       TMO, HOPS, RNGINC, RNG, TRSEC, TIMEX, YLAT, YLON, PHI, EMAX, 
  5706.          HEMAX, THICKE, F1MAX, HF1MAX, THIKF1, F2MAX, HF2MAX, THIKF2, FOE,
  5707.          HME, F0F1, HMF1, F0F2, HMF2, HE, HF, AVEHE, AVEHF, FMINE, FMINF,
  5708.          FMAXE, FMAXF, F0E: float;
  5709.       ISTRT, IEND, I, J, NMNTH, K: integer;
  5710. --
  5711.       Begin
  5712.  
  5713.       R := float(AVERAGE_SUN_SPOT_NUMBER);
  5714.       PMA := 2.0;
  5715.       NMNTH := MONTH;
  5716.       TMO := FLOAT(MONTH);
  5717.       HOPS := FLOAT(NHOPS);
  5718.       ISTRT := ISTRTM(NHOPS);
  5719.       IEND := IENDM(NHOPS);
  5720.       If IENTER <= 1 Then
  5721.          For I in 1..15 Loop
  5722.             For J in 1..4 Loop
  5723.                F0HT(I,J) := 0.0;
  5724.             End Loop;
  5725.          End Loop;
  5726.       End If;
  5727.       If F0HT(ISTRT, 1) > 0.0 Then
  5728.          EHT := CDATA(NHOPS,1);
  5729.          FHT := CDATA(NHOPS,2);
  5730.          F0FMAX := CDATA(NHOPS,3);
  5731.          F0FMIN := CDATA(NHOPS,4);
  5732.          F0EMAX := CDATA(NHOPS,5);
  5733.          F0EMIN := CDATA(NHOPS,6);
  5734.          Return;
  5735.       End If;
  5736. --
  5737.       RNGINC := DPATH/HOPS;
  5738.       RNG := 0.0;
  5739.       TRSEC := (REFERENCE_TIME - (REFERENCE_TIME/100.0)*40.0)*60.0;
  5740.       TIMEX := (TIMSEC + TRSEC)/3600.0;
  5741. --
  5742.       For J in ISTRT..IEND Loop
  5743.          RNG := RNG + RNGINC;
  5744.          If J <= ISTRT Then
  5745.             RNG := RNGINC*0.5;
  5746.          End If;
  5747.          NODELOC.LOCNEW (TLAT, TLON, BRNG1, RNG, YLAT, YLON);
  5748.          If YLON < 0.0 Then
  5749.             YLON := YLON + 360.0;
  5750.          End If;
  5751.          PLAT(J) := YLAT;
  5752.          PLON(J) := YLON;
  5753.          PTIME(J) := TIMEX + YLON*0.0666666;
  5754.          Loop
  5755.             Exit When PTIME(J) >= 0.0 and PTIME(J) <= 24.0;
  5756.             If PTIME(J) > 24.0 Then
  5757.                PTIME(J) := PTIME(J) - 24.0;
  5758.             End If;
  5759.             If PTIME(J) < 0.0 Then
  5760.                PTIME(J) := PTIME(J) + 24.0;
  5761.             End If;
  5762.          End Loop;
  5763.       End Loop;
  5764.       TMO := FLOAT(MONTH);
  5765.       For K in ISTRT..IEND Loop
  5766.          If F0HT(1,1) >= 1.0 Then
  5767.             If  K = 5 Then 
  5768.                F0HT(5,1) := F0HT(1,1);
  5769.                F0HT(5,2) := F0HT(1,2);
  5770.                F0HT(5,3) := F0HT(1,3);
  5771.                F0HT(5,4) := F0HT(1,4);
  5772.             Elsif K = 13 Then
  5773.                F0HT(13,1) := F0HT(1,1);
  5774.                F0HT(13,2) := F0HT(1,2);
  5775.                F0HT(13,3) := F0HT(1,3);
  5776.                F0HT(13,4) := F0HT(1,4);
  5777.             End If;
  5778.          Elsif ABS(PLAT(K)) <= 60.0 Then
  5779.             PHI := PTIME(K)*0.04166666*TWOPI;
  5780.             AMBION (PLAT(K), PLON(K), PHI, TMO, R,
  5781.                     EMAX, HEMAX, THICKE,
  5782.                     F1MAX, HF1MAX, THIKF1,
  5783.                     F2MAX, HF2MAX, THIKF2);
  5784.             F0HT(K,1) := 8977.9*SQRT(EMAX)*1.0E-6;
  5785.             F0HT(K,3) := 8977.9*SQRT(F2MAX)*1.0E-6;
  5786.             F0HT(K,2) := HEMAX*1.0E-5;
  5787.             F0HT(K,4) := HF2MAX*1.0E-5;
  5788.          Else
  5789.             NHOUR := INTEGER(PTIME(K));
  5790.             MIN := INTEGER(PTIME(K) - FLOAT(NHOUR))*60;
  5791.             POLAR(PLAT(K), PLON(K), F0E, HME, F0F1, HMF1, F0F2, HMF2);
  5792.             F0HT(K,1) := F0E; 
  5793.             F0HT(K,2) := HME;
  5794.             F0HT(K,3) := F0F2;
  5795.             F0HT(K,4) := HMF2;
  5796.          End If;
  5797.       End Loop;
  5798.       HE := 0.0;
  5799.       HF := 0.0;
  5800.       For K in ISTRT..IEND loop
  5801.          HE := F0HT(K,2) + HE;
  5802.          HF := F0HT(K,4) + HF;
  5803.       End Loop;
  5804.       AVEHE := HE/HOPS;
  5805.       AVEHF := HF/HOPS;
  5806.       FMINE := 1.0E20;
  5807.       FMINF := 1.0E20;
  5808.       FMAXE := 0.0;
  5809.       FMAXF := 0.0;
  5810. --
  5811.       For K in ISTRT..IEND Loop
  5812.          FMINE := AMIN1(FMINE, F0HT(K,1));
  5813.          FMAXE := AMAX1(FMAXE, F0HT(K,1));
  5814.          FMINF := AMIN1(FMINF, F0HT(K,3));
  5815.          FMAXF := AMAX1(FMAXF, F0HT(K,3));
  5816.       End Loop;
  5817.       CDATA(NHOPS,1) := AVEHE;
  5818.       CDATA(NHOPS,2) := AVEHF;
  5819.       CDATA(NHOPS,3) := FMAXF;
  5820.       CDATA(NHOPS,4) := FMINF;
  5821.       CDATA(NHOPS,5) := FMAXE;
  5822.       CDATA(NHOPS,6) := FMINE;
  5823.       EHT := CDATA(NHOPS,1);
  5824.       FHT := CDATA(NHOPS,2);
  5825.       F0FMAX := CDATA(NHOPS,3);
  5826.       F0FMIN := CDATA(NHOPS,4);
  5827.       F0EMAX := CDATA(NHOPS,5);
  5828.       F0EMIN := CDATA(NHOPS,6);
  5829. --
  5830.       Return;
  5831. --
  5832.       End IONDAT;
  5833. --
  5834. --
  5835.       Procedure IONFT1 (ZMAX: out float;
  5836.                         EMAX: out float;
  5837.                         THICK: out float;
  5838.                         LAYER: in integer;
  5839.                         RZUR: in float;
  5840.                         PHI: in float;
  5841.                         TMO: in float;
  5842.                         RLT: in float;
  5843.                         RLTM: in float;
  5844.                         RLGM: in float;
  5845.                         DIP: in float) is
  5846. --
  5847. --#PURPOSE: IONFT1 supplies inonospheric parameters for a single
  5848. --           ambient layer using a parabolic fit.
  5849. --
  5850. --#AUTHOR:  J. Conrad
  5851. --
  5852. --#TYPE:    Numerical Analysis
  5853. --
  5854. --#PARAMETER DESCRIPTIONS:
  5855. --OUT       ZMAX   = Height of maximum elctron density
  5856. --OUT       EMAX   = Maximum electron density
  5857. --OUT       THICK  = Thickness of layer
  5858. --IN        LAYER  = layer of ionosphere(E=1,F1=2,F2=3)
  5859. --IN        RZUR   = Smothed Zurich Sunspot number
  5860. --IN        PHI    = Time of day( 0 - 2PI, 1 day = 2PI)
  5861. --IN        TMO    = Month of year,starting December 15 (0 - 12)
  5862. --                   (eg. June 1 := 6.5 )
  5863. --IN        RLT    = Latitude (geographic)
  5864. --IN        RLTM   = Geomagnetic latitude
  5865. --IN        RLGM   = Geomagnetic longitude
  5866. --IN        DIP    = Dip angle
  5867. --
  5868. --#CALLED BY:
  5869. --          AMBION
  5870. --
  5871. --#CALLS TO:
  5872. --          TVARF2
  5873. --          TVEF1
  5874. --
  5875. --#TECHNICAL DESCRIPTION:
  5876. --          IONFT1 supplies inonospheric parameters for a single
  5877. --           ambient layer using a parabolic fit.  This routine is
  5878. --           based on Mission Research Corp.'s FORTRAN program HFNET.
  5879. --
  5880.       ZMAXE, HMAXE, ZMAX1, HMAX1, SDEC, DEC, DELP, SEASN, R, XLAM, CLTM,
  5881.          SLTM, ZALF, ZBA, ZBAR, Z, H2, ZP, RATIO, PHIT: float;
  5882. --
  5883.       Begin
  5884.  
  5885.       ZMAXE := 110.0;
  5886.       HMAXE := 10.0;
  5887.       ZMAX1 := 180.0;
  5888.       HMAX1 := 34.0;
  5889.       PHIT := PHI;
  5890.       SDEC := 0.39795*SIN(PI6*(TMO - 3.167));
  5891.       DEC := ASIN(SDEC);
  5892.       DELP := ABS(ABS(RLT) - HALFPI);
  5893.       If DELP <= 1.0E-03 Then
  5894.          SEASN := RLT*DEC;
  5895.          If SEASN < 0.0 Then
  5896.             PHIT := 0.0;
  5897.          Else
  5898.             PHIT := PI;
  5899.          End If;
  5900.       End If;
  5901.       R := RZUR/100.0;
  5902. --
  5903. --CHECK TO SEE IF E- LAYER IS DESIRED, LAYER = 1
  5904.       If LAYER = 1 Then
  5905.          EMAX := 1.36E5*TVEF1(1.15 ,0.0, 0.4, 2.0, RLT, R, PHIT, DEC);
  5906.          ZMAX := ZMAXE;
  5907.          THICK := 1.9626*HMAXE;
  5908.          Return;
  5909.       End If;
  5910. --
  5911. --NOW TRY FOR THE F1 LAYER.  LAYER = 2
  5912.       If LAYER = 2 Then
  5913.          XLAM := 1.0 + 0.5*LOG(1.0 + 30.0*R);
  5914.          EMAX := 2.44E5*TVEF1(1.24, 0.25, 0.25, XLAM, RLT, R, PHIT, DEC);
  5915.          ZMAX := ZMAX1;
  5916.          THICK := 1.9626*HMAX1;
  5917.          Return;
  5918.       End If;
  5919. --
  5920. --ALL ELSE FAILING, IT MUST BE THE F3 LAYER.
  5921.       CLTM := COS(RLTM);
  5922.       SLTM := SIN(RLTM);
  5923.       ZALF := -4.5*ABS(RLTM) - PI;
  5924.       ZBA := 240.0 + 10.0*CLTM*COS(PI*(TMO/3.0 - 1.5));
  5925.       ZBAR := ZBA + R*(75.0 + 83.0*CLTM*SDEC*SLTM);
  5926.       ZMAX := ZBAR + 30.0*COS(PHIT + ZALF);
  5927.       EMAX := 0.66E5*TVARF2(RLTM, RLGM, DIP, R, PHIT, TMO, DEC, CLTM, SLTM);
  5928.       Z := ZMAX - 100.0;
  5929.       H2 := 0.2*Z + 40.0;
  5930.       ZP := -100.0/H2;
  5931.       RATIO := EXP(1.0 - ZP - EXP(-ZP));
  5932.       THICK := 100.0/SQRT(1.0 - RATIO);
  5933. --
  5934.       Return;
  5935. --
  5936.       End IONFT1;
  5937. --
  5938. --
  5939.       Procedure MAGNET (H: in float;
  5940.                         COLAT: in float;
  5941.                         ELONG: in float;
  5942.                         BFELD: out float;
  5943.                         SINDIP: out float;
  5944.                         SINDEC: out float;
  5945.                         COSDEC: out float;
  5946.                         COSMAG: out float;
  5947.                         ELONMG: out float) is
  5948. --
  5949. --#PURPOSE: MAGNET calculates the geomagnetic coordinates given the
  5950. --          geographic latitude, longitude and altitude of a point.
  5951. --
  5952. --#AUTHOR:  J. Conrad
  5953. --
  5954. --#TYPE:    Numerical Analysis
  5955. --
  5956. --#PARAMETER DESCRIPTIONS:
  5957. --IN        H      = Height, Km.
  5958. --IN        COLAT  = Colatitude, radians
  5959. --IN        ELONG  = Geographic east longitude, radians
  5960. --OUT       BFELD  = Magnetic field of Earth
  5961. --OUT       SINDIP = Sine of dip angle
  5962. --OUT       SINDEC = Sine of declination
  5963. --OUT       COSDEC = Cosine of declination
  5964. --OUT       COSMAG = Cosine of magnetic longitude
  5965. --OUT       ELOMNG = East geomagnetic longitude, radians
  5966. --
  5967. --#CALLED BY:
  5968. --          AMBION
  5969. --
  5970. --#CALLS TO:
  5971. --          'NONE'
  5972. --
  5973. --#TECHNICAL DESCRIPTION:
  5974. --          MAGNET calculates the geomagnetic coordinates given the
  5975. --          geographic latitude, longitude and altitude of a point.
  5976. --          This routine is based on Mission Research Corp.'s FORTRAN
  5977. --          program HFNET.
  5978. --
  5979.       SINC, COSC, SINEW, COSEW, ROOT, SINMAG: float;
  5980. --
  5981.       Begin
  5982. --
  5983.       SINC := SIN(COLAT);
  5984.       COSC := COS(COLAT);
  5985.       SINEW := SIN(ELONG + WMERID);
  5986.       COSEW := COS(ELONG + WMERID);
  5987.       COSMAG := COSC*SINPOL + SINC*COSPOL*COSEW;
  5988.       ROOT := SQRT(1.0 + 3.0*COSMAG**2);
  5989.       SINMAG := SQRT(1.0 - COSMAG**2);
  5990.       BFELD := DIPOLE*(RADIUS_OF_EARTH_IN_KM/
  5991.                       (RADIUS_OF_EARTH_IN_KM + H))**3*ROOT;
  5992.       SINDIP := 2.0*COSMAG/ROOT;
  5993.       If ABS(SINDIP) < 0.1 Then
  5994.          SINDIP := SIGN(0.1, SINDIP);
  5995.       End If;
  5996.       SINDEC := -COSPOL*SINEW/SINMAG;
  5997.       COSDEC := (SINPOL - COSC*COSMAG)/(SINC*SINMAG);
  5998.       ELONMG:=ATAN2(SINC*SINEW, SINC*SINPOL*COSEW-COSC*COSPOL);
  5999. --
  6000.       Return;
  6001. --
  6002.       End MAGNET;
  6003. --
  6004. --
  6005.       Procedure POLAR (PLAT: in float;
  6006.                        PLONG: in float;
  6007.                        F0E: out float;
  6008.                        HME: out float;
  6009.                        F0F1: out float;
  6010.                        HMF1: out float;
  6011.                        F0F2: out float;
  6012.                        HMF2: out float) is
  6013. --
  6014. --#PURPOSE: POLAR calculates ambient ionosphere parameters at high
  6015. --          latitudes.
  6016. --
  6017. --#AUTHOR:  J. Conrad
  6018. --
  6019. --#TYPE:    Computational Procedure
  6020. --
  6021. --#PARAMETER DESCRIPTIONS:
  6022. --IN        PLAT   = North latitude (degrees)
  6023. --IN        PLONG  = East longitude (degrees)
  6024. --OUT       F0E    = Critical frequency for E layer (MHz)
  6025. --OUT       HME    = Height of maximum electron density for E layer (Km)
  6026. --OUT       F0F1   = Critical frequency for F1 layer (MHz)
  6027. --OUT       HMF1   = Height of maximum electron density for F1 layer (Km)
  6028. --OUT       F0F2   = Critical frequency for F2 layer (MHz)
  6029. --OUT       HMF2   = Height of maximum electron density for F2 layer (Km)
  6030. --
  6031. --#CALLED BY:
  6032. --          IONDAT
  6033. --
  6034. --#CALLS TO:
  6035. --          CGMCS
  6036. --          ECALC
  6037. --          EDAT
  6038. --          EPHT
  6039. --          F0F2FN
  6040. --          F1CALC
  6041. --          HMF2FN
  6042. --
  6043. --#TECHNICAL DESCRIPTION:
  6044. --          POLAR calculates ambient ionosphere parameters at high
  6045. --          latitudes.  This routine is based on the RADC-POLAR model.
  6046. --
  6047.       SEC, XMIN, HOUR, THRL, RSX, EDATE, GMT: float;
  6048. --
  6049.       Begin
  6050. --
  6051.       R := FLOAT(AVERAGE_SUN_SPOT_NUMBER);
  6052.       GLAT := PLAT;
  6053.       GLONG := PLONG;
  6054.       SEC := FLOAT(NSEC);
  6055.       XMIN := FLOAT(MIN);
  6056.       HOUR := FLOAT(NHOUR);
  6057.       THRL := HOUR + XMIN/60.0 + SEC/3600.0;
  6058. --
  6059. --.....UNIVERSAL TIME
  6060. --
  6061.       GLONG := AMOD(GLONG, 360.0);
  6062.       If GLONG < 0.0 Then
  6063.          GLONG := GLONG + 360.0;
  6064.       End If;
  6065.       UTIME := HOUR + ((XMIN + SEC/60.0) - GLONG/15.0);
  6066.       If UTIME < 0.0 Then
  6067.          UTIME := UTIME + 24.0;
  6068.       End If;
  6069. --
  6070. --COMPUTE SOLAR FLUX
  6071.       RSX := R;
  6072.       If RSX <= 8.0 Then
  6073.          RSX := 8.00001;
  6074.       End If;
  6075.       SOLFX := 69.0 + 0.38*(RSX - 8.0)**1.17;
  6076.       AP := 10.0**(0.25*PMA + 0.4);
  6077. --
  6078.       EDATE := EDAT;
  6079.       EDATE := EPHT(EDATE);
  6080.       CGMCS;
  6081.       GMT := GMLONG/15.0 + 12.0;
  6082.       GMT := AMOD(GMT, 24.0);
  6083.       IF GMT < 0.0 Then
  6084.          GMT := GMT + 24.0;
  6085.       End If;
  6086.       ECALC (GMT, F0E, HME);
  6087.       F1CALC (F0F1, HMF1);
  6088.       F0F2 := F0F2FN (GMT, THRL);
  6089.       HMF2 := HMF2FN (GMT);
  6090. --
  6091.       Return;
  6092. --
  6093.       End POLAR;
  6094. --
  6095. --
  6096.       Function POLR (RLTM: float;
  6097.                      RLGM: float;
  6098.                      R: float;
  6099.                      PHI: float;
  6100.                      TMO: float) return float is
  6101. --
  6102. --#PURPOSE: POLR calculates geomagnetic influence on density
  6103. --          variations for F2 layer.
  6104. --
  6105. --#AUTHOR:  J. Conrad
  6106. --
  6107. --#TYPE:    Numerical Analysis
  6108. --
  6109. --#PARAMETER DESCRIPTIONS:
  6110. --IN        RLTM   = Geomagnetic latitude
  6111. --IN        RLGM   = Geomagnetic longitude
  6112. --IN        R      = Smoothed Zurich sunspot number divided by 100
  6113. --IN        PHI    = Time of day in radians( 1 day := 2pi radians )
  6114. --IN        TMO    = month, starting December 15 ( 0 - 12 )
  6115. --                   (eg. 1 day := 6.5 )
  6116. --OUT       POLR   = Geomagnetic influence on density variations
  6117. --
  6118. --#CALLED BY:
  6119. --          TVARF2
  6120. --
  6121. --#CALLS TO:
  6122. --          'NONE'
  6123. --
  6124. --#TECHNICAL DESCRIPTION:
  6125. --          POLR calculates geomagnetic influence on density
  6126. --          variations for F2 layer.  This routine is based on
  6127. --          HFNET -- a propagation prediction model for HF as 
  6128. --          developed by Mission Research Corp.
  6129. --
  6130.       C: float := -0.4101524;
  6131.       T, V, U, Y, YS, Z, ZA, AM, P, WFNCTN, B, POLER: float;
  6132. --
  6133.       Begin
  6134. --
  6135.       T := PI12*TMO;
  6136.       V := SIN(T);
  6137.       U := COS(T + T);
  6138.       Y := SIN(RLGM/2.0);
  6139.       YS := COS(RLGM/2.0 - PI20);
  6140.       Z := SIN(RLGM);
  6141.       ZA := SQRT(ABS(Z));
  6142.       AM := 1.0 + V;
  6143.       If RLTM >= 0.0 Then               --  COMPUTE WEIGHT FUNCTION
  6144.          P := RLTM + C*COS(PHI);
  6145.          WFNCTN := EXP(-1.2*(COS(P) - COS(RLTM)));
  6146.          Return (2.0 + 1.2*R)*WFNCTN*(1.0 + 0.3*V);
  6147.       End If;
  6148.       B := V*(0.5*Y - 0.5*Z - Y**8) - AM*U*(Z/ZA)*EXP(-4.0*Y*Y);
  6149.       POLER := 2.5 + 2.0*R + U*(0.5 + (1.3 + 0.2*R)*YS**4);
  6150.       POLER := POLER + (1.3 + 0.5*R)*COS(PHI - PI*(1.0 + B));
  6151.       Return POLER*(1.0 + 0.4*(1.0 - V*V))*EXP(-1.0*V*YS**4);
  6152. --
  6153.       End POLR;
  6154. --
  6155. --
  6156.       Procedure SCALHT (FBAR: in float;
  6157.                         F: in float;
  6158.                         SOLDEC: in float;
  6159.                         GLATR: in float;
  6160.                         HA: in float;
  6161.                         HEIGHT: in float;
  6162.                         TATR: out float;
  6163.                         SMULT: out float) is
  6164. --
  6165. --#PURPOSE: SCALHT calculates a Jacchia model neutral atmosphere.
  6166. --
  6167. --#AUTHOR:  J. Conrad
  6168. --
  6169. --#TYPE:    Computational Procedure
  6170. --
  6171. --#PARAMETER DESCRIPTIONS:
  6172. --IN        FBAR   = Average daily 10.7 cm. solar flux values
  6173. --                   over 3 solar rotations
  6174. --IN        F      = Value of 10.7 cm. solar flux the previous day
  6175. --IN        SOLDEC = Solar declination (radians)
  6176. --IN        GLATR  = Geographic latitude (radians)
  6177. --IN        HA     = Solar hour angle (radians)
  6178. --IN        HEIGHT = Altitude (Km)
  6179. --OUT       TATR   = Temperature
  6180. --OUT       SMULT = Scale height
  6181. --
  6182. --#CALLED BY:
  6183. --          HMF2FN
  6184. --
  6185. --#CALLS TO:
  6186. --          DENS
  6187. --          EXOT
  6188. --
  6189. --#TECHNICAL DESCRIPTION:
  6190. --          SCALHT calculates a Jacchia model neutral atmosphere.
  6191. --          The method used is based on the RADC-POLAR model.
  6192. --
  6193.       TINF: float;
  6194. --
  6195.       Begin
  6196. --
  6197.       TINF := EXOT(FBAR,F,SOLDEC,GLATR,HA);
  6198.       DENS (TINF, HEIGHT, TATR, SMULT);
  6199. --
  6200.       Return;
  6201. --
  6202.       End SCALHT;
  6203. --
  6204. --
  6205. --
  6206.       Function TABINT (K: integer;
  6207.                        I: integer;
  6208.                        J: integer) return float is
  6209. --
  6210. --#PURPOSE: TABINT replaces the 13286 element TABLE1 sequential
  6211. --          data file with a 730 element data array. The values for
  6212. --          TABLE1 are regenerated by interpolation.
  6213. --
  6214. --#AUTHOR:  J. Conrad
  6215. --
  6216. --#TYPE:    Table Look-up
  6217. --
  6218. --#PARAMETER DESCRIPTIONS:
  6219. --IN        K      = Coordinate type where-
  6220. --                      1 = latitude, and
  6221. --                      2 = longitude.
  6222. --IN        I      = Polar latitude index (degrees*2).
  6223. --IN        J      = Polar longitiude index (degrees*2).
  6224. --OUT       TABINT = Geomagnetic coordinate.
  6225. --
  6226. --#CALLED BY:
  6227. --          FETCH
  6228. --
  6229. --#CALLS TO:
  6230. --          'NONE'
  6231. --
  6232. --#TECHNICAL DESCRIPTION:
  6233. --          Aitken's iteration method is used to  interpolate between
  6234. --          the data array values. Depending on the polar latitude,
  6235. --          a polynomial of degree two or three is used.
  6236. --
  6237.       POLE: array (integer range 1..2, integer range 1..2) of float :=
  6238.          ((81.69, -74.13),
  6239.          (171.12, 17.07));
  6240.       F0, F1, F2, F01, F02, F012, F3, F03, F023, F0123, F4, F6, F5, F56,
  6241.          F46, F456, F36, F346, F3456, RESULT: float;
  6242.  
  6243.       Function DETERM (A: float; B: float;
  6244.                       IC: integer; ID: integer) return float is
  6245. --
  6246. --STATEMENT FUNCTION FOR SECOND ORDER DETERMINANT AS USED BY Function TABINT.
  6247. --
  6248. --    DETERM(A, B, IC, ID) := A*ID - B*IC
  6249. --
  6250.       Begin
  6251. --
  6252.          Return A*FLOAT(ID) - B*FLOAT(IC);
  6253. --
  6254.       End DETERM;
  6255. --
  6256.       Begin
  6257.       If I <= 24 Then
  6258.          F0 := POLE(K, 1);
  6259.          F1 := FARKLER.FARKLE(1,J,K);
  6260.          F2 := FARKLER.FARKLE(2,J,K);
  6261.          F01 := (1.0/3.0)*DETERM(F0, F1, 1-I, 4-I);
  6262.          F02 := (1.0/23.0)*DETERM(F0, F2, 1-I, 24-I);
  6263.          F012 := (1.0/20.0)*DETERM(F01, F02, 4-I, 24-I);
  6264.          RESULT := F012;
  6265.          If I <= 4 Then
  6266.             Return RESULT;
  6267.          End If;
  6268.          F3 := FARKLER.FARKLE(3,J,K);
  6269.          F03 := (1.0/43.0)*DETERM(F0, F3, 1-I, 44-I);
  6270.          F023 := (1.0/20.0)*DETERM(F02, F03, 24-I, 44-I);
  6271.          F0123 := (1.0/40.0)*DETERM(F012, F023, 4-I, 44-I);
  6272.          RESULT := F0123;
  6273.          Return RESULT;
  6274.       Elsif I <= 69 Then
  6275.          F2 := FARKLER.FARKLE(2,J,K);
  6276.          F4 := FARKLER.FARKLE(4,J,K);
  6277.          RESULT := (1.0/45.0)*DETERM(F2, F4, 24-I, 69-I);
  6278.          Return RESULT;
  6279.       Else
  6280.          F6 := POLE(K, 2);
  6281.          F5 := FARKLER.FARKLE(5,J,K);
  6282.          If F5 > 360.0 Then
  6283.             F6 := F6 + 360.0;
  6284.          End If;
  6285.          F4 := FARKLER.FARKLE(4,J,K);
  6286.          F56 := (1.0/2.0)*DETERM(F5, F6, 89-I, 91-I);
  6287.          F46 := (1.0/22.0)*DETERM(F4, F6, 69-I, 91-I);
  6288.          F456 := (1.0/20.0)*DETERM(F46, F56, 69-I, 89-I);
  6289.          RESULT := F456;
  6290.          If I >= 89 Then
  6291.             Return RESULT;
  6292.          End If;
  6293.          F3 := FARKLER.FARKLE(3,J,K);
  6294.          F36 := (1.0/47.0)*DETERM(F3, F6, 44-I, 91-I);
  6295.          F346 := (1.0/25.0)*DETERM(F36, F46, 44-I, 69-I);
  6296.          F3456 := (1.0/45.0)*DETERM(F346, F456, 44-I, 89-I);
  6297.          RESULT := F3456;
  6298.          Return RESULT;
  6299.       End If;
  6300. --
  6301.       End TABINT;
  6302. --
  6303. --
  6304.       Function TATRFN (TINF: float; HEIGHT: float) return float is
  6305. --
  6306. --#PURPOSE: TATRFN calculates temperatures of the atmosphere
  6307. --          after the F2 layer at a specific height.
  6308. --
  6309. --#AUTHOR:  J. Conrad
  6310. --
  6311. --#TYPE:    Numerical Analysis
  6312. --
  6313. --#PARAMETER DESCRIPTIONS:
  6314. --IN        TINF   = Exospheric temperature
  6315. --IN        HEIGHT = Height at which temperature is calculated
  6316. --OUT       TATRFN = Temperature at altitude HEIGHT
  6317. --
  6318. --#CALLED BY:
  6319. --          DENS
  6320. --
  6321. --#CALLS TO:
  6322. --          'NONE'
  6323. --
  6324. --#TECHNICAL DESCRIPTION:
  6325. --          TATRFN is based on the RADC-POLAR model.
  6326. --
  6327.       C90: array (integer range 1..4) of float := (1.9, 0.0, -1.7, -0.8);
  6328.       C1: float := 371.6678;
  6329.       C2: float := 0.0518806;
  6330.       C3: float := -294.3505;
  6331.       C4: float := -0.00216222;
  6332.       Z90: float := 90.0;
  6333.       Z125: float := 125.0;
  6334.       BX: float := 4.5E-6;
  6335.       BETA: float := 2.5;
  6336.       PIBY2: float := 1.57079633;
  6337.       F2, DBDT, F1, F3, DGDT, DZI, F4, AX, DZEX, ARG, GXR, DADT, RESULT: float;
  6338. --
  6339.       Begin
  6340. --
  6341.       TX := TINF;
  6342. --                           TB := C1 + C2*TINF + C3*EXP(C4*TINF)
  6343. --                           GX := C90(1)*(TB - T90)/(Z125 - Z90)
  6344.       F2 := EXP(C4*TINF);
  6345.       TB := C1 + C2*TINF + C3*F2;
  6346.       DBDT := C2 + C3*C4*F2;
  6347.       F1 := TB - T90;
  6348.       F3 := C90(1)/(Z125 - Z90);
  6349.       GX := F1*F3;
  6350.       DGDT := DBDT*F3;
  6351.       If HEIGHT > Z90 Then
  6352.          DZI := HEIGHT - Z125;
  6353.          If DZI < 0.0 Then
  6354.             DZI := DZI/(Z125 - Z90);
  6355. --                           RESULT := TB + (TB - T90)*DZI*(C90(1) + 
  6356. --                                     DZI*(C90(2) + DZI*(C90(3) + DZI*C90(4))
  6357.             F4 := DZI*(C90(1) + DZI*(C90(2) + DZI*(C90(3) + DZI*C90(4))));
  6358.             RESULT := TB + F1*F4;
  6359.             DTDR := F1*(C90(1) + DZI*(2.0*C90(2) + DZI*(3.0*C90(3) + 
  6360.                     DZI*4.0*C90(4))))/(Z125 - Z90);
  6361.             DTDT := DBDT + DBDT*F4;
  6362.             TR := RESULT;
  6363.             Return RESULT;
  6364.          Elsif DZI = 0.0 Then
  6365.             RESULT := TB;
  6366.             DTDR := GX;
  6367.             DTDT := DBDT;
  6368.             TR := RESULT;
  6369.             Return RESULT;
  6370.          Else
  6371.             AX := (TINF - TB)/PIBY2;
  6372.             DZEX := BX*(DZI**BETA);
  6373.             ARG := (GX/AX)*DZI*(1.0 + DZEX);
  6374.             GXR := GX*((1.0 + DZEX) + BETA*DZEX);
  6375.             DADT := (1.0 - DBDT)/PIBY2;
  6376.             F4 := ATAN(ARG);
  6377.             RESULT := TB + AX*F4;
  6378.             DTDT := DBDT + DADT*F4 + (DGDT*AX/GX - DADT)*ARG/(1.0 + ARG*ARG);
  6379.             DTDR := GXR/(1.0 + ARG*ARG);
  6380.             TR := RESULT;
  6381.             Return RESULT;
  6382.          End If;
  6383.       End If;
  6384.       DTDR := (T90 - T0)/Z90;
  6385.       DTDT := 0.0;
  6386.       RESULT := T0 + DTDR*HEIGHT;
  6387.       TR := RESULT;
  6388.       Return RESULT;
  6389. --
  6390.       End TATRFN;
  6391. --
  6392. --
  6393.       Function TVARF2 (RLTM: float;
  6394.                        RLGM: float;
  6395.                        DIP: float;
  6396.                        R: float;
  6397.                        PHI: float;
  6398.                        TMO: float;
  6399.                        DEC: float;
  6400.                        CLTM: float;
  6401.                        SLTM: float) return float is
  6402. --
  6403. --#PURPOSE: TVARF2 calculates seasonal and hourly variabilty
  6404. --          of density for the F2 layer.
  6405. --
  6406. --#AUTHOR:  J. Conrad
  6407. --
  6408. --#TYPE:    Numerical Analysis
  6409. --
  6410. --#PARAMETER DESCRIPTIONS:
  6411. --IN        RLTM   = Geomagnetic latitude
  6412. --IN        RLGM   = Geomagnetic longitude
  6413. --IN        DIP    = Dip angle
  6414. --IN        R      = Sunspot number divided by 100 
  6415. --IN        PHI    = Time of day in radians; (1day := 2pi radians)
  6416. --IN        TMO    = Month (0-12; starting from december 15;
  6417. --                   e. g. June 1 := 6.5)
  6418. --IN        DEC    = Declination angle of sun
  6419. --IN        CLTM   = Cosine of geomagnetic latitude
  6420. --IN        SLTM   = Sine of geomagnetic latitude
  6421. --OUT       TVARF2 = Density for F2 layer variation
  6422. --
  6423. --#CALLED BY:
  6424. --          IONFT1
  6425. --
  6426. --#CALLS TO:
  6427. --          POLR
  6428. --          YONII
  6429. --
  6430. --#TECHNICAL DESCRIPTION:
  6431. --          TVARF2 is based on HFNET -- an HF propagation prediction code 
  6432. --          developed by Mission Research Corp.
  6433. --
  6434.       SHIFT, ALTM, ATMO, SEMI, REQ, SD, X, FF, GG, CPD, EF, EMF, ADIUR, 
  6435.          BQ, AQE, AQT, AEQ, EQ, VEQ, VDIUR, VLT, RTL, VLAT, RF, CQ, VUT, 
  6436.          POLER, ER, VLONG, ADIP, DP, VDP, VDIP, F2, RESULT: float;
  6437. --
  6438.       Begin
  6439.       SHIFT := 1.2217305;
  6440.       ALTM := ABS(RLTM);
  6441.       ATMO := TMO*PI6;
  6442.       SEMI := 0.5 - COS(2.0*ATMO) + COS(ATMO);
  6443.       REQ := 1.0 - 0.2*R + 0.6*SQRT(R);
  6444.       SD := SIN(DEC)*SIN(RLTM);
  6445.       X := (2.2 + (0.2 + 0.1*R)*SLTM)*CLTM;
  6446.       X := AMIN1(X, 2.0);
  6447.       FF := EXP(-X**6);
  6448.       GG := 1.0-FF;
  6449.       CPD := COS(PHI - 0.873);
  6450.       EF := COS(PHI + PI4);
  6451.       EMF := EF*EF;
  6452.       ADIUR := (0.9 + 0.32*SD)*(1.0 + SD*EMF);
  6453.       BQ := COS(ALTM - 0.2618);
  6454.       AQE := CLTM**8;
  6455.       AQT := AQE*CLTM*CLTM;
  6456.       AEQ := AQE*REQ*EXP(0.25*(1.0 - CPD));
  6457.       EQ := (1.0 - 0.4*AQT)*(1.0+AEQ*BQ**12)*(1.0 + 0.6*AQT*EMF);
  6458.       VEQ := EQ*(1.0 + 0.05*SEMI);
  6459.       VDIUR := ADIUR*EXP(-1.1*(CPD + 1.0));
  6460.       VLT := (EXP(3.0*COS(RLTM*(SIN(PHI) - 1.0)/2.0)))*(1.2 - 0.5*CLTM*CLTM);
  6461.       VLT := VLT*(1.0 + 0.05*R*COS(ATMO)*SLTM**3);
  6462.       RTL := SQRT((12.0*RLTM+PI43)**2 + (TMO/2.0 - 3.0)**2);
  6463.       VLAT := VLT*(1.0 - 0.15*EXP(-RTL));
  6464.       RF := 1.0 + R + (0.204 + 0.03*R)*R*R;
  6465.       If R - 1.1 > 0.0 Then
  6466.          CQ := 1.53*SLTM*SLTM;
  6467.          RF := 2.39+CQ*(RF - 2.39);
  6468.       End If;
  6469.       VUT := YONII(RLTM, RF, R, PHI, TMO, DEC, CLTM, SLTM);
  6470.       POLER := POLR(RLTM, RLGM, R, PHI, TMO);
  6471.       VLONG := 1.0 + 0.1*(CLTM**3)*COS(2.0*(RLGM - SHIFT));
  6472.       ADIP := ABS(DIP);
  6473.       DP :=  0.15 - 0.5*(1.0 + R)*(1.0 - CLTM)*EXP(-0.33*(TMO - 6.0)**2);
  6474.       VDP := 1.0 + DP*EXP(-18.0*(ADIP - PI29)**2);
  6475.       VDIP := VDP*(1.0 + 0.03*SEMI);
  6476.       F2 := VDIUR*VLAT*VUT*VEQ*RF*VLONG*VDIP;
  6477.       Return FF*POLER+GG*F2;
  6478. --
  6479.       End TVARF2;
  6480. --
  6481.       Function TVEF1 (A: float;
  6482.                       B: float;
  6483.                       C: float;
  6484.                       D: float;
  6485.                       RLT: float;
  6486.                       R: float;
  6487.                       PHI: float;
  6488.                       DEC: float) return float is
  6489. --
  6490. --#PURPOSE: TVEF1 calculates seasonal and hourly variation
  6491. --          of density function for the E and F1 layers.
  6492. --
  6493. --#AUTHOR:  J. Conrad
  6494. --
  6495. --#TYPE:    Numerical Analysis
  6496. --
  6497. --#PARAMETER DESCRIPTIONS:
  6498. --IN        A      = Parameter (= 1.15 for E layer, := 1.24 for
  6499. --                   F1 layer)
  6500. --IN        B      = Parameter (= 0 for both E and F1)
  6501. --IN        C      = Parameter (= .4 for E and .25 for F1 layer)
  6502. --IN        D      = parameter (= 2. for E and .25 for F1 layer)
  6503. --IN        RLT    = Latitude
  6504. --IN        R      = The smootheed Zurich sunspot number divided
  6505. --                   by 100.
  6506. --IN        PHI    = Time of day in radians; (1day := 2pi radians)
  6507. --IN        DEC    = Declination angle of sun
  6508. --OUT       TVEF1  = Density for E, F1 layer variation
  6509. --
  6510. --#CALLED BY:
  6511. --          IONFT1
  6512. --
  6513. --#CALLS TO:
  6514. --          'NONE'
  6515. --
  6516. --#TECHNICAL DESCRIPTION:
  6517. --          TVEF1 is based on HFNET -- an HF propagation
  6518. --          prediction code developed by Mission Research Corp.
  6519. --
  6520.       RF, CSL, CSX, CSX2, XF, P, VUT, VDIUR: float;
  6521. --
  6522.       Begin
  6523. --
  6524.       RF := SQRT(1.0 + A*R+B*R*R);
  6525.       CSL := COS(RLT);
  6526.       CSX := -CSL*COS(DEC)*COS(PHI) + SIN(RLT)*SIN(DEC);
  6527.       CSX2 := SQRT(ABS(CSX));
  6528.       XF := SIGN(CSX2,CSX);
  6529. --
  6530. --COMPUTE WEIGHT FUNCTION
  6531.       P := RLT + DEC*COS(PHI);
  6532.       VUT := EXP(-C*(COS(P) - COS(RLT)));
  6533. --
  6534.       VDIUR := EXP(D*(XF - 1.0));
  6535.       Return RF*VDIUR*VUT;
  6536. --
  6537.       End TVEF1;
  6538. --
  6539. --
  6540.       Function YONII (RLTM: float;
  6541.                       RF: float;
  6542.                       R: float;
  6543.                       PHI: float;
  6544.                       TMO: float;
  6545.                       DEC: float;
  6546.                       CLTM: float;
  6547.                       SLTM: float) return float is
  6548. --
  6549. --#PURPOSE: YONII is used in the calculation of density
  6550. --          variations for the F2 layer.
  6551. --
  6552. --#AUTHOR:  J. Conrad
  6553. --
  6554. --#TYPE:    Numerical Analysis
  6555. --
  6556. --#PARAMETER DESCRIPTIONS:
  6557. --IN        RLTM   = Geomagnetic latitude
  6558. --IN        RF     = Variation due to sunspot number at specified
  6559. --                   magnetic latitude
  6560. --IN        R      = Sunspot number divided by 100
  6561. --IN        PHI    = Time of day in radians; 1day := 2pi radians
  6562. --IN        TMO    = Month of year
  6563. --IN        DEC    = Declination angle of sun
  6564. --IN        CLTM   = Cosine of geomagnetic latitude
  6565. --IN        SLTM   = Sine of geomagnetic latitude
  6566. --OUT       YONII  = Density variations for F2 layer
  6567. --
  6568. --#CALLED BY:
  6569. --          TVARF2
  6570. --
  6571. --#CALLS TO:
  6572. --          'NONE'
  6573. --
  6574. --#TECHNICAL DESCRIPTION:
  6575. --          YONII is based on HFNET -- an HF propagation
  6576. --          prediction model developed by Mission Research Corp.
  6577. --
  6578.       W1, W2, B, DRF, DE, ALTM, SNX, AE, BLTM, SX, FE, YM, CPHG, XTC, YTC, T1,
  6579.          TRIV, QQ, P, WFNCTN, T2, T3: float;
  6580. --
  6581.       Begin
  6582. --
  6583.       W1 := 0.5235988;
  6584.       W2 := 1.047198;
  6585.       B := 1.3 + (0.139*(1.0 + COS(RLTM - PI4)) + 0.0517*R)*R*R;
  6586.       DRF := 1.0/RF;
  6587.       DE := 0.1778*R*R;
  6588.       ALTM := ABS(RLTM);
  6589.       SNX := SIN(ALTM - 0.5236);
  6590.       AE := 0.2*(1.0 - SNX);
  6591.       BLTM := ABS(ALTM - PI9);
  6592.       SX := SIN(BLTM);
  6593.       FE := 0.13 - 0.06*SX;
  6594.       YM := COS(RLTM + DEC);
  6595.       CPHG := COS(PHI);
  6596.       XTC := YM**3*(1.0 - CPHG)**0.25;
  6597.       YTC := -(0.15 + 0.3*SIN(ALTM))*XTC;
  6598.       T1 := AE*(1.0 + 0.6*COS(W2*(TMO - 4.0)))*COS(W1*(TMO - 1.0));
  6599.       TRIV := (COS(RLTM - W1))*(COS(W1*(0.5*TMO - 1.0)))**3;
  6600.       TRIV := TRIV + (COS(RLTM + PI4))*(COS(W1*(0.5*TMO - 4.0)))**2;
  6601.       QQ := 1.0 + 0.085*TRIV;
  6602. --
  6603. --COMPUTE WEIGHT FUNCTION
  6604.       P := RLTM + DEC*COS(PHI);
  6605.       WFNCTN := EXP(-B*(COS(P) - COS(RLTM)));
  6606. --
  6607.       T2 := 0.7*(QQ + DE*DRF*COS(W2*(TMO - 4.3)))*WFNCTN;
  6608.       T3 := FE*COS(W2*(TMO - 4.5)) + YTC;
  6609.       Return (T1 + T3)*DRF + T2;
  6610. --
  6611.       End YONII;
  6612. --
  6613. --
  6614. End HF_ATMOSPHERICS;
  6615.  
  6616. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6617. --RFUTIL
  6618. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  6619. With Debugger2; Use Debugger2;
  6620. With Text_IO; Use Text_io, integer_io, float_io;
  6621. With Types; Use Types;
  6622. With Mathlib; Use Mathlib, numeric_primitives, 
  6623.                            core_functions, trig_functions;
  6624. With Complex_numbers; Use complex_numbers;
  6625. With Constants; Use Constants;
  6626. With Propagation_constants; use Propagation_constants;
  6627. With Constant3; Use Constant3;
  6628. With NODELOC;
  6629.  
  6630. Package RFUTIL is
  6631. --
  6632.       Function ADJBW (FREQT: float; 
  6633.                       BANDT: float; 
  6634.                       FREQR: float; 
  6635.                       BANDR: float)
  6636.                       return float;
  6637.       Function AOW (FREQ: float; ELV: float) return float;
  6638.       Procedure COORDX (HO: in float;
  6639.                         MODE: in integer;
  6640.                         RXSE: in float;
  6641.                         AYAA: in float;
  6642.                         HZEH: in float;
  6643.                         R: out float;
  6644.                         A: out float;
  6645.                         H: out float;
  6646.                         X: out float;
  6647.                         Y: out float;
  6648.                         Z: out float;
  6649.                         S: out float;
  6650.                         E: out float);
  6651.       Function CTANH (VAL: complex) return complex;
  6652.       Procedure DAYNIT (IDN: out DAY_OR_NIGHT;
  6653.                         TLON: in float;
  6654.                         RLON: in float);
  6655.       Procedure DNTR;
  6656.       Procedure GNDCON (XLAT: in float;
  6657.                         XLONG: in float;
  6658.                         COND: out float);
  6659.       Function HTOS (H1: float;
  6660.                      H2: float;
  6661.                      COSE: float;
  6662.                      SINE: float) return float;
  6663.       Function LOS (XLA1: float;
  6664.                     XLO1: float;
  6665.                     AL1: float;
  6666.                     XLA2: float;
  6667.                     XLO2: float;
  6668.                     AL2: float) return boolean;
  6669.       Function PLYVAL (YARRAY: F_ARRAY;
  6670.                        MAXY: integer;
  6671.                        X: float) return float;
  6672.       Procedure ZENITH (XLAT: in float;
  6673.                         XLONG: in float;
  6674.                         CHI: out float;
  6675.                         TOD: out float;
  6676.                         IDN: out DAY_OR_NIGHT);
  6677. --
  6678. End RFUTIL;
  6679. --
  6680. Package body RFUTIL is
  6681. --
  6682. -- RF_UTILITIES Package of PROP_LINK 
  6683. -- Version 1.0,  March 12, 1985.
  6684. --
  6685. -- This RF_UTILITIES Package contains all of the procedures that are used 
  6686. -- as RF propagation utilities.
  6687. --
  6688. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  6689. -- radio frequency propagation prediction code.
  6690. --
  6691. -- PROP_LINK has been developed for the Department of Defense under
  6692. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  6693. -- Systems Inc. (Jim Conrad).
  6694. --
  6695. -- Instantiate integer and floating point IO.
  6696. --      Package IO_INTEGER is new INTEGER_IO(INTEGER);
  6697. --      Package IO_FLOAT is new FLOAT_IO(FLOAT);
  6698. -- Use IO_INTEGER,IO_FLOAT;
  6699. --
  6700.       Pragma Source_info(on);
  6701.       Function ADJBW (FREQT: float; 
  6702.                       BANDT: float; 
  6703.                       FREQR: float; 
  6704.                       BANDR: float)
  6705.                       return float is
  6706. --
  6707. --#PURPOSE:ADJBW computes an adjustment factor for possible bandwidth mismatch.
  6708. --
  6709. --#AUTHOR:  J. Conrad
  6710. --
  6711. --#TYPE:    Computational Module
  6712. --
  6713. --#PARAMETER DESCRIPTIONS:
  6714. --IN        FREQT  = Frequency of transmitter
  6715. --IN        BANDT  = Bandwidth of transmitter
  6716. --IN        FREQR  = Frequency of receiver
  6717. --IN        BANDR  = Bandwidth of receiver
  6718. --OUT       ADJBW  = Adjustment factor
  6719. --
  6720. --#CALLED BY:
  6721. --          RF_PROPAGATION_HANDLER
  6722. --
  6723. --#CALLS TO:
  6724. --          'NONE'
  6725. --
  6726. --#TECHNICAL DESCRIPTION:
  6727. --          A comparison is made between the frequency of the transmitter
  6728. --          and the frequency of the receiver -- considering the impact of
  6729. --          overlap caused by non-equal bandwidths.  An adjustment factor
  6730. --          is computed based on the degree of this overlap.
  6731. --
  6732.       OFFSET: float;
  6733. --
  6734.       Begin
  6735. --
  6736.       OFFSET := ABS(FREQT - FREQR);
  6737. --
  6738. --NO OVERLAP BETWEEN BANDS.
  6739.       If 2.0*OFFSET  >=  BANDT + BANDR Then
  6740.          Return 0.0;
  6741.       End If; 
  6742. --
  6743. --RECEIVER BAND WITHIN TRANSMITTER BAND.
  6744.       If 2.0*OFFSET + BANDR <= BANDT Then
  6745.          Return 1.0;
  6746.       End If;
  6747. --
  6748. --TRANSMITTER BAND WITHIN RECEIVER BAND.
  6749.       If 2.0*OFFSET + BANDT <= BANDR Then
  6750.          Return BANDT/BANDR;
  6751.       End If;
  6752. --
  6753. --BANDS OVERLAP.
  6754.       Return ((BANDR + BANDT)*0.5 - OFFSET)/BANDR;
  6755. --
  6756.       End ADJBW;
  6757. --
  6758. --
  6759.       Function AOW (FREQ: float; ELV: float) return float is
  6760. --
  6761. --#PURPOSE: AOW calculates the absorption due to oxygen and water
  6762. --          vapor for a path which passes through the atmosphere.
  6763. --
  6764. --#AUTHOR:  J. Conrad
  6765. --
  6766. --#TYPE:    Numerical Analysis
  6767. --
  6768. --#PARAMETER DESCRIPTIONS:
  6769. --IN        FREQ   = Frequency in MHz
  6770. --IN        ELV    = Elevation angle of path in radians
  6771. --OUT       AOW    = Absorption, dB
  6772. --
  6773. --#CALLED BY:
  6774. --          VHF_UHF_SHF_EHF_HANDLER
  6775. --
  6776. --#CALLS TO:
  6777. --          PLYVAL
  6778. --
  6779. --#TECHNICAL DESCRIPTION:
  6780. --          Curve fits for the absorption due to water and oxygen
  6781. --          have been represented by 5th order polynomials for
  6782. --          frequencies from 100MHz to 54 GHz.  For frequencies
  6783. --          between 100MHz and 20GHz, a simple formulation is
  6784. --          employed.  For frequencies between 20GHz and 54GHz, direct
  6785. --          5th order polynomial fits of AOW versus frequency are
  6786. --          used.
  6787. --
  6788.       PCOEFF: F_ARRAY (integer range 1..6)
  6789.       := (-0.1133607, -0.4605316, 0.2858249, 2.37588, 0.3513365, -2.849912);
  6790.       COEFFK: F_ARRAY(integer range 1..6)
  6791.       := (-0.1260167, -0.587672, -0.2332291, 1.184484, -1.476704, -3.377323);
  6792.       BOUNDS: F_ARRAY (integer range 1..6)
  6793.       := (1.570796, 1.0, 0.5, 0.2, 0.1, 0.05);
  6794.       COEFS: array (integer range 1..6, integer range 1..6) of float
  6795.       := ((0.5759213E-6,  -0.1058284E-3,      0.7698042E-2,
  6796.           -0.2740164,      0.4744495E1,      -0.3163005E2),
  6797.           (0.635214E-6,   -0.1144331E-3,      0.8143891E-2,
  6798.           -0.2839701,      0.4817095E1,      -0.3140205E2),
  6799.           (0.6259988E-7,  -0.9344444E-5,      0.5452778E-3,
  6800.           -0.9251671E-2,  -0.1647310,         0.5061962E1),
  6801.           (0.3834260E-5,  -0.6391562E-3,      0.4176852E-1,
  6802.           -0.1328056E1,    0.2041086E2,      -0.1189484E3),
  6803.          (-0.4923502E-5,   0.8537153E-3,     -0.5817072E-1,
  6804.            0.1956157E1,   -0.3258934E2,       0.2189743E3),
  6805.           (0.1668294E-4,  -0.2963053E-2,      0.2077701,
  6806.           -0.7180226E1,    0.1221736E3,      -0.8126215E3));
  6807.       COEF: F_ARRAY(integer range 1..6);
  6808.       FLOG, ELOG, PLOG, P, CAY, ELE, ELEMAX, ELEMIN, DBMIN,
  6809.                                               DBMAX, RATIO: float;
  6810.       I, II, J, K: Integer;
  6811. --
  6812.       Begin
  6813. --
  6814.       If FREQ <= 100.0 Then
  6815.          Return 0.0;
  6816.       End If;
  6817.       If FREQ < 2.1E4 Then
  6818.          FLOG := LOG10(FREQ);
  6819.          ELOG := LOG10(AMAX1(ELV,0.001));
  6820.          PLOG := PLYVAL(PCOEFF,6,ELOG);
  6821.          P:=4.3 + 10.0**PLOG;
  6822.          CAY := PLYVAL(COEFFK,6,ELOG);
  6823.          CAY := 10.0**CAY;
  6824.          Return CAY*(1.0/(P - FLOG) - 1.0/(P - 2.0));
  6825.       Else
  6826.          FLOG := AMIN1(5.4E4,FREQ);
  6827.          FLOG := FLOG*0.001;
  6828.          For I in 1..5 Loop      
  6829.             II := I;
  6830.             J := I + 1;
  6831.             ELE := AMAX1(ELV,0.05);
  6832.             Exit When (ELE >= BOUNDS(J) and ELE <= BOUNDS(I));
  6833.          End Loop;
  6834.          ELEMAX := BOUNDS(II);
  6835.          ELEMIN := BOUNDS(J);
  6836.          For K in 1..6 Loop
  6837.             COEF(K) := COEFS(K,II);
  6838.          End Loop;
  6839.          DBMIN := PLYVAL(COEF,6,FLOG);
  6840.          For K in 1..6 Loop
  6841.             COEF(K) := COEFS(K,J);
  6842.          End Loop;
  6843.          DBMAX := PLYVAL(COEF,6,FLOG);
  6844.          RATIO := (ELEMIN - ELE)/(ELEMIN - ELEMAX);
  6845.          Return DBMAX - RATIO*(DBMAX - DBMIN);
  6846.       End If;
  6847. --
  6848.       End AOW;
  6849. --
  6850. --
  6851.       Procedure COORDX (HO: in float;
  6852.                         MODE: in integer;
  6853.                         RXSE: in float;
  6854.                         AYAA: in float;
  6855.                         HZEH: in float;
  6856.                         R: out float;
  6857.                         A: out float;
  6858.                         H: out float;
  6859.                         X: out float;
  6860.                         Y: out float;
  6861.                         Z: out float;
  6862.                         S: out float;
  6863.                         E: out float) is
  6864. --
  6865. --#PURPOSE: COORDX performs geometrical transformations on the
  6866. --          coordinates of a point given in any one of several systems
  6867. --          and returns the coordinates in all of the systems.
  6868. --
  6869. --#AUTHOR:  J. Conrad
  6870. --
  6871. --#TYPE:    Geometric Transformation
  6872. --
  6873. --#PARAMETER DESCRIPTIONS:
  6874. --IN        HO     = Altitude of the origin of the coordinate
  6875. --                   system (Km)
  6876. --IN        MODE   = 1, 2, 3, 4
  6877. --IN        RXSE   = Ground range (Km), X(East,(Km)), Slant
  6878. --                   range(Km), Elevation(Degrees)
  6879. --IN        AWAA   = Azimuth (Degrees), Y (North, Km),
  6880. --                   Azimuth (Degrees), Azimuth (Degrees)
  6881. --IN        HZEH   = Altitude (Km), Z (Up, Km)
  6882. --                   Elevation (Degrees), Altitude(Km)
  6883. --OUT       R      = Ground range
  6884. --OUT       A      = Azimuth
  6885. --OUT       H      = Altitude
  6886. --OUT       X      = Tangent-plane coordinate
  6887. --OUT       Y      = Tangent-plane coordinate
  6888. --OUT       Z      = Tangent-plane coordinate
  6889. --OUT       S      = Slant range
  6890. --OUT       E      = Elevation angle
  6891. --
  6892. --#CALLED BY:
  6893. --          IONCAL
  6894. --          NOISE_HANDLER
  6895. --          VHF_UHF_SHF_EHF_HANDLER
  6896. --
  6897. --#CALLS TO:
  6898. --          HTOS
  6899. --
  6900. --#TECHNICAL DESCRIPTION:
  6901. --          COORDX performs geometrical transformations on the
  6902. --          coordinates of a point given in any one of several systems
  6903. --          and returns the coordinates in all of the systems.
  6904. --          The input MODE determines how the input data is to be treated
  6905. --          so that the proper trigonometric conversions can be made.
  6906. --
  6907. --            MODE              INPUTS
  6908. --            ____              ______
  6909. --             1              Ground range, Azimuth and Altitude
  6910. --             2              X,Y,Z tamgent plane coordinates
  6911. --             3              Slant range, Azimuth and Elevation
  6912. --             4              Elevation, Azimuth and Altitude
  6913. --
  6914.       REH, U0, U1, U2, U3: float;
  6915.       COSE, SINE: float;
  6916. --
  6917.       Begin
  6918. --
  6919.       REH := RADIUS_OF_EARTH_IN_KM + HO;
  6920. --
  6921.       If MODE = 1 Then   --  SURFACE RANGE, AZIMUTH, ALTITUDE GIVEN
  6922.          R := RXSE;
  6923.          A := AYAA;
  6924.          H := HZEH;
  6925.          U0 := R/RADIUS_OF_EARTH_IN_KM;
  6926.          U2 := A*RADIANS_PER_DEGREE;
  6927.          U3 := RADIUS_OF_EARTH_IN_KM + H;
  6928.          U1 := U3*SIN(U0);
  6929.          X := U1*SIN(U2);
  6930.          Y := U1*COS(U2);
  6931.          Z := U3*COS(U0) - REH;
  6932.          If U0 = 0.0 Then
  6933.             Z := H - HO;
  6934.          End If;
  6935.          If U1 = 0.0 Then
  6936.             S := ABS(Z);
  6937.             E := 90.0;
  6938.             If Z < 0.0 Then
  6939.                E := -90.0;
  6940.             End If;
  6941.          Else
  6942.             S := SQRT(U1**2 + Z**2);
  6943.             E := ASIN(Z/S)*DEGREES_PER_RADIAN;
  6944.          End If;
  6945.          Return;
  6946.       End If;
  6947. --
  6948.       If MODE = 2 Then  --  X,Y,Z COORDINATES GIVEN
  6949.          X := RXSE;
  6950.          Y := AYAA;
  6951.          Z := HZEH;
  6952.          U1 := X**2 + Y**2;
  6953.          If U1 = 0.0 Then
  6954.             R := 0.0;
  6955.             A := 0.0;
  6956.             H := HO + Z;
  6957.             S := ABS(Z);
  6958.             E := 90.0;
  6959.             If Z < 0.0 Then
  6960.                E := -90.0;
  6961.             End If;
  6962.          Else
  6963.             U2 := REH + Z;
  6964.             U3 := SQRT(U1 + U2**2);
  6965.             U1 := SQRT(U1);
  6966.             R := ASIN(U1/U3)*RADIUS_OF_EARTH_IN_KM;
  6967.             If U2 < 0.0 Then
  6968.                R := PI*RADIUS_OF_EARTH_IN_KM - R;
  6969.             End If;
  6970.             A := ASIN(X/U1)*DEGREES_PER_RADIAN;
  6971.             If Y < 0.0 Then
  6972.                A := 180.0 - A;
  6973.             End If;
  6974.             H := U3 - RADIUS_OF_EARTH_IN_KM;
  6975.             S := SQRT(U1**2 + Z**2);
  6976.             E := ASIN(Z/S)*DEGREES_PER_RADIAN;
  6977.          End If;
  6978.          Return;
  6979.       End If;
  6980. --
  6981.       If MODE = 3 Then  --  SLANT RANGE, AZIMUTH, ELEVATION GIVEN
  6982.          S := RXSE;
  6983.          A := AYAA;
  6984.          E := HZEH;
  6985.          U2 := A*RADIANS_PER_DEGREE;
  6986.          U3 := E*RADIANS_PER_DEGREE;
  6987.          U1 := S*COS(U3);
  6988.          X := U1*SIN(U2);
  6989.          Y := U1*COS(U2);
  6990.          Z := S*SIN(U3);
  6991.          U2 := REH + Z;
  6992.          U3 := SQRT(U1**2 + U2**2);
  6993.          R := ASIN(U1/U3)*RADIUS_OF_EARTH_IN_KM;
  6994.          If U2 < 0.0 Then
  6995.             R := PI*RADIUS_OF_EARTH_IN_KM - R;
  6996.          End If;
  6997.          H := U3 - RADIUS_OF_EARTH_IN_KM;
  6998.          Return;
  6999.       End If;
  7000. --
  7001.       If MODE = 4 Then  --  ELEVATION, AZIMUTH, ALTITUDE GIVEN
  7002.          E := RXSE;
  7003.          A := AYAA;
  7004.          H := HZEH;
  7005.          U2 := A*RADIANS_PER_DEGREE;
  7006.          U3 := E*RADIANS_PER_DEGREE;
  7007.          COSE := COS(U3);
  7008.          SINE := SIN(U3);
  7009.          S := HTOS (HO, H, COSE, SINE);
  7010.          U1 := S*COSE;
  7011.          X := U1*SIN(U2);
  7012.          Y := U1*COS(U2);
  7013.          Z := S*SINE;
  7014.          U3 := RADIUS_OF_EARTH_IN_KM + H;
  7015.          R := ASIN(U1/U3)*RADIUS_OF_EARTH_IN_KM;
  7016.          If REH + Z < 0.0 Then
  7017.             R := PI*RADIUS_OF_EARTH_IN_KM - R;
  7018.          End If;
  7019.       End If;
  7020.       Return;
  7021. --
  7022.       End COORDX;
  7023. --
  7024. --
  7025.       Function CTANH (VAL: complex) return complex is
  7026. --
  7027. --#PURPOSE: CTANH computes complex hyperbolic tangent.
  7028. --
  7029. --#AUTHOR:  J. Conrad
  7030. --
  7031. --#TYPE:    Numerical Analysis
  7032. --
  7033. --#PARAMETER DESCRIPTIONS:
  7034. --IN        VAL    = Input value array (a complex number)
  7035. --OUT       CTANH  = Computed complex hyperbolic tangent array 
  7036. --                   (a complex number)
  7037. --
  7038. --#CALLED BY:
  7039. --          REFCAL
  7040. --
  7041. --#CALLS TO:
  7042. --          'NONE'
  7043. --
  7044. --#TECHNICAL DESCRIPTION:
  7045. --          CTANH computes complex hyperbolic tangent using:
  7046. --
  7047. --             CTANH = CMPLX(SINH(X), SIN(Y))/(COSH(X) + COS(Y))
  7048. --
  7049. --              where:
  7050. --                 X := 2.0*AREAL(VAL)     the real part
  7051. --                 Y := 2.0*AIMAG(VAL)     the imaginary part
  7052. --
  7053.       X, Y: float;
  7054. --
  7055.       Begin
  7056. --
  7057.       X := 2.0*AREAL(VAL);
  7058.       Y := 2.0*AIMAG(VAL);
  7059.       If X <= 86.0 Then
  7060.          Return (CMPLX(SINH(X), SIN(Y))/(COSH(X) + COS(Y)));
  7061.       Else
  7062.          Return CMPLX(1.0, 0.0);
  7063.       End If;
  7064. --
  7065.       End CTANH;
  7066. --
  7067. --
  7068.       Procedure DAYNIT (IDN: out DAY_OR_NIGHT;
  7069.                         TLON: in float;
  7070.                         RLON: in float) is
  7071. --
  7072. --#PURPOSE: DAYNIT determines whether transmission on a given link
  7073. --          is in daytime, nighttime, or mixed day-night conditions.
  7074. --
  7075. --#AUTHOR:  J. Conrad
  7076. --
  7077. --#TYPE:    Numerical Analysis
  7078. --
  7079. --#PARAMETER DESCRIPTIONS:
  7080. --OUT       IDN    = Indicator as to whether day or night
  7081. --                   conditions prevail over the link;
  7082. --IN        TLON   = Transmitter longitude in degrees east
  7083. --IN        RLON   = Receiver longitude in degrees east
  7084. --
  7085. --#CALLED BY:
  7086. --          ELF_HANDLER
  7087. --          LF_HANDLER
  7088. --          REFCAL
  7089. --
  7090. --#CALLS TO:
  7091. --          'NONE'
  7092. --
  7093. --#TECHNICAL DESCRIPTION:
  7094. --          The day-night indicator is set according to the sun
  7095. --          conditions prevailing at the longitude midway between the
  7096. --          transmitter and the receiver.  The seasonal tilt of the
  7097. --          earth's axis is ignored.
  7098. --
  7099.       NHR, III: integer;
  7100.       SUNRIS, SUNSET, T1, T2, CENLON: float;
  7101. --
  7102.       Begin
  7103. --
  7104.       NHR := INTEGER(REFERENCE_TIME/100.0);
  7105.       SUNRIS := -90.0 - FLOAT(NHR)*15.0 - 
  7106.                 (REFERENCE_TIME - 100.0*FLOAT(NHR))*0.25 - 
  7107.                  CURRENT_TIME*0.25;
  7108.       Loop
  7109.          Exit When SUNRIS > -180.0;
  7110.          SUNRIS := SUNRIS + 360.0;
  7111.       End Loop;
  7112.       SUNSET := SUNRIS + 180.0;
  7113.       If SUNSET > 180.0 Then
  7114.          SUNSET := SUNSET - 360.0;
  7115.       End If;
  7116.       If SUNRIS >= SUNSET Then
  7117.          III := 1;
  7118.          T1 := SUNRIS;
  7119.          T2 := SUNSET;
  7120.       Else
  7121.          III := 0;
  7122.          T1 := SUNSET;
  7123.          T2 := SUNRIS;
  7124.       End If;
  7125.       CENLON := (TLON + RLON)*0.5;
  7126.       If ABS(TLON - RLON) > 180.0 Then
  7127.          CENLON := CENLON + 180.0;
  7128.          If CENLON > 180.0 Then
  7129.             CENLON := CENLON - 360.0;
  7130.          End If;
  7131.       End If;
  7132.       If CENLON >= T1  and  CENLON <= T2 Then
  7133.          III := 1 - III;
  7134.       End If;
  7135.       If III = 0 Then
  7136.          IDN := NIGHT;
  7137.       Else
  7138.          IDN := DAY;
  7139.       End If;
  7140. --
  7141.       Return;
  7142. --
  7143.       End DAYNIT;
  7144. --
  7145. --
  7146.       Procedure DNTR is
  7147. --
  7148. --#PURPOSE: DNTR determines if and where a day-night terminator
  7149. --          crosses a transmitter/receiver path.
  7150. --
  7151. --#AUTHOR:  J. Conrad
  7152. --
  7153. --#TYPE:    Numerical Analysis
  7154. --
  7155. --#PARAMETER DESCRIPTIONS:
  7156. --OUT       IDNT & IDNR (globally visible -- see technical description)
  7157. --
  7158. --#CALLED BY:
  7159. --          ELF_HANDLER
  7160. --          MF_HF_HANDLER
  7161. --          VLF_HANDLER
  7162. --
  7163. --#CALLS TO:
  7164. --          LOCNEW
  7165. --          ZENITH
  7166. --
  7167. --#TECHNICAL DESCRIPTION:
  7168. --          Subroutine ZENITH is used to determine IDNT and IDNR.
  7169. --          If both are in day or night, the other outputs are set and
  7170. --          there is a return to the calling program.  If IDNT /=
  7171. --          IDNR, a terminator crosses the path.  The location of the
  7172. --          terminator is established by iteration on LOCNEW and ZENITH.
  7173. --          Each iteration divides the path in half until the location
  7174. --          of the intersection of the terminator and communication
  7175. --          path is known within 100 Km.  All output from DNTR is via
  7176. --          the globally visible variables IDNT and IDNR.
  7177. --
  7178.       IT: array (integer range 1..3) of DAY_OR_NIGHT;
  7179.       DX: array (integer range 1..3) of float;
  7180.       ERR, XLAT, XLON, CHI, TOD: float;
  7181. --
  7182.       Begin
  7183. --
  7184.       DISTOT := DPATH;
  7185.       ZENITH (TLAT, TLON, CHI, TOD, IT(1));
  7186.       IDNT := IT(1);
  7187.       ZENITH (RLAT, RLON, CHI, TOD, IT(3));
  7188.       IDNR := IT(3);
  7189.       TRBRNG := BRNG1;
  7190.       RTBRNG := BRNG2;
  7191.       DISDAY := DPATH;
  7192.       DISNIT := 0.0;
  7193.       TERLAT := -1000.0;
  7194.       TERLON := -1000.0;
  7195.       If IDNT = NIGHT and IDNR = NIGHT Then
  7196.           DISDAY := 0.0;
  7197.           DISNIT := DPATH;
  7198.       End If;
  7199.       If IDNT = IDNR Then
  7200.          Return;
  7201.       End If;
  7202. --
  7203. --  FIND DAY-NIGHT TERMINATOR.
  7204.       DX(1) := 0.0;
  7205.       DX(3) := DPATH;
  7206.       DX(2) := 0.5*DPATH;
  7207. --
  7208.       Loop
  7209.          NODELOC.LOCNEW (TLAT, TLON, BRNG1, DX(2), XLAT, XLON);
  7210.          ZENITH (XLAT, XLON, CHI, TOD, IT(2));
  7211.          If IT(2) = IT(1) Then
  7212.             DX(1) := DX(2);
  7213.          End If;
  7214.          If IT(2) = IT(3) Then
  7215.             DX(3) := DX(2);
  7216.          End If;
  7217.          DX(2) := (DX(1) + DX(3))*0.5;
  7218.          ERR := ABS((DX(3) - DX(2))/DPATH);
  7219.          Exit When ERR <= 1.0E-5;
  7220.       End Loop;
  7221.       NODELOC.LOCNEW (TLAT, TLON, BRNG1, DX(2), TERLAT, TERLON);
  7222.       DISDAY := DX(2);
  7223.       If IDNT = NIGHT Then
  7224.           DISDAY := DPATH - DISDAY;
  7225.       End If;
  7226.       DISNIT := DPATH - DISDAY;
  7227.       End DNTR;
  7228. --
  7229. --
  7230.       Procedure GNDCON (XLAT: in float;
  7231.                         XLONG: in float;
  7232.                         COND: out float) is
  7233. --
  7234. --#PURPOSE: GNDCON computes the ground conductivity at a location
  7235. --          on the earth's surface, given the latitude and longitude
  7236. --          of the location.
  7237. --
  7238. --#AUTHOR:  J. Conrad
  7239. --
  7240. --#TYPE:    Table Look-up.
  7241. --
  7242. --#PARAMETER DESCRIPTIONS:
  7243. --IN        XLAT   = Latitude (north positive)
  7244. --IN        XLONG  = Longitude (east positive)
  7245. --OUT       COND   = Ground conductivity in Mhos/m.
  7246. --
  7247. --#CALLED BY:
  7248. --          MF_HF_HANDLER
  7249. --          LF_HANDLER
  7250. --          VLF_HANDLER
  7251. --
  7252. --#CALLS TO:
  7253. --          'NONE'
  7254. --
  7255. --#TECHNICAL DESCRIPTION:
  7256. --          A ground gonductivity map has been specified with
  7257. --          a granularity of 5 degrees (i.e., the map is separated
  7258. --          into 5 degree X 5 degree boxes) with one of eight
  7259. --          conductivity code numbers is assigned to each box.
  7260. --          A ground conductivity is associated with each code
  7261. --          number.
  7262. --
  7263. --          When the latitude and longitude of a location
  7264. --          are input, the appropriate box is referenced.  The ground
  7265. --          conductivity associated with the conductivity code of this
  7266. --          referenced box is returned to the calling routine.
  7267. --
  7268.       SIGMA: array (integer range 1..8) of float
  7269.       := (1.0E-5, 1.0E-4, 3.0E-4, 1.0E-3, 3.0E-3, 1.0E-2, 5.0E-2, 4.0);
  7270.       IA, IB, ILAT, ILONG, ICODE: integer;
  7271.       XLAT_TEMP: float:=XLAT;
  7272.  
  7273. --DATA TO DEFINE THE GROUND CONDUCTIVITY MAP:
  7274. --
  7275.       NCODE: array (integer range 1..72, integer range 1..36) of integer
  7276.       :=((8,  8,  8,  8,  8,  8,  8,  8,  6,  7,  8,  7,
  7277.           7,  5,  6,  6,  5,  8,  8,  8,  8,  8,  8,  8,
  7278.           8,  8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1),
  7279.          (8,  8,  8,  8,  8,  6,  7,  7,  7,  8,  8,  7,
  7280.           7,  5,  7,  6,  5,  8,  8,  8,  8,  8,  8,  8,
  7281.           8,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7282.          (8,  8,  6,  3,  7,  6,  7,  7,  6,  8,  8,  7,
  7283.           7,  7,  7,  7,  5,  5,  5,  6,  6,  6,  8,  8,
  7284.           8,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7285.          (8,  8,  5,  8,  6,  6,  7,  7,  7,  7,  8,  8,
  7286.           7,  6,  7,  7,  6,  5,  6,  6,  6,  6,  5,  6,
  7287.           7,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7288.          (8,  7,  6,  8,  6,  6,  7,  7,  7,  6,  7,  8,
  7289.           7,  7,  6,  5,  5,  5,  6,  6,  7,  7,  7,  6,
  7290.           7,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7291.          (8,  8,  8,  7,  5,  6,  6,  6,  7,  7,  7,  8,
  7292.           7,  7,  6,  5,  5,  5,  5,  6,  6,  6,  5,  6,
  7293.           7,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7294.          (8,  8,  8,  8,  6,  6,  7,  7,  7,  8,  6,  8,
  7295.           6,  6,  6,  5,  7,  5,  5,  5,  5,  5,  7,  7,
  7296.           8,  8,  8,  8,  8,  8,  8,  6,  2,  1,  1,  1),
  7297.          (8,  8,  8,  8,  6,  7,  7,  7,  7,  8,  7,  7,
  7298.           7,  6,  5,  6,  6,  5,  5,  5,  5,  6,  8,  8,
  7299.           8,  8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1),
  7300.          (8,  8,  8,  8,  7,  7,  7,  7,  7,  6,  7,  7,
  7301.           6,  5,  6,  6,  6,  7,  8,  8,  8,  8,  8,  8,
  7302.           8,  8,  8,  8,  8,  8,  8,  5,  2,  1,  1,  1),
  7303.          (8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  6,  7,
  7304.           7,  7,  7,  7,  7,  8,  8,  8,  7,  6,  6,  8,
  7305.           8,  8,  8,  8,  8,  8,  8,  4,  2,  1,  1,  1),
  7306.          (8,  8,  8,  6,  7,  7,  7,  7,  7,  8,  7,  6,
  7307.           7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7308.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7309.          (8,  8,  7,  5,  6,  6,  6,  5,  7,  7,  6,  7,
  7310.           7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7311.           8,  8,  8,  8,  8,  8,  8,  4,  1,  1,  1,  1),
  7312.          (8,  7,  5,  8,  5,  6,  6,  6,  7,  7,  7,  7,
  7313.           7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7314.           8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  1,  1),
  7315.          (8,  8,  6,  7,  5,  7,  7,  7,  7,  7,  6,  7,
  7316.           7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7317.           8,  8,  8,  8,  8,  8,  8,  5,  3,  2,  1,  1),
  7318.          (8,  8,  8,  6,  5,  6,  7,  7,  7,  7,  5,  7,
  7319.           7,  6,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7320.           8,  8,  8,  8,  8,  8,  8,  5,  2,  2,  1,  1),
  7321.          (8,  8,  8,  6,  5,  6,  7,  7,  7,  7,  5,  5,
  7322.           7,  6,  6,  6,  8,  8,  8,  8,  8,  8,  8,  8,
  7323.           8,  8,  8,  8,  8,  8,  8,  5,  2,  2,  1,  1),
  7324.          (8,  8,  8,  6,  5,  6,  7,  7,  7,  7,  6,  6,
  7325.           6,  6,  7,  8,  7,  8,  8,  8,  8,  8,  8,  8,
  7326.           8,  8,  8,  8,  8,  8,  8,  4,  1,  2,  1,  1),
  7327.          (8,  8,  8,  5,  5,  6,  7,  6,  6,  7,  5,  6,
  7328.           6,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7329.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7330.          (8,  7,  7,  5,  4,  5,  5,  5,  5,  7,  6,  6,
  7331.           5,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7332.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7333.          (8,  8,  6,  5,  4,  5,  6,  4,  5,  7,  7,  6,
  7334.           6,  6,  7,  8,  8,  7,  8,  8,  8,  8,  8,  8,
  7335.           8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1,  1),
  7336.          (8,  8,  5,  4,  4,  5,  6,  5,  4,  7,  7,  7,
  7337.           6,  6,  7,  7,  8,  8,  7,  8,  8,  8,  8,  8,
  7338.           8,  8,  8,  8,  8,  8,  8,  2,  1,  1,  1,  1),
  7339.          (8,  8,  6,  4,  4,  5,  5,  5,  5,  7,  7,  7,
  7340.           7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,
  7341.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7342.          (8,  8,  7,  5,  4,  5,  4,  4,  5,  7,  7,  7,
  7343.           6,  7,  8,  8,  8,  7,  7,  8,  8,  8,  8,  8,
  7344.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7345.          (8,  8,  8,  5,  4,  5,  3,  4,  5,  7,  7,  7,
  7346.           6,  8,  8,  8,  8,  7,  8,  8,  8,  8,  5,  5,
  7347.           5,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7348.          (8,  8,  8,  5,  5,  5,  3,  4,  5,  7,  8,  8,
  7349.           8,  8,  8,  8,  8,  8,  7,  8,  8,  7,  5,  5,
  7350.           5,  8,  8,  8,  8,  8,  8,  3,  1,  1,  1,  1),
  7351.          (8,  8,  8,  6,  5,  5,  4,  4,  5,  5,  6,  8,
  7352.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  6,  6,
  7353.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  2,  2),
  7354.          (8,  8,  8,  7,  5,  5,  4,  4,  6,  8,  8,  8,
  7355.           8,  8,  8,  8,  8,  8,  8,  8,  7,  6,  6,  6,
  7356.           8,  8,  8,  8,  8,  8,  8,  3,  1,  1,  2,  2),
  7357.          (8,  8,  7,  7,  5,  5,  4,  6,  7,  8,  8,  8,
  7358.           8,  8,  8,  8,  8,  8,  7,  8,  8,  6,  6,  7,
  7359.           6,  8,  8,  8,  8,  8,  8,  3,  1,  1,  2,  2),
  7360.          (8,  8,  7,  6,  5,  5,  7,  8,  8,  8,  8,  8,
  7361.           8,  8,  8,  8,  8,  8,  8,  7,  8,  7,  7,  7,
  7362.           7,  7,  8,  8,  8,  8,  8,  3,  1,  1,  3,  2),
  7363.          (8,  8,  8,  6,  5,  5,  8,  8,  8,  8,  8,  8,
  7364.           8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,
  7365.           6,  7,  8,  8,  8,  8,  8,  4,  2,  1,  3,  2),
  7366.          (8,  8,  8,  7,  5,  5,  8,  8,  8,  8,  8,  8,
  7367.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,
  7368.           7,  8,  8,  8,  8,  8,  8,  5,  2,  2,  3,  2),
  7369.          (8,  8,  8,  7,  5,  5,  7,  7,  8,  8,  8,  8,
  7370.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7371.           8,  8,  8,  8,  8,  8,  8,  8,  2,  3,  3,  2),
  7372.          (8,  8,  8,  8,  5,  5,  7,  8,  8,  8,  8,  8,
  7373.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7374.           8,  8,  8,  8,  8,  8,  8,  8,  3,  4,  3,  2),
  7375.          (8,  8,  8,  8,  5,  5,  8,  8,  8,  8,  8,  8,
  7376.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7377.           8,  8,  8,  8,  8,  8,  8,  8,  4,  5,  3,  2),
  7378.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7379.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7380.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  4,  2),
  7381.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7382.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7383.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  4,  2),
  7384.          (8,  8,  8,  8,  5,  8,  8,  8,  8,  8,  8,  8,
  7385.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7386.           8,  8,  8,  8,  8,  8,  8,  8,  8,  6,  4,  3),
  7387.          (8,  8,  8,  8,  6,  8,  8,  8,  8,  8,  8,  8,
  7388.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7389.           8,  8,  8,  8,  8,  8,  8,  8,  8,  6,  4,  3),
  7390.          (8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7391.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7392.           8,  8,  8,  8,  8,  8,  8,  8,  8,  6,  4,  2),
  7393.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7394.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7395.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  4,  2),
  7396.          (8,  8,  8,  8,  5,  6,  7,  8,  8,  8,  8,  8,
  7397.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7398.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  4,  2),
  7399.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7400.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7401.           8,  8,  8,  8,  8,  8,  8,  8,  8,  4,  3,  2),
  7402.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7403.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7404.           8,  8,  8,  8,  8,  8,  8,  8,  8,  3,  3,  2),
  7405.          (8,  8,  8,  8,  5,  6,  8,  8,  8,  8,  8,  8,
  7406.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7407.           8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  2),
  7408.          (8,  8,  8,  8,  6,  6,  8,  8,  8,  8,  8,  8,
  7409.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7410.           8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  2),
  7411.          (8,  8,  8,  8,  5,  6,  6,  8,  8,  8,  8,  8,
  7412.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7413.           8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  2,  2),
  7414.          (8,  8,  8,  8,  5,  6,  6,  6,  8,  8,  8,  8,
  7415.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7416.           8,  8,  8,  8,  8,  8,  8,  8,  5,  2,  2,  2),
  7417.          (8,  8,  7,  5,  5,  6,  7,  6,  7,  7,  7,  8,
  7418.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7419.           8,  8,  8,  8,  8,  8,  8,  8,  5,  2,  2,  2),
  7420.          (8,  8,  5,  5,  4,  5,  7,  5,  6,  6,  6,  7,
  7421.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7422.           8,  8,  8,  8,  8,  8,  8,  8,  6,  1,  2,  2),
  7423.          (8,  8,  5,  4,  4,  4,  6,  7,  7,  7,  7,  7,
  7424.           7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7425.           8,  8,  8,  8,  8,  8,  8,  8,  6,  1,  1,  2),
  7426.          (8,  8,  6,  5,  4,  4,  5,  7,  7,  7,  7,  7,
  7427.           6,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7428.           8,  8,  8,  8,  8,  8,  8,  8,  7,  1,  1,  2),
  7429.          (8,  8,  5,  6,  4,  4,  4,  7,  7,  7,  7,  7,
  7430.           7,  6,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7431.           8,  8,  8,  8,  8,  8,  8,  8,  5,  1,  1,  2),
  7432.          (8,  8,  4,  5,  4,  4,  4,  6,  6,  7,  7,  7,
  7433.           7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7434.           8,  8,  8,  8,  8,  8,  8,  8,  4,  1,  1,  2),
  7435.          (8,  6,  4,  4,  3,  5,  6,  5,  5,  7,  7,  7,
  7436.           8,  8,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7437.           8,  8,  8,  8,  8,  8,  8,  8,  4,  1,  2,  2),
  7438.          (8,  5,  4,  4,  4,  8,  8,  5,  6,  7,  7,  7,
  7439.           8,  8,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,
  7440.           8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  2),
  7441.          (8,  4,  3,  3,  5,  6,  8,  7,  5,  7,  5,  5,
  7442.           7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7443.           8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  2),
  7444.          (8,  3,  4,  3,  6,  5,  4,  4,  5,  7,  5,  8,
  7445.           8,  8,  8,  8,  7,  7,  7,  7,  3,  8,  8,  8,
  7446.           8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  2),
  7447.          (8,  3,  6,  4,  3,  4,  3,  3,  4,  6,  8,  8,
  7448.           8,  8,  8,  8,  7,  7,  7,  7,  6,  7,  8,  8,
  7449.           7,  7,  7,  6,  6,  8,  8,  8,  3,  3,  2,  2),
  7450.          (8,  5,  3,  8,  3,  5,  3,  3,  5,  8,  8,  8,
  7451.           8,  8,  8,  8,  6,  5,  6,  7,  7,  6,  5,  5,
  7452.           6,  7,  7,  7,  8,  8,  8,  5,  3,  3,  2,  2),
  7453.          (8,  5,  2,  8,  4,  8,  5,  3,  7,  8,  8,  8,
  7454.           8,  8,  8,  8,  6,  5,  6,  6,  6,  6,  7,  7,
  7455.           7,  7,  7,  8,  8,  8,  7,  3,  3,  3,  2,  2),
  7456.          (8,  4,  1,  8,  8,  8,  8,  5,  6,  8,  8,  8,
  7457.           8,  8,  8,  8,  7,  5,  6,  6,  6,  7,  7,  7,
  7458.           7,  8,  8,  8,  8,  8,  7,  8,  8,  4,  2,  2),
  7459.          (8,  4,  1,  2,  4,  8,  8,  8,  7,  8,  8,  8,
  7460.           8,  8,  8,  8,  8,  5,  6,  5,  6,  7,  7,  7,
  7461.           7,  8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2),
  7462.          (8,  3,  1,  1,  1,  2,  8,  8,  8,  8,  8,  8,
  7463.           8,  8,  8,  8,  8,  8,  7,  6,  5,  6,  6,  7,
  7464.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  3,  2),
  7465.          (8,  3,  1,  1,  1,  2,  8,  8,  8,  8,  8,  8,
  7466.           8,  8,  8,  8,  8,  8,  7,  6,  5,  5,  6,  8,
  7467.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  3,  2),
  7468.          (8,  3,  1,  1,  2,  8,  8,  8,  8,  8,  8,  8,
  7469.           8,  8,  8,  8,  8,  8,  7,  5,  7,  7,  8,  8,
  7470.           8,  8,  8,  8,  8,  8,  8,  8,  8,  5,  3,  2),
  7471.          (8,  3,  1,  1,  3,  8,  8,  8,  8,  8,  8,  8,
  7472.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7473.           8,  8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2),
  7474.          (8,  4,  1,  1,  8,  8,  8,  8,  8,  8,  8,  8,
  7475.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7476.           8,  8,  8,  8,  8,  8,  8,  8,  8,  3,  2,  2),
  7477.          (8,  5,  2,  3,  8,  8,  8,  8,  8,  8,  8,  8,
  7478.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7479.           8,  8,  8,  8,  8,  8,  8,  8,  6,  3,  2,  2),
  7480.          (8,  5,  6,  8,  8,  7,  8,  8,  8,  8,  8,  8,
  7481.           8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7482.           8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  2),
  7483.          (8,  6,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
  7484.           7,  5,  6,  6,  6,  8,  8,  8,  8,  8,  8,  8,
  7485.           8,  8,  8,  8,  8,  8,  8,  8,  4,  2,  2,  2),
  7486.          (8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,
  7487.           6,  6,  7,  5,  5,  8,  8,  8,  8,  8,  8,  8,
  7488.           8,  8,  8,  8,  8,  8,  8,  8,  3,  2,  2,  2),
  7489.          (8,  8,  8,  8,  8,  8,  7,  8,  7,  7,  7,  7,
  7490.           7,  7,  7,  5,  5,  8,  8,  8,  8,  8,  8,  8,
  7491.           8,  8,  8,  8,  8,  8,  8, 8 ,  3,  2,  2,  2)); 
  7492.  
  7493. --
  7494.       Begin
  7495. --
  7496.       IA := 1;
  7497.       IB := 1;
  7498.       If XLAT < 0.0 Then
  7499.          IA := 0;
  7500.       End If;
  7501.       If XLONG < 0.0 Then
  7502.          IB := 0;
  7503.       End If;
  7504.       If XLAT = 90.0 Then
  7505.          XLAT_TEMP := 89.0;
  7506.       End If;
  7507.       If XLAT = -90.0 Then
  7508.          XLAT_TEMP := -89.0;
  7509.       End If;
  7510. --
  7511.       ILAT := INTEGER(TRUNCATE(XLAT_TEMP/5.0));
  7512.       ILAT := ILAT + IA;
  7513.       ILONG := INTEGER(TRUNCATE(XLONG/5.0));
  7514.       ILONG := ILONG + IB;
  7515.       ILAT := 19 - ILAT;
  7516.       If XLONG < 0.0 Then
  7517.          ILONG := 72 + ILONG;
  7518.       End If;
  7519. --
  7520.       ICODE := NCODE(ILONG, ILAT);
  7521.       COND := SIGMA(ICODE);
  7522. --
  7523.       Return;
  7524. --
  7525.       End GNDCON;
  7526. --
  7527. --
  7528.       Function HTOS (H1: float;
  7529.                      H2: float;
  7530.                      COSE: float;
  7531.                      SINE: float) return float is
  7532. --
  7533. --#PURPOSE: HTOS computes the slant range between two points, given
  7534. --          their altitudes and the elevation angle of point 2 with
  7535. --          respect to point 1.
  7536. --
  7537. --#AUTHOR:  J. Conrad
  7538. --
  7539. --#TYPE:    Numerical Analysis
  7540. --
  7541. --#PARAMETER DESCRIPTIONS:
  7542. --IN        H1     = Altitude of point 1 in km
  7543. --IN        H2     = Altitude of point 2 in km
  7544. --IN        COSE   = Elevation of point 2 with respect to point1, cosine
  7545. --IN        SINE   = Elevation of point 2 with respect to point1, sine
  7546. --OUT       HTOS   = Slant range between the points in km
  7547. --
  7548. --#CALLED BY:
  7549. --          COORDX
  7550. --
  7551. --#CALLS TO:
  7552. --          'NONE'
  7553. --
  7554. --#TECHNICAL DESCRIPTION:
  7555. --          HTOS computes the slant range between two points, given
  7556. --          their altitudes and the elevation angle of point 2 with
  7557. --          respect to point 1.  Standard spherical trigonometry is
  7558. --          used to perform the computation.
  7559. --
  7560.       R1, R2, SIND, COSD: float;
  7561. --
  7562.       Begin
  7563. --
  7564.       R1 := RADIUS_OF_EARTH_IN_KM + H1;
  7565.       R2 := RADIUS_OF_EARTH_IN_KM + H2;
  7566.       SIND := R1*COSE/R2;
  7567.       SIND := AMIN1(SIND,1.0);
  7568.       COSD := SQRT(1.0 - SIND**2);
  7569.       Return R2*COSD - R1*SINE;
  7570. --
  7571.       End HTOS;
  7572. --
  7573. --
  7574.       Function LOS (XLA1: float;
  7575.                     XLO1: float;
  7576.                     AL1: float;
  7577.                     XLA2: float;
  7578.                     XLO2: float;
  7579.                     AL2: float) return boolean is
  7580. --
  7581. --#PURPOSE: LOS determines if there is a line-of-sight path between
  7582. --          a point above the earth's surface and point on or above
  7583. --          the earth's surface.
  7584. --
  7585. --#AUTHOR:  J. Conrad
  7586. --
  7587. --#TYPE:    Numerical Analysis
  7588. --
  7589. --#PARAMETER DESCRIPTIONS:
  7590. --IN        XLA1   = Latitude of first point in radians
  7591. --IN        XLO1   = Longitude of first point in radians
  7592. --IN        AL1    = Altitude of first point in kilometers
  7593. --IN        XLA2   = Latitude of second point in radians
  7594. --IN        XLO2   = Longitude of second point in radians
  7595. --IN        AL2    = Altitude of second point in kilometers
  7596. --OUT       LOS    = TRUE or FALSE as to whether line-of-sight exists
  7597. --
  7598. --#CALLED BY:
  7599. --          RF_PROPAGATION_HANDLER
  7600. --          VHF_UHF_SHF_EHF_HANDLER
  7601. --
  7602. --#CALLS TO:
  7603. --          'NONE'
  7604. --
  7605. --#TECHNICAL DESCRIPTION:
  7606. --          This routine first determines which point is higher and
  7607. --          makes it point 1.  The remaining point becomes point 2.
  7608. --          The routine operates by determining the angular
  7609. --          width, A, of the cone subtended by the earth at point l as
  7610. --          well as the distance, DISN, from point 1 to a tangential
  7611. --          intersection with the earth.  Point 2 is in line-of-sight
  7612. --          from point 1 if either point 2 is outside the shadow cone
  7613. --          subtended by the earth or if point 2 is closer than the
  7614. --          tangential distance, DISN.
  7615. --
  7616.       PONE: array (integer range 1..3) of float;
  7617.       PTWO: array (integer range 1..3) of float;
  7618.       XLAT1, XLON1, ALT1, RHO1, XLAT2, XLON2, ALT2, RHO2: float;
  7619.       A1, A2, B1, B2, C1, C2: float;
  7620.       DISC, DISO, DISN, COSA, A, H, COSB: float;
  7621. --
  7622.       Begin
  7623. --
  7624. --  TEST FOR COLOCATION
  7625.       If (XLA1 = XLA2 and XLO1 = XLO2 and AL1 = AL2) Then
  7626.          Return TRUE;
  7627.       End If;
  7628. --  CONVERT TO ECI COORDINATES
  7629.       If (AL2 - AL1) >= 0.0 Then
  7630.          XLAT1 := XLA1;
  7631.          XLON1 := XLO1;
  7632.          ALT1 := AL1;
  7633.          XLAT2 := XLA2;
  7634.          XLON2 := XLO2;
  7635.          ALT2 := AL2;
  7636.       Else
  7637.          XLAT1 := XLA2;
  7638.          XLON1 := XLO2;
  7639.          ALT1 := AL2;
  7640.          XLAT2 := XLA1;
  7641.          XLON2 := XLO1;
  7642.          ALT2 := AL1;
  7643.       End If;
  7644. --
  7645.       RHO1 := RADIUS_OF_EARTH_IN_KM + ALT1;
  7646.       PONE(1) := RHO1*COS(XLAT1)*COS(XLON1);
  7647.       PONE(2) := RHO1*COS(XLAT1)*SIN(XLON1);
  7648.       PONE(3) := RHO1*SIN(XLAT1);
  7649.       RHO2 := RADIUS_OF_EARTH_IN_KM + ALT2;
  7650.       PTWO(1) := RHO2*COS(XLAT2)*COS(XLON2);
  7651.       PTWO(2) := RHO2*COS(XLAT2)*SIN(XLON2);
  7652.       PTWO(3) := RHO2*SIN(XLAT2);
  7653. --
  7654. --  FIND DIRECTION NUMBERS FOR EARTH CENTER TO TRANSMITTER AND
  7655. --  TRANSMITTER TO RECEIVER VECTORS
  7656.       A1 := -PONE(1);
  7657.       A2 := PTWO(1) - PONE(1);
  7658.       B1 := -PONE(2);
  7659.       B2 := PTWO(2) - PONE(2);
  7660.       C1 := -PONE(3);
  7661.       C2 := PTWO(3) - PONE(3);
  7662. --
  7663. --  RESPECTIVE DISTANCES OF POINTS IN SPACE
  7664.       DISC := RADIUS_OF_EARTH_IN_KM + ALT1;
  7665.       DISO := SQRT(A2**2 + B2**2 + C2**2);
  7666.       DISN := SQRT(ALT1**2 + 2.0*ALT1*RADIUS_OF_EARTH_IN_KM);
  7667. --
  7668. --  ANGLE OF EARTH SHADOW
  7669.       COSA := DISN/DISC;
  7670. --
  7671. --  DIRECTION COSINE FOR LOS ANGLE
  7672.       A := A1*A2 + B1*B2 + C1*C2;
  7673.       H := DISC*DISO;
  7674.       COSB := A/H;
  7675. --
  7676. --  CAN TRANSMITTER SEE RECEIVER?
  7677.       If DISO <= DISN Then
  7678.          Return TRUE;
  7679.       End If;
  7680.       If COSA <= COSB Then
  7681.          Return FALSE;
  7682.       Else
  7683.          Return TRUE;
  7684.       End If;
  7685. --
  7686.       End LOS;
  7687. --
  7688. --
  7689.       Function PLYVAL (YARRAY: F_ARRAY;
  7690.                        MAXY: integer;
  7691.                        X: float) return float is
  7692. --
  7693. --#PURPOSE: PLYVAL evaluates a general polynomial in one variable.
  7694. --
  7695. --#AUTHOR:  J. Conrad
  7696. --
  7697. --#TYPE:    Numerical Analysis
  7698. --
  7699. --#PARAMETER DESCRIPTIONS:
  7700. --IN        YARRAY = The array of coefficients, highest order
  7701. --                   first
  7702. --IN        MAXY   = The number of coefficients in the polynomial
  7703. --                   including the zeroth order coefficient
  7704. --                   (= n + 1)
  7705. --IN        X      = The value of the independent variable at
  7706. --                   which the polynomial is to be calculated
  7707. --OUT       PLYVAL = The value of the polynomial (= f(x))
  7708. --
  7709. --#CALLED BY:
  7710. --          AOW
  7711. --          IONCAL
  7712. --
  7713. --#CALLS TO:
  7714. --          'NONE'
  7715. --
  7716. --#TECHNICAL DESCRIPTION:
  7717. --          PLYVAL evaluates a general polynomial in one variable.
  7718. --          A simple LOOP with a summation step is employed.
  7719. --
  7720.       SUM: float;
  7721.       I: integer;
  7722. --
  7723.       Begin
  7724. --
  7725.       SUM := YARRAY(1);
  7726.       For I in 2..MAXY Loop
  7727.          SUM := SUM*X + YARRAY(I);
  7728.       End Loop;
  7729.       Return SUM;
  7730. --
  7731.       End PLYVAL;
  7732. --
  7733. --
  7734.       Procedure ZENITH (XLAT: in float;
  7735.                         XLONG: in float;
  7736.                         CHI: out float;
  7737.                         TOD: out float;
  7738.                         IDN: out DAY_OR_NIGHT) is
  7739. --
  7740. --#PURPOSE: ZENITH calculates the local time of day and the solar
  7741. --          zenith angle and determines whether it is day or night.
  7742. --
  7743. --#AUTHOR:  J. Conrad
  7744. --
  7745. --#TYPE:    Numerical Analysis
  7746. --
  7747. --#PARAMETER DESCRIPTIONS:
  7748. --IN        XLAT   = Latitude in degrees north
  7749. --IN        XLONG  = Longitude in degrees east
  7750. --OUT       CHI    = Solar zenith angle in degrees
  7751. --OUT       TOD    = Local time of day in hours
  7752. --OUT       IDN    = Day/Night indicator
  7753. --
  7754. --#CALLED BY:
  7755. --          DNTR
  7756. --          MF_HF_HANDLER
  7757. --          NOISE_HANDLER
  7758. --
  7759. --#CALLS TO:
  7760. --          'NONE'
  7761. --
  7762. --#TECHNICAL DESCRIPTION:
  7763. --          Local time of day, TOD is calculated from:
  7764. --
  7765. --               TOD = (T+RT)/3600.0 + XLONG/15.0
  7766. --
  7767. --               Where:
  7768. --                     T = Current time in seconds
  7769. --                     RT = GMT reference time in seconds
  7770. --
  7771. --          Solar zenith angle, CHI is then calculated and if
  7772. --          less than or equal to 90 degrees it is deemed to be
  7773. --          daytime, otherwise it is night.
  7774. --
  7775.       T, RT, GT, SLAT, SLONG: float;
  7776.       NHR: integer;
  7777. --
  7778.       Begin
  7779. --
  7780.       T := CURRENT_TIME*60.0;
  7781.       NHR := INTEGER(REFERENCE_TIME*0.01);
  7782.       RT := (REFERENCE_TIME - FLOAT(NHR)*40.0)*60.0;
  7783.       GT := (T + RT)/3600.0;
  7784.       TOD := GT + XLONG/15.0;
  7785.       Loop
  7786.          Exit When TOD > 0.0;
  7787.          TOD := TOD + 24.0;
  7788.       End Loop;
  7789.       Loop
  7790.          Exit When TOD < 24.0;
  7791.          TOD := TOD - 24.0;
  7792.       End Loop;
  7793. --
  7794. --  SOLAR SUB POINT LAT - LONG, DEGREES
  7795.       SLAT := - 23.5*COS(FLOAT(MONTH)*PI6);
  7796.       SLONG := 180.0 - 15.0*GT;
  7797. --
  7798. --  ZENITH CALCULATION
  7799.       CHI := ACOS(SIN(SLAT*RADIANS_PER_DEGREE)*SIN(XLAT*RADIANS_PER_DEGREE) + 
  7800.              COS(SLAT*RADIANS_PER_DEGREE)*COS(XLAT*RADIANS_PER_DEGREE)*
  7801.              COS(RADIANS_PER_DEGREE*(SLONG - XLONG)))/RADIANS_PER_DEGREE;
  7802. --
  7803. --  DAY VS NIGHT
  7804.       IDN := NIGHT;
  7805.       If CHI <= 90.0 Then
  7806.          IDN := DAY;
  7807.       End If;
  7808. --
  7809.       Return;
  7810. --
  7811.       End ZENITH;
  7812. --
  7813. --
  7814. End RFUTIL;
  7815.  
  7816. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7817. --ELFLFHFA
  7818. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  7819. With Debugger2; Use Debugger2;
  7820. With Mathlib; Use Mathlib, numeric_primitives, 
  7821.               core_functions,trig_functions;
  7822. With Rfutil;
  7823. With Propagation_constants; use Propagation_constants;
  7824. With COMPLEX_NUMBERS; use COMPLEX_NUMBERS;
  7825. With Constants;use Constants;
  7826.  
  7827. Package ELF_LF_HF_ATMOSPHERICS is
  7828. --
  7829.       Type IONO_LAYERS is array (integer range 1..20) of float;
  7830.  
  7831.       Procedure ATMOSD (MODE: in integer;
  7832.                         H: in float;
  7833.                         RHO: out float;
  7834.                         HS: out float;
  7835.                         TEM: out float;
  7836.                         CONN2: out float;
  7837.                         CONO2: out float;
  7838.                         CONO: out float;
  7839.                         WTMOL: out float);
  7840.  
  7841.       Procedure CHEMD (H: in float;
  7842.                        NDI: in DAY_OR_NIGHT;
  7843.                        RHO: in float;
  7844.                        TEM: in float;
  7845.                        CONN2: in float;
  7846.                        CONO2: in float;
  7847.                        CONO: in float;
  7848.                        ALPHAD: out float;
  7849.                        ALPHAI: out float;
  7850.                        A: out float;
  7851.                        D: out float;
  7852.                        VEAIR: out float;
  7853.                        VEOX: out float;
  7854.                        VIAIR: out float);
  7855.  
  7856.       Function FITRAT (C1: float; C2: float; C3: float; C4: float; DH: float)
  7857.                       return float;
  7858.  
  7859.       Procedure IONCAL (XLAT: in float;
  7860.                         XLON: in float;
  7861.                         TIME: in float;
  7862.                         IDN: in DAY_OR_NIGHT;
  7863.                         EN: out IONO_LAYERS;
  7864.                         PN: out IONO_LAYERS;
  7865.                         VEAIR: out IONO_LAYERS;
  7866.                         VIAIR: out IONO_LAYERS);
  7867.  
  7868.       Procedure IONOSD (HC: in float;
  7869.                         NDI: in DAY_OR_NIGHT;
  7870.                         ALPHAD: in float;
  7871.                         ALPHAI: in float;
  7872.                         A: in float;
  7873.                         D: in float;
  7874.                         QA: out float;
  7875.                         ENPQ: out float;
  7876.                         ENEQ: out float);
  7877.  
  7878.       Procedure REFCAL (XLAT: in float;
  7879.                         XLON: in float;
  7880.                         TIME: in float;
  7881.                         FREQ: in float;
  7882.                         HXR: out float;
  7883.                         ALP1: out float);
  7884. --
  7885. --
  7886. End ELF_LF_HF_ATMOSPHERICS;
  7887. --
  7888. Package body ELF_LF_HF_ATMOSPHERICS is
  7889. --
  7890. -- ELF_LF_HF_ATMOSPHERICS Package of PROP_LINK 
  7891. -- Version 1.0,  April 21, 1985.
  7892. --
  7893. -- This ELF_LF_HF_ATMOSPHERICS Package contains all of the procedures that 
  7894. -- are used to compute the behavior of the ionosphere for ELF & LF
  7895. -- propagation, as well as some of the procedures required for HF propagation.
  7896. --
  7897. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  7898. -- radio frequency propagation prediction code.
  7899. --
  7900. -- PROP_LINK has been developed for the Department of Defense under
  7901. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  7902. -- Systems Inc. (Jim Conrad).
  7903. --
  7904. --      Instantiate integer and floating point IO.
  7905. --      Package IO_INTEGER is new INTEGER_IO(INTEGER);
  7906. --      Package IO_FLOAT is new FLOAT_IO(FLOAT);
  7907. --      Use IO_INTEGER,IO_FLOAT;
  7908. --
  7909.       Pragma Source_info (on);
  7910. --
  7911.       Procedure ATMOSD (MODE: in integer;
  7912.                         H: in float;
  7913.                         RHO: out float;
  7914.                         HS: out float;
  7915.                         TEM: out float;
  7916.                         CONN2: out float;
  7917.                         CONO2: out float;
  7918.                         CONO: out float;
  7919.                         WTMOL: out float) is
  7920. --
  7921. --#PURPOSE: ATMOSD calculates the atmospheric properties at a point
  7922. --          below 120Km.
  7923. --
  7924. --#AUTHOR:  J. Conrad
  7925. --
  7926. --#TYPE:    Numerical Analysis
  7927. --
  7928. --#PARAMETER DESCRIPTIONS:
  7929. --IN        MODE   = 1...Return full set of output quantities
  7930. --                   0...Return only density, scale height,
  7931. --                     and temperature
  7932. --IN        H      = Altitude of point (Km)
  7933. --OUT       RHO    = Density (gm/(CM**3))
  7934. --OUT       HS     = Local density scale height (Km) Scale height
  7935. --                   provided is not the same as CIRA 1965
  7936. --                   pressure scale heights.
  7937. --OUT       TEM    = Temperature in degrees Kelvin
  7938. --OUT       CONN2  = Nitrogen concentration (/(CM**3))
  7939. --OUT       CONO2  = (Oxygen)2 concentration (/(CM**3))
  7940. --OUT       CONO   = (Oxygen) + (Oxygen)3 concentration
  7941. --                   (/(CM**3))
  7942. --OUT       WTMOL  = Mean molecular weight
  7943. --
  7944. --#CALLED BY:
  7945. --          IONCAL
  7946. --
  7947. --#CALLS TO:
  7948. --          'NONE'
  7949. --
  7950. --#TECHNICAL DESCRIPTION:
  7951. --          ATMOSD is a natural atmosphere model that computes the
  7952. --          atmospheric properties from 0 to 50 Km using the 1962
  7953. --          U.S. Standard Atmosphere model and from 50 to 120Km using
  7954. --          the CIRA (CCSPAR International Reference Atmospheres)
  7955. --          2965 mean atmosphere model.  The routine uses internally
  7956. --          defined tabularized data and linear interpolation to
  7957. --          provide fast accurate calculations.
  7958. --
  7959. --
  7960.       ISD: integer;
  7961.       HSA: array (integer range 1..61) of float;
  7962. --
  7963. --  DENSITY (0 TO 120 KM, 2 KM INTERVALS)
  7964.       RHOA: array (integer range 1..61) of float
  7965.       := (1.225E-3, 1.007E-3, 8.194E-4, 6.601E-4, 5.258E-4, 4.135E-4, 
  7966.           3.119E-4, 2.279E-4, 1.665E-4, 1.217E-4, 8.891E-5, 6.451E-5,
  7967.           4.694E-5, 3.426E-5, 2.508E-5, 1.841E-5, 1.356E-5, 9.887E-6,
  7968.           7.258E-6, 5.367E-6, 3.996E-6, 2.995E-6, 2.259E-6, 1.714E-6,
  7969.           1.317E-6, 1.041E-6, 8.271E-7, 6.543E-7, 5.151E-7, 4.034E-7,
  7970.           3.142E-7, 2.433E-7, 1.873E-7, 1.433E-7, 1.090E-7, 8.234E-8,
  7971.           6.199E-8, 4.629E-8, 3.427E-8, 2.513E-8, 1.825E-8, 1.276E-8,
  7972.           8.926E-9, 6.245E-9, 4.369E-9, 3.058E-9, 2.091E-9, 1.445E-9,
  7973.           1.009E-9, 7.114E-10, 5.062E-10, 3.570E-10, 2.557E-10, 1.858E-10,
  7974.           1.367E-10, 1.019E-10, 7.354E-11, 5.449E-11, 4.127E-11, 3.186E-11,
  7975.           2.501E-11);
  7976. --  TEMPERATURE (0 TO 120 KM, 2 KM INTERVALS)
  7977.       TEMPA: array (integer range 1..61) of float
  7978.       := (288.2, 275.2, 262.2, 249.2, 236.2, 223.3, 216.7, 216.7, 216.7,
  7979.           216.7, 216.7, 218.6, 220.6, 222.5, 224.5, 226.5, 228.5, 233.7,
  7980.           239.3, 244.8, 250.4, 255.9, 261.4, 266.9, 270.7, 271.0, 265.5,
  7981.           259.9, 254.4, 248.8, 243.3, 238.0, 232.6, 227.3, 221.9, 216.6,
  7982.           210.5, 204.4, 198.2, 192.1, 186.0, 186.0, 185.9, 185.9, 185.9,
  7983.           185.8, 190.9, 195.9, 200.4, 204.4, 208.1, 215.7, 224.6, 233.4,
  7984.           242.3, 251.1, 271.9, 292.7, 313.1, 334.0, 355.0);
  7985. --  O + O3 CONCENTRATION (0 TO 120 KM, 2 KM INTERVALS)
  7986.       CONOA: array (integer range 1..61) of float
  7987.       := (1.0E+10, 1.5E+10, 2.75E+10, 4.8E+10, 8.0E+10, 1.3E+11, 2.0E+11,
  7988.           3.1E+11, 4.8E+11, 7.2E+11, 1.0E+12, 1.65E+12, 2.25E+12, 2.8E+12,
  7989.           2.9E+12, 3.0E+12, 2.75E+12, 2.25E+12, 1.8E+12, 1.3E+12, 8.0E+11,
  7990.           5.5E+11, 3.25E+11, 1.95E+11, 1.15E+11, 7.0E+10, 4.6E+10, 3.4E+10,
  7991.           2.7E+10, 2.3E+10, 2.0E+10, 1.95E+10, 1.95E+10, 2.0E+10, 2.05E+10,
  7992.           2.15E+10, 2.3E+10, 2.65E+10, 3.0E+10, 3.5E+10, 4.0E+10, 5.0E+10,
  7993.           6.0E+10, 7.6E+10, 1.0E+11, 1.25E+11, 1.68E+11, 2.66E+11, 4.10E+11,
  7994.           4.8E+11, 5.0E+11, 4.76E+11, 4.05E+11, 3.21E+11, 2.51E+11, 2.0E+11,
  7995.           1.64E+11, 1.35E+11, 1.13E+11, 9.25E+10, 7.6E+10);
  7996. --  N2 CONCENTRATION (80 TO 120 KM, 2 KM INTERVALS)
  7997.       CONN2A: array (integer range 1..21) of float
  7998.       := (2.963E+14, 2.072E+14, 1.449E+14, 1.014E+14, 7.095E+13, 4.965E+13,
  7999.           3.544E+13, 2.349E+13, 1.626E+13, 1.146E+13, 8.178E+12, 5.704E+12,
  8000.           4.060E+12, 2.950E+12, 2.174E+12, 1.620E+12, 1.164E+12, 8.606E+11,
  8001.           6.513E+11, 5.057E+11, 4.008E+11);
  8002. --  O2 CONCENTRATION (80 TO 120 KM, 2 KM INTERVALS)
  8003.       CONO2A: array (integer range 1..21) of float
  8004.       := (7.950E+13, 5.559E+13, 3.888E+13, 2.721E+13, 1.906E+13, 1.332E+13,
  8005.           9.188E+12, 6.146E+12, 4.296E+12, 2.936E+12, 1.994E+12, 1.359E+12,
  8006.           9.443E+11, 6.693E+11, 4.809E+11, 3.492E+11, 2.443E+11, 1.757E+11,
  8007.           1.292E+11, 9.744E+10, 7.495E+10);
  8008. --  MEAN MOLECULAR WEIGHT (80 TO 120 KM, 2 KM INTERVALS)
  8009.       WTMOLA: array (integer range 1..21) of float
  8010.       := (28.96, 28.96, 28.95, 28.95, 28.95, 28.94, 28.89, 28.83, 28.70,
  8011.           28.52, 28.30, 28.02, 27.92, 27.82, 27.74, 27.66, 27.49, 27.34,
  8012.           27.19, 27.08, 27.01);
  8013. --
  8014.       Z, X: float;
  8015.       I: integer;
  8016. --
  8017.       Begin
  8018. --
  8019.       Z := H;
  8020. --
  8021. --COMPUTE DENSITY SCALE HEIGHTS.
  8022.       If ISD /= 1 Then
  8023.          ISD := 1;
  8024.          For I in 2..60 Loop
  8025.             HSA(I) := 4.0/LOG(RHOA(I-1)/RHOA(I+1));
  8026.          End Loop;
  8027.          HSA(1) := 2.0*HSA(2) - HSA(3);
  8028.          HSA(61) := 8.3;
  8029.       End If;
  8030. --
  8031. --INTERPOLATE FOR DENSITY, SCALE HEIGHT, AND TEMPERATURE.
  8032.       I := MIN(MAX(INTEGER(TRUNCATE(Z/2.0)) + 1, 1), 60);
  8033.       X := (Z - 2.0*FLOAT(I-1))/2.0;
  8034.       RHO := RHOA(I)*(RHOA(I+1)/RHOA(I))**X;
  8035.       HS := HSA(I) + (HSA(I+1) - HSA(I))*X;
  8036.       TEM := TEMPA(I) + (TEMPA(I+1) - TEMPA(I))*X;
  8037.       If MODE = 0 Then
  8038.          Return;
  8039.       End If;
  8040. --
  8041. --INTERPOLATE FOR NUMBER DENSITIES AND MEAN MOLECULAR WEIGHT.
  8042.       CONO := CONOA(I)*(CONOA(I+1)/CONOA(I))**X;
  8043.       If (Z - 80.0) <= 0.0 Then
  8044.          CONN2 := 1.6236E+22*RHO;
  8045.          CONO2 := 4.3562E+21*RHO;
  8046.          WTMOL := 28.96;
  8047.       Else
  8048.          I := I - 40;
  8049.          CONN2 := CONN2A(I)*(CONN2A(I+1)/CONN2A(I))** X;
  8050.          CONO2 := CONO2A(I)*(CONO2A(I+1)/CONO2A(I))**X;
  8051.          WTMOL := WTMOLA(I) + (WTMOLA(I+1) - WTMOLA(I))*X;
  8052.       End If;
  8053.       Return;
  8054. --
  8055.       End ATMOSD;
  8056. --
  8057. --
  8058.       Procedure CHEMD (H: in float;
  8059.                        NDI: in DAY_OR_NIGHT;
  8060.                        RHO: in float;
  8061.                        TEM: in float;
  8062.                        CONN2: in float;
  8063.                        CONO2: in float;
  8064.                        CONO: in float;
  8065.                        ALPHAD: out float;
  8066.                        ALPHAI: out float;
  8067.                        A: out float;
  8068.                        D: out float;
  8069.                        VEAIR: out float;
  8070.                        VEOX: out float;
  8071.                        VIAIR: out float) is
  8072. --
  8073. --
  8074. --#PURPOSE: CHEMD computes deionization reaction rate coefficients
  8075. --          for a point below 100 Km.
  8076. --
  8077. --#AUTHOR:  J. Conrad
  8078. --
  8079. --#TYPE:    Numerical Analysis
  8080. --
  8081. --#PARAMETER DESCRIPTIONS:
  8082. --IN        H      = Altitude of Point (Km)
  8083. --IN        NDI    = Day/night indicator 
  8084. --IN        RHO    = Mass density (GM/CM**-3)
  8085. --IN        TEM    = Gas temperature (deg. Kelvin)
  8086. --IN        CONN2  = Nitrogen concentration (CM**-3
  8087. --IN        CONO2  = (Oxygen)2 concentraion (CM**-3)
  8088. --IN        CONO   = (Oxygen) + (Oxygen)3 concentration (CM**-3)
  8089. --OUT       ALPHAD = Electron-ion recombination rate
  8090. --                   coefficient (CM**3/sec)
  8091. --OUT       ALPHAI = ION-ION recombination rate coefficient
  8092. --                   (CM**3/sec-)
  8093. --OUT       A      = Attachment rate (sec**-1)
  8094. --OUT       D      = Detachment rate (sec**-1)
  8095. --OUT       VEAIR  = Electronic molecule collision frequency
  8096. --                   (sec**-1)
  8097. --OUT       VEOX   = Electron atom collision frequency (sec**-1)
  8098. --OUT       VIAIR  = Ion molecule collision frequency (sec**-1)
  8099. --
  8100. --#CALLED BY:
  8101. --          IONCAL
  8102. --
  8103. --#CALLS TO:
  8104. --          FITRAT
  8105. --
  8106. --#TECHNICAL DESCRIPTION:
  8107. --          An altitude index is computed by dividing the input
  8108. --          altitude by the increment (5Km) between reference
  8109. --          altitudes for which data is stored.  If the input
  8110. --          altitude is within 0.5Km of a reference altitude,
  8111. --          stored values are returned for the reaction rates
  8112. --          corresponding to the altitude index computed.  If
  8113. --          the input altitude differs from the reference
  8114. --          altitude by more than 0.5Km, Function FITRAT is
  8115. --          called and interpolated values for reaction rates
  8116. --          are returned.
  8117. --
  8118.       AN: array (integer range 1..20) of float
  8119.       := (2.19E+07, 5.42E+06, 1.04E+06, 2.38E+05, 5.00E+04, 1.08E+04,
  8120.           2.43E+03, 5.81E+02, 1.50E+02, 4.30E+01, 1.27E+01, 3.58E+00,
  8121.           9.94E-01, 3.23E-01, 1.80E-01, 1.11E-01, 4.13E-02, 1.31E-02,
  8122.           3.35E-03, 9.23E-04);
  8123.       DN: array (integer range 1..20) of float
  8124.       := (1.00E-11, 1.00E-11, 1.00E-11, 1.73E-11, 1.01E-10, 3.93E-10,
  8125.           2.34E-09, 1.69E-08, 7.47E-08, 2.31E-07, 1.29E-07, 1.66E-07,
  8126.           3.60E-07, 7.44E-07, 3.58E-04, 5.07E-01, 8.46E+00, 2.92E+01,
  8127.           9.44E+01, 1.49E+02);
  8128.       ALIN: array (integer range 1..20) of float
  8129.       := (3.00E-08, 3.00E-08, 3.00E-08, 3.00E-08, 3.00E-08,
  8130.           3.00E-08, 3.00E-08, 3.00E-08, 3.01E-08, 3.03E-08,
  8131.           3.06E-08, 3.11E-08, 3.21E-08, 3.51E-08, 5.55E-08,
  8132.           1.95E-07, 2.00E-07, 2.00E-07, 2.00E-07, 2.00E-07);
  8133.       ALDN: array (integer range 1..20) of float
  8134.       := (7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,
  8135.           7.00E-6,  7.00E-6,  7.00E-6,  6.99E-6,  6.98E-6,
  8136.           6.97E-6,  6.94E-6,  6.89E-6,  6.75E-6,  5.94E-6,
  8137.           6.09E-07, 4.88E-07, 4.85E-07, 4.54E-07, 4.32E-07);
  8138.       AD: array (integer range 1..20) of float
  8139.       := (2.19E+07, 5.47E+06, 1.04E+06, 2.38E+05, 5.00E+04, 1.08E+04,
  8140.           2.43E+03, 5.81E+02, 1.50E+02, 4.30E+01, 1.27E+01, 3.50E+00,
  8141.           8.95E-01, 2.10E-01, 4.48E-02, 8.53E-03, 1.56E-03, 4.27E-04,
  8142.           4.84E-04, 6.61E-04);
  8143.       DD: array (integer range 1..20) of float
  8144.       := (1.01E-2,  1.01E-2,  1.01E-2,  1.01E-2,  1.01E-2,
  8145.           1.01E-2,  1.01E-2,  1.05E-2,  1.27E-2,  2.63E-2,
  8146.           8.06E-2,  3.64E-1,  1.76,    4.88,    8.46,
  8147.           12.4,    20.7,    37.9,    99.4,    150.0);
  8148.       ALID: array (integer range 1..20) of float
  8149.       := (3.00E-08, 3.00E-08, 3.00E-08, 3.00E-08, 3.00E-08,
  8150.           3.00E-08, 3.00E-08, 3.00E-08, 3.00E-08, 3.01E-08,
  8151.           3.04E-8,  3.57E-8,  8.96E-8,  1.57E-7,  1.86E-7,
  8152.           1.97E-07, 2.00E-07, 2.00E-07, 2.00E-07, 2.00E-07);
  8153.       ALDD: array (integer range 1..20) of float
  8154.       := (7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,
  8155.           7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,  7.00E-6,
  8156.           6.98E-6,  6.76E-6,  4.54E-6,  1.92E-6,  9.12E-7,
  8157.           5.80E-07, 4.92E-07, 4.85E-07, 4.54E-07, 4.32E-07);
  8158. --
  8159.       RHO2, ENOFO, TS, X, HX, DX, DH: float;
  8160.       I, INTRP: integer;
  8161. --
  8162.       Begin
  8163. --
  8164. --  NUMBER DENSITY OF ATOMIC OXYGEN,DAYTIME
  8165.       RHO2:= RHO**2;
  8166.       ENOFO:= 1.3E-13*CONO/(RHO2 + 1.3E-13);
  8167.       If NDI /= DAY Then  --  NUMBER DENSITY OF ATOMIC OXYGEN, NIGHTTIME
  8168.          TS := 2.0E4;
  8169.          X := 4.0E10*RHO2*TS;
  8170.          If X > 85.0 Then
  8171.             ENOFO := 0.0;
  8172.          End If;
  8173.          If  X <= 85.0 Then
  8174.             ENOFO := ENOFO * EXP(-X);
  8175.          End If;
  8176.       End If;
  8177.       INTRP := 0;
  8178.       I := integer(TRUNCATE((H + 0.01)/5.0));
  8179.       HX := FLOAT(I)*5.0;
  8180.       DH := H - HX;
  8181.       If DH > 0.5 Then
  8182.          INTRP := 1;
  8183.       End If;
  8184.       If NDI /= DAY Then
  8185.          If INTRP <= 0 and (I = 1 or I >= 19) Then
  8186.             ALPHAD := ALDN(I);
  8187.             ALPHAI := ALIN(I);
  8188.             D := DN(I);
  8189.             A := AN(I);
  8190.             VEAIR := (2.6E-11*CONN2 + 1.5E-11*CONO2)*TEM;
  8191.             VEOX := 8.0E-10*ENOFO*SQRT(TEM);
  8192.             VIAIR := VEAIR/20.0;
  8193.             Return;
  8194.          End If;
  8195.          ALPHAD := FITRAT(ALDN(I-1),ALDN(I),ALDN(I+1),ALDN(I+2),DH);
  8196.          ALPHAI := FITRAT(ALIN(I-1),ALIN(I),ALIN(I+1),ALIN(I+2),DH);
  8197.          D := FITRAT(DN(I-1),DN(I),DN(I+1),DN(I+2),DH);
  8198.          A := FITRAT(AN(I-1),AN(I),AN(I+1),AN(I+2),DH);
  8199.          VEAIR := (2.6E-11*CONN2 + 1.5E-11*CONO2)*TEM;
  8200.          VEOX := 8.0E-10*ENOFO*SQRT(TEM);
  8201.          VIAIR := VEAIR/20.0;
  8202.          Return;
  8203.       End If;
  8204.       If INTRP <= 0 and (I = 1 or I >= 19) Then
  8205.          ALPHAD := ALDD(I); 
  8206.          ALPHAI := ALID(I);
  8207.          D := DD(I);
  8208.          A := AD(I);
  8209.          VEAIR := (2.6E-11*CONN2 + 1.5E-11*CONO2)*TEM;
  8210.          VEOX := 8.0E-10*ENOFO*SQRT(TEM);
  8211.          VIAIR := VEAIR/20.0;
  8212.          Return;
  8213.       End If;
  8214.       ALPHAD := FITRAT(ALDD(I-1),ALDD(I),ALDD(I+1),ALDD(I+2),DH);
  8215.       ALPHAI := FITRAT(ALID(I-1),ALID(I),ALID(I+1),ALID(I+2),DH);
  8216.       D := FITRAT(DD(I-1),DD(I),DD(I+1),DD(I+2),DH);
  8217.       A := FITRAT(AD(I-1),AD(I),AD(I+1),AD(I+2),DH);
  8218.       VEAIR := (2.6E-11*CONN2 + 1.5E-11*CONO2)*TEM;
  8219.       VEOX := 8.0E-10*ENOFO*SQRT(TEM);
  8220.       VIAIR := VEAIR/20.0;
  8221.       Return;
  8222. --
  8223.       End CHEMD;
  8224. --
  8225. --
  8226.       Function FITRAT (C1: float; C2: float; C3: float; C4: float; DH: float)
  8227.                       return float is
  8228. --
  8229. --#PURPOSE: FITRAT obtains the reaction rates at altitudes between
  8230. --          reference altitudes for which reaction rate data is
  8231. --          stored by Lagrangian interpolation.
  8232. --
  8233. --#AUTHOR:  J. Conrad
  8234. --
  8235. --#TYPE:    Numerical Analysis
  8236. --
  8237. --#PARAMETER DESCRIPTIONS:
  8238. --IN        C1     = Reaction rate value for altitude below the
  8239. --                   point of interest
  8240. --IN        C2     = Reaction rate value for altitude below the
  8241. --                   point of interest
  8242. --IN        C3     = Reaction rate value for altitude above the
  8243. --                   point of interest
  8244. --IN        C4     = Reaction rate value for altitude above the
  8245. --                   point of interest
  8246. --IN        DH     = Altitude difference between point of
  8247. --                   interest and the reference altitude
  8248. --                   corresponding to C2 (km)
  8249. --#CALLED BY:
  8250. --          CHEMD
  8251. --
  8252. --#CALLS TO:
  8253. --          'NONE'
  8254. --
  8255. --#TECHNICAL DESCRIPTION:
  8256. --          Standard Lagrangian interpolation formulas are used.
  8257. --
  8258.       X1, X2, X3, X4, W1, W2, W3, W4, Y: float;
  8259. --
  8260.       Begin
  8261. --
  8262.       X1 := -5.0 - DH;
  8263.       X2 := -DH;
  8264.       X3 := 5.0 - DH;
  8265.       X4 := 10.0 - DH;
  8266.       W1 := -X2/(X1 - X2)*X3/(X1 - X3)*X4/(X1 - X4);
  8267.       W2 := -X1/(X2 - X1)*X3/(X2 - X3)*X4/(X2 - X4);
  8268.       W3 := -X1/(X3 - X1)*X2/(X3 - X2)*X4/(X3 - X4);
  8269.       W4 := -X1/(X4 - X1)*X2/(X4 - X2)*X3/(X4 - X3);
  8270.       Y  := W1*LOG(C1) + W2*LOG(C2) + W3*LOG(C3) + W4*LOG(C4);
  8271.       Return EXP(Y);
  8272. --
  8273.       End FITRAT;
  8274. --
  8275. --
  8276.       Procedure IONCAL (XLAT: in float;
  8277.                         XLON: in float;
  8278.                         TIME: in float;
  8279.                         IDN: in DAY_OR_NIGHT;
  8280.                         EN: out IONO_LAYERS;
  8281.                         PN: out IONO_LAYERS;
  8282.                         VEAIR: out IONO_LAYERS;
  8283.                         VIAIR: out IONO_LAYERS) is
  8284. --
  8285. --
  8286. --#PURPOSE: IONCAL calculates the electron and positive ion
  8287. --          densities as well as the collision frequencies for an
  8288. --          array of altitudes in ambient environments for a specified 
  8289. --          latitude and longitude.
  8290. --
  8291. --#AUTHOR:  J. Conrad
  8292. --
  8293. --#TYPE:    Numerical Analysis
  8294. --
  8295. --#PARAMETER DESCRIPTIONS:
  8296. --IN        XLAT   = The geographic coordinate of a point,
  8297. --                   positive degrees north
  8298. --IN        XLON   = The geographic coordinate of a point,
  8299. --                   positive degrees east
  8300. --IN        TIME   = Evaluation time in seconds
  8301. --                   (-TIME is a flag for ambient calculations)
  8302. --IN        IDN    = Day/night indicator
  8303. --OUT       EN     = Equilibrium positive ion concentration (/CM**3) array 
  8304. --OUT       PN     = Equilibrium electron concentration (/CM**3) array
  8305. --OUT       VEAIR  = Electron molecule collision frequency (sec**-1) array
  8306. --OUT       VIAIR  = Ion molecule collision frequency (sec**-1) array
  8307. --
  8308. --#CALLED BY:
  8309. --          HFNORM
  8310. --          REFCAL
  8311. --
  8312. --#CALLS TO:
  8313. --          ATMOSD
  8314. --          CHEMD
  8315. --          IONOSD
  8316. --
  8317. --#TECHNICAL DESCRIPTION:
  8318. --          Ambient electron and positive ion densities are calculated
  8319. --          using the standard atmospheric routines contained in
  8320. --          subroutines ATMOSD, CHEMD, and IONOSD.  The routine is
  8321. --          called initially to set ambient values at 5 kilometer
  8322. --          increments.  These values are stored in arrays ENA and ENP.
  8323. --
  8324.       TEM: array (integer range 1..20) of float;
  8325.       CONN2: array (integer range 1..20) of float;
  8326.       CONO2: array (integer range 1..20) of float;
  8327.       ALPHAI: array (integer range 1..20) of float;
  8328.       A: array (integer range 1..20) of float;
  8329.       D: array (integer range 1..20) of float;
  8330.       ALPHAD: array (integer range 1..20) of float;
  8331.       QA: array (integer range 1..20) of float;
  8332.       PNA: array (integer range 1..20) of float;
  8333.       ENA: array (integer range 1..20) of float;
  8334.       RHO: array (integer range 1..20) of float;
  8335.       HS: array (integer range 1..20) of float;
  8336.       VEO, CONO, WTMOL: float;
  8337. --
  8338.       Begin
  8339. --
  8340.       For I in 1..20 Loop
  8341.          ATMOSD (1, HP(I), RHO(I), HS(I), TEM(I), CONN2(I),
  8342.                  CONO2(I), CONO, WTMOL);
  8343.          CHEMD  (HP(I), IDN, RHO(I), TEM(I), CONN2(I), CONO2(I), CONO,
  8344.                  ALPHAD(I), ALPHAI(I), A(I), D(I), VEAIR(I), VEO, VIAIR(I));
  8345.          IONOSD (HP(I), IDN, ALPHAD(I), ALPHAI(I), A(I), D(I),
  8346.                  QA(I), PNA(I), ENA(I));
  8347.          EN(I) := ENA(I);
  8348.          PN(I) := PNA(I);
  8349.       End Loop;
  8350. --
  8351.       End IONCAL;
  8352. --
  8353. --
  8354.       Procedure IONOSD (HC: in float;
  8355.                         NDI: in DAY_OR_NIGHT;
  8356.                         ALPHAD: in float;
  8357.                         ALPHAI: in float;
  8358.                         A: in float;
  8359.                         D: in float;
  8360.                         QA: out float;
  8361.                         ENPQ: out float;
  8362.                         ENEQ: out float) is
  8363. --
  8364. --
  8365. --#PURPOSE: IONOSD computes normal ionosheric properties at a point
  8366. --          below 120 Km..
  8367. --
  8368. --#AUTHOR:  J. Conrad
  8369. --
  8370. --#TYPE:    Numerical Analysis
  8371. --
  8372. --#PARAMETER DESCRIPTIONS:
  8373. --IN        HC     = Height of point (Km)
  8374. --IN        NDI    = Day/night indicator
  8375. --IN        ALPHAD = Electron-Ion recombination rate coefficient
  8376. --                   (CM**3/SEC)
  8377. --IN        ALPHAI = Ion-Ion recombination rate coefficient
  8378. --                   (CM**3/SEC)
  8379. --IN        A      = Attachment rate (/SEC)
  8380. --IN        D      = Detachment rate (/SEC)
  8381. --OUT       QA     = Normal ion-production rate (/CM**3)
  8382. --OUT       ENPQ   = Equilibrium positive ion concentration
  8383. --                   (/CM**3)
  8384. --OUT       ENEQ   = Equilibrium electron concentration
  8385. --                   (/CM**3)
  8386. --
  8387. --#CALLED BY:
  8388. --          IONCAL
  8389. --
  8390. --#CALLS TO:
  8391. --          'NONE'
  8392. --
  8393. --#TECHNICAL DESCRIPTION:
  8394. --          The normal ion production rate is computed using
  8395. --          exponential interpolation between data stored for an
  8396. --          array of reference altitudes.  The production rate is then
  8397. --          used to determine a quasi-equilibrium solution for
  8398. --          electron and positive ion concentrations.
  8399. --
  8400.       QADN: array (integer range 1..7) of float;
  8401.       QAN: array (integer range 1..7) of float;
  8402.       QAD: array (integer range 1..7) of float;
  8403.       X, ALPHA: float;
  8404.       I, J: integer;
  8405. --
  8406.       Begin
  8407. --
  8408.       QADN:=(1.2E2, 3.1E1, 7.0E0, 1.8E0, 4.0E-1, 2.0E-1, 1.0E-1);
  8409.       QAN:=(1.0E-1, 2.0E-2, 1.0E-2, 5.0E-2, 2.0E-1, 5.68E-1, 8.4E-1);
  8410.       QAD:=(1.0E-1, 3.0E-1, 1.0E0, 1.0E1, 1.0E3, 2.17E3,2.69E3);
  8411.       I := MIN(MAX(INTEGER(TRUNCATE(HC/10.0)) + 1,1),12);
  8412.       X := (HC - 10.0*FLOAT(I - 1))/10.0;
  8413.       If I - 7 < 0 Then
  8414.          QA := QADN(I)*(QADN(I+1)/QADN(I))**X;
  8415.       Else
  8416.          I := I - 6;
  8417.          If NDI = NIGHT Then
  8418.             QA := QAN(I)*(QAN(I+1)/QAN(I))**X;
  8419.          Else
  8420.             QA := QAD(I)*(QAD(I+1)/QAD(I))**X;
  8421.          End If;
  8422.       End If;
  8423.       ALPHA := (A*ALPHAI+D*ALPHAD)/(A + D);
  8424.       ENPQ := SQRT(QA/ALPHA);
  8425.       For J in 1..2 Loop
  8426.          ALPHA := (A*ALPHAI + D*ALPHAD + ALPHAD*ALPHAI*ENPQ)/
  8427.                   (A + D + ALPHAI*ENPQ);
  8428.       End Loop;
  8429.       ENPQ := SQRT(QA/ALPHA);
  8430.       ENEQ := (QA + D*ENPQ)/(A + D + ALPHAD*ENPQ);
  8431. --
  8432.       End IONOSD;
  8433. --
  8434. --
  8435.       Procedure REFCAL (XLAT: in float;
  8436.                         XLON: in float;
  8437.                         TIME: in float;
  8438.                         FREQ: in float;
  8439.                         HXR: out float;
  8440.                         ALP1: out float) is
  8441. --
  8442. --#PURPOSE: REFCAL computes the ionospheric reflection coefficient
  8443. --          (float part) at calculated altitude above a point in an
  8444. --          ambient or nuclear environment.
  8445. --
  8446. --#AUTHOR:  J. Conrad
  8447. --
  8448. --#TYPE:    Numerical Analysis
  8449. --
  8450. --#PARAMETER DESCRIPTIONS:
  8451. --IN        XLAT   = Latitude of point +north
  8452. --IN        XLON   = Longitude of point +east
  8453. --IN        TIME   = Evaluation time, in seconds (-TIME is a flag
  8454. --                   for ambient calculations)
  8455. --IN        FREQ   = Signal Frequency in KHz
  8456. --OUT       HXR    = Ionosphere reflection height in km
  8457. --OUT       ALP1   = float part of reflection coefficient to be
  8458. --                   used in an exponential expansion
  8459. --
  8460. --#CALLED BY:
  8461. --          ELF, HIGHTF, VLFNUC
  8462. --
  8463. --#CALLS TO:
  8464. --          CTANH
  8465. --          DAYNIT
  8466. --          IONCAL
  8467. --
  8468. --#TECHNICAL DESCRIPTION:
  8469. --          The reflection coefficients are calculated using a method
  8470. --          described by Wait, 1962.  In this method, the ionized
  8471. --          layer is represented by homogeneous slabs where the wave
  8472. --          is incident on the layer bottom at an angle.  A recursive
  8473. --          algorithm is employed to compute the float and the imaginary
  8474. --          parts of the reflection coefficient -- however, only the
  8475. --          float part is returned to the calling routine.
  8476. --
  8477.       BBB, X, Y, Z, XK, ZX, TEST, TH, R: complex;
  8478.       CID: array (integer range 1..2) of float := (0.1, 0.2);
  8479.       A: array (integer range 1..20) of float;
  8480.       B: array (integer range 1..20) of float;
  8481.       AMP: array (integer range 1..20) of float;
  8482.       ALPHX: array (integer range 1..2) of float;
  8483.       C: constant float := 2.997956E8;
  8484.       NH: constant integer := 20;
  8485.       DELTAH: constant float := 5.0;
  8486.       DH: constant float := 1000.0;
  8487.       EPS: constant float := 8.854E-12;
  8488.       U: constant float := 1.256637E-6;
  8489.       OMEGA, OMEGA2, WAVE, WE, TMIN, AE, BE, AI, BI, B1, HBS, XI, RIPREV,
  8490.       C2, OK, A1, HAS, XN, HOUT, RIM, RI, RRR, TESTI, TESTR, AMTEST: float;
  8491.       K, NINV, KK, N, I, NPHASE, L: integer; 
  8492.       IDN: DAY_OR_NIGHT;
  8493.       EN, PN, VEAIR, VIAIR: IONO_LAYERS;
  8494. --
  8495.       Begin
  8496. --
  8497. --  CALCULATE CONSTANTS FOR LATER USE.
  8498.       OMEGA := TWOPI*FREQ*1.0E3;
  8499.       OMEGA2 := OMEGA*OMEGA;
  8500.       WAVE := OMEGA/C;
  8501.       WE    := EPS*OMEGA;
  8502.       TMIN := ABS(TIME)/60.0;
  8503. --
  8504. --
  8505. --CALCULATE IONOSPHERIC PROFILES
  8506. --
  8507.        RFUTIL.DAYNIT (IDN, XLON, XLON);
  8508.        IONCAL (XLAT, XLON, TIME, IDN, EN, PN, VEAIR, VIAIR);
  8509. --
  8510. --COMPUTE THE float AND IMIGINARY PARTS OF THE INDEX OF REFRACTION
  8511. --
  8512.       For K in 1..NH Loop
  8513.          AE := (3.18E9*EN(K))/(OMEGA2 + (0.7745967*VEAIR(K))**2);
  8514.          BE := VEAIR(K)*AE/OMEGA;
  8515.          AI := (5.45E4*PN(K))/(OMEGA2 + VIAIR(K)*VIAIR(K));
  8516.          BI := VIAIR(K)*AI/OMEGA;
  8517.          A(K) := AE + AI;
  8518.          B(K) := BE + BI;
  8519.       End Loop;
  8520. --
  8521. --FIX SLAB THICKNESS, NUMBER OF SUBSLABS AND SUBSLAB THICKNESS
  8522.       NINV := integer(TRUNCATE(DELTAH));
  8523.       KK := 0;
  8524.       HXR := -1.0;
  8525. --
  8526. --INDEX OF REFRACTION COMPONENTS AND REFERENCE ALTITUDE
  8527. --
  8528. --BEGIN ALTITUDE LOOP
  8529.       For K in 1..NH Loop
  8530. --FIRST ALTITUDE
  8531.          If K <= 1 Then
  8532. --SET IMAGINARY COMPONENT OF THE INDEX OF REFRACTION
  8533.             B1 := B(K);
  8534. --COMPUTE THE EXPONENTIAL EXPANSION COEFFICIENT FOR KTH SLAB
  8535.          Else
  8536.             HBS := DELTAH/LOG((B(K))/B1);
  8537. --HAS THE PHASE REFERENCE ALTITUDE BEEN FOUND
  8538.             If HXR < 0.0 Then
  8539. --BEGIN SUBSLAB LOOP
  8540.                For N in 1..NINV Loop
  8541. --CAN A PHASE REFERENCE ALTITUDE BE FOUND IN THIS SLAB SATISFYING
  8542. --CRAIN-BOOKER CRITERION
  8543.                   XI := FLOAT(N);
  8544.                   B1 := B1*EXP(DH/HBS/1000.0);
  8545.                   If B1 > 0.04 Then
  8546.                      HXR := HP(K-1)+XI*DH/1000.0;
  8547.                      exit ;
  8548.                   End If;
  8549.                End Loop;
  8550.                Goto FIFTY;
  8551. --CAN A MAXIMUM ALTITUDE INDEX BE FOUND
  8552.             End If;
  8553.             If KK <= 0 Then
  8554.               KK := MIN(NH,integer(TRUNCATE(AMIN1(15.0/DELTAH,
  8555.                                         5.0*ABS(HBS)/DELTAH)))+1+K);
  8556.               Goto FIFTY;
  8557.             End If;
  8558.             If K >= KK  Then
  8559.                exit;
  8560.             End If;
  8561. --SET COMPLEX COMPONENT OF INDEX OF REFRACTION OF KTH SLAB AS
  8562. --ADJACENT TO (K+1)TH SLAB
  8563. --
  8564. <<FIFTY>>
  8565.             B1 := B(K);
  8566. --END ALTITUDE LOOP
  8567.          End If;
  8568.       End Loop;
  8569. --
  8570. --REFLECTION COEFFICIENT DOWN TO ALTITUDE H
  8571. --
  8572. --BEGIN IONOSPHERIC INCIDENT ANGLE LOOP
  8573. --
  8574.       For I in 1..2 Loop
  8575.          NPHASE := 0;
  8576.          RIPREV := 0.0;
  8577.          C2 := CID(I)**2;
  8578.          OK := SQRT(U*C2/EPS);
  8579. --BEGIN SLAB LOOP
  8580.          For L in 1..KK Loop
  8581.             K := KK + 1 - L;
  8582. --TOP OF IONOSPHERE
  8583.             If L <= 1 Then
  8584. --SET COMPONENTS OF COMPLEX INDEX OF REFRACTION
  8585.                A1 := A(K);
  8586.                B1 := B(K);
  8587.             Else
  8588. --EXPONENTIAL INTERPOLATION PARAMETERS FOR THE COMPONENTS, A AND B
  8589. --OF THE INDEX OF REFRACTION
  8590.                HAS := DELTAH/LOG(A1/A(K));
  8591.                HBS := DELTAH/LOG(B1/B(K));
  8592. --BOTTOM OF TOP SLAB
  8593.                If L <= 2 Then
  8594. --USING THE COMPLEX VALUE, BBB, OBTAIN THE IMPEDANCE
  8595.                   BBB := CMPLX(A1 - C2, B1);
  8596.                   BBB := CSQRT(BBB)*CMPLX(SIGN(1.0, AREAL(CSQRT(BBB))),0.0);
  8597.                   Z := (CMPLX(WAVE,0.0)*BBB)/CMPLX(WE*B1, WE*(1.0 - A1));
  8598. --BEGIN SUBSLAB LOOP
  8599.                End If;
  8600.                For N in 1..NINV Loop
  8601.                   XN := FLOAT(N);
  8602.                   HOUT := HP(K) + 5.0 - XN;
  8603. --INTERPOLATE FOR COMPONENTS OF COMPLEX INDEX OF REFRACTION
  8604.                   A1 := A1*EXP(-DH/HAS/1000.0);
  8605.                   B1 := B1*EXP(-DH/HBS/1000.0);
  8606.                   BBB := CMPLX(A1 - C2, B1);
  8607.                   BBB := CSQRT(BBB)*CMPLX(SIGN(1.0, AREAL(CSQRT(BBB))),0.0);
  8608.                   BBB := CMPLX(WAVE,0.0) * BBB;
  8609.                   XK := BBB/CMPLX (WE*B1, WE*(1.0 - A1 ));
  8610.                   TH :=  RFUTIL.CTANH (CMPLX(DH,0.0)*BBB);
  8611.                   X := XK*TH;
  8612.                   Y := Z*TH;
  8613.                   ZX := (Z + X)/(XK + Y );
  8614.                   Z := ZX*XK;
  8615.                   R := (CMPLX(OK,0.0) - Z)/(CMPLX(OK, 0.0) + Z);
  8616. --IS THE REFERENCE ALTITUDE LESS THAN FIELD ALTIUDE
  8617.                   If HOUT < HXR Then
  8618. --COUNT THE NUMBER OF REVOLUTIONS OF THE REFLECTION
  8619. --COEFFICIENT VECTOR
  8620.                      RIM := AIMAG (R);
  8621.                      If ABS(RIPREV) >= 0.000001 or AREAL(R) >= 0.0 Then
  8622.                         If RIPREV > 0.0 and RIM < 0.0 Then
  8623.                            NPHASE := NPHASE + 1;
  8624.                         End If;
  8625.                         If RIPREV < 0.0 and RIM > 0.0 Then
  8626.                            NPHASE := NPHASE - 1;
  8627.                         End If;
  8628.                      End If;
  8629.                      RIPREV := RIM;
  8630. --END OF SUBINTERVAL LOOP OBTAINING THE IMPEDANCE FOR THE KTH SLAB
  8631.                   End If;
  8632.                End Loop;
  8633. --RESET THE COMPONENTS OF THE INDEX OF REFRACTION , OBTAIN THE
  8634. --COMPONENTS OF THE REFLECTION COEFFICIENT AND CALCULATE
  8635. --THE ATTENUATION DIVIDED BY COSINE OF THE INCIDENCE ANGLE
  8636.                A1 := A(K);
  8637.                B1 := B(K);
  8638.                RRR := AREAL(R);
  8639.                RI  := AIMAG(R);
  8640.                AMP(K) := -8.7*LOG(1.0/SQRT(RRR*RRR + RI*RI))/CID(I);
  8641. --OBTAIN THE FRESNEL REFLECTION COEFFICIENT
  8642.                TEST := (CMPLX(OK, 0.0) - XK)/(CMPLX(OK,0.0) + XK);
  8643.                TESTR := AREAL(TEST);
  8644.                TESTI := AIMAG (TEST);
  8645.                AMTEST := 8.7*LOG(1.0/SQRT(TESTR**2 + TESTI**2));
  8646. --IS 40 DB GREATER THAN SUM OF ATTENUATION OF THE REFLECTION
  8647. --COEFFICIENT + FRESNEL REFLECTION
  8648.                If AMTEST + AMP(K)*CID(I) > 40.0 Then
  8649.                   exit;
  8650.                End If;
  8651. --END OF FIELD ALTITUDE LOOP
  8652.             End If;
  8653.          End Loop;
  8654. --
  8655. --AMPLITUDE  OF REFLECTION COEFFICIENT: 960
  8656. --
  8657. --COMPUTE THE PHASES FOR THIS INCIDENCE ANGLE
  8658. --
  8659.          ALPHX(I) := AMP(K)/8.7;
  8660. --END OF INCIDENCE ANGLE LOOP
  8661.       End Loop;
  8662. --OBTAIN THE EXPANSION COEFFICIENTS OF THE REFLECTION COEFFICIENT
  8663.       ALP1 := (ALPHX(1) + ALPHX(2))/2.0;
  8664. --
  8665.       Return;
  8666.       End REFCAL;
  8667. --
  8668. --
  8669. End ELF_LF_HF_ATMOSPHERICS;
  8670. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8671. --AIR
  8672. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  8673. With Debugger2; Use Debugger2;
  8674. With text_io; Use Text_io;
  8675. With Complex_numbers; Use Complex_numbers;
  8676. With Mathlib; Use Mathlib, Numeric_primitives, Core_functions, Trig_functions;
  8677.  
  8678. package AIR is
  8679.  
  8680.       Function CXSQRT (Z: complex) return complex;
  8681.       Procedure ZEXP (A: in float;
  8682.                       B: in float;
  8683.                       X: out float;
  8684.                       Y: out float;
  8685.                       MAGTUD: out integer);
  8686.       Function AIRY (ZZ: complex; K: integer) return complex;
  8687.       MEXP: integer;
  8688.  
  8689. end AIR;
  8690. package body AIR is
  8691.       Pragma source_info (on);
  8692.       Function ANM (Z: complex) return float is
  8693. --
  8694. --#PURPOSE: Calculates the sum of the absolute values of the real and
  8695. --          imaginary parts of the input argument.
  8696. --
  8697. --#AUTHOR:  J. Conrad
  8698. --
  8699. --#TYPE:    Math utility
  8700. --
  8701. --#PARAMETER DESCRIPTIONS:
  8702. --IN        Z      = Function argument
  8703. --
  8704. --#CALLED BY:
  8705. --          AIRY
  8706. --
  8707. --#CALLS TO:
  8708. --          'NONE'
  8709. --
  8710. --#TECHNICAL DESCRIPTION:
  8711. --          Calculates the sum of the absolute values of the real and
  8712. --          imaginary parts of the input argument.
  8713. --
  8714.       Begin
  8715. --
  8716.       Return ABS(AREAL(Z)) + ABS(AIMAG(Z));
  8717.  
  8718. --
  8719.       End ANM;
  8720. --
  8721.       Function CXSQRT (Z: complex) return complex is
  8722. --
  8723. --#PURPOSE: Calculates the complex square root with positive sense.
  8724. --
  8725. --#AUTHOR:  J. Conrad
  8726. --
  8727. --#TYPE:    Math utility
  8728. --
  8729. --#PARAMETER DESCRIPTIONS:
  8730. --IN        Z      = Function argument
  8731. --
  8732. --#CALLED BY:
  8733. --          AIRY
  8734. --
  8735. --#CALLS TO:
  8736. --          'NONE'
  8737. --
  8738. --#TECHNICAL DESCRIPTION:
  8739. --          The complex square root of a complex number is computed and
  8740. --          the sign of the real paart of the input argument is placed
  8741. --          on the return argument.
  8742. --
  8743.       Begin
  8744. --
  8745.       Return CSQRT(Z)*SIGN(1.0,AREAL(CSQRT(Z)));
  8746. --
  8747.       End CXSQRT;
  8748.  
  8749.       Procedure ZEXP (A: in float;
  8750.                       B: in float;
  8751.                       X: out float;
  8752.                       Y: out float;
  8753.                       MAGTUD: out integer) is
  8754. --
  8755. --#PURPOSE:ZEXP converts the form representing a complex number
  8756. --          from a complex exponential to a real exponential times a
  8757. --          complex number.
  8758. --
  8759. --#AUTHOR: J. Conrad
  8760. --
  8761. --#TYPE:    Numerical Analysis
  8762. --
  8763. --#PARAMETER DESCRIPTIONS:
  8764. --IN        A      = Real part of the argument
  8765. --IN        B      = Complex part of the argument
  8766. --OUT       X      = A scalar quantity
  8767. --OUT       Y      = A scalar quantity
  8768. --OUT       MAGTUD = The largest integer less than or equal to A
  8769. --
  8770. --#CALLED BY:
  8771. --          AIRY
  8772. --          GRWAVE
  8773. --
  8774. --#CALLS TO:
  8775. --          'NONE'
  8776. --
  8777. --#TECHNICAL DESCRIPTION:
  8778. --          ZEXP converts the form representing a complex number
  8779. --          from a complex exponential to a real exponential times a
  8780. --          complex number. 
  8781. --
  8782.       E, SCALE: float;
  8783. --
  8784.       Begin
  8785. --
  8786.       MAGTUD := INTEGER(A);
  8787.       SCALE := FLOAT(MAGTUD);
  8788.       E := EXP(A - SCALE);
  8789.       X := E*COS(B);
  8790.       Y := E*SIN(B);
  8791.       Return;
  8792. --
  8793.       End ZEXP;
  8794. --
  8795.             Function AIRY (ZZ: complex; K: integer) return complex is
  8796. --
  8797. --#PURPOSE: AIRY calculates Airy functions.
  8798. --
  8799. --#AUTHOR:  J. Conrad
  8800. --
  8801. --#TYPE:    Computational Subroutine
  8802. --
  8803. --#PARAMETER DESCRIPTIONS:
  8804. --IN        ZZ     = Airy function argument
  8805. --IN        K      = Branching index
  8806. --
  8807. --#CALLED BY:
  8808. --          CWAIRY
  8809. --
  8810. --#CALLS TO:
  8811. --          ANM
  8812. --          CXSQRT
  8813. --          ZEXP
  8814. --
  8815. --#TECHNICAL DESCRIPTION:
  8816. --          Hufford's normalization of the Airy functions is used.
  8817. --
  8818.       WI1, WI1P, WI2, WI2P: complex;
  8819.       Z, U, ZT, ZA, ZB, ZE, ZR, B0, B1, B2, B3: complex;
  8820.       LG: array (integer range 1..3) of boolean := (FALSE, FALSE, FALSE);
  8821.       X:array (integer range 1..2) of float;
  8822.       X1: array (integer range 1..2) of float;
  8823.       XT: array (integer range 1..2) of float;
  8824.       AN, P, Q, SX, SY, T, XA, ZM: float;
  8825.       IP, IQ, N, IK, I, NT, LA, LB, LC: integer;
  8826.       A, AP, Z1: complex;
  8827.       AV, APV: array (integer range 1..70) of complex;
  8828.       ASLT: array (integer range 1..17) of float :=
  8829.         (1.1407E+02, 1.1549E+02,
  8830.          1.1779E+02, 1.2124E+02, 1.2619E+02, 1.3319E+02,
  8831.          1.4307E+02, 1.5716E+02, 1.7774E+02, 2.0884E+02,
  8832.          2.5832E+02, 3.4294E+02, 5.0339E+02, 8.5678E+02,
  8833.          1.8336E+03, 5.7270E+03, 3.5401E+04);
  8834. --
  8835.       ASV: array (integer range 1..21) of float :=
  8836.         (1.83357669E+10,
  8837.          1.92937554E+09, 2.14288037E+08, 2.51989198E+07,
  8838.          3.14825741E+06, 4.19524875E+05, 5.98925135E+04,
  8839.          9.20720660E+03, 1.53316943E+03, 2.78465080E+02,
  8840.          5.56227853E+01, 1.23415733E+01, 3.07945303E+00,
  8841.          8.77666969E-01, 2.91591399E-01, 1.16099064E-01,
  8842.          5.76491904E-02, 3.79930591E-02, 3.71334876E-02,
  8843.          6.94444444E-02, 1.00000000E+00);
  8844. --
  8845.       APSV: array (integer range 1..21) of float :=
  8846.        (-1.86439310E+10,
  8847.         -1.96352378E+09,-2.18293420E+08,-2.56979083E+07,
  8848.         -3.21453652E+06,-4.28952400E+05,-6.13357066E+04,
  8849.         -9.44635482E+03,-1.57635730E+03,-2.87033237E+02,
  8850.         -5.75083035E+01,-1.28072930E+01,-3.21049358E+00,
  8851.         -9.20479992E-01,-3.08253764E-01,-1.24105896E-01,
  8852.         -6.26621635E-02,-4.24628307E-02,-4.38850308E-02,
  8853.         -9.72222222E-02, 1.00000000E+00);
  8854. --
  8855.       NQTT: array (integer range 1..15) of integer :=
  8856.          (1, 3, 7, 12, 17, 23, 29, 35, 41, 47, 53, 59, 64, 68, 71);
  8857. --
  8858.    begin
  8859.       Z1 := CMPLX(0.0,0.0);
  8860.       A := CMPLX(0.35502805,0.0);
  8861.       AP := CMPLX(-0.25881940,0.0);
  8862. --
  8863. -- A TEMPORARY BLOCK IS USED TO LOAD COMPLEX ARRAYS
  8864.       declare
  8865.          TEMP: array (integer range 1..70, integer range 1..2) of float;
  8866.       begin
  8867.          TEMP :=
  8868.         ((-3.29145173E-01, 0.00000000E+00),
  8869.         (-2.67800356E+00, 1.47745895E+00),
  8870.         ( 3.50761009E-01, 0.00000000E+00),
  8871.         ( 2.41222621E+00, 6.98651244E-01),
  8872.         ( 3.36355311E+01,-3.46009596E+00),
  8873.         ( 3.44497396E+02,-3.36908902E+02),
  8874.         (-7.02655329E-02, 0.00000000E+00),
  8875.         (-5.48182192E-01,-1.92073659E+00),
  8876.         (-1.33833953E+01,-1.60225908E+01),
  8877.         (-2.29677959E+02,-3.20724526E+01),
  8878.         (-1.80407804E+03, 2.19176750E+03),
  8879.         (-3.78814293E-01, 0.00000000E+00),
  8880.         (-1.34918360E+00, 8.49690772E-01),
  8881.         (-6.04533393E+00, 1.06231755E+01),
  8882.         ( 3.11696216E+01, 9.88135176E+01),
  8883.         ( 9.89253493E+02, 1.39052860E+02),
  8884.         ( 2.27407428E-01, 0.00000000E+00),
  8885.         ( 7.18574034E-01, 9.78090941E-01),
  8886.         ( 6.06210880E+00, 2.72030148E+00),
  8887.         ( 3.63070848E+01,-2.09613558E+01),
  8888.         (-6.71397891E+01,-3.09046387E+02),
  8889.         (-2.80016536E+03, 4.66493659E+02),
  8890.         ( 5.35560883E-01, 0.00000000E+00),
  8891.         ( 9.24073653E-01,-1.91065600E-01),
  8892.         ( 1.87161859E+00,-2.57433103E+00),
  8893.         (-7.21884363E+00,-1.29242001E+01),
  8894.         (-8.17873778E+01, 3.20870138E+01),
  8895.         ( 2.99339485E+02, 5.69221792E+02),
  8896.         ( 3.55028053E-01, 0.00000000E+00),
  8897.         ( 3.12034381E-01,-3.88453850E-01),
  8898.         (-5.28399993E-01,-1.09764112E+00),
  8899.         (-4.20093515E+00, 1.19401511E+00),
  8900.         ( 7.18588328E+00, 1.96009125E+01),
  8901.         ( 1.01291210E+02,-7.59512332E+01),
  8902.         ( 1.35292416E-01, 0.00000000E+00),
  8903.         ( 3.26184783E-02,-1.70848727E-01),
  8904.         (-3.42153810E-01,-8.90676463E-02),
  8905.         (-1.45096414E-01, 1.03280157E+00),
  8906.         ( 4.10019685E+00,-6.89369117E-01),
  8907.         (-1.30301240E+01,-1.69105414E+01),
  8908.         ( 3.49241304E-02, 0.00000000E+00),
  8909.         (-8.44647266E-03,-4.20451544E-02),
  8910.         (-6.93132689E-02, 3.53647987E-02),
  8911.         ( 1.52276226E-01, 1.28484544E-01),
  8912.         ( 1.06813731E-01,-6.77661535E-01),
  8913.         (-2.61934327E+00, 1.56998599E+00),
  8914.         ( 6.59113935E-03, 0.00000000E+00),
  8915.         (-3.94439855E-03,-6.80601061E-03),
  8916.         (-5.98201310E-03, 1.17990101E-02),
  8917.         ( 2.99224984E-02,-5.97729307E-03),
  8918.         (-7.74641302E-02,-5.22924027E-02),
  8919.         ( 1.12765858E-01, 3.51124424E-01),
  8920.         ( 9.51563851E-04, 0.00000000E+00),
  8921.         (-8.08429956E-04,-7.65901326E-04),
  8922.         ( 1.61478160E-04, 1.76617551E-03),
  8923.         ( 2.01387183E-03,-3.19767166E-03),
  8924.         (-9.50867844E-03, 4.53778324E-03),
  8925.         ( 3.75601918E-02, 5.73619168E-04),
  8926.         ( 1.08344428E-04, 0.00000000E+00),
  8927.         (-1.09686064E-04,-5.99023296E-05),
  8928.         ( 1.07781913E-04, 1.57715962E-04),
  8929.         (-6.89809378E-05,-3.76264573E-04),
  8930.         (-1.61661261E-04, 9.74577732E-04),
  8931.         ( 9.94769436E-06, 0.00000000E+00),
  8932.         (-1.09568239E-05,-2.95087996E-06),
  8933.         ( 1.47090745E-05, 8.10420897E-06),
  8934.         (-2.44460151E-05,-2.06381431E-05),
  8935.         ( 7.49212886E-07, 0.00000000E+00),
  8936.         (-8.46190689E-07,-3.68073383E-08),
  8937.         ( 1.21839633E-06, 8.35891994E-08));
  8938.          for I in 1..70 loop
  8939.             AV(I):=CMPLX(TEMP(I,1),TEMP(I,2));
  8940.          end loop;
  8941.  
  8942.          TEMP :=
  8943.         (( 3.45935487E-01, 0.00000000E+00),
  8944.         ( 4.17088765E+00, 6.24144377E+00),
  8945.         ( 3.27192818E-01, 0.00000000E+00),
  8946.         ( 1.08287427E+00,-5.49283025E+00),
  8947.         (-2.33635179E+01,-7.49018481E+01),
  8948.         (-1.02648775E+03,-5.67079408E+02),
  8949.         (-7.90628575E-01, 0.00000000E+00),
  8950.         (-3.80858333E+00, 1.51296051E+00),
  8951.         (-2.60863790E+01, 3.55407099E+01),
  8952.         ( 1.07618382E+02, 5.12399449E+02),
  8953.         ( 6.65977971E+03, 1.80961862E+03),
  8954.         ( 3.14583769E-01, 0.00000000E+00),
  8955.         ( 1.87154254E+00, 2.05448365E+00),
  8956.         ( 2.25917369E+01, 4.85629954E+00),
  8957.         ( 1.61629978E+02,-1.43355971E+02),
  8958.         (-8.00471616E+02,-2.15274542E+03),
  8959.         ( 6.18259020E-01, 0.00000000E+00),
  8960.         ( 1.30196038E+00,-1.22907749E+00),
  8961.         ( 1.50361187E-01,-1.10080928E+01),
  8962.         (-7.01168003E+01,-4.04808227E+01),
  8963.         (-4.83171669E+02, 4.96927557E+02),
  8964.         ( 4.89706556E+03, 4.86272908E+03),
  8965.         (-1.01605671E-02, 0.00000000E+00),
  8966.         (-5.48266364E-01,-7.13652884E-01),
  8967.         (-4.67491340E+00,-1.19242452E-01),
  8968.         (-1.05363978E+01, 2.49437113E+01),
  8969.         ( 1.63337706E+02, 9.03949106E+01),
  8970.         ( 5.64494552E+02,-1.42483244E+03),
  8971.         (-2.58819403E-01, 0.00000000E+00),
  8972.         (-4.86207541E-01, 1.56899249E-01),
  8973.         (-4.73481318E-01, 1.70934381E+00),
  8974.         ( 7.03738407E+00, 3.62818249E+00),
  8975.         ( 1.77395863E+01,-4.03604224E+01),
  8976.         (-2.97915119E+02,-3.84088929E+01),
  8977.         (-1.59147441E-01, 0.00000000E+00),
  8978.         (-1.13404235E-01, 1.97305049E-01),
  8979.         ( 4.01262091E-01, 3.92229958E-01),
  8980.         ( 1.33486524E+00,-1.43772724E+00),
  8981.         (-7.90224947E+00,-4.20636446E+00),
  8982.         (-1.38927521E+00, 5.12294167E+01),
  8983.         (-5.30903844E-02, 0.00000000E+00),
  8984.         (-1.68329655E-03, 6.83669678E-02),
  8985.         ( 1.37894013E-01,-1.16138040E-02),
  8986.         (-1.47137306E-01,-3.71519857E-01),
  8987.         (-1.00701964E+00, 1.15913484E+00),
  8988.         ( 7.50450491E+00, 4.69131153E-01),
  8989.         (-1.19129767E-02, 0.00000000E+00),
  8990.         ( 5.14685749E-03, 1.36608912E-02),
  8991.         ( 1.83097105E-02,-1.88085884E-02),
  8992.         (-6.44615931E-02,-1.36117947E-02),
  8993.         ( 1.05162399E-01, 1.93130535E-01),
  8994.         ( 2.05200462E-01,-9.17726173E-01),
  8995.         (-1.95864095E-03, 0.00000000E+00),
  8996.         ( 1.46956495E-03, 1.80863846E-03),
  8997.         ( 5.97099479E-04,-3.83326992E-03),
  8998.         (-6.89108930E-03, 5.44674252E-03),
  8999.         ( 2.61679277E-02,-8.40920002E-04),
  9000.         (-8.82844741E-02,-4.64753121E-02),
  9001.         (-2.47413890E-04, 0.00000000E+00),
  9002.         ( 2.37078374E-04, 1.64611095E-04),
  9003.         (-1.74655698E-04,-4.20267839E-04),
  9004.         (-1.03945161E-04, 9.47618443E-04),
  9005.         ( 1.30041105E-03,-2.24466568E-03),
  9006.         (-2.47652003E-05, 0.00000000E+00),
  9007.         ( 2.67148709E-05, 9.86915650E-06),
  9008.         (-3.35397741E-05,-2.71132849E-05),
  9009.         ( 4.91978431E-05, 6.93490920E-05),
  9010.         (-2.00815089E-06, 0.00000000E+00),
  9011.         ( 2.26712445E-06, 2.78485083E-07),
  9012.         (-3.26921327E-06,-7.39434886E-07));
  9013.          for I in 1..70 loop
  9014.             APV(I):=CMPLX(TEMP(I,1),TEMP(I,2));
  9015.          end loop;
  9016.       end; 
  9017. --
  9018.       If K = 1 or K = 2 Then
  9019.          LA := 1;
  9020.       Else
  9021.          LA := -1;
  9022.       End If;
  9023.       If K = 1 or K = 3 Then
  9024.          LB := 0;
  9025.       Else
  9026.          LB := 1;
  9027.       End If;
  9028. --
  9029.       Z := ZZ;
  9030.       If LA /= 0 Then
  9031.          If LA > 0 Then
  9032.             U := CMPLX(-0.5, 0.86602540);
  9033.          Else
  9034.             U := CMPLX(-0.5, -0.86602540);
  9035.          End If;
  9036.          Z := U*Z;
  9037.       End If;
  9038. --
  9039.       LC := 0;
  9040.       X(1) := AREAL (Z);
  9041.       X(2) := AIMAG (Z);
  9042.       If X(2) < 0.0 Then
  9043.          LC := 1;
  9044.          X(2) := -X(2);
  9045.          Z := CMPLX (X(1), X(2));
  9046.       End If;
  9047. --
  9048. --COMPARE WITH PREVIOUS.
  9049. --
  9050.       X1(1) := AREAL (Z1);
  9051.       X1(2) := AIMAG (Z1);
  9052.       If X(1) /= X1(1)  or  X(2) /= X1(2) Then
  9053.          Goto AFFINE_COORDINATES;
  9054.       End If;
  9055.       If LG(LB+1) Then
  9056.          Goto EXXIT;
  9057.       End If;
  9058.       If LB /= 0 Then
  9059.          Goto APSTAR;
  9060.       End If;
  9061.       Goto ASTAR;
  9062. --
  9063. <<EXXIT>>
  9064. --
  9065.       If LB /= 0 Then
  9066.          Goto SIXTY;
  9067.       End If;
  9068. --
  9069. <<FIFTY>> 
  9070.       ZT := A;
  9071.       If LC /= 0 Then
  9072.          XT(1) := AREAL(ZT);
  9073.          XT(2) := AIMAG(ZT);
  9074.          XT(2) := -XT(2);
  9075.          ZT := CMPLX (XT(1), XT(2));
  9076.       End If;
  9077.       If LA < 0 Then
  9078.          Goto EIGHTY;
  9079.       Elsif LA = 0 Then
  9080.          Return ZT;
  9081.       Else
  9082.          Goto SEVENTY;
  9083.       End If;
  9084. --
  9085. <<SIXTY>>
  9086.       ZT := AP;
  9087.       XT(1) := AREAL(ZT);
  9088.       XT(2) := AIMAG(ZT);
  9089.       If LC /= 0 Then
  9090.          XT(2) := -XT(2);
  9091.          ZT := CMPLX (XT(1), XT(2));
  9092.       End If;
  9093.       If LA = 0 Then
  9094.          Return ZT;
  9095.       Elsif LA > 0 Then
  9096.          Goto EIGHTY;
  9097.       End If;
  9098. --
  9099. <<SEVENTY>>
  9100.       U := CMPLX(1.0, -1.73205080);
  9101.       Goto NINETY;
  9102. --
  9103. <<EIGHTY>>
  9104.       U := CMPLX(1.0, 1.73205080);
  9105. --
  9106. <<NINETY>>
  9107.       ZT := U*ZT;
  9108.       Return ZT;
  9109. --
  9110. <<AFFINE_COORDINATES>>
  9111. --
  9112.       MEXP := 0;
  9113.       Z1 := Z;
  9114.       X1(1) := AREAL(Z1);
  9115.       X1(2) := AIMAG(Z1);
  9116.       XT(1) := AREAL(ZT);
  9117.       XT(2) := AIMAG(ZT);
  9118.       X(1) := AREAL(Z);
  9119.       X(2) := AIMAG(Z);
  9120.       LG(1) := FALSE;
  9121.       LG(2) := FALSE;
  9122.       LG(3) := FALSE;
  9123.       If X(1) <= -7.0  or  X(1) > 7.0  or  X(2) > 6.92820323 Then
  9124.          Goto ASYMPTOTICS;
  9125.       End If;
  9126.       IP := INTEGER(7.0 - X(1));
  9127.       IP := 7 - IP;
  9128.       P := FLOAT(IP);
  9129.       IQ := INTEGER(0.86602540*X(2) + 0.5*(P - X(1)));
  9130.       Q := FLOAT(IQ);
  9131.       N := NQTT(IP + 7) + IQ;
  9132.       If N >= NQTT(IP + 8) Then
  9133.          Goto ASYMPTOTICS;
  9134.       End If;
  9135. --
  9136. --SERIES.
  9137. --
  9138.       XT(1) := P;
  9139.       XT(2) := 1.15470053*Q;
  9140.       ZT := CMPLX (XT(1), XT(2));
  9141.       U := Z - ZT;
  9142.       B1 := AV(N);
  9143.       B3 := B1*ZT*U;
  9144.       AP := APV(N);
  9145.       B2 := AP*U;
  9146.       A := B2 + B1;
  9147.       AP := AP + B3;
  9148.       AN := 1.0;
  9149.       IK := 3;
  9150.       I := 1;
  9151.  --
  9152. <<TWENTY>>
  9153.       I := I + 1;
  9154.       AN := AN + 1.0;
  9155.       B3 := B3*U/AN; 
  9156.       A := B3 + A;
  9157.       B0 := B1;
  9158.       B1 := B2;
  9159.       B2 := B3;
  9160.       B3 := (ZT*B1 + U*B0)*U/AN;
  9161.       AP := B3 + AP;
  9162.       If ANM(B2) >= 0.5E-10*ANM(A) or
  9163.          ANM(B3) >= 0.5E-10*ANM(AP) Then
  9164.          If I < 99 Then
  9165.             Goto TWENTY;
  9166.          End If;
  9167.          New_Line;
  9168.          Put ("Possible error in Procedure AIRY...no convergence");
  9169.          New_Line;
  9170.          Put ("after 99 iterations.  Groundwave signal level may");
  9171.          New_Line;
  9172.          Put ("be incorrect by a significant amount.");
  9173.       End If;
  9174.       LG(1) := TRUE;
  9175.       LG(2) := TRUE;
  9176.       Goto EXXIT;
  9177. --
  9178. <<ASYMPTOTICS>>
  9179.       ZA := CXSQRT(Z);
  9180.       ZB := 0.28209479/CXSQRT(ZA);
  9181.       ZT := -0.66666666*Z*ZA;
  9182.       XT(1) := AREAL(ZT);
  9183.       XT(2) := AIMAG(ZT);
  9184.       T := XT(1)**2 + XT(2)**2;
  9185.       ZEXP(XT(1), XT(2), SX, SY, MEXP);
  9186.       ZE := CMPLX(SX , SY);
  9187.       XA := FLOAT(MEXP + MEXP);
  9188.       IF 2*MEXP > 50 tHEN
  9189.          XA := 50.0;
  9190.       End If;
  9191.       If 2*MEXP < -50 Then
  9192.          XA := -50.0;
  9193.       End If;
  9194.       ZM := EXP(-XA);
  9195.       ZR := 1.0/ZT;
  9196.       If XT(2) > 0.0  and  XT(1) < 11.8595 Then
  9197.          LG(3) := TRUE;
  9198.       End If;
  9199.       For I in 2..19 Loop
  9200.          NT := I;
  9201.          Exit When (NT = 19 or T < ASLT(NT-1));
  9202.       End Loop;
  9203.       If LB /= 0 Then
  9204.          Goto APSTAR;
  9205.       End If;
  9206. --
  9207. <<ASTAR>>
  9208.       ZT := CMPLX(ASV(NT-1), 0.0);
  9209.       If NT <= 21 Then
  9210.          For I in NT..21 Loop
  9211.             ZT := ASV(I) + ZT*ZR;
  9212.          End Loop;
  9213.       End If;
  9214.       A := ZT*ZE;
  9215.       If LG(3) Then
  9216.          Goto A1310;
  9217.       End If;
  9218. --
  9219. <<A1300>>
  9220.       A := ZB*A;
  9221.       LG(1) := TRUE;
  9222.       Goto FIFTY;
  9223. --
  9224. <<A1310>>
  9225.       ZT := CMPLX(ASV(NT-1),0.0);
  9226.       If NT <= 21 Then
  9227.          For I in NT..21 Loop
  9228.             ZT := ASV(I) - ZT*ZR;
  9229.         End Loop;
  9230.       End If;
  9231.       A := A + CMPLX(0.0, 1.0)*ZT/(ZE)*ZM;
  9232.       Goto A1300;
  9233. --
  9234. <<APSTAR>>
  9235.       ZT := CMPLX(APSV(NT-1),0.0);
  9236.       If NT <= 21 Then
  9237.          For I in NT..21 Loop
  9238.             ZT := APSV(I) + ZT*ZR;
  9239.          End Loop;
  9240.       End If;
  9241.       AP := -ZT*ZE;
  9242.       If LG(3) Then
  9243.          Goto AP1380;
  9244.       End If;
  9245. -- 
  9246. <<AP1370>>
  9247.       AP := ZA*ZB*AP;
  9248.       LG(2) := TRUE;
  9249.       Goto SIXTY;
  9250. --
  9251. <<AP1380>>
  9252.       ZT := CMPLX(APSV(NT-1),0.0);
  9253.       If NT <= 21 Then
  9254.          For I in NT..21 Loop
  9255.             ZT := APSV(I) - ZT*ZR;
  9256.          End Loop;
  9257.       End If;
  9258.       AP := AP + CMPLX(0.0, 1.0)*ZT/(ZE)*ZM;
  9259.       Goto AP1370;
  9260. --
  9261.       End AIRY;
  9262.  
  9263. End AIR;
  9264. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9265. --LFHFGROU
  9266. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9267. With Debugger2; Use Debugger2;
  9268. With Complex_numbers; Use Complex_numbers;
  9269. With Mathlib; Use Mathlib, Numeric_primitives, Core_functions, Trig_functions;
  9270. With Text_io; Use Text_io;
  9271. With Constants; Use Constants;
  9272. With Propagation_constants; Use Propagation_Constants;
  9273. With Air; Use Air;
  9274.  
  9275. Package LF_HF_GROUNDWAVES is
  9276. --
  9277. --
  9278.       Procedure GRWAVE (COND: in float;
  9279.                         FREQ: in float;
  9280.                         SURDIS: in float;
  9281.                         NPOL: in integer;
  9282.                         POWER: in float;
  9283.                         HLOWER: in float;
  9284.                         HHIGHR: in float;
  9285.                         VOLTPM: out float;
  9286.                         DBLOSS: out float);
  9287. --
  9288. --
  9289. End LF_HF_GROUNDWAVES;
  9290. --
  9291. Package body LF_HF_GROUNDWAVES is
  9292. --
  9293. -- LF_HF_GROUNDWAVES Package of PROP_LINK 
  9294. -- Version 1.0,  April 23, 1985.
  9295. --
  9296. -- This LF_HF_GROUNDWAVES Package contains all of the procedures that 
  9297. -- are used to compute groundwave RF propagation at LF and HF frequencies.
  9298. --
  9299. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  9300. -- radio frequency propagation prediction code.
  9301. --
  9302. -- PROP_LINK has been developed for the Department of Defense under
  9303. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  9304. -- Systems Inc. (Jim Conrad).
  9305. --
  9306.       Pragma Source_info (on);
  9307. --
  9308. --VARIABLES THAT ARE TO BE VISIBLE TO ALL ROUTINES WITHIN THIS PACKAGE ONLY:
  9309.       Q: complex;
  9310.       AK1, V, ZC, Y1, Y2, COTH, STH, X, HTKM, HRKM, FLF, A: float;
  9311.  
  9312.       Procedure UP (A: in COMPLEX; E: out COMPLEX);
  9313.       Function OMCOS (X: float) return float;
  9314.       Function RGW (MMM: in integer) return complex;
  9315.       Procedure TW (I: in integer;
  9316.                     Q: in complex;
  9317.                     T: out complex;
  9318.                     W1: out complex;
  9319.                     MW1: out integer;
  9320.                     DW1: out complex;
  9321.                     MD1: out integer;
  9322.                     W2: out complex;
  9323.                     MW2: out integer;
  9324.                     DW2: out complex;
  9325.                     MD2: out integer);
  9326. --
  9327. --
  9328. --
  9329. --
  9330.       Procedure CWAIRY (KK: in integer;
  9331.                         T: in complex;
  9332.                         F1: out complex;
  9333.                         M1: out integer;
  9334.                         F2: out complex;
  9335.                         M2: out integer) is
  9336. --
  9337. --#PURPOSE: CWAIRY calculates the Airy functions.
  9338. --
  9339. --#AUTHOR:  J. Conrad
  9340. --
  9341. --#TYPE:    Numerical Analysis
  9342. --
  9343. --#PARAMETER DESCRIPTIONS:
  9344. --IN        KK     = Flag indicating types of calculations desired;
  9345. --                   1...For Kind 1 and 2
  9346. --                   2...For derivatives
  9347. --IN        T      = The complex argument MEXP 
  9348. --OUT       F1     = The Airy function coefficient for the
  9349. --                   Airy function Kind 1 or its derivative,
  9350. --                   depending on KK.  The Airy function
  9351. --                   value equals F1*(E**M1) where E is
  9352. --                   the Napierian base.
  9353. --OUT       M1     = The Airy function exponent for the Airy
  9354. --                   function Kind 1 or its derivatives,
  9355. --                   depending on KK.  The Airy function
  9356. --                   value equals F1*(E**M1) where E is
  9357. --                   the Napierian base.
  9358. --OUT       F2     = Same as F1 for Kind 2
  9359. --OUT       M2     = Same as M1 for Kind 2
  9360. --
  9361. --#CALLED BY:
  9362. --          GRWAVE
  9363. --          RGW
  9364. --          TW
  9365. --
  9366. --#CALLS TO:
  9367. --          AIRY
  9368. --
  9369. --#TECHNICAL DESCRIPTION:
  9370. --          CWAIRY is the master subroutine for calculating Airy
  9371. --          functions of Kinds 1 and 2, and their derivatives.
  9372. --          See Function AIRY.  Subroutine CWAIRY enters Function
  9373. --          AIRY at different points depending on the type of
  9374. --          function or its derivative that is being evaluated.
  9375. --
  9376. --
  9377.       Begin
  9378. --
  9379.       If KK = 1 Then
  9380.          F2 := AIRY(T, 1);
  9381.          M2 := MEXP;
  9382.          F1 := AIRY(T, 3);
  9383.          M1 := MEXP;
  9384.       Else
  9385.          F2 := AIRY(T, 2);
  9386.          M2 := MEXP;
  9387.          F1 := AIRY(T, 4);
  9388.          M1 := MEXP;
  9389.       End If;
  9390.       F1 := 1.77245385*CMPLX(0.0, -1.0)*F1;
  9391.       F2 := 1.77245385*CMPLX(0.0, +1.0)*F2;
  9392.       Return;
  9393. --
  9394.       End CWAIRY;
  9395. --
  9396. --
  9397. --
  9398. --
  9399.       Procedure DOWN (A: in complex;
  9400.                       E: out complex) is
  9401. --
  9402. --#PURPOSE: DOWN calculates error function values.
  9403. --
  9404. --#AUTHOR:  J. Conrad
  9405. --
  9406. --#TYPE:    Numerical Analysis
  9407. --
  9408. --#PARAMETER DESCRIPTIONS:
  9409. --IN        A      = Complex argument
  9410. --OUT       E      = CEXP (A**2) + ERF(A)
  9411. --
  9412. --#CALLED BY:
  9413. --          UP
  9414. --
  9415. --#CALLS TO:
  9416. --          UP
  9417. --
  9418. --#TECHNICAL DESCRIPTION:
  9419. --          The essence of this routine has been extracted from:
  9420. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  9421. --          developed by Leslie A. Berry of the U.S. Department of
  9422. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  9423. --          Colorado.
  9424. --
  9425.       U: complex;
  9426.       Z,ZI, CR, CI, BR, BI, Z2R, Z2I, EM, PR, PI, EI, ER: float;
  9427. --
  9428.       Begin
  9429. --
  9430.       If (CABS(A) - 3.5) > 0.0 Then
  9431.          UP(A,U);
  9432.          E := CEXP(A**2) - U;
  9433.       Else
  9434.          Z := AREAL (A);
  9435.          ZI := AIMAG (A);
  9436.          CR := 1.12837916*Z;
  9437.          CI := 1.12837916*ZI;
  9438.          BR := CR;
  9439.          BI := CI;
  9440.          Z2R := Z*Z-ZI*ZI;
  9441.          Z2I := 2.0*Z*ZI;
  9442.          EM := 1.5;
  9443.          Loop
  9444.             PR := Z2R*CR - Z2I*CI;
  9445.             PI := Z2R*CI + Z2I*CR;
  9446.             CR := PR/EM;
  9447.             CI := PI/EM;
  9448.             BR := BR + CR;
  9449.             BI := BI + CI;
  9450.             Exit When ((CR*CR+CI*CI)/(BR*BR+BI*BI)-1.0E-11) <= 0.0;
  9451.             EM := EM + 1.0;
  9452.          End Loop;
  9453.          ER := BR;
  9454.          EI := BI;
  9455.          E := CMPLX (ER,EI);
  9456.       End If;
  9457.       Return;
  9458. --
  9459.       End DOWN;
  9460. --
  9461. --
  9462.       Function ECOM (Z: complex) return complex is
  9463. --
  9464. --#PURPOSE:ECOM calculates the values of complementary error
  9465. --          functions with complex arguments.
  9466. --
  9467. --#AUTHOR:  J. Conrad
  9468. --
  9469. --#TYPE:    Numerical Analysis
  9470. --
  9471. --#PARAMETER DESCRIPTIONS:
  9472. --IN        Z      = The complex argument
  9473. --OUT       ECOM   = ECOM := CEXP (Z**2)*ERFC(Z)
  9474. --
  9475. --#CALLED BY:
  9476. --          GRWAVE
  9477. --
  9478. --#CALLS TO:
  9479. --          UP
  9480. --
  9481. --#TECHNICAL DESCRIPTION:
  9482. --          ECOM calls UP for evaluation of the complementary error
  9483. --          function value, ERFC.
  9484. --
  9485. --          The essence of this routine has been extracted from:
  9486. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  9487. --          developed by Leslie A. Berry of the U.S. Department of
  9488. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  9489. --          Colorado.
  9490. --
  9491.       ZP, RESULT: complex;
  9492.       ZR, XA: float;
  9493. --
  9494.       Begin
  9495. --
  9496.       ZR := AREAL(Z);
  9497.       XA := AREAL(Z**2);
  9498.       If ZR >= 0.0 Then
  9499.          UP (Z, RESULT);
  9500.       Else
  9501.          UP (-Z,ZP);
  9502.          RESULT := CMPLX(1.0E15,0.0);
  9503.          If XA < 50.0 Then
  9504.             RESULT := CMPLX(2.0,0.0)*CEXP(Z**2) - ZP;
  9505.          End If;
  9506.       End If;
  9507.       Return RESULT;
  9508. --
  9509.       End ECOM;
  9510. --
  9511. --
  9512.       Procedure GRWAVE (COND: in float;
  9513.                         FREQ: in float;
  9514.                         SURDIS: in float;
  9515.                         NPOL: in integer;
  9516.                         POWER: in float;
  9517.                         HLOWER: in float;
  9518.                         HHIGHR: in float;
  9519.                         VOLTPM: out float;
  9520.                         DBLOSS: out float) is
  9521. --
  9522. --#PURPOSE: GRWAVE calculates ground wave signal levels at HF.
  9523. --
  9524. --#AUTHOR:  J. Conrad
  9525. --
  9526. --#TYPE:    Numerical Analysis
  9527. --
  9528. --#PARAMETER DESCRIPTIONS:
  9529. --IN        COND   = Ground conductivity at transmitterin mho/m
  9530. --IN        FREQ   = Frequency in kHz
  9531. --IN        SURDIS = Great circle path surface distance in km
  9532. --IN        NPOL   = Polarization flag (1:=Vertical, 2:=Horizontal)
  9533. --IN        POWER  = Transmitter radiated power in kW
  9534. --IN        HLOWER = Height of the lower antenna in m
  9535. --IN        HHIGHR = Height of the higher antenna in m
  9536. --OUT       VOLTPM = Electric field intensity at the receiving
  9537. --                   location in the polarized direction in V/m
  9538. --OUT       DBLOSS = A relative loss factor in dB
  9539. --
  9540. --#CALLED BY:
  9541. --          HFGSIG
  9542. --          LFPROP
  9543. --
  9544. --#CALLS TO:
  9545. --          CWAIRY
  9546. --          ECOM
  9547. --          OMCOS
  9548. --          RGW
  9549. --          TW
  9550. --          ZEXP
  9551. --
  9552. --#TECHNICAL DESCRIPTION:
  9553. --          The essence of this routine has been extracted from:
  9554. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  9555. --          developed by Leslie A. Berry of the U.S. Department of
  9556. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  9557. --          Colorado.
  9558. --
  9559. --
  9560.       LAMBDA, DMIN, HTC, HRC, EPS, DELT, DMAX, ALFA, START, WAVE, V2, Z: float;
  9561.       TEST, FTEST, FTESTT, B, R, DEGTST, THETA, DEGTH, HT2, HR2, A1, A2: float;
  9562.       XA, D, D1, D2, CSQD, SD2, SD, S, SSQ, ASQ, SE, SSE, SA, DELANG: float;
  9563.       BOT, YONE, TOP, FTX, SGN, TX, XONE, F, FF, TY, DCHECK, AMP: float;
  9564.       PHASE, EJ, ER, DT: float;
  9565.       ILOS, IGAUSS, NN, NNN, MGW, KOUNT, N, MZ, MA, KK, I, K, MY1, M: integer;
  9566.       ISKIP, MY2, MT, FLG: integer; 
  9567.       ETA, DELTAX, RO, U, CZW, E, Z2, RR: complex;
  9568.       TS, ZZ, TZ, WY1, WY2, EEK, EAK, ECK, ZR, ZT, ZO: complex;
  9569.       M1: array (integer range 1..96) of integer;
  9570.       M2: array (integer range 1..96) of integer;
  9571.       MD1: array (integer range 1..96) of integer;
  9572.       MD2: array (integer range 1..96) of integer;
  9573.       MPT: array (integer range 1..96) of integer;
  9574.       PT: array (integer range 1..96) of complex;
  9575.       O: array (integer range 1..96) of complex;
  9576.       W1: array (integer range 1..96) of complex;
  9577.       W2: array (integer range 1..96) of complex;
  9578.       DW1: array (integer range 1..96) of complex;
  9579.       DW2: array (integer range 1..96) of complex;
  9580.       WX: array (integer range 1..96) of complex;
  9581.       WW1: array (integer range 1..96) of complex;
  9582.       WW2: array (integer range 1..96) of complex;
  9583. --
  9584.       Begin
  9585. --
  9586.       DMIN := SURDIS;
  9587.       If DMIN <= 1.0E-10 Then
  9588.          E := CMPLX(1.0, 0.0);
  9589.          New_Line;
  9590.          Put ("WARNING--In routine GRWAVE the surface distance is zero.");
  9591.          New_Line;
  9592.          Put ("The signal has been set to assure successful communications.");
  9593.          Goto MASTER_NODE;
  9594.       End If;
  9595. --
  9596.       HTC := HLOWER;
  9597.       HRC := HHIGHR;
  9598.       ILOS := 4;
  9599.       IGAUSS := 1;
  9600.       EPS := 10.0;
  9601.       If COND > 0.30 Then
  9602.          EPS := 80.0;
  9603.       End If;
  9604.       DELT := 0.0;
  9605.       DMAX := DMIN;
  9606.       ALFA := 1.33333333;
  9607. --
  9608. --     ALFA  = EFFECTIVE EARTH RADIUS FACTOR,
  9609. --           = EFFECTIVE RADIUS/ACTUAL RADIUS
  9610. --
  9611.       NN := 1;
  9612.       NNN := 1;
  9613.       START := DMIN;
  9614.       A := ALFA*RADIUS_OF_EARTH_IN_KM;
  9615.       LAMBDA := 2.997925E2/FREQ;
  9616. --
  9617. --     LAMBDA = WAVELENGTH IN KM FOR FREQ IN KHZ.
  9618. --
  9619.       WAVE := TWOPI/LAMBDA;
  9620. --
  9621. --     WAVE  = WAVE NUMBER IN RADIANS/KM.
  9622. --
  9623.       AK1 := A*WAVE;
  9624.       V := (AK1/2.0)**0.33333333;
  9625.       V2 := V*V;
  9626.       Z := 0.5/V2;
  9627.       ZC := 2.5*Z;
  9628.       FLF := 300.0*SQRT(POWER);
  9629.       ETA := CMPLX(EPS,-18.0E6*COND/FREQ);
  9630.       DELTAX := CXSQRT(ETA - 1.0);
  9631.       If NPOL /= 2 Then
  9632.          DELTAX:=DELTAX/ETA;
  9633.       End If;
  9634.       Q := CMPLX(0.0,-V)*DELTAX;
  9635.       MGW := 1;
  9636.       TEST := 0.0;
  9637.       DMIN := START;
  9638.       HTKM := HTC/1000.0;
  9639.       HRKM := HRC/1000.0;
  9640.       Y1 := WAVE*HTKM/V;
  9641.       Y2 := WAVE*HRKM/V;
  9642.       FTEST := AMAX1(5.0,437.0/(FREQ**0.38));
  9643.       FTESTT := FTEST*(POWER**0.5);
  9644.       If WAVE*(HTKM + HRKM)*CABS(DELTAX) > 0.1 Then
  9645.          FTEST := 0.0;
  9646.       End If;
  9647. --
  9648. --     FTEST IMPLIES FLAT EARTH O.K. TO 5 KM FOR ALL
  9649. --     FREQUENCIES, AND > 5 KM FOR FREQUENCIES <
  9650. --     128,599 KHZ (8.69KM AT 30MHZ; 20.85KM AT 3MHZ).
  9651. --
  9652.       If HTC + HRC > 0.0 Then
  9653.          B := A + HTKM;
  9654.          R := A + HRKM;
  9655.          TEST := A*(ACOS(A/R) + ACOS(A/B));
  9656.          DEGTST := DEGREES_PER_RADIAN*TEST/A;
  9657.       End If;
  9658.       THETA := DMIN/A;
  9659.       DEGTH := DEGREES_PER_RADIAN*THETA;
  9660.       X := V*THETA;
  9661.       STH := SIN(THETA);
  9662.       COTH := COS(THETA)/STH;
  9663.       E := CMPLX(0.0,0.0);
  9664.       If DMIN <= FTEST Then
  9665.          Goto FLAT_EARTH;
  9666.       Elsif DMIN > TEST Then
  9667.          Goto RESIDUE_SERIES;
  9668.       Else
  9669.          Goto GEOMETRIC_OPTICS;
  9670.       End If;
  9671. --
  9672. --     IF DMIN > TEST, THE TRANSMITTER AND RECEIVER
  9673. --     ARE BEYOND LINE-OF-SIGHT BASED ON A SPHERICAL
  9674. --     EARTH OF ALFA*REARTH RADIUS, I.0E. A RADIUS
  9675. --     ADJUSTED FOR NORMAL ATMOSPHERIC REFRACTION IN
  9676. --     THE TROPOSPHERE.
  9677. --
  9678. <<FLAT_EARTH>>
  9679. --     CALCULATION OF THE GROUND WAVE WITH A FLAT EARTH.
  9680. --
  9681.       R := SQRT(DMIN*DMIN*1.0E6 + (HTC - HRC)**2);
  9682.       RO := CMPLX(0.886227, 0.886227)*SQRT(WAVE*R*1.0E-3);
  9683.       U := R*DELTAX*(1.0 + (HTC + HRC)/(DELTAX*R));
  9684.       CZW := U*CMPLX(0.5, 0.5)*SQRT(WAVE/(R*1.0E-3))*0.001;
  9685.       E := (1.0 - RO*DELTAX*ECOM(CZW))*FLF/(1000.0*DMIN);
  9686.       Goto MASTER_NODE;
  9687. --
  9688. <<GEOMETRIC_OPTICS>>
  9689. --     CALCULATION OF THE GROUND WAVE WITH GEOMETRIC OPTICS.
  9690. --
  9691.       HT2 := HTKM*HTKM;
  9692.       HR2 := HRKM*HRKM;
  9693.       A1 := 2.0*A*HTKM + HT2;
  9694.       A2 := 2.0*A*HRKM + HR2;
  9695.       XA := OMCOS(THETA);
  9696.       D := SQRT((2.0*A*A + 2.0*A*(HTKM + HRKM))*XA + HT2 + HR2 - 2.0
  9697.            *HTKM*HRKM*COS(THETA));
  9698. --
  9699.       If HTC = 0.0 Then
  9700.          D1 := 0.0;
  9701.  
  9702.          CSQD := (((A + HRKM)*SIN(THETA))/D)**2.0;
  9703.          SD2 := 1.0 - CSQD;
  9704.          If ABS(SD2) < 0.0001 Then
  9705.             SD2:= 0.0001;
  9706.          End If;
  9707.          SD := SQRT(SD2);
  9708.          Goto G1090;
  9709.       End If;
  9710. --
  9711.       KOUNT := 1;
  9712.       S := 1.0/SQRT(1.0 + (DMIN/(HTKM + HRKM))**2);
  9713.       SSQ := S*S;
  9714.       ASQ := A*A;
  9715.       D1 := SQRT(ASQ*SSQ + A1) - A*S;
  9716.       D2 := SQRT(ASQ*SSQ + A2) - A*S;
  9717.       SE := (D1 + D2)**2 - 4.0*D1*D2*SSQ - D*D;
  9718.       SD := S + SIGN(0.01,SE);
  9719.       SD2 := SD*SD;
  9720. <<G1080>>
  9721.       D1 := SQRT(ASQ*SD2 + A1) - A*SD;
  9722.       D2 := SQRT(ASQ*SD2 + A2) - A*SD;
  9723.       SSE := (D1 + D2)**2 - 4.0*D1*D2*SD2 - D*D;
  9724.       KOUNT := KOUNT + 1;
  9725.       If KOUNT > 20 Then
  9726.          Goto G1090;
  9727.       End If;
  9728.       XA := SSE - SE;
  9729.       If ABS(XA) < 1.0E-10 Then
  9730.          XA := 1.0E-10*SIGN(1.0,XA);
  9731.       End If;
  9732.       SA := SD + (S - SD)*SSE/XA;
  9733.       S := SD;
  9734.       SSQ := S*S;
  9735.       SE := SSE;
  9736.       SD := SA;
  9737.       SD2 := SD*SD;
  9738.       If ABS(SSE) >= 0.1*LAMBDA Then
  9739.          Goto G1080;
  9740.       End If;
  9741.       CSQD := 1.0 - SD2;
  9742. --
  9743. <<G1090>>
  9744.       DELANG := ASIN(SD);
  9745.       DELANG := DEGREES_PER_RADIAN*DELANG;
  9746. --
  9747. -- *** NEAR THE HORIZON (SMALL SD) USE NUMERICAL INTEGRATION.
  9748. --
  9749.       If IGAUSS = 0 or SD >= 2.0/V Then
  9750.          Z2 := CXSQRT(ETA-CSQD);
  9751.          If NPOL = 1 Then
  9752.             Z2 := Z2/ETA;
  9753.          End If;
  9754.          RR := (SD - Z2)/(SD + Z2);
  9755.          DT := 4.0*D1*D2*SD2/(D1 + D2 + D);
  9756.          E := FLF*CEXP(CMPLX(0.0,-WAVE*(D-DMIN)))/(2000.0*D)*(1.0 +
  9757.               RR*CEXP(CMPLX(0.0,-WAVE*DT)));
  9758.          Goto MASTER_NODE;
  9759.       End If;
  9760. --
  9761. --     CALCULATION OF THE GROUND WAVE WITH GAUSSIAN NUMERICAL INTEGRATION
  9762. --
  9763.       N := 0;
  9764.       TW (N,Q,TZ,EEK,MZ,EAK,MA,ECK,MZ,ECK,MZ);
  9765.       BOT := 0.5*AIMAG(TZ);
  9766.       YONE := BOT;
  9767.       XONE := AREAL(TZ);
  9768.       TOP := -AMIN1(6.0/X,100.0);
  9769.       TOP := AMIN1(TOP,-SQRT(Y1)-SQRT(Y2));
  9770.       FTX := 0.5*(TOP - BOT);
  9771.       KK := 0;
  9772.       SGN := 1.0;
  9773. --
  9774. -- *** COMPUTE INTEGRAND FACTOR THAT IS INDEPENDENT OF DISTANCE.
  9775. --
  9776.       For I in 1..2 Loop
  9777.          SGN := -SGN;
  9778.          For K in 1..48 Loop
  9779.             KK := KK + 1;
  9780.             TX := ((TOP - BOT)*G(K) + TOP + BOT)*0.5;
  9781.             O(KK) := CMPLX(XONE + SGN*(TX - YONE),TX);
  9782.          End Loop;
  9783.       End Loop;
  9784. --
  9785.       For K in 1..96 Loop
  9786.          If ABS(AREAL(O(K)) - Y2) > 5.0 and Y1 > 0.0 and CABS(O(K)) > 5.0 Then
  9787.             Goto G1140;
  9788.          End If;
  9789.          CWAIRY(1,O(K),W1(K),M1(K),W2(K),M2(K));
  9790.          CWAIRY(2,O(K),DW1(K),MD1(K),DW2(K),MD2(K));
  9791.          F := 2.7182818**(MD1(K) - M1(K));
  9792.          WX(K) := F*DW1(K)/W1(K) - Q;
  9793.          CWAIRY(1,O(K) - Y2,WY1,MY1,EEK,M);
  9794.          MPT(K) := MY1 - M1(K);
  9795.          PT(K) := WY1/W1(K)/WX(K);
  9796.          If Y1 <= 0.0 Then
  9797.             Goto G1160;
  9798.          End If;
  9799.          WW1(K) := 2.7182818**(MD1(K) - M1(K))*DW1(K) - W1(K)*Q;
  9800.          WW2(K) := 2.7182818**(MD2(K) - M2(K))*DW2(K) - W2(K)*Q;
  9801.          CWAIRY(1,O(K) - Y1,WY1,MY1,WY2,MY2);
  9802.          F := 2.7182818**(MY1 + M2(K));
  9803.          FF := 2.7182818**(MY2 + M1(K));
  9804.          PT(K) := CMPLX(0.0,-0.5)*(FF*WY2*WW1(K) - F*WY1*WW2(K))*PT(K);
  9805.          Goto G1160;
  9806. --
  9807. <<G1140>>
  9808.          MPT(K) := 0;
  9809.          If K > 48 Then
  9810.             Goto G1150;
  9811.          End If;
  9812.          TS := CXSQRT(O(K));
  9813.          ZO := 0.66666666* O(K)*TS;
  9814.          ZR := CXSQRT(O(K) - Y2);
  9815.          ZT := CXSQRT(O(K) - Y1);
  9816.          ZZ := CXSQRT(ZR*ZT);
  9817.          ZR := 0.66666666*ZR*(O(K) - Y2);
  9818.          ZT := 0.66666666*ZT*(O(K) - Y1);
  9819. --
  9820. --SEE IF EXPONENTIAL HAS EXCEEDED MACHINE LIMITS
  9821.          FLG:=0;
  9822.          If CABS(ZR-ZT) >= 88.0 or CABS(2.0*ZT-ZO) >= 88.0 Then
  9823.             E := CMPLX(1.0E-11,0.0);
  9824.             FLG:=1;
  9825.             EXIT;
  9826.          End If;
  9827.          PT(K) := 0.5*CEXP(ZR-ZT)*(1.0+CEXP(2.0*(ZT-ZO))*(TS+Q)/(TS-Q))/ZZ;
  9828.          Goto G1160;
  9829. --
  9830. <<G1150>>
  9831.          TS := CXSQRT(-O(K));
  9832.          ZO := -0.66666666*O(K)*TS;
  9833.          ZR := CXSQRT(Y2 - O(K));
  9834.          ZT := CXSQRT(Y1 - O(K));
  9835.          ZZ := CXSQRT(ZR*ZT);
  9836.          ZR := 0.66666666*ZR*(Y2 - O(K));
  9837.          ZT := 0.66666666*ZT*(Y1 - O(K));
  9838.          PT(K) := 0.5*CEXP(CMPLX(0.0,-1.0)*(ZR - ZT))*
  9839.                   (1.0 + CEXP(CMPLX(0.0,-2.0)*
  9840.                   (ZT - ZO))*(CMPLX(0.0,1.0)*TS + Q)/(CMPLX(0.0,1.0)*TS - Q))/
  9841.                   (CMPLX(0.0,1.0)*ZZ);
  9842. <<G1160>>
  9843.          Null;
  9844.       End Loop;
  9845.       if FLG=1 then Goto MASTER_NODE; end if;
  9846.       NN := 3;
  9847.       KK := 0;
  9848.       SGN := 1.0;
  9849. --
  9850. -- *** INTEGRATE FOR THIS DISTANCE.
  9851. --
  9852.       For I in 1..2 Loop
  9853.          SGN := -SGN;
  9854.          For K in 1..48 Loop
  9855.             KK := KK + 1;
  9856.             ZEXP(X*AIMAG(O(KK)),-X*AREAL(O(KK)),TX,TY,MT);
  9857.             F := 2.718282**(MT + MPT(KK));
  9858.             E := E + W(K)*FTX*F*CMPLX(TX,TY)*CMPLX(1.0,SGN)*PT(KK);
  9859.          End Loop;
  9860.       End Loop;
  9861.       E := FLF*SQRT(V/(6.0*STH))/(2000.0*A)*E*CMPLX(-1.0,-1.0);
  9862.       Goto MASTER_NODE;
  9863. --
  9864. <<RESIDUE_SERIES>>
  9865. --
  9866. --     CALCULATION OF THE GROUND WAVE WITH THE FOK-WAIT
  9867. --     RESIDUE SERIES.
  9868. --
  9869.       E:=CMPLX(1.0E-11,0.0);
  9870. --
  9871. --     LOOP AROUND RGW BASED ON LINE-OF-SIGHT DISTANCE,
  9872. --     INPUT VARIABLE ILOS, AND MINIMUM DISTANCE VARIABLE FTESTT.
  9873. --
  9874.       If ILOS = 1 Then
  9875.          Goto G1200;
  9876.       End If;
  9877.       DCHECK := FLOAT(ILOS - 1)*TEST;
  9878.       DCHECK := AMAX1(DCHECK,20.0*FTESTT);
  9879.       If COND > 0.30 Then
  9880.          DCHECK := AMAX1(DCHECK,100.0*FTESTT);
  9881.       End If;
  9882. --
  9883. --     THIS MEANS THAT EVEN IF BOTH ANTENNAS ARE AT GROUND, CALCULATIONS
  9884. --     WILL BE PERFORMED TO AT LEAST 417 KM FOR 3 MHZ, AND 173.8 KM
  9885. --     FOR 30 MHZ OVER LAND, AND 5 TIMES THESE DISTANCES OVER SEA.
  9886. --
  9887.       If DMIN > DCHECK Then
  9888.          Goto MASTER_NODE;
  9889.       End If;
  9890. --
  9891. <<G1200>>
  9892.       E := RGW(MGW);
  9893. --
  9894. --     MASTER NODE AFTER E HAS BEEN CALCULATED.
  9895. --
  9896. <<MASTER_NODE>>
  9897.       AMP := CABS(E);
  9898.       AMP := AMAX1(1.0E-10,AMP);
  9899.       AMP := AMIN1(AMP,1.0E10);
  9900.       ISKIP := 0;
  9901.       If AMP > 0.999E10 or AMP < 1.0001E-10 Then
  9902.          ISKIP := 1;
  9903.       End If;
  9904.       PHASE := 0.0;
  9905.       If ISKIP /= 1 Then
  9906.          EJ := AIMAG(E);
  9907.          ER := AREAL(E);
  9908.          If EJ > 0.0 Then
  9909.             PHASE := HALFPI;
  9910.          End If;
  9911.          If EJ < 0.0 Then
  9912.             PHASE := PI + HALFPI;
  9913.          End If;
  9914.          If ER > 0.0001 Then
  9915.             PHASE := ATAN(EJ/ER);
  9916.          End If;
  9917.       End If;
  9918. --
  9919. --     CALCULATE DB LOSS AND SIGNAL STRENGTH IN VOLTS/METER
  9920. --
  9921.       VOLTPM := AMP;
  9922.       DBLOSS := 400.0;
  9923.       If AMP > 0.9999E10 Then
  9924.          DBLOSS := 0.0;
  9925.       End If;
  9926.       If ISKIP /= 1 Then
  9927.          DBLOSS := 10.0*LOG10(POWER*(FREQ/AMP)**2) + 22.45;
  9928.       End If;
  9929.       Return;
  9930. --
  9931.       End GRWAVE;
  9932. --
  9933. --
  9934.       Function OMCOS (X: float) return float is
  9935. --
  9936. --#PURPOSE: OMCOS calculates ( l.0 - cos (x)) for very small x.
  9937. --
  9938. --#AUTHOR:  J. Conrad
  9939. --
  9940. --#TYPE:    Numerical Analysis
  9941. --
  9942. --#PARAMETER DESCRIPTIONS:
  9943. --IN        X      = Argument
  9944. --OUT       OMCOS  = 1. - cos (x)
  9945. --
  9946. --#CALLED BY:
  9947. --          GRWAVE
  9948. --
  9949. --#CALLS TO:
  9950. --          'NONE'
  9951. --
  9952. --#TECHNICAL DESCRIPTION:
  9953. --          OMCOS calculates (l.0 - cos (x)) for very small x by
  9954. --          using the sum of Taylor series.
  9955. --
  9956.       S, T, R, RESULT: float;
  9957. --
  9958.       Begin
  9959. --
  9960.       If ABS(X) > 0.15 Then
  9961.          Return 1.0 - COS(X);
  9962.       Elsif X = 0.0 Then
  9963.          Return 0.0;
  9964.       Else
  9965.          S := X*X;
  9966.          T := 0.5*S;
  9967.          RESULT := T;
  9968.          R := 4.0;
  9969.          Loop
  9970.             T := -T*S/(R*(R - 1.0));
  9971.             RESULT := RESULT + T;
  9972.             Exit When ABS(T/RESULT) <= 0.5E-9;
  9973.             R := R + 2.0;
  9974.          End Loop;
  9975.          Return RESULT;
  9976.       End If;
  9977. --
  9978.       End OMCOS;
  9979. --
  9980. --
  9981.       Function RGW (MMM: in integer) return complex is
  9982. --
  9983. --#PURPOSE: RGW calculates the values of a residue series used for
  9984. --          ground wave signal level determination at HF.
  9985. --
  9986. --#AUTHOR:  J. Conrad
  9987. --
  9988. --#TYPE:    Numerical Analysis
  9989. --
  9990. --#PARAMETER DESCRIPTIONS:
  9991. --IN        MMM     = Flag indicating a new case (MM=1) of that
  9992. --                   only the distance has been changed from the
  9993. --                   last case (MM=2)
  9994. --OUT       RGW    = Ground wave signal strength in V/M
  9995. --
  9996. --#CALLED BY:
  9997. --          GRWAVE
  9998. --
  9999. --#CALLS TO:
  10000. --          CWAIRY
  10001. --          TW
  10002. --
  10003. --#TECHNICAL DESCRIPTION:
  10004. --          The essence of this routine has been extracted from:
  10005. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  10006. --          developed by Leslie A. Berry of the U.S. Department of
  10007. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  10008. --          Colorado.
  10009. --
  10010.       G, GW, CZERO, ARG, RATIO, W1, DW1, S, WY1, WY2: complex;
  10011.       T: array (integer range 1..200) of complex;
  10012.       W: array (integer range 1..200) of complex;
  10013.       J1, J2, J, MW1, MD1, M, MY1, MY2: integer; 
  10014.       MM: integer := MMM;
  10015. --
  10016.       Begin
  10017. --
  10018.       CZERO := CMPLX(0.0, 0.0);
  10019.       GW := CMPLX(0.0, 0.0);
  10020.       If MM = 2 Then
  10021.          Goto R1070;
  10022.       End If;
  10023.       J2 := 1;
  10024.       MM := 2;
  10025. --
  10026. <<R1010>>
  10027.       For J in J2..200 Loop
  10028.          TW (J-1 , Q, T(J), W1, MW1, DW1, MD1, S,M,S,M);
  10029.          If HTKM > 0.0 Then
  10030.            Goto R1030;
  10031.          Elsif HRKM > 0.0 Then
  10032.            Goto R1020;
  10033.          End If;
  10034.          W(J) := CMPLX(1.0,0.0);
  10035.          Goto R1040;
  10036. --
  10037. -- *** COMPUTE HEIGHT GAIN FACTORS
  10038. --
  10039. <<R1020>>
  10040.          CWAIRY(1,T(J)-Y2,WY2,MY2,S,M);
  10041.          W(J) := 2.7182818**(MY2-MW1)*WY2/W1;
  10042.          Goto R1040;
  10043. --
  10044. <<R1030>>
  10045.          CWAIRY(1,T(J)-Y1,WY1,MY1,S,M);
  10046.          W(J) := 2.7182818**(MY1-MW1)*WY1/W1;
  10047.          If HRKM <= 0.0 Then
  10048.             Goto R1040;
  10049.          End If;
  10050.          CWAIRY(1,T(J)-Y2,WY2,MY2,S,M);
  10051.          S := 2.7182818**(MY2-MW1)*WY2/W1;
  10052.          W(J) := W(J)*S;
  10053. --
  10054. <<R1040>>
  10055.          W(J) := W(J)/(T(J)-Q*Q);
  10056. --
  10057. -- *** W(J) IS THE COEFFICIENT OF THE DISTANCE FACTOR FOR
  10058. --     THE J-TH TERM.
  10059. --
  10060.          ARG := CMPLX(0.0,-1.0)*X*T(J);
  10061.          If AREAL(ARG) >= -69.0 Then
  10062.             G:=W(J)*CEXP(ARG);
  10063.          Else
  10064.             G := CMPLX(0.0,0.0);
  10065.          End If;
  10066.          GW := GW + G;
  10067.          If J = 1 Then
  10068.             Goto R1050;
  10069.          End If;
  10070.          If AREAL(GW) = AREAL(CZERO) and AIMAG(GW) = AIMAG(CZERO) Then
  10071.             Goto R1050;
  10072.          End If;
  10073.          RATIO := G/GW;
  10074.          If CABS(RATIO)  > 0.0005 Then
  10075.             Goto R1050;
  10076.          End If;
  10077.          J1 := J;
  10078.          Exit;
  10079. <<R1050>>
  10080.          Null;
  10081.       End Loop;
  10082. --
  10083.       if J1<200 and J1>J2 then
  10084.          J2:=J1;
  10085.       else
  10086.          J2 := 200;
  10087.       end if;
  10088.       Goto R1090;
  10089. --
  10090. -- *** SUM THE RESIDUE SERIES FOR THIS DISTANCE.
  10091. --
  10092. <<R1070>>
  10093.       For J in 1..J2 Loop
  10094.          G := W(J)*CEXP(CMPLX(0.0,-1.0)*X*T(J));
  10095.          GW := GW + G;
  10096.          If J = 1 Then
  10097.             Goto R1080;
  10098.          End If;
  10099.          If AREAL(GW) = AREAL(CZERO) and AIMAG(GW) = AIMAG(CZERO) Then
  10100.             Goto R1080;
  10101.          End If;
  10102.          RATIO := G/GW;
  10103.          If CABS(RATIO)  < 0.0005 Then
  10104.             Exit;
  10105.          End If;
  10106. <<R1080>>
  10107.          Null;
  10108.       End Loop;
  10109. --
  10110.       If J2 >= 200 or CABS(RATIO)  < 0.0005 then
  10111.          Goto R1090;
  10112.       End If;
  10113.       J2 := J2 + 1;
  10114.       Goto R1010;
  10115. --
  10116. <<R1090>>
  10117.       Return GW*(FLF*PI*1.0E-3*SQRT(V/(6.0*STH))/A)*CMPLX(1.0,-1.0);
  10118. --
  10119.       End RGW;
  10120. --
  10121. --
  10122.       Procedure TW (I: in integer;
  10123.                     Q: in complex;
  10124.                     T: out complex;
  10125.                     W1: out complex;
  10126.                     MW1: out integer;
  10127.                     DW1: out complex;
  10128.                     MD1: out integer;
  10129.                     W2: out complex;
  10130.                     MW2: out integer;
  10131.                     DW2: out complex;
  10132.                     MD2: out integer) is
  10133. --
  10134. --#PURPOSE: TW calculates the roots of Airy function equations.
  10135. --
  10136. --#AUTHOR:  J. Conrad
  10137. --
  10138. --#TYPE:    Numerical Analysis
  10139. --
  10140. --#PARAMETER DESCRIPTIONS:
  10141. --IN        I      = The root of interest
  10142. --IN        Q      = A coefficient in the equation
  10143. --OUT       T      = The I-th root
  10144. --OUT       W1     = Airy function root
  10145. --OUT       MW1    = Airy function root
  10146. --OUT       DW1    = Airy function root
  10147. --OUT       MD1    = Airy function root
  10148. --OUT       W2     = Airy function root
  10149. --OUT       MW2    = Airy function root
  10150. --OUT       DW2    = Airy function root
  10151. --OUT       MD2    = Airy function root
  10152. --
  10153. --#CALLED BY:
  10154. --          GRWAVE,
  10155. --          RGW
  10156. --
  10157. --#CALLS TO:
  10158. --          CWAIRY
  10159. --
  10160. --
  10161. --#TECHNICAL DESCRIPTION:
  10162. --          The essence of this routine has been extracted from:
  10163. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  10164. --          developed by Leslie A. Berry of the U.S. Department of
  10165. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  10166. --          Colorado.
  10167. --
  10168.       A: complex;
  10169.       PH: complex := CMPLX(0.5, -0.8660254);
  10170. --
  10171. --      W-SUB-ONE-PRIME(TZERO(I)) := 0.0
  10172.       TZERO: array (integer range 1..11) of float :=
  10173.          (1.018793, 3.2481975, 4.8200992, 6.1633074, 7.3721773, 8.4884868,
  10174.           9.5354490, 10.52766, 11.475057, 12.384788, 13.262219);
  10175. --
  10176. --      W-SUB-ONE(TINFIN(I)) := 0.0
  10177.       TINFIN: array (integer range 1..11) of float :=
  10178.          (2.3380997, 4.0879494, 5.5205598, 6.7867081, 7.9441336, 9.0226508, 
  10179.           10.040174, 11.008524, 11.936016, 12.828777, 13.691489);
  10180.       CON: float := 1.17809724;
  10181.       YS, TZ: float;
  10182.       K: integer;
  10183. --
  10184.       Begin
  10185. --
  10186.       If AREAL(Q)**2 + AIMAG(Q)**2 > 1.0 Then
  10187.          Goto T1020;
  10188.       Elsif I > 10 Then
  10189.          Goto T1000;
  10190.       End If;
  10191.       TZ := TZERO(I+1);
  10192.       Goto T1010;
  10193. --
  10194. <<T1000>>
  10195.       YS := (float(4*I + 1)*CON)**2;
  10196.       TZ := YS** 0.33333333*(1.0 - 0.1458333/YS);
  10197. --
  10198. <<T1010>>
  10199.       T := TZ*PH;
  10200. --
  10201. --     T IS NOW SOLUTION FOR Q :=0.0  THE NEXT STEP IS THE FIRST NEWTON
  10202. --     ITERATION.
  10203. --
  10204.       T := T + Q/T;
  10205.       Goto T1050;
  10206. --
  10207. <<T1020>>
  10208.       If I > 10 Then
  10209.          Goto T1030;
  10210.       End If;
  10211.       TZ := TINFIN(I+1);
  10212.       Goto T1040;
  10213. --
  10214. <<T1030>>
  10215.       YS := (float(4*I + 3)*CON)**2;
  10216.       TZ := YS** 0.33333333*(1.0 + 0.1041667/YS);
  10217. --
  10218. <<T1040>> 
  10219.       T := TZ*PH;
  10220. --
  10221. --  T IS SOLUTION FOR Q:=INFINITY.  NEXT STEP IS THE FIRST NEWTON
  10222. --     ITERATION.
  10223. --
  10224.       T := T + 1.0/Q;
  10225. --
  10226. <<T1050>> 
  10227.       K := 0;
  10228. --
  10229. --      NOW, USE NEWTONS ITERATION TO CONVERGE ON SOLUTION
  10230. --        CWAIRY COMPUTES  W(T) AND W PRIME (T)
  10231. --
  10232. <<T1060>>
  10233.       CWAIRY (1,T,W1,MW1,W2, MW2);
  10234.       CWAIRY (2,T,DW1,MD1,DW2,MD2);
  10235.       A := (2.71828182**(MD1 - MW1))*DW1/W1;
  10236.       A := (A - Q)/(T - A*Q);
  10237.       T := T - A;
  10238.       K := K + 1;
  10239.       If K > 30 Then
  10240.          Goto T1070;
  10241.       Elsif CABS(A/T) > 0.5E-6 Then
  10242.          Goto T1060;
  10243.       Else
  10244.          Return;
  10245.       End If;
  10246. --
  10247. <<T1070>>
  10248.       New_Line;
  10249.       Put ("Convergence failed in Procedure TW.");
  10250.       Return;
  10251. --
  10252.       End TW;
  10253. --
  10254. --
  10255.       Procedure UP (A: in complex;
  10256.                     E: out complex) is
  10257. --
  10258. --#PURPOSE: UP calculates the value of a complementary error
  10259. --          function by a power series summation.
  10260. --
  10261. --#AUTHOR:  J. Conrad
  10262. --
  10263. --#TYPE:    Numerical Analysis
  10264. --
  10265. --#PARAMETER DESCRIPTIONS:
  10266. --IN        A      = The complex argument
  10267. --OUT       E      = CEXP (A**2) *ERFC(A)
  10268. --
  10269. --#CALLED BY:
  10270. --          DOWN
  10271. --          ECOM
  10272. --
  10273. --#CALLS TO:
  10274. --          DOWN
  10275. --
  10276. --#TECHNICAL DESCRIPTION:
  10277. --          The essence of this routine has been extracted from:
  10278. --          GW SNR (Ground Wave Signal-to-Noise Ratio) a FORTRAN code
  10279. --          developed by Leslie A. Berry of the U.S. Department of
  10280. --          Commerce, Institute for Telecommunication Sciences, Bolder,
  10281. --          Colorado.
  10282. --
  10283.       Z, EP, Z2, GN: complex;
  10284.       ZB2, EN: float;
  10285. --
  10286.       Begin
  10287. --
  10288.       Z := A;
  10289.       If CABS(Z) - 3.5 <= 0.0 Then
  10290.          DOWN (Z,EP);
  10291.          E := CEXP(Z**2) - EP;
  10292.          Return;
  10293.       End If;
  10294.       Z2 := -Z*Z;
  10295.       ZB2 := CABS(Z2);
  10296.       GN := CMPLX(0.56418958,0.0)/Z;
  10297.       EP := GN;
  10298.       EN := 0.5;
  10299. --
  10300. <<D1020>>
  10301.       GN := EN*GN/Z2;
  10302.       EP := EP + GN;
  10303.       If CABS(GN/EP) - 1.0E-05 <= 0.0 Then
  10304.          Goto D1040;
  10305.       End If;
  10306. --
  10307. <<D1030>>
  10308.       EN := EN + 1.0;
  10309.       If EN - ZB2 < 0.0 Then
  10310.          Goto D1020;
  10311.       End If;
  10312. --
  10313. <<D1040>> 
  10314.       E := EP;
  10315.       Return;
  10316. --
  10317.       End UP;
  10318. --
  10319. --
  10320. --
  10321. --
  10322. End LF_HF_GROUNDWAVES;
  10323. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10324. --VHFUHFSH
  10325. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10326. With Debugger2; Use Debugger2;
  10327. With Constants; Use Constants;
  10328. With Propagation_Constants; Use Propagation_constants;
  10329. With Mathlib; Use Mathlib, Core_functions;
  10330. With RFUtil;
  10331.  
  10332. Package VHF_UHF_SHF_EHF_PROPAGATION is
  10333. --
  10334.       Procedure VHF_UHF_SHF_EHF_HANDLER;
  10335. --
  10336. End VHF_UHF_SHF_EHF_PROPAGATION;
  10337. --
  10338. Package body VHF_UHF_SHF_EHF_PROPAGATION is
  10339. --
  10340. -- VHF_UHF_SHF_EHF_PROPAGATION Package of PROP_LINK 
  10341. -- Version 1.0,  July 2, 1985.
  10342. --
  10343. -- This VHF_UHF_SHF_EHF_PROPAGATION Package contains all of the procedures
  10344. -- that are used to perform VHF_UHF_SHF_EHF propagation prediction.
  10345. --
  10346. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  10347. -- radio frequency propagation prediction code.
  10348. --
  10349. -- PROP_LINK has been developed for the Department of Defense under
  10350. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  10351. -- Systems Inc. (Jim Conrad).
  10352. --
  10353.       Pragma Source_info (on);
  10354. --
  10355.       Procedure VHF_UHF_SHF_EHF_HANDLER is
  10356. --
  10357. --#PURPOSE: VHF_UHF_SHF_EHF_HANDLER computes the signal strength at a receiver 
  10358. --          location for HF links.
  10359. --
  10360. --#AUTHOR:  J. Conrad
  10361. --
  10362. --#TYPE:    Numerical Analysis
  10363. --
  10364. --#PARAMETER DESCRIPTIONS:
  10365. --IN        TALT   = Transmitter altitude in kilometers
  10366. --IN        RALT   = Receiver altitude in kilometers
  10367. --IN        DPATH  = Creat circle path length between transmitter & receiver
  10368. --                   in km
  10369. --IN        BRNG2  = Bearing from receiver to transmitter in degrees
  10370. --IN        FREQMC = Frequency in MHz
  10371. --IN        TERP   = Transmitter power in dBW
  10372. --IN        RLL    = Receiver line loss in dB
  10373. --OUT       SIGNAL = Signal strength at receiver in dBW
  10374. --
  10375. --#CALLED BY:
  10376. --          RF_PROPAGATION_HANDLER
  10377. --
  10378. --#CALLS TO:
  10379. --          AOW
  10380. --          COORDX
  10381. --
  10382. --#TECHNICAL DESCRIPTION:
  10383. --     VHF_UHF_SHF_EHF_HANDLER is the RF propagation prediction routine 
  10384. --     VHF/UHF/SHF/EHF electromagnetic waves. 
  10385. --
  10386.       ATMOS2: constant float:= 60.0;
  10387.       AW0, ELEV, FSL: float;
  10388.       R, AZSATD, H, XR, YR, ZR, SRSATJ, ELSATD: float;
  10389. --
  10390.       Begin
  10391. --
  10392. --COMPUTE AMBIENT SIGNAL STRENGTH AT RECEIVER EXCLUSIVE OF ANTENNA GAIN
  10393. --  WHICH IS ADDED IN Procedure NOISY AS PART OF G/T.
  10394.       AW0 := 0.0;
  10395.       RFUTIL.COORDX (RALT, 1, DPATH, BRNG2, TALT, R, AZSATD, H,
  10396.               XR, YR, ZR, SRSATJ, ELSATD);
  10397.       If RALT <= ATMOS2 or TALT <= ATMOS2 Then
  10398.          ELEV := ABS(ELSATD)*RADIANS_PER_DEGREE;
  10399.          AW0 := RFUTIL.AOW (FREQMC, ELEV);
  10400.       End If;
  10401.       FSL := 0.0;
  10402.       SRSATJ := ABS(SRSATJ);
  10403.       If SRSATJ /= 0.0 Then
  10404.          FSL := 32.5 + 20.0*LOG10(FREQMC) + 20.0*LOG10(SRSATJ);
  10405.       End If;
  10406.       SIGNAL := TERP - FSL - AW0 - RLL;
  10407. --
  10408.       Return;
  10409. --
  10410.       End VHF_UHF_SHF_EHF_HANDLER;
  10411. --
  10412. --
  10413. End VHF_UHF_SHF_EHF_PROPAGATION;
  10414. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10415. --MFHFPROP
  10416. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  10417. With Debugger2; Use Debugger2;
  10418. With Text_IO; Use Text_io, integer_io, float_io;
  10419. With Constants; Use Constants;
  10420. With Propagation_constants; Use Propagation_constants;
  10421. With Mathlib; Use Mathlib, numeric_primitives, core_functions, trig_functions;
  10422. With Complex_numbers; Use Complex_numbers;
  10423. With RFUtil;
  10424. With Nodeloc;
  10425. With Hf_atmospherics;
  10426. With Elf_Lf_Hf_atmospherics;
  10427. With Lf_Hf_Groundwaves;
  10428.  
  10429. Package MF_HF_PROPAGATION is
  10430. --
  10431.       Procedure MF_HF_HANDLER;
  10432. --
  10433. End MF_HF_PROPAGATION;
  10434. --
  10435. Package body MF_HF_PROPAGATION is
  10436. --
  10437. -- MF_HF_PROPAGATION Package of PROP_LINK 
  10438. -- Version 1.0,  July 2, 1985.
  10439. --
  10440. -- This MF_HF_PROPAGATION Package contains all of the procedures that 
  10441. -- are used to perform MF_HF propagation prediction.
  10442. --
  10443. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  10444. -- radio frequency propagation prediction code.
  10445. --
  10446. -- PROP_LINK has been developed for the Department of Defense under
  10447. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  10448. -- Systems Inc. (Jim Conrad).
  10449. --
  10450. -- Use Text_IO;
  10451. -- Instantiate integer and floating point IO.
  10452. --     Package IO_INTEGER is new INTEGER_IO(INTEGER);
  10453. --     Package IO_FLOAT is new FLOAT_IO(FLOAT);
  10454. --Use IO_INTEGER,IO_FLOAT;
  10455. --
  10456.    Pragma Source_info (on);
  10457. --
  10458.       EFDATA: array (integer range 1..5, 
  10459.                      integer range 1..6, 
  10460.                      integer range 1..6) of float;
  10461.       NSUCC: array (integer range 1..20) of integer;
  10462.       SECACP: array (integer range 1..20) of float;
  10463.       ACPLAT: array (integer range 1..140) of float;
  10464.       ACPLON: array (integer range 1..140) of float;
  10465.       ACPABS: array (integer range 1..140) of float;
  10466.       SPLOSS, RELOSS, GT, GR, PL, GRSIG, CHI, AMBAB: float;
  10467.       GTANT: array (integer range 1..21) of float;
  10468.       GRANT: array (integer range 1..21) of float;
  10469.       SIGPWR: array (integer range 1..20) of float;
  10470.       PLOSS: array (integer range 1..20) of float;
  10471.       PLNA: array (integer range 1..20) of float;
  10472.       FMX: array (integer range 1..20) of float;
  10473.       FMN: array (integer range 1..20) of float;
  10474.       ALOS: array (integer range 1..20) of float;
  10475.       SPLHF: array (integer range 1..20) of float;
  10476.       RELHF: array (integer range 1..20) of float;
  10477. --**************************************************************************
  10478. --
  10479.       Function FPSI (HANGLE: float; CONST: float) return float is
  10480. --
  10481. --FPSI IS THE RADIATION ANGLE DETERMINED FROM THE HALF CENTRAL ANGLE AND 
  10482. --A CONSTANT.
  10483. --
  10484.       Begin
  10485. --
  10486.       Return ATAN((COS(HANGLE)-CONST)/(AMAX1(1.0E-10, SIN(HANGLE))));
  10487. --
  10488.       End FPSI;
  10489. --
  10490. --
  10491.       Function FAVG (A: float; B: float) return float is
  10492. --
  10493.       Begin
  10494. --
  10495.       Return (A + B)*0.5;
  10496. --
  10497.       End FAVG;
  10498. --
  10499. --
  10500.       Function FRANG (HEIGHT: float; HANG: float) return float is
  10501. --
  10502.       Begin
  10503.       Return ATAN ((RADIUS_OF_EARTH_IN_KM + HEIGHT - RADIUS_OF_EARTH_IN_KM*
  10504.              COS(HANG))/(RADIUS_OF_EARTH_IN_KM*AMAX1(1.0E-10,SIN(HANG)))) -
  10505.              HANG;
  10506. --
  10507.       End FRANG;
  10508. --
  10509. --
  10510.       Function FSEC (HANGLE: float; RANGLE: float) return float is
  10511. --
  10512.       Begin
  10513. --
  10514.       Return 1.0/SIN(HANGLE+RANGLE);
  10515. --
  10516.       End FSEC;
  10517. --
  10518. --
  10519.       Function FHANG (PSI: float; CONST: float) return float is
  10520. --
  10521.       Begin
  10522. --
  10523.       Return ACOS(CONST*COS(PSI)) - PSI;
  10524. --
  10525.       End FHANG;
  10526. --
  10527. --
  10528.       Function FLHS (A1: float; BETA: float; ALPF: float) return float is
  10529. --
  10530.       Begin
  10531. --
  10532.       Return SIN(A1*ALPF - BETA);
  10533. --
  10534.       End FLHS;
  10535. --
  10536. --
  10537.       Function FRHS (CE: float; CF: float; AK: float; BETA: float; ALPF: float)
  10538.                     return float is
  10539. --
  10540.       Begin
  10541. --
  10542.       Return CE*SIN(ALPF) + CF*SIN(AK*ALPF - BETA);
  10543. --
  10544.       End FRHS;
  10545. --
  10546. --
  10547.       Function CXSQRT (ZT: complex) return complex is
  10548. --
  10549.       Begin
  10550. --
  10551.       Return CSQRT(ZT)*SIGN(1.0,AREAL(CSQRT(ZT)));
  10552. --
  10553.       End CXSQRT;
  10554. --
  10555. --
  10556.       Function FD20 (R: float; D: float) return float is
  10557. --
  10558. --    FD20 IS FOR CALCULATING SPACE LOSS.
  10559. --
  10560.       Begin
  10561. --
  10562.       Return 71.0 + 8.7*LOG(R/COS(D));
  10563. --
  10564.       End FD20;
  10565. --
  10566. --
  10567.       Function FEPS (SIGMA: float) return float is
  10568. --
  10569. --    FEPS IS FOR CALCULATING AN EPS CONSISTENT WITH THE
  10570. --          INPUT CONDUCTIVITY.  FOR POOR EARTH WITH A
  10571. --          CONDUCTIVITY OF 0.001, EPS := 4.0  FOR A GOOD
  10572. --          EARTH WITH A CONDUCTIVITY OF 0.01, EPS := 10.0
  10573. --          EPS IS EXTRAPOLATED/INTERPOLATED IN BOTH DIRECTIONS
  10574. --          BUT NOT ALLOWED TO BE LESS THAN 1.
  10575. --          IF SIGMA IS > 0.9 MHO/M, IT IS ASSUMED THAT
  10576. --          THE REFLECTION MEDIUM IS WATER, AND EPS IS SET := 80.0
  10577. --
  10578.       Begin
  10579. --
  10580.       Return AMAX1 (1.0, 6.0*LOG10(1000.0*SIGMA) + 4.0);
  10581. --
  10582.       End FEPS;
  10583. --
  10584.       Procedure AEORAF (EHTD: in float;
  10585.                         EHTN: in float;
  10586.                         FHTD: in float;
  10587.                         FHTN: in float) is
  10588. --
  10589. --#PURPOSE: AEORAF calculates which single modes are possible and
  10590. --          fills EFDATA with variable values for the possible cases.
  10591. --
  10592. --#AUTHOR:  J. Conrad
  10593. --
  10594. --#TYPE:    Numerical Analysis
  10595. --
  10596. --#PARAMETER DESCRIPTIONS:
  10597. --IN        EHTD   = Height of the E layer of the ionosphere in
  10598. --                   DAY conditions in kilometers
  10599. --IN        EHTN   = Height of the E layer of the ionosphere in
  10600. --                   NIGHT conditions in kilometers
  10601. --IN        FHTD   = Height of the F layer of the ionosphere in
  10602. --                   DAY conditions in kilometers
  10603. --IN        FHTN   = Height of the F layer of the ionosphere in
  10604. --                   NIGHT conditions in kilometers
  10605. --
  10606. --#CALLED BY:
  10607. --          EFMODE
  10608. --
  10609. --#CALLS TO:
  10610. --          'NONE'
  10611. --
  10612. --#TECHNICAL DESCRIPTION:
  10613. --          Straightforward spherical geometry is employed to determine
  10614. --          which of five E layer modes and which of five F layer modes
  10615. --          are feasible (i.e., launch angles do not intersect the earth).
  10616. --
  10617.       EHT, FHT, DUMA, DUMB, DHOP, ALPE, RADANG, SECX: float;
  10618.       I, J, NMODE, NHOPS, IYEFD, IZEFD: integer;
  10619. --
  10620.       Begin
  10621.  
  10622.       If IDNT = DAY and IDNR = DAY Then
  10623.          EHT := EHTD;
  10624.          FHT := FHTD;
  10625.       Elsif IDNT /= IDNR Then
  10626.          DUMA := DISDAY/DISTOT;
  10627.          DUMB := DISNIT/DISTOT;
  10628.          EHT := DUMA*EHTD + DUMB*EHTN;
  10629.          FHT := DUMA*FHTD + DUMB*FHTN;
  10630.       Else
  10631.          EHT := EHTN;
  10632.          FHT := FHTN;
  10633.       End If;
  10634. --
  10635. --DO E MODES.
  10636.       J := 0;
  10637.       For I in 1..5 Loop
  10638.          NMODE := IJTMD(I+1,J+1);
  10639.          NHOPS := IHFMD(NMODE,3);
  10640.          IYEFD := IHFMD(NMODE,6);
  10641.          IZEFD := IHFMD(NMODE,7);
  10642.          DHOP := DISTOT/FLOAT(NHOPS);
  10643.          ALPE := 0.5*DHOP/RADIUS_OF_EARTH_IN_KM;
  10644.          RADANG := FRANG(EHT, ALPE);
  10645.          SECX := FSEC(ALPE, RADANG);
  10646.          If RADANG >= RADIANS_PER_DEGREE Then
  10647.             EFDATA(1,IYEFD,IZEFD) := ALPE;
  10648.             EFDATA(3,IYEFD,IZEFD) := RADANG;
  10649.             EFDATA(4,IYEFD,IZEFD) := SECX;
  10650.          Elsif RADANG > 0.0 Then
  10651.             EFDATA(3,IYEFD,IZEFD) := -TWOPI;
  10652.          End If;
  10653.       End Loop;
  10654. --
  10655. --DO F MODES.
  10656.       I:=0;
  10657.       For J in 1..5 Loop
  10658.          NMODE := IJTMD(I+1,J+1);
  10659.          NHOPS := IHFMD(NMODE,3);
  10660.          IYEFD := IHFMD(NMODE,6);
  10661.          IZEFD := IHFMD(NMODE,7);
  10662.          DHOP := DISTOT/FLOAT(NHOPS);
  10663.          ALPE := 0.5*DHOP/RADIUS_OF_EARTH_IN_KM;
  10664.          RADANG := FRANG(FHT, ALPE);
  10665.          SECX := FSEC(ALPE, RADANG);
  10666.          If RADANG >= RADIANS_PER_DEGREE Then
  10667.             EFDATA(2,IYEFD,IZEFD) := ALPE;
  10668.             EFDATA(3,IYEFD,IZEFD) := RADANG;
  10669.             EFDATA(5,IYEFD,IZEFD) := SECX;
  10670.          Elsif RADANG > 0.0 Then
  10671.             EFDATA(3,IYEFD,IZEFD) := -TWOPI;
  10672.          End If;
  10673.       End Loop;
  10674. --
  10675.       Return;
  10676. --
  10677.       End AEORAF;
  10678. --
  10679. --
  10680.       Procedure EFHOP (EHTD: in float;
  10681.                        FHTN: in float;
  10682.                        NITMAX: in integer) is
  10683. --
  10684. --#PURPOSE: EFHOP calculates which mixed modes are possible and
  10685. --          fills EFDATA with variable values for the possible cases.
  10686. --
  10687. --#AUTHOR:  J. Conrad
  10688. --
  10689. --#TYPE:    Numerical Analysis
  10690. --
  10691. --#PARAMETER DESCRIPTIONS:
  10692. --IN        EHTD   = Height of the E layer of the ionosphere in
  10693. --                   DAY conditions in kilometers
  10694. --IN        FHTN   = Height of the F layer of the ionosphere in
  10695. --                   NIGHT conditions in kilometers
  10696. --IN        NITMAX = The maximum number of iterations allowed for
  10697. --                   convergence
  10698. --
  10699. --#CALLED BY:
  10700. --          EFMODE
  10701. --
  10702. --#CALLS TO:
  10703. --          'NONE'
  10704. --
  10705. --#TECHNICAL DESCRIPTION:
  10706. --          EFHOP calculates the geometrically viable number of hops
  10707. --          in mixed mode HF skywave communications.  All output data is
  10708. --          passed via COMMON EFMDAT.
  10709. --
  10710. --          The technique employed is one of iterative search for each
  10711. --          of the possible combinations of mixed E and F layer hop
  10712. --          modes.  The launch angle is adjusted each time until
  10713. --          convergence is found -- unless the mode is found to be
  10714. --          divergent because it is geometrically impossible.
  10715. --
  10716.       ALP: array (integer range 1..3) of float;
  10717.       ALPERR: array (integer range 1..3) of float;
  10718.       ALFMXA, ALPTOT, ERRBND, ALPFMN, ALFMXB, ALPFMX, DUMA, DUMB, DUMC: float;
  10719.       A1, BETA, C, ALPE, ALPF, A2, PSIF, PSIE: float;
  10720.       NMODE, NEHOPS, NFHOPS, NHOPS, IYEFD, IZEFD, NIT, INFLG: integer;
  10721.       KA, KB, IFLG: integer;
  10722.       CE, CF, AK: float;
  10723. --
  10724.       Begin
  10725. --
  10726.       CE := RADIUS_OF_EARTH_IN_KM/(EHTD + RADIUS_OF_EARTH_IN_KM);
  10727.       CF := RADIUS_OF_EARTH_IN_KM/(FHTN + RADIUS_OF_EARTH_IN_KM);
  10728.       ALFMXA := ACOS(CF);
  10729.       ALPTOT := 0.5*DISTOT/RADIUS_OF_EARTH_IN_KM;
  10730.       ERRBND := 0.001*RADIANS_PER_DEGREE;
  10731. --
  10732. --START THE LOOP OVER THE MODES.
  10733. --
  10734.       For NMODE in 11..20 Loop
  10735.          NEHOPS := IHFMD(NMODE,1);
  10736.          NFHOPS := IHFMD(NMODE,2);
  10737.          NHOPS  := IHFMD(NMODE,3);
  10738.          IYEFD  := IHFMD(NMODE,6);
  10739.          IZEFD  := IHFMD(NMODE,7);
  10740.          ALPFMN := ALPTOT/FLOAT(NHOPS);
  10741.          ALFMXB := ALPTOT/FLOAT(NFHOPS);
  10742.          ALPFMX := AMIN1(ALFMXA, ALFMXB);
  10743. --
  10744. --DO A QUICK CHECK ON THE TERMINATOR.
  10745. --     USE THE MAXIMUM ALPHA F TO DETERMINE THE MAXIMUM
  10746. --          F HOP SEGMENT DISTANCE.
  10747. --     USE THE MINIMUM ALPHA F TO DETERMINE THE MINIMUM
  10748. --          F HOP SEGMENT DISTANCE.
  10749. --     IF THE MINIMUM DISTANCE IS GREATER THAN DISNIT
  10750. --          OR IF THE MAXIMUM DISTANCE IS LESS THAN DISNIT
  10751. --          THE MODE IS NOT POSSIBLE.
  10752. --
  10753.          DUMA := (2.0*FLOAT(NFHOPS) + 1.0)*RADIUS_OF_EARTH_IN_KM*ALPFMX;
  10754.          DUMB := (2.0*FLOAT(NFHOPS) - 1.0)*RADIUS_OF_EARTH_IN_KM*ALPFMN;
  10755.          If DUMA >= DISNIT and DUMB <= DISNIT Then
  10756.             BETA := ALPTOT/FLOAT(NEHOPS);
  10757.             AK := FLOAT(NFHOPS)/FLOAT(NEHOPS);
  10758.             A1 := 1.0 + AK;
  10759.             DUMC := FPSI(ALPFMN,CF);
  10760.             If DUMC >= 0.0 Then
  10761.                NIT := 0;
  10762.                INFLG := 0;
  10763.                KA := 0;
  10764.                KB := 0;
  10765.                ALP(1) := ALPFMN;
  10766.                ALP(3) := ALPFMX;
  10767.                ALP(2) := FAVG(ALPFMN, ALPFMX);
  10768. --
  10769.                For K in 1..3 Loop
  10770.                   ALPERR(K) := FLHS(A1,BETA, ALP(K))-
  10771.                                FRHS(CE, CF, AK, BETA, ALP(K));
  10772.                   If ALPERR(K) > 0.0 Then
  10773.                      KA := KA + 1;
  10774.                   End If;
  10775.                   If ALPERR(K) < 0.0 Then
  10776.                      KB := KB + 1;
  10777.                   End If;
  10778.                End Loop;
  10779. --
  10780.                If KA <= 2 and KB <= 2 Then
  10781.                   Loop
  10782.                      NIT := NIT + 1;
  10783.                      If NIT > NITMAX Then
  10784.                         New_Line;
  10785.                         Put("ERROR...Convergence failed in EFHOP.");
  10786.                         INFLG := 1;
  10787.                         Exit;
  10788.                      Else
  10789.                         If ALPERR(2) >= 0.0 Then
  10790.                            ALP(3) := ALP(2);
  10791.                            ALPERR(3) := ALPERR(2);
  10792.                         Else
  10793.                            ALP(1) := ALP(2);
  10794.                            ALPERR(1) := ALPERR(2);
  10795.                         End If;
  10796.                         ALP(2) := FAVG(ALP(1), ALP(3));
  10797.                         ALPERR(2) := FLHS(A1, BETA, ALP(2)) -
  10798.                                      FRHS(CE, CF, AK, BETA, ALP(2));
  10799.                         Exit When ABS(ALPERR(2)) <= ERRBND;
  10800.                      End If;
  10801.                   End Loop;
  10802. --
  10803. --THERE IS A POTENTIALLY SUCCESSFUL RESULT.
  10804. --
  10805.                   ALPF := ALP(2);
  10806.                   ALPE := BETA - AK*ALPF;
  10807. -- 
  10808. --CASE IS GEOMETRICALLY POSSIBLE FOR SOME LOCATION OF THE TERMINATOR, 
  10809. --CHECK IF ACTUAL TERMINATOR LOCATION NULLIFIES SUCCESSFUL PROPAGATION
  10810. --
  10811.                   A1 := (2.0*FLOAT(NEHOPS) - 1.0)*ALPE*RADIUS_OF_EARTH_IN_KM;
  10812.                   A2 := (2.0*FLOAT(NEHOPS) + 1.0)*ALPE*RADIUS_OF_EARTH_IN_KM;
  10813.                   IFLG := 0;
  10814.                   If A1 <= DISDAY and A2 >= DISDAY Then
  10815.                      IFLG := 1;
  10816.                   End If;
  10817.                   If IFLG >= 1 Then
  10818. --
  10819. --CHECK THAT THE TWO PSI-S PRODUCED ARE EQUAL WITHIN 1 PERCENT.
  10820. --
  10821.                      PSIF := FPSI(ALPF,CF);
  10822.                      PSIE := FPSI(ALPE,CE);
  10823.                      DUMA := FAVG(PSIE,PSIF);
  10824.                      If INFLG > 0 Then
  10825.                         EFDATA(1,IYEFD,IZEFD) := ALPE;
  10826.                         EFDATA(2,IYEFD,IZEFD) := ALPF;
  10827.                         EFDATA(3,IYEFD,IZEFD) := DUMA;
  10828.                         DUMB := FSEC(ALPE, DUMA);
  10829.                         EFDATA(4,IYEFD,IZEFD) := DUMB;
  10830.                         DUMB := FSEC(ALPF,DUMA);
  10831.                         EFDATA(5,IYEFD,IZEFD) := DUMB;
  10832.                      Else
  10833.                         If DUMA >= 0.0 Then
  10834.                            If DUMA >= RADIANS_PER_DEGREE Then
  10835.                               DUMB := ABS(PSIE - PSIF)/DUMA;
  10836.                               If DUMB > 0.01 Then
  10837.                                  New_Line;
  10838.                                  Put("ERROR...Convergence failed in EFHOP.");
  10839.                                  INFLG := 1;
  10840.                               Else
  10841.                                  EFDATA(1,IYEFD,IZEFD) := ALPE;
  10842.                                  EFDATA(2,IYEFD,IZEFD) := ALPF;
  10843.                                  EFDATA(3,IYEFD,IZEFD) := DUMA;
  10844.                                  DUMB := FSEC(ALPE, DUMA);
  10845.                                  EFDATA(4,IYEFD,IZEFD) := DUMB;
  10846.                                  DUMB := FSEC(ALPF,DUMA);
  10847.                                  EFDATA(5,IYEFD,IZEFD) := DUMB;
  10848.                               End If;
  10849.                            Else  --PSI IS > 0.0 BUT < 1 DEG.  SET PSI := -TWOPI
  10850.                               EFDATA(3,IYEFD,IZEFD) := -TWOPI;
  10851.                            End If;
  10852.                         End If;
  10853.                      End If;
  10854.                   End If;
  10855.                End If;
  10856.             End If;
  10857.          End If;
  10858.       End Loop;
  10859. --
  10860.       Return;
  10861. --
  10862.       End EFHOP;
  10863. --
  10864. --
  10865.       Procedure EFMODE (EHTD: in float;
  10866.                         EHTN: in float;
  10867.                         FHTD: in float;
  10868.                         FHTN: in float) is
  10869. --
  10870. --#PURPOSE: EFMODE controls the subroutines that determine the
  10871. --          viable single and mixed modes for HF skywave communication
  10872. --          for the particular geometry and solar conditions.
  10873. --
  10874. --#AUTHOR:  J. Conrad
  10875. --
  10876. --#TYPE:    Control Module
  10877. --
  10878. --#PARAMETER DESCRIPTIONS:
  10879. --IN        EHTD   = Height of the E layer of the ionosphere in
  10880. --                   DAY conditions in kilometers
  10881. --IN        EHTN   = Height of the E layer of the ionosphere in
  10882. --                   NIGHT conditions in kilometers
  10883. --IN        FHTD   = Height of the F layer of the ionosphere in
  10884. --                   DAY conditions in kilometers
  10885. --IN        FHTN   = Height of the F layer of the ionosphere in
  10886. --                   NIGHT conditions in kilometers
  10887. --
  10888. --#CALLED BY:
  10889. --          MF_HF_HANDLER
  10890. --
  10891. --#CALLS TO:
  10892. --          AEORAF
  10893. --          EFHOP
  10894. --
  10895. --#TECHNICAL DESCRIPTION:
  10896. --          EFMODE is the control routine for identifying the
  10897. --          geometrically viable HF communication skywave modes.
  10898. --          It controls all of the other routines that determine the
  10899. --          viable single and mixed modes for HF skywave communication
  10900. --          for the particular geometry and solar conditions.
  10901. --
  10902.       J, I, K: integer;
  10903. --
  10904.       Begin
  10905. --
  10906. --INITIALIZE EFDATA.
  10907.       For J in 1..6 Loop
  10908.          For I in 1..6 Loop
  10909.             For K in 1..5 Loop
  10910.                EFDATA(K,I,J) := 0.0;
  10911.             End Loop;
  10912.          End Loop;
  10913.       End Loop;
  10914. --
  10915. --EVALUATE THE ALL E AND ALL F MODES OF PROPAGATION.
  10916. --
  10917.       AEORAF (EHTD, EHTN, FHTD, FHTN);
  10918. --
  10919. --EVALUATE THE MIXED MODES IF A DAY/NITE TERMINATOR CROSSES THE PATH.
  10920. --
  10921.       If IDNT /= IDNR Then
  10922.          EFHOP (EHTD, FHTN, 10);
  10923.       End If;
  10924. --
  10925.       Return;
  10926. --
  10927.       End EFMODE;
  10928. --
  10929.       Function CSZ1 (X: float) return complex is
  10930. --
  10931. --#PURPOSE: CSZ1 evaluates the sine and cosine integral functions.
  10932. --
  10933. --#AUTHOR:  J. Conrad
  10934. --
  10935. --#TYPE:    Numerical Analysis
  10936. --
  10937. --#PARAMETER DESCRIPTIONS:
  10938. --IN        X      = Integrand
  10939. --OUT       CSZ1   = Value of cosine or sine integral function
  10940. --
  10941. --#CALLED BY:
  10942. --          HFGAIN
  10943. --
  10944. --#CALLS TO:
  10945. --          'NONE'
  10946. --
  10947. --#TECHNICAL DESCRIPTION:
  10948. --          CSZ1 evaluates the sine and cosine integral functions.
  10949. --          A series expansion is used to numerically evaluate the
  10950. --          cosine integral.  The calculation is taken from
  10951. --          Barghausen, 1969.
  10952. --
  10953.       A, AM1, AM2, B, BM1, BM2, SA: complex;
  10954.       EN, X2, TN, SI, CI, P, TM1, T: float;
  10955.       K: integer;
  10956.       TESTQ: float := 4.0E-10;
  10957.       GAMA: float := 0.5772156;
  10958. --
  10959.       Begin
  10960. --
  10961.       If X <= 6.0 Then
  10962.          EN := 0.0;
  10963.          X2 := X*X;
  10964.          TN := X;
  10965.          SI := X;
  10966.          Loop
  10967.             EN := EN + 1.0;
  10968.             TN := -TN*X2*(2.0*EN - 1.0)/((2.0*EN)*(2.0*EN + 1.0)**2);
  10969.             Exit When ABS(TN/SI) <= TESTQ;
  10970.             SI := SI + TN;
  10971.          End Loop;
  10972.          EN := 1.0;
  10973.          TN := - X2/4.0;
  10974.          CI := TN + GAMA + LOG(X);
  10975.          Loop
  10976.             EN := EN + 1.0;  
  10977.             TN := -TN*X2*(2.0*EN - 2.0)/((2.0*EN - 1.0)*(2.0*EN)**2);
  10978.             Exit When ABS(TN/CI) <= TESTQ;
  10979.             CI := CI + TN;
  10980.          End Loop;
  10981.          Return CMPLX(CI, -SI);
  10982.       Else
  10983.          AM1 := CMPLX(1.0,0.0);
  10984.          AM2 := CMPLX(1.0,0.0);
  10985.          BM1 := CMPLX(1.0,0.0);
  10986.          BM2 := CMPLX(0.0,0.0);
  10987.          P := 0.0;
  10988.          K := 0;
  10989.          TM1 := 0.0;
  10990.          Loop
  10991.             P := P + 1.0;
  10992.             K := K + 1;
  10993.             If K mod 2 /= 0 Then
  10994.                SA := CMPLX(0.0,(P + 1.0)/(2.0*X));
  10995.             Else
  10996.                SA := CMPLX(0.0,P/(2.0*X));
  10997.             End If;
  10998.             A := AM1 + SA*AM2;
  10999.             B := BM1 + SA*BM2;
  11000.             T := CABS(A/B);
  11001.             Exit When ABS((T - TM1)/T) < TESTQ;
  11002.             AM2 := AM1;
  11003.             AM1 := A;
  11004.             BM2 := BM1;
  11005.             BM1 := B;
  11006.             TM1 := T;
  11007.          End Loop;
  11008.          Return CONJG(CMPLX(0.0,HALFPI) + 
  11009.                 CMPLX(COS(X),SIN(X))/(CMPLX(0.0,X)*A/B));
  11010.       End If;
  11011. --
  11012.       End CSZ1;
  11013. --
  11014.       Procedure HFGAIN (IA: in integer;
  11015.                         IT: in integer;
  11016.                         DEL: in float;
  11017.                         XL: in float;
  11018.                         HI: in float;
  11019.                         A: in float;
  11020.                         GX: in float;
  11021.                         SIG: in float;
  11022.                         ER : in float;
  11023.                         G: out float) is
  11024. --
  11025. --#PURPOSE: HFGAIN calulates transmitter and receiver antenna gains.
  11026. --
  11027. --#AUTHOR:  J. Conrad
  11028. --
  11029. --#TYPE:    Numerical Analysis
  11030. --
  11031. --#PARAMETER DESCRIPTIONS:
  11032. --IN        IA     = Antenna type:
  11033. --                   5 = Constant Gain
  11034. --                   6 = Rhombic
  11035. --                   7 = Vertical
  11036. --                   8 = Horizontal Half Wave Dipole
  11037. --IN        IT     = Type option (0 = ground losses, 1 = antenna gain)
  11038. --IN        DEL    = Radiation angle in radians
  11039. --IN        XL     = Antenna length term in meters (IA := 6 or 7 only)
  11040. --IN        HI     = Antenna height term in meters (IA := 6 or 8 only)
  11041. --IN        A      = Antenna tilt angle in degrees (IA := 6 only)
  11042. --IN        GX     = Antenna gain term in dB (IA := 5 only)
  11043. --IN        SIG    = Surface conductivity in MHOS/M
  11044. --IN        ER     = Surface relative dielectric constant
  11045. --OUT       G      = Ground loss or antenna gain in dB
  11046. --
  11047. --#CALLED BY:
  11048. --          HFGL
  11049. --
  11050. --#CALLS TO:
  11051. --          CSZ1
  11052. --
  11053. --#TECHNICAL DESCRIPTION:
  11054. --          Standard formulas for the gain of rhombic, vertical, and
  11055. --          horizontal half-wave dipole antennas are evaluated.  These
  11056. --          formulas are taken from Barghausen, 1969.
  11057. --
  11058.       DIF, ACSQ, QPER, QPAR, ZT, SQRD: complex;
  11059.       DID: array (integer range 1..2) of float;
  11060.       O: array (integer range 1..2) of complex;
  11061.       VOFL: float := 2.997925E5;
  11062.       GAMA: float := 0.5772156;
  11063.       RATIO: float := 1.414214E-3;
  11064.       WAVE, EFF, Q, T, CV, PSIV, CH, PSIH, EL, H, PHI, BETA, EL1: float;
  11065.       FAC, FAC2, FAC4, X, HWAVE, HQWAVE, RHI, SR, CR, RETA, SB, CB: float;
  11066.       TSC, TCS, U1, U2, W1, W3, RAIN, SFAC2, CFAC2, HQ, ACLOC, AS: float;
  11067.       FLOG, C2KEL, S2KEL, RIN, RZERO, W4, CFAC, W2, CPHI, SPHI2: float;
  11068.       GI, ETETA1, EPHI1, ETETA2, EPHI2, TT, UZ, VZ, V1, CXC, RAINE: float;
  11069.       J, IBRNCH: integer;
  11070. --
  11071.       Begin
  11072. --
  11073.       If IA = 5 and IT = 1 Then
  11074.          G := GX;
  11075.          Return;
  11076.       End If;
  11077. --
  11078.       WAVE := (VOFL*0.001)/FREQMC;
  11079.       EFF := 0.0;
  11080.       G := -10.0;
  11081.       Q := SIN(DEL);
  11082.       T := COS(DEL);
  11083.       DIF := CMPLX(ER,-60.0*SIG*WAVE);
  11084.       ACSQ := CXSQRT(DIF-T*T);
  11085.       If AREAL(ACSQ) < 0.0 Then
  11086.          ACSQ := -ACSQ;
  11087.       End If;
  11088.       QPER := (DIF*Q - ACSQ)/(DIF*Q + ACSQ);
  11089.       CV := CABS(QPER);
  11090.       PSIV := AIMAG(CLOG(QPER));
  11091.       QPAR := (Q - ACSQ)/(Q + ACSQ);
  11092.       CH := CABS(QPAR);
  11093.       PSIH := AIMAG(CLOG(QPAR));
  11094.       If IT <= 0 Then  --COMPUTE G AS GROUND LOSS
  11095.          G := 4.35*LOG(0.5*(CH*CH + CV*CV));
  11096.          Return;
  11097.       End If;
  11098. --
  11099. --BEGIN ANTENNA GAIN CALCULATIONS
  11100.       EL := XL;
  11101.       If IA = 8 Then
  11102.          EL := -0.5*WAVE;
  11103.       End If;
  11104.       H := HI;
  11105.       PHI := A;
  11106.       BETA := 0.0;
  11107.       EL1 := EL/WAVE;
  11108.       If EL < 0.0 Then
  11109.          EL1 := ABS(EL);
  11110.       End If;
  11111.       FAC := PI*EL1;
  11112.       FAC2 := TWOPI*EL1;
  11113.       FAC4 := 2.0*FAC2;
  11114.       X := H/WAVE;
  11115.       If H < 0.0 Then
  11116.          X := ABS(H);
  11117.       End If;
  11118.       HWAVE := TWOPI*X;
  11119.       HQWAVE := 2.0*HWAVE*Q;
  11120.       RHI := PHI*RADIANS_PER_DEGREE;
  11121.       SR := SIN(RHI);
  11122.       CR := COS(RHI);
  11123.       RETA := BETA*RADIANS_PER_DEGREE;
  11124.       SB := SIN(RETA);
  11125.       CB := COS(RETA);
  11126. --
  11127. --BRANCH TO PROPER ANTENNA TYPE FOR GAIN GALCULATIONS
  11128.       IBRNCH := IA - 5;
  11129.       If IBRNCH = 1 Then  -- TERMINATED RHOMBIC ANTENNA, IA = 6
  11130.          TSC := 1.0 - T*SR*CB;
  11131.          TCS := T*CR*SB;
  11132.          U1 := TSC - TCS;
  11133.          U2 := TSC + TCS;
  11134.          W1 := COS(PSIH - HQWAVE);
  11135.          W3 := COS(PSIV-HQWAVE);
  11136.          RAIN := 3.2*(CR*SIN(FAC*U1)*SIN(FAC*U2)/(U1*U2))**2*((CB - 
  11137.                  SR*T)**2*(CH**2 + 1.0 + 2.0*CH*W1) + SB**2*(CV**2 +
  11138.                  1.0 - 2.0*CV*W3)*Q**2);
  11139.          EFF := -1.7;
  11140. --
  11141.       Elsif IBRNCH = 2 Then  -- VERTICAL ANTENNA, IA = 7
  11142.          If DEL = HALFPI Then
  11143.             G := -10.0;
  11144.             EFF := 0.0;
  11145.             Return;
  11146.          End If;
  11147.          SFAC2 := SIN(FAC2);
  11148.          CFAC2 := COS(FAC2);
  11149.          HQ := FAC2*Q;
  11150.          ACLOC := COS(HQ) - CFAC2;
  11151.          AS := SIN(HQ) - Q*SFAC2;
  11152.          FLOG := LOG(FAC2);
  11153.          C2KEL := 2.0*CFAC2*CFAC2 - 1.0;
  11154.          S2KEL := 2.0*CFAC2*SFAC2;
  11155.          If FAC4 < 1.0E-7 Then
  11156.             Return;
  11157.          End If;
  11158.          ZT := CSZ1(4.0*FAC2);
  11159.          RZERO := 0.5*(C2KEL*(AREAL(ZT) - FLOG - 1.3862943612 - GAMA) -
  11160.                   S2KEL*AIMAG(ZT));
  11161.          ZT := CSZ1(FAC4);
  11162.          RZERO := 30.0*(RZERO + (1.0 + C2KEL)*(AREAL(-ZT) + FLOG + 
  11163.                   0.6931471806 + GAMA) + S2KEL*AIMAG(ZT));
  11164.          RIN := RZERO;
  11165.          W3 := COS(PSIV - HQWAVE);
  11166.          W4 := SIN(PSIV - HQWAVE);
  11167.          RAIN := 30.0*((ACLOC*(1.0 + CV*W3) + AS*CV*W4)**2 + 
  11168.                  (ACLOC*CV*W4 + AS*(1.0 - CV*W3))**2)/(RIN*T**2);
  11169.          If EL1 < 0.35 Then
  11170.             EFF := -((((6416.702*EL1 - 6091.33)*EL1 + 2179.89)*EL1 - 
  11171.                    364.817)*EL1 + 25.646);
  11172.          End If;
  11173. --
  11174.       Elsif IBRNCH = 3 Then  -- HORIZONTAL HALF WAVE DIPOLE ANTENNA, IA = 8
  11175.          CFAC := COS(FAC);
  11176.          W1 := COS(PSIH - HQWAVE);
  11177.          W2 := SIN(PSIH - HQWAVE);
  11178.          W3 := COS(PSIV - HQWAVE);
  11179.          W4 := SIN(PSIV - HQWAVE);
  11180.          CPHI := T*SB;
  11181.          SPHI2 := 1.0 - CPHI**2;
  11182.          If SPHI2 = 0.0 Then
  11183.             G := -10.0;
  11184.             EFF := 0.0;
  11185.             Return;
  11186.          End If;
  11187.          GI := (COS(FAC*CPHI) - CFAC)/SPHI2;
  11188.          ETETA1 := SB*Q*GI*(1.0 - CV*W3);
  11189.          EPHI1 := CB*GI*(1.0 + CH*W1);
  11190.          ETETA2 := -SB*Q*GI*CV*W4;
  11191.          EPHI2 := CB*GI*CH*W2;
  11192.          DID(1) := 2.0*HWAVE;
  11193.          DID(2) := RATIO*FAC2;
  11194.          SFAC2 := SIN(FAC2);
  11195.          CFAC2 := COS(FAC2);
  11196.          For J in 1..2 Loop
  11197.             TT := SQRT(DID(J)**2 + FAC2**2);
  11198.             UZ := TT - FAC2;
  11199.             If UZ < 1.0E-7 Then
  11200.                Return;
  11201.             End If;
  11202.             VZ := TT + FAC2;
  11203.             TT := SQRT(DID(J)**2+FAC2**2/4.0);
  11204.             U1 := TT - FAC;
  11205.             If U1 < 1.0E-7 Then
  11206.                Return;
  11207.             End If;
  11208.             V1 := TT + FAC;
  11209.             O(J) := (CSZ1(UZ) - 2.0*CSZ1(U1))*CMPLX(CFAC2,-SFAC2) + 
  11210.                     (CSZ1(VZ)-2.0*CSZ1(V1))*CMPLX(CFAC2,SFAC2) - 
  11211.                     2.0*(CSZ1(U1) + CSZ1(V1)) + 2.0*CSZ1(DID(J))*(CFAC2 + 2.0);
  11212.             O(J) := O(J)*60.0/(1.0 - CFAC2);
  11213.          End Loop;
  11214.          SQRD := CXSQRT(DIF);
  11215.          If AREAL(SQRD) < 0.0 Then
  11216.             SQRD := -SQRD;
  11217.          End If;
  11218.          CXC := AREAL(O(1)*((1.0 - SQRD)/(1.0 + SQRD)));
  11219.          RIN := AREAL(O(2)) + CXC;
  11220.          RAIN :=120.0*(ETETA1**2 + ETETA2**2 + EPHI1**2 + EPHI2**2)/RIN;
  11221.       End If;
  11222. --
  11223. --CALCULATES DECIBELS
  11224.       If RAIN <= 0.0 Then
  11225.          G := -10.0;
  11226.          EFF := 0.0;
  11227.          Return;
  11228.       End If;
  11229.       G := 10.0*LOG10(RAIN);
  11230.       If G < -10.0 Then
  11231.          G := -10.0;
  11232.          EFF := 0.0;
  11233.          Return;
  11234.       End If;
  11235.       RAINE := G + EFF;
  11236.       If RAINE < -10.0 Then
  11237.          RAINE := -10.0;
  11238.          EFF := RAINE - G;
  11239.       End If;
  11240.       G := RAINE;
  11241. --
  11242.       Return;
  11243. --
  11244.       End HFGAIN;
  11245. --
  11246. --
  11247.       Procedure HFGL (IGCALC: in integer;
  11248.                       IRONLY: in integer;
  11249.                       PL: in float;
  11250.                       ELANG: in float;
  11251.                       SIGMA: in float) is
  11252. --
  11253. --#PURPOSE: HFGL calculates ground reflection and path losses at HF.
  11254. --
  11255. --#AUTHOR:  J. Conrad
  11256. --
  11257. --#TYPE:    Numerical Analysis
  11258. --
  11259. --#PARAMETER DESCRIPTIONS:
  11260. --IN        IGCALC = 1 causes only GT to be calculated; 2 causes
  11261. --                   only GR to be calculated; otherwise, all
  11262. --                   outputs may be calculated
  11263. --IN        IRONLY = 1 causes only reflection loss to be
  11264. --                   calculated; otherwise, all outputs may be calculated
  11265. --IN        PL     = Total surface path length in km
  11266. --IN        ELANG  = Radiation angle in degrees
  11267. --IN        SIGMA  = Surface conductivity in MHO/M
  11268. --
  11269. --#CALLED BY:
  11270. --          MF_HF_HANDLER
  11271. --
  11272. --#CALLS TO:
  11273. --          HFGAIN
  11274. --
  11275. --#TECHNICAL DESCRIPTION:
  11276. --          HFGL calculates ground reflection and path losses at HF.
  11277. --          It should be noted that hops are assumed between the end
  11278. --          points, and that the takeoff angle is specified by ELANG.
  11279. --          HFGAIN is called for ground reflection loss and
  11280. --          transmitter and receiver antenna gain calculations.
  11281. --
  11282.       EPS, GL: float;
  11283. --
  11284.       Begin
  11285. --
  11286.       If SIGMA >= 0.9 Then
  11287.          EPS := 80.0;
  11288.       Else
  11289.          EPS := FEPS(SIGMA);
  11290.       End If;
  11291. --
  11292.       If IGCALC = 1 Then  --TRANSMITTER GAIN.
  11293.          HFGAIN (IATYPT, 1, ELANG, LNX, HTX, TAX, GNX, SIGMA, EPS, GT);
  11294.          Return;
  11295.       End If;
  11296.       If IGCALC = 2 Then  --RECEIVER GAIN.
  11297.          HFGAIN(IATYPR, 1, ELANG, LNR, HTR, TAR, GNR, SIGMA, EPS, GR);
  11298.          Return;
  11299.       End If;
  11300. --
  11301.       If IRONLY /= 1 Then  --FREE SPACE LOSS PLUS GROUND REFLECTION LOSS.
  11302.          SPLOSS := 0.0;
  11303.          If PL/COS(ELANG) /= 0.0 Then
  11304.             SPLOSS := FD20(PL, ELANG);
  11305.          End If;
  11306.          HFGAIN (1, 0, ELANG, 0.0, 0.0, 0.0, 0.0, SIGMA, EPS, GL);
  11307.          RELOSS := GL;
  11308.          HFGAIN (IATYPT, 1, ELANG, LNX, HTX, TAX, GNX, SIGMA, EPS, GT);
  11309.          HFGAIN (IATYPR, 1, ELANG, LNR, HTR, TAR, GNR, SIGMA, EPS, GR);
  11310.       Else  --GROUND REFLECTION LOSS ONLY.
  11311.          HFGAIN (1, 0, ELANG, 0.0, 0.0, 0.0, 0.0, SIGMA, EPS, GL);
  11312.          RELOSS := GL;
  11313.       End If;
  11314.       Return;
  11315. --
  11316.       End HFGL;
  11317. --
  11318. --
  11319.       Procedure HFGSIG (SURDIS: in float; 
  11320.                         SIGMA: in float;
  11321.                         GRSIGL: out float) is
  11322. --
  11323. --#PURPOSE: HFGSIG is a master subroutine for calculating ground
  11324. --          wave signal levels at HF.
  11325. --
  11326. --#AUTHOR:  J. Conrad
  11327. --
  11328. --#TYPE:    Numerical Analysis
  11329. --
  11330. --#PARAMETER DESCRIPTIONS:
  11331. --IN        SURDIS = Great circle path surface distance in km
  11332. --IN        SIGMA  = Ground conductivity at transmitter in MHO/M
  11333. --OUT       GRSIG  = Ground wave signal stregth at receiver in dBW
  11334. --
  11335. --#CALLED BY:
  11336. --          MF_HF_HANDLER
  11337. --
  11338. --#CALLS TO:
  11339. --          GRWAVE
  11340. --
  11341. --#TECHNICAL DESCRIPTION:
  11342. --          HFGSIG sets the parameters for and calls GRWAVE to
  11343. --          calculate the volts/meter at the receiving antenna.  The
  11344. --          GRSIG is determined from:  GRSIG := 10.0* LOG10 (VOLTPM/
  11345. --          FREQMC) + 69.74  where VOLTPM is the value returned from
  11346. --          GRWAVE in volts/meter.
  11347. --
  11348.       HTRANS, HRECV, TPWRKW, HLOWER, HHIGHR, VOLTPM, DBLOSS: float;
  11349.       NPOL: integer;
  11350. --
  11351.       Begin
  11352. --
  11353.       HTRANS := 1000.0*TALT;
  11354.       HRECV := 1000.0*RALT;
  11355.       TPWRKW := 10.0**(TERP*0.1)*0.001;
  11356. --
  11357. -- CALCULATE GROUNDWAVE SIGNAL
  11358.       NPOL := 1;
  11359.       If IATYPR = 8 Then
  11360.          NPOL := 2;
  11361.       End If;
  11362.       HLOWER := AMIN1(HTRANS, HRECV);
  11363.       HHIGHR := AMAX1(HTRANS, HRECV);
  11364.       LF_HF_GROUNDWAVES.GRWAVE (SIGMA, FREQKC, SURDIS, NPOL, TPWRKW,
  11365.                                 HLOWER, HHIGHR, VOLTPM, DBLOSS);
  11366. --
  11367. --CONVERT VOLTS/METER TO DBW .
  11368. --  NOTE:   GRSIG ASSUMES AN ISOTROPIC RECEIVING ANTENNA AT ZERO ALTITUDE.
  11369.       GRSIG := -3000.0;
  11370.       If VOLTPM >= 1.0001E-10 Then
  11371.          GRSIG := 20.0*LOG10(VOLTPM/FREQKC) + 71.5 - 1.761;
  11372.       End If;
  11373. --
  11374.       Return;
  11375. --
  11376.       End HFGSIG;
  11377. --
  11378. --
  11379.       Procedure HFNACP (NMODE: in integer) is
  11380. --
  11381. --#PURPOSE: HFNACP calculates the locations of the absorption
  11382. --          control points (ACPs) for HF links.
  11383. --
  11384. --#AUTHOR:  J. Conrad
  11385. --
  11386. --#TYPE:    Numerical Analysis
  11387. --
  11388. --#PARAMETER DESCRIPTIONS:
  11389. --IN        NMODE  = The HF skywave mode number
  11390. --
  11391. --#CALLED BY:
  11392. --          MF_HF_HANDLER
  11393. --
  11394. --#CALLS TO:
  11395. --          LOCNEW
  11396. --
  11397. --#TECHNICAL DESCRIPTION:
  11398. --          The secant of the angle through the absorption control point
  11399. --          (SECACP) is determined directly from the input radiation
  11400. --          angle.  The mode number implies through HFINDX the number
  11401. --          of hops, J.  TR/J is the earth central angle per hop.
  11402. --          Knowing the radiation angle, the earth central angle, and
  11403. --          the raduis of the earth, the distance from each ground
  11404. --          reflection point to the ground zero point under an ACP
  11405. --          (altitude := 65 km) can be calculated.  The latitude and
  11406. --          longitude parameters input through COMMON /PATH/ are used
  11407. --          to associate the ground zero point distances with earth
  11408. --          based latitudes and longitudes.
  11409. --
  11410.       CACP, ALPE, ALPF, ALPD, DISD, DISE, DISF, DISX, DIS, RLATX, RLONX: float;
  11411.       RANGLE: float;
  11412.       NEHOPS, NFHOPS, LSTRT, LEND, IYEFD, IZEFD, IE, IFX, IEF, LPASS: integer;
  11413.       IEND, L: integer;
  11414. --
  11415.       Begin
  11416. --
  11417.       CACP := RADIUS_OF_EARTH_IN_KM/(65.0 + RADIUS_OF_EARTH_IN_KM);
  11418.       NEHOPS := IHFMD(NMODE,1);
  11419.       NFHOPS := IHFMD(NMODE,2);
  11420.       LSTRT  := IHFMD(NMODE,4);
  11421.       LEND   := IHFMD(NMODE,5);
  11422.       IYEFD  := IHFMD(NMODE,6);
  11423.       IZEFD  := IHFMD(NMODE,7);
  11424. --
  11425.       ALPE   := EFDATA(1,IYEFD,IZEFD);
  11426.       ALPF   := EFDATA(2,IYEFD,IZEFD);
  11427.       RANGLE := EFDATA(3,IYEFD,IZEFD);
  11428. --
  11429.       IE  := 0;
  11430.       IFX := 0;
  11431.       If NEHOPS > 0 Then
  11432.          IE := 1;
  11433.       End If;
  11434.       If NFHOPS > 0 Then
  11435.          IFX := 1;
  11436.       End If;
  11437.       IEF := IE*IFX;
  11438. --
  11439.       ALPD := FHANG (RANGLE, CACP);
  11440.       SECACP(NMODE) := FSEC(ALPD, RANGLE);
  11441.       DISD := RADIUS_OF_EARTH_IN_KM*ALPD;
  11442.       DISE := RADIUS_OF_EARTH_IN_KM*2.0*ALPE;
  11443.       DISF := RADIUS_OF_EARTH_IN_KM*2.0*ALPF;
  11444.       If IEF < 1 Then
  11445.          DISX := AMAX1(DISE, DISF) - 2.0*DISD;
  11446.       End If;
  11447. --
  11448.       LPASS := 0;
  11449. --
  11450.       IEND := LEND - 1;
  11451.       L := LSTRT;
  11452.       While L <= IEND Loop
  11453.          LPASS := LPASS + 1;
  11454.          If L <= LSTRT Then
  11455.             DIS := DISD;
  11456.          Else
  11457.             DIS := DIS + 2.0*DISD;
  11458.          End If;
  11459.          NODELOC.LOCNEW (TLAT, TLON, TRBRNG, DIS, RLATX, RLONX);
  11460.          ACPLAT(L) := RLATX;
  11461.          ACPLON(L) := RLONX;
  11462.          If IEF >= 1 Then  --HAVE A MIXED MODE.
  11463.             If IDNT = DAY and LPASS <= NEHOPS Then
  11464.                DISX := DISE - 2.0*DISD;
  11465.             End If;
  11466.             If IDNT =NIGHT and LPASS <= NFHOPS Then
  11467.                DISX := DISF - 2.0*DISD;
  11468.             End If;
  11469.             If IDNT = DAY and LPASS > NEHOPS Then
  11470.                DISX := DISF - 2.0*DISD;
  11471.             End If;
  11472.             If IDNT = NIGHT and LPASS > NFHOPS Then
  11473.                DISX := DISE - 2.0*DISD;
  11474.             End If;
  11475.          End If;
  11476.          DIS := DIS + DISX;
  11477.          NODELOC.LOCNEW (TLAT, TLON, TRBRNG, DIS, RLATX, RLONX);
  11478.          ACPLAT(L+1) := RLATX;
  11479.          ACPLON(L+1) := RLONX;
  11480.          L := L + 2;
  11481.       End Loop;
  11482. --
  11483.       Return;
  11484. --
  11485.       End HFNACP;
  11486. --
  11487. --    
  11488.       Procedure MMMUF (IENTER: in integer;
  11489.                        ICALC: in integer;
  11490.                        NMODE: in integer;
  11491.                        EHTD: out float;
  11492.                        EHTN: out float;
  11493.                        FHTD: out float;
  11494.                        FHTN: out float; 
  11495.                        FMAX: out float;
  11496.                        FMIN: out float) is
  11497. --
  11498. --#PURPOSE: MMMUF uses the layer heights to determine the
  11499. --          geometrically viable mixed modes.  The frequencies are
  11500. --          used to determine if the ray will penetrate the layer or
  11501. --          be reflected by a lower layer.
  11502. --
  11503. --#AUTHOR:  J. Conrad
  11504. --
  11505. --#TYPE:    Numerical Analysis
  11506. --
  11507. --#PARAMETER DESCRIPTIONS:
  11508. --IN        IENTER = 1 if new geometry or time of evaluation; the
  11509. --                   number greater than one if only the number
  11510. --                   of hops have changed since the last call
  11511. --IN        ICALC  = 1 : return layer heights
  11512. --                   2 : return critical frequencies
  11513. --IN        NMODE  = Skywave mode number
  11514. --OUT       EHTD   = E layer height in day segment of path in km
  11515. --OUT       EHTN   = E layer height in night segment of path in km
  11516. --OUT       FHTD   = F layer height in day segment of path in km
  11517. --OUT       FHTN   = F layer height in night segment of path in km
  11518. --OUT       FMAX   = Maximum permissible frequency for the
  11519. --                   specified mode in MHz
  11520. --OUT       FMIN   = Minimum permissible frequency for the
  11521. --                   specified mode in MHz
  11522. --
  11523. --#CALLED BY:
  11524. --          MF_HF_HANDLER
  11525. --
  11526. --#CALLS TO:
  11527. --          IONDAT
  11528. --          LOCNEW
  11529. --
  11530. --#TECHNICAL DESCRIPTION:
  11531. --     MMMUF determines the layer heights of the ionosphere and the
  11532. --     critical frequencies for HF mixed mode skywave propagation. The
  11533. --     layer heights are used to determine the geometricaly viable mixed
  11534. --     modes and the critical frequencies are used to determine if the
  11535. --     ray will penetrate the layer or be reflected by a lower layer.
  11536. --
  11537. --     The procedure employed is to first determine whether the transmit-
  11538. --     ter is in day or night. If night, the problem is solved by begin-
  11539. --     ning at the transmitter and going to the receiver, starting first
  11540. --     with the F-layer modes. If day, the opposite path is followed but
  11541. --     still beginning with the F-layer modes first.
  11542. --
  11543.       EHT, FHT, DUMA, DUMB, DUMC, DUMD, EHANG, FHANG, SECE, SECF: float;
  11544.       FOEMAX, FOEMIN, FOFMAX, FOFMIN, FMAXF, FMAXE: float;
  11545.       SLAT1, SLON1, SLAT2, SLON2, TLATX, TLONX, RLATX, RLONX: float;
  11546.       NEHOPS, NFHOPS, KA, KB: integer;
  11547. --
  11548.       Begin
  11549. --
  11550.       If ICALC = 1 Then
  11551.          SLAT1 := RLAT;
  11552.          SLON1 := RLON;
  11553.          RLAT := TERLAT;
  11554.          RLON := TERLON;
  11555.          HF_ATMOSPHERICS.IONDAT(1, 1, EHT, FHT, DUMA, DUMB, DUMC, DUMD);
  11556.          RLAT := SLAT1;
  11557.          RLON := SLON1;
  11558.          EHTD:=EHT;
  11559.          FHTD:=FHT;
  11560.          SLAT1 := TLAT;
  11561.          SLON1 := TLON;
  11562.          TLAT := TERLAT;
  11563.          TLON := TERLON;
  11564.          HF_ATMOSPHERICS.IONDAT(1, 1, EHT, FHT, DUMA, DUMB, DUMC, DUMD);
  11565.          TLAT := SLAT1;
  11566.          TLON := SLON1;
  11567.          IF IDNR = DAY Then
  11568.             EHTN := EHTD;
  11569.             FHTN := FHTD;
  11570.             EHTD := EHT;
  11571.             FHTD := FHT;
  11572.          Else
  11573.             EHTN:=EHT;
  11574.             FHTN:=FHT;
  11575.          End If;
  11576.          Return;
  11577.       Else
  11578.          NEHOPS := IHFMD(NMODE,1);
  11579.          NFHOPS := IHFMD(NMODE,2);
  11580.          KA     := IHFMD(NMODE,6);
  11581.          KB     := IHFMD(NMODE,7);
  11582.          EHANG := EFDATA(1,KA,KB);
  11583.          FHANG := EFDATA(2,KA,KB);
  11584.          SECE  := EFDATA(4,KA,KB);
  11585.          SECF  := EFDATA(5,KA,KB);
  11586.          If IDNT = NIGHT Then  --WORK FROM THE TRANSMITTER TO THE RECEIVER 
  11587.                                --STARTING WITH F MODES.
  11588.             TLATX := TLAT;
  11589.             TLONX := TLON;
  11590.             DUMA := RADIUS_OF_EARTH_IN_KM*FHANG*FLOAT(NFHOPS)*2.0;
  11591.             NODELOC.LOCNEW (TLATX, TLONX, TRBRNG, DUMA, RLATX, RLONX);
  11592.             SLAT1 := RLAT;
  11593.             SLON1 := RLON;
  11594.             RLAT := RLATX;
  11595.             RLON := RLONX;
  11596.             HF_ATMOSPHERICS.IONDAT (1, NFHOPS, DUMA, DUMB, FOEMAX, FOEMIN,
  11597.                                        FOFMAX, FOFMIN);
  11598.             RLAT := SLAT1;
  11599.             RLON := SLON1;
  11600.             FMAXF := FOFMIN*SECF;
  11601.             FMIN := FOEMAX*SECE;
  11602.             SLAT1 := TLAT;
  11603.             SLON1 := TLON;
  11604.             TLAT := RLATX;
  11605.             TLON := RLONX;
  11606.             HF_ATMOSPHERICS.IONDAT (1, NEHOPS, DUMA, DUMB, FOEMAX, FOEMIN, 
  11607.                                        FOFMAX, FOFMIN);
  11608.             TLAT := SLAT1;
  11609.             TLON := SLON1;
  11610.             FMAXE := FOEMIN*SECE;
  11611.          Else --TRANSMITTER IS IN DAYLIGHT, WORK FROM THE RECEIVER
  11612.               --TO THE TRANSMITTER STARTING WITH F MODES.
  11613.             TLATX := RLAT;
  11614.             TLONX := RLON;
  11615.             DUMA := RADIUS_OF_EARTH_IN_KM*FHANG*FLOAT(NFHOPS)*2.0;
  11616.             NODELOC.LOCNEW (TLATX, TLONX, RTBRNG, DUMA, RLATX, RLONX);
  11617.             SLAT1 := TLAT;
  11618.             SLON1 := TLON;
  11619.             SLAT2 := RLAT;
  11620.             SLON2 := RLON;
  11621.             TLAT := TLATX;
  11622.             TLON := TLONX;
  11623.             RLAT := RLATX;
  11624.             RLON := RLONX;
  11625.             HF_ATMOSPHERICS.IONDAT (1, NFHOPS, DUMA, DUMB, FOEMAX, FOEMIN, 
  11626.                                        FOFMAX, FOFMIN);
  11627.             FMAXF := FOFMIN*SECF;
  11628.             FMIN := FOEMAX*SECE;
  11629.             TLAT := RLAT;
  11630.             TLON := RLON;
  11631.             RLAT := SLAT1;
  11632.             RLON := SLON1;
  11633.             HF_ATMOSPHERICS.IONDAT (1, NEHOPS, DUMA, DUMB, FOEMAX, FOEMIN, 
  11634.                                        FOFMAX, FOFMIN);
  11635.             TLAT := SLAT1;
  11636.             TLON := SLON1;
  11637.             RLAT := SLAT2;
  11638.             RLON := SLON2;
  11639.             FMAXE := FOEMIN*SECE;
  11640.          End If;
  11641. --
  11642.          FMAX := AMIN1(FMAXF, FMAXE);
  11643.          FMIN := AMAX1(FMIN, 0.0);
  11644.       End If;
  11645. --
  11646.       Return;
  11647. --
  11648.       End MMMUF;
  11649. --
  11650. --
  11651.       Procedure MF_HF_HANDLER is
  11652. --
  11653. --#PURPOSE: MF_HF_HANDLER computes the signal strength at a receiver location
  11654. --          for HF links.
  11655. --
  11656. --#AUTHOR:  J. Conrad
  11657. --
  11658. --#TYPE:    Numerical Analysis
  11659. --
  11660. --#PARAMETER DESCRIPTIONS:
  11661. --IN        CURRENT_TIME  = Scenario time in minutes from reference time
  11662. --IN        TLAT   = Transmitter latitude in degrees north
  11663. --IN        TLON   = Transmitter longitude in degrees east
  11664. --IN        TALT   = Transmitter altitude in kilometers
  11665. --IN        RLAT   = Receiver latitude in degrees north
  11666. --IN        RLON   = Receiver longitude in degrees east
  11667. --IN        RALT   = Receiver altitude in kilometers
  11668. --IN        FREQMC = Frequency in MHz
  11669. --IN        TERP   = Transmitter power in dBW
  11670. --OUT       SIGNAL = Signal strength at receiver in dBW
  11671. --
  11672. --#CALLED BY:
  11673. --          RF_PROPAGATION_HANDLER
  11674. --
  11675. --#CALLS TO:
  11676. --          DNTR
  11677. --          EFMODE
  11678. --          GNDCON
  11679. --          HFGL
  11680. --          HFGSIG
  11681. --          HFNACP
  11682. --          IONCAL
  11683. --          IONDAT
  11684. --          LOCNEW
  11685. --          MMMUF
  11686. --          ZENITH
  11687. --
  11688. --#TECHNICAL DESCRIPTION:
  11689. --     MF_HF_HANDLER is the RF propagation prediction routine for HF (3-30 MHz
  11690. --     electromagnetic waves. This routine computes the signal strength
  11691. --     at a receiver location based on E-layer, F-layer as well as mixed
  11692. --     E and F-layer modes.
  11693. --
  11694. --     Upon entry, MF_HF_HANDLER first determines the path length that
  11695. --     is in daylight and the length that is in night. In addition, it
  11696. --     determines whether the transmitter and/or receiver is in daylight
  11697. --     or in night. It then initializes certain variables prior to the
  11698. --     initial computations and begins the computations for the heights
  11699. --     of the E and F-layers. The viable modes are determined next based
  11700. --     on geometrical considerations. MF_HF_HANDLER next determines whether 
  11701. --     the frequency is in an acceptable band, thereby determining the
  11702. --     viable modes.
  11703. --
  11704. --     Once the viable modes are known, the solar zenith angle at the
  11705. --     path midpoint is computed as is the local time of day at path
  11706. --     midpoint. The ambient absorption index is set based on those
  11707. --     midpoint values of solar zenith angle and time. The transmitter's
  11708. --     effective radiated power is computed next based on the actual
  11709. --     transmitter power and considering that it is radiated into
  11710. --     an angle of 4*PI and considering the frequency.
  11711. --
  11712. --     The locations of the absorption control points are next computed,
  11713. --     followed by the reflection losses based on ground conductivity
  11714. --     at the ACP's. The total link signal strength is now computed
  11715. --     based on the radiated power minus the losses due to free space,
  11716. --     D-region absorption and reflection losses. Finally, the strength
  11717. --     of the groundwave signal is computed. The returned signal
  11718. --     strength is the maximum of the skywave modes and the groundwave
  11719. --     signals.
  11720. --
  11721.       NP, LEND, N, I, J, NHOPS, LSTRT, NHR, L, KA, KB: integer;
  11722.       IPASS, NMODE, NEHOPS, IYEFD, IZEFD, NFHOPS, IDUMA, LA, LB, IL: integer;
  11723.       IDN: DAY_OR_NIGHT;
  11724.       GGFREQ, TREFSE, EHT, FHT, DUMA, DUMB, DUMC, DUMD: float;
  11725.       EHTD, FHTD, EHTN, FHTN, SECE, FOEMAX, FOEMIN, FOFMAX: float;
  11726.       FOFMIN, ALPF, RADANG, AEDF, C, THETAE, FMAX, FMIN, HAFPL: float;
  11727.       HAFLAT, HAFLON, TODM, AI, P622, SIGMA, DUMX, DUMY, SUM: float;
  11728.       HANGLE, SIGMAT, SIGMAR, CONST, SECF: float;
  11729.       EN, PN, VEAIR, VIAIR: ELF_LF_HF_ATMOSPHERICS.IONO_LAYERS;
  11730. --
  11731.       Begin
  11732. --
  11733. --NP IS THE NUMBER OF MODES INCLUDED IN THE CALCULATIONS.
  11734.       NP := 20;
  11735.       If IHFMD(10,5) <= 1 Then
  11736.          LEND:=0;
  11737.          For N in 1..NP Loop
  11738.             I := IHFMD(N,1);
  11739.             J := IHFMD(N,2);
  11740.             NHOPS := I + J;
  11741.             LSTRT := LEND + 1;
  11742.             LEND := 2*NHOPS + LSTRT - 1;
  11743.             IHFMD(N,3) := NHOPS;
  11744.             IHFMD(N,4) := LSTRT;
  11745.             IHFMD(N,5) := LEND;
  11746.             IHFMD(N,6) := I + 1;
  11747.             IHFMD(N,7) := J + 1;
  11748.          End Loop;
  11749.       End If;
  11750. --
  11751. --DETERMINE THE PATH LENGTH THAT IS IS DAYLIGHT, THE PATH LENGTH
  11752. --THAT IS IN NIGHT, AND WHETHER THE TRANSMITTER AND RECEIVER ARE
  11753. --IN DAY OR NIGHT.
  11754.       RFUTIL.DNTR;
  11755. --
  11756. --CALCULATE TOTAL TRANSMITTER TO RECEIVER SURFACE DISTANCE.
  11757.       PL := DISTOT;
  11758. --
  11759. --SET SELECT CONSTANTS AND INITIALIZE SELECT VARIABLES FOR START OF 
  11760. --CALCULATIONS.
  11761. --  GGFREQ IS GYRO FREQUENCY.
  11762. --  TREFSE IS "REFERENCE_TIME" CONVERTED TO SECONDS.
  11763. --  SIGMAT IS THE SURFACE CONDUCTIVITY AT THE TRANSMITTER.
  11764. --  SIGMAR IS THE SURFACE CONDUCTIVITY AT THE RECEIVER.
  11765.       GGFREQ := 1.5;
  11766.       SIGNAL := -1000.0;
  11767.       GRSIG := -1000.0;
  11768.       NHR := INTEGER(REFERENCE_TIME/100.0);
  11769.       TREFSE := (REFERENCE_TIME - FLOAT(NHR)*40.0)*60.0;
  11770. NEW_LINE;
  11771.       RFUTIL.GNDCON (TLAT, TLON, SIGMAT);
  11772.       RFUTIL.GNDCON (RLAT, RLON, SIGMAR);
  11773.       For N in 1..NP Loop
  11774.          ALOS(N)    := 0.0;
  11775.          FMX(N)     := 0.0;
  11776.          FMN(N)     := 0.0;
  11777.          GRANT(N)   := 0.0;
  11778.          GTANT(N)   := 0.0;
  11779.          IHFMD(N,8) := 0;
  11780.          IHFMD(N,9) := 0;
  11781.          NSUCC(N)   := 0;
  11782.          PLNA(N)    := 0.0;
  11783.          PLOSS(N)   := -3000.0;
  11784.          RELHF(N)   := 0.0;
  11785.          SECACP(N)  := 0.0;
  11786.          SIGPWR(N)  := -3000.0;
  11787.          SPLHF(N)   := 0.0;
  11788.       End Loop;
  11789.       GRANT(21) := 0.0;
  11790.       GTANT(21) := 0.0;
  11791.       For L in 1..140 Loop
  11792.          ACPLAT(L) := 0.0;
  11793.          ACPLON(L) := 0.0;
  11794.          ACPABS(L) := 0.0;
  11795.       End Loop;
  11796. --
  11797. --DETERMINE THE APPROPRIATE E & F LAYER HEIGHTS.
  11798. --
  11799.       If IDNT /= IDNR Then  
  11800.          MMMUF (1, 1, 1, EHTD, EHTN, FHTD, FHTN, DUMA, DUMB);
  11801.       Else
  11802.          HF_ATMOSPHERICS.IONDAT (1, 1, EHT, FHT, DUMA, DUMB, DUMC, DUMD);
  11803.          EHTD := 0.0;
  11804.          FHTD := 0.0;
  11805.          EHTN := EHT;
  11806.          FHTN := FHT;
  11807.          If IDNT = DAY and IDNR = DAY Then
  11808.              EHTD := EHTN;
  11809.              FHTD := FHTN;
  11810.              EHTN := 0.0;
  11811.              FHTN := 0.0;
  11812.          End If;
  11813.       End If;
  11814. --
  11815. --DETERMINE THE VIABLE MODES BASED ON GEOMETRY ONLY.
  11816. --
  11817.       EFMODE (EHTD, EHTN, FHTD, FHTN);
  11818. --
  11819. --FILL IHFMD COLUMN 8 WITH A 1 IF THE MODE CAN EXIST BASED ON GEOMETRY 
  11820. --CONSIDERATIONS ONLY.
  11821. --
  11822.       For I in 1..NP Loop
  11823.          KA := IHFMD(I,6);
  11824.          KB := IHFMD(I,7);
  11825.          If EFDATA(3,KA,KB) > 1.0E-10 Then
  11826.             IHFMD(I,8) := 1;
  11827.          End If;
  11828.       End Loop;
  11829. --
  11830. --DETERMINE IF THE FREQUENCY IS IN AN ACCEPTABLE BAND FOR THE MODE.
  11831. --       IF THE MODE CAN NOT EXIST DUE TO PURELY GEOMETRIC
  11832. --            REASONS, DO NOT CALCULATE THE MAX/MIN FREQUENCIES.
  11833. --       STOP AFTER THE FIRST SUCCESSFUL MODE OF EACH OF THE THREE TYPES.
  11834. --
  11835. --DO E MODES.
  11836. --
  11837.       IPASS := 0;
  11838. --
  11839.       For NMODE in 1..5 Loop
  11840.          If IHFMD(NMODE,8) >= 1 Then
  11841.             IPASS   := IPASS + 1;
  11842.             NEHOPS  := IHFMD(NMODE,1);
  11843.             IYEFD   := IHFMD(NMODE,6);
  11844.             IZEFD   := IHFMD(NMODE,7);
  11845.             SECE    := EFDATA(4,IYEFD,IZEFD);
  11846.             HF_ATMOSPHERICS.IONDAT (IPASS, NEHOPS, DUMA, DUMB,
  11847.                     FOEMAX, FOEMIN, FOFMAX, FOFMIN);
  11848.             FMX(NMODE) := FOEMIN*SECE;
  11849.             If FREQMC <= FMX(NMODE) Then
  11850.                IHFMD(NMODE,9) := 1;
  11851.                Exit;
  11852.             End If;
  11853.          End If;
  11854.       End Loop;
  11855. --
  11856. --DO F MODES.
  11857. --
  11858.       CONST := (RADIUS_OF_EARTH_IN_KM + 340.0)/(RADIUS_OF_EARTH_IN_KM + 110.0);
  11859.       For NMODE in 6..10 Loop
  11860.          IF IHFMD(NMODE,8) >= 1 Then
  11861.             IPASS  := IPASS + 1;
  11862.             NFHOPS := IHFMD(NMODE,2);
  11863.             IYEFD  := IHFMD(NMODE,6);
  11864.             IZEFD  := IHFMD(NMODE,7);
  11865.             ALPF   := EFDATA(2,IYEFD,IZEFD);
  11866.             RADANG := EFDATA(3,IYEFD,IZEFD);
  11867.             SECF   := EFDATA(5,IYEFD,IZEFD);
  11868.             DUMB   := HALFPI - ALPF - RADANG;
  11869.             DUMC   := AMIN1(0.9999, CONST*SIN(DUMB));
  11870.             THETAE := ASIN(DUMC);
  11871.             SECE   := 1.0/COS(THETAE);
  11872.             HF_ATMOSPHERICS.IONDAT (IPASS, NFHOPS, DUMA, DUMB,
  11873.                     FOEMAX, FOEMIN, FOFMAX, FOFMIN);
  11874.             FMAX   := FOFMIN*SECF;
  11875.             FMIN   := FOEMAX*SECE;
  11876.             FMX(NMODE) := FMAX;
  11877.             FMN(NMODE) := FMIN;
  11878.             If FREQMC >= FMIN and FREQMC <= FMAX Then
  11879.                IHFMD(NMODE,9) := 1;
  11880.                Exit;
  11881.             End If;
  11882.          End If;
  11883.       End Loop;
  11884. --
  11885. --DO MIXED MODES.
  11886. --
  11887.       If IDNT /= IDNR Then
  11888.          IPASS := 0;
  11889. --
  11890.          For N in 11..20 Loop
  11891.             NMODE := N;
  11892.             If IHFMD(NMODE,8) >= 1 Then
  11893.                IPASS := IPASS + 1;
  11894.                MMMUF (IPASS, 2, NMODE, DUMA, DUMB, DUMC, DUMD, FMAX, FMIN);
  11895.                FMX(NMODE) := FMAX;
  11896.                FMN(NMODE) := FMIN;
  11897.                If FREQMC >= FMIN and FREQMC <= FMAX Then
  11898.                   IHFMD(NMODE,9) := 1;
  11899.                   Exit;
  11900.                End If;
  11901.             End If;
  11902.          End Loop;
  11903.       End If;
  11904. --
  11905. --END OF PERMISSIBLE MODE CALCULATIONS.
  11906. --
  11907. --FILL NSUCC WITH THE MODE NUMBERS OF THE SUCCESSFUL MODES.
  11908. --
  11909.       IPASS:=0;
  11910. --
  11911.       For NMODE in 1..NP Loop
  11912.          If IHFMD(NMODE,8) >= 1 and IHFMD(NMODE,9) >= 1 Then
  11913.             IPASS := IPASS + 1;
  11914.             NSUCC(IPASS) := NMODE;
  11915.          End If;
  11916.       End Loop;
  11917. --
  11918. --MAKE THE SKYWAVE SIGNAL CALCULATIONS FOR THE MODES OF INTEREST AS LISTED 
  11919. --IN NSUCC.
  11920. --
  11921. --DETERMINE TIME OF DAY AND SOLAR ZENITH ANGLE, CHI AT THE MIDPOINT.
  11922. --
  11923.       HAFPL := PL*0.5;
  11924.       NODELOC.LOCNEW (TLAT, TLON, TRBRNG, HAFPL, HAFLAT, HAFLON);
  11925.       RFUTIL.ZENITH (HAFLAT, HAFLON, CHI, TODM, IDN);
  11926. --
  11927. --"TODM" IS LOCAL TIME OF DAY AT PATH MIDPOINT, HRS, 0 TO 24.
  11928. --
  11929. --
  11930. --SET THE AMBIENT ABSORBTION INDEX BASED ON ASN AND CHI.
  11931. --
  11932.       AI := 0.01;
  11933.       If CHI < 102.0 Then
  11934.          AI := (1.0 + 0.0037*FLOAT(AVERAGE_SUN_SPOT_NUMBER))*
  11935.                (COS(0.881*RADIANS_PER_DEGREE*CHI))**1.3;
  11936.       End If;
  11937. --
  11938. --SET P622.  F622 IS THE TRANSMITTED POWER (NOT ERP)*WAVELENGTH**2/(4*PI).
  11939.       P622 := 38.5503 + TERP - 10.0*LOG10(FREQMC*FREQMC);
  11940. --
  11941. --SET "AMBAB" BASED ON THE AMBIENT ABSORPTION INDEX.
  11942. --
  11943.       AMBAB := 150.00*AI/((FREQMC + GGFREQ)**2);
  11944. --
  11945. --LOOP OVER THE MODES.
  11946. --
  11947.       For N in 1..NP Loop
  11948.          NMODE := NSUCC(N);
  11949.          Exit When NMODE < 1;
  11950.          NEHOPS := IHFMD(NMODE,1);
  11951.          NFHOPS := IHFMD(NMODE,2);
  11952.          NHOPS  := IHFMD(NMODE,3);
  11953.          LSTRT  := IHFMD(NMODE,4);
  11954.          LEND   := IHFMD(NMODE,5);
  11955.          IYEFD  := IHFMD(NMODE,6);
  11956.          IZEFD  := IHFMD(NMODE,7);
  11957.          RADANG := EFDATA(3,IYEFD,IZEFD);
  11958.  
  11959. --DETERMINE THE FREE SPACE LOSS, TRANSMITTER ANTENNA GAIN, AND RECEIVER 
  11960. --ANTENNA GAIN.
  11961. --
  11962.          HFGL (1, 0, PL, RADANG, SIGMAT);
  11963.          GTANT(NMODE) := GT;
  11964.          HFGL (0, 0, PL, RADANG, SIGMAR);
  11965.          GRANT(NMODE) := GR;
  11966.          SPLHF(NMODE) := SPLOSS;
  11967. --
  11968. --DETERMINE THE LOCATIONS OF THE ABSORPTION CONTROL POINTS (ACP-S).
  11969. --
  11970.          HFNACP (NMODE);
  11971. --
  11972. --DETERMINE THE REFLECTION LOSSES USING THE NEAREST ACP LOCATION FOR 
  11973. --CONDUCTIVITY DETERMINATIONS.
  11974. --
  11975.          LA := LSTRT + 1;
  11976.          LB := LEND - 2;
  11977.          L := LA;
  11978.          While L <= LB Loop
  11979.             DUMA := FAVG(ACPLAT(L), ACPLAT(L+1));
  11980.             DUMB := FAVG(ACPLON(L), ACPLON(L+1));
  11981.             If ABS(DUMB - ACPLON(L)) > 90.0 Then
  11982.                DUMB := DUMB + 180.0;
  11983.             End If;
  11984.             RFUTIL.GNDCON (DUMA, DUMB, SIGMA);
  11985.             HFGL ( 0, 1, PL, RADANG, SIGMA);
  11986.             RELHF(NMODE) := RELHF(NMODE) + RELOSS;
  11987.             L := L + 2;
  11988.          End Loop;
  11989. --
  11990. --COMPUTE PLNA FOR THE MODE.
  11991. --
  11992.          PLNA(NMODE) := SPLHF(NMODE) + RELHF(NMODE);
  11993. --
  11994. --CALCULATE THE ABSORPTION LOSS FOR THIS MODE.
  11995. --
  11996.          DUMX := 1.0/(TWOPI*1.0E6);
  11997.          DUMY := (FREQMC + GGFREQ)**2;
  11998.          IDN := NIGHT;
  11999.          If DISDAY > DISNIT Then
  12000.             IDN := DAY;
  12001.          End If;
  12002.          For L in LSTRT..LEND Loop
  12003.             ELF_LF_HF_ATMOSPHERICS.IONCAL(ACPLAT(L), ACPLON(L), 
  12004.                                    -CURRENT_TIME*60.0, IDN,
  12005.                    EN, PN, VEAIR, VIAIR);
  12006.             SUM := 0.0;
  12007.             For IL in 10..18 Loop
  12008.                DUMA := 7.3E-3*EN(IL)*(VEAIR(IL) + VIAIR(IL))*DUMX;
  12009.                DUMB := DUMY + ((0.775*VEAIR(IL) + VIAIR(IL))*DUMX)**2;
  12010.                DUMA := DUMA/DUMB;
  12011.                SUM := SUM + 5.0*DUMA;
  12012.             End Loop;
  12013.             ACPABS(L) := SUM;
  12014.             ALOS(NMODE) := ALOS(NMODE) + ACPABS(L);
  12015.          End Loop;
  12016.          ALOS(NMODE) := AMAX1(ALOS(NMODE), 2.0*float(NHOPS)*AMBAB);
  12017.          ALOS(NMODE) := ALOS(NMODE)*SECACP(NMODE);
  12018. --
  12019. --CALCULATE THE NET PATH LOSS, PLOSS.
  12020. --
  12021.          PLOSS(NMODE) := PLNA(NMODE) + ALOS(NMODE) 
  12022.                           - GTANT(NMODE) - GRANT(NMODE);
  12023. --
  12024. --SIGNAL POWER IN DBW
  12025.          SIGPWR(NMODE) := P622 - PLOSS(NMODE);
  12026.          SIGNAL := AMAX1(SIGNAL, SIGPWR(NMODE));
  12027.       End Loop;
  12028. --
  12029. -- CALCULATE GROUNDWAVE SIGNAL
  12030.       HFGSIG (PL, SIGMAT, GRSIG);
  12031.       DUMA := ABS(RALT - TALT);
  12032.       DUMA := RADIUS_OF_EARTH_IN_KM/(RADIUS_OF_EARTH_IN_KM + DUMA);
  12033.       HANGLE := 0.5*PL/RADIUS_OF_EARTH_IN_KM;
  12034.       RADANG := FPSI(HANGLE, DUMA);
  12035.       RADANG := AMAX1(0.0,DUMA);
  12036.       HFGL (1, 0, PL, RADANG, SIGMAT);
  12037.       GTANT(21) := GT;
  12038.       HFGL(2, 0, PL, RADANG, SIGMAR);
  12039.       GRANT(21) := GR;
  12040.       GRSIG := GRSIG + GTANT(21) + GRANT(21);
  12041.       SIGNAL := AMAX1(SIGNAL,GRSIG);
  12042. --
  12043.       Return;
  12044. --
  12045.       End MF_HF_HANDLER;
  12046. --
  12047. End MF_HF_PROPAGATION;
  12048. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12049. --LFPROP
  12050. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12051. With Debugger2; Use Debugger2;
  12052. With Mathlib; Use Mathlib, Numeric_primitives, trig_functions, core_functions;
  12053. With Constants; Use Constants;
  12054. With Propagation_Constants; Use Propagation_constants;
  12055. With Nodeloc;
  12056. With ELF_LF_HF_atmospherics;
  12057. With RFUTIL;
  12058. With LF_HF_Groundwaves;
  12059. With Text_IO; Use Text_io, Integer_io, Float_io;
  12060.  
  12061. Package LF_PROPAGATION is
  12062. --
  12063.       Procedure LF_HANDLER;
  12064. --
  12065. End LF_PROPAGATION;
  12066. --
  12067. Package body LF_PROPAGATION is
  12068. --
  12069. -- LF_PROPAGATION Package of PROP_LINK 
  12070. -- Version 1.0,  June 28, 1985.
  12071. --
  12072. -- This LF_PROPAGATION Package contains all of the procedures that 
  12073. -- are used to perform LF propagation prediction.
  12074. --
  12075. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  12076. -- radio frequency propagation prediction code.
  12077. --
  12078. -- PROP_LINK has been developed for the Department of Defense under
  12079. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  12080. -- Systems Inc. (Jim Conrad).
  12081. --
  12082. --Use Text_IO;
  12083. -- Instantiate integer and floating point IO.
  12084. --      Package IO_INTEGER is new INTEGER_IO(INTEGER);
  12085. --      Package IO_FLOAT is new FLOAT_IO(FLOAT);
  12086. --Use IO_INTEGER,IO_FLOAT;
  12087. --
  12088. --
  12089.       Pragma Source_info (on);
  12090. --
  12091. --**************************************************************************
  12092. --VARIABLES THAT ARE TO BE VISIBLE TO ALL ROUTINES WITHIN THIS PACKAGE.
  12093.       PLAT: array (integer range 1..5) of float;
  12094.       PLONG: array (integer range 1..5) of float;
  12095.       COEF: array (integer range 1..5) of float;
  12096.       GAMMA: array (integer range 1..5) of float;
  12097.       BETA: array (integer range 1..5) of float;
  12098.       PALT: array (integer range 1..5) of float;
  12099.       MODFES: array (integer range 1..5) of integer;
  12100. --**************************************************************************
  12101. --
  12102. --
  12103.       Procedure HIGHTF is
  12104. --
  12105. --#PURPOSE: HIGHTF calculates the ionospheric reflection height for
  12106. --          LF propagation.
  12107. --
  12108. --#AUTHOR:  J. Conrad 
  12109. --
  12110. --#TYPE:    Numerical Analysis
  12111. --
  12112. --#PARAMETER DESCRIPTIONS:
  12113. --          'NONE'
  12114. --
  12115. --#CALLED BY:
  12116. --          LF_HANDLER
  12117. --
  12118. --#CALLS TO:
  12119. --          LOCNEW
  12120. --          REFCAL
  12121. --
  12122. --#TECHNICAL DESCRIPTION:
  12123. --          Breaks the ionosphere into layers, determines electron and
  12124. --          positive ion densities, then calculates critical frequency
  12125. --          and the resulting height of reflection.
  12126. --
  12127.       I: integer;
  12128.       DISTPT: float;
  12129. --
  12130.       Begin
  12131. --
  12132.       For I in 1..NHOP Loop
  12133.          DISTPT := DPATH*PTS(I);
  12134.          NODELOC.LOCNEW (TLAT, TLON, BRNG1, DISTPT, PLAT(I), PLONG(I));
  12135.          ELF_LF_HF_Atmospherics.REFCAL (PLAT(I), PLONG(I), -CURRENT_TIME*60.0, 
  12136.                           FREQKC, PALT(I), COEF(I));
  12137.          PALT(I) := PALT(I) + RADIUS_OF_EARTH_IN_KM;
  12138.       End Loop;
  12139. --
  12140.       Return;
  12141. --
  12142.       End HIGHTF;
  12143. --
  12144. --
  12145.       Procedure TERAIN (XLAT: in float;
  12146.                         XLONG: in float;
  12147.                         FREQ: in float;
  12148.                         D: in float;
  12149.                         TLOSS: out float) is
  12150. --
  12151. --
  12152. --#PURPOSE: TERAIN COMPUTES TERRAIN LOSS ON LF GROUNDWAVE PROPAGATION.
  12153. --          THIS IS A ZEROTH ORDER APPROXIMATION OF THE GROUND TERRAIN
  12154. --          IMPACT ON LF GROUNDWAVE WITHIN THE CONUS AREA ONLY. THIS
  12155. --          HAS BEEN DEVELOPED FOR THE PRELIMINARY EVALUATION OF THE
  12156. --          GROUNDWAVE EMERGENCY NETWORK(GWEN).
  12157. --
  12158. --#AUTHOR:  J. Conrad
  12159. --
  12160. --#TYPE:    Numerical Analysis.
  12161. --
  12162. --#PARAMETER DESCRIPTIONS:
  12163. --IN         XLAT   = PATH MIDPOINT IN DEGREES NORTH
  12164. --IN         XLONG  = PATH MIDPOINT IN DEGREES EAST
  12165. --IN         FREQ   = LINK FREQUENCY IN MHZ
  12166. --IN         D      = PATH LENGTH IN KILOMETERS
  12167. --OUT        TLOSS  = PATH LOSS DUE TO TERRAIN ROUGHNESS IN DB
  12168. --
  12169. --#CALLED BY:
  12170. --          LFPROP
  12171. --
  12172. --#CALLS TO:
  12173. --          LOCGRB
  12174. --
  12175. --#TECHNICAL DESCRIPTION:
  12176. --          THIS IS A ZEROTH ORDER APPROXIMATION OF THE GROUND TERRAIN
  12177. --          IMPACT ON LF GROUNDWAVE WITHIN THE CONUS AREA ONLY. THIS
  12178. --          HAS BEEN DEVELOPED FOR THE PRELIMINARY EVALUATION OF THE
  12179. --          GROUNDWAVE EMERGENCY NETWORK(GWEN).  DATA SUPPLIED BY
  12180. --          ROCKWELL-COLLINS.
  12181. --
  12182.       HEIGHT: array (integer range 1..3) of float
  12183.       :=(1000.0, 500.0, 300.0);
  12184.       SEPART: array (integer range 1..3) of float
  12185.       :=(20.0, 20.0, 10.0);
  12186.       IAREA: integer;
  12187.       BRN1, BRN2, RANG: float;
  12188. --
  12189.       Begin
  12190. --
  12191.       TLOSS := 0.0;
  12192. --
  12193. --COMPUTE WHERE THE PATH MIDPOINT LIES.
  12194. --
  12195. --IS THE PATH MIDPOINT IN THE NORTHWEST OR SOUTHWEST CONUS?
  12196. --
  12197.       IAREA := 1;
  12198.       If XLONG > -105.0 Then
  12199.          Goto N_S_CENTRAL;
  12200.       End If;
  12201.       If XLAT <= 45.0 Then
  12202.          Goto COMPUTE;
  12203.       End If;
  12204.       If XLONG <= -110.0 and XLAT >= 45.0 Then
  12205.          Goto COMPUTE;
  12206.       End If;
  12207.       NODELOC.LOCGRB (45.0, -105.0, XLAT, XLONG, BRN1, BRN2, RANG);
  12208.       If BRN1 >= 180.0 and BRN1 < 315.0 Then
  12209.          Goto COMPUTE;
  12210.       End If;
  12211. --
  12212. --  IS THE PATH MIDPOINT IN THE NORTH CENTRAL OR SOUTH CENTRAL CONUS.
  12213. <<N_S_CENTRAL>>
  12214.       If XLONG < -85.0 Then
  12215.          Return;
  12216.       End If;
  12217.       If XLAT < 40.0 Then
  12218.          Goto NEW_ENGLAND;
  12219.       End If;
  12220.       NODELOC.LOCGRB (40.0, -85.0, XLAT, XLONG, BRN1, BRN2, RANG);
  12221.       If BRN1 <= 45.0 Then
  12222.          Return;
  12223.       End If;
  12224. --
  12225. --  IS THE PATH MIDPOINT IN THE NEW ENGLAND STATES?
  12226. <<NEW_ENGLAND>>
  12227.       IAREA := 2;
  12228.       If XLONG >= -75.0 Then
  12229.          Goto COMPUTE;
  12230.       End If;
  12231. --
  12232. --  IS THE PATH MIDPOINT IN GEORGIA OR FLORIDA?
  12233.       If XLAT <= 35.0 and XLONG <= -83.0 Then
  12234.          Return;
  12235.       End If;
  12236.       NODELOC.LOCGRB (35.0, -83.0, XLAT, XLONG, BRN1, BRN2, RANG);
  12237.       If BRN1 >= 135.0 Then
  12238.          Return;
  12239.       End If;
  12240. --
  12241. --  IS THE PATH MIDPOINT IN THE MID-ATLANTIC REGION.
  12242. --
  12243.       IAREA := 3;
  12244. --
  12245. --COMPUTE PATH LOSS DUE TO TERRAIN ROUGHNESS (TLOSS).
  12246. --
  12247. <<COMPUTE>>
  12248.       TLOSS := D*(3.7E-3*HEIGHT(IAREA)*FREQ + 1.65E-5*
  12249.                HEIGHT(IAREA)*HEIGHT(IAREA)*FREQ*FREQ)/
  12250.                SEPART(IAREA);
  12251. --
  12252.       Return;
  12253. --
  12254.       End TERAIN;
  12255. --
  12256.       Procedure LFPROP is
  12257. --
  12258. --#PURPOSE: LFPROP computes the RF signal strength of a LF transmitter
  12259. --          at a receiver location.
  12260. --
  12261. --#AUTHOR:  J. Conrad
  12262. --
  12263. --#TYPE:    NUMERICAL ANALYSIS
  12264. --
  12265. --#PARAMETER DESCRIPTIONS:
  12266. --          'NONE'
  12267. --#CALLED BY:
  12268. --          LF_HANDLER
  12269. --
  12270. --#CALLS TO:
  12271. --          DAYNIT
  12272. --          GNDCON
  12273. --          GRWAVE
  12274. --          LOCNEW
  12275. --          TERAIN
  12276. --
  12277. --#TECHNICAL DESCRIPTION:
  12278. --       At small distances (<500km) from an LF transmitter,the received
  12279. --       signal is predominantly a ground wave. For these distances the
  12280. --       E-field strength add vectorially the first hop skywave and the
  12281. --       groundwave. At greater distances, the signal is due to skywaves
  12282. --       reflected from the ionosphere. If the path length is greater
  12283. --       than 1500km, a RSS of the signals from ray paths with from 1-5
  12284. --       hops plus groundwave is computed. If the distance is greater than
  12285. --       7000km a warning message will be printed but the calculation
  12286. --       will continue.
  12287. --
  12288.       MED: array (integer range 1..2) of integer;
  12289.       RDB: array (integer range 1..2) of float;
  12290.       JJ: array (integer range 1..2) of integer;
  12291.       AFS: array (integer range 1..2) of float;
  12292.       FDN: array (integer range 1..5) of float; 
  12293.       GPTS: array (integer range 1..5) of float
  12294.       :=(0.5, 0.25, 0.3, 0.6, 0.75);
  12295.       CND: array (integer range 1..5) of float; 
  12296.       EEO: array (integer range 1..6) of float; 
  12297.       SGR:array (integer range 1..5, integer range 1..5) of float
  12298.       :=((0.0,0.0,0.0,0.0,0.0),
  12299.          (0.0,0.0,0.0,0.0,0.0),
  12300.          (0.0,0.0,0.0,0.0,0.0),
  12301.          (0.0,0.0,0.0,0.0,0.0),
  12302.          (0.0,0.0,0.0,0.0,0.0));
  12303.       GDB: array (integer range 1..5) of float;  
  12304.       INDX: array (integer range 1..4, integer range 1..4) of integer
  12305.       :=((1, 0, 0, 0),
  12306.          (3, 4, 0, 0),
  12307.          (1, 2, 5, 0),
  12308.          (2, 3, 4, 5));
  12309. --
  12310. --THE FOLLOWING DATA STATEMENTS
  12311. --  SPECIFY THE CONSTANTS FOR PIECEWISE LINEAR FITS TO
  12312. --  CCIR DATA.
  12313. --
  12314. --  FOR PARAMETERS WHICH ARE FUNCTIONS OF FREQUENCY, THE FOLLOWING
  12315. --  PIECEWISE LINEAR FORM IS USED
  12316. --  X(F) := X(FF(I)) + XD(I)*(F - FF(I))   WHERE X IS THE FUNCTION
  12317. --  BEING DETERMINED,  FF IS A SET OF FREQUENCY BREAKPOINTS FOR THE
  12318. --  PARAMETER X,  FF(I) IS THE LARGEST BREAKPOINT LESS THAN F, AND
  12319. --  XD (:=(X(FF(I+1))-X(FF(I)))/(FF(I+1)-FF(I)) )  IS GIVEN AS A SET
  12320. --  CONSTANTS.
  12321. --
  12322. --  CONSTANTS FOR ANTENNA FACTORS - PIECEWISE FITS TO CCIR DATA (REPT
  12323. --  PP 159-160)
  12324.       FAF: array (integer range 1..4) of float 
  12325.       := (20.0, 50.0, 100.0, 200.0);
  12326. --
  12327. --  DATA FITS GOOD TO 500 KHZ.
  12328. --
  12329. --  SEA WATER.
  12330. --      -LOG AF := 0.                    PSI  GT  5.
  12331. --              := A(F)*(5. - PSI)**2  -2.5  LT  PSI  LT  5.
  12332. --              := B(F) - C(F)*PSI     PSI  LT  -2.5
  12333.       AFSA: array (integer range 1..4) of float
  12334.       :=(5.35E-3, 6.00E-3, 7.07E-3, 8.33E-3);
  12335.       AFSAD: array (integer range 1..4) of float
  12336.       :=(2.167E-5, 2.14E-5, 1.26E-5, 0.593E-5);
  12337.       AFSB: array (integer range 1..4) of float
  12338.       :=(0.0825, 0.035, 0.042, -0.019);
  12339.       AFSBD: array (integer range 1..4) of float
  12340.       :=(-1.583E-3, 1.4E-4, -6.1E-4, 4.4E-4);
  12341.       AFSC: array (integer range 1..4) of float
  12342.       :=(0.0785, 0.110, 0.135, 0.181);
  12343.       AFSCD: array (integer range 1..4) of float
  12344.       :=(1.05E-3, 0.5E-3, 0.46E-3, 0.293E-3);
  12345. --
  12346. --  LAND.
  12347. --     -LOG AF := A(F)                     PSI  GT  10.
  12348. --             := A(F) + B(F)*(10-PSI)**2  -2.5 LT PSI LT 10 AND F LT 100
  12349. --             := A(F) + B(F)*(10-PSI)**3  -2.5 LT PSI LT 10 AND F GT 100
  12350. --             := C(F) + D(F)*PSI        PSI  LT  -2.5
  12351. --
  12352.       AFLA : array (integer range 1..4) of float
  12353.       :=(0.036, 0.051, 0.0915, 0.137); 
  12354.       AFLAD: array (integer range 1..4) of float 
  12355.       :=(5.0E-4, 8.1E-4, 4.55E-4, 2.7E-4);
  12356.       AFLB: array (integer range 1..4) of float 
  12357.       :=(1.86E-3, 2.68E-3, 3.52E-4, 5.41E-4);
  12358.       AFLBD: array (integer range 1..4) of float 
  12359.       :=(2.733E-5, 1.68E-5, 1.89E-6, 4.23E-7);
  12360.       AFLC: array (integer range 1..4) of float 
  12361.       :=(0.1255, 0.1835, 0.189, 0.188);
  12362.       AFLCD: array (integer range 1..4) of float 
  12363.       :=(1.933E-3, 1.1E-4, -1.0E-5, 1.367E-3);
  12364.       AFLD: array (integer range 1..4) of float 
  12365.       :=(-0.0767, -0.1075, -0.186, -0.333);
  12366.       AFLDD: array (integer range 1..4) of float 
  12367.       :=(-1.0267E-3, -1.57E-3, -1.47E-3, -5.067E-3);
  12368. --
  12369. --CONSTANTS FOR IONOSPHERIC FOCUSSING FACTORS  -  PIECEWISE FITS TO
  12370. --  CCIR DATA (REPORT 265-2, PP 157-156)
  12371. --
  12372.       FFDN: array (integer range 1..4) of float
  12373.       :=(20.0, 50.0, 100.0, 150.0);
  12374. --
  12375. --  DATA FITS GOOD TO 200 KHZ.
  12376. --
  12377. --  DAYTIME.
  12378. --       FD := 1. + A*X + B*X**2             X  LT  1000
  12379. --          := C + D*X + E(F)*(X-800)**2     1000  LT  X  LT  1700
  12380. --          := F(F)                          1700  LT  X  LT  1900
  12381. --          := G(F) + H*X                    X  GT  1900
  12382. --  WHERE X IS DISTANCE PER HOP.
  12383. --
  12384.       FDA: float := -2.0E-5;
  12385.       FDB: float := 4.0E-7;
  12386.       FDC: float := 0.927;
  12387.       FDD: float := 4.33E-4;
  12388.       FDH: float := 4.8E-4;
  12389.       FDE: array (integer range 1..4) of float
  12390.       :=(0.0, 2.97E-7, 5.94E-7, 7.5E-7);
  12391.       FDED: array (integer range 1..4) of float 
  12392.       :=(9.9E-9, 5.94E-9, 3.21E-9, 2.50E-9);
  12393.       FDF: array (integer range 1..4) of float 
  12394.       :=(1.64, 1.89, 2.11, 2.25);
  12395.       FDFD: array (integer range 1..4) of float 
  12396.       :=(8.33E-3, 4.4E-3, 2.8E-3, 2.6E-3);
  12397.       FDG: array (integer range 1..4) of float 
  12398.       :=(0.724, 1.014, 1.264, 1.434);
  12399.       FDGD: array (integer range 1..4) of float 
  12400.       :=(9.67E-3, 5.0E-3, 3.4E-3, 2.2E-3);
  12401. --
  12402. --  NIGHTTIME.
  12403. --     FN := 1. + A*X + B* X**2                  X  LT  1000.
  12404. --        := C + D*X + E(F)*(X-1000)**2          1000  LT  X  LT  1900
  12405. --        := F(F)                                1900  LT  X  LT  2100
  12406. --        := G(F) + H*X                          X  GT  2100
  12407. --  WHERE X IS DISTANCE PER HOP AND FREQ IS FREQUENCY.
  12408. --
  12409.       FNA: float := 3.0E-6;
  12410.       FNB: float := 0.26E-6;
  12411.       FNC: float := 0.79;
  12412.       FND: float := 5.0E-4;
  12413.       FNH: float := 0.00053;
  12414.       FNE: array (integer range 1..4) of float 
  12415.       :=(0.0, 3.44E-7, 6.41E-7, 7.97E-7);
  12416.       FNED: array (integer range 1..4) of float 
  12417.       :=(1.143E-8, 5.84E-9, 3.12E-9, 1.56E-9);
  12418.       FNF: array (integer range 1..4) of float 
  12419.       :=(1.72, 2.00, 2.26, 2.39);
  12420.       FNFD: array (integer range 1..4) of float 
  12421.       :=(0.00967, 0.0052, 0.0026, 0.0022);
  12422.       FNG: array (integer range 1..4) of float 
  12423.       :=(0.585, 0.885, 1.155, 1.325);
  12424.       FNGD: array (integer range 1..4) of float 
  12425.       :=(0.01, 0.0054, 0.0034, 0.0024);
  12426. --
  12427.       I, ITIM, ISOLC, ISOL, ITR, IAF, JDN, NPASS, K, IND, NHOPP1, J: integer;
  12428.       FLOG, Z, GA, GT, GR, RORO, XMI, D1, PSI: float;
  12429.       DF, PSID, AF, X, CONDT, CONDR: float;
  12430.       Y, EO, ANSN, PLSAV, HHIGHR, HLOWER, HTEMP, GRLOSS, CONDUC: float;
  12431.       TLOSS, S, THETA, CTHETA, PATH, SID1, SID2, SID5, SID3, SID4: float;
  12432.       PLOSS, REFLOS, REFION, ANS, SS, SSVOLT, SQUARE, DRADNS, DISTGP: float;
  12433.       XGVOLT, RRVOLT, XRVOLT, YRVOLT, XSUM, VOLTSM: float;
  12434.       XLAT, XLON, EEOTEMP: float;
  12435.       IDANIT: DAY_OR_NIGHT;
  12436. --
  12437.       Begin
  12438. --
  12439. --INITIALIZE SIGNAL STRENGTH ARRAY TO ZERO
  12440.       For I in 1..6 Loop
  12441.          EEO(I) := 0.0;
  12442.       End Loop;
  12443. --
  12444. --SET THE SEASON "ITIM" BASED ON MONTH
  12445.       If MONTH = 12 or MONTH = 1 or MONTH = 2 Then
  12446.          ITIM := 2;
  12447.       Elsif MONTH = 3 or MONTH = 4 or MONTH = 5 or 
  12448.             MONTH = 9 or MONTH = 10 or MONTH = 11 Then
  12449.          ITIM := 3;
  12450.       Elsif MONTH = 6 or MONTH = 7 or MONTH = 8 Then
  12451.          ITIM := 4;
  12452.       End If;
  12453. --
  12454. --COMPUTE THE SOLAR CYCLE "ISOL" (1 = MAXIMUM, 2 = MINIMUM)
  12455.       ISOLC := INTEGER(FLOAT(AVERAGE_SUN_SPOT_NUMBER)*0.025);
  12456.       If ISOLC > 1 Then
  12457.          ISOLC := 1;
  12458.       End If;
  12459.       ISOL := 2 - ISOLC;
  12460. --
  12461. --MAKE SURE THAT ANTENNA TYPE IS PROPER & IF NOT DEFAULT TO LOOP TYPE
  12462.       If IATYPT >= 3  Then
  12463.          IATYPT := 1;
  12464.       End If;
  12465. --
  12466. --HEIGHT GAIN FACTORS.
  12467. --
  12468. --  GAIN FACTOR DATA IS FROM VLF RADIO ENGINEERING, FIG. 3.2.10, P 190.
  12469. --
  12470. --  SEA
  12471. --     G := 0
  12472. --
  12473. --  LAND
  12474. --     G := 0                            ALT  LT  Z(F)
  12475. --       := A(F)*LOG(ALT/Z(F))         ALT  GT  Z(F)
  12476. --  WHERE ALT IS ALTITUDE OF ANTENNA AND FREQ IS FREQUENCY.
  12477. --        Z(F) := 11.75 -4.67*LOG FREQKC
  12478. --        A(F) := 16.38*LOG FREQKC  -16.26
  12479. --  HOWEVER G IS NOT ALLOWED TO EXCEED 30 DB.
  12480. --
  12481. --  FIRST COMPUTE THE REFLECTION MEDIUM AT THE TRANSMITTER AND RECEIVER
  12482.       MED(1) := 1;
  12483.       RFUTIL.GNDCON (TLAT, TLON, CONDT);
  12484.       If CONDT > 0.05 Then
  12485.          MED(1) := 2;
  12486.       End If;
  12487.       MED(2) := 1;
  12488.       RFUTIL.GNDCON (RLAT, RLON, CONDR);
  12489.       If CONDR > 0.05 Then
  12490.          MED(2) := 2;
  12491.       End If;
  12492. --
  12493. --  NOW THE GAIN FUNCTIONS
  12494.       FLOG := LOG10(FREQKC);
  12495.       Z := 11.75 - 4.67*FLOG;
  12496.       GA := 16.38*FLOG - 16.26;
  12497.       GT := 0.0;
  12498.       If MED(1) /= 2 and TALT >= Z Then
  12499.          GT := GA*LOG10(TALT/Z);
  12500.          If GT > 30.0 Then
  12501.             GT := 30.0;
  12502.          End If;
  12503.       End If;
  12504.       GR := 0.0;
  12505.       If MED(2) /= 2 and RALT >= Z Then
  12506.          GR := GA*LOG10(RALT/Z);
  12507.          If GR > 30.0 Then
  12508.             GR := 30.0;
  12509.          End If;
  12510.       End If;
  12511. --
  12512. --GT, GR ARE THE HEIGHT GAIN FACTORS (IN DB) FOR THE TRANS AND REC.
  12513. --
  12514.       RORO := (RADIUS_OF_EARTH_IN_KM)**2;
  12515. --
  12516. --PROPAGATION CALCULATIONS.
  12517.       For I in 1..NHOP Loop
  12518.          XMI := FLOAT(I);
  12519.          D1 := DPATH/XMI;
  12520.          PSI := BETA(I) - HALFPI;
  12521. --
  12522. --PSI IS THE ELEVATION ANGLE.
  12523.          GDB(I) := float(IATYPT)*20.0*LOG10(COS(PSI));
  12524. --
  12525. --COMPUTE ANTENNA FACTOR, AF.
  12526.          For ITR in 1..2 Loop
  12527.              For J in 2..5 Loop
  12528.                 IAF := J;
  12529.                 Exit When FREQKC < FAF(IAF) or IAF = 5;
  12530.              End Loop;
  12531.              IAF := IAF - 1;
  12532.              DF := FREQKC - FAF(IAF);
  12533.              PSID := PSI*DEGREES_PER_RADIAN;
  12534. --
  12535. --IS TRANSMITTER/RECEIVER ON LAND (MED = 1) OR SEA (MED = 2)?
  12536.              IF MED(ITR) = 1 Then
  12537.                 If PSID >= 10.0 Then
  12538.                    AF := AFLA(IAF) + AFLAD(IAF)*DF;
  12539.                 Elsif PSID <= -2.5 Then
  12540.                    AF := (AFLC(IAF) + AFLCD(IAF)*DF) + PSID*(AFLD(IAF)
  12541.                          + AFLDD(IAF)*DF);
  12542.                 Elsif IAF > 2 Then
  12543.                    AF := (AFLA(IAF) + AFLAD(IAF)*DF) + (AFLB(IAF)
  12544.                          + AFLBD(IAF)*DF)*((10.0 - PSID)**3);
  12545.                 Else 
  12546.                    AF := (AFLA(IAF) + AFLAD(IAF)*DF) + (AFLB(IAF) +
  12547.                          AFLBD(IAF)*DF)*((10.0 - PSID)**2);
  12548.                 End If;
  12549.              Else
  12550.                 If PSID >= 5.0 Then
  12551.                   AF := 0.0;
  12552.                 Elsif PSID <= -2.5 Then
  12553.                   AF := (AFSB(IAF) + AFSBD(IAF)*DF) - PSID*(AFSC(IAF) +
  12554.                         AFSCD(IAF)*DF);
  12555.                 Else
  12556.                    AF := (AFSA(IAF) + AFSAD(IAF)*DF)*((PSID - 5.0)**2);
  12557.              End If;
  12558.           End If;
  12559.           AFS(ITR) := AF;
  12560.       End Loop;
  12561. --
  12562. --AFS GIVES THE FOCUSSING FACTORS FOR THE ANTENNAE (-DB/20)  (1 IS THE
  12563. --  TRANSMITTER, 2 IS RECEIVER).
  12564. --
  12565. --  IONOSPHERIC FOCUSSING FACTOR.
  12566. --
  12567.          For J in 2..5 Loop
  12568.             JDN := J;
  12569.             Exit When FREQKC < FFDN(JDN) or JDN = 5;
  12570.          End Loop;
  12571.          JDN := JDN - 1;
  12572.          DF := FREQKC - FFDN(JDN);
  12573.          RFUTIL.DAYNIT (IDANIT, PLONG(I), PLONG(I));
  12574.          If IDANIT = DAY Then
  12575. --
  12576. --FD IS THE DAYTIME IONOSPHERIC FOCUSING FACTOR.
  12577.             If D1 <= 1000.0 Then
  12578.                FDN(I) := 1.0 + FDA*D1 + FDB*(D1**2);
  12579.             Elsif D1 <= 1700.0 Then
  12580.                FDN(I) := FDC + FDD*D1 + (FDE(JDN) + FDED(JDN)*DF) *
  12581.                         ((D1 - 800.0)**2);
  12582.             Elsif D1 <= 1900.0 Then
  12583.                FDN(I) := FDF(JDN) + FDFD(JDN)*DF;
  12584.             Else
  12585.                FDN(I) := (FDG(JDN) + FDGD(JDN)*DF) + FDH*D1;
  12586.             End If;
  12587. --
  12588. --FN IS THE NIGHTIME IONOSPHERIC FOCUSING FACTOR.
  12589.          Else
  12590.             If D1 <= 1000.0 Then
  12591.                FDN(I) := 1.0 + FNA*D1 + FNB*(D1**2);
  12592.             Elsif D1 <= 1900.0 Then
  12593.                FDN(I) := FNC + FND*D1 + (FNE(JDN) + FNED(JDN)*DF) *
  12594.                         ((D1 - 1000.0)**2);
  12595.             Elsif D1 <= 2100.0 Then
  12596.                FDN(I) := FNF(JDN) + FNFD(JDN)*DF;
  12597.             Else
  12598.                FDN(I) := (FNG(JDN) + FNGD(JDN)*DF) + FNH*D1;
  12599.             End If;
  12600.          End If;
  12601. --
  12602. --FDN(I) IS THE IONOSPHERIC FOCUSSING FACTOR.
  12603. --
  12604.          FDN(I) := 20.0*LOG10(FDN(I));
  12605. --
  12606. --GROUND REFLECTION FACTORS.
  12607. --  TECHNIQUE:  PARTIALLY FILL ARRAY OF (NHOPS,REFLECTION POINTS).
  12608. --
  12609.          If I /= 1 Then
  12610.             NPASS := I - 1;
  12611.             For K in 1.. NPASS Loop
  12612. --
  12613. --  CALCULATE SGR(I,K).
  12614.                X := ABS(SIN(PSI));
  12615.                If X < 1.0E-04 Then
  12616.                   X := 1.0E-04;
  12617.                End If;
  12618.                X := LOG10(X);
  12619. --
  12620. --  COMPUTE LOCATIONS AND CONDUCTIVITY AT GROUND REFLECTIONS.
  12621.                IND := INDX(NPASS, K);
  12622.                DISTGP := DPATH*GPTS(IND);
  12623.                NODELOC.LOCNEW (TLAT, TLON, BRNG1, DISTGP, XLAT, XLON);
  12624. --
  12625. --  IS POINT ON LAND OR SEA?
  12626.                RFUTIL.GNDCON (XLAT, XLON, CND(I));
  12627.                If CND(I) <= 0.05 Then
  12628. --
  12629. --  LAND REFLECTION.
  12630.                   If X <= -2.7 Then
  12631.                      Y := 1.7 + X;
  12632.                   Elsif X <= -0.3 Then
  12633.                      Y := -1.0 + 0.778*SIN((X + 2.7)*1.308997);
  12634.                   Else
  12635.                      Y := -1.3 - X;
  12636.                   End If;
  12637.                Else
  12638. --
  12639. --  SEA REFLECTION.
  12640.                   If X <= -4.1 Then
  12641.                      Y := 3.1 + X;
  12642.                   Elsif X <= -1.9 Then
  12643.                      Y := -1.0 + 0.778*SIN((X + 4.1)*1.427997);
  12644.                   Else
  12645.                      Y := -2.9 - X;
  12646.                   End If;
  12647.                End If;
  12648.                SGR(I,K) := -20.0*LOG10(1.0 - 10.0**Y);
  12649. --
  12650. --       SGR IS THE LOSS DUE TO A SINGLE GROUND REFLECTION.
  12651. --
  12652.             End Loop;
  12653.          End If;
  12654.       End Loop;
  12655. --
  12656. --FIELD STRENGTH CALCULATIONS.
  12657. --
  12658.       EO := 20.0*LOG10(295.0E03*SQRT(TERP));
  12659.       ANSN := 0.0;
  12660.       PLSAV := -100.0;
  12661.       NHOPP1 := NHOP + 1;
  12662.       For I in 1..NHOPP1 Loop
  12663.          If I = 1 Then
  12664. --
  12665. --  DO GROUND WAVE CALCULATION FIRST.
  12666. --
  12667. --  GROUND WAVE PROPAGATION.
  12668.             HHIGHR := TALT*1.0E3;
  12669.             HLOWER := RALT*1.0E3;
  12670.             If HLOWER > HHIGHR Then
  12671.                HTEMP := HHIGHR;
  12672.                HHIGHR := HLOWER;
  12673.                HLOWER := HTEMP;
  12674.             End If;
  12675.             LF_HF_GROUNDWAVES.GRWAVE(CONDT, FREQKC, DPATH, 1, TERP, 
  12676.                                      HLOWER, HHIGHR, EEO(1), GRLOSS);
  12677. --
  12678. --CONVERT V/M TO DB/MICROVOLT/M
  12679.             EEO(1) := 20.0*LOG10(EEO(1)) + 120.0;
  12680. --
  12681. --      ACCOUNT FOR GROUNDWAVE LOSS DUE TERRAIN ROUGHNESS
  12682.             RFUTIL.GNDCON (PLAT(1), PLONG(1), CONDUC);
  12683.             If CONDUC <= 0.05 Then
  12684.                TERAIN (PLAT(1), PLONG(1), FREQMC, DPATH, TLOSS);
  12685.                EEO(1) := EEO(1) - TLOSS;
  12686.             End If;
  12687. --
  12688.          Else
  12689. --
  12690. --SKYWAVE CALCULATIONS.
  12691.             J := I - 1;
  12692. --
  12693. --  IF MODE IS BELOW HORIZION, SKY WAVE DOES NOT EXIST.
  12694. --
  12695.             EEO(I) := -200.0;
  12696.             If MODFES(J) >= 1 Then
  12697. --
  12698. --  COMPUTE PATH LENGTH AND PATH LOSS.
  12699.                S := DPATH/FLOAT(J);
  12700.                THETA := 0.5*S/RADIUS_OF_EARTH_IN_KM;
  12701.                CTHETA := COS(THETA);
  12702.                PATH := 0.0;
  12703.                SID1 := PALT(1);
  12704.                IF J = 1  or  J = 3  or  J = 5 Then
  12705.                   PATH := PATH + 2.0*SQRT(RORO + SID1*SID1 - 
  12706.                           2.0*RADIUS_OF_EARTH_IN_KM*SID1*CTHETA);
  12707.                End If;
  12708.                SID2 := PALT(2);
  12709.                SID5 := PALT(5);
  12710.                If J > 2 Then
  12711.                   PATH := PATH + 2.0*SQRT(RORO + SID2*SID2 - 
  12712.                           2.0*RADIUS_OF_EARTH_IN_KM*SID2*CTHETA) + 
  12713.                           2.0*SQRT(RORO + SID5*SID5 - 2.0*
  12714.                           RADIUS_OF_EARTH_IN_KM*SID5*CTHETA);
  12715.                End If;
  12716.                SID3 := PALT(3);
  12717.                SID4 := PALT(4);
  12718.                If J = 2  or  J > 3 Then
  12719.                   PATH := PATH + 2.0*SQRT(RORO + SID4*SID4 - 2.0*
  12720.                           RADIUS_OF_EARTH_IN_KM*SID4*CTHETA) + 
  12721.                           2.0*SQRT(RORO + SID3*SID3 -
  12722.                           2.0*RADIUS_OF_EARTH_IN_KM*SID3*CTHETA);
  12723.                End If;
  12724.                If PLSAV <= 0.0 Then
  12725.                   PLSAV := PATH;
  12726.                End If;
  12727. --
  12728. --  PLOSS IS THE LOSS DUE TO PATH LENGTH.
  12729.                PLOSS := 20.0*LOG10(PATH);
  12730. --
  12731. --COMPUTE IONOSPHERIC AND GROUND REFLECTION LOSSES.
  12732.                REFLOS := 0.0;
  12733. --
  12734. --  IONOSPHERIC LOSSES FIRST.
  12735.                If J = 1  or  J = 3  or  J = 5 Then
  12736.                   REFLOS := REFLOS + COEF(1)*GAMMA(J);
  12737.                End If;
  12738.                If J > 2 Then
  12739.                   REFLOS := REFLOS + COEF(2)*GAMMA(J) + COEF(5)*GAMMA(J);
  12740.                End If;
  12741.                If J = 2  or  J > 3 Then
  12742.                   REFLOS := REFLOS + COEF(3)*GAMMA(J) + COEF(4)*GAMMA(J);
  12743.                End If;
  12744.                REFLOS := -20.0*LOG10(EXP(AMAX1(REFLOS,-87.5)));
  12745.                REFION := REFLOS;
  12746. --
  12747. --  NOW GROUND REFLECTION LOSSES.
  12748.                If J = 2 Then
  12749.                   REFLOS := REFLOS + SGR(2,1);
  12750.                End If;
  12751.                If J = 3 Then
  12752.                   REFLOS := REFLOS + SGR(3,1) + SGR(3,2);
  12753.                End If;
  12754.                If J = 4 Then
  12755.                   REFLOS := REFLOS + SGR(4,1) + SGR(4,2) + SGR(4, 3);
  12756.                End If;
  12757.                If J = 5 Then
  12758.                   REFLOS := REFLOS + SGR(5,1) + SGR(5,2) + SGR(5,3) + SGR(5,4);
  12759.                End If;
  12760. --
  12761. --NOW COMPUTE TOTAL FIELD STRENGTH.
  12762. --
  12763.                EEO(I) := EO + 6.0 + GT + GR - REFLOS + GDB(J) +
  12764.                          FDN(J) - PLOSS - 20.0*(AFS(1) + AFS(2));
  12765. --
  12766. --  EEO IS REFERRED TO INVERSE DISTANCE.
  12767.             End If;
  12768.          End If;
  12769.       End Loop;
  12770. --
  12771. --DETERMINE RSS SIGNAL STRENGTH IF D > 1500KM.
  12772. --
  12773.       If DPATH > 1500.0 Then
  12774.          ANS := 0.0;
  12775.          For I in 1..NHOPP1 Loop
  12776.             SS := EEO(I);
  12777.             SSVOLT := 10.0**(SS*0.05);
  12778.             SQUARE := SSVOLT*SSVOLT;
  12779.             ANS := ANS + SQUARE;
  12780.          End Loop;
  12781.          ANS := 20.0*LOG10(SQRT(ANS));
  12782.       Else
  12783. --
  12784. --IF D < 1500
  12785. --  DETERMINE VECTOR SUM OF GROUND WAVE AND STRONGEST HOP SIGNAL.
  12786. --  (THIS IS USUALLY THE ONE HOP SIGNAL AS LONG AS BETA(1) > PI2)
  12787. --
  12788.          DRADNS := ABS(PLSAV - DPATH)*FREQKC*0.333333E-2;
  12789.          DRADNS := (DRADNS - TRUNCATE(DRADNS))*TWOPI;
  12790.          SS := EEO(1);
  12791.          XGVOLT := 10.0**(SS*0.05);
  12792.          EEOTEMP:=EEO(2);
  12793.          for I in 3..6 loop
  12794.             EEOTEMP := AMAX1(EEOTEMP, EEO(I));
  12795.          end loop;
  12796.          SS := EEOTEMP;
  12797.          RRVOLT := 10.0**(SS*0.05);
  12798.          XRVOLT := RRVOLT*COS(DRADNS);
  12799.          YRVOLT := RRVOLT*SIN(DRADNS);
  12800.          XSUM := XRVOLT + XGVOLT;
  12801.          VOLTSM := SQRT(XSUM*XSUM + YRVOLT*YRVOLT);
  12802.          ANS := 20.0*LOG10(VOLTSM);
  12803.       End If;
  12804.       SIGNAL := ANS;
  12805. --
  12806.       Return;
  12807. --
  12808.       End LFPROP;
  12809. --
  12810.       Procedure LF_HANDLER is
  12811. --
  12812. --#PURPOSE: LF_HANDLER controls LF propagation prediction calculations.
  12813. --
  12814. --#AUTHOR:  J. Conrad
  12815. --
  12816. --#TYPE:    Numerical Analysis
  12817. --
  12818. --#PARAMETER DESCRIPTIONS:
  12819. --IN        CURRENT_TIME = Current scenario time in minutes.
  12820. --IN        TLAT   = Transmitter latitude in degrees north
  12821. --IN        TLON   = Transmitter longitude in degrees east
  12822. --IN        TALT   = Transmitter altitude in kilometers
  12823. --IN        RLAT   = Receiver latitude in degrees north
  12824. --IN        RLON   = Receiver longitude in degrees east
  12825. --IN        RALT   = Receiver altitude in kilometers
  12826. --IN        FREQKC = Frequency in Khz
  12827. --IN        TERP   = Transmitter radiated power in Kw
  12828. --IN        IATYPT = Transmitting antenna type (1 = loop, 2 = whip)
  12829. --OUT       SIGNAL = Signal strength at receiver in DB/MICROVOLT/METER
  12830. --
  12831. --#CALLED BY:
  12832. --          RF_PROPAGATION_HANDLER
  12833. --
  12834. --#CALLS TO:
  12835. --          HIGHTF
  12836. --          LFPROP
  12837. --
  12838. --#TECHNICAL DESCRIPTION:
  12839. --          LF_HANDLER is the set-up routine for LF propagation prediction
  12840. --          calculations. It first divides the propagation path in
  12841. --          segments and then computes the launch angle and reflection
  12842. --          angle geometries. Next, the height of the ionosphere along
  12843. --          the path is computed and passed to subroutine LFPROP for
  12844. --          the actual propagation prediction calculations.
  12845. --
  12846.       I: integer;
  12847.       ALPHA, BPG, PALTT, BMG: float;
  12848. --
  12849.       Begin
  12850. --
  12851. --PROPAGATION GEOMETRY.
  12852. --
  12853. --FIRST DIVIDE THE PATH INTO SEGMENTS AND COMPUTE THE
  12854. --  REFLECTION LOSS AND HEIGHT AT EACH OF FIVE POINTS.
  12855. --
  12856. --FILL PALT AND COEF ARRAY.
  12857.       HIGHTF;
  12858.       For I in 1..NHOP Loop
  12859. --
  12860. --ALPHA IS THE ANGLE BETWEEN LINES FROM EARTH CENTER
  12861. --TO GROUND AND IONOSPHERE REFLECTION POINTS RESPECTIVELY.
  12862.          ALPHA := DPATH/(2.0*RADIUS_OF_EARTH_IN_KM*FLOAT(I));
  12863.          BPG := 0.5*(PI - ALPHA);
  12864.          PALTT := PALT(1) - RADIUS_OF_EARTH_IN_KM;
  12865.          If I = 2 Then
  12866.             PALTT := PALT(3) - RADIUS_OF_EARTH_IN_KM;
  12867.          End If;
  12868.          If I > 2 Then
  12869.             PALTT := PALT(2) - RADIUS_OF_EARTH_IN_KM;
  12870.          End If;
  12871.          BMG := ATAN((PALTT/(PALTT + 2.0*RADIUS_OF_EARTH_IN_KM))*TAN(BPG));
  12872. --
  12873. --BETA IS THE ANGLE BETWEEN A LINE FROM EARTH CENTER TO
  12874. --GROUND POINT AND A LINE FROM GROUND POINT TO IONOSPHERIC
  12875. --REFLECTION POINT.
  12876.          BETA(I) := BPG + BMG;
  12877. --
  12878. --CHECK IS BETA IS BELOW HORZION.
  12879.          MODFES(I) := 1;
  12880.          If BETA(I) <= HALFPI Then
  12881.             MODFES(I) := 0;
  12882.          End If;
  12883.          GAMMA(I) := COS(BPG - BMG);
  12884.       End Loop;
  12885. --
  12886. --COMPUTE THE TOTAL SIGNAL STRENGTH AT THE RECEIVER
  12887.       LFPROP;
  12888. --
  12889.       Return;
  12890. --
  12891.       End LF_HANDLER;
  12892. --
  12893. End LF_PROPAGATION;
  12894. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12895. --VLFPROP
  12896. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  12897. With Debugger2; Use Debugger2;
  12898. With Text_io; Use Text_io;
  12899. With Mathlib; use Mathlib, numeric_primitives, core_functions, trig_functions;
  12900. With Constants; Use Constants;
  12901. With Propagation_constants; Use Propagation_constants;
  12902. With RFUtil;
  12903. With Nodeloc;
  12904.  
  12905. Package VLF_PROPAGATION is
  12906. --
  12907.       Procedure VLF_HANDLER;
  12908. --
  12909. End VLF_PROPAGATION;
  12910. --
  12911. Package body VLF_PROPAGATION is
  12912. --
  12913. -- VLF_PROPAGATION Package of PROP_LINK 
  12914. -- Version 1.0,  June 27, 1985.
  12915. --
  12916. -- This VLF_PROPAGATION Package contains all of the procedures that 
  12917. -- are used to perform VLF propagation prediction.
  12918. --
  12919. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  12920. -- radio frequency propagation prediction code.
  12921. --
  12922. -- PROP_LINK has been developed for the Department of Defense under
  12923. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  12924. -- Systems Inc. (Jim Conrad).
  12925. --
  12926. --Use Text_IO;
  12927. -- Instantiate integer and floating point IO.
  12928. --      Package IO_INTEGER is new INTEGER_IO(INTEGER);
  12929. --      Package IO_FLOAT is new FLOAT_IO(FLOAT);
  12930. --Use IO_INTEGER,IO_FLOAT;
  12931. --
  12932.   Pragma Source_info (on);
  12933. --
  12934. --**************************************************************************
  12935. --VARIABLES THAT ARE TO BE VISIBLE TO ALL ROUTINES WITHIN THIS PACKAGE
  12936.       MLA1, MLA2, MLA3, PLA1, PLA2, PLA3: float;
  12937.       IPERM: integer;
  12938.       MGZ1: array (integer range 1..2) of float;
  12939.       MGZ2: array (integer range 1..2) of float;
  12940.       MGZ3: array (integer range 1..2) of float;
  12941.       PGZ1: array (integer range 1..2) of float;
  12942.       PGZ2: array (integer range 1..2) of float;
  12943.       PGZ3: array (integer range 1..2) of float;
  12944.       ALPD1: float := 0.0;
  12945.       ALPD2: float := 0.0;
  12946.       ALPD3: float := 0.0;
  12947.       ALPN1: float := 0.0;
  12948.       ALPN2: float := 0.0;
  12949.       ALPN3: float := 0.0;
  12950.       VPD1: float := 0.0;
  12951.       VPD2: float := 0.0;
  12952.       VPD3: float := 0.0;
  12953.       VPN1: float := 0.0;
  12954.       VPN2: float := 0.0;
  12955.       VPN3: float := 0.0;
  12956. --**************************************************************************
  12957. --
  12958.       Function MAX0 (I,J:Integer) return float is
  12959.       begin
  12960.          if I>J then
  12961.             Return float(I);
  12962.          else
  12963.             Return float(J);
  12964.          end if;
  12965.       end MAX0;
  12966. --
  12967.       Function MIN0 (I,J: integer) return float is
  12968.       begin
  12969.          if I<J then
  12970.             Return float(I);
  12971.          else
  12972.             Return float(J);
  12973.          end if;
  12974.       end MIN0;
  12975. --
  12976. --
  12977.       Procedure VPDAY is
  12978. --
  12979. --#PURPOSE: VPDAY calculates the phase velocity for VLF mode
  12980. --          analysis for day conditions.
  12981. --
  12982. --#AUTHOR:  J. Conrad
  12983. --
  12984. --#TYPE:    Numerical Analysis
  12985. --
  12986. --#PARAMETER DESCRIPTIONS:
  12987. --          'NONE'
  12988. --
  12989. --#CALLED BY:
  12990. --          VLF_HANDLER
  12991. --
  12992. --#CALLS TO:
  12993. --          'NONE'
  12994. --
  12995. --#TECHNICAL DESCRIPTION:
  12996. --          The phase velocities are based on curve fits to data in
  12997. --          Watt, 1967.  The independent variable is frequency.
  12998. --
  12999.       Begin
  13000. --
  13001.       VPD1 := 3.0E5*((3.0811 + (-0.41925 + (0.017934 - 0.00025929*FREQKC)* 
  13002.               FREQKC)*FREQKC)*0.01 + 1.0);
  13003.       VPD2 := 3.0E5*((20.25 + (-2.2144 + (0.084483 - 0.0010997*FREQKC)*
  13004.               FREQKC)*FREQKC)*0.01 + 1.0);
  13005.       VPD3 := 3.0E5*((45.552 + (-4.4442 + (0.15493 - 0.0018666*FREQKC)* 
  13006.               FREQKC)*FREQKC)*0.01 + 1.0);
  13007. --
  13008.       Return;
  13009. --
  13010.       End VPDAY;
  13011. --
  13012. --
  13013.       Procedure VPNITE is
  13014. --
  13015. --#PURPOSE: VPNITE calculates the phase velocity for VLF mode
  13016. --          analysis for night conditions.
  13017. --
  13018. --#AUTHOR:  J. Conrad
  13019. --
  13020. --#TYPE:    Numerical Analysis
  13021. --
  13022. --#PARAMETER DESCRIPTIONS:
  13023. --          'NONE'
  13024. --
  13025. --#CALLED BY:
  13026. --          VLF_HANDLER
  13027. --
  13028. --#CALLS TO:
  13029. --          'NONE'
  13030. --
  13031. --#TECHNICAL DESCRIPTION:
  13032. --          The phase velocities are based on curve fits to data in
  13033. --          Watt, l967.  The independent variable is frequency.
  13034. --
  13035.       Begin
  13036. --
  13037.       VPN1 := 3.0E5*((((-0.00018012*FREQKC + 0.011752)*FREQKC - 0.2702)* 
  13038.               FREQKC + 1.7143)*0.01 + 1.0);
  13039.       VPN2 := 3.0E5*((((-0.0006901*FREQKC + 0.05096)*FREQKC - 1.2867)* 
  13040.               FREQKC + 11.144)*0.01 + 1.0);
  13041.       VPN3 := 3.0E5*((((-0.002474*FREQKC + 0.17879)*FREQKC - 4.4185)* 
  13042.               FREQKC + 38.331)*0.01 + 1.0);
  13043. --
  13044.       Return;
  13045. --
  13046.       End VPNITE;
  13047. --
  13048. --
  13049. -- START CURVE FIT FUNCTIONS
  13050. --
  13051. --
  13052.       Function ALPID1 (F: float) return float is
  13053.       Begin
  13054.       Return 11.053-1.1706*F+0.048434*F**2-0.000574170*F**3;
  13055.       End ALPID1;
  13056. --
  13057. --
  13058.       Function ALPID2 (F: float) return float is
  13059.       Begin
  13060.       Return 46.121+(-4.0519+((0.14693-0.001842*F)*F))*F;
  13061.       End ALPID2;
  13062. --
  13063. --
  13064.       Function ALPID3 (F: float) return float is
  13065.       Begin
  13066.       Return (0.024184*F - 1.5467)*F + 35.352;
  13067.       End ALPID3;
  13068. --
  13069. --
  13070.       Function ALPIN1 (F: float) return float is
  13071.       Begin
  13072.       Return (((0.000052083*F - 0.0043692)*F + 0.1376)*F - 1.8338)*F + 
  13073.                 9.9667;
  13074.       End ALPIN1;
  13075. --
  13076. --
  13077.       Function ALPIN2 (F: float) return float is
  13078.       Begin
  13079.       Return ((-0.0013411*F + 0.10118)*F - 2.6140)*F + 25.563;
  13080.       End ALPIN2;
  13081. --
  13082. --
  13083.       Function ALPIN3 (F: float) return float is
  13084.       Begin
  13085.       Return ((-0.0016*F + 0.133)*F -3.865)*F + 44.55;
  13086.       End ALPIN3;
  13087. --
  13088. --
  13089.       Function KTTED1 (F: float) return float is
  13090.       Begin
  13091.       Return (0.00057143*F - 0.031257)*F + 0.473;
  13092.       End KTTED1;
  13093. --
  13094. --
  13095.       Function KTTWD1 (F: float) return float is
  13096.       Begin
  13097.       Return (0.0004*F - 0.0284)*F + 0.568;
  13098.       End KTTWD1;
  13099. --
  13100. --
  13101.       Function KTTED2 (F: float) return float is
  13102.       Begin
  13103.       Return (0.00033714*F -0.019846)*F + 0.3336;
  13104.       End KTTED2;
  13105. --
  13106. --
  13107.       Function KTTWD2 (F: float) return float is
  13108.       Begin
  13109.       Return (0.00045*F - 0.02695)*F + 0.48325;
  13110.       End KTTWD2;
  13111. --
  13112. --
  13113.       Function DSGD1 (F: float) return float is
  13114.       Begin
  13115.       Return float(MAX(0,2-IPERM))*((-0.0015429*F + 0.046114)*F + 0.3940);
  13116.       End DSGD1;
  13117. --
  13118. --
  13119.       Function DSGN1 (F: float) return float is
  13120.       Begin
  13121.       Return float(MAX(0,2-IPERM))*(((0.66667E-4*F - 0.0039143)*F + 0.050762)
  13122.              *F + 0.236);
  13123.       End DSGN1;
  13124. --
  13125. --
  13126.       Function SFA1 (F: float) return float is
  13127.       Begin
  13128.       Return (-0.0095577*F + 0.1302)*F + 0.66667;
  13129.       End SFA1;
  13130. --
  13131. --
  13132.       Function SFA2 (F: float) return float is
  13133.       Begin
  13134.       Return (-0.013058*F + 0.18804)*F + 0.071875;
  13135.       End SFA2;
  13136. --
  13137. --
  13138.       Function SFB1 (F: float) return float is
  13139.       Begin
  13140.       Return (0.001608*F + 0.047224)*F + 0.55361;
  13141.       End SFB1;
  13142. --
  13143. --
  13144.       Function SFB2 (F: float) return float is
  13145.       Begin
  13146.       Return (-0.00082783*F + 0.1154)*F + 0.0078095;
  13147.       End SFB2;
  13148. --
  13149. --
  13150.       Function SFC1 (F: float) return float is
  13151.       Begin
  13152.       Return (0.0030655*F - 0.087429)*F + 1.5417;
  13153.       End SFC1;
  13154. --
  13155. --
  13156.       Function SFD1 (F: float) return float is
  13157.       Begin
  13158.       Return (0.023772*F - 0.92938)*F + 11.367;
  13159.       End SFD1;
  13160. --
  13161. --
  13162.       Function SFD2 (F: float) return float is
  13163.       Begin
  13164.       Return (0.038839*F - 0.98464)*F + 12.177;
  13165.       End SFD2;
  13166. --
  13167. --
  13168.       Function SFE1 (F: float) return float is
  13169.       Begin
  13170.       Return (-0.00267*F - 0.14786)*F + 4.1943;
  13171.       End SFE1;
  13172. --
  13173. --
  13174.       Function SFE2 (F: float) return float is
  13175.       Begin
  13176.       Return (0.016518*F - 0.70821)*F + 8.5486;
  13177.       End SFE2;
  13178. --
  13179. --
  13180.       Function SFF1 (F: float) return float is
  13181.       Begin
  13182.       Return (-0.0039286*F + 0.12057)*F - 0.10343;
  13183.       End SFF1;
  13184. --
  13185. --
  13186.       Function SFAA1 (F: float) return float is
  13187.       Begin
  13188.       Return ((-0.15046E-2*F + 0.017634)*F - 0.27146)*F + 1.7667;
  13189.       End SFAA1;
  13190. --
  13191. --
  13192.       Function SFAA2 (F: float) return float is
  13193.       Begin
  13194.       Return ((-0.63657E-3*F - 0.022321)*F + 0.20661)*F - 0.16191;
  13195.       End SFAA2;
  13196. --
  13197. --
  13198.       Function SFBB1 (F: float) return float is
  13199.       Begin
  13200.       Return (((0.25228E-4*F - 0.0029724)*F + 0.099049)*F - 1.1238)*F + 
  13201.                 5.4726;
  13202.       End SFBB1;
  13203. --
  13204. --
  13205.       Function SFBB2 (F: float) return float is
  13206.       Begin
  13207.       Return (((0.52897E-4*F - 0.005089)*F + 0.15267)*F -1.6844)*F +
  13208.                  7.4821;
  13209.       End SFBB2;
  13210. --
  13211. --
  13212.       Function SFCC1 (F: float) return float is
  13213.       Begin
  13214.       Return ((-0.13021E-3*F + 0.0125)*F - 0.22292)*F + 2.15;
  13215.       End SFCC1;
  13216. --
  13217. --
  13218.       Function SFDD1 (F: float) return float is
  13219.       Begin
  13220.       Return (((-0.89518E-4*F + 0.0064743)*F - 0.1056)*F + 0.2174)*F + 
  13221.                 6.5119;
  13222.       End SFDD1;
  13223. --
  13224. --
  13225.       Function SFDD2 (F: float) return float is
  13226.       Begin
  13227.       Return ((-0.0025535*F + 0.18304)*F - 2.8216)*F + 18.455;
  13228.       End SFDD2;
  13229. --
  13230. --
  13231.       Function SFEE1 (F: float) return float is
  13232.       Begin
  13233.       Return ((0.00039063*F - 0.0066964)*F -0.38839)*F + 5.8557;
  13234.       End SFEE1;
  13235. --
  13236. --
  13237.       Function SFEE2 (F: float) return float is
  13238.       Begin
  13239.       Return ((-0.00026042*F + 0.051339)*F - 1.3744)*F + 11.053;
  13240.       End SFEE2;
  13241. --
  13242. --
  13243.       Function SFFF1 (F: float) return float is
  13244.       Begin
  13245.       Return ((0.00069922*F - 0.044149)*F + 0.81712)*F -3.6579;
  13246.       End SFFF1;
  13247. --
  13248. --
  13249. --
  13250.       Function MLAD1 return float is
  13251.       Begin
  13252.       Return MAX0(0,2-IPERM)*(SFA1(FREQKC)) + 
  13253.                 MIN0(1,IPERM/2)*(SFA2(FREQKC));
  13254.       End MLAD1;
  13255. --
  13256. --
  13257.       Function MLAD2 return float is
  13258.       Begin
  13259.       Return MAX0(0,2-IPERM)*(SFB1(FREQKC)) + 
  13260.                 MIN0(1,IPERM/2)*(SFB2(FREQKC));
  13261.       End MLAD2;
  13262. --
  13263. --
  13264.       Function MLAD3 return float is
  13265.       Begin
  13266.       Return SFC1(FREQKC);
  13267.       End MLAD3;
  13268. --
  13269. --
  13270.       Function PLAD1 return float is
  13271.       Begin
  13272.       Return MAX0(0,2-IPERM)*(SFD1(FREQKC)) + 
  13273.                 MIN0(1,IPERM/2)*(SFD2(FREQKC));
  13274.       End PLAD1;
  13275. --
  13276. --
  13277.       Function PLAD2 return float is
  13278.       Begin
  13279.       Return MAX0(0,2-IPERM)*(SFE1(FREQKC)) + 
  13280.                 MIN0(1,IPERM/2)*(SFE2(FREQKC));
  13281.       End PLAD2;
  13282. --
  13283. --
  13284.       Function PLAD3 return float is
  13285.       Begin
  13286.       Return SFF1(FREQKC);
  13287.       End PLAD3;
  13288. --
  13289. --
  13290.       Function MLAN1 return float is
  13291.       Begin
  13292.       Return MAX0(0,2-IPERM)*(SFAA1(FREQKC)) + 
  13293.                 MIN0(1,IPERM/2)*(SFAA2(FREQKC));
  13294.       End MLAN1;
  13295. --
  13296. --
  13297.       Function MLAN2 return float is
  13298.       Begin
  13299.       Return MAX0(0,2-IPERM)*(SFBB1(FREQKC)) +
  13300.                 MIN0(1,IPERM/2)*(SFBB2(FREQKC));
  13301.       End MLAN2;
  13302. --
  13303. --
  13304.       Function MLAN3 return float is
  13305.       Begin
  13306.       Return SFCC1(FREQKC);
  13307.       End MLAN3;
  13308. --
  13309. --
  13310.       Function PLAN1 return float is
  13311.       Begin
  13312.       Return MAX0(0,2-IPERM)*(SFDD1(FREQKC)) +
  13313.                 MIN0(1,IPERM/2)*(SFDD2(FREQKC));
  13314.       End PLAN1;
  13315. --
  13316. --
  13317.       Function PLAN2 return float is
  13318.       Begin
  13319.       Return MAX0(0,2-IPERM)*(SFEE1(FREQKC)) +
  13320.                 MIN0(1,IPERM/2)*(SFEE2(FREQKC));
  13321.       End PLAN2;
  13322. --
  13323.       Function PLAN3 return float is
  13324.       Begin
  13325.       Return SFFF1(FREQKC);
  13326.       End PLAN3;
  13327. --
  13328. --
  13329. --END CURVE FIT FUNCTIONS
  13330. --
  13331. --
  13332. --START GENERAL EQUATIONS
  13333. --
  13334.       Function F1 (ALT: float; HION:float; X2PI:float) return float is
  13335.       Begin
  13336.       Return COS((X2PI*ALT)/(4.0*HION));
  13337.       End F1;
  13338. --
  13339.       Function F2 (ALT: float; HION:float; X2PI:float) return float is
  13340.       Begin
  13341.       Return  COS((X2PI*ALT)/(1.333333 * HION));
  13342.       End F2;
  13343. --
  13344.       Function F3 (ALT: float; HION:float; X2PI:float) return float is
  13345.       Begin
  13346.       Return COS((X2PI*ALT)/(0.8*HION));
  13347.       End F3;
  13348. --
  13349.       Function FDB (X: float) return float is
  13350.       Begin
  13351.       Return 20.0*LOG10(X);
  13352.       End FDB;
  13353. --
  13354. --END GENERAL EQUATIONS
  13355. --
  13356. --
  13357.       Procedure CLAMB is
  13358. --
  13359. --#PURPOSE: CLAMB calculates the relative excitation factors
  13360. --          at the transmitter and receiver for VLF mode
  13361. --          analysis.
  13362. --
  13363. --#AUTHOR:  J. Conrad
  13364. --
  13365. --#TYPE:    Numerical Analysis
  13366. --
  13367. --#PARAMETER DESCRIPTIONS:
  13368. --          'NONE'
  13369. --
  13370. --#CALLED BY:
  13371. --          VLF_HANDLER
  13372. --
  13373. --#CALLS TO:
  13374. --          'NONE'
  13375. --
  13376. --#TECHNICAL DESCRIPTION:
  13377. --          The calculations are based on curve fits to data in
  13378. --          Watt,1967 .  If a terminator crosses the path (IDNT /=
  13379. --          IDNR), values for day and night are added and divided by
  13380. --          2 based on the relationship:
  13381. --
  13382. --          Effective Value = SQRT(Transmitter Value * Receiver Value)
  13383. --
  13384.       Begin
  13385. --
  13386. --ZERO OUT PHASORS
  13387.       MLA1 := 0.0;
  13388.       MLA2 := 0.0;
  13389.       MLA3 := 0.0;
  13390.       PLA1 := 0.0;
  13391.       PLA2 := 0.0;
  13392.       PLA3 := 0.0;
  13393. --
  13394. --CALCULATE MAGNITUDES
  13395.       If IDNT = DAY or IDNR = DAY Then
  13396.          MLA1 := MLAD1;
  13397.          MLA2 := MLAD2;
  13398.          MLA3 := MLAD3;
  13399.       End If;
  13400.       If IDNT = NIGHT or IDNR = NIGHT Then
  13401.          MLA1 := MLA1 + MLAN1;
  13402.          MLA2 := MLA2 + MLAN2;
  13403.          MLA3 := MLA3 + MLAN3;
  13404.       End If;
  13405. --
  13406. --CALCULATE PHASES
  13407.       If IDNT = DAY or IDNR = DAY Then
  13408.          PLA1 := PLAD1;
  13409.          PLA2 := PLAD2;
  13410.          PLA3 := PLAD3;
  13411.       End If;
  13412.       If IDNT = NIGHT or IDNR = NIGHT Then
  13413.          PLA1 := PLA1 + PLAN1;
  13414.          PLA2 := PLA2 + PLAN2;
  13415.          PLA3 := PLA3 + PLAN3;
  13416.       End If;
  13417.       If IDNT /= IDNR Then
  13418.          MLA1 := MLA1*0.5;
  13419.          MLA2 := MLA2*0.5;
  13420.          MLA3 := MLA3*0.5;
  13421.          PLA1 := PLA1*0.5;
  13422.          PLA2 := PLA2*0.5;
  13423.          PLA3 := PLA3*0.5;
  13424.       End If;
  13425. --
  13426.       Return;
  13427. --
  13428.       End CLAMB;
  13429. --
  13430. --
  13431.       Procedure GZN (ALT: in float;
  13432.                      HION: in float;
  13433.                      ITR: in integer) is
  13434. --
  13435. --#PURPOSE: GZN calculates the height gain functions for the
  13436. --          transmitter and receiver for VLF mode analysis.
  13437. --
  13438. --#AUTHOR:  J. Conrad
  13439. --
  13440. --#TYPE:    Numerical Analysis
  13441. --
  13442. --#PARAMETER DESCRIPTIONS:
  13443. --IN        ALT    = Altitude in km
  13444. --IN        HION   = Height of the ionosphere in km
  13445. --IN        ITR    = 1 if a transmitter, 2 if a receiver
  13446. --
  13447. --#CALLED BY:
  13448. --          VLF_HANDLER
  13449. --
  13450. --#CALLS TO:
  13451. --          'NONE"
  13452. --
  13453. --#TECHNICAL DESCRIPTION:
  13454. --          For frequencies below 15 kHz, the height gain functions
  13455. --          are assumed to have the sinusoidal forms.  For frequencies
  13456. --          greater than 15 kHz, adjustments are made as follows:
  13457. --
  13458. --                    Mode 1 - curve fit to data in Watt, 1967 for
  13459. --               heights 20.1 km; and default message for heights
  13460. --               greater than or equal to 20.1 km.
  13461. --
  13462. --                    Mode 2 and 3 - effective height of the
  13463. --               ionosphere is raised to 1.16 * HION at 30 kHz and a
  13464. --               proportional amount for frequencies between 15 and 30
  13465. --               kHz;  sinusoidal distributions are retained.
  13466. --
  13467.       K: integer;
  13468.       FREQSF, HIONE: float;
  13469. --
  13470.       Begin
  13471. --
  13472.       K := ITR;
  13473.       MGZ1(K) := 1.0;
  13474.       MGZ2(K) := 1.0;
  13475.       MGZ3(K) := 1.0;
  13476.       If ALT >= 0.1  Then
  13477.          FREQSF := (FREQKC - 15.0)/15.0;
  13478.          If FREQKC > 15.0 and ALT < 20.1 Then
  13479.             MGZ1(K) := F1(ALT,HION,TWOPI) + 0.4*FREQSF*F1(ALT,HION,TWOPI);
  13480.             HIONE := 1.0 + FREQSF * 0.16;
  13481.             HIONE := HION*HIONE;
  13482.             MGZ2(K) := F2(ALT,HIONE,TWOPI);
  13483.             MGZ3(K) := F3(ALT,HIONE,TWOPI);
  13484.          Elsif FREQKC > 15.0 and ALT >= 20.1 Then
  13485.             New_line;
  13486.             Put("THIS TRANSMITTER/RECEIVER ALTITUDE AND FREQUENCY");
  13487.             New_line;
  13488.             Put("COMBINATION IS NOT INCLUDED IN THE MODE ANALYSIS MODELS.");
  13489.             New_line;
  13490.             Put("DEFAULT VALUES OF THE HEIGHT GAIN FUNCTION ARE EMPLOYED");
  13491.             New_line;
  13492.             Put("TO PERMIT PROBLEM CONTINUATION BUT THEIR ACCURACY IS");
  13493.             New_line;
  13494.             Put("UNCERTAIN.");
  13495.             MGZ1(K) := AMAX1(F1(ALT,HION,TWOPI)*ALT*5.25/HION*FREQSF,
  13496.                              F1(ALT,HION,TWOPI));
  13497.             HIONE := 1.0 + FREQSF * 0.16;
  13498.             HIONE := HION*HIONE;
  13499.             MGZ2(K) := F2(ALT,HIONE,TWOPI);
  13500.             MGZ3(K) := F3(ALT,HIONE,TWOPI);
  13501.          Else
  13502.             MGZ1(K) := F1(ALT,HION,TWOPI);
  13503.             MGZ2(K) := F2(ALT,HION,TWOPI);
  13504.             MGZ3(K) := F3(ALT,HION,TWOPI);
  13505.          End If;
  13506.       End If;
  13507.       PGZ1(K) := 0.0;
  13508.       PGZ2(K) := 0.0;
  13509.       PGZ3(K) := 0.0;
  13510.       If MGZ2(K) < 0.0 Then
  13511.          PGZ2(K) := 180.0;
  13512.       End If;
  13513.       If MGZ3(K) < 0.0 Then
  13514.          PGZ3(K) := 180.0;
  13515.       End If;
  13516.       If ALT > HION Then
  13517.          New_line;
  13518.          Put("THE INPUT ALTITUDE IS GREATER THAN THE IONOSPHERIC HEIGHT.");
  13519.          New_line;
  13520.          Put("SUCH A RELATIONSHIP IS NOT ACCOMODATED BY VLF MODE ANALYSIS.");
  13521.       End If;
  13522.       MGZ1(K) := FDB(ABS(MGZ1(K)));
  13523.       MGZ2(K) := FDB(ABS(MGZ2(K)));
  13524.       MGZ3(K) := FDB(ABS(MGZ3(K)));
  13525. --
  13526.       Return;
  13527. --
  13528.       End GZN;
  13529. --
  13530.       Procedure ALDAY (TLATX: in float;
  13531.                        TLONX: in float;
  13532.                        RLATX: in float;
  13533.                        RLONX: in float) is
  13534. --
  13535. --#PURPOSE: ALDAY determines the distance attenuation constant for day
  13536. --          conditions for VLF mode analysis.
  13537. --
  13538. --#AUTHOR:  J. Conrad
  13539. --
  13540. --#TYPE:    Numerical Analysis
  13541. --
  13542. --#PARAMETER DESCRIPTIONS:
  13543. --IN        TLATX  = Transmitter latitude in degrees north
  13544. --IN        TLONX  = Transmitter longitude in degrees east
  13545. --IN        RLATX  = Receiver latitude in degrees north
  13546. --IN        RLONX  = Receiver longitude in degrees east
  13547. --
  13548. --#CALLED BY:
  13549. --          VLF_HANDLER
  13550. --
  13551. --#CALLS TO:
  13552. --          LOCGRB
  13553. --          LOCNEW
  13554. --          ALPID1
  13555. --          ALPID2
  13556. --          ALPID3
  13557. --          KTTED1
  13558. --          KTTWD1
  13559. --          KTTED2
  13560. --          KTTWD2
  13561. --          DSGD1
  13562. --
  13563. --#TECHNICAL DESCRIPTION:
  13564. --          The methods are based on curve fits as described in
  13565. --          Watt,1967 .  The same formulation is used for all 3
  13566. --          modes. 
  13567. --
  13568.       ALPDI1, ALPDI2, ALPDI3, PHIA, KD1, KD2, KD3, PHIM, XA: float;
  13569.       MSIG1, MSIG2, MSIG3: float;
  13570.       BRN1, BRN2, BRNX, PL, XLAT, XLON: float;
  13571.       ITTE: integer;
  13572. --
  13573.       Begin
  13574. --
  13575. --CALCULATE ALPHAN(I,AVERAGE)
  13576.       ALPDI1 := ALPID1(FREQKC);
  13577.       ALPDI2 := ALPID2(FREQKC);
  13578.       ALPDI3 := ALPID3(FREQKC);
  13579.       If FREQKC < 8.0 Then
  13580.           ALPDI1 := ALPID1(8.0)*(8.0/FREQKC)**2.635046;
  13581.       End If;
  13582.       If FREQKC < 12.0 Then
  13583.           ALPDI2 := ALPID2(12.0)*(12.0/FREQKC)**2.624672;
  13584.       End If; 
  13585.       If FREQKC < 16.0 Then
  13586.           ALPDI3 := ALPID3(16.0)*(16.0/FREQKC)**2.349624;
  13587.       End If;
  13588.       ALPD1 := ALPDI1;
  13589.       ALPD2 := ALPDI2;
  13590.       ALPD3 := ALPDI3;
  13591. --
  13592. --CALCULATE DEL-ALPHAN(I) DUE TO EARTH'S MAGNETIC FIELD.
  13593.       NODELOC.LOCGRB (TLATX, TLONX, RLATX, RLONX, BRN1, BRN2, PL);
  13594.       PL := PL*0.5;
  13595.       NODELOC.LOCNEW (TLATX, TLONX, BRN1, PL, XLAT, XLON);
  13596.       NODELOC.LOCGRB (TLATX, TLONX, XLAT, XLON, BRN1, BRNX, PL);
  13597.       BRNX := BRNX - 180.0;
  13598.       ITTE := 0;
  13599.       If BRNX < 180.0 Then
  13600.         ITTE := 1;
  13601.       End If;
  13602.       PHIA := BRNX*RADIANS_PER_DEGREE;
  13603.       If ITTE /= 1 Then
  13604.          KD1 := KTTWD1(FREQKC);
  13605.          KD2 := KTTWD2(FREQKC);
  13606.          KD3 := (KD2/KD1)**2 * KD1;
  13607.       Else
  13608.          KD1 := KTTED1(FREQKC);
  13609.          KD1 := 1.5*KD1;
  13610.          KD2 := KTTED2(FREQKC);
  13611.          KD3 := KD2;
  13612.       End If;
  13613.       PHIM := ABS(XLAT + TLATX)*0.5*RADIANS_PER_DEGREE;
  13614.       XA := COS(PHIM)*SIN(PHIA);
  13615.       ALPDI1 := -KD1*XA*ALPDI1;
  13616.       ALPDI2 := -KD2*XA*ALPDI2;
  13617.       ALPDI3 := -KD3*XA*ALPDI3;
  13618.       ALPD1 := ALPD1 + ALPDI1;
  13619.       ALPD2 := ALPD2 + ALPDI2;
  13620.       ALPD3 := ALPD3 + ALPDI3;
  13621. --
  13622. --CALCULATE DEL-ALPHN(SIGMA-GROUND)
  13623.       MSIG1 := DSGD1(FREQKC);
  13624.       MSIG2 := 2.0*MSIG1;
  13625.       MSIG3 := 3.0*MSIG1;
  13626.       ALPD1 := ALPD1 + MSIG1;
  13627.       ALPD2 := ALPD2 + MSIG2;
  13628.       ALPD3 := ALPD3 + MSIG3;
  13629. --
  13630.       Return;
  13631. --
  13632.       End ALDAY;
  13633. --
  13634. --
  13635.       Procedure ALNITE (TLATX: in float;
  13636.                         TLONX: in float;
  13637.                         RLATX: in float;
  13638.                         RLONX: in float) is
  13639. --
  13640. --#PURPOSE: ALNITE determines the distance attenuation constant for
  13641. --          night conditions for VLF mode analysis.
  13642. --
  13643. --#AUTHOR:  J. Conrad
  13644. --
  13645. --#TYPE:    Numerical Analysis
  13646. --
  13647. --#PARAMETER DESCRIPTIONS:
  13648. --IN        TLATX  = Transmitter latitude in degrees north
  13649. --IN        TLONX  = Transmitter longitude in degrees east
  13650. --IN        RLATX  = Receiver latitude in degrees north
  13651. --IN        RLONX  = Receiver longitude in degrees east
  13652. --
  13653. --#CALLED BY:
  13654. --          VLF_HANDLER
  13655. --
  13656. --#CALLS TO:
  13657. --          LOCGRB
  13658. --          LOCNEW
  13659. --          ALPIN1
  13660. --          ALPIN2
  13661. --          ALPIN3
  13662. --          KTTED1
  13663. --          KTTWD1
  13664. --          KTTED2
  13665. --          KTTWD2
  13666. --          DSGN1
  13667. --
  13668. --#TECHNICAL DESCRIPTION:
  13669. --          The methods are based on curve fits as described in
  13670. --          Watt, 1967. The same formulation is used for all three
  13671. --          modes. 
  13672. --
  13673.       ALPNI1, ALPNI2, ALPNI3, PHIA, KD1, KD2, KD3, PHIM, XA: float;
  13674.       MSIG1, MSIG2, MSIG3: float;
  13675.       BRN1, BRN2, BRNX, PL, XLAT, XLON: float;
  13676.       ITTE: integer;
  13677. --
  13678.       Begin
  13679. --
  13680. --CALCULATE ALPHAN(I,AVERAGE)
  13681.       ALPNI1 := ALPIN1(FREQKC);
  13682.       ALPNI2 := ALPIN2(FREQKC);
  13683.       ALPNI3 := ALPIN3(FREQKC);
  13684.       If FREQKC < 8.0 Then
  13685.           ALPNI1 := ALPIN1(8.0)*(8.0/FREQKC)**2.635046;
  13686.       End If;
  13687.       If FREQKC < 12.0 Then
  13688.           ALPNI2 := ALPIN2(12.0)*(12.0/FREQKC)**2.624672;
  13689.       End If; 
  13690.       If FREQKC < 16.0 Then
  13691.           ALPNI3 := ALPIN3(16.0)*(16.0/FREQKC)**2.349624;
  13692.       End If;
  13693.       ALPN1 := ALPNI1;
  13694.       ALPN2 := ALPNI2;
  13695.       ALPN3 := ALPNI3;
  13696. --
  13697. --CALCULATE DEL-ALPHAN(I) DUE TO EARTH'S MAGNETIC FIELD.
  13698.       NODELOC.LOCGRB (TLATX, TLONX, RLATX, RLONX, BRN1, BRN2, PL);
  13699.       PL := PL*0.5;
  13700.       NODELOC.LOCNEW (TLATX, TLONX, BRN1, PL, XLAT, XLON);
  13701.       NODELOC.LOCGRB (TLATX, TLONX, XLAT, XLON, BRN1, BRNX, PL);
  13702.       BRNX := BRNX - 180.0;
  13703.       ITTE := 0;
  13704.       If BRNX < 180.0 Then
  13705.         ITTE := 1;
  13706.       End If;
  13707.       PHIA := BRNX*RADIANS_PER_DEGREE;
  13708.       If ITTE /= 1 Then
  13709.          KD1 := 0.6*KTTWD1(FREQKC);
  13710.          KD2 := KTTWD2(FREQKC);
  13711.          KD3 := (KD2/KD1)**2 * KD1;
  13712.       Else
  13713.          KD1 := KTTWD1(FREQKC);
  13714.          KD2 := KTTED2(FREQKC);
  13715.          KD3 := KD2;
  13716.       End If;
  13717.       PHIM := ABS(XLAT + TLATX)*0.5*RADIANS_PER_DEGREE;
  13718.       XA := COS(PHIM)*SIN(PHIA);
  13719.       ALPNI1 := -KD1*XA*ALPNI1;
  13720.       ALPNI2 := -KD2*XA*ALPNI2;
  13721.       ALPNI3 := -KD3*XA*ALPNI3;
  13722.       ALPN1 := ALPN1 + ALPNI1;
  13723.       ALPN2 := ALPN2 + ALPNI2;
  13724.       ALPN3 := ALPN3 + ALPNI3;
  13725. --
  13726. --CALCULATE DEL-ALPHN(SIGMA-GROUND)
  13727.       MSIG1 := DSGN1(FREQKC);
  13728.       MSIG2 := 2.0*MSIG1;
  13729.       MSIG3 := 3.0*MSIG1;
  13730.       ALPN1 := ALPN1 + MSIG1;
  13731.       ALPN2 := ALPN2 + MSIG2;
  13732.       ALPN3 := ALPN3 + MSIG3;
  13733. --
  13734.       Return;
  13735. --
  13736.       End ALNITE;
  13737. --
  13738.       Procedure VLF_HANDLER is
  13739. --
  13740. --#PURPOSE: VLF_HANDLER calculates the ambient signal level for a VLF
  13741. --          transmission link using mode analysis.
  13742. --
  13743. --#AUTHOR:  J. Conrad
  13744. --
  13745. --#TYPE:    Numerical Analysis
  13746. --
  13747. --#PARAMETER DESCRIPTIONS:
  13748. --IN        TLAT         = Transmitter latitude in degrees north
  13749. --IN        TLON         = Transmitter longitude in degrees east
  13750. --IN        TALT         = Transmitter altitude in kilometers
  13751. --IN        RLAT         = Receiver latitude in degrees north
  13752. --IN        RLON         = Receiver longitude in degrees east
  13753. --IN        RALT         = Receiver altitude in kilometers
  13754. --IN        FREQKC       = Link frequency in Khz
  13755. --IN        TERP         = Transmitter radiated power in Kw
  13756. --OUT       SIGNAL       = Signal strength in dB above one micro(V)/m
  13757. --
  13758. --#CALLED BY:
  13759. --          RF_PROPAGATION_HANDLER
  13760. --
  13761. --#CALLS TO:
  13762. --          ALDAY
  13763. --          ALNITE
  13764. --          CLAMB
  13765. --          DNTR
  13766. --          GNDCON
  13767. --          GZN
  13768. --          VPDAY
  13769. --          VPNITE
  13770. --
  13771. --#TECHNICAL DESCRIPTION:
  13772. --    VLF_HANDLER is a master routine for performing waveguide mode calcula-
  13773. --    tions to determine received signal strengths for VLF links.  The
  13774. --    analytical approach is described in: Watt, 1967.
  13775. --
  13776.       MEZ1, MEZ2, MEZ3, MCONST, DIS, HION, XA: float;
  13777.       XD, XN, X21D, X31D, X21N, X31N: float;
  13778.       DPHI21 , DPHI31: float;
  13779.       AEZ1, AEZ2, AEZ3, AEZR, AEZJ, AEZ, EZ, COND: float;
  13780.       HIOND: float := 70.0;
  13781.       HIONN: float := 90.0;
  13782.       ITR: integer;
  13783. --
  13784.       Begin
  13785. --
  13786. --DETERMINE THE GROUND CONDUCTIVITY
  13787.       IPERM := 1;
  13788.       RFUTIL.GNDCON (RLAT, RLON, COND);
  13789.       If COND > 0.05 Then
  13790.          IPERM := 2;
  13791.       End If;
  13792. --
  13793. --DETERMINE THE PATH LENGTH THAT IS IN DAYLIGHT, AND THE PATH LENGTH THAT 
  13794. --IS IN NITE, AND WHETHER THE TRANSMITTER AND RECEIVER ARE IN DAY OR NITE.
  13795.       RFUTIL.DNTR;
  13796. --
  13797. --CALCULATE TOTAL TRANSMITTER TO RECEIVER PATH LENGTH.
  13798.       DIS := DISDAY + DISNIT;
  13799. --
  13800. --CALCULATE CAP-LAMBDA, THE RELATIVE EXCITATION FACTOR
  13801.       CLAMB;
  13802. --
  13803. --CALCULATE GZN, THE HEIGHT GAIN FUNCTION FOR THE TRANSMITTER
  13804.       If IDNT = DAY Then
  13805.          HION := HIOND;
  13806.       Else
  13807.          HION := HIONN;
  13808.       End If;
  13809.       ITR := 1;
  13810.       GZN (TALT, HION, ITR);
  13811. --
  13812. --CALCULATE GZN, THE HEIGHT GAIN FUNCTION FOR THE RECEIVER
  13813.       If IDNR = DAY Then
  13814.          HION := HIOND;
  13815.       Else
  13816.          HION := HIONN;
  13817.       End If;
  13818.       ITR := 2;
  13819.       GZN (RALT, HION, ITR);
  13820. --
  13821. --CALCULATE ALPHAN, THE DISTANCE ATTENUATION RATE.
  13822.       If IDNT = DAY and IDNR = DAY Then
  13823.          ALDAY (TLAT, TLON, RLAT, RLON);
  13824.       ElsIf IDNT = NIGHT and IDNR = NIGHT Then
  13825.          ALNITE (TLAT, TLON, RLAT, RLON);
  13826.       ElsIf IDNT = DAY and IDNR = NIGHT Then
  13827.          ALDAY (TLAT, TLON, TERLAT, TERLON);
  13828.          ALNITE (TERLAT, TERLON, RLAT, RLON);
  13829.       ElsIf IDNT = NIGHT and IDNR = DAY Then
  13830.          ALDAY (TERLAT, TERLON, RLAT, RLON);
  13831.          ALNITE (TLAT, TLON, TERLAT, TERLON);
  13832.       End If;
  13833. --
  13834. --CALCULATE THE MODE PHASE VELOCITIES.
  13835.       If IDNT = NIGHT or IDNR = NIGHT Then
  13836.          VPNITE;
  13837.       End If;
  13838.       If IDNT = DAY or IDNR = DAY Then
  13839.          VPDAY;
  13840.       End If;
  13841. --
  13842. --CALCULATE THE MAGNITUDE OF THE FIELDS FOR EACH OF THE THREE MODES.
  13843.       XA := RADIUS_OF_EARTH_IN_KM*SIN(DIS/RADIUS_OF_EARTH_IN_KM);
  13844.       HION := SQRT(HIOND*HIONN);
  13845.       If IDNR = DAY and IDNT = DAY Then
  13846.          HION := HIOND;
  13847.       End If;
  13848.       If IDNR = NIGHT and IDNT = NIGHT Then
  13849.          HION := HIONN;
  13850.       End If;
  13851.       MCONST := 104.3 + 10.0*LOG10(TERP*1000.0) - 10.0*LOG10(FREQKC*1000.0)
  13852.                 -20.0*LOG10(HION*1000.0) - 10.0*LOG10(XA*1000.0);
  13853.       MEZ1 := MCONST + MLA1 + MGZ1(1) + MGZ1(2) - ALPD1/1000.0*DISDAY - 
  13854.               ALPN1/1000.0*DISNIT;
  13855.       MEZ2 := MCONST + MLA2 + MGZ2(1) + MGZ2(2) - ALPD2/1000.0*DISDAY -
  13856.               ALPN2/1000.0*DISNIT;
  13857.       MEZ3 := MCONST + MLA3 + MGZ3(1) + MGZ3(2) - ALPD3/1000.0*DISDAY -
  13858.               ALPN3/1000.0*DISNIT;
  13859.       If MEZ1 <= -400.0 Then
  13860.          MEZ1 := -400.0;
  13861.       End If;
  13862.       If MEZ2 <= -400.0 Then
  13863.          MEZ2 := -400.0;
  13864.       End If;
  13865.       If MEZ3 <= -400.0 Then
  13866.          MEZ3 := -400.0;
  13867.       End If;
  13868. --
  13869. --CALCULATE PHASE DIFFERENCE OF MODES 2 AND 3 RE MODE 1
  13870.       XD := TWOPI*FREQKC*DISDAY*1000.0;
  13871.       XN := TWOPI*FREQKC*DISNIT*1000.0;
  13872.       X21D := 0.0;
  13873.       X31D := 0.0;
  13874.       X21N := 0.0;
  13875.       X31N := 0.0;
  13876.       If VPD2*VPD1 > 1.0 Then 
  13877.          X21D := XD*(VPD2 - VPD1)/VPD2/VPD1;
  13878.       End If;
  13879.       If VPD3*VPD1 > 1.0 Then 
  13880.          X31D := XD*(VPD3 - VPD1)/VPD3/VPD1;
  13881.       End If;
  13882.       If VPN2*VPN1 > 1.0 Then 
  13883.          X21N := XN*(VPN2 - VPN1)/VPN2/VPN1;
  13884.       End If;
  13885.       If VPN3*VPN1 > 1.0 Then 
  13886.          X31N := XN*(VPN3 - VPN1)/VPN3/VPN1;
  13887.       End If;
  13888.       DPHI21 := X21D + X21N + ((PLA2 - PLA1) + (PGZ2(1) - PGZ1(1)) +
  13889.                (PGZ2(2) - PGZ1(2)))*RADIANS_PER_DEGREE;
  13890.       DPHI31 := X31D + X31N + ((PLA3 - PLA1) + (PGZ3(1) - PGZ1(1)) +
  13891.                (PGZ3(2) - PGZ1(2)))*RADIANS_PER_DEGREE;
  13892. --
  13893. --CALCULATE VERTICAL ELECTRIC FIELD AMPLITUDE
  13894.       AEZ1 := AMAX1(1.0E-20, 10.0**(MEZ1/20.0));
  13895.       AEZ2 := AMAX1(1.0E-20, 10.0**(MEZ2/20.0));
  13896.       AEZ3 := AMAX1(1.0E-20, 10.0**(MEZ3/20.0));
  13897.       AEZR := AEZ1 + AEZ2*COS(DPHI21) + AEZ3*COS(DPHI31);
  13898.       AEZJ := AEZ2*SIN(DPHI21) + AEZ3*SIN(DPHI31);
  13899.       IF ABS(AEZR) <= 1.0E-15 Then
  13900.          AEZR := 1.0E-15;
  13901.       End If;
  13902.       If ABS(AEZJ) <= 1.0E-15 Then
  13903.          AEZJ := 1.0E-15;
  13904.       End If;
  13905.       AEZ := AEZR*AEZR + AEZJ*AEZJ;
  13906.       AEZ := SQRT(AEZ);
  13907.       EZ := 20.0*LOG10(ABS(AEZ));
  13908.       SIGNAL := EZ + 120.0;
  13909. --
  13910.       Return;
  13911. --
  13912.       End VLF_HANDLER;
  13913. --
  13914. End VLF_PROPAGATION;
  13915.  
  13916. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  13917. --ELFPROP
  13918. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  13919. With Debugger2; Use Debugger2;
  13920. With Mathlib; Use Mathlib, Numeric_primitives, Trig_functions, Core_functions;
  13921. With Rfutil;
  13922. With NodeLoc;
  13923. With Elf_Lf_Hf_Atmospherics;
  13924. With Constants; Use Constants;
  13925. With Propagation_Constants; Use Propagation_Constants;
  13926.  
  13927. Package ELF_PROPAGATION is
  13928. --
  13929. --
  13930.       Procedure ELF_HANDLER;
  13931. --
  13932. End ELF_PROPAGATION;
  13933. --
  13934. Package body ELF_PROPAGATION is
  13935. --
  13936. -- ELF_PROPAGATION Package of PROP_LINK 
  13937. -- Version 1.0,  June 26, 1985.
  13938. --
  13939. -- This ELF_PROPAGATION Package contains all of the procedures that 
  13940. -- are used to perform ELF propagation prediction.
  13941. --
  13942. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  13943. -- radio frequency propagation prediction code.
  13944. --
  13945. -- PROP_LINK has been developed for the Department of Defense under
  13946. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  13947. -- Systems Inc. (Jim Conrad).
  13948. --
  13949.       Pragma Source_info (on);
  13950. --
  13951.       Procedure ELFKS (JDN: in DAY_OR_NIGHT;
  13952.                        ALPHA: out float;
  13953.                        BETA: out float);
  13954. --
  13955.       Procedure ELF_HANDLER is
  13956. --
  13957. --#PURPOSE: ELF_HANDLER calculates the ELF signal strength of the vertical
  13958. --          E-Field at a receiver for ambient environments.
  13959. --
  13960. --#AUTHOR:  J. Conrad
  13961. --
  13962. --#TYPE:    Numerical Analysis
  13963. --
  13964. --#PARAMETER DESCRIPTIONS:
  13965. --IN        CURRENT_TIME   = Time in seconds after scenario start
  13966. --IN        TLAT           = Transmitter lattitude in degrees north
  13967. --IN        TLON           = Transmitter longitude in degrees east
  13968. --IN        RLAT           = Receiver latitude in degrees north
  13969. --IN        RLON           = Receiver longitude in degrees east
  13970. --IN        FREQ           = Signal frequency (Hz)
  13971. --IN        TERP           = Transmitter I L product (current times length)
  13972. --                           in amp-meters
  13973. --OUT       SIGNAL         = Ambient signal strength of vertical E-
  13974. --                           Field at receiver dB/micro(V)/m
  13975. --#CALLED BY:
  13976. --          RF_PROPAGATION_HANDLER
  13977. --
  13978. --#CALLS TO:
  13979. --          DAYNIT
  13980. --          DNTR
  13981. --          ELFKS
  13982. --          LOCNEW
  13983. --          REFCAL
  13984. --
  13985. --#TECHNICAL DESCRIPTION:
  13986. --
  13987. --     Procedure ELF_HANDLER is the computation and control routine for ELF
  13988. --     electromagnetic propagation prediction. This routine calculates
  13989. --     the ELF signal strength of the vertical E-Field at a receiver for
  13990. --     both ambient environments.
  13991. --
  13992. --     The far-field vertical ELF field strength at the ocean
  13993. --     surface is considered to be adequately represented by:
  13994. --
  13995. --          IL                             ABS(SQRT(So))
  13996. --     Ev = --- x SQRT(PII x Uo / C) x F x --------------- x
  13997. --          2.0                            Hi x SQRT(Mhos)
  13998. --
  13999. --
  14000. --          EXP(-A x R) x SQRT(COS(Phi)/(Re x SIN(R/Re)))
  14001. --
  14002. --     Where:
  14003. --
  14004. --          Ev   = Vertical E-field in Volts/Meter
  14005. --          IL   = Current moment in Amp-Meters
  14006. --          PII  = 2 x PI := 6.283185308
  14007. --          Uo   = Permeability of free space, PI x 4E-7 Henries/Meter
  14008. --          C    = Speed of light, 3E+8 Meters/Second
  14009. --          F    = Signal frequency in Hertz
  14010. --          So   = Earth ionosphere wavequide propagation constant
  14011. --          Hi   = Effective height of ionosphere in Meters
  14012. --          Mhos = Effective ground conductivity in Mhos/Meter
  14013. --          A    = Normal attenuation rate in Nepers/Meter
  14014. --                  (from Procedure ELFKS)
  14015. --          R    = Great circle distance Xmtr-Rcvr in Meters
  14016. --          Re   = Earth radius (6,364,000 Meters)
  14017. --          Phi  = Azimuth angle
  14018. --
  14019. --     A factor which is not accounted for in this simple equation is the
  14020. --     interference of the wave propagating the long way around the earth
  14021. --     to the receiver. The relative strength of this component depends
  14022. --     on the difference in path lengths and the baud rate of the pseudo-
  14023. --     random modulation as well as the propagation conditions on the two
  14024. --     paths. The two signals may be combined as:
  14025. --
  14026. --          Et = Ef + (Er x K x COS(Pr - Pf))
  14027. --
  14028. --     Where:
  14029. --
  14030. --          Et   = Total combined signal in Volts/Meter
  14031. --          Ef   = Forward signal in Volts/Meter
  14032. --          Er   = Reverse signal in Volts/Meter
  14033. --          K    = Combining factor depending on autocorrelation
  14034. --                 function of MSK waveform
  14035. --               = (SIN(Ga x PI)/PI) + (1 - Ga) x COS(Ga x PI)
  14036. --          Ga   = BW x (40 - (2 x Rf))/600
  14037. --          PI   = 3.141592654
  14038. --          BW   = Bandwidth of signal in Hertz
  14039. --          Rf   = Path length of forward path in Meters
  14040. --          Pr   = Phase shift on reverse path in radians
  14041. --                 (from Procedure ELFKS)
  14042. --          Pf   = Phase shift on forward path in radians
  14043. --                 (from Procedure ELFKS)
  14044. --
  14045.       SRSO: array (DAY_OR_NIGHT range DAY..NIGHT) of float
  14046.       := (1.118034, 1.048809);
  14047. --
  14048.       COND: float := 3.0E-4;
  14049.       C: float := 2.998E8;
  14050.       XMUO: float := 1.255637E-6;
  14051.       XINC: float := 4000.0;
  14052.       DBONEP: float := 8.685889;
  14053.       PLFWD, PLBAK, HI, XCONST, ROMM, XNORMF, XNORMB, BPS, ALP, PHACTR: float;
  14054.       FINC, BINC, SUMATT, SUMBF, DEL, HAFDEL, EVPFWD, AFWD, BFWD: float;
  14055.       SUMATB, SUMBB, EVPBK, ABAK, BBAK, SIGTOT, EVPBAK: float;
  14056.       ALPHA, BETA, XLAT, XLON, HIT, HIR, DUM: float;
  14057.       IDN: Day_or_night;
  14058.       NFWD, NBAK, I: integer;
  14059. --
  14060.       Begin
  14061. --
  14062. --ZERO OUTPUT.
  14063.       SIGNAL := 0.0;
  14064. --
  14065. --CALCULATE THE FORWARD AND REVERSE PATH LENGTHS IN MEGAMETERS.
  14066.       PLFWD := DPATH * 0.001;
  14067.       PLBAK := 39.98619 - PLFWD;
  14068. --
  14069. --COMPUTE AMBIENT NORMALIZATIONS FOR PROPAGATION.
  14070.       ELF_LF_Hf_Atmospherics.REFCAL (TLAT, TLON, -CURRENT_TIME*60.0,
  14071.                                     FREQ*1.0E-3, HIT, DUM);
  14072.       ELF_LF_Hf_Atmospherics.REFCAL (RLAT, RLON, -CURRENT_TIME*60.0,
  14073.                                     FREQ*1.0E-3, HIR, DUM);
  14074.       HI := SQRT(HIT*HIR);
  14075.       RFUTIL.DAYNIT (IDN, TLON, TLON);
  14076.       XCONST := TERP*0.5*SQRT(2.0*PI*XMUO/C)*FREQ*SRSO(IDN)/
  14077.                 (SQRT(COND*RADIUS_OF_EARTH_IN_KM*1.0E3)*HI*1.0E3);
  14078.       ROMM := RADIUS_OF_EARTH_IN_KM*1.0E-3;
  14079.       XNORMF := XCONST*SQRT(1.0/(ABS(SIN(PLFWD/ROMM))));
  14080.       XNORMB := XCONST*SQRT(1.0/(ABS(SIN(PLBAK/ROMM))));
  14081. --
  14082. --ASSUME THAT DATA RATE IS EQUAL TO THE BANDWIDTH.
  14083.       BPS := BW;
  14084.       ALP := BPS*(40.0 - 2.0*PLFWD)/600.0;
  14085.       PHACTR := SIN(ALP*PI)/PI + (1.0 - ALP)*COS(ALP*PI);
  14086.       If ABS(ALP) > 1.0 Then
  14087.          PHACTR := 0.0;
  14088.       End If;
  14089. --
  14090. --DIVIDE PATH INTO XINC INCREMENTS (AMBIENT INCREMENTS ARE 4000 KM.)
  14091.       NFWD := INTEGER(PLFWD*1.0E3/XINC) + 2;
  14092.       NBAK := INTEGER(PLBAK*1.0E3/XINC) + 2;
  14093.       FINC := PLFWD/FLOAT(NFWD - 1);
  14094.       BINC := PLBAK/FLOAT(NBAK - 1);
  14095. --
  14096. --BEGIN AMBIENT PROPAGATION CALCULATIONS, ONE INCREMENT AT A TIME.
  14097. --CALCULATE IONOSPHERIC PROFILES AT INCREMENT POINTS, ALPHA AND BETA.
  14098.       SUMATT := 0.0;
  14099.       SUMBF := 0.0;
  14100.       For I in 2..NFWD Loop
  14101.          DEL := FINC*FLOAT(I - 1)*1.0E3;
  14102.          HAFDEL := DEL*0.5;
  14103.          NODELOC.LOCNEW (TLAT, TLON, BRNG1, HAFDEL, XLAT, XLON);
  14104.          RFUTIL.DAYNIT (IDN, XLON, XLON);
  14105.          ELFKS (IDN, ALPHA, BETA);
  14106.          SUMATT := ALPHA*FINC + SUMATT;
  14107.          SUMBF := BETA*FINC + SUMBF;
  14108.       End Loop;
  14109.       EVPFWD := XNORMF*EXP(-AMIN1(50.0, SUMATT));
  14110.       AFWD   := SUMATT/PLFWD*DBONEP;
  14111.       BFWD   := 2.0E6*PI*FREQ*PLFWD/(C*SUMBF);
  14112. --
  14113. --NOW FOR THE REVERSE PATH
  14114.       SUMATB := 0.0;
  14115.       SUMBB := 0.0;
  14116.       For I in 2..NBAK Loop
  14117.          DEL := BINC*FLOAT(I - 1)*1.0E3;
  14118.          HAFDEL := DEL*0.5;
  14119.          NODELOC.LOCNEW (TLAT, TLON, BRNG2, HAFDEL, XLAT, XLON);
  14120.          RFUTIL.DAYNIT(IDN, XLON, XLON);
  14121.          ELFKS (IDN, ALPHA, BETA);
  14122.          SUMATB := ALPHA*BINC + SUMATB;
  14123.          SUMBB := BETA*BINC + SUMBB;
  14124.       End Loop;
  14125.       EVPBK := XNORMB*EXP(-AMIN1(50.0, SUMATB));
  14126.       ABAK := SUMATT/PLBAK*DBONEP;
  14127.       BBAK := 2.0E6*PI*FREQ*PLBAK/(C*SUMBB);
  14128. --
  14129. --COMBINE THE FORWARD AND REVERSE SIGNALS.
  14130.       SIGTOT := EVPFWD + EVPBK*PHACTR*COS(SUMBB - SUMBF);
  14131. --
  14132. --CONVERT TO DB/MICROVOLT/METER.
  14133.       SIGNAL := 20.0*LOG10(ABS(SIGTOT)) + 120.0;
  14134. --
  14135.       RETURN;
  14136. --
  14137.       End ELF_HANDLER;
  14138. --
  14139. --
  14140.       Procedure ELFKS (JDN: in DAY_OR_NIGHT;
  14141.                        ALPHA: out float;
  14142.                        BETA: out float) is
  14143. --
  14144. --#PURPOSE: ELFKS computes precalculated values of the complex
  14145. --          coefficient of propagation at ELF frequencies.
  14146. --
  14147. --#AUTHOR:  J. Conrad
  14148. --
  14149. --#TYPE:    Numerical Analysis
  14150. --
  14151. --#PARAMETER DESCRIPTIONS:
  14152. --IN        JDN    = Flag for day or night conditions (DAY or NIGHT)
  14153. --OUT       ALPHA  = Attenuation rate, Nepers/Megameter
  14154. --OUT       BETA   = Phase shift of the ELF signal.
  14155. --
  14156. --#CALLED BY:
  14157. --          ELF_HANDLER
  14158. --
  14159. --#CALLS TO:
  14160. --          'NONE'
  14161. --
  14162. --#TECHNICAL DESCRIPTION:
  14163. --          Curve fits to data presented in  Fields,1968 are assessed
  14164. --          to compute the amplitude attenuation and the phase shift
  14165. --          of the ELF signal.
  14166. --
  14167.       AD0: array (integer range 1..3) of float
  14168.       :=(+4.023E+00, -2.290E+00, +3.824E-01);
  14169.       BD0: array (integer range 1..3) of float
  14170.       :=(+1.219E+00, +5.289E-02, -1.283E-02);
  14171.       AN0: array (integer range 1..3) of float
  14172.       :=(+3.234E+00, -1.804E+00, +3.311E-01);
  14173.       BN0: array (integer range 1..3) of float
  14174.       :=(+1.404E+00, -3.372E-02, -5.125E-03);
  14175.       X: float;
  14176.       DBONEP:float := 8.686;
  14177.       TOPIOC:float := 0.02097;
  14178. --
  14179.       Begin
  14180. --
  14181.       X := LOG(FREQ);
  14182.       If JDN = DAY Then
  14183.          ALPHA := AD0(1) + AD0(2)*X + AD0(3)*(X**2);
  14184.          BETA := BD0(1) + BD0(2)*X + BD0(3)*(X**2);
  14185.       Else
  14186.          ALPHA := AN0(1) + AN0(2)*X + AN0(3)*(X**2);
  14187.          BETA := BN0(1) + BN0(2)*X + BN0(3)*(X**2);
  14188.       End If;
  14189. --
  14190.        ALPHA := ALPHA/DBONEP;
  14191.        BETA := TOPIOC*FREQ*BETA;
  14192. --
  14193.       Return;
  14194. --
  14195.       End ELFKS;
  14196. --
  14197. --
  14198. End ELF_PROPAGATION;
  14199. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14200. --NOISE
  14201. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14202. With Debugger2; Use Debugger2;
  14203. With Mathlib; Use Mathlib, numeric_primitives, trig_functions, core_functions;
  14204. With Text_io; Use Text_io, Integer_io, Float_io;
  14205. With Types; Use Types;
  14206. With Constants; Use Constants;
  14207. With Propagation_Constants; Use Propagation_Constants;
  14208. With RFUtil; Use RFUtil;
  14209.  
  14210. Package NOISE is
  14211.  
  14212.       Procedure NOISE_HANDLER;
  14213.       ANA: array (integer range 1..1050) of float;
  14214.       FAM: array (integer range 1..14, integer range 1..12) of float;
  14215.  
  14216. End NOISE;
  14217.  
  14218. Package body NOISE is
  14219.  
  14220. -- NOISE Package of PROP_LINK 
  14221. -- Version 1.0,  April 23, 1985.
  14222.  
  14223. -- This NOISE Package contains all of the procedures that 
  14224. -- are used to compute atmospheric and man-made noise.
  14225. --
  14226. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  14227. -- radio frequency propagation prediction code.
  14228. --
  14229. -- PROP_LINK has been developed for the Department of Defense under
  14230. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  14231. -- Systems Inc. (Jim Conrad).
  14232. --
  14233.       Pragma Source_info (on);
  14234. --
  14235.       Procedure VLF_LF_MF_HF_NOISE (T: in float) is
  14236. --
  14237. --#PURPOSE: VLF_LF_MF_HF_NOISE performs the ambient VLF/LF/MF/HF noise 
  14238. --          calculations.
  14239. --
  14240. --#AUTHOR:  J. Conrad
  14241. --
  14242. --#TYPE:    Numerical Analysis
  14243. --
  14244. --#PARAMETER DESCRIPTIONS:
  14245. --          T       = Local time in hours.
  14246. --
  14247. --#CALLED BY:
  14248. --          NOISE_HANDLER
  14249. --
  14250. --#CALLS TO:
  14251. --          'NONE'
  14252. --
  14253. --#TECHNICAL DESCRIPTION:
  14254. --    This routine calculates the maximum of atmospheric, galactic, and
  14255. --    man-made noise at a location for a given time, frequency, and type
  14256. --    of area at the location. Galactic noise is computed by:
  14257. --               NG = 165 + 9.555 ln (F/3)
  14258. --    where F is the wave frequency in MHz. Man-made noise is computed as
  14259. --               NM = XNO + BCO ln (F/3)
  14260. --    where XNO and BCO have the following frequency dependency:
  14261. --               F (MHz)        XNO       BCO
  14262. --               F < 10       -148.6    -12.768
  14263. --               F >= 10 and
  14264. --               F < 20       -167.5     -2.866
  14265. --               F <= 20      -142.2    -10.423
  14266. --    The values of atmospheric radio noise are taken from worldwide
  14267. --    1 MHz noise maps found in CCIR Report No. 322.  The numerical
  14268. --    coefficients, which represent the worldwide distribution of atmos-
  14269. --    pheric noise as a function of geographic location, were generated
  14270. --    by means of a least squares fit using Fourier analysis.  The
  14271. --    frequency dependence is computed using a power series least squares
  14272. --    fit.
  14273. --
  14274.       C: array (integer range 1..13) of float;
  14275.       S: array (integer range 1..13) of float;
  14276.       TL: array (integer range 1..27, integer range 1..5) of float;
  14277.       TIME: array (integer range 1..5) of float;
  14278.       XNOA: array (integer range 1..3) of float := (-148.6, -167.5, -142.2);
  14279.       BCOA: array (integer range 1..3) of float := (-12.768, -2.866, -10.423);
  14280.       IUNIT: FILE_TYPE;
  14281.       CLT, GMT, XLON, CLG, GSIN, GCOS, CLGS, QGCI, G, QANA, F, R: float;
  14282.       TX, ANOS, ATMNO, TM, ABCT, X, PZ, PX, CZ, ATNO, ATNX, F3LOG: float;
  14283.       GNOS, XNO, BCO, XNOISE, FREQMH: float;
  14284.       I, J, K, M, ICI, ITT, JL, JT, IT, NTB, NTX, ITIME, ITB, NFR: integer;
  14285. --
  14286.       Begin
  14287. --
  14288.       FREQMH := FREQ*1.0E-6;
  14289. --
  14290. --ATMOSPHERIC NOISE AT RECEIVER FOR 1 MHZ FREQ. ,WRECS XNOISE.
  14291.       CLT := RLAT*RADIANS_PER_DEGREE;
  14292.       GMT := T - RLON/15.0;
  14293.       If GMT < 0.0 Then
  14294.          GMT := GMT + 24.0;
  14295.       End If;
  14296.       If GMT > 24.0 Then
  14297.          GMT := GMT - 24.0;
  14298.       End If;
  14299.       NSEAS := (MONTH - 1)/3;
  14300.       If NSEAS <= 0 Then
  14301.          NSEAS := 4;
  14302.       End If;
  14303.       If NSEAS /= CURRENT_NOISE_SEASON Then
  14304.          Case NSEAS is
  14305.             when 1 => OPEN (IUNIT, in_file, "SPRING.DAT");
  14306.             when 2 => OPEN (IUNIT, in_file, "SUMMER.DAT");
  14307.             when 3 => OPEN (IUNIT, in_file, "FALL.DAT");
  14308.             when 4 => OPEN (IUNIT, in_file, "WINTER.DAT");
  14309.             when others => null;
  14310.          End case;
  14311.          SET_INPUT(IUNIT);
  14312.          For I in 1..1050 Loop
  14313.             Get (ANA(I), 11);
  14314.             If I rem 5 = 0 Then
  14315.                Skip_Line;
  14316.             End If;
  14317.          End Loop;
  14318.          For J in 1..12 Loop
  14319.             For I in 1..14 Loop
  14320.                Get (FAM(I,J), 11);
  14321.                If (14*(J-1)+I) rem 5 = 0 Then
  14322.                   Skip_Line;
  14323.                End If;
  14324.             End Loop;
  14325.          End Loop;
  14326.          Close (IUNIT);
  14327.          SET_INPUT(STANDARD_INPUT);
  14328.          CURRENT_NOISE_SEASON := NSEAS;
  14329.       End If;
  14330. --
  14331.       XLON := -RLON;
  14332.       CLG := (360.0 - XLON)*RADIANS_PER_DEGREE;
  14333.       GSIN := SIN(CLT);
  14334.       GCOS := COS(CLT);
  14335.       CLGS := CLG - RADIANS_PER_DEGREE*2.143;
  14336.       If CLGS < 0.0 Then
  14337.          CLGS := CLGS + TWOPI;
  14338.       End If;
  14339.       For K in 1..5 Loop
  14340.          QGCI := 1.0;
  14341.          For I in 1..21 Loop
  14342.             G := 0.0;
  14343.             M := I;
  14344.             If M mod 2 = 0 Then
  14345.                QGCI := QGCI*GCOS;
  14346.             End If;
  14347.             For J in 1..10 Loop
  14348.                ICI := I + 21*(10 - J + 10*(K - 1));
  14349.                QANA := ANA(ICI);
  14350.                If QANA /= 0.0 Then
  14351.                   If J /= 10 Then
  14352.                      G := (G + QANA)*GSIN;
  14353.                   End If;
  14354.                End If;
  14355.             End Loop;
  14356.             TL(I,K) := (G + QANA) * QGCI;
  14357.          End Loop;
  14358.       End Loop;
  14359.       C(1) := COS(CLGS);
  14360.       S(1) := SIN(CLGS);
  14361.       For M in 2..10 Loop
  14362.          C(M) := C(1)*C(M - 1) - S(1)*S(M - 1);
  14363.          S(M) := C(1)*S(M - 1) + S(1)*C(M - 1);
  14364.       End Loop;
  14365.       For ITT in 1..5 Loop
  14366.          F := TL(1,ITT);
  14367.          For JL in 1..10 Loop
  14368.             F := F + TL(2*JL,ITT)*S(JL) + TL(2*JL + 1,ITT)*C(JL);
  14369.          End Loop;
  14370.          TIME(ITT) := F;
  14371.       End Loop;
  14372.       IT := INTEGER(GMT);
  14373.       R := (15.0*GMT - 180.0)*RADIANS_PER_DEGREE;
  14374.       C(1) := COS(R);
  14375.       S(1) := SIN(R);
  14376.       C(2) := COS(R + R);
  14377.       S(2) := SIN(R + R);
  14378.       TX := TIME(1);
  14379.       For JT in 1..2 Loop
  14380.          TX := TX + TIME(2*JT)*S(JT) + TIME(2*JT + 1)*C(JT);
  14381.       End Loop;
  14382.       ANOS := TX;
  14383.       ATMNO := ANOS - 204.0;
  14384.       If ABS(FREQMH - 1.0) < 0.01 Then
  14385.          Goto GALACTIC_NOISE;
  14386.       End If;
  14387. --
  14388. --Routine GENFAM from WRECS.
  14389.       F := LOG10(FREQMH);
  14390.       NTB := Integer(T/4.0 + 1.0);
  14391.       If NTB > 6 Then
  14392.          NTB := 6;
  14393.       End If;
  14394.       TM := FLOAT(4*NTB - 2);
  14395.       ABCT := ABS(T - TM)/4.0;
  14396.       NTX := NTB - 1;
  14397.       If T > TM Then
  14398.          NTX := NTB + 1;
  14399.       End If;
  14400.       If NTX > 6 Then
  14401.          NTX := 1;
  14402.       End If;
  14403.       If NTX < 1 Then
  14404.          NTX := 6;
  14405.       End If;
  14406.       For ITIME in 1..2 Loop
  14407.          ITB := NTB;
  14408.          If ITIME = 2 Then
  14409.             ITB := NTX;
  14410.          End If;
  14411.          If RLAT < 0.0 Then
  14412.             ITB := ITB + 6;
  14413.          End If;
  14414.          X := -0.75;
  14415.          loop
  14416.             PZ := 0.0;
  14417.             PX := 0.0;
  14418.             For I in 1..7 Loop
  14419.                PZ := X*PZ + FAM(I,ITB);
  14420.                PX := X*PX + FAM(I+ 7,ITB);
  14421.             End Loop;
  14422.             If X /= -0.75 Then exit; end if;
  14423.             CZ := ANOS*(2.0 - PZ) - PX;
  14424.             X := (8.0*2.0**F - 11.0)/4.0;
  14425.          End loop;
  14426.          If ITIME = 1 Then
  14427.             ATNO := CZ*PZ + PX;
  14428.          End If;
  14429.          If ITIME = 2 Then
  14430.             ATNX := CZ*PZ + PX;
  14431.          End If;
  14432.       End Loop;
  14433.       ATMNO := (ATNO + (ATNX - ATNO)*ABCT) - 204.0;
  14434. --
  14435. <<GALACTIC_NOISE>>
  14436.       F3LOG := LOG(FREQMH/3.0);
  14437.       GNOS := -(165.0 + 9.555*F3LOG);
  14438. --
  14439. --MAN MADE NOISE.
  14440.       NFR := 1;
  14441.       If FREQMH > 10.0 Then
  14442.          NFR := 2;
  14443.       End If;
  14444.       If FREQMH >= 20.0 Then
  14445.          NFR := 3;
  14446.       End If;
  14447.       XNO := XNOA(NFR);
  14448.       BCO := BCOA(NFR);
  14449.       XNOISE := XNO + BCO*F3LOG;
  14450.       SIGNOS := AMAX1(ATMNO, AMAX1(GNOS, XNOISE));
  14451.       Return;
  14452. --
  14453.       End VLF_LF_MF_HF_NOISE;
  14454. --
  14455. --
  14456.       Procedure ELF_NOISE is
  14457. --
  14458. --#PURPOSE: ELF_NOISE computes the effective atmospheric noise levels,
  14459. --          on a world-wide basis, at ELF frequencies.
  14460. --
  14461. --#AUTHOR:  J. Conrad 
  14462. --
  14463. --#TYPE:    Numerical Analysis
  14464. --
  14465. --#CALLED BY:
  14466. --          NOISE_HANDLER
  14467. --
  14468. --#CALLS TO:
  14469. --          'NONE'
  14470. --
  14471. --#TECHNICAL DESCRIPTION:
  14472. --          A limited amount of ELF wideband noise data has been
  14473. --          collected at Saipan, Malta, and Norway.  Based on these
  14474. --          three known noise levels and the fact that ELF noise is
  14475. --          predominantly generated by equatorial thunderstorms, three
  14476. --          equivalent equatorial ELF noise sources can be postulated
  14477. --          with appropriate power to yield these three known values
  14478. --          of noise.  It is this technique that has been employed
  14479. --          in ELF_NOISE to generate world-wide ELF noise.
  14480. --
  14481. --          A noise adjustment factor as a function of
  14482. --          frequency is also included in ELF_NOISE based on the data
  14483. --          presented in the "SANGUINE System Design Study (SSDS)"
  14484. --          (U), December 1970, (SRD).
  14485. --
  14486.       P1: constant float := 1.094475E3;
  14487.       P2: constant float := 2.783973E3;
  14488.       P3: constant float := 9.114757E2;
  14489.       FACTR, D1, D2, D3, DELF: float;
  14490. --
  14491.       Begin
  14492. --
  14493. --  FIRST CALCULATE THE EFFECTIVE NOISE AT 45 HZ. AS A FUNCTION OF
  14494. --  DISTANCE FROM EACH OF THE 3 ASSUMED EQUATORIAL NOISE SOURCES.
  14495. --
  14496.       FACTR := COS(RLAT*RADIANS_PER_DEGREE);
  14497.       D1 := RADIUS_OF_EARTH_IN_KM*ACOS(FACTR*
  14498.             COS(ABS(110.0 - RLON)*RADIANS_PER_DEGREE));
  14499.       D2 := RADIUS_OF_EARTH_IN_KM*ACOS(FACTR*
  14500.             COS(ABS(-60.0 - RLON)*RADIANS_PER_DEGREE));
  14501.       D3 := RADIUS_OF_EARTH_IN_KM*ACOS(FACTR*
  14502.             COS(ABS( 15.0 - RLON)*RADIANS_PER_DEGREE));
  14503.       D1 := AMAX1(D1, 1.0E-4);
  14504.       D2 := AMAX1(D2, 1.0E-4);
  14505.       D3 := AMAX1(D3, 1.0E-4);
  14506. --
  14507.       SIGNOS := P1/(D1*D1) + P2/(D2*D2) + P3/(D3*D3);
  14508.       SIGNOS := 20.0*LOG10(SIGNOS) + 120.0;
  14509.       SIGNOS := AMIN1(50.0, SIGNOS);
  14510. --
  14511. --NOW APPLY THE FREQUENCY ADJUSTMENT FACTOR AS PER SSDS FIG. 5-7
  14512. --
  14513.       DELF := FREQ - 45.0;
  14514.       SIGNOS := SIGNOS + DELF*2.666667E-2;
  14515. --
  14516.       Return;
  14517. --
  14518.       End ELF_NOISE;
  14519. --
  14520.       Procedure NOISE_HANDLER is
  14521. --
  14522. --#PURPOSE: NOISE_HANDLER computes the signal-strength of the background noise.
  14523. --
  14524. --#AUTHOR:  J. Conrad
  14525. --
  14526. --#TYPE:    Handler subroutine.
  14527. --
  14528. --#CALLED BY:
  14529. --          RF_PROPAGATION_HANDLER
  14530. --
  14531. --#CALLS TO:
  14532. --          ELF_NOISE
  14533. --          VLF_LF_MF_HF_NOISE
  14534. --          ZENITH
  14535. --
  14536. --#TECHNICAL DESCRIPTION:
  14537. --          This is the handler routine for all of the atmospheric/
  14538. --          man-made noise models. The procedure employed is to first
  14539. --          determine the frequency and location of the receiver and
  14540. --          then to access the appropriate noise model.
  14541. --
  14542.       BOLTZ: constant float := -228.6;
  14543.       TIMSEC, FREQMH, HR, TREFSE, CHI, TOD: float;
  14544.       NITDAY: DAY_OR_NIGHT;
  14545.       NHR: integer;
  14546. --
  14547.       Begin
  14548. --
  14549. --SET VALUES OF TIME TO SECONDS AND FREQUENCY TO MEGAHERTZ
  14550.       TIMSEC := CURRENT_TIME*60.0;
  14551.       FREQMH := FREQ*1.0E-6;
  14552. --
  14553. --ELF NOISE HANDLER
  14554.       If FREQ < 3.0E3 Then
  14555.          ELF_NOISE;
  14556.          Return;
  14557.       End If;
  14558. --
  14559. -- VLF/LF/MF/HF NOISE HANDLER
  14560.       If FREQ < 3.0E7 Then 
  14561.          HR := REFERENCE_TIME*0.01;
  14562.          NHR := INTEGER(HR);
  14563.          TREFSE := (REFERENCE_TIME - FLOAT(NHR)*40.0)*60.0;
  14564.          ZENITH (RLAT, RLON, CHI, TOD, NITDAY);
  14565.          VLF_LF_MF_HF_NOISE (TOD);
  14566.          If FREQ < 3.0E5 Then -- (VLF/LF units conversion)
  14567.             SIGNOS := SIGNOS + 20.0*LOG10(FREQ) - 11.5;
  14568.          End If;
  14569.          Return;
  14570.       End If;
  14571. --
  14572. --VHF/UHF/SHF/EHF NOISE HANDLER
  14573. --
  14574. --  IN AN AMBIENT ENVIRONMENT, THE NOISE IS CONTAINED IN THE G/T TERM
  14575. --  SO SET THE SIGNOS VALUE TO -G/T PLUS BOLTZMANNS CONSTANT.
  14576.       SIGNOS := BOLTZ - GOT;
  14577.       Return;
  14578. --
  14579.       End NOISE_HANDLER;
  14580. --
  14581. End NOISE;
  14582. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14583. --TRANSMIT
  14584. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  14585. With Text_IO; use Text_io, float_io, integer_io;
  14586. With Entityuti; use Entityuti;
  14587. With Types; use Types;
  14588. With Constants; use Constants;
  14589. With Constant2; use Constant2;
  14590. With Constant3; use Constant3;
  14591. With Helps; Use Helps;
  14592. With Debugger; use Debugger;
  14593. Package TRANSMIT is
  14594. --
  14595.       Procedure TRANSMITTER_ADD (IXMT: in integer;
  14596.                                  IFLG: in out integer;
  14597.                                  IERR: out integer);
  14598.       Procedure TRANSMITTER_DATA (INUMBR: in integer;
  14599.                                   FREQ: in float;
  14600.                                   IFLG: in out integer;
  14601.                                   INOADD: out integer);
  14602.       Procedure TRANSMITTER_DISPLAY (IBUFF: in L_ARRAY; 
  14603.                                      NV: in out integer);
  14604.       Procedure TRANSMITTER_FETCH (KNAME: out string;
  14605.                                    INAME: out long_integer;
  14606.                                    INUMBR: out integer;
  14607.                                    ISTOP: out integer);
  14608.       Procedure TRANSMITTER_FIND (INAME: in long_integer; 
  14609.                                   INUMBR: out integer);
  14610.       Procedure TRANSMITTER_HANDLER;
  14611.       Procedure TRANSMITTER_HELP (IWHO: in integer);
  14612.       Procedure TRANSMITTER_REMOVE (IBUFF: in out L_ARRAY;
  14613.                                     NUMBR: in integer);
  14614. --
  14615. End TRANSMIT;
  14616. -- 
  14617. Package body TRANSMIT is
  14618. --
  14619. -- TRANSMIT Package of PROP_LINK Version 1.0, February 16, 1985
  14620. --
  14621. -- This TRANSMIT Package contains all of the procedures that manipulate 
  14622. -- transmitter data.
  14623. --
  14624. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  14625. -- radio frequency propagation prediction code.
  14626. --
  14627. -- PROP_LINK has been developed for the Department of Defense under
  14628. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  14629. -- Systems Inc. (Jim Conrad).
  14630. --
  14631. --
  14632.       Procedure TRANSMITTER_ADD (IXMT: in integer;
  14633.                                  IFLG: in out integer;
  14634.                                  IERR: out integer) is
  14635. --
  14636. --#PURPOSE: TRANSMITTER_ADD processes the addition of one or more transmitter
  14637. --          classes.
  14638. --
  14639. --#AUTHOR:  J. Conrad
  14640. --
  14641. --#TYPE:    I/O Processing
  14642. --
  14643. --#PARAMETER DESCRIPTIONS:
  14644. --IN        IXMT  = The position of the transmitter class to be added,
  14645. --                  if 0 on entry, then additions will be allowed
  14646. --                  until a = is entered.
  14647. --IO        IFLG  = Flag indicating,
  14648. --                   0...Addition
  14649. --                   1...Modify or Like
  14650. --OUT       IERR   = The error code where,
  14651. --                   0 means no errors encountered,
  14652. --                   1 means an attempt to add too many
  14653. --                     transmitter classes has been made.
  14654. --
  14655. --#CALLED BY:
  14656. --          NODE_HANDLER
  14657. --          TRANSMITTER_HANDLER
  14658. --
  14659. --#CALLS TO:
  14660. --          BLANK_CHECK
  14661. --          HELP_CHECK
  14662. --          INTEGER_TO_ALPHA
  14663. --          PARSE
  14664. --          TRANSMITTER_DATA
  14665. --
  14666. --#TECHNICAL DESCRIPTION:
  14667. --          TRANSMITTER_ADD processes the addition of transmitter classes as
  14668. --          well as the replacement of transmitter class data when the
  14669. --          modify command has been used.  Echo checking is used
  14670. --          so that the operator may inspect the current value for
  14671. --          each data element.  The "LIKE" command is also supported
  14672. --          so that a transmitter class may be specified as being like
  14673. --          some other previously described transmitter class.
  14674. --
  14675.       KNAME: string(1..6);
  14676.       INUMBR, INOADD: integer;
  14677. --
  14678.       Begin
  14679. --
  14680. --INITIALIZE.
  14681.       IERR := 0;
  14682. --
  14683. --GET TRANSMITTER CLASS FREQUENCY.
  14684. <<FREQUENCY>>
  14685.       New_line;
  14686.       Put("Frequency: ");
  14687.       Put(FREXMT(IXMT));
  14688.       Put(" Hz."); New_line;
  14689.       Get_line(INPUT_BUFFER, MAX);
  14690. --
  14691. --IF A <N>  ENTERED SET TRANSMITTER CLASS FREQUENCY TO ZERO AND BRANCH TO 
  14692. --TRANSMITTER_DATA_CALL.
  14693.       If INPUT_BUFFER(1) = 'N' or INPUT_BUFFER(1) = 'n' Then
  14694.          NEW_TITLE_CHECK;
  14695.          XARRAY(1) := 0.0;
  14696.          Goto TRANSMITTER_DATA_CALL;
  14697.       End If;
  14698. --
  14699. --IF A <CR> ENTERED SAVE THIS DATA ELEMENT AS IS AND GET NEXT ONE.
  14700.       XARRAY(1) := FREXMT(IXMT);
  14701.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  14702.          Goto TRANSMITTER_DATA_CALL;
  14703.       End If;
  14704. --
  14705. --IF A = ENTERED TERMINATE WITH ALL VALUES AS THEY ARE RIGHT NOW.
  14706.       If INPUT_BUFFER(1) = '=' Then
  14707.          New_line;
  14708.          Put("No transmitter data was added or changed in this ");
  14709.          Put("transmitter class");
  14710.          IERR := 1;
  14711.          Return;
  14712.       End If;
  14713. --
  14714. --IF AN <H> ENTERED THEN PRINT A HELP MESSAGE AND RE-PROMPT.
  14715.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  14716.          TRANSMITTER_HELP (1);
  14717.          Goto FREQUENCY;
  14718.       End If;
  14719. --
  14720. --IF A <L> ENTERED THEN THIS TRANSMITTER CLASS IS LIKE SOME OTHER,
  14721. --NOW GET THE OTHER TRANSMITTER CLASS FOR THIS ASSIGNMENT.
  14722.       If INPUT_BUFFER(1) = 'L' or INPUT_BUFFER(1) = 'l' Then
  14723.          IFLG := 1;
  14724. <<LIKE>>
  14725.          New_line;
  14726.          Put("Which transmitter class? ");
  14727.          Get_line(INPUT_BUFFER, MAX);
  14728.          If INPUT_BUFFER(1) = '=' Then
  14729.             New_line;
  14730.             Put("No transmitter data was added or changed in this ");
  14731.             Put("transmitter class");
  14732.             IERR := 1;
  14733.             Return;
  14734.          End If;
  14735.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  14736.             TRANSMITTER_HELP(2);
  14737.             Goto LIKE;
  14738.          End If;
  14739.          NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  14740.          PARSE (INPUT_BUFFER(1..MAX));
  14741.          If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  14742.             Goto LIKE;
  14743.          End If;
  14744.          TRANSMITTER_FIND(IARRAY(1), INUMBR);
  14745.          If INUMBR <= 0 Then
  14746.             INTEGER_TO_ALPHA (IARRAY(1), KNAME);
  14747.             New_line;
  14748.             Put("Transmitter class ");
  14749.             Put(KNAME);
  14750.             Put(" was not found.");
  14751.             Goto LIKE;
  14752.          End If;
  14753.          NEW_TITLE_CHECK;
  14754.          ITPXMT(IXMT) := ITPXMT(INUMBR);
  14755.          IATXMT(IXMT) := IATXMT(INUMBR);
  14756.          FREXMT(IXMT) := FREXMT(INUMBR);
  14757.          TRPXMT(IXMT) := TRPXMT(INUMBR);
  14758.          ANTGNX(IXMT) := ANTGNX(INUMBR);
  14759.          ANTHTX(IXMT) := ANTHTX(INUMBR);
  14760.          ANTLNX(IXMT) := ANTLNX(INUMBR);
  14761.          ANTTAX(IXMT) := ANTTAX(INUMBR);
  14762.          Goto FREQUENCY;
  14763.       End If;
  14764. --
  14765.       NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  14766.       PARSE(INPUT_BUFFER(1..MAX));
  14767. --
  14768. <<TRANSMITTER_DATA_CALL>>
  14769.       If XARRAY(1) > 3.0E+11 Then
  14770.          New_line;
  14771.          Put(XARRAY(1));
  14772.          Put(" is not an acceptable frequency.");
  14773.          Goto FREQUENCY;
  14774.       End If;
  14775. --
  14776.       If FREXMT(IXMT) /= XARRAY(1) Then
  14777.          NEW_TITLE_CHECK;
  14778.       End If;
  14779. --
  14780.       FREXMT(IXMT) := XARRAY(1);
  14781.       TRANSMITTER_DATA(IXMT, FREXMT(IXMT), IFLG, INOADD);
  14782.       If IFLG = 1 Then
  14783.          Return;
  14784.       End If;
  14785.       If INOADD /= 0 Then
  14786.          New_line;
  14787.          Put("No transmitter data was added or changed in this ");
  14788.          Put("transmitter class");
  14789.          IERR := 1;
  14790.          Return;
  14791.       End If;
  14792. --
  14793.       Return;
  14794. --
  14795.       End TRANSMITTER_ADD;
  14796. --
  14797. --
  14798.       Procedure TRANSMITTER_DATA (INUMBR: in integer;
  14799.                                   FREQ: in float;
  14800.                                   IFLG: in out integer;
  14801.                                   INOADD: out integer) is
  14802. --
  14803. --#PURPOSE: TRANSMITTER_DATA is responsible for accepting and checking any 
  14804. --          data entered for a given transmitter class.
  14805. --
  14806. --#AUTHOR:  J. Conrad
  14807. --
  14808. --#TYPE:    I/O Processing
  14809. --
  14810. --#PARAMETER DESCRIPTIONS:
  14811. --IN        INUMBR = The index number of the transmitter class being
  14812. --                   added.
  14813. --IN        FREQ   = The frequency of the transmitter class.
  14814. --IO        IFLG   = Flag indicating,
  14815. --                   0...Addition
  14816. --                   1...Modify or like
  14817. --OUT       INOADD = The stop flag where,
  14818. --                      0 means that all additions were
  14819. --                        normal,
  14820. --                      1 means that an addition was terminated
  14821. --                        before completion.
  14822. --
  14823. --#CALLED BY:
  14824. --          TRANSMITTER_ADD
  14825. --
  14826. --#CALLS TO:
  14827. --          ANTENNA_CHECK
  14828. --          BLANK_CHECK
  14829. --          HELP_CHECK
  14830. --          PARSE
  14831. --          TRANSMITTER_HELP
  14832. --
  14833. --#TECHNICAL DESCRIPTION:
  14834. --          TRANSMITTER_DATA is responsible for accepting and checking any 
  14835. --          data entered for a given transmitter class.  Straightforward
  14836. --          branching on transmitter class type and comparison testing
  14837. --          is employed to select only the data that is appropriate
  14838. --          for each type of transmitter class.
  14839. --
  14840.       I: integer;
  14841.       LCTYP: BAND_TYPES;
  14842.       IATYP: integer;
  14843.       TRP: float;
  14844.       GNX: float;
  14845.       HTX: float;
  14846.       LNX: float;
  14847.       TAX: float;
  14848.       IERR: integer;
  14849. --
  14850.       Begin
  14851. --
  14852. --INITIALIZE.
  14853.       INOADD := 0;
  14854.       LCTYP := ITPXMT(INUMBR);
  14855.       IATYP := IATXMT(INUMBR);
  14856.       TRP   := TRPXMT(INUMBR);
  14857.       GNX   := ANTGNX(INUMBR);
  14858.       HTX   := ANTHTX(INUMBR);
  14859.       LNX   := ANTLNX(INUMBR);
  14860.       TAX   := ANTTAX(INUMBR);
  14861. --
  14862. --ASSIGN TRANSMITTER CLASS TYPE.
  14863.       If FREQ < 3.0 Then
  14864.          LCTYP := HARD_WIRED;
  14865.          New_line;
  14866.          Put("HARD_WIRED type of link assigned to transmitter.");
  14867.          Goto ACCEPT_DATA;
  14868.       End If;
  14869.       If FREQ <= 3.0E+03 Then
  14870.          LCTYP := ELF;
  14871.       Elsif FREQ > 3.0E+03 and FREQ <= 3.0E+04 Then
  14872.          LCTYP := VLF;
  14873.       Elsif FREQ > 3.0E+04 and FREQ <= 3.0E+05 Then
  14874.          LCTYP := LF;
  14875.       Elsif FREQ > 3.0E+05 and FREQ <= 3.0E+06 Then
  14876.          LCTYP := MF;
  14877.       Elsif FREQ > 3.0E+06 and FREQ <= 3.0E+07 Then
  14878.          LCTYP := HF;
  14879.       Elsif FREQ > 3.0E+07 and FREQ <= 3.0E+08 Then
  14880.          LCTYP := VHF;
  14881.       Elsif FREQ > 3.0E+08 and FREQ <= 3.0E+09 Then
  14882.          LCTYP := UHF;
  14883.       Elsif FREQ > 3.0E+09 and FREQ <= 3.0E+10 Then
  14884.          LCTYP := SHF;
  14885.       Elsif FREQ > 3.0E+10 and FREQ <= 3.0E+11 Then
  14886.          LCTYP := EHF;
  14887.       End If;
  14888.       New_line;
  14889.       Put(Band_types'image(LCTYP));
  14890.       Put(" frequency class assigned.");
  14891. --
  14892. <<TRANSMITTER_POWER>>
  14893.       New_line;
  14894.       Put("Transmitter power: ");
  14895.       Put(TRP);
  14896.       Case LCTYP is
  14897.          When ELF => Put(" Amp-Meters"); New_line;
  14898.          When VLF|LF => Put(" kW"); New_line;
  14899.          When Others => Put(" dBW"); New_line;
  14900.       End Case;
  14901.       Get_line(INPUT_BUFFER, MAX);
  14902.       If INPUT_BUFFER(1) = '=' Then
  14903.          Goto FLAG_CHECK;
  14904.       End If;
  14905.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  14906.          TRANSMITTER_HELP(6);
  14907.          Goto TRANSMITTER_POWER;
  14908.       End If;
  14909.       If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  14910.          NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  14911.          PARSE(INPUT_BUFFER(1..MAX));
  14912.          If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  14913.             Goto TRANSMITTER_POWER;
  14914.          End If;
  14915.          NEW_TITLE_CHECK;
  14916.          TRP := XARRAY(1);
  14917.       End If;
  14918. --
  14919. <<ANTENNA_TYPE>>
  14920.       If LCTYP = HARD_WIRED or LCTYP = ELF or LCTYP = VLF Then
  14921.          IATYP := 0;
  14922.       Else
  14923.          If IATYP=0 then        -- Set some default antenna types
  14924.             If LCTYP = LF Then
  14925.                IATYP := 1;
  14926.             Elsif LCTYP in MF..HF Then
  14927.                IATYP := 5;
  14928.             Elsif LCTYP in VHF..EHF Then
  14929.                IATYP := 3;
  14930.             End if;  
  14931.          End If;
  14932.          New_line;
  14933.          Put(Band_types'image(LCTYP));
  14934.          Put(" Antenna type: ");
  14935.          Put(IATYP); New_line;
  14936.          Get_line(INPUT_BUFFER, MAX);
  14937.          If INPUT_BUFFER(1) = '=' Then
  14938.             Goto FLAG_CHECK;
  14939.          End If;
  14940.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  14941.             TRANSMITTER_HELP(7);
  14942.             Goto ANTENNA_TYPE;
  14943.          End If;
  14944.          If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  14945.             NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  14946.             PARSE(INPUT_BUFFER(1..MAX));
  14947.             If NUMBER_OF_VARIABLES_EXTRACTED /= 1 or XARRAY(1) < 1.0 or
  14948.                XARRAY(1) > 8.0 Then
  14949.                Goto ANTENNA_TYPE;
  14950.             End If;
  14951.             NEW_TITLE_CHECK;
  14952.             IATYP := INTEGER(XARRAY(1));
  14953.          End If;
  14954.          ANTENNA_CHECK (IATYP, LCTYP, GNX, HTX, LNX, TAX, IERR);
  14955.          If IERR > 1 Then
  14956.             Goto ANTENNA_TYPE;
  14957.          End If;
  14958.          If IERR = 1 Then
  14959.             Goto FLAG_CHECK;
  14960.          End If;
  14961.       End If;
  14962. --
  14963. <<ACCEPT_DATA>>
  14964.       ITPXMT(INUMBR) := LCTYP;
  14965.       IATXMT(INUMBR) := IATYP;
  14966.       FREXMT(INUMBR) := FREQ;
  14967.       TRPXMT(INUMBR) := TRP;
  14968.       ANTGNX(INUMBR) := GNX;
  14969.       ANTHTX(INUMBR) := HTX;
  14970.       ANTLNX(INUMBR) := LNX;
  14971.       ANTTAX(INUMBR) := TAX;
  14972.       Return;
  14973. --
  14974. <<FLAG_CHECK>>
  14975.       If IFLG /= 1 Then 
  14976.          INOADD := 1;
  14977.       End If;
  14978.       Return;
  14979. --
  14980.       End TRANSMITTER_DATA;
  14981. --
  14982. --
  14983.       Procedure TRANSMITTER_DISPLAY (IBUFF: in L_ARRAY; 
  14984.                                      NV: in out integer) is
  14985. --
  14986. --#PURPOSE: TRANSMITTER_DISPLAY displays the requested transmitter classes to 
  14987. --          either the printer or the terminal depending on the value of 
  14988. --          CURRENT_COMMAND.
  14989. --
  14990. --#AUTHOR:  J. Conrad
  14991. --
  14992. --#TYPE:    Output module
  14993. --
  14994. --#PARAMETER DESCRIPTIONS:
  14995. --IN        IBUFF  = The array containing the transmitter class numbers to 
  14996. --                   be displayed.
  14997. --IN        NV     = The number of elements in IBUFF.
  14998. --
  14999. --#CALLED BY:
  15000. --          TRANSMITTER_HANDLER
  15001. --
  15002. --#CALLS TO:
  15003. --          INTEGER_TO_ALPHA
  15004. --          TRANSMITTER_FIND
  15005. --
  15006. --#TECHNICAL DESCRIPTION:
  15007. --          TRANSMITTER_DISPLAY displays only the transmitter classes listed 
  15008. --          in IBUFF as long as NV is not 0 on entry.  When NV is 0 this
  15009. --          signals that all transmitters should be displayed, therefore if 
  15010. --          many transmitters exist, and the specified device is the terminal, 
  15011. --          this can cause data to scroll off the screen.
  15012. --
  15013. --
  15014.       ICOMPL: boolean;
  15015.       I,INUM: integer;
  15016.       KNREC: string(1..6);
  15017. --
  15018.       Begin
  15019. --
  15020. --
  15021. --SET THE OUTPUT DEVICE.
  15022.       If CURRENT_COMMAND = PRINT Then
  15023.          SET_OUTPUT(PRINTER_OUTPUT_FILE);
  15024.       End If;
  15025. --
  15026. --GET THE NUMBER OF TRANSMITTER CLASSES TO DISPLAY AND THE DEVICE NUMBER.
  15027.       ICOMPL := FALSE;
  15028.       If NV = 0 or NV = NUMXMT Then
  15029.          ICOMPL := TRUE;
  15030.       End If;
  15031. --
  15032. --PRINT OUT REPORT HEADER.
  15033.       If ICOMPL Then
  15034.          New_line;
  15035.          Put(TITLE);
  15036.          New_line;New_line;
  15037.          Put("                    TRANSMITTER SUMMARY");
  15038.          New_line;
  15039.          Put("               There are currently ");
  15040.          Put(NUMXMT);
  15041.          Put(" transmitter classes");
  15042.          New_line;
  15043.          NV := NUMXMT;
  15044.       End If;
  15045. --
  15046. --LOOP ON NUMBER OF TRANSMITTER CLASSES TO PRINT.
  15047.       If NV < 1 Then
  15048.          Return;
  15049.       End If;
  15050.       For I in 1..NV Loop
  15051.          If I /= 1 Then
  15052.             Put("====================================");
  15053.             Put("====================================");
  15054.          End If;
  15055.          TRANSMITTER_FIND(IBUFF(I), INUM);
  15056.          If INUM < 1 Then
  15057.             --RESET THE OUTPUT DEVICE.
  15058.             If CURRENT_COMMAND = PRINT Then
  15059.                SET_OUTPUT(STANDARD_OUTPUT);
  15060.             End If;
  15061.             INTEGER_TO_ALPHA (IBUFF(I), KNREC);
  15062.             New_line;
  15063.             Put("Transmitter class ");
  15064.             Put(KNREC);
  15065.             Put(" does not yet exist.");
  15066.             --SET THE OUTPUT DEVICE.
  15067.             If CURRENT_COMMAND = PRINT Then
  15068.                SET_OUTPUT(PRINTER_OUTPUT_FILE);
  15069.             End If;
  15070.             Goto END_OF_LOOP;
  15071.          End If;
  15072.          INTEGER_TO_ALPHA(NAMXMT(INUM), KNREC);
  15073.          If ITPXMT(INUM) = HARD_WIRED Then
  15074.             New_line;
  15075.             Put("Transmitter ");
  15076.             Put(KNREC);
  15077.             Put(" is a HARD_WIRED class.");
  15078.             Goto END_OF_LOOP;
  15079.          End If;
  15080.          New_line;
  15081.          Put("Transmitter name.........");
  15082.          Put(KNREC);
  15083.          Put("          Frequency class...");
  15084.          Put(band_types'image(ITPXMT(INUM)));
  15085.          New_line;
  15086.          Put("Frequency (Hz)..........");
  15087.          Put(FREXMT(INUM),2,5,3);
  15088.          Put("     Power.............");
  15089.          Put(TRPXMT(INUM),2,5,3);
  15090.          Case ITPXMT(INUM) is
  15091.             When ELF => Put(" Amp-Meters");
  15092.             When VLF|LF => Put(" kW");
  15093.             When Others => Put(" dBW");
  15094.          End Case;
  15095.          New_line;
  15096.          If ITPXMT(INUM) > VLF Then
  15097.             New_line;
  15098.             Put("Antenna type..........");
  15099.             If IATXMT(INUM) = 1 Then
  15100.                Put("Loop");
  15101.             Elsif IATXMT(INUM) = 2 Then
  15102.                Put("Whip");
  15103.             Elsif IATXMT(INUM) = 3 Then
  15104.                Put("Dish with tapered side lobe");
  15105.             Elsif IATXMT(INUM) = 4 Then
  15106.                Put("Dish with constant side lobe");
  15107.             Elsif IATXMT(INUM) = 5 Then
  15108.                Put("Constant gain");
  15109.             Elsif IATXMT(INUM) = 6 Then
  15110.                Put("Rhombic");
  15111.             Elsif IATXMT(INUM) = 7 Then
  15112.                Put("Vertical");
  15113.             Elsif IATXMT(INUM) = 8 Then
  15114.                Put("Horizontal half-wave dipole");
  15115.             End If;
  15116.          End If;
  15117.          If IATXMT(INUM) = 5 Then
  15118.             New_line;
  15119.             Put("Antenna gain (dB).....");
  15120.             Put(ANTGNX(INUM),2,5,3);
  15121.          Elsif IATXMT(INUM) = 6 Then
  15122.             New_line;
  15123.             Put("Ant tilt angle (deg)..");
  15124.             Put(ANTTAX(INUM),2,1,0);
  15125.             New_line;
  15126.             Put("Antenna height (m)....");
  15127.             Put(ANTHTX(INUM),2,5,3);
  15128.             New_line;
  15129.             Put("Ant leg length (m)....");
  15130.             Put(ANTLNX(INUM),2,5,3);
  15131.          Elsif IATXMT(INUM) = 7 Then
  15132.             New_line;
  15133.             Put("Ant leg length (m)....");
  15134.             Put(ANTLNX(INUM),2,5,3);
  15135.          Elsif IATXMT(INUM) = 8 Then
  15136.             New_line;
  15137.             Put("Antenna height (m)....");
  15138.             Put(ANTHTX(INUM),2,5,3);
  15139.          End If;
  15140. <<END_OF_LOOP>>
  15141.          Null;
  15142.          New_line;
  15143.       End Loop;
  15144. --
  15145. --RESET THE OUTPUT DEVICE.
  15146.       If CURRENT_COMMAND = PRINT Then
  15147.          SET_OUTPUT(STANDARD_OUTPUT);
  15148.       End If;
  15149. --
  15150.       Return;
  15151. --
  15152.       End TRANSMITTER_DISPLAY;
  15153. --
  15154. --
  15155.       Procedure TRANSMITTER_FETCH (KNAME: out string;
  15156.                                    INAME: out long_integer;
  15157.                                    INUMBR: out integer;
  15158.                                    ISTOP: out integer) is
  15159. --
  15160. --#PURPOSE: TRANSMITTER_FETCH obtains a transmitter class from the 
  15161. --          transmitter data structure.
  15162. --
  15163. --#AUTHOR:  J. Conrad
  15164. --
  15165. --#TYPE:    Table Look-up
  15166. --
  15167. --#PARAMETER DESCRIPTIONS:
  15168. --OUT       KNAME  = The transmitter class name string.
  15169. --OUT       INAME  = The coded transmitter class name.
  15170. --OUT       INUMBR = The location of INAME in the transmitter
  15171. --                   data structure.
  15172. --                   A value of zero (0) is returned if INAME
  15173. --                   cannot be located.
  15174. --OUT       ISTOP  = Flag to tell if = is encountered
  15175. --                   0...No = encountered
  15176. --                   1...A terminator = was encountered
  15177. --
  15178. --#CALLED BY:
  15179. --          TRANSMITTER_HANDLER
  15180. --
  15181. --#CALLS TO:
  15182. --          BLANK_CHECK
  15183. --          INTEGER_TO_ALPHA
  15184. --          PARSE
  15185. --          TRANSMITTER_FIND
  15186. --
  15187. --#TECHNICAL DESCRIPTION:
  15188. --          TRANSMITTER_FETCH queries the operator for a transmitter class 
  15189. --          name then does a table lookup in the transmitter data structure 
  15190. --          for the specified transmitter class.  When the transmitter class
  15191. --          is located, its position in the structure is returned in the
  15192. --          variable INUMBR.  If the transmitter cannot be located, a value
  15193. --          of zero is returned in INUMBR.
  15194. --
  15195.       Begin
  15196. --
  15197.       ISTOP := 0;
  15198. --
  15199. <<GET_TRANSMITTER_CLASS_NAME>>
  15200.       New_line;
  15201.       Put("Enter the transmitter class name: ");
  15202.       Get_line(INPUT_BUFFER, MAX);
  15203.       KNAME := INPUT_BUFFER(1..6);
  15204.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  15205.          Goto GET_TRANSMITTER_CLASS_NAME;
  15206.       End If;
  15207.       If INPUT_BUFFER(1) = '=' Then
  15208.          ISTOP := 1;
  15209.          Return;
  15210.       End If;
  15211.       NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  15212.       PARSE (INPUT_BUFFER(1..MAX));
  15213.       If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  15214.          Goto GET_TRANSMITTER_CLASS_NAME;
  15215.       End If;
  15216.       INAME:=IARRAY(1);
  15217.       INTEGER_TO_ALPHA(IARRAY(1), KNAME);
  15218.       TRANSMITTER_FIND (IARRAY(1), INUMBR);
  15219. --
  15220.       Return;
  15221. --
  15222.       End TRANSMITTER_FETCH;
  15223. --
  15224. --
  15225.       Procedure TRANSMITTER_FIND (INAME: in long_integer; 
  15226.                                   INUMBR: out integer) is
  15227. --
  15228. --#PURPOSE: TRANSMITTER_FIND locates a transmitter class in the transmitter 
  15229. --          data structure.
  15230. --
  15231. --#AUTHOR:  J. Conrad
  15232. --
  15233. --#TYPE:    Table Look-up
  15234. --
  15235. --#PARAMETER DESCRIPTIONS:
  15236. --IN        INAME  = The coded transmitter class name.
  15237. --OUT       INUMBR = The location of INAME in the transmitter data structure.
  15238. --                   A value of zero (0) is returned if INAME cannot be 
  15239. --                   located.
  15240. --
  15241. --#CALLED BY:
  15242. --          TRANSMITTER_HANDLER
  15243. --          TRANSMITTER_ADD
  15244. --          TRANSMITTER_DISPLAY
  15245. --          TRANSMITTER_FETCH
  15246. --          TRANSMITTER_REMOVE
  15247. --
  15248. --#CALLS TO:
  15249. --          'NONE'
  15250. --
  15251. --#TECHNICAL DESCRIPTION:
  15252. --          TRANSMITTER_FIND does a table lookup in the transmitter data 
  15253. --          structure the specified transmitter class.  When the transmitter 
  15254. --          class is located, its position in the structure is returned in 
  15255. --          the variable INUMBR.  If the transmitter class cannot be located, 
  15256. --          a value of zero is returned in INUMBR.
  15257. --
  15258.       KNAME: string(1..6);
  15259.       I: integer;
  15260. --
  15261.       Begin
  15262. --
  15263.       INUMBR := 0;
  15264.       If NUMXMT < 1 Then
  15265.          Return;
  15266.       End If;
  15267. --
  15268. --SEARCH THE DATA STRUCTURE FOR THE TRANSMITTER CLASS.
  15269.       For I in 1..NUMXMT Loop
  15270.          If INAME = NAMXMT(I) Then
  15271.             INUMBR := I;
  15272.             Return;
  15273.          End If;
  15274.       End Loop;
  15275.       Return;
  15276. --
  15277.       End TRANSMITTER_FIND;
  15278. --
  15279. --
  15280.       Procedure TRANSMITTER_HANDLER is
  15281. --
  15282. --#PURPOSE: TRANSMITTER_HANDLER drives the transmitter class processing 
  15283. --          routines.
  15284. --
  15285. --#AUTHOR:  J. Conrad
  15286. --
  15287. --#TYPE:    I/O PROCESSING
  15288. --
  15289. --#PARAMETER DESCRIPTIONS:
  15290. --          'NONE'
  15291. --
  15292. --#CALLED BY:
  15293. --          MAIN
  15294. --          PRINT_HANDLER
  15295. --
  15296. --#CALLS TO:
  15297. --          BLANK_CHECK
  15298. --          INTEGER_TO_ALPHA
  15299. --          PARSE
  15300. --          TRANSMITTER_ADD
  15301. --          TRANSMITTER_DISPLAY
  15302. --          TRANSMITTER_FETCH
  15303. --          TRANSMITTER_FIND
  15304. --          TRANSMITTER_REMOVE
  15305. --
  15306. --#TECHNICAL DESCRIPTION:
  15307. --          TRANSMITTER_HANDLER serves as the driver for the routines which
  15308. --          add, delete, and modify transmitter classes.  Trickle down logic 
  15309. --          is used to select the desired command.
  15310. --
  15311.       INAME: L_ARRAY(1..MAXRNT);
  15312.       IFLG,NV,I,K: integer;
  15313.       KNAME:string(1..6);
  15314.       JNAME: long_integer;
  15315.       JNUMBR, ISTOP, IERR, INUMBR: integer;
  15316. --
  15317.       Begin
  15318. --
  15319. --INITIALIZE.
  15320.       IFLG := 0;
  15321.       NV := 0;
  15322. --
  15323.       Case CURRENT_COMMAND is
  15324.       When ADD =>
  15325. <<ADD_TRANSMITTER>>
  15326.          TRANSMITTER_FETCH (KNAME, JNAME, JNUMBR, ISTOP);
  15327.          If ISTOP = 1 Then
  15328.             Return;
  15329.          End If;
  15330.          If JNUMBR >= 1 Then
  15331.             New_line;
  15332.             Put("Transmitter class ");
  15333.             Put(KNAME);
  15334.             Put(" already exists.");
  15335.             Goto ADD_TRANSMITTER;
  15336.          End If;
  15337.          If NUMXMT >= MAXRNT Then
  15338.             New_line;
  15339.             Put("No more transmitter classes may be added.");
  15340.             Put("  Redimension transmitter arrays.");
  15341.             Return;
  15342.          End If;
  15343.          NUMXMT := NUMXMT + 1;
  15344.          JNUMBR := NUMXMT;
  15345.          NAMXMT (JNUMBR) := JNAME;
  15346.          ITPXMT (JNUMBR) := ELF;
  15347.          IATXMT (JNUMBR) := 0;
  15348.          FREXMT (JNUMBR) := 3.0;
  15349.          TRPXMT (JNUMBR) := 0.0;
  15350.          ANTGNX (JNUMBR) := 0.0;
  15351.          ANTHTX (JNUMBR) := 0.0;
  15352.          ANTLNX (JNUMBR) := 0.0;
  15353.          ANTTAX (JNUMBR) := 0.0;
  15354.          TRANSMITTER_ADD (JNUMBR, IFLG, IERR);
  15355.          If IERR = 0 Then
  15356.             Goto ADD_TRANSMITTER;
  15357.          End If;
  15358. --
  15359. --TRANSMITTER CLASS ADDITION WAS TERMINATED.
  15360.          NUMXMT := NUMXMT - 1;
  15361.          Return;
  15362. --
  15363. --PROCESS THE VIEW OR PRINT COMMANDS.
  15364.       When VIEW | PRINT =>
  15365.          NV := NUMXMT;
  15366.          If NV >= 1 Then
  15367.             For K in 1..NUMXMT Loop
  15368.                INAME(K) := NAMXMT(K);
  15369.             End Loop;
  15370.             If not BLANK_CHECK(ARGUMENT_BUFFER) Then
  15371.                NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  15372.                PARSE(ARGUMENT_BUFFER);
  15373.                NV := NUMBER_OF_VARIABLES_EXTRACTED;
  15374.                For K in 1..NV Loop
  15375.                   INAME(K) := IARRAY(K);
  15376.                End Loop;
  15377.             End If;
  15378.          End If;
  15379.          TRANSMITTER_DISPLAY (INAME, NV);
  15380.          Return;
  15381. --
  15382. --PROCESS THE DELETION COMMAND.
  15383.       When DEL =>
  15384.          Loop
  15385.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  15386.             New_line;
  15387.             Put("Enter the transmitter class names to be deleted,");
  15388.             Put(" separated by spaces.");
  15389.             New_line;
  15390.             Get_line(ARGUMENT_BUFFER, MAX);
  15391.          End Loop;
  15392.          If ARGUMENT_BUFFER(1) = '=' Then
  15393.             Return;
  15394.          End If;
  15395.          NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  15396.          PARSE(ARGUMENT_BUFFER);
  15397.          NV := NUMBER_OF_VARIABLES_EXTRACTED;
  15398.          If NV <= 0 Then
  15399.             NV := 1;
  15400.          End If;
  15401.          TRANSMITTER_REMOVE(IARRAY, NV);
  15402.          Return;
  15403. --
  15404. --PROCESS THE MODIFY COMMAND.
  15405.       When MODIFY =>
  15406.          IFLG := 1;
  15407.          Loop
  15408.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  15409.             New_line;
  15410.             Put("Enter the name of the transmitter class to be modified: ");
  15411.             Get_line(ARGUMENT_BUFFER, MAX);
  15412.          End Loop;
  15413.          If ARGUMENT_BUFFER(1) = '=' Then
  15414.             Return;
  15415.          End If;
  15416.          NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  15417.          PARSE(ARGUMENT_BUFFER);
  15418.          If NUMBER_OF_VARIABLES_EXTRACTED > 0 Then
  15419.             TRANSMITTER_FIND (IARRAY(1), INUMBR);
  15420.             INTEGER_TO_ALPHA (IARRAY(1), KNAME);
  15421.             If INUMBR <= 0 Then
  15422.                New_line;
  15423.                Put("Transmitter class name ");
  15424.                Put(KNAME);
  15425.                Put(" does not exist.");
  15426.                Return;
  15427.             End If;
  15428.             TRANSMITTER_ADD (INUMBR, IFLG, IERR);
  15429.          End If;
  15430. --
  15431. --ILLEGAL COMMAND WARNING.
  15432.       When others =>
  15433.          New_line;
  15434.          Put("The command code is not valid for transmitter class processing.");
  15435.          Return;
  15436.       End case;
  15437. --
  15438.       End TRANSMITTER_HANDLER;
  15439. --
  15440. --
  15441.       Procedure TRANSMITTER_HELP (IWHO: in integer) is
  15442. --
  15443. --#PURPOSE: TRANSMITTER_HELP prints the various help messages as requested 
  15444. --          by the operator for the different levels of transmitter class
  15445. --          processing.
  15446. --
  15447. --#AUTHOR:  J. Conrad
  15448. --
  15449. --#TYPE:    Operator assistance
  15450. --
  15451. --#PARAMETER DESCRIPTIONS:
  15452. --IN        IWHO   := The indicator flag for which help message to print.
  15453. --
  15454. --#CALLED BY:
  15455. --          TRANSMITTER_ADD
  15456. --          TRANSMITTER_DATA
  15457. --
  15458. --#CALLS TO:
  15459. --          'NONE'
  15460. --
  15461. --#TECHNICAL DESCRIPTION:
  15462. --          TRANSMITTER_HELP prints the various help messages as requested 
  15463. --          by the operator for the different levels of transmitter class
  15464. --          processing.  The value of IWHO determines the message to
  15465. --          display.
  15466. --
  15467.       Begin
  15468. --
  15469. --SELECT THE HELP MESSAGE TO DISPLAY.
  15470.       If IWHO = 1 Then
  15471.          New_line;
  15472.          Put("At this point you can enter the frequency in Hz of the ");
  15473.          Put("transmitter. The range");  
  15474.          New_line;
  15475.          Put("of frequency is from 3Hz to 3.0E+11 Hz.  If the transmitter ");
  15476.          Put("frequency that was");  
  15477.          New_line;
  15478.          Put("just echoed is satisfactory, then simply enter a carriage");
  15479.          Put("return.  You may also");
  15480.          New_line;
  15481.          Put("enter  L  or  LIKE  to set this transmitter up exactly like ");
  15482.          Put("some other transmitter.");  
  15483.          New_line;
  15484.          Put("Finally, you may enter  N  or  NONE  to signify that a ");
  15485.          Put("HARD_WIRED link is");
  15486.          New_line;
  15487.          Put("desired.");
  15488.          New_line;
  15489.          Put("An = (equal sign) terminates the addition of this transmitter ");
  15490.          Put("with the current");
  15491.          New_line;
  15492.          Put("information to this point and the transmitter lost, unless ");
  15493.          Put("this addition is");
  15494.          New_line;
  15495.          Put("-like- some other transmitter, then it is saved.");
  15496.          New_line;
  15497.          Return;
  15498.       End If;      
  15499. --
  15500.       If IWHO = 2 Then
  15501.          New_line;
  15502.          Put("Since you have specified that this transmitter should be "); 
  15503.          Put("like some other");
  15504.          New_line;
  15505.          Put("transmitter, you must now enter the name of the transmitter ");
  15506.          Put("that has already");
  15507.          New_line;
  15508.          Put("been entered which has the data that should be used to define ");
  15509.          Put("this transmitter.");
  15510.          New_line;
  15511.          Put("If you made a mistake and don't want this feature, then enter ");
  15512.          Put("an = to take you");
  15513.          New_line;
  15514.          Put("back to the executive for another command.");
  15515.          New_line;
  15516.          Return;
  15517.       End If;
  15518. --
  15519.       If IWHO = 3 Then
  15520.          New_line;
  15521.          Put("Enter a class name (maximum of 6 characters). ");
  15522.          New_line;
  15523.          Put("An = (equal sign) terminates the addition of this transmitter ");
  15524.          Put("with the current");
  15525.          New_line;
  15526.          Put("information to this point and the transmitter lost, unless ");
  15527.          Put("this addition is");
  15528.          New_line;
  15529.          Put("-like- some other transmitter, then it is saved.");
  15530.          New_line;
  15531.          Return;
  15532.       End If;
  15533. --
  15534.       If IWHO = 6 Then
  15535.          New_line;
  15536.          Put("If the transmitter radiating power just echoed is ");
  15537.          Put("satisfactory then enter a");
  15538.          New_line;
  15539.          Put("carriage return.  Otherwise, enter the transmitter ");
  15540.          Put("radiating power.");
  15541.          New_line;
  15542.          Put("The units are Amp-Meters for ELF, kW for VLF or LF, or");
  15543.          Put("dBW for all");
  15544.          New_line;
  15545.          Put("other frequency classes.");
  15546.          New_line;
  15547.          Put("An = (equal sign) terminates the addition of this transmitter ");
  15548.          Put("with the current");
  15549.          New_line;
  15550.          Put("information to this point and the transmitter lost, unless ");
  15551.          Put("this addition is");
  15552.          New_line;
  15553.          Put("-like- some other transmitter, then it is saved.");
  15554.          New_line;
  15555.          Return;
  15556.       End If;
  15557. --
  15558.       If IWHO = 7 Then
  15559.          New_line;
  15560.          Put("If the antenna type just echoed is satisfactory then enter ");
  15561.          Put("a carriage return.");
  15562.          New_line;
  15563.          Put("Otherwise, enter the value of the transmitter antenna type.  ");
  15564.          Put("The value must be:");
  15565.          New_line;
  15566.          Put("   1 - loop type (LF only);");
  15567.          New_line;
  15568.          Put("   2 - whip type (LF only);");
  15569.          New_line;
  15570.          Put("   3 - dish with tapered side lobe (VHF and above only);");
  15571.          New_line;
  15572.          Put("   4 - dish with constant side lobe (VHF and above only);");
  15573.          New_line;
  15574.          Put("   5 - constant gain (MF and HF only);");
  15575.          New_line;
  15576.          Put("   6 - rhombic (MF and HF only);");
  15577.          New_line;
  15578.          Put("   7 - vertical (MF and HF only); or,");
  15579.          New_line;
  15580.          Put("   8 - horizontal half-wave dipole (MF and HF only).");
  15581.          New_line;
  15582.          Put("An = (equal sign) terminates the addition of this transmitter ");
  15583.          Put("with the current");
  15584.          New_line;
  15585.          Put("information to this point and the transmitter lost, unless ");
  15586.          Put("this addition is");
  15587.          New_line;
  15588.          Put("-like- some other transmitter, then it is saved.");
  15589.          New_line;
  15590.          Return;
  15591.       End If;
  15592. --
  15593.       End TRANSMITTER_HELP;
  15594. --
  15595. -- 
  15596.       Procedure TRANSMITTER_REMOVE (IBUFF: in out L_ARRAY;
  15597.                                     NUMBR: in integer) is
  15598. --
  15599. --#PURPOSE: TRANSMITTER_REMOVE removes a specified transmitter class from the
  15600. --          data base.
  15601. --
  15602. --#AUTHOR:  J. Conrad
  15603. --
  15604. --#TYPE:    I/O Processing
  15605. --
  15606. --#PARAMETER DESCRIPTIONS:
  15607. --IN        IBUFF  = The array containing the transmitter class names
  15608. --                   to be deleted.
  15609. --IN        NUMBR  = The number of transmitter class names in IBUFF.
  15610. --
  15611. --#CALLED BY:
  15612. --          TRANSMITTER_HANDLER
  15613. --
  15614. --#CALLS TO:
  15615. --          INTEGER_TO_ALPHA
  15616. --          TRANSMITTER_FIND
  15617. --
  15618. --#TECHNICAL DESCRIPTION:
  15619. --          TRANSMITTER_REMOVE removes a specified transmitter class from the
  15620. --          data base.  Before a transmitter class is removed, a check
  15621. --          is first made to be sure that some node does not use
  15622. --          the transmitter class.  If such a node is found, a message
  15623. --          indicating the problem is issued to the operator.  If
  15624. --          no node conflict is found, the transmitter class is effectively
  15625. --          removed by shifting each transmitter class with an index value
  15626. --          higher than the one being removed down by one.
  15627. --
  15628.       KNAM: string(1..6);
  15629.       KNAME2: string(1..6);
  15630.       I,J,L,N: integer;
  15631.       JNUM: integer;
  15632. --
  15633.       Begin
  15634. --
  15635. --CHECK IBUFF FOR USE AT A NODE.
  15636.       If NUMNOD > 0 Then
  15637.          For I in 1..NUMNOD Loop
  15638.             If NXSND(I) > 0 Then
  15639.                For J in 1..NXSND(I) Loop
  15640.                   For L in 1..NUMBR Loop
  15641.                      If IBUFF(L) /= 0 and IBUFF(L) = IXTSND(2,J,I) Then
  15642.                         INTEGER_TO_ALPHA (IBUFF(L), KNAM);
  15643.                         INTEGER_TO_ALPHA (NAMNOD(I), KNAME2);
  15644.                         New_line;
  15645.                         Put("Transmitter ");
  15646.                         Put(KNAM);
  15647.                         Put(" is used at node ");
  15648.                         Put(KNAME2);
  15649.                         Put(".  Modify it first.");
  15650.                         IBUFF(L) := 0;
  15651.                         Exit;
  15652.                      End If;
  15653.                   End Loop;
  15654.                End Loop;
  15655.             End If;
  15656.          End Loop;
  15657.       End If;
  15658. --
  15659. --LOOP ON ALL ELEMENTS TO BE REMOVED.
  15660.       For I in 1..NUMBR Loop
  15661.          If IBUFF(I) /= 0 Then
  15662.             TRANSMITTER_FIND (IBUFF(I), JNUM);
  15663.             If JNUM = 0 Then
  15664.                --
  15665.                --TRYING TO REMOVE A TRANSMITTER CLASS NOT YET ADDED.
  15666.                INTEGER_TO_ALPHA (IBUFF(I), KNAM);
  15667.                New_line;
  15668.                Put("Transmitter class ");
  15669.                Put(KNAM);
  15670.                Put(" not in database...no action taken.");
  15671.             Else
  15672.                --
  15673.                --REMOVE TRANSMITTER CLASS AT LOCATION J
  15674.                NEW_TITLE_CHECK;
  15675.                N := NUMXMT - 1;
  15676.                If N >= JNUM Then
  15677.                   For L in JNUM..N Loop
  15678.                      NAMXMT(L) := NAMXMT(L+1);
  15679.                      ITPXMT(L) := ITPXMT(L+1);
  15680.                      IATXMT(L) := IATXMT(L+1);
  15681.                      FREXMT(L) := FREXMT(L+1);
  15682.                      TRPXMT(L) := TRPXMT(L+1);
  15683.                      ANTGNX(L) := ANTGNX(L+1);
  15684.                      ANTHTX(L) := ANTHTX(L+1);
  15685.                      ANTLNX(L) := ANTLNX(L+1);
  15686.                      ANTTAX(L) := ANTTAX(L+1);
  15687.                   End Loop;
  15688.                End If;
  15689.                NUMXMT := N;
  15690.             End If;
  15691.          End If;
  15692.       End Loop;
  15693. --
  15694.       End TRANSMITTER_REMOVE;
  15695. --
  15696. --
  15697. End TRANSMIT;
  15698. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15699. --RECEIVERS
  15700. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  15701. With Text_IO; use Text_io, float_io, integer_io;
  15702. With Entityuti; use entityuti;
  15703. With types; use Types;
  15704. With Constants; use Constants; with Constant2; use Constant2;
  15705. With Constant3; use Constant3;
  15706. With Helps; use Helps;
  15707. With Debugger; use Debugger;
  15708. Package RECEIVERS is
  15709. --
  15710.       Procedure RECEIVER_ADD (IREC: in integer;
  15711.                               IFLG: in out integer;
  15712.                               IERR: out integer);
  15713.       Procedure RECEIVER_DATA (INUMBR: in integer;
  15714.                                FREQ: in float;
  15715.                                IFLG: in out integer;
  15716.                                INOADD: out integer);
  15717.       Procedure RECEIVER_DISPLAY (IBUFF: in L_ARRAY; 
  15718.                                   NV: in out integer);
  15719.       Procedure RECEIVER_FETCH (KNAME: out string;
  15720.                                 INAME: out long_integer;
  15721.                                 INUMBR: out integer;
  15722.                                 ISTOP: out integer);
  15723.       Procedure RECEIVER_FIND (INAME: in long_integer; 
  15724.                                INUMBR: out integer);
  15725.       Procedure RECEIVER_HANDLER;
  15726.       Procedure RECEIVER_HELP (IWHO: in integer);
  15727.       Procedure RECEIVER_REMOVE (IBUFF: in out L_ARRAY;
  15728.                                  NUMBR: in integer);
  15729. --
  15730. End RECEIVERS;
  15731. -- 
  15732. Package body RECEIVERS is
  15733. --
  15734. -- RECEIVERS Package of PROP_LINK Version 1.0, February 12, 1985
  15735. --
  15736. -- This RECEIVERS Package contains all of the procedures that manipulate 
  15737. -- receiver data.
  15738. --
  15739. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  15740. -- radio frequency propagation prediction code.
  15741. --
  15742. -- PROP_LINK has been developed for the Department of Defense under
  15743. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  15744. -- Systems Inc. (Jim Conrad).
  15745. --
  15746. --
  15747. --
  15748.       Procedure RECEIVER_ADD (IREC: in integer;
  15749.                               IFLG: in out integer;
  15750.                               IERR: out integer) is
  15751. --
  15752. --#PURPOSE: RECEIVER_ADD processes the addition of one or more receiver
  15753. --          classes.
  15754. --
  15755. --#AUTHOR:  J. Conrad
  15756. --
  15757. --#TYPE:    I/O Processing
  15758. --
  15759. --#PARAMETER DESCRIPTIONS:
  15760. --IN        IREC  = The position of the receiver class to be added,
  15761. --                  if 0 on entry, then additions will be allowed
  15762. --                  until a = is entered.
  15763. --IO        IFLG  = Flag indicating,
  15764. --                   0...Addition
  15765. --                   1...Modify or Like
  15766. --OUT       IERR   = The error code where,
  15767. --                   0 means no errors encountered,
  15768. --                   1 means an attempt to add too many
  15769. --                     receiver classes has been made.
  15770. --
  15771. --#CALLED BY:
  15772. --          NODE_HANDLER
  15773. --          RECEIVER_HANDLER
  15774. --
  15775. --#CALLS TO:
  15776. --          BLANK_CHECK
  15777. --          HELP_CHECK
  15778. --          INTEGER_TO_ALPHA
  15779. --          PARSE
  15780. --          RECEIVER_DATA
  15781. --
  15782. --#TECHNICAL DESCRIPTION:
  15783. --          RECEIVER_ADD processes the addition of receiver classes as
  15784. --          well as the replacement of receiver class data when the
  15785. --          modify command has been used.  Echo checking is used
  15786. --          so that the operator may inspect the current value for
  15787. --          each data element.  The "LIKE" command is also supported
  15788. --          so that a receiver class may be specified as being like
  15789. --          some other previously described receiver class.
  15790. --
  15791.       KNAME: string(1..6);
  15792.       INUMBR: integer;
  15793.       INOADD: integer;
  15794. --
  15795.       Begin
  15796. --
  15797. --INITIALIZE.
  15798.       IERR := 0;
  15799. --
  15800. --GET RECEIVER CLASS FREQUENCY.
  15801. <<FREQUENCY>>
  15802.       New_line;
  15803.       Put("Frequency: ");
  15804.       Put(FREREC(IREC));
  15805.       Put(" Hz."); New_line;
  15806.       Get_line(INPUT_BUFFER, MAX);
  15807. --
  15808. --IF A <N>  ENTERED SET RECEIVER CLASS FREQUENCY TO ZERO AND BRANCH TO 
  15809. --RECEIVER_DATA_CALL.
  15810.       If INPUT_BUFFER(1) = 'N' or INPUT_BUFFER(1) = 'n' Then
  15811.          NEW_TITLE_CHECK;
  15812.          XARRAY(1) := 0.0;
  15813.          Goto RECEIVER_DATA_CALL;
  15814.       End If;
  15815. --
  15816. --IF A <CR> ENTERED SAVE THIS DATA ELEMENT AS IS AND GET NEXT ONE.
  15817.       XARRAY(1) := FREREC(IREC);
  15818.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  15819.          Goto RECEIVER_DATA_CALL;
  15820.       End If;
  15821. --
  15822. --IF A = ENTERED TERMINATE WITH ALL VALUES AS THEY ARE RIGHT NOW.
  15823.       If INPUT_BUFFER(1) = '=' Then
  15824.          New_line;
  15825.          Put("No receiver data was added or changed in this receiver class");
  15826.          IERR := 1;
  15827.          Return;
  15828.       End If;
  15829. --
  15830. --IF AN <H> ENTERED THEN PRINT A HELP MESSAGE AND RE-PROMPT.
  15831.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  15832.          RECEIVER_HELP (1);
  15833.          Goto FREQUENCY;
  15834.       End If;
  15835. --
  15836. --IF A <L> ENTERED THEN THIS RECEIVER CLASS IS LIKE SOME OTHER,
  15837. --NOW GET THE OTHER RECEIVER CLASS FOR THIS ASSIGNMENT.
  15838.       If INPUT_BUFFER(1) = 'L' or INPUT_BUFFER(1) = 'l' Then
  15839.          IFLG := 1;
  15840. <<LIKE>>
  15841.          New_line;
  15842.          Put("Which receiver class? ");
  15843.          Get_line(INPUT_BUFFER, MAX);
  15844.          If INPUT_BUFFER(1) = '=' Then
  15845.             New_line;
  15846.             Put("No receiver data was added or changed in this ");
  15847.             Put("receiver class");
  15848.             IERR := 1;
  15849.             Return;
  15850.          End If;
  15851.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  15852.             RECEIVER_HELP(2);
  15853.             Goto LIKE;
  15854.          End If;
  15855.          NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  15856.          PARSE (INPUT_BUFFER(1..MAX));
  15857.          If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  15858.             Goto LIKE;
  15859.          End If;
  15860.          RECEIVER_FIND(IARRAY(1), INUMBR);
  15861.          If INUMBR <= 0 Then
  15862.             INTEGER_TO_ALPHA (IARRAY(1), KNAME);
  15863.             New_line;
  15864.             Put("Receiver class ");
  15865.             Put(KNAME);
  15866.             Put(" was not found.");
  15867.             Goto LIKE;
  15868.          End If;
  15869.          NEW_TITLE_CHECK;
  15870.          ITPREC(IREC) := ITPREC(INUMBR);
  15871.          IATREC(IREC) := IATREC(INUMBR);
  15872.          FREREC(IREC) := FREREC(INUMBR);
  15873.          GTREC(IREC)  := GTREC(INUMBR);
  15874.          BWREC(IREC)  := BWREC(INUMBR);
  15875.          RLLREC(IREC) := RLLREC(INUMBR);
  15876.          ANTGNR(IREC) := ANTGNR(INUMBR);
  15877.          ANTHTR(IREC) := ANTHTR(INUMBR);
  15878.          ANTLNR(IREC) := ANTLNR(INUMBR);
  15879.          ANTTAR(IREC) := ANTTAR(INUMBR);
  15880.          Goto FREQUENCY;
  15881.       End If;
  15882. --
  15883.       NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  15884.       PARSE(INPUT_BUFFER(1..MAX));
  15885. --
  15886. <<RECEIVER_DATA_CALL>>
  15887.       If XARRAY(1) > 3.0E+11 Then
  15888.          New_line;
  15889.          Put(XARRAY(1));
  15890.          Put(" is not an acceptable frequency.");
  15891.          Goto FREQUENCY;
  15892.       End If;
  15893. --
  15894.       If FREREC(IREC) /= XARRAY(1) Then
  15895.          NEW_TITLE_CHECK;
  15896.       End If;
  15897. --
  15898.       FREREC(IREC) := XARRAY(1);
  15899.       RECEIVER_DATA(IREC, FREREC(IREC), IFLG, INOADD);
  15900.       If IFLG = 1 Then
  15901.          Return;
  15902.       End If;
  15903.       If INOADD /= 0 Then
  15904.          New_line;
  15905.          Put("No receiver data was added or changed in this receiver class");
  15906.          IERR := 1;
  15907.          Return;
  15908.       End If;
  15909. --
  15910.       Return;
  15911. --
  15912.       End RECEIVER_ADD;
  15913. --
  15914. --
  15915.       Procedure RECEIVER_DATA (INUMBR: in integer;
  15916.                                FREQ: in float;
  15917.                                IFLG: in out integer;
  15918.                                INOADD: out integer) is
  15919. --
  15920. --#PURPOSE: RECEIVER_DATA is responsible for accepting and checking any 
  15921. --          data entered for a given receiver class.
  15922. --
  15923. --#AUTHOR:  J. Conrad
  15924. --
  15925. --#TYPE:    I/O Processing
  15926. --
  15927. --#PARAMETER DESCRIPTIONS:
  15928. --IN        INUMBR = The index number of the receiver class being
  15929. --                   added.
  15930. --IN        FREQ   = The frequency of the receiver class.
  15931. --IO        IFLG   = Flag indicating,
  15932. --                   0...Addition
  15933. --                   1...Modify or like
  15934. --OUT       INOADD = The stop flag where,
  15935. --                      0 means that all additions were
  15936. --                        normal,
  15937. --                      1 means that an addition was terminated
  15938. --                        before completion.
  15939. --
  15940. --#CALLED BY:
  15941. --          RECEIVER_ADD
  15942. --
  15943. --#CALLS TO:
  15944. --          ANTENNA_CHECK
  15945. --          BLANK_CHECK
  15946. --          HELP_CHECK
  15947. --          PARSE
  15948. --          RECEIVER_HELP
  15949. --
  15950. --#TECHNICAL DESCRIPTION:
  15951. --          RECEIVER_DATA is responsible for accepting and checking any 
  15952. --          data entered for a given receiver class.  Straightforward
  15953. --          branching on receiver class type and comparison testing
  15954. --          is employed to select only the data that is appropriate
  15955. --          for each type of receiver class.
  15956. --
  15957.       I: integer;
  15958.       LCTYP: BAND_TYPES;
  15959.       IATYP: integer;
  15960.       GT: float;
  15961.       BW: float;
  15962.       RLL: float;
  15963.       GNR: float;
  15964.       HTR: float;
  15965.       LNR: float;
  15966.       TAR: float;
  15967.       IERR: integer;
  15968. --
  15969.       Begin
  15970. --
  15971. --INITIALIZE.
  15972.       INOADD := 0;
  15973.       LCTYP := ITPREC(INUMBR);
  15974.       IATYP := IATREC(INUMBR);
  15975.       GT    := GTREC(INUMBR);
  15976.       BW    := BWREC(INUMBR);
  15977.       RLL   := RLLREC(INUMBR);
  15978.       GNR   := ANTGNR(INUMBR);
  15979.       HTR   := ANTHTR(INUMBR);
  15980.       LNR   := ANTLNR(INUMBR);
  15981.       TAR   := ANTTAR(INUMBR);
  15982. --
  15983. --ASSIGN RECEIVER CLASS TYPE.
  15984.       If FREQ < 3.0 Then
  15985.          LCTYP := HARD_WIRED;
  15986.          New_line;
  15987.          Put("HARD_WIRED type of link assigned to receiver.");
  15988.          Goto ACCEPT_DATA;
  15989.       End If;
  15990.       If FREQ <= 3.0E+03 Then
  15991.          LCTYP := ELF;
  15992.       Elsif FREQ > 3.0E+03 and FREQ <= 3.0E+04 Then
  15993.          LCTYP := VLF;
  15994.       Elsif FREQ > 3.0E+04 and FREQ <= 3.0E+05 Then
  15995.          LCTYP := LF;
  15996.       Elsif FREQ > 3.0E+05 and FREQ <= 3.0E+06 Then
  15997.          LCTYP := MF;
  15998.       Elsif FREQ > 3.0E+06 and FREQ <= 3.0E+07 Then
  15999.          LCTYP := HF;
  16000.       Elsif FREQ > 3.0E+07 and FREQ <= 3.0E+08 Then
  16001.          LCTYP := VHF;
  16002.       Elsif FREQ > 3.0E+08 and FREQ <= 3.0E+09 Then
  16003.          LCTYP := UHF;
  16004.       Elsif FREQ > 3.0E+09 and FREQ <= 3.0E+10 Then
  16005.          LCTYP := SHF;
  16006.       Elsif FREQ > 3.0E+10 and FREQ <= 3.0E+11 Then
  16007.          LCTYP := EHF;
  16008.       End If;
  16009.       New_line;
  16010.       Put(BAND_TYPES'IMAGE(LCTYP));
  16011.       Put(" frequency class assigned.");
  16012. --
  16013.       If LCTYP >= VHF Then
  16014. <<GAINER>>
  16015.          New_line;
  16016.          Put("Antenna G/T: ");
  16017.          Put(GT);
  16018.          Put(" (dB/K)"); New_line;
  16019.          Get_line(INPUT_BUFFER, MAX);
  16020.          If INPUT_BUFFER(1) = '=' Then
  16021.             Goto FLAG_CHECK;
  16022.          End If;
  16023.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  16024.             RECEIVER_HELP(6);
  16025.             Goto GAINER;
  16026.          End If;
  16027.          If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  16028.             NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  16029.             PARSE(INPUT_BUFFER(1..MAX));
  16030.             If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  16031.                Goto GAINER;
  16032.             End If;
  16033.             NEW_TITLE_CHECK;
  16034.             GT := XARRAY(1);
  16035.          End If;
  16036. --
  16037. <<RECEIVER_LINE_LOSS>>
  16038.          New_line;
  16039.          Put("Receiver line loss: ");
  16040.          Put(RLL);
  16041.          Put(" dB"); New_line;
  16042.          Get_line(INPUT_BUFFER, MAX);
  16043.          If INPUT_BUFFER(1) = '=' Then
  16044.             Goto FLAG_CHECK;
  16045.          End If;
  16046.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  16047.             RECEIVER_HELP(12);
  16048.             Goto RECEIVER_LINE_LOSS;
  16049.          End If;
  16050.          If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  16051.             NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  16052.             PARSE(INPUT_BUFFER(1..MAX));
  16053.             If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  16054.                Goto RECEIVER_LINE_LOSS;
  16055.             End If;
  16056.             NEW_TITLE_CHECK;
  16057.             RLL := XARRAY(1);
  16058.          End If;
  16059.       End If;
  16060. --
  16061. <<BANDWIDTH>>
  16062.       New_line;
  16063.       Put("Receiver noise bandwidth: ");
  16064.       Put(BW);
  16065.       Put(" (Hz)"); New_line;
  16066.       Get_line(INPUT_BUFFER, MAX);
  16067.       If INPUT_BUFFER(1) = '=' Then
  16068.          Goto FLAG_CHECK;
  16069.       End If;
  16070.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  16071.          RECEIVER_HELP(9);
  16072.          Goto BANDWIDTH;
  16073.       End If;
  16074.       If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  16075.          NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  16076.          PARSE(INPUT_BUFFER(1..MAX));
  16077.          If NUMBER_OF_VARIABLES_EXTRACTED /= 1 or XARRAY(1) <= 0.0 Then
  16078.             Goto BANDWIDTH;
  16079.          End If;
  16080.          NEW_TITLE_CHECK;
  16081.          BW := XARRAY(1);
  16082.       End If;
  16083. --
  16084. <<ANTENNA_TYPE>>
  16085.       If LCTYP = HARD_WIRED or LCTYP = ELF or LCTYP = VLF Then
  16086.          IATYP := 0;
  16087.       Else
  16088.          If IATYP = 0 then              -- Set some default antenna values
  16089.             If LCTYP = LF Then
  16090.                IATYP := 1;
  16091.             Elsif LCTYP in MF..HF Then
  16092.                IATYP := 5;
  16093.             Elsif LCTYP in VHF..EHF Then
  16094.                IATYP := 3;
  16095.             End If;
  16096.          End If;
  16097.          New_line;
  16098.          Put(BAND_TYPES'IMAGE(LCTYP));
  16099.          Put(" Antenna type: ");
  16100.          Put(IATYP); New_line;
  16101.          Get_line(INPUT_BUFFER, MAX);
  16102.          If INPUT_BUFFER(1) = '=' Then
  16103.             Goto FLAG_CHECK;
  16104.          End If;
  16105.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  16106.             RECEIVER_HELP(11);
  16107.             Goto ANTENNA_TYPE;
  16108.          End If;
  16109.          If not BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  16110.             NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  16111.             PARSE(INPUT_BUFFER(1..MAX));
  16112.             If NUMBER_OF_VARIABLES_EXTRACTED /= 1 or XARRAY(1) < 1.0 or
  16113.                XARRAY(1) > 8.0 Then
  16114.                Goto ANTENNA_TYPE;
  16115.             End If;
  16116.             NEW_TITLE_CHECK;
  16117.             IATYP := INTEGER(XARRAY(1));
  16118.             ANTENNA_CHECK (IATYP, LCTYP, GNR, HTR, LNR, TAR, IERR);
  16119.             If IERR > 1 Then
  16120.                Goto ANTENNA_TYPE;
  16121.             End If;
  16122.             If IERR = 1 Then
  16123.                Goto FLAG_CHECK;
  16124.             End If;
  16125.          End If;
  16126.       End If;
  16127. --
  16128. <<ACCEPT_DATA>>
  16129.       ITPREC(INUMBR) := LCTYP;
  16130.       IATREC(INUMBR) := IATYP;
  16131.       FREREC(INUMBR) := FREQ;
  16132.       GTREC(INUMBR) := GT;
  16133.       BWREC(INUMBR) := BW;
  16134.       RLLREC(INUMBR) := RLL;
  16135.       ANTGNR(INUMBR) := GNR;
  16136.       ANTHTR(INUMBR) := HTR;
  16137.       ANTLNR(INUMBR) := LNR;
  16138.       ANTTAR(INUMBR) := TAR;
  16139.       Return;      
  16140. --
  16141. <<FLAG_CHECK>>
  16142.       If IFLG /= 1 Then 
  16143.          INOADD := 1;
  16144.       End If;
  16145.       Return;
  16146. --
  16147.       End RECEIVER_DATA;
  16148. --
  16149. --
  16150.       Procedure RECEIVER_DISPLAY (IBUFF: in L_ARRAY;
  16151.                                      NV: in out integer) is
  16152. --
  16153. --#PURPOSE: RECEIVER_DISPLAY displays the requested receiver classes to 
  16154. --          either the printer or the terminal depending on the value of 
  16155. --          CURRENT_COMMAND.
  16156. --
  16157. --#AUTHOR:  J. Conrad
  16158. --
  16159. --#TYPE:    Output module
  16160. --
  16161. --#PARAMETER DESCRIPTIONS:
  16162. --IN        IBUFF  = The array containing the receiver class numbers to 
  16163. --                   be displayed.
  16164. --IN        NV     = The number of elements in IBUFF.
  16165. --
  16166. --#CALLED BY:
  16167. --          RECEIVER_HANDLER
  16168. --
  16169. --#CALLS TO:
  16170. --          INTEGER_TO_ALPHA
  16171. --          RECEIVER_FIND
  16172. --
  16173. --#TECHNICAL DESCRIPTION:
  16174. --          RECEIVER_DISPLAY displays only the receiver classes listed in
  16175. --          IBUFF as long as NV is not 0 on entry.  When NV is 0 this
  16176. --          signals that all receivers should be displayed, therefore if 
  16177. --          many receivers exist, and the specified device is the terminal, 
  16178. --          this can cause data to scroll off the screen.
  16179. --
  16180. --
  16181.       ICOMPL: boolean;
  16182.       I,INUM: integer;
  16183.       KNREC: string(1..6);
  16184. --
  16185.       Begin
  16186. --
  16187. --SET THE OUTPUT DEVICE.
  16188.       If CURRENT_COMMAND = PRINT Then
  16189.          SET_OUTPUT(PRINTER_OUTPUT_FILE);
  16190.       End If;
  16191. --
  16192. --GET THE NUMBER OF RECEIVER CLASSES TO DISPLAY AND THE DEVICE NUMBER.
  16193.       ICOMPL := FALSE;
  16194.       If NV = 0 or NV = NUMREC Then
  16195.          ICOMPL := TRUE;
  16196.       End If;
  16197. --
  16198. --PRINT OUT REPORT HEADER.
  16199.       If ICOMPL Then
  16200.          New_line;
  16201.          Put(TITLE);
  16202.          New_line;New_line;
  16203.          Put("                    RECEIVER SUMMARY");
  16204.          New_line;
  16205.          Put("               There are currently ");
  16206.          Put(NUMREC);
  16207.          Put(" receiver classes");
  16208.          New_line;
  16209.          NV := NUMREC;
  16210.       End If;
  16211. --
  16212. --LOOP ON NUMBER OF RECEIVER CLASSES TO PRINT.
  16213.       If NV < 1 Then
  16214.          Return;
  16215.       End If;
  16216.       For I in 1..NV Loop
  16217.          If I /= 1 Then
  16218.             Put("====================================");
  16219.             Put("====================================");
  16220.          End If;
  16221.          RECEIVER_FIND(IBUFF(I), INUM);
  16222.          If INUM < 1 Then
  16223.             --RESET THE OUTPUT DEVICE.
  16224.             If CURRENT_COMMAND = PRINT Then
  16225.                SET_OUTPUT(STANDARD_OUTPUT);
  16226.             End If;
  16227.             INTEGER_TO_ALPHA (IBUFF(I), KNREC);
  16228.             New_line;
  16229.             Put("Receiver class ");
  16230.             Put(KNREC);
  16231.             Put(" does not yet exist.");
  16232.             --SET THE OUTPUT DEVICE.
  16233.             If CURRENT_COMMAND = PRINT Then
  16234.                SET_OUTPUT(PRINTER_OUTPUT_FILE);
  16235.             End If;
  16236.             Goto END_OF_LOOP;
  16237.          End If;
  16238.          INTEGER_TO_ALPHA(NAMREC(INUM), KNREC);
  16239.          If ITPREC(INUM) = HARD_WIRED Then
  16240.             New_line;
  16241.             Put("Receiver ");
  16242.             Put(KNREC);
  16243.             Put(" is a HARD_WIRED class.");
  16244.             Goto END_OF_LOOP;
  16245.          End If;
  16246.          New_line;
  16247.          Put("Receiver name.........");
  16248.          Put(KNREC);
  16249.          Put("          Frequency class...");
  16250.          Put(Band_types'IMAGE(ITPREC(INUM)));
  16251.          New_line;
  16252.          Put("Frequency (Hz)..........");
  16253.          Put(FREREC(INUM),2,5,3);
  16254.          Put("    Bandwidth (Hz)........");
  16255.          Put(BWREC(INUM),2,5,3);
  16256.          New_line;
  16257.          If ITPREC(INUM) > VLF Then
  16258.             New_line;
  16259.             Put("Antenna type..........");
  16260.             If IATREC(INUM) = 1 Then
  16261.                Put("Loop");
  16262.             Elsif IATREC(INUM) = 2 Then
  16263.                Put("Whip");
  16264.             Elsif IATREC(INUM) = 3 Then
  16265.                Put("Dish with tapered side lobe");
  16266.             Elsif IATREC(INUM) = 4 Then
  16267.                Put("Dish with constant side lobe");
  16268.             Elsif IATREC(INUM) = 5 Then
  16269.                Put("Constant gain");
  16270.             Elsif IATREC(INUM) = 6 Then
  16271.                Put("Rhombic");
  16272.             Elsif IATREC(INUM) = 7 Then
  16273.                Put("Vertical");
  16274.             Elsif IATREC(INUM) = 8 Then
  16275.                Put("Horizontal half-wave dipole");
  16276.             End If;
  16277.          End If;
  16278.          If ITPREC(INUM) >= VHF Then
  16279.             New_line;
  16280.             Put("Antenna G/T (dB/K)....");
  16281.             Put(GTREC(INUM),2,5,3);
  16282.             New_line;
  16283.             Put("Rec. line loss (dB)....");
  16284.             Put(RLLREC(INUM),2,5,3);
  16285.          End If;
  16286.          If IATREC(INUM) = 5 Then
  16287.             New_line;
  16288.             Put("Antenna gain (dB).....");
  16289.             Put(ANTGNR(INUM),2,5,3);
  16290.          Elsif IATREC(INUM) = 6 Then
  16291.             New_line;
  16292.             Put("Ant tilt angle (deg)..");
  16293.             Put(ANTTAR(INUM),3,1,0);
  16294.             New_line;
  16295.             Put("Antenna height (m)....");
  16296.             Put(ANTHTR(INUM),2,5,3);
  16297.             New_line;
  16298.             Put("Ant leg length (m)....");
  16299.             Put(ANTLNR(INUM),2,5,3);
  16300.          Elsif IATREC(INUM) = 7 Then
  16301.             New_line;
  16302.             Put("Ant leg length (m)....");
  16303.             Put(ANTLNR(INUM),2,5,3);
  16304.          Elsif IATREC(INUM) = 8 Then
  16305.             New_line;
  16306.             Put("Antenna height (m)....");
  16307.             Put(ANTHTR(INUM),2,5,3);
  16308.          End If;
  16309. <<END_OF_LOOP>>
  16310.          Null;
  16311.          New_line;
  16312.       End Loop;
  16313. --
  16314. --RESET THE OUTPUT DEVICE.
  16315.       If CURRENT_COMMAND = PRINT Then
  16316.          SET_OUTPUT(STANDARD_OUTPUT);
  16317.       End If;
  16318. --
  16319.       Return;
  16320. --
  16321.       End RECEIVER_DISPLAY;
  16322. --
  16323. --
  16324.       Procedure RECEIVER_FETCH (KNAME: out string;
  16325.                                 INAME: out long_integer;
  16326.                                 INUMBR: out integer;
  16327.                                 ISTOP: out integer) is
  16328. --
  16329. --#PURPOSE: RECEIVER_FETCH obtains a receiver class from the receiver data
  16330. --          structure.
  16331. --
  16332. --#AUTHOR:  J. Conrad
  16333. --
  16334. --#TYPE:    Table Look-up
  16335. --
  16336. --#PARAMETER DESCRIPTIONS:
  16337. --OUT       KNAME  = The receiver class name string.
  16338. --OUT       INAME  = The coded receiver class name.
  16339. --OUT       INUMBR = The location of INAME in the receiver
  16340. --                   data structure.
  16341. --                   A value of zero (0) is returned if INAME
  16342. --                   cannot be located.
  16343. --OUT       ISTOP  = Flag to tell if = is encountered
  16344. --                   0...No = encountered
  16345. --                   1...A terminator = was encountered
  16346. --
  16347. --#CALLED BY:
  16348. --          RECEIVER_HANDLER
  16349. --
  16350. --#CALLS TO:
  16351. --          BLANK_CHECK
  16352. --          INTEGER_TO_ALPHA
  16353. --          PARSE
  16354. --          RECEIVER_FIND
  16355. --
  16356. --#TECHNICAL DESCRIPTION:
  16357. --          RECEIVER_FETCH queries the operator for a receiver class name
  16358. --          then does a table lookup in the receiver data structure for
  16359. --          the specified receiver class.  When the receiver class is
  16360. --          located, its position in the structure is returned in the
  16361. --          variable INUMBR.  If the receiver cannot be located, a value
  16362. --          of zero is returned in INUMBR.
  16363. --
  16364.       Begin
  16365. --
  16366.       ISTOP := 0;
  16367. --
  16368. <<GET_RECEIVER_CLASS_NAME>>
  16369.       New_line;
  16370.       Put("Enter the receiver class name: ");
  16371.       Get_line(INPUT_BUFFER, MAX);
  16372.       KNAME := INPUT_BUFFER(1..6);
  16373.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  16374.          Goto GET_RECEIVER_CLASS_NAME;
  16375.       End If;
  16376.       If INPUT_BUFFER(1) = '=' Then
  16377.          ISTOP := 1;
  16378.          Return;
  16379.       End If;
  16380.       NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  16381.       PARSE (INPUT_BUFFER(1..MAX));
  16382.       If NUMBER_OF_VARIABLES_EXTRACTED /= 1 Then
  16383.          Goto GET_RECEIVER_CLASS_NAME;
  16384.       End If;
  16385.       INAME:=IARRAY(1);
  16386.       INTEGER_TO_ALPHA(IARRAY(1), KNAME);
  16387.       RECEIVER_FIND (IARRAY(1), INUMBR);
  16388. --
  16389.       Return;
  16390. --
  16391.       End RECEIVER_FETCH;
  16392. --
  16393. --
  16394.       Procedure RECEIVER_FIND (INAME: in long_integer; INUMBR: out integer) is
  16395. --
  16396. --#PURPOSE: RECEIVER_FIND locates a receiver class in the receiver data
  16397. --          structure.
  16398. --
  16399. --#AUTHOR:  J. Conrad
  16400. --
  16401. --#TYPE:    Table Look-up
  16402. --
  16403. --#PARAMETER DESCRIPTIONS:
  16404. --IN        INAME  = The coded receiver class name.
  16405. --OUT       INUMBR = The location of INAME in the receiver data structure.
  16406. --                   A value of zero (0) is returned if INAME cannot be 
  16407. --                   located.
  16408. --
  16409. --#CALLED BY:
  16410. --          RECEIVER_HANDLER
  16411. --          RECEIVER_ADD
  16412. --          RECEIVER_DISPLAY
  16413. --          RECEIVER_FETCH
  16414. --          RECEIVER_REMOVE
  16415. --
  16416. --#CALLS TO:
  16417. --          'NONE'
  16418. --
  16419. --#TECHNICAL DESCRIPTION:
  16420. --          RECEIVER_FIND does a table lookup in the receiver data 
  16421. --          structure the specified receiver class.  When the receiver 
  16422. --          class is located, its position in the structure is returned in 
  16423. --          the variable INUMBR.  If the receiver class cannot be located, a
  16424. --          value of zero is returned in INUMBR.
  16425. --
  16426.       KNAME: string(1..6);
  16427.       I: integer;
  16428. --
  16429.       Begin
  16430. --
  16431.       INUMBR := 0;
  16432.       If NUMREC < 1 Then
  16433.          Return;
  16434.       End If;
  16435. --
  16436. --SEARCH THE DATA STRUCTURE FOR THE RECEIVER CLASS.
  16437.       For I in 1..NUMREC Loop
  16438.          If INAME = NAMREC(I) Then
  16439.             INUMBR := I;
  16440.             Return;
  16441.          End If;
  16442.       End Loop;
  16443.       Return;
  16444. --
  16445.       End RECEIVER_FIND;
  16446. --
  16447. --
  16448.       Procedure RECEIVER_HANDLER is
  16449. --
  16450. --#PURPOSE: RECEIVER_HANDLER drives the receiver class processing routines.
  16451. --
  16452. --#AUTHOR:  J. Conrad
  16453. --
  16454. --#TYPE:    I/O PROCESSING
  16455. --
  16456. --#PARAMETER DESCRIPTIONS:
  16457. --          'NONE'
  16458. --
  16459. --#CALLED BY:
  16460. --          MAIN
  16461. --          PRINT_HANDLER
  16462. --
  16463. --#CALLS TO:
  16464. --          BLANK_CHECK
  16465. --          INTEGER_TO_ALPHA
  16466. --          PARSE
  16467. --          RECEIVER_ADD
  16468. --          RECEIVER_DISPLAY
  16469. --          RECEIVER_FETCH
  16470. --          RECEIVER_FIND
  16471. --          RECEIVER_REMOVE
  16472. --
  16473. --#TECHNICAL DESCRIPTION:
  16474. --          RECEIVER_HANDLER serves as the driver for the routines which
  16475. --          add, delete, and modify receiver classes.  Trickle down logic 
  16476. --          is used to select the desired command.
  16477. --
  16478.       INAME: L_ARRAY(1..MAXRNT);
  16479.       IFLG,NV,I,K: integer;
  16480.       KNAME: string(1..6);
  16481.       JNAME: long_integer;
  16482.       JNUMBR: integer;
  16483.       ISTOP: integer;
  16484.       IERR: integer;
  16485.       INUMBR: integer;
  16486. --
  16487.       Begin
  16488. --
  16489. --INITIALIZE.
  16490.       IFLG := 0;
  16491.       NV := 0;
  16492. --
  16493.       Case CURRENT_COMMAND is
  16494.       When ADD =>
  16495. <<ADD_RECEIVER>>
  16496.          RECEIVER_FETCH (KNAME, JNAME, JNUMBR, ISTOP);
  16497.          If ISTOP = 1 Then
  16498.             Return;
  16499.          End If;
  16500.          If JNUMBR >= 1 Then
  16501.             New_line;
  16502.             Put("Receiver class ");
  16503.             Put(KNAME);
  16504.             Put(" already exists.");
  16505.             Goto ADD_RECEIVER;
  16506.          End If;
  16507.          If NUMREC >= MAXRNT Then
  16508.             New_line;
  16509.             Put("No more receiver classes may be added.");
  16510.             Put("  Redimension receiver arrays.");
  16511.             Return;
  16512.          End If;
  16513.          NUMREC := NUMREC + 1;
  16514.          JNUMBR := NUMREC;
  16515.          NAMREC (JNUMBR) := JNAME;
  16516.          ITPREC (JNUMBR) := ELF;
  16517.          IATREC (JNUMBR) := 0;
  16518.          FREREC (JNUMBR) := 3.0;
  16519.          GTREC  (JNUMBR) := -30.0;
  16520.          BWREC  (JNUMBR) := 1.0;
  16521.          RLLREC (JNUMBR) := 0.0;
  16522.          ANTGNR (JNUMBR) := 0.0;
  16523.          ANTHTR (JNUMBR) := 0.0;
  16524.          ANTLNR (JNUMBR) := 0.0;
  16525.          ANTTAR (JNUMBR) := 0.0;
  16526.          RECEIVER_ADD (JNUMBR, IFLG, IERR);
  16527.          If IERR = 0 Then
  16528.             Goto ADD_RECEIVER;
  16529.          End If;
  16530. --
  16531. --RECEIVER CLASS ADDITION WAS TERMINATED.
  16532.          NUMREC := NUMREC - 1;
  16533.          Return;
  16534. --
  16535. --PROCESS THE VIEW OR PRINT COMMANDS.
  16536.       When VIEW | PRINT =>
  16537.          NV := NUMREC;
  16538.          If NV >= 1 Then
  16539.             For K in 1..NUMREC Loop
  16540.                INAME(K) := NAMREC(K);
  16541.             End Loop;
  16542.             If not BLANK_CHECK(ARGUMENT_BUFFER) Then
  16543.                NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  16544.                PARSE(ARGUMENT_BUFFER);
  16545.                NV := NUMBER_OF_VARIABLES_EXTRACTED;
  16546.                For K in 1..NV Loop
  16547.                   INAME(K) := IARRAY(K);
  16548.                End Loop;
  16549.             End If;
  16550.          End If;
  16551.          RECEIVER_DISPLAY (INAME, NV);
  16552.          Return;
  16553. --
  16554. --PROCESS THE DELETION COMMAND.
  16555.       When DEL =>
  16556.          Loop
  16557.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  16558.             New_line;
  16559.             Put("Enter the receiver class names to be deleted,");
  16560.             Put(" separated by spaces.");
  16561.             New_line;
  16562.             Get_line(ARGUMENT_BUFFER, MAX);
  16563.          End Loop;
  16564.          If ARGUMENT_BUFFER(1) = '=' Then
  16565.             Return;
  16566.          End If;
  16567.          NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  16568.          PARSE(ARGUMENT_BUFFER);
  16569.          NV := NUMBER_OF_VARIABLES_EXTRACTED;
  16570.          If NV <= 0 Then
  16571.             NV := 1;
  16572.          End If;
  16573.          RECEIVER_REMOVE(IARRAY, NV);
  16574.          Return;
  16575. --
  16576. --PROCESS THE MODIFY COMMAND.
  16577.       When MODIFY =>
  16578.          IFLG := 1;
  16579.          Loop
  16580.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  16581.             New_line;
  16582.             Put("Enter the name of the receiver class to be modified: ");
  16583.             Get_line(ARGUMENT_BUFFER, MAX);
  16584.          End Loop;
  16585.          If ARGUMENT_BUFFER(1) = '=' Then
  16586.             Return;
  16587.          End If;
  16588.          NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  16589.          PARSE(ARGUMENT_BUFFER);
  16590.          If NUMBER_OF_VARIABLES_EXTRACTED > 0 Then
  16591.             RECEIVER_FIND (IARRAY(1), INUMBR);
  16592.             INTEGER_TO_ALPHA (IARRAY(1), KNAME);
  16593.             If INUMBR <= 0 Then
  16594.                New_line;
  16595.                Put("Receiver class name ");
  16596.                Put(KNAME);
  16597.                Put(" does not exist.");
  16598.                Return;
  16599.             End If;
  16600.             RECEIVER_ADD (INUMBR, IFLG, IERR);
  16601.          End If;
  16602. --
  16603. --ILLEGAL COMMAND WARNING.
  16604.       When others =>
  16605.          New_line;
  16606.          Put("The command code is not valid for receiver class processing.");
  16607.          Return;
  16608.       End Case;
  16609. --
  16610.       End RECEIVER_HANDLER;
  16611. --
  16612. --
  16613.       Procedure RECEIVER_HELP (IWHO: in integer) is
  16614. --
  16615. --#PURPOSE: RECEIVER_HELP prints the various help messages as requested 
  16616. --          by the operator for the different levels of receiver class
  16617. --          processing.
  16618. --
  16619. --#AUTHOR:  J. Conrad
  16620. --
  16621. --#TYPE:    Operator assistance
  16622. --
  16623. --#PARAMETER DESCRIPTIONS:
  16624. --IN        IWHO   := The indicator flag for which help message to print.
  16625. --
  16626. --#CALLED BY:
  16627. --          RECEIVER_ADD
  16628. --          RECEIVER_DATA
  16629. --
  16630. --#CALLS TO:
  16631. --          'NONE'
  16632. --
  16633. --#TECHNICAL DESCRIPTION:
  16634. --          RECEIVER_HELP prints the various help messages as requested 
  16635. --          by the operator for the different levels of receiver class
  16636. --          processing.  The value of IWHO determines the message to
  16637. --          display.
  16638. --
  16639.       Begin
  16640. --
  16641. --SELECT THE HELP MESSAGE TO DISPLAY.
  16642.       If IWHO = 1 Then
  16643.          New_line;
  16644.          Put("At this point you can enter the frequency in Hz of the ");
  16645.          Put("receiver. The range of");  
  16646.          New_line;
  16647.          Put("frequency is from 3Hz to 3.0E+11 Hz.  If the receiver ");
  16648.          Put("frequency that was just");  
  16649.          New_line;
  16650.          Put("echoed is satisfactory, then simply enter a carriage return.");
  16651.          Put("  You may also");
  16652.          New_line;
  16653.          Put("enter  L  or  LIKE  to set this receiver up exactly like ");
  16654.          Put("some other receiver.");  
  16655.          New_line;
  16656.          Put("Finally, you may enter  N  or  NONE  to signify that a ");
  16657.          Put("HARD_WIRED link is");
  16658.          New_line;
  16659.          Put("desired.");
  16660.          New_line;
  16661.          Put("An = (equal sign) terminates the addition of this receiver ");
  16662.          Put("with the current");
  16663.          New_line;
  16664.          Put("information to this point and the receiver lost, unless this ");
  16665.          Put("addition is");
  16666.          New_line;
  16667.          Put("-like- some other receiver, then it is saved.");
  16668.          New_line;
  16669.       Return;
  16670.       End If;      
  16671. --
  16672.       If IWHO = 2 Then
  16673.          New_line;
  16674.          Put("Since you have specified that this receiver should be like "); 
  16675.          Put("some other");
  16676.          New_line;
  16677.          Put("receiver, you must now enter the name of the receiver that ");
  16678.          Put("has already been");
  16679.          New_line;
  16680.          Put("entered which has the data that should be used to define ");
  16681.          Put("this receiver. If");
  16682.          New_line;
  16683.          Put("you made a mistake and don't want this feature, then enter ");
  16684.          Put("an = to take you");
  16685.          New_line;
  16686.          Put("back to the executive for another command.");
  16687.          New_line;
  16688.          Return;
  16689.       End If;
  16690. --
  16691.       If IWHO = 5 Then
  16692.          New_line;
  16693.          Put("Enter a class name (maximum of 6 characters). ");
  16694.          New_line;
  16695.          Put("An = (equal sign) terminates the addition of this receiver ");
  16696.          Put("with the current");
  16697.          New_line;
  16698.          Put("information to this point and the receiver lost, unless this ");
  16699.          Put("addition is");
  16700.          New_line;
  16701.          Put("-like- some other receiver, then it is saved.");
  16702.          New_line;
  16703.          Return;
  16704.       End If;
  16705. --
  16706.       If IWHO = 6 Then
  16707.          New_line;
  16708.          Put("If the antenna G/T just echoed is satisfactory then enter");
  16709.          Put(" a carriage return.");
  16710.          New_line;
  16711.          Put("Otherwise, enter the value of the receiving antenna ");
  16712.          Put("in (dB/k).");
  16713.          New_line;
  16714.          Put("G/T is a figure of merit for a VHF/UHF/SHF/EHF satellite ");
  16715.          Put("receiver.  G refers");
  16716.          New_line;
  16717.          Put("to the gain of the antenna in the receive mode, and T is ");
  16718.          Put("the equivalent noise");
  16719.          New_line;
  16720.          Put("temperature of the receiving system.  The equivalent noise ");
  16721.          Put("temperature is");
  16722.          New_line;
  16723.          Put("based on the total amount of noise in the received signal.  ");
  16724.          Put("The units of G/T");
  16725.          New_line;
  16726.          Put("are dB/k which may be computed as:");
  16727.          New_line;
  16728.          Put("      10.0 * alog10 (gain / temp)");
  16729.          New_line;
  16730.          Put("   where:");
  16731.          New_line;
  16732.          Put("      gain = gain of the antenna as a multiplier..not dB; and,");
  16733.          New_line;
  16734.          Put("      temp = noise temperature in degrees kelvin.");
  16735.          New_line;
  16736.          Put("An = (equal sign) terminates the addition of this receiver ");
  16737.          Put("with the current");
  16738.          New_line;
  16739.          Put("information to this point and the receiver lost, unless this ");
  16740.          Put("addition is");
  16741.          New_line;
  16742.          Put("-like- some other receiver, then it is saved.");
  16743.          New_line;
  16744.          Return;
  16745.       End If;
  16746. --
  16747.       If IWHO = 9 Then
  16748.          New_line;
  16749.          Put("If the bandwidth just echoed is satisfactory then enter a ");
  16750.          Put("carriage return.");
  16751.          New_line;
  16752.          Put("Otherwise, enter the value of the receiver bandwidth in Hz.");
  16753.          New_line;
  16754.          Put("An = (equal sign) terminates the addition of this receiver ");
  16755.          Put("with the current");
  16756.          New_line;
  16757.          Put("information to this point and the receiver lost, unless this ");
  16758.          Put("addition is");
  16759.          New_line;
  16760.          Put("-like- some other receiver, then it is saved.");
  16761.          New_line;
  16762.          Return;
  16763.       End If;
  16764. --
  16765.       If IWHO = 11 Then
  16766.          New_line;
  16767.          Put("If the antenna type just echoed is satisfactory then enter ");
  16768.          Put("a carriage return.");
  16769.          New_line;
  16770.          Put("Otherwise, enter the value of the receiver antenna type.  ");
  16771.          Put("The value must be:");
  16772.          New_line;
  16773.          Put("   1 - loop type (LF only);");
  16774.          New_line;
  16775.          Put("   2 - whip type (LF only);");
  16776.          New_line;
  16777.          Put("   3 - dish with tapered side lobe (VHF and above only);");
  16778.          New_line;
  16779.          Put("   4 - dish with constant side lobe (VHF and above only);");
  16780.          New_line;
  16781.          Put("   5 - constant gain (MF and HF only);");
  16782.          New_line;
  16783.          Put("   6 - rhombic (MF and HF only);");
  16784.          New_line;
  16785.          Put("   7 - vertical (MF and HF only); or,");
  16786.          New_line;
  16787.          Put("   8 - horizontal half-wave dipole (MF and HF only).");
  16788.          New_line;
  16789.          Put("An = (equal sign) terminates the addition of this receiver ");
  16790.          Put("with the current");
  16791.          New_line;
  16792.          Put("information to this point and the receiver lost, unless this ");
  16793.          Put("addition is");
  16794.          New_line;
  16795.          Put("-like- some other receiver, then it is saved.");
  16796.          New_line;
  16797.          Return;
  16798.       End If;
  16799. --
  16800.       If IWHO = 12 Then
  16801.          New_line;
  16802.          Put("If the receiver line loss just echoed is satisfactory then ");
  16803.          Put("enter a carriage");
  16804.          Put("return.  Otherwise, enter the value of the receiver line ");
  16805.          Put("loss in dB.");
  16806.          New_line;
  16807.          Put("An = (equal sign) terminates the addition of this receiver ");
  16808.          Put("with the current");
  16809.          New_line;
  16810.          Put("information to this point and the receiver lost, unless this ");
  16811.          Put("addition is");
  16812.          New_line;
  16813.          Put("-like- some other receiver, then it is saved.");
  16814.          New_line;
  16815.          Return;
  16816.       End If;
  16817. --
  16818.       End RECEIVER_HELP;
  16819. --
  16820. -- 
  16821.       Procedure RECEIVER_REMOVE (IBUFF: in out L_ARRAY;
  16822.                                  NUMBR: in integer) is
  16823. --
  16824. --#PURPOSE: RECEIVER_REMOVE removes a specified receiver class from the
  16825. --          data base.
  16826. --
  16827. --#AUTHOR:  J. Conrad
  16828. --
  16829. --#TYPE:    I/O Processing
  16830. --
  16831. --#PARAMETER DESCRIPTIONS:
  16832. --IN        IBUFF  = The array containing the receiver class names
  16833. --                   to be deleted.
  16834. --IN        NUMBR  = The number of receiver class names in IBUFF.
  16835. --
  16836. --#CALLED BY:
  16837. --          RECEIVER_HANDLER
  16838. --
  16839. --#CALLS TO:
  16840. --          INTEGER_TO_ALPHA
  16841. --          RECEIVER_FIND
  16842. --
  16843. --#TECHNICAL DESCRIPTION:
  16844. --          RECEIVER_REMOVE removes a specified receiver class from the
  16845. --          data base.  Before a receiver class is removed, a check
  16846. --          is first made to be sure that some node does not use
  16847. --          the receiver class.  If such a node is found, a message
  16848. --          indicating the problem is issued to the operator.  If
  16849. --          no node conflict is found, the receiver class is effectively
  16850. --          removed by shifting each receiver class with an index value
  16851. --          higher than the one being removed down by one.
  16852. --
  16853.       KNAM: string(1..6);
  16854.       KNAME2: string(1..6);
  16855.       I,J,L,N: integer;
  16856.       JNUM: integer;
  16857. --
  16858.       Begin
  16859. --
  16860. --CHECK IBUFF FOR USE AT A NODE.
  16861.       If NUMNOD > 0 Then
  16862.          For I in 1..NUMNOD Loop
  16863.             If NRSND(I) > 0 Then
  16864.                For J in 1..NRSND(I) Loop
  16865.                   For L in 1..NUMBR Loop
  16866.                      If IBUFF(L) /= 0 and IBUFF(L) = IRCSND(2,J,I) Then
  16867.                         INTEGER_TO_ALPHA (IBUFF(L), KNAM);
  16868.                         INTEGER_TO_ALPHA (NAMNOD(I), KNAME2);
  16869.                         New_line;
  16870.                         Put("Receiver ");
  16871.                         Put(KNAM);
  16872.                         Put(" is used at node ");
  16873.                         Put(KNAME2);
  16874.                         Put(".  Modify it first.");
  16875.                         IBUFF(L) := 0;
  16876.                         Exit;
  16877.                      End If;
  16878.                   End Loop;
  16879.                End Loop;
  16880.             End If;
  16881.          End Loop;
  16882.       End If;
  16883. --
  16884. --LOOP ON ALL ELEMENTS TO BE REMOVED.
  16885.       For I in 1..NUMBR Loop
  16886.          If IBUFF(I) /= 0 Then
  16887.             RECEIVER_FIND (IBUFF(I), JNUM);
  16888.             If JNUM = 0 Then
  16889.                --
  16890.                --TRYING TO REMOVE A RECEIVER CLASS NOT YET ADDED.
  16891.                INTEGER_TO_ALPHA (IBUFF(I), KNAM);
  16892.                New_line;
  16893.                Put("Receiver class ");
  16894.                Put(KNAM);
  16895.                Put(" not in database...no action taken.");
  16896.             Else
  16897.                --
  16898.                --REMOVE RECEIVER CLASS AT LOCATION J
  16899.                NEW_TITLE_CHECK;
  16900.                N := NUMREC - 1;
  16901.                If N >= JNUM Then
  16902.                   For L in JNUM..N Loop
  16903.                      NAMREC(L) := NAMREC(L+1);
  16904.                      ITPREC(L) := ITPREC(L+1);
  16905.                      IATREC(L) := IATREC(L+1);
  16906.                      FREREC(L) := FREREC(L+1);
  16907.                      GTREC(L) := GTREC(L+1);
  16908.                      BWREC(L) := BWREC(L+1);
  16909.                      RLLREC(L) := RLLREC(L+1);
  16910.                      ANTGNR(L) := ANTGNR(L+1);
  16911.                      ANTHTR(L) := ANTHTR(L+1);
  16912.                      ANTLNR(L) := ANTLNR(L+1);
  16913.                      ANTTAR(L) := ANTTAR(L+1);
  16914.                   End Loop;
  16915.                End If;
  16916.                NUMREC := N;
  16917.             End If;
  16918.          End If;
  16919.       End Loop;
  16920. --
  16921.       End RECEIVER_REMOVE;
  16922. --
  16923. --
  16924. End RECEIVERS;
  16925. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16926. --NODES
  16927. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  16928. With Debugger; Use Debugger;
  16929. With Text_io, system;   use Text_io,float_io,integer_io,LONG_INTEGER_IO;
  16930. With Types;     use Types;
  16931. With Constants; use Constants; 
  16932. With Constant2; use constant2;
  16933. With Constant3; use Constant3;
  16934. With Helps;     use Helps;
  16935. With Entityuti; use Entityuti;
  16936. Package NODES is
  16937. --
  16938.       Procedure ENTITY_DATA (ITYPE: in integer;
  16939.                              IENT: in out integer;
  16940.                              NENT: in out integer;
  16941.                              LENT: in out SND3;
  16942.                              NUMCL: in out integer;
  16943.                              NAMCL: in out L_ARRAY;
  16944.                              ITPCL: out BAND_ARRAY;
  16945.                              INUMBR: in integer;
  16946.                              IERR: out integer);
  16947.       Procedure INITIALIZE_NODES;
  16948.       Procedure NODE_ADD (INUMBR: in integer; 
  16949.                           IERRCD: out integer);
  16950.       Procedure NODE_DATA (INUMBR: in integer; 
  16951.                            ISTOP: out integer);
  16952.       Procedure NODE_DISPLAY (IBUFF: in L_ARRAY; NV: in out integer);
  16953.       Procedure NODE_FETCH (KNAME: out string;
  16954.                             INAME: out long_integer; 
  16955.                             INUMBR: out integer;
  16956.                             IERRCD: out integer);
  16957.       Procedure NODE_FIND (KNAME: out string;
  16958.                            INAME: in long_integer;
  16959.                            INUMBR: out integer;
  16960.                            IERRCD: out integer);
  16961.       Procedure NODE_HANDLER;
  16962.       Procedure NODE_HELP (IWHO: in integer);
  16963.       Procedure NODE_REMOVE (INAME: L_ARRAY;
  16964.                              NUMBR: in integer);
  16965.       Procedure LOCATION_DATA ( INUMBR: in integer; 
  16966.                                 LOCERR: out integer );
  16967. --
  16968. End NODES;
  16969. -- 
  16970. Package body NODES is
  16971. --
  16972. -- NODES Package of PROP_LINK Version 1.0, February 8, 1985
  16973. --
  16974. -- This NODES Package contains all of the procedures that manipulate node data.
  16975. --
  16976. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  16977. -- radio frequency propagation prediction code.
  16978. --
  16979. -- PROP_LINK has been developed for the Department of Defense under
  16980. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  16981. -- Systems Inc. (Jim Conrad).
  16982. --
  16983. --
  16984. --
  16985.       Procedure ENTITY_DATA (ITYPE: in integer;
  16986.                              IENT: in out integer;
  16987.                              NENT: in out integer;
  16988.                              LENT: in out SND3;
  16989.                              NUMCL: in out integer;
  16990.                              NAMCL: in out L_ARRAY;
  16991.                              ITPCL: out BAND_ARRAY;
  16992.                              INUMBR: in integer;
  16993.                              IERR: out integer) is
  16994. --
  16995. --PURPOSE: ENTITY_DATA enters entity data (receiver and transmitter
  16996. --         classes) for nodes.
  16997. --
  16998. --AUTHOR:  J. Conrad
  16999. --
  17000. --TYPE:    Input module.
  17001. --
  17002. --PARAMETER DESCRIPTIONS:
  17003. --IN        ITYPE  = entity type code,
  17004. --                  1, receiver,
  17005. --                  2, transmitter.
  17006. --IN        IENT   = entity location in entity array (1 -> 15).
  17007. --IN        NENT   = number of entities in entity array.
  17008. --IO        LENT   = entity array.
  17009. --                  LENT(1,IENT,INUMBR) entity name.
  17010. --                  LENT(2,IENT,INUMBR) entity class.
  17011. --IN        NUMCL  = number of entity classes.
  17012. --IO        NAMCL  = entity class names.
  17013. --OUT       ITPCL  = entity class types.
  17014. --IN        INUMBR = node number of entity.
  17015. --OUT       IERR   = error code,
  17016. --                  0, data correctly entered.
  17017. --                  1, end of data indication (=),
  17018. --
  17019. --CALLED BY:
  17020. --         NODE_DATA
  17021. --
  17022. --CALLS TO:
  17023. --         BLANK_CHECK
  17024. --         HELP_CHECK 
  17025. --         INTEGER_TO_ALPHA
  17026. --         NEW_TITLE_CHECK
  17027. --         NODE_HELP
  17028. --         PARSE
  17029. --
  17030. --TECHNICAL DESCRIPTION:
  17031. --         ENTITY_DATA enters entity data (receiver and transmitter
  17032. --         classes) for nodes.  It does all error checking internally.
  17033. --
  17034.       TYPE KNSTRING IS array (integer range 1..2) of string(1..6);
  17035.       TYPE KTSTRING IS array (integer range 1..2) of string(1..11);
  17036.       KNAME: KNSTRING;
  17037.       KTYPE: KTSTRING;
  17038.       QREC: integer := 99;
  17039.       QXMT: integer := 99;
  17040.       IWHO: integer;
  17041.       I,J: integer;
  17042.       FLG: integer;
  17043. --
  17044.       Begin
  17045. --
  17046.       KTYPE(1):="   RECEIVER";
  17047.       KTYPE(2):="TRANSMITTER";
  17048.       IWHO := ITYPE + 6;
  17049.       IERR := 0;
  17050. --
  17051. <<CONVERT_NAMES>>
  17052.        INTEGER_TO_ALPHA (LENT(1,IENT,INUMBR), KNAME(1));
  17053.        INTEGER_TO_ALPHA (LENT(2,IENT,INUMBR), KNAME(2));
  17054. <<OUTPUT_NAMES>>
  17055.        New_line;
  17056.        Put(KTYPE(ITYPE));
  17057.        Put("-");
  17058.        Put(KNAME(1));
  17059.        Put(" CLASS-");
  17060.        Put(KNAME(2));
  17061.        New_line;
  17062.        INPUT_BUFFER(1..10):="          ";
  17063.        Get_line(INPUT_BUFFER,MAX);
  17064.        If INPUT_BUFFER(1) = '=' Then
  17065.          If NENT /= (IENT - 1) Then
  17066.             NEW_TITLE_CHECK;
  17067.          End If;
  17068.          NENT := IENT - 1;
  17069.          IERR := 1;
  17070.          Return;
  17071.       End If;
  17072.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  17073.          NODE_HELP (IWHO);
  17074.          Goto OUTPUT_NAMES;
  17075.       End If;
  17076. --
  17077.       If LENT(1,IENT,INUMBR) /= 0  Then
  17078.          If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  17079.             Goto CHECK_FOR_DUPLICATE; 
  17080.          End If;
  17081.       End If;
  17082. --
  17083.       NUMBER_OF_VARIABLES_TO_EXTRACT := -2;
  17084.       PARSE (INPUT_BUFFER(1..MAX));
  17085.       If NUMBER_OF_VARIABLES_EXTRACTED < 2 Then
  17086.          New_line;
  17087.          Put("Invalid format...re-enter data.");
  17088.          Goto CONVERT_NAMES;
  17089.       End If;
  17090.       LENT(1,IENT,INUMBR) := IARRAY(1);
  17091.       FLG:=0;
  17092.       For J in 1..NUMCL Loop
  17093.          If IARRAY(2) = NAMCL(J) Then
  17094.             NEW_TITLE_CHECK;
  17095.             LENT(2,IENT,INUMBR) := IARRAY(2);
  17096.             FLG:=1;
  17097.             exit; 
  17098.          End If;
  17099.       End Loop;
  17100.       If FLG=1 then
  17101.          goto CHECK_FOR_DUPLICATE;
  17102.       end if;
  17103.       If (NUMCL > QREC and ITYPE = 1) or
  17104.          (NUMCL > QXMT and ITYPE = 2) Then
  17105.          INTEGER_TO_ALPHA (IARRAY(2), KNAME(1));
  17106.          New_line;
  17107.          Put("No room to add ");
  17108.          Put(KTYPE(ITYPE));
  17109.          Put(" class ");
  17110.          Put(KNAME(1));
  17111.          Put("  Redimension arrays.");
  17112.             Goto CONVERT_NAMES;
  17113.       End If;
  17114. --
  17115.       NUMCL := NUMCL + 1;
  17116.       NAMCL(NUMCL) := IARRAY(2);  
  17117.       ITPCL(NUMCL) := UNDEFINED;
  17118.       NEW_TITLE_CHECK;
  17119.       LENT(2,IENT,INUMBR) := IARRAY(2);
  17120. --
  17121. --NEW ENTITY ADDED, CHECK FOR DUPLICATE
  17122. <<CHECK_FOR_DUPLICATE>>
  17123.       If IENT <= 1 Then
  17124.          NENT := IENT;
  17125.          Return;
  17126.       End If;
  17127.       For I in 1..IENT Loop
  17128.          If I = IENT Then
  17129.             NENT := IENT;
  17130.             Return;
  17131.          End If;
  17132.          If LENT(1,I,INUMBR) = LENT(1,IENT,INUMBR) Then
  17133.             Exit;
  17134.          End If;
  17135.       End Loop;
  17136. --
  17137. --FOUND A DUPLICATE ENTITY.
  17138.       New_line;
  17139.       Put("Duplicate names are not allowed...");
  17140.       Goto CONVERT_NAMES;
  17141. --
  17142.       Exception
  17143.           When others => Put_line("handling exception");
  17144.                          system.report_error;
  17145.                          raise;
  17146.       End ENTITY_DATA;
  17147. --
  17148. --
  17149.       Procedure INITIALIZE_NODES is
  17150. --
  17151. --PURPOSE: INITIALIZE_NODES initializes the node data structure.
  17152. --
  17153. --AUTHOR: J. Conrad
  17154. --
  17155. --TYPE:    Initialization
  17156. --
  17157. --PARAMETER DESCRIPTIONS:
  17158. --         'NONE'
  17159. --
  17160. --CALLED BY:
  17161. --         MAIN
  17162. --         READ_NODE
  17163. --
  17164. --CALLS TO:
  17165. --         'NONE'
  17166. --
  17167. --TECHNICAL DESCRIPTION:
  17168. --         INITIALIZE_NODES initializes the node data structure by setting the
  17169. --         node names to null and creating the node pointers.
  17170. --
  17171.       I: integer;
  17172. --
  17173.       Begin
  17174.       NUMNOD := 0;
  17175.       For I in 1..100 Loop
  17176.          NAMNOD(I) := 0;
  17177.       End Loop;
  17178. --
  17179.       End INITIALIZE_NODES;
  17180. --
  17181. --
  17182.       Procedure NODE_ADD (INUMBR: in integer; IERRCD: out integer) is
  17183. --
  17184. --PURPOSE: NODE_ADD processes the addition of one or more nodes.
  17185. --
  17186. --AUTHOR:  J. Conrad
  17187. --
  17188. --TYPE:    I/O Processing
  17189. --
  17190. --PARAMETER DESCRIPTIONS:
  17191. --IN        INUMBR  = The number of the node to add.
  17192. --OUT       IERRCD  = The error code where,
  17193. --                  =0, means no errors encountered,
  17194. --                  =1, means no data was created.
  17195. --                  >1, indicates an error with disc I/O.
  17196. --
  17197. --CALLED BY:
  17198. --         NODE_HANDLER
  17199. --
  17200. --CALLS TO:
  17201. --         BLANK_CHECK
  17202. --         HELP_CHECK
  17203. --         NEW_TITLE_CHECK
  17204. --         NODE_DATA
  17205. --         NODE_FETCH
  17206. --         NODE_HELP
  17207. --
  17208. --TECHNICAL DESCRIPTION:
  17209. --         NODE_ADD processes the addition of nodes as
  17210. --         well as the replacement of node data when the modify
  17211. --         command has been used.  The "LIKE" command is also
  17212. --         supported so that nodes may be specified as being like
  17213. --         another node that has been previously defined.
  17214. --
  17215.       KTYPE: array (integer range 1..2, integer range 1..4) of character;
  17216.       ITYPE: integer;
  17217.       KNAME: string (1..6);
  17218.       JNAME: long_integer;
  17219.       JNUMBR: integer;
  17220.       IERR: integer;
  17221.       ISTOP: integer;
  17222.       I,J: integer;
  17223.       FLG: integer;
  17224. --
  17225.       Begin
  17226.       KTYPE:=(('L','F','M','S'),
  17227.          ('l','f','m','s'));
  17228. <<GET_NODE_TYPE>>
  17229.       Case ITYSND(INUMBR) is
  17230.          When FIXED => ITYPE := 2;
  17231.             New_line;
  17232.             Put("Type is Fixed");
  17233.          When MOVING => ITYPE := 3;
  17234.             New_line;
  17235.             Put("Type is Moving");
  17236.          When SATELLITE => ITYPE := 4;
  17237.             New_line;
  17238.             Put("Type is Satellite");
  17239.          When Others => ITYPE := 0;
  17240.             New_line;
  17241.             Put("Enter type: ");
  17242.       End Case;
  17243.       new_line;
  17244.       Get_line(INPUT_BUFFER, MAX);
  17245.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  17246.          Goto GOOD_NODE_TYPE;
  17247.       End If;
  17248.       If INPUT_BUFFER(1) = '=' Then
  17249.          Goto CHECK_FOR_ERROR;
  17250.       End If;
  17251.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) THEN
  17252.          NODE_HELP (1);
  17253.          Goto GET_NODE_TYPE;
  17254.       End If;
  17255. --
  17256. --PROCESS THE TYPE CODE.
  17257.       FLG:=0;
  17258.       For I in 1..4 Loop
  17259.          ITYPE := I;
  17260.          If INPUT_BUFFER(1) = KTYPE(1,I) or 
  17261.             INPUT_BUFFER(1) = KTYPE(2,I) Then
  17262.             FLG:=1;
  17263.             Exit;
  17264.          End If;
  17265.       End Loop;
  17266.       If FLG=0 then
  17267.          New_line;
  17268.          Put("Type is not valid...");
  17269.          Goto GET_NODE_TYPE;
  17270.       end if;
  17271. --
  17272. --GOOD NODE TYPE.  GET THE DATA FOR THIS NODE.
  17273.       NEW_TITLE_CHECK;
  17274. <<GOOD_NODE_TYPE>>
  17275.       If ITYPE < 1 Then
  17276.          Goto GET_NODE_TYPE;
  17277.       End If;
  17278.       If ITYPE = 1 Then  --NODE LIKE ANOTHER NODE.  GET NODE NAME.
  17279.          Loop
  17280.             New_line;
  17281.             Put("Like which node?");
  17282.             New_line;
  17283.             NODE_FETCH (KNAME, JNAME, JNUMBR, IERR);
  17284.             If IERR /= 0 Then
  17285.                New_line;
  17286.                Put("Node fetch error...No data created.");
  17287.                Goto CHECK_FOR_ERROR;
  17288.             End If;
  17289.             If JNUMBR > 0  Then
  17290.                NEW_TITLE_CHECK;
  17291. -- COPY DATA FROM NODE JNUMBR TO INUMBR
  17292.                ITYSND(INUMBR) := ITYSND(JNUMBR);
  17293.                NLSND(INUMBR) := NLSND(JNUMBR);
  17294.                NRSND(INUMBR) := NRSND(JNUMBR);
  17295.                NXSND(INUMBR) := NXSND(JNUMBR);
  17296.                for I in 1..4 loop
  17297.                   for J in 1..10 loop
  17298.                      XPSSND(I,J,INUMBR) := XPSSND(I,J,JNUMBR);
  17299.                   end loop;
  17300.                end loop;
  17301.                for I in 1..6 loop
  17302.                EPHSND(I,INUMBR) := EPHSND(I,JNUMBR);
  17303.                end loop; 
  17304.                for I in 1..2 loop
  17305.                   for J in 1..15 loop
  17306.                      IRCSND(I,J,INUMBR) := IRCSND(I,J,JNUMBR);
  17307.                      IXTSND(I,J,INUMBR) := IXTSND(I,J,JNUMBR);
  17308.                   end loop;
  17309.                end loop;
  17310.                New_line;
  17311.                Put("Do you wish to modify this node? (Y/N): ");
  17312.                Get_LINE(INPUT_BUFFER, MAX);
  17313.                If (INPUT_BUFFER(1) = 'N') or (INPUT_BUFFER(1) = 'n') Then
  17314.                   Goto CHECK_FOR_ERROR;
  17315.                Else
  17316.                   Goto GET_NODE_TYPE;
  17317.                End If; 
  17318.                New_line;
  17319.                Put("Node does not exist.");
  17320.             End If;
  17321.          End Loop;
  17322.       End If;
  17323. --
  17324. --ENTER NODE DATA.
  17325.       ITYSND(INUMBR) := NODE_TYPES'VAL(ITYPE - 1);
  17326.       NODE_DATA (INUMBR, ISTOP);
  17327.       If ISTOP = 0 Then
  17328.           IERRCD := 0;
  17329.       End If;
  17330. --
  17331. <<CHECK_FOR_ERROR>>
  17332.       If ITYPE = 0 Then
  17333.          IERRCD := 1;
  17334.       End If;
  17335.       If IERRCD = 0 Then
  17336.          Return;
  17337.       Else
  17338.          New_line;
  17339.          Put("Node data not saved.  Error code = ");
  17340.          Put(IERRCD);
  17341.       End If;
  17342. --
  17343.       End NODE_ADD;
  17344. --
  17345. --
  17346.       Procedure NODE_DATA (INUMBR: in integer; ISTOP: out integer) is
  17347. --
  17348. --PURPOSE: NODE_DATA is responsible for accepting and checking any data
  17349. --         entered for a given node.  It acquires all data which
  17350. --         depends on the type of node.
  17351. --
  17352. --AUTHOR:  J. Conrad
  17353. --
  17354. --TYPE:    I/O Processing
  17355. --
  17356. --PARAMETER DESCRIPTIONS:
  17357. --IN        INUMBR = The index number of the node being added.
  17358. --OUT       ISTOP  = The stop flag where,
  17359. --                      0 means that all additions were
  17360. --                        normal,
  17361. --                      1 means that an addition was terminated
  17362. --                        before completion.
  17363. --
  17364. --CALLED BY:
  17365. --         NODE_ADD
  17366. --
  17367. --CALLS TO:
  17368. --         BLANK_CHECK
  17369. --         ENTITY_DATA
  17370. --         HELP_CHECK
  17371. --         INTEGER_TO_ALPHA
  17372. --         LOCATION_DATA
  17373. --         NODE_HELP
  17374. --         PARSE
  17375. --
  17376. --TECHNICAL DESCRIPTION:
  17377. --         NODE_DATA accepts all data needed for each specific type of
  17378. --         node.  Any name of alphanumeric data is accepted as such
  17379. --         and converted to integer format before storing in NODNAM.
  17380. --         The operator may terminate an addition at any time simply 
  17381. --         by entering an =.
  17382. --
  17383.       I,J: integer;
  17384.       LOCERR,IERR: integer;
  17385. --
  17386.       Begin
  17387. --
  17388. --LOCATION.
  17389.       ISTOP := 1;
  17390.       LOCATION_DATA(INUMBR, LOCERR);
  17391.       IF LOCERR /= 0 Then
  17392.          Return;
  17393.       End If;
  17394. --
  17395. --RECEIVERS.
  17396.       For I in 1..15 Loop
  17397.          J := I;
  17398.          ENTITY_DATA(1,J, NRSND(INUMBR), IRCSND, NUMREC, NAMREC,
  17399.                       ITPREC, INUMBR, IERR);
  17400.          Exit When IERR = 1;
  17401.       End Loop;
  17402. --
  17403. --TRANSMITTERS.
  17404.       For I in 1..15 Loop
  17405.          J := I;
  17406.          ENTITY_DATA(2,J, NXSND(INUMBR), IXTSND, NUMXMT, NAMXMT,
  17407.                       ITPXMT, INUMBR, IERR);
  17408.          Exit When IERR = 1;
  17409.       End Loop;
  17410. --
  17411. --ALL DATA ADDED.");
  17412.       ISTOP := 0;
  17413.       Return;
  17414. --
  17415.       End NODE_DATA;
  17416. --
  17417. --
  17418.       Procedure NODE_DISPLAY (IBUFF: in L_ARRAY; NV: in out integer) is
  17419. --
  17420. --PURPOSE: NODE_DISPLAY displays the requested nodes to either the print      
  17421. --         or the monitor depending on the value of CURRENT_COMMAND.
  17422. --
  17423. --AUTHOR:  J. Conrad
  17424. --
  17425. --TYPE:    Output module
  17426. --
  17427. --PARAMETER DESCRIPTIONS:
  17428. --IN        IBUFF  = The array containing the node numbers to be displayed.
  17429. --IN        NV     = The number of elements in IBUFF.
  17430. --
  17431. --CALLED BY:
  17432. --         NODE_HANDLER
  17433. --
  17434. --CALLS TO:
  17435. --         INTEGER_TO_ALPHA
  17436. --         NODE_FIND
  17437. --
  17438. --TECHNICAL DESCRIPTION:
  17439. --         NODE_DISPLAY displays only the nodes listed in the array IBUFF
  17440. --         as long as NV is not 0 on entry.  When NV is 0 this signals
  17441. --         that all nodes should be displayed, therefore if many nodes 
  17442. --         exist, and the specified device is the monitor, this can cause 
  17443. --         data to scroll off the screen.  Note that the standard output
  17444. --         device is switched from the monitor to the printer depending
  17445. --         on CURRENT_COMMAND.
  17446. --
  17447.       ICOMPL: boolean;
  17448.       I,II,J: integer;
  17449.       IERRCD: integer;
  17450.       KNAME: string(1..6);
  17451.       INUMBR: integer;
  17452. --
  17453.       Begin
  17454. --
  17455. --SET THE OUTPUT DEVICE.
  17456.       If CURRENT_COMMAND = PRINT Then
  17457.          SET_OUTPUT(PRINTER_OUTPUT_FILE);
  17458.       End If;
  17459. --
  17460. --GET THE NUMBER OF NODES TO DISPLAY AND THE DEVICE NUMBER.
  17461.       ICOMPL := FALSE;
  17462.       If NV = 0 or NV = NUMNOD Then
  17463.          ICOMPL := TRUE;
  17464.       End If;
  17465. --
  17466. --PRINT OUT REPORT HEADER.
  17467.       If ICOMPL Then
  17468.          New_line;
  17469.          Put(TITLE); 
  17470.          New_line;New_line;
  17471.          Put("                    NODE SUMMARY"); 
  17472.          New_line;
  17473.          Put("               There are currently "); 
  17474.          Put(NUMNOD); 
  17475.          Put(" nodes."); 
  17476.          New_line;
  17477.          NV := NUMNOD;
  17478.       End If;
  17479. --
  17480. --LOOP ON NUMBER OF NODES TO PRINT.
  17481.       If NV < 1 Then
  17482.          Return;
  17483.       End If;
  17484. --
  17485.       For II in 1..NV Loop
  17486.          NODE_FIND (KNAME, IBUFF(II), INUMBR, IERRCD);
  17487.          If IERRCD /= 0 Then
  17488.             --RESET THE OUTPUT DEVICE.
  17489.             If CURRENT_COMMAND = PRINT Then
  17490.                 SET_OUTPUT(STANDARD_OUTPUT);
  17491.             End If;
  17492.             New_line;
  17493.             Put("Unable to access node ");
  17494.             Put(KNAME);
  17495.             Put("  Error = ");
  17496.             Put(IERRCD);
  17497.             --SET THE OUTPUT DEVICE.
  17498.             If CURRENT_COMMAND = PRINT Then
  17499.                SET_OUTPUT(PRINTER_OUTPUT_FILE);
  17500.             End If;
  17501.             Goto END_OF_LOOP;
  17502.          End If;
  17503.          If INUMBR < 1 Then
  17504.             --RESET THE OUTPUT DEVICE.
  17505.             If CURRENT_COMMAND = PRINT Then
  17506.                 SET_OUTPUT(STANDARD_OUTPUT);
  17507.             End If;
  17508.             New_line;
  17509.             Put("Cannot find node ");
  17510.             Put(KNAME);
  17511.             --SET THE OUTPUT DEVICE.
  17512.             If CURRENT_COMMAND = PRINT Then
  17513.                SET_OUTPUT(PRINTER_OUTPUT_FILE);
  17514.             End If;
  17515.             Goto END_OF_LOOP;
  17516.          End If;
  17517. --
  17518. --PRINT HEADING
  17519. --NODE NAME.
  17520. --
  17521. --GET THE LOCATION DATA BASED ON TYPE.
  17522.          If ITYSND(INUMBR) = FIXED Then
  17523.             I := 1;
  17524.             New_line;New_line;New_line;New_line;New_line;
  17525.             Put(KNAME);
  17526.             Put(" is a fixed node.");
  17527.             New_line;New_line;
  17528.             Put("  North      East");
  17529.             New_line;
  17530.             Put("Latitude   Longitude   Altitude");
  17531.             New_line;
  17532.             Put("  (deg)      (deg)       (km)");
  17533.             New_line;
  17534.             For J in 2..4 Loop
  17535.                Put(XPSSND(J,I,INUMBR),5,1,0);
  17536.                Put("   ");
  17537.             End Loop;
  17538.          End If;
  17539. --
  17540.          If ITYSND(INUMBR) = MOVING Then
  17541.             New_line;New_line;New_line;New_line;New_line;
  17542.             Put(KNAME);
  17543.             Put(" is a moving node.");
  17544.             New_line;New_line;
  17545.             Put("               North      East");
  17546.             New_line;
  17547.             Put("Time (min)   Latitude   Longitude   Altitude");
  17548.             New_line;
  17549.             Put("               (deg)      (deg)       (km)");
  17550.             New_line;
  17551.             For I in 1..NLSND(INUMBR) Loop
  17552.                For J in 1..4 Loop
  17553.                   Put (XPSSND(J,I,INUMBR),5,2,0);
  17554.                   Put("   ");
  17555.                End Loop;
  17556.                New_line;
  17557.             End Loop;
  17558.          End If;
  17559. --
  17560.          If ITYSND(INUMBR) = SATELLITE Then
  17561.             New_line;New_line;New_line;New_line;New_line;
  17562.             Put(KNAME);
  17563.             Put(" is a satellite.");
  17564.             New_line;
  17565.             Put_line("                          Arg.of    East Long.");
  17566.             Put("SM-Axis   Eccen   Incln   Perigee   of Ascnd   ");
  17567.             Put_line("Time since Perigee");
  17568.             Put("  (km)            (deg)     (deg)   node (deg) ");
  17569.             Put_line(" (min)");
  17570.                Put(EPHSND(1,INUMBR),5,0,0);
  17571.                Put(EPHSND(2,INUMBR),3,3,0);
  17572.                Put("   ");
  17573.             For J in 3..6 Loop
  17574.                Put(EPHSND(J,INUMBR),5,0,0);
  17575.                Put("   ");
  17576.             End Loop;
  17577.             New_line;
  17578.          End If;
  17579. --
  17580. --RECEIVERS.
  17581.          If NRSND(INUMBR) >= 1 Then
  17582.             New_line;   
  17583.             Put("Receiver   Class");
  17584.             For I in 1..NRSND(INUMBR) Loop
  17585.                INTEGER_TO_ALPHA (IRCSND(1,I,INUMBR), KNAME);
  17586.                New_line;
  17587.                Put(KNAME);
  17588.                INTEGER_TO_ALPHA (IRCSND(2,I,INUMBR), KNAME);
  17589.                Put("     ");
  17590.                Put(KNAME);
  17591.             End Loop;
  17592.          End If;
  17593. --
  17594. --TRANSMITTERS.
  17595.          If NXSND(INUMBR) >= 1 Then
  17596.             New_line;   
  17597.             Put("Transmitter   Class");
  17598.             For I in 1..NXSND(INUMBR) Loop
  17599.                INTEGER_TO_ALPHA (IXTSND(1,I,INUMBR), KNAME);
  17600.                New_line;
  17601.                Put(KNAME);
  17602.                INTEGER_TO_ALPHA (IXTSND(2,I,INUMBR), KNAME);
  17603.                Put("        ");
  17604.                Put(KNAME);
  17605.             End Loop;
  17606.          End If;
  17607. --
  17608. <<END_OF_LOOP>>
  17609.          Null;
  17610.          New_line;
  17611. --
  17612.       End Loop;
  17613. --
  17614. --RESET THE OUTPUT DEVICE.
  17615.       If CURRENT_COMMAND = PRINT Then
  17616.          SET_OUTPUT(STANDARD_OUTPUT);
  17617.       End If;
  17618. --
  17619.       Return;
  17620. --
  17621.       End NODE_DISPLAY;
  17622. --
  17623. --
  17624.       Procedure NODE_FETCH (KNAME: out string;
  17625.                             INAME: out long_integer; 
  17626.                             INUMBR: out integer;
  17627.                             IERRCD: out integer) is
  17628. --
  17629. --PURPOSE: NODE_FETCH obtains a node from the node data structure.
  17630. --
  17631. --AUTHOR:  J. Conrad
  17632. --
  17633. --TYPE:    Table Look-up
  17634. --
  17635. --PARAMETER DESCRIPTIONS:
  17636. --OUT       KNAME  = Node name string.
  17637. --OUT       INAME  = The coded node name.
  17638. --OUT       INUMBR = The location of INAME in the node data structure.
  17639. --                   A value of zero (0) is returned if INAME
  17640. --                   cannot be located.
  17641. --OUT       IERRCD = The error code where 0 is normal or it is set to 1 
  17642. --                   if the user types a =.
  17643. --
  17644. --CALLED BY:
  17645. --         NODE_ADD
  17646. --         NODE_HANDLER
  17647. --
  17648. --CALLS TO:
  17649. --         HELP_CHECK
  17650. --         NODE_FIND
  17651. --         NODE_HELP
  17652. --         PARSE
  17653. --
  17654. --TECHNICAL DESCRIPTION:
  17655. --         NODE_FETCH queries the operator for a node name, and then
  17656. --         does a table lookup in the node data structure for
  17657. --         the specified node.  When the node is located, its
  17658. --         position in the structure is returned in the variable
  17659. --         INUMBR.  If the node cannot be located, a value of zero
  17660. --         is returned in INUMBR.
  17661. --
  17662. --
  17663.       Begin
  17664. --
  17665.       IERRCD := 1;
  17666. <<GET_NODE_NAME>>
  17667.       New_line;
  17668.       Put("Enter node name: ");
  17669.       Get_LINE(INPUT_BUFFER, MAX);
  17670.       KNAME := INPUT_BUFFER(1..6);
  17671.       If INPUT_BUFFER(1) = '=' Then
  17672.          Return;
  17673.       End If;
  17674.       If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  17675.          NODE_HELP (9);
  17676.          Goto GET_NODE_NAME;
  17677.       End If;
  17678.       NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  17679.       PARSE (INPUT_BUFFER(1..MAX));
  17680.       If NUMBER_OF_VARIABLES_EXTRACTED < 1 Then
  17681.          Goto GET_NODE_NAME;
  17682.       End If;
  17683. --
  17684. --FOUND NAME STRING.
  17685.       IERRCD := 0;
  17686.       INAME:=IARRAY(1);
  17687.       NODE_FIND (KNAME, IARRAY(1), INUMBR, IERRCD);
  17688. --
  17689.       Return;
  17690. --
  17691.       End NODE_FETCH;
  17692. --
  17693. --
  17694.       Procedure NODE_FIND (KNAME: out string;
  17695.                            INAME: in long_integer;
  17696.                            INUMBR: out integer;
  17697.                            IERRCD: out integer) is
  17698. --
  17699. --PURPOSE: NODE_FIND locates a node in the node data structure.
  17700. --
  17701. --AUTHOR:  J. Conrad
  17702. --
  17703. --TYPE:    Table Look-up
  17704. --
  17705. --PARAMETER DESCRIPTIONS:
  17706. --OUT       KNAME  = Alphanumeric node name string.
  17707. --IN        INAME  = Coded node name.
  17708. --OUT       INUMBR = Location of INAME in the node data structure.
  17709. --                   A value of zero (0) is returned if INAME
  17710. --                   cannot be located.
  17711. --OUT       IERRCD = Error flag, any value greater than zero indicates
  17712. --                   an error has occured.
  17713. --
  17714. --CALLED BY:
  17715. --         NODE_DISPLAY
  17716. --         NODE_FETCH
  17717. --         NODE_HANDLER
  17718. --         NODE_REMOVE
  17719. --
  17720. --CALLS TO:
  17721. --         INTEGER_TO_ALPHA
  17722. --
  17723. --TECHNICAL DESCRIPTION:
  17724. --         NODE_FIND does a table lookup in the node data structure for
  17725. --         the specified node.  When the node is located, its
  17726. --         position in the structure is returned in the variable
  17727. --         INUMBR.  If the node cannot be located, a value of zero
  17728. --         is returned in INUMBR.
  17729. --
  17730.       I: integer;
  17731. --
  17732.       Begin
  17733. --
  17734.       IERRCD := 0;
  17735. --
  17736. --CONVERT NAME TO ALPHA.
  17737.       INTEGER_TO_ALPHA (INAME, KNAME);
  17738. --
  17739.       INUMBR := 0;
  17740.       IF NUMNOD < 1 Then
  17741.          INUMBR := 0;
  17742.          Return;
  17743.       End If;
  17744. --
  17745. --SEARCH THE DATA STRUCTURE FOR THE NODE.
  17746.       For I in 1..NUMNOD Loop
  17747.          INUMBR := I;
  17748.          If INAME = NAMNOD(I) Then
  17749.             Return;
  17750.          End If;
  17751.       End Loop;
  17752.       INUMBR := 0;
  17753.       Return;
  17754. --
  17755.       End NODE_FIND;
  17756. --
  17757. --
  17758.       Procedure NODE_HANDLER is
  17759. --
  17760. --PURPOSE: NODHND drives the node processing routines.
  17761. --
  17762. --AUTHOR:  J. Conrad
  17763. --
  17764. --TYPE:    I/O PROCESSING
  17765. --
  17766. --PARAMETER DESCRIPTIONS:
  17767. --         'NONE'  
  17768. --
  17769. --CALLED BY:
  17770. --          MAIN
  17771. --          PRINT_HANDLER
  17772. --
  17773. --CALLS TO:
  17774. --         BLANK_CHECK
  17775. --         INTEGER_TO_ALPHA
  17776. --         NODE_ADD
  17777. --         NODE_DISPLAY
  17778. --         NODE_FETCH
  17779. --         NODE_FIND
  17780. --         NODE_REMOVE
  17781. --         PARSE
  17782. --
  17783. --TECHNICAL DESCRIPTION:
  17784. --         NODE_HANDLER serves as the driver for the routines which add,
  17785. --         delete, and modify nodes.
  17786. --
  17787.       INAME: L_ARRAY(1..MAXNOD);
  17788.       K,NV,IFLG: integer;
  17789.       KNAME: string(1..6);
  17790.       JNAME: long_integer;
  17791.       JNUMBR: integer;
  17792.       IERR: integer;
  17793.       IERRCD: integer;
  17794.       INUMBR: integer;
  17795. --
  17796.       Begin
  17797. --
  17798.       IFLG := 0;
  17799. --
  17800.       Case CURRENT_COMMAND is 
  17801.        When ADD =>
  17802. <<ADD_NODE>>
  17803.          NODE_FETCH (KNAME, JNAME, JNUMBR, IERRCD);
  17804.          If KNAME(1) = '=' or IERRCD /= 0 Then return; End if;
  17805.          If JNUMBR >= 1 Then
  17806.             New_line;
  17807.             Put("Node ");
  17808.             Put(KNAME);
  17809.             Put(" already exists.");
  17810.             GoTo ADD_NODE;
  17811.           End If;
  17812.           If NUMNOD >= MAXNOD Then
  17813.              New_line;
  17814.              Put("No more nodes may be added.  Redimension node arrays.");
  17815.              Return;
  17816.           End If;
  17817.           NUMNOD := NUMNOD + 1;
  17818.           JNUMBR := NUMNOD;
  17819.           NAMNOD(JNUMBR) := JNAME;
  17820. --CLEARS NODE FOR INPUT
  17821.           ITYSND(JNUMBR):=NOTDEFINED;
  17822.           for I in 1..10 loop
  17823.              for J in 2..4 loop
  17824.                 XPSSND(J,I,JNUMBR) := 0.0;
  17825.              end loop;
  17826.           end loop;
  17827.           for I in 1..6 loop
  17828.              EPHSND(I,JNUMBR) := 0.0;
  17829.           end loop;
  17830.           for I in 1..2 loop
  17831.              for J in 1..15 loop
  17832.                 IRCSND(I,J,JNUMBR):=0;
  17833.                 IXTSND(I,J,JNUMBR):=0;
  17834.              end loop;
  17835.           end loop;
  17836.           NLSND(JNUMBR) := 0;
  17837.           NRSND(JNUMBR) := 0;
  17838.           NXSND(JNUMBR) := 0;
  17839. --
  17840.           NODE_ADD (JNUMBR, IERRCD);
  17841.           If IERRCD = 0 Then
  17842.              Goto ADD_NODE;
  17843.           Else
  17844.              NUMNOD := NUMNOD - 1;
  17845.           End If;
  17846. --
  17847. --PROCESS THE VIEW OR PRINT COMMANDS.
  17848.      When VIEW | PRINT =>
  17849.          NV := NUMNOD;
  17850.          If NV >= 1 Then
  17851.             For K in 1..NV Loop
  17852.                INAME(K) := NAMNOD(K);
  17853.             End Loop;
  17854.             If not BLANK_CHECK(ARGUMENT_BUFFER) Then
  17855.                NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  17856.                PARSE (ARGUMENT_BUFFER);
  17857.                NV := NUMBER_OF_VARIABLES_EXTRACTED;
  17858.                For K in 1..NV Loop
  17859.                    INAME(K) := IARRAY(K);
  17860.                End Loop;
  17861.             End If;
  17862.          End If;
  17863.          NODE_DISPLAY (INAME, NV);
  17864. --
  17865. --PROCESS THE DELETION COMMAND.
  17866.       When DEL  =>
  17867.          Loop
  17868.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  17869.             New_line;
  17870.             Put("Enter the node names to be deleted, separated by spaces.");
  17871.             New_line;
  17872.             Get_Line(ARGUMENT_BUFFER, MAX);
  17873.          End Loop;
  17874.          If ARGUMENT_BUFFER(1) = '=' Then Return; End if;
  17875.          NUMBER_OF_VARIABLES_TO_EXTRACT := -40;
  17876.          PARSE (ARGUMENT_BUFFER);
  17877.          NV := NUMBER_OF_VARIABLES_EXTRACTED;
  17878.          If NV <= 0 Then
  17879.             NV := 1;
  17880.          End If;
  17881.          NODE_REMOVE (IARRAY, NV);
  17882. --
  17883. --PROCESS THE MODIFY COMMAND.
  17884.       When MODIFY =>
  17885.          Loop
  17886.             Exit When not BLANK_CHECK(ARGUMENT_BUFFER);
  17887.             New_line;
  17888.             Put("Enter the name of the node to be modified: ");
  17889.             Get_LINE(ARGUMENT_BUFFER,MAX);
  17890.          End Loop;
  17891.          If ARGUMENT_BUFFER(1) = '=' Then Return; end if;
  17892.          NUMBER_OF_VARIABLES_TO_EXTRACT := -1;
  17893.          PARSE (ARGUMENT_BUFFER);
  17894.          If NUMBER_OF_VARIABLES_EXTRACTED > 0 Then
  17895.             NODE_FIND (KNAME, IARRAY(1), INUMBR, IERRCD);
  17896.             If IERRCD /= 0 Then return; end if;
  17897.             If INUMBR <= 0 Then
  17898.                New_line;
  17899.                Put("Node name ");
  17900.                Put(KNAME);
  17901.                Put(" does not exist.");
  17902.                Return; 
  17903.             End If;
  17904.             NODE_ADD (INUMBR, IERRCD);
  17905.           End If;
  17906. --
  17907. --INVALID COMMAND WARNING.
  17908.       When others => New_line;
  17909.       Put("The command code is not valid for node processing.");
  17910.       Return;
  17911.    end Case;
  17912. --
  17913.    end NODE_HANDLER;
  17914. --
  17915. --
  17916.       Procedure NODE_HELP (IWHO: in integer) is
  17917. --
  17918. --PURPOSE: NODE_HELP prints the various help messages as requested by
  17919. --         the operator for the different levels of node processing.
  17920. --
  17921. --AUTHOR:  J. Conrad
  17922. --
  17923. --TYPE:    Operator assistance
  17924. --
  17925. --PARAMETER DESCRIPTIONS:
  17926. --IN        IWHO   = The indicator flag for which help message to print.
  17927. --
  17928. --CALLED BY:
  17929. --         ENTITY_DATA
  17930. --         LOCATION_DATA
  17931. --         NODE_ADD
  17932. --         NODE_DATA
  17933. --         NODE_FETCH
  17934. --
  17935. --CALLS TO:
  17936. --         'NONE'
  17937. --
  17938. --TECHNICAL DESCRIPTION:
  17939. --         NODE_HELP prints the various help messages as requested by
  17940. --         the operator for the different levels of node processing.
  17941. --         The particular help message printed depends on the value
  17942. --         of IWHO input.
  17943. --
  17944.       Begin
  17945. --
  17946. --SELECT THE HELP MESSAGE TO DISPLAY.
  17947.       If IWHO = 1 Then
  17948.          New_line;
  17949.          Put("Select the node type as one of the following:");
  17950.          New_line;
  17951.          Put("    Fixed;");
  17952.          New_line;
  17953.          Put("    Moving; or,");
  17954.          New_line;
  17955.          Put("    Satellite.");
  17956.          New_line; New_line;
  17957.          Put("Or, you may also enter L or LIKE to set this node up exactly");
  17958.          New_line;
  17959.          Put("like some other node.");
  17960.          New_line;New_line;
  17961.       End If;
  17962. --
  17963.       If IWHO = 2 Then
  17964.          New_line;
  17965.          Put("Enter the latitude (degrees -90 to 90, positive north),");
  17966.          Put(" longitude (degrees");
  17967.          New_line;
  17968.          Put("-180 to 180, positive east), and altitude (kilometers),");
  17969.          Put(" separated by blanks.");
  17970.          New_line;New_line;
  17971.       End If;
  17972. -- 
  17973.       If IWHO = 3 Then
  17974.          New_line;
  17975.          Put("Enter the time (minutes), latitude (degrees -90 to 90,");
  17976.          Put(" positive north),");
  17977.          New_line;
  17978.          Put("longitude (degrees -180 to 180, positive, east), and");
  17979.          Put(" altitude (kilometers),");
  17980.          New_line;
  17981.          Put("separated by blanks.");
  17982.          New_line;New_line;
  17983.       End If;
  17984. --                                             
  17985.       If IWHO = 4 Then
  17986.          New_line;
  17987.          Put("The ephemeride data consist of six items:");
  17988.          New_line;
  17989.          Put(" 1 - the semi-major axis of the elliptical orbit");
  17990.          Put(" (0 - 200,000 km);");
  17991.          New_line;
  17992.          Put(" 2 - the eccentricity of the orbital ellipse (0 - 1);");
  17993.          New_line;
  17994.          Put(" 3 - the inclination of the orbital plane to the equitorial");
  17995.          New_line;
  17996.          Put("     plane(0 to 180 degrees);");
  17997.          New_line;
  17998.          Put(" 4 - the argument of perigee (-180 to 180 degrees);");
  17999.          New_line;
  18000.          Put(" 5 - the longitude of the ascending node");
  18001.          Put(" (-180 to 180 degrees);");
  18002.          New_line;
  18003.          Put(" 6 - the time since perigee (minutes).");
  18004.          New_line;New_line;
  18005.       End If;
  18006. -- 
  18007.       If IWHO = 7 Then
  18008.          New_line;
  18009.          Put("Enter the name of the receiver (up to six characters,");
  18010.          Put(" it should be unique for");
  18011.          New_line;
  18012.          Put("this node), and the receiver class name (up to six");
  18013.          Put(" characters).  If the");
  18014.          New_line;
  18015.          Put("receiver class does not already exist, a null receiver");
  18016.          Put(" class record will be");
  18017.          New_line;
  18018.          Put("created.");
  18019.          New_line;New_line;
  18020.       End If;
  18021. --                                             
  18022.       If IWHO = 8 Then
  18023.          New_line;
  18024.          Put("Enter the name of the transmitter (up to six characters)");
  18025.          Put(" and the transmitter");
  18026.          New_line;
  18027.          Put("class name (up to six characters).  If the transmitter");
  18028.          Put(" class does not already");
  18029.          New_line;
  18030.          Put("exist, a null transmitter class record will be created.");
  18031.          New_line;New_line;
  18032.       End If;
  18033. --
  18034.       If IWHO = 9 then
  18035.          NEW_LINE;
  18036.          Put("Enter a six character, alpha-numeric node name. "); 
  18037.          Put("If an = is entered, control is "); NEW_LINE;
  18038.          Put("returned to the executive and no data for this node"); 
  18039.          Put(" is entered.  If a carriage"); NEW_LINE;
  18040.          Put("return is entered, the node name prompt will be repeated.");
  18041.          NEW_LINE;
  18042.          Return;
  18043.       End if;
  18044. --
  18045.       If IWHO = 1 or IWHO = 2 or IWHO = 4 then
  18046.          Put("If the value displayed is satisfactory, then enter a");
  18047.          Put(" carriage return.  An =");
  18048.          New_line;
  18049.          Put("terminates the entry of this node with the information");
  18050.          Put(" entered to this point");
  18051.          New_line;
  18052.          Put("lost, unless this addition is -like- some other node or");
  18053.          Put(" if the node is being");
  18054.          New_line;
  18055.          Put("modified, then it is saved.");
  18056.          New_line;
  18057.          Return;
  18058.       end if;
  18059.       If IWHO = 3 or IWHO = 7 or IWHO = 8 then
  18060.          Put("If the data displayed are satisfactory, then enter a");
  18061.          Put(" carriage return.  An =");
  18062.          New_line;
  18063.          Put("terminates the entry for this sequence with the information");
  18064.          Put(" entered to this");
  18065.          New_line;
  18066.          Put("point saved.");
  18067.          New_line;
  18068.          Return;                                                    
  18069.       end if;
  18070.       Put("No help"); New_line;
  18071.       Return;
  18072. --
  18073.       End NODE_HELP;
  18074. --
  18075. --
  18076.       Procedure NODE_REMOVE (INAME: in L_ARRAY;
  18077.                              NUMBR: in integer) is
  18078. --
  18079. --PURPOSE: NODE_REMOVE removes nodes from the network.
  18080. --
  18081. --AUTHOR:  J. Conrad
  18082. --
  18083. --TYPE:    I/O Processing
  18084. --
  18085. --PARAMETER DESCRIPTIONS:
  18086. --IN        INAME  = The array containing the node names to be deleted.
  18087. --IN        NUMBR  = The number of node names in INAME.
  18088. --
  18089. --CALLED BY:
  18090. --         NODE_HANDLER
  18091. --
  18092. --CALLS TO:
  18093. --         NEW_TITLE_CHECK
  18094. --         NODE_FIND
  18095. --
  18096. --TECHNICAL DESCRIPTION:
  18097. --         NODE_REMOVE removes nodes from the database.  The pointer into
  18098. --         the node data array is adjusted for all nodes with an index
  18099. --         greater than the node being deleted; thereby effectively
  18100. --         overwriting the node data of the node to be deleted.
  18101. --
  18102.       I,N,IPT,L: integer;
  18103.       J, IERR: integer;
  18104.       KNAME: string(1..6);
  18105. --
  18106.       Begin
  18107. --
  18108. --LOOP ON ALL ELEMENTS TO BE REMOVED.
  18109.       For I in 1..NUMBR Loop
  18110.          NODE_FIND (KNAME, INAME(I), J, IERR);
  18111.          If J <= 0 Then
  18112.             New_line;
  18113.             Put("Node ");
  18114.             Put(KNAME);
  18115.             Put(" not found...no action taken.");
  18116.             Return;
  18117.          End If;
  18118.          NEW_TITLE_CHECK;
  18119.          N := NUMNOD - 1;
  18120.          If N >= J Then
  18121.             IPT := IPTNOD(J);
  18122.             For L in J..N Loop
  18123.                NAMNOD(L) := NAMNOD(L+1);
  18124.                IPTNOD(L) := IPTNOD(L+1);
  18125.             End Loop;
  18126.             IPTNOD(NUMNOD) := IPT;
  18127.             NAMNOD(NUMNOD) := 0;
  18128.          End If;
  18129.          NUMNOD := N;
  18130.       End Loop;
  18131. --
  18132.       Return;
  18133. --
  18134.       End NODE_REMOVE;
  18135. --
  18136. --
  18137.       Procedure LOCATION_DATA ( INUMBR: in integer; LOCERR: out integer ) is
  18138. --
  18139. --PURPOSE: LOCATION_DATA acquires the data for a single node location.
  18140. --
  18141. --AUTHOR:  J. Conrad
  18142. --
  18143. --TYPE:    I/O Processing
  18144. --
  18145. --PARAMETER DESCRIPTIONS:
  18146. --IN        INUMBR = The index number of the node being addressed.
  18147. --OUT       LOCERR = Flag set to 1 if = is read for a fixed
  18148. --                   location or node type is invalid.
  18149. --
  18150. --CALLED BY:
  18151. --         NODE_DATA
  18152. --
  18153. --CALLS TO:
  18154. --         BLANK_CHECK
  18155. --         HELP_CHECK
  18156. --         NEW_TITLE_CHECK
  18157. --         NODE_HELP
  18158. --         PARSE
  18159. --
  18160. --TECHNICAL DESCRIPTION:
  18161. --         LOCATION_DATA is responsible for accepting and checking the
  18162. --         location data for a single node.  It acquires
  18163. --         latitude, longitude and altitude for fixed and moving
  18164. --         locations and acquires ephemeride data for satellites.
  18165. --
  18166.       I,J: integer;
  18167.       NLOC: integer;
  18168. --
  18169.       Begin
  18170. --
  18171.       LOCERR := 1;
  18172. --
  18173. --GET THE LOCATION DATA BASED ON TYPE.
  18174. --
  18175.       If ITYSND(INUMBR) = FIXED Then
  18176.          NLSND(INUMBR) := 1;
  18177. <<FIXED_NODE>>
  18178.          New_line;
  18179.          Put("  Latitude   Longitude   Altitude");
  18180.          New_line;
  18181.          Put(XPSSND(2,1,INUMBR),5,1,0);
  18182.          Put("   ");
  18183.          Put(XPSSND(3,1,INUMBR),5,1,0);
  18184.          Put("  ");
  18185.          Put(XPSSND(4,1,INUMBR),5,1,0);
  18186.          New_line;
  18187.          Get_LINE(INPUT_BUFFER,MAX);
  18188.          If INPUT_BUFFER(1) = '=' Then
  18189.             Return;
  18190.          End If;
  18191.          IF HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  18192.             NODE_HELP (2);
  18193.             Goto FIXED_NODE;
  18194.          End If;
  18195.          If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  18196.             LOCERR := 0;
  18197.             Return;
  18198.          End If;
  18199.          NUMBER_OF_VARIABLES_TO_EXTRACT := 3;
  18200.          PARSE (INPUT_BUFFER(1..MAX));
  18201.          If NUMBER_OF_VARIABLES_EXTRACTED /= 3 or
  18202.             XARRAY(1) < -90.0 or XARRAY(1) > 90.0 or
  18203.             XARRAY(2) < -180.0 or XARRAY(2) > 180.0 or
  18204.             XARRAY(3) < 0.0 Then  
  18205.             New_line;
  18206.             Put("Format error...re-enter data.");
  18207.             Goto FIXED_NODE;
  18208.          End If;
  18209.          For J in 2..4 Loop 
  18210.             XPSSND(J,1,INUMBR) := XARRAY(J-1);
  18211.          End Loop;
  18212.          NEW_TITLE_CHECK;
  18213.          LOCERR := 0;
  18214.          Return;
  18215.       End If;
  18216. --
  18217.       If ITYSND(INUMBR) = MOVING Then
  18218. <<MOVING_NODE>>
  18219.          New_line;
  18220.          Put("  Time   Latitude   Longitude   Altitude");
  18221.          For I in 1..10 Loop
  18222. <<TOP>>
  18223.             New_line;
  18224.             Put(XPSSND(1,I,INUMBR),5,0,0);
  18225.             Put("   ");
  18226.             Put(XPSSND(2,I,INUMBR),5,1,0);
  18227.             Put("   ");
  18228.             Put(XPSSND(3,I,INUMBR),5,1,0);
  18229.             Put("  ");
  18230.             Put(XPSSND(4,I,INUMBR),5,1,0);
  18231.             New_line;
  18232.             Get_LINE(INPUT_BUFFER,MAX);
  18233.             If INPUT_BUFFER(1) = '=' Then
  18234.                NLSND(INUMBR) := I - 1;
  18235.                LOCERR := 0;
  18236.                Return;
  18237.             End If;
  18238.             If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  18239.                NODE_HELP (3);
  18240.                Goto TOP;
  18241.             End If;
  18242.             If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  18243.                Goto BOTTOM;
  18244.             End If;
  18245.             NUMBER_OF_VARIABLES_TO_EXTRACT := 4;
  18246.             PARSE (INPUT_BUFFER(1..MAX));
  18247.             If NUMBER_OF_VARIABLES_EXTRACTED /= 4 or
  18248.                XARRAY(2) < -90.0 or XARRAY(2) > 90.0 or
  18249.                XARRAY(3) < -180.0 or XARRAY(3) > 180.0 or
  18250.                XARRAY(4) < 0.0  Then                       
  18251.                New_line;
  18252.                Put("Format error...re-enter data.");
  18253.                Goto TOP;
  18254.             End If;
  18255.             For J in 1..4 Loop 
  18256.                XPSSND(J,I,INUMBR) := XARRAY(J);
  18257.             End Loop;
  18258.             NEW_TITLE_CHECK;
  18259. <<BOTTOM>>
  18260.             Null;
  18261.          End Loop;
  18262.          NLSND(INUMBR) := 10;
  18263.          LOCERR := 0;
  18264.          Return;
  18265.       End If;
  18266. --
  18267.       If ITYSND(INUMBR) = SATELLITE Then
  18268.          New_line;
  18269.          Put("SM-Axis   Eccen   Incln   Perigee   Ascnd   Time");
  18270. <<SATELLITE_NODE>>
  18271.          New_line;
  18272.          Put(EPHSND(1,INUMBR),5,0,0);
  18273.          Put(EPHSND(2,INUMBR),5,3,0);
  18274.          Put(" ");
  18275.          For J in 3..6 Loop
  18276.             Put(EPHSND(J,INUMBR),6,0,0);
  18277.          End Loop;
  18278.          New_line;
  18279.          Get_LINE(INPUT_BUFFER,MAX);
  18280.          If INPUT_BUFFER(1) = '=' Then
  18281.             Return;
  18282.          End If;
  18283.          If HELP_CHECK(INPUT_BUFFER(1..MAX)) Then
  18284.            NODE_HELP (4);
  18285.             Goto SATELLITE_NODE;
  18286.          End If;
  18287.          IF BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  18288.             LOCERR := 0;
  18289.             Return;
  18290.          End If;
  18291.          NUMBER_OF_VARIABLES_TO_EXTRACT := 6;
  18292.          PARSE (INPUT_BUFFER(1..MAX));
  18293.          If NUMBER_OF_VARIABLES_EXTRACTED /= 6 or
  18294.             XARRAY(1) < 0.0 or XARRAY(1) > 200000.0 or
  18295.             XARRAY(2) < 0.0 or XARRAY(2) > 1.0 or
  18296.             XARRAY(3) < 0.0 or XARRAY(3) > 180.0 or
  18297.             XARRAY(4) < -180.0 or XARRAY(4) > 180.0 or
  18298.             XARRAY(5) < -180.0 or XARRAY(5) > 180.0 Then
  18299.             New_line;
  18300.             Put("Format error...re-enter data.");
  18301.             Goto SATELLITE_NODE;
  18302.          End If;
  18303.          For J in 1..6 Loop
  18304.             EPHSND(J,INUMBR) := XARRAY(J);
  18305.          End Loop;
  18306.          NEW_TITLE_CHECK;
  18307.          NLSND(INUMBR) := 0;
  18308.          LOCERR := 0;
  18309.          Return;
  18310.       End If;
  18311. --
  18312.       Return;
  18313. --
  18314.       End LOCATION_DATA;
  18315. --
  18316. --
  18317. End NODES;
  18318. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18319. --EXECUTIVE
  18320. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18321. With Text_IO; use Text_io;
  18322. With Helps; use Helps;
  18323. With Types; use Types;
  18324. With Constants; use Constants;
  18325. --
  18326. Package EXECUTIVE is
  18327.       Procedure COMMAND_LINE_PROCESSOR;
  18328.       Procedure INTERPRET_ENTITY;
  18329. End EXECUTIVE;
  18330. --
  18331. Package body EXECUTIVE is
  18332. --
  18333. -- EXECUTIVE Package of PROP_LINK Version 1.0,  February 16, 1985.
  18334. --
  18335. -- This EXECUTIVE Package contains the MAIN program as well as all
  18336. -- command line interpretation procedures.
  18337. --
  18338. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  18339. -- radio frequency propagation prediction code.
  18340. --
  18341. -- PROP_LINK has been developed for the Department of Defense under
  18342. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  18343. -- Systems Inc. (Jim Conrad).
  18344. --
  18345. Procedure COMMAND_LINE_PROCESSOR is
  18346. --
  18347. --PURPOSE:COMMAND_LINE_PROCESSOR is the Command Line Processor.
  18348. --
  18349. --AUTHOR:  J. Conrad
  18350. --
  18351. --TYPE:    Input Conversion
  18352. --
  18353. --PARAMETER DESCRIPTIONS:
  18354. --          'NONE'
  18355. --
  18356. --CALLED BY:
  18357. --          MAIN
  18358. --
  18359. --CALLS TO:
  18360. --          INTERPRET_ENTITY
  18361. --          HELP_CHECK
  18362. --          SHIFT_LEFT
  18363. --
  18364. --TECHNICAL DESCRIPTION:
  18365. --         This procedure decodes the command line in terms of commands and 
  18366. --         entities.  If an entity is associated with the command, a call to
  18367. --         INTERPRET_ENTITY is made to decode the entity as well.
  18368. --
  18369.       I,J,K,FLG: integer;
  18370.       KOMAND: array (integer range 1..2, integer range 0..8) of character;
  18371. --
  18372. Begin
  18373.       KOMAND :=(('R','W','P','V','S','G','A','D','M'),
  18374.                ('r','w','p','v','s','g','a','d','m'));
  18375.  
  18376. <<ACCEPT_INPUT>>
  18377.       New_line;
  18378.       Put("Type H for help or enter command: ");
  18379.       for I in INPUT_BUFFER'RANGE loop
  18380.          INPUT_BUFFER(I):=' ';
  18381.       end loop;
  18382.       Get_line(INPUT_BUFFER, MAX);
  18383.       If INPUT_BUFFER(1)='H' or INPUT_BUFFER(1)='h' Then
  18384.          New_line;
  18385.          Put("The proper format is:"); New_line;
  18386.          Put("<Command> <Entity> <Argument>"); New_line; New_line;
  18387.          Put("The valid commands are:"); New_line; New_line;
  18388.          Put("Read   -- recovers an existing data base;"); New_line;
  18389.          Put("Write  -- saves the current data base;"); New_line;
  18390.          Put("Print  -- outputs the current data base"); New_line;
  18391.          Put("          (one or all entities) to a print file;"); New_line;
  18392.          Put("View   -- displays the current data base"); New_line;
  18393.          Put("          (one or all entities) on the monitor;"); New_line;
  18394.          Put("Stop   -- halts program execution;"); New_line;
  18395.          Put("Go     -- begins RF propagation calculations;"); New_line;
  18396.          Put("Add    -- adds an entity to the current data base;"); New_line;
  18397.          Put("Delete -- removes an entity from the current data base; and,");
  18398.          New_line;
  18399.          Put("Modify -- modifies an entity in the current data base."); 
  18400.          New_line;
  18401.          Goto ACCEPT_INPUT;
  18402.       End If;
  18403. --CHECK FOR TYPE OF COMMAND
  18404.       FLG:=0; 
  18405.       SEARCH:
  18406.       For I in KOMAND'RANGE(1) Loop
  18407.          For J in KOMAND'RANGE(2) Loop
  18408.             IF INPUT_BUFFER(1) = KOMAND(I,J) Then
  18409.                K:=J;
  18410.                FLG := 1;
  18411.                EXIT SEARCH;
  18412.             End If;
  18413.          End Loop;
  18414.       End Loop SEARCH;
  18415.       If FLG=0 then
  18416.          Put_line(" That command is not valid...");
  18417.          Goto ACCEPT_INPUT;
  18418.       End if;
  18419. --
  18420. <<FOUND_COMMAND>>
  18421.       CURRENT_COMMAND := COMMAND'VAL(K);
  18422.       If (CURRENT_COMMAND = STOP) or (CURRENT_COMMAND = GO) Then
  18423.          Return;
  18424.       End If;
  18425. --SEARCH FOR END OF COMMAND
  18426.       FLG:=0;
  18427.       For I in INPUT_BUFFER'RANGE Loop
  18428.          If INPUT_BUFFER(1) = ' ' Then 
  18429.             FLG:=1;
  18430.             Exit; 
  18431.          End If;
  18432.          SHIFT_LEFT(INPUT_BUFFER);
  18433.       End Loop;
  18434.       If FLG=0 then
  18435.          New_line;
  18436.          Put("No blank found after command...");
  18437.          Goto ACCEPT_INPUT;
  18438.       End if;
  18439. --
  18440. <<CHECK_ENTITY>>
  18441.       INTERPRET_ENTITY;
  18442.       If (CURRENT_COMMAND = READ) or (CURRENT_COMMAND = WRITE) Then
  18443.          Return;
  18444.       End If;
  18445.       If CURRENT_ENTITY = ENTITY_ERROR and CURRENT_COMMAND /= PRINT Then
  18446.         Goto ACCEPT_INPUT;
  18447.       End If;
  18448. --
  18449.       End COMMAND_LINE_PROCESSOR;
  18450. --
  18451. Procedure INTERPRET_ENTITY is 
  18452. --
  18453. --PURPOSE: INTERPRET_ENTITY searches for the command line entity and 
  18454. --         decodes it.
  18455. --
  18456. --AUTHOR:  J. Conrad
  18457. --
  18458. --TYPE:    Conversion Module
  18459. --
  18460. --PARAMETER DESCRIPTIONS:
  18461. --          'NONE'
  18462. --
  18463. --CALLED BY:
  18464. --          COMMAND_LINE_PROCESSOR
  18465. --CALLS TO:
  18466. --         BLANK_CHECK
  18467. --         HELP_CHECK
  18468. --         SHIFT_LEFT
  18469. --
  18470. --TECHNICAL DESCRIPTION:
  18471. --         This procedure searches for valid entities based on the first 
  18472. --         letter of the entity.  A simple LOOP type search and compare
  18473. --         over the possible entity types is used.
  18474. --
  18475.       I,J,K,FLG: integer;
  18476.       KNT: array (integer range 1..2, integer range 0..2) of character;
  18477. --
  18478.       Begin
  18479.       KNT := (('R','T','N'),
  18480.              ('r','t','n'));
  18481.       CURRENT_ENTITY := ENTITY_ERROR;
  18482.       For I in ENTITY_BUFFER'RANGE Loop
  18483.          ENTITY_BUFFER(I) := ' ';
  18484.       End Loop;
  18485. --SEARCH FOR ENTITY
  18486.       FLG:=0;
  18487.       For I in INPUT_BUFFER'RANGE Loop
  18488.          If INPUT_BUFFER(1) /= ' ' Then
  18489.             FLG:=1;
  18490.             Exit; 
  18491.          End If;
  18492.          SHIFT_LEFT(INPUT_BUFFER);
  18493.       End Loop;
  18494.       If FLG=1 then 
  18495.          Goto DECODE_ENTITY;
  18496.       End if;
  18497. --NO ENTITY FOUND SO GET THE ENTITY, UNLESS A PRINT COMMAND.
  18498.       IF CURRENT_COMMAND = PRINT Then
  18499.          Return;
  18500.       End If;
  18501. --
  18502. <<GET_ENTITY>>
  18503.       If (CURRENT_COMMAND = READ) or (CURRENT_COMMAND = WRITE) Then
  18504.          New_line;
  18505.          Put(" Enter the filename: ");
  18506.       Else
  18507.          New_line;
  18508.          Put(" Enter the entity: ");
  18509.       End If;
  18510.       Get_LINE(INPUT_BUFFER,MAX);
  18511.       IF INPUT_BUFFER(1)='H' or INPUT_BUFFER(1)='h' Then
  18512.          New_line;
  18513.          Put("The valid entities are:"); New_line;New_line;
  18514.          Put("Node;"); New_line;
  18515.          Put("Receiver; and,"); New_line;
  18516.          Put("Transmitter."); New_line;
  18517.          Goto GET_ENTITY;
  18518.       End If;
  18519. --
  18520. <<DECODE_ENTITY>>
  18521.       IF (CURRENT_COMMAND = READ) or (CURRENT_COMMAND = WRITE) Then
  18522.          Goto BLANK_BUFFER_TEST;
  18523.       End If;
  18524.       FLG:=0;
  18525.       SEARCH:
  18526.       For I in KNT'RANGE(1) Loop
  18527.           For J in KNT'RANGE(2) Loop
  18528.             If INPUT_BUFFER(1) = KNT(I,J) Then
  18529.                K:=J;
  18530.                FLG:=1;
  18531.                Exit SEARCH; 
  18532.             End If;
  18533.           End Loop;
  18534.       End Loop SEARCH;
  18535.       If FLG=1 then 
  18536.          Goto FOUND_ENTITY;
  18537.       End if;
  18538.       If (CURRENT_COMMAND = READ) or (CURRENT_COMMAND = WRITE) or 
  18539.          (CURRENT_COMMAND = PRINT) Then
  18540.          Return;
  18541.       End If;
  18542. --A VALID ENTITY WAS NOT FOUND.
  18543.       New_line;
  18544.       Put(" There is an entity error...");
  18545.       Goto GET_ENTITY;
  18546. --
  18547. <<FOUND_ENTITY>>
  18548. --REMOVE THE REST OF THE ENTITY.
  18549.       CURRENT_ENTITY := ENTITY'VAL(K);
  18550.       For I in INPUT_BUFFER'RANGE Loop
  18551.          If INPUT_BUFFER(1) = ' ' Then
  18552.             Exit;
  18553.          Else 
  18554.          SHIFT_LEFT(INPUT_BUFFER);
  18555.          End If;
  18556.       End Loop;
  18557. --FIND THE START OF THE ARGUMENT BUFFER.
  18558.       For I in INPUT_BUFFER'RANGE Loop
  18559.          If INPUT_BUFFER(1) /= ' ' Then
  18560.             exit;
  18561.          Else
  18562.             SHIFT_LEFT(INPUT_BUFFER);
  18563.          End If;
  18564.       End Loop;
  18565.       Goto BUFFER_COPY;
  18566. --
  18567. <<BLANK_BUFFER_TEST>>
  18568.       If BLANK_CHECK(INPUT_BUFFER(1..MAX)) Then
  18569.          Goto GET_ENTITY;
  18570.       End If; 
  18571. --
  18572. <<BUFFER_COPY>>
  18573. --COPY OVER THE ARGUMENT BUFFER FOR USE IN THE HANDLERS.
  18574.       For I in INPUT_BUFFER'RANGE Loop
  18575.          ARGUMENT_BUFFER(I) := INPUT_BUFFER(I);
  18576.       End Loop;
  18577. --
  18578.       End INTERPRET_ENTITY;
  18579. --
  18580. End EXECUTIVE;
  18581. --
  18582.  
  18583. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18584. --IOANDFILE
  18585. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  18586. With debugger2; Use debugger2;
  18587. With Text_IO; Use Text_io, Float_io, Integer_io, Long_integer_io;
  18588. with Types; Use Types;
  18589. with Constants; use Constants;
  18590. with Constant2; use Constant2;
  18591. with Constant3; use Constant3;
  18592. with Nodes;
  18593. with Entityuti; use Entityuti;
  18594. Package IOANDFILE is
  18595. --
  18596. --    Type REAL is digits 6;
  18597. --
  18598.       Procedure READ_HANDLER;
  18599.       Procedure WRITE_HANDLER;
  18600. --
  18601. --
  18602. End IOANDFILE;
  18603. --
  18604. Package body IOANDFILE is
  18605. --
  18606. -- IO_AND_FILE_HANDLERS Package of PROP_LINK Version 1.0,  February 21, 1985.
  18607. --
  18608. -- This IO_AND_FILE_HANDLERS Package contains all of the procedures that
  18609. -- are used to perform file input and output.
  18610. --
  18611. -- PROP_LINK is the Ada version of STRATLINK, a FORTRAN stand-alone
  18612. -- radio frequency propagation prediction code.
  18613. --
  18614. -- PROP_LINK has been developed for the Department of Defense under
  18615. -- contract N66001-85-C-0042 by IWG Corp. (Bruce Perry) and StratCom
  18616. -- Systems Inc. (Jim Conrad).
  18617. --
  18618. -- Instantiate integer and floating point IO.
  18619. --    Package IO_INTEGER is new INTEGER_IO(INTEGER);
  18620. --    Package IO_FLOAT is new FLOAT_IO(FLOAT);
  18621. --    Use IO_INTEGER,IO_FLOAT;
  18622. --
  18623. --
  18624. --  VARIABLES:
  18625.       IUNIT: FILE_TYPE;
  18626. --
  18627. --
  18628.       Procedure ENSORT (NUMENT: in integer; 
  18629.                         NAMENT: in L_ARRAY;
  18630.                         INDEX: out I_ARRAY) is
  18631. --
  18632. --#PURPOSE: ENSORT performs an alphabetical sort of entities.
  18633. --
  18634. --#AUTHOR:  J. Conrad
  18635. --
  18636. --#TYPE:    Input
  18637. --
  18638. --#PARAMETER DESCRIPTIONS:
  18639. --IN        NUMENT := number of enties to be sorted.
  18640. --IN        NAMENT := array of entities to be sorted.
  18641. --OUT       INDEX  := pointer array of sorted names.
  18642. --
  18643. --#CALLED BY:
  18644. --          WRTNOD
  18645. --          WRTREC
  18646. --          WRTXMT
  18647. --
  18648. --#CALLS TO:
  18649. --          'NONE'
  18650. --
  18651. --#TECHNICAL DESCRIPTION:
  18652. --          ENSORT sorts the array of entities into alphabetical order.
  18653. --          The algorithm employed is a shell sort technique that has
  18654. --          been adapted from D. Knuth's "Art of Computer Programming".
  18655. --
  18656.       INCR,INCR1,INDX, I: integer;
  18657.       NAME: long_integer;
  18658. --
  18659.       Begin
  18660. --
  18661.       For I in 1..NUMENT Loop
  18662.          INDEX(I) := I;
  18663.       End Loop;
  18664.       If NUMENT <= 1  Then
  18665.          Return;
  18666.       End If;
  18667.       INCR := 13;
  18668. --
  18669.       Loop
  18670.          Exit When INCR >= NUMENT;
  18671.          INCR := 3*INCR + 1;
  18672.       End Loop;
  18673. --
  18674.       INCR := INCR/3;
  18675. --
  18676. -- MAJOR SORT LOOP
  18677.       Loop
  18678.          INCR := INCR/3;
  18679.          If INCR < 1 Then
  18680.             Return;
  18681.          End If;
  18682.          INCR1 := INCR + 1;
  18683.          For J in INCR1..NUMENT Loop
  18684.             I := J - INCR;
  18685.             INDX := INDEX(J);
  18686.             NAME := NAMENT(INDX);
  18687.             Loop
  18688.                Exit When NAME >= NAMENT(INDEX(I));
  18689.                INDEX(I+INCR) := INDEX(I);
  18690.                I := I - INCR;
  18691.                Exit When I <= 0;
  18692.             End Loop;
  18693.             INDEX(I+INCR) := INDX;
  18694.          End Loop;
  18695.       End Loop;
  18696. --
  18697.       End ENSORT;
  18698. --
  18699. --
  18700.       Procedure REDNOD is
  18701. --
  18702. --#PURPOSE: REDNOD reads the node data from the disk file.
  18703. --
  18704. --#AUTHOR:  J. Conrad
  18705. --
  18706. --#TYPE:    Input
  18707. --
  18708. --#PARAMETER DESCRIPTIONS:
  18709. --IN        'NONE'
  18710. --
  18711. --#CALLED BY:
  18712. --          READ_HANDLER
  18713. --
  18714. --#CALLS TO:
  18715. --          INITIALIZE_NODES
  18716. --
  18717. --#TECHNICAL DESCRIPTION:
  18718. --          REDNOD reads the node data from the disk file using a
  18719. --          series of Get statements.
  18720. --
  18721. --          Note that NKSND, TPKSND, TTRNOD, NPSND IPRSND and PROSND 
  18722. --          are only read to be compatible with SIMSTAR/StratSim/StratLink 
  18723. --          data bases.  Also note that both the old (IFORM /= 1) and
  18724. --          new SIMSTAR database formats may be read.
  18725. --
  18726.       J,K: Integer;
  18727.       IFORM, INODE, NKSND, NPSND, IPRSND, ITYPE: Integer;
  18728.       TPKSND, TTRNOD, PROSND: float;
  18729.       NAME1, NAME2: string(1..6);
  18730.       DUMMY: string(1..4);
  18731. --
  18732.      Begin
  18733. --
  18734. --BEGIN THE INPUT OPERATION.
  18735.       NODES.INITIALIZE_NODES;
  18736. --
  18737.       Get(NUMNOD, 5);
  18738.       Get(IFORM, 5);
  18739.       If NUMNOD <= 0 Then
  18740.          Return;
  18741.       End If;
  18742. --
  18743.       For INODE in 1..NUMNOD Loop
  18744.          If IFORM /= 1 Then
  18745.             Skip_line;
  18746.             Get(NAMNOD(INODE), 15);
  18747.          Else
  18748.             Skip_Line;
  18749.             Get(NAME1);
  18750.             ALPHA_TO_INTEGERIZED_ALPHA(NAME1, NAMNOD(INODE));
  18751.          End If;
  18752. --
  18753.          Skip_Line;
  18754.          Get(ITYPE, 5);
  18755.          Case ITYPE is
  18756.             When 1 => ITYSND(INODE) := FIXED;
  18757.             When 2 => ITYSND(INODE) := MOVING;
  18758.             When 3 => ITYSND(INODE) := SATELLITE;
  18759.             When Others => New_Line;
  18760.                Put("ERROR in REDNOD...unknown node type.");
  18761.          End Case;
  18762.          Get(NLSND(INODE), 7);
  18763.          Get(NKSND, 7);
  18764.          Get(NRSND(INODE), 7);
  18765.          Get(NXSND(INODE), 7);
  18766.          Get(NPSND, 7);
  18767.          If ITYSND(INODE) = SATELLITE Then
  18768.             Skip_line;
  18769.             For J in 1..5 Loop
  18770.                Get(EPHSND(J,INODE), 15);
  18771.             End Loop;
  18772.             Skip_line;
  18773.             Get(EPHSND(6,INODE), 15);
  18774.          End If;
  18775.          If NLSND(INODE) > 0 Then
  18776.             For K in 1..NLSND(INODE) Loop
  18777.                For J in 1..4 Loop
  18778.                   If (4*(K-1)+J) rem 5 = 1 Then
  18779.                      Skip_Line;
  18780.                   End If; 
  18781.                   Get(XPSSND(J,K,INODE), 15);
  18782.                End Loop;
  18783.             End Loop;
  18784.          End if;
  18785.          If NKSND > 0 Then
  18786.             For K in 1..NKSND Loop
  18787.                For J in 1..2 Loop
  18788.                   If (2*(K-1)+J) rem 5 = 1 Then
  18789.                      Skip_Line;
  18790.                   End If;
  18791.                   Get(TPKSND, 15);
  18792.                End Loop;
  18793.             End Loop;
  18794.             Skip_Line;
  18795.             Get(TTRNOD, 15);
  18796.          End If;
  18797.          If IFORM /= 1 Then
  18798.             If NRSND(INODE) > 0 Then
  18799.                For K in 1..NRSND(INODE) Loop
  18800.                   Skip_Line;
  18801.                   Get(IRCSND(1,K,INODE), 15);
  18802.                   Get(IRCSND(2,K,INODE), 17);
  18803.                End Loop;
  18804.             End If;
  18805.             If NXSND(INODE) > 0 Then
  18806.                For K in 1..NXSND(INODE) Loop
  18807.                   Skip_Line;
  18808.                   Get(IXTSND(1,K,INODE), 15);
  18809.                   Get(IXTSND(2,K,INODE), 17);
  18810.                End Loop;
  18811.             End If;
  18812.             If NPSND > 0 Then
  18813.                For K in 1..NPSND Loop
  18814.                   For J in 1..5 Loop
  18815.                      If J = 1 Then
  18816.                         Skip_Line;
  18817.                         Get(IPRSND, 15);
  18818.                      Else
  18819.                         Get(IPRSND, 16);
  18820.                      End If;
  18821.                   End Loop;
  18822.                End Loop;
  18823.             End If;
  18824.          Else
  18825. -- IFORM = 1 so read the names and convert them to integer.
  18826.             If NRSND(INODE) > 0 Then
  18827.                For K in 1..NRSND(INODE) Loop
  18828.                   Skip_Line;
  18829.                   Get(NAME1);
  18830.                   Get(DUMMY); -- Skip four spaces;
  18831.                   Get(NAME2);
  18832.                   ALPHA_TO_INTEGERIZED_ALPHA(NAME1,IRCSND(1,K,INODE));
  18833.                   ALPHA_TO_INTEGERIZED_ALPHA(NAME2,IRCSND(2,K,INODE));
  18834.                End Loop;
  18835.             End If;
  18836.             If NXSND(INODE) > 0 Then
  18837.                For K in 1..NXSND(INODE) Loop
  18838.                   Skip_Line;
  18839.                   Get(NAME1);
  18840.                   Get(DUMMY); -- Skip four spaces;
  18841.                   Get(NAME2);
  18842.                   ALPHA_TO_INTEGERIZED_ALPHA(NAME1,IXTSND(1,K,INODE));
  18843.                   ALPHA_TO_INTEGERIZED_ALPHA(NAME2,IXTSND(2,K,INODE));
  18844.                End Loop;
  18845.             End If;
  18846.             If NPSND > 0 Then
  18847.                For K in 1..NPSND Loop
  18848.                   Skip_Line;
  18849.                End Loop;
  18850.                For K in 1..NPSND Loop
  18851.                   For J in 1..4 Loop
  18852.                      If (4*(K-1)+J) rem 5 = 1 Then
  18853.                         Skip_Line;
  18854.                      End If; 
  18855.                      Get(PROSND);
  18856.                   End Loop;
  18857.                End Loop;
  18858.             End If;
  18859.          End If;
  18860. --
  18861.       End Loop;
  18862. --
  18863.       Return;
  18864. --    
  18865.       End REDNOD;
  18866. --
  18867. --
  18868.       Procedure REDREC is
  18869. --
  18870. --#PURPOSE: REDREC reads the receiver class data from the disk file.
  18871. --
  18872. --#AUTHOR:  J. Conrad
  18873. --
  18874. --#TYPE:    Input
  18875. --
  18876. --#PARAMETER DESCRIPTIONS:
  18877. --IN        'NONE'
  18878. --
  18879. --#CALLED BY:
  18880. --          READ_HANDLER
  18881. --
  18882. --#CALLS TO:
  18883. --          'NONE'
  18884. --
  18885. --#TECHNICAL DESCRIPTION:
  18886. --          REDREC reads the receiver class data from the disk file
  18887. --          using a series of Get statements.
  18888. --
  18889. --          Note that MODREC, SLBREC, BEMREC, NPHREC, ICRREC, FNDREC,
  18890. --          KBFREC, LRCREC, NSLREC, PFTIME, PFVAL, TTRREC, and NRPF
  18891. --          are only read to be compatible with SIMSTAR/StratSim/StratLink 
  18892. --          data bases.  Also note that both the old (IFORM /= 1) and
  18893. --          new SIMSTAR database formats may be read.
  18894. --
  18895.       NAME: string(1..6);
  18896.       I, J, IFLAG, ICRREC, ITYPE, MODREC, NPHREC, KBFREC: Integer;
  18897.       LRCREC, NSLREC: Integer;
  18898.       SLBREC, BEMREC, FMDREC, PFTIME, PFVAL, TTRREC: Float;
  18899.       NRPF: array (integer range 1..99) of integer;
  18900.       DUMMY: string(1..4);
  18901. --
  18902.       Begin
  18903. --
  18904. --BEGIN THE INPUT OPERATION.
  18905.       Get(NUMREC, 5);
  18906.       Get(IFLAG, 5);
  18907.       If NUMREC <= 0 Then
  18908.          Return;
  18909.       End If;
  18910. --
  18911.       If IFLAG /= 1 Then
  18912.          For I in 1..NUMREC Loop
  18913.             If I rem 4 = 1 Then
  18914.                Skip_Line;
  18915.                Get(NAMREC(I), 15);
  18916.             Else
  18917.                Get(NAMREC(I), 17);
  18918.             End If;
  18919.          End Loop;
  18920.          For I in 1..NUMREC Loop
  18921.             If I rem 10 = 1 Then
  18922.                Skip_Line;
  18923.                Get(ITYPE, 5);
  18924.             Else
  18925.                Get(ITYPE, 7);
  18926.             End If;
  18927.             begin
  18928.                ITPREC(I) := BAND_TYPES'VAL(ITYPE+1);
  18929.             exception
  18930.                when CONSTRAINT_ERROR =>
  18931.                   Put_line("ERROR in REDREC...unknown receiver type.");
  18932.             End;
  18933.          End Loop;
  18934.          For I in 1..NUMREC Loop
  18935.             If I rem 10 = 1 Then
  18936.                Skip_Line;
  18937.                Get(MODREC, 5);
  18938.             Else
  18939.                Get(MODREC, 7);
  18940.             End If;
  18941.          End Loop;
  18942.          For I in 1..NUMREC Loop
  18943.             If I rem 10 = 1 Then
  18944.                Skip_Line;
  18945.                Get(IATREC(I), 5);
  18946.             Else
  18947.                Get(IATREC(I), 7);
  18948.             End If;
  18949.          End Loop;
  18950.          For I in 1..NUMREC Loop
  18951.             If I rem 5 = 1 Then
  18952.                Skip_Line;
  18953.             End If;
  18954.             Get(FREREC(I), 15);
  18955.          End Loop;
  18956.          For I in 1..NUMREC Loop
  18957.             If I rem 5 = 1 Then
  18958.                Skip_Line;
  18959.             End If;
  18960.             Get(GTREC(I), 15);
  18961.          End Loop;
  18962.          For I in 1..NUMREC Loop
  18963.             If I rem 5 = 1 Then
  18964.                Skip_Line;
  18965.             End If;
  18966.             Get(BWREC(I), 15);
  18967.          End Loop;
  18968.          For I in 1..NUMREC Loop
  18969.             If I rem 5 = 1 Then
  18970.                Skip_Line;
  18971.             End If;
  18972.             Get(RLLREC(I), 15);
  18973.          End Loop;
  18974.          For I in 1..NUMREC Loop
  18975.             If I rem 5 = 1 Then
  18976.                Skip_Line;
  18977.             End If;
  18978.             Get(BEMREC, 15);
  18979.          End Loop;
  18980.          For I in 1..NUMREC Loop
  18981.             If I rem 10 = 1 Then
  18982.                Skip_Line;
  18983.                Get(NPHREC, 5);
  18984.             Else
  18985.                Get(NPHREC, 7);
  18986.             End If;
  18987.          End Loop;
  18988.          For I in 1..NUMREC Loop
  18989.             If I rem 10 = 1 Then
  18990.                Skip_Line;
  18991.                Get(ICRREC, 5);
  18992.             Else
  18993.                Get(ICRREC, 7);
  18994.             End If;
  18995.          End Loop;
  18996.          For I in 1..NUMREC Loop
  18997.             If I rem 5 = 1 Then
  18998.                Skip_Line;
  18999.             End If;
  19000.             Get(FMDREC, 15);
  19001.          End Loop;
  19002.          For I in 1..NUMREC Loop
  19003.             If I rem 10 = 1 Then
  19004.                Skip_Line;
  19005.                Get(KBFREC, 5);
  19006.             Else
  19007.                Get(KBFREC, 7);
  19008.             End If;
  19009.          End Loop;
  19010.          For I in 1..NUMREC Loop
  19011.             If I rem 10 = 1 Then
  19012.                Skip_Line;
  19013.                Get(LRCREC, 5);
  19014.             Else
  19015.                Get(LRCREC, 7);
  19016.             End If;
  19017.          End Loop;
  19018.          For I in 1..NUMREC Loop
  19019.             If I rem 10 = 1 Then
  19020.                Skip_Line;
  19021.                Get(NSLREC, 5);
  19022.             Else
  19023.                Get(NSLREC, 7);
  19024.             End If;
  19025.          End Loop;
  19026. --
  19027. --INPUT THE ADDITIONAL ANTENNA CHARACTERISTICS NEEDED FOR
  19028. --CONSTANT GAIN (5), RHOMBIC (6), VERTICAL (7) AND
  19029. --HORIZONTAL HALF WAVE DIPOLE (8) ANTENNA TYPES.
  19030.          For I in 1..NUMREC Loop
  19031.             If IATREC(I) > 4 and IATREC(I) < 9 Then
  19032.                Skip_Line;
  19033.                If IATREC(I) = 5 Then
  19034.                   Get(ANTGNR(I), 15);
  19035.                Elsif IATREC(I) = 6 Then
  19036.                   Get(ANTTAR(I), 15);
  19037.                   Get(ANTHTR(I), 15);
  19038.                   Get(ANTLNR(I), 15);
  19039.                Elsif IATREC(I) = 7 Then
  19040.                   Get(ANTLNR(I), 15);
  19041.                Elsif IATREC(I) = 8 Then
  19042.                   Get(ANTHTR(I), 15);
  19043.                End If;
  19044.             End If;
  19045.          End Loop;
  19046. --
  19047.          For I in 1..NUMREC Loop
  19048.             If I rem 10 = 1 Then
  19049.                Skip_Line;
  19050.                Get(NRPF(I), 5);
  19051.             Else
  19052.                Get(NRPF(I), 7);
  19053.             End If;
  19054.          End Loop;
  19055.          For I in 1..NUMREC Loop
  19056.             If NRPF(I) > 0 Then
  19057.                For J in 1..2*NRPF(I) Loop
  19058.                   If J rem 5 = 1 Then
  19059.                      Skip_Line;
  19060.                   End If;
  19061.                   Get(PFTIME, 15);  --PFVAL is actually every other Get.
  19062.                End Loop;
  19063.             End If;
  19064.          End Loop; 
  19065.          For I in 1..NUMREC Loop
  19066.             If I rem 5 = 1 Then
  19067.                Skip_Line;
  19068.             End If;
  19069.             Get(TTRREC, 15);
  19070.          End Loop;
  19071.       Else
  19072. --
  19073. -- INPUT FILE IS IN "NEW" FORMAT, EACH RECEIVER HAS ALPHA NAME AND ALL
  19074. -- DATA TOGETHER
  19075. --
  19076.          For I in 1..NUMREC Loop
  19077.             Skip_Line;
  19078.             Get(NAME);
  19079.             ALPHA_TO_INTEGERIZED_ALPHA(NAME,NAMREC(I));
  19080.             Get(DUMMY);      -- Skip 4 spaces.
  19081.             Get(ITYPE, 5);
  19082.             begin 
  19083.                ITPREC(I) := BAND_TYPES'VAL(ITYPE+1);
  19084.             exception
  19085.                When CONSTRAINT_ERROR =>
  19086.                   Put_line("ERROR in REDREC...unknown receiver type.");
  19087.             End;
  19088.             Get(MODREC, 5);
  19089.             Get(IATREC(I), 5);
  19090.             Get(LRCREC, 5);
  19091.             Get(NSLREC, 5);
  19092.             Get(FREREC(I), 15);
  19093.             Get(GTREC(I), 15);
  19094.             Get(BWREC(I), 15);
  19095.             Skip_line;
  19096.             Get(NPHREC, 5);
  19097.             Get(ICRREC, 5);
  19098.             Get(KBFREC, 5);
  19099.             Get(NRPF(I), 5);
  19100.             Get(FMDREC, 15);
  19101.             Get(SLBREC, 15);
  19102.             Get(BEMREC, 15);
  19103.             Get(RLLREC(I), 15);
  19104.             If IATREC(I) >= 5 and IATREC(I) <= 8 Then
  19105.                Skip_Line;
  19106.                Get(ANTGNR(I), 15);
  19107.                Get(ANTTAR(I), 15);
  19108.                Get(ANTHTR(I), 15);
  19109.                Get(ANTLNR(I), 15);
  19110.             End If;
  19111.             If NRPF(I) > 0 Then
  19112.                For J in 1..2*NRPF(I) Loop
  19113.                   If J rem 5 = 1 Then
  19114.                      Skip_Line;
  19115.                   End If;
  19116.                   Get(PFTIME, 15);  --PFVAL is actually every other Get.
  19117.                End Loop;
  19118.             End If;
  19119.          End Loop;
  19120. --
  19121.       End If;
  19122.       Return;
  19123. --
  19124.       End REDREC;
  19125. --
  19126. --
  19127.       Procedure REDXMT is
  19128. --
  19129. --#PURPOSE: REDXMT reads the transmitter class data from the disk file.
  19130. --
  19131. --#AUTHOR:  J. Conrad
  19132. --
  19133. --#TYPE:    Input
  19134. --
  19135. --#PARAMETER DESCRIPTIONS:
  19136. --IN        'NONE'
  19137. --
  19138. --#CALLED BY:
  19139. --          READ_HANDLER
  19140. --
  19141. --#CALLS TO:
  19142. --          'NONE'
  19143. --
  19144. --#TECHNICAL DESCRIPTION:
  19145. --          REDXMT reads the transmitter class data from the disk file
  19146. --          using a series of Get statements.
  19147. --
  19148. --          Note that DRTXMT, CHUXMT, PFTIMX, PFVALX, TTRXMT and NXPF
  19149. --          are only read to be compatible with SIMSTAR/StratSim/StratLink
  19150. --          data bases.  Also note that both the old (IFORM /= 1) and
  19151. --          new SIMSTAR database formats may be read.
  19152. --
  19153.       NAME: string(1..6);
  19154.       I, J, IFORM, ITYPE: Integer;
  19155.       DRTXMT, CHUXMT, PFTIMX, PFVALX, TTRXMT: Float;
  19156.       NXPF: array (integer range 1..99) of integer;
  19157.       DUMMY: string(1..4);
  19158. --
  19159.       Begin
  19160. --
  19161. --BEGIN THE INPUT OPERATION.
  19162.       Skip_line;
  19163.       Get(NUMXMT, 5);
  19164.       Get(IFORM, 5);
  19165.       If NUMXMT <= 0 Then
  19166.          Return;
  19167.       End If;
  19168. --
  19169.       If IFORM /= 1 Then
  19170.          For I in 1..NUMXMT Loop
  19171.             If I rem 4 = 1 Then
  19172.                Skip_Line;
  19173.                Get(NAMXMT(I), 15);
  19174.             Else
  19175.                Get(NAMXMT(I), 17);
  19176.             End If;
  19177.          End Loop;
  19178.          For I in 1..NUMXMT Loop
  19179.             If I rem 10 = 1 Then
  19180.                Skip_Line;
  19181.                Get(ITYPE, 5);
  19182.             Else
  19183.                Get(ITYPE, 7);
  19184.             End If;
  19185.             begin
  19186.                ITPXMT(I) := BAND_TYPES'VAL(ITYPE+1);
  19187.             exception
  19188.                When CONSTRAINT_ERROR =>
  19189.                   Put("ERROR in REDXMT...unknown transmitter type.");
  19190.             End;
  19191.          End Loop;
  19192.          For I in 1..NUMXMT Loop
  19193.             If I rem 10 = 1 Then
  19194.                Skip_Line;
  19195.                Get(IATXMT(I), 5);
  19196.             Else
  19197.                Get(IATXMT(I), 7);
  19198.             End If;
  19199.          End Loop;
  19200.          For I in 1..NUMXMT Loop
  19201.             If I rem 5 = 1 Then
  19202.                Skip_Line;
  19203.             End If;
  19204.             Get(BWXMT(I), 15);
  19205.          End Loop;
  19206.          For I in 1..NUMXMT Loop
  19207.             If I rem 5 = 1 Then
  19208.                Skip_Line;
  19209.             End If;
  19210.             Get(TRPXMT(I), 15);
  19211.          End Loop;
  19212.          For I in 1..NUMXMT Loop
  19213.             If I rem 5 = 1 Then
  19214.                Skip_Line;
  19215.             End If;
  19216.             Get(FREXMT(I), 15);
  19217.          End Loop;
  19218.          For I in 1..NUMXMT Loop
  19219.             If I rem 5 = 1 Then
  19220.                Skip_Line;
  19221.             End If;
  19222.             Get(DRTXMT, 15);
  19223.          End Loop;
  19224.          For I in 1..NUMXMT Loop
  19225.             If I rem 5 = 1 Then
  19226.                Skip_Line;
  19227.             End If;
  19228.             Get(CHUXMT, 15);
  19229.          End Loop;
  19230. --
  19231. --INPUT THE ADDITIONAL ANTENNA CHARACTERISTICS NEEDED FOR
  19232. --  CONSTANT GAIN (5),RHOMBIC (6),VERTICAL (7) AND
  19233. --  HORIZONTAL HALF WAVE DIPOLE (8) ANTENNA TYPES.
  19234.          For I in 1..NUMXMT Loop
  19235.             If IATXMT(I) > 4 and IATXMT(I) < 9 Then
  19236.                Skip_Line;
  19237.                If IATXMT(I) = 5 Then
  19238.                   Get(ANTGNX(I), 15);
  19239.                Elsif IATXMT(I) = 6 Then
  19240.                   Get(ANTTAX(I), 15);
  19241.                   Get(ANTHTX(I), 15);
  19242.                   Get(ANTLNX(I), 15);
  19243.                Elsif IATXMT(I) = 7 Then
  19244.                   Get(ANTLNX(I), 15);
  19245.                Elsif IATXMT(I) = 8 Then
  19246.                   Get(ANTHTX(I), 15);
  19247.                End If;
  19248.             End If;
  19249.          End Loop;
  19250. --
  19251.          For I in 1..NUMXMT Loop
  19252.             If I rem 10 = 1 Then
  19253.                Skip_Line;
  19254.                Get(NXPF(I), 5);
  19255.             Else
  19256.                Get(NXPF(I), 7);
  19257.             End If;
  19258.          End Loop;
  19259.          For I in 1..NUMXMT Loop
  19260.             If NXPF(I) > 0 Then
  19261.                For J in 1..2*NXPF(I) Loop
  19262.                   If J rem 5 = 1 Then
  19263.                      Skip_Line;
  19264.                   End If;
  19265.                   Get(PFTIMX, 15);  --PFVALX is actually every other Get.
  19266.                End Loop;
  19267.             End If;
  19268.          End Loop; 
  19269.          For I in 1..NUMXMT Loop
  19270.             If I rem 5 = 1 Then
  19271.                Skip_Line;
  19272.             End If;
  19273.             Get(TTRXMT, 15);
  19274.          End Loop;
  19275.       Else
  19276. --
  19277. -- INPUT FILE IS IN "NEW" FORMAT, EACH TRANSMITTER HAS ALPHA NAME AND ALL
  19278. -- DATA TOGETHER
  19279. --
  19280.          For I in 1..NUMXMT Loop
  19281.             Skip_Line;
  19282.             Get(NAME);
  19283.             ALPHA_TO_INTEGERIZED_ALPHA(NAME,NAMXMT(I));
  19284.             Get(DUMMY);      -- Skip 4 spaces.
  19285.             Get(ITYPE, 5);
  19286.             begin
  19287.                ITPXMT(I) := BAND_TYPES'VAL(ITYPE+1);
  19288.             exception
  19289.                When CONSTRAINT_ERROR =>
  19290.                   Put("ERROR in REDXMT...unknown transmitter type.");
  19291.             End;
  19292.             Get(IATXMT(I), 5);
  19293.             Get(NXPF(I), 5);
  19294.             Skip_Line;
  19295.             Get(BWXMT(I), 15);
  19296.             Get(TRPXMT(I), 15);
  19297.             Get(FREXMT(I), 15);
  19298.             Get(DRTXMT, 15);
  19299.             Get(CHUXMT, 15);
  19300.             If IATXMT(I) >= 5 and IATXMT(I) <= 8 Then
  19301.                Skip_Line;
  19302.                Get(ANTGNX(I), 15);
  19303.                Get(ANTTAX(I), 15);
  19304.                Get(ANTHTX(I), 15);
  19305.                Get(ANTLNX(I), 15);
  19306.             End If;
  19307.             If NXPF(I) > 0 Then
  19308.                For J in 1..2*NXPF(I) Loop
  19309.                   If J rem 5 = 1 Then
  19310.                      Skip_Line;
  19311.                   End If;
  19312.                   Get(PFTIMX, 15);  --PFVALX is actually every other Get.
  19313.                End Loop;
  19314.             End If;
  19315.          End Loop;
  19316. --
  19317.       End If;
  19318.       Return;
  19319. --
  19320.       End REDXMT;
  19321. --
  19322.       Procedure READ_HANDLER is
  19323. --
  19324. --#PURPOSE: READ_HANDLER is the driver for the file reading routines.
  19325. --
  19326. --#AUTHOR:  J. Conrad
  19327. --
  19328. --#TYPE:    Input
  19329. --
  19330. --#PARAMETER DESCRIPTIONS:
  19331. --          'NONE'
  19332. --
  19333. --#CALLED BY:
  19334. --          MAIN
  19335. --
  19336. --#CALLS TO:
  19337. --          REDNOD
  19338. --          REDREC
  19339. --          REDXMT
  19340. --
  19341. --#TECHNICAL DESCRIPTION:
  19342. --          READ_HANDLER drives the various routines which read the
  19343. --          data stored in the file as specified by ARGUMENT_BUFFER.
  19344. --          The number of each entity read is output to the
  19345. --          operator after each individual read operation.
  19346. --
  19347. --
  19348.       Begin
  19349. --
  19350. --OPEN FILE.
  19351.       Open (IUNIT, in_file, ARGUMENT_BUFFER); 
  19352. --
  19353. --SET THE INPUT DEVICE.
  19354.       SET_INPUT(IUNIT);
  19355. --
  19356. --READ ALL DATA.
  19357.       Get(TITLE);
  19358.       Skip_line;
  19359.       New_line;
  19360.       Put(TITLE);
  19361.       DATABASE_HAS_BEEN_MODIFIED := FALSE;
  19362.       REDNOD;
  19363.       New_line;
  19364.       Put(NUMNOD);
  19365.       Put(" nodes read.");
  19366. --
  19367. --SKIP THE NEXT LINE OF INPUT.
  19368.       Skip_line;
  19369.       Skip_line;
  19370.       REDREC;
  19371.       New_line;
  19372.       Put(NUMREC);
  19373.       Put(" receiver classes read.");
  19374. --
  19375. --SKIP THE NEXT LINE OF INPUT.
  19376.       Skip_line;
  19377.       Skip_line;
  19378.       REDXMT;
  19379.       New_line;
  19380.       Put(NUMXMT);
  19381.       Put(" transmitter classes read.");
  19382.       New_line;
  19383. --
  19384. --CLOSE READ FILE.
  19385.       Close(IUNIT);
  19386. --
  19387. --RESET INPUT DEVICE.
  19388.       SET_INPUT(STANDARD_INPUT);
  19389. --
  19390.       Return;
  19391. --
  19392.       Exception
  19393.          When Status_Error =>
  19394.             New_line;
  19395.             Put("File handling error in READ_HANDLER.");
  19396.             Return;
  19397.          When Others =>
  19398.             New_line;
  19399.             Put("File handling error in READ_HANDLER.");
  19400.             Return;
  19401. --
  19402.       End READ_HANDLER;
  19403. --
  19404. --
  19405.       Procedure WRTNOD is
  19406. --
  19407. --#PURPOSE: WRTNOD writes the node data to the disk file.
  19408. --
  19409. --#AUTHOR:  J. Conrad
  19410. --
  19411. --#TYPE:    Input
  19412. --
  19413. --#PARAMETER DESCRIPTIONS:
  19414. --IN        'NONE'
  19415. --
  19416. --#CALLED BY:
  19417. --          WRITE_HANDLER
  19418. --
  19419. --#CALLS TO:
  19420. --          'NONE'
  19421. --
  19422. --#TECHNICAL DESCRIPTION:
  19423. --          WRTNOD writes the node data to the disk file using a
  19424. --          series of Put statements.
  19425. --
  19426. --          Note that NKSND, NPSND are only written to be compatible 
  19427. --          with SIMSTAR/StratSim/StratLink data bases.  
  19428. --
  19429.       I,J,K: Integer;
  19430.       IFORM: Integer := 1;
  19431.       INODE, NKSND, NPSND, ITYPE: Integer := 0;
  19432.       NAME1, NAME2: string(1..6);
  19433.       INDEX: I_ARRAY(1..NUMNOD);
  19434. --
  19435.      Begin
  19436. --
  19437. --BEGIN THE OUTPUT OPERATION.
  19438.       New_line;
  19439.       Put(NUMNOD, 5);
  19440.       Put(IFORM, 5);
  19441.       If NUMNOD <= 0 Then
  19442.          Return;
  19443.       End If;
  19444. --
  19445.       ENSORT (NUMNOD, NAMNOD, INDEX);
  19446.       For I in 1..NUMNOD Loop
  19447.          INODE := INDEX(I);
  19448.          INTEGER_TO_ALPHA (NAMNOD(INODE), NAME1);
  19449.          New_line;
  19450.          Put(NAME1);
  19451.          ITYPE := NODE_TYPES'POS(ITYSND(INODE));
  19452.          New_line;
  19453.          Put(ITYPE, 5);
  19454.          Put(NLSND(INODE), 7);
  19455.          Put(NKSND, 7);
  19456.          Put(NRSND(INODE), 7);
  19457.          Put(NXSND(INODE), 7);
  19458.          Put(NPSND, 7);
  19459.          If ITYPE = 3 Then
  19460.             New_line;
  19461.             For J in 1..5 Loop
  19462.                Put(EPHSND(J,INODE),3,7,3);
  19463.             End Loop;
  19464.             New_line;
  19465.             Put(EPHSND(6,INODE),3,7,3);
  19466.          End If;
  19467.          If NLSND(INODE) > 0 Then
  19468.             For K in 1..NLSND(INODE) Loop
  19469.                For J in 1..4 Loop
  19470.                   If (4*(K-1)+J) rem 5 = 1 Then
  19471.                      New_Line;
  19472.                   End If; 
  19473.                   Put(XPSSND(J,K,INODE),3,7,3);
  19474.                End Loop;
  19475.             End Loop;
  19476.          End If;
  19477.          If NRSND(INODE) > 0 Then
  19478.             For K in 1..NRSND(INODE) Loop
  19479.                INTEGER_TO_ALPHA(IRCSND(1,K,INODE), NAME1);
  19480.                INTEGER_TO_ALPHA(IRCSND(2,K,INODE), NAME2);
  19481.                New_Line;
  19482.                Put(NAME1);
  19483.                Put("    "); -- Skip four spaces;
  19484.                Put(NAME2);
  19485.             End Loop;
  19486.          End If;
  19487.          If NXSND(INODE) > 0 Then
  19488.             For K in 1..NXSND(INODE) Loop
  19489.                INTEGER_TO_ALPHA(IXTSND(1,K,INODE), NAME1);
  19490.                INTEGER_TO_ALPHA(IXTSND(2,K,INODE), NAME2);
  19491.                New_Line;
  19492.                Put(NAME1);
  19493.                Put("    "); -- Skip four spaces;
  19494.                Put(NAME2);
  19495.             End Loop;
  19496.          End If;
  19497. --
  19498.       End Loop;
  19499. --
  19500.       Return;
  19501. --    
  19502.       End WRTNOD;
  19503. --
  19504. --
  19505.       Procedure WRTREC is
  19506. --
  19507. --#PURPOSE: WRTREC writes the receiver class data to the disk file.
  19508. --
  19509. --#AUTHOR:  J. Conrad
  19510. --
  19511. --#TYPE:    Input
  19512. --
  19513. --#PARAMETER DESCRIPTIONS:
  19514. --IN        'NONE'
  19515. --
  19516. --#CALLED BY:
  19517. --          WRITE_HANDLER
  19518. --
  19519. --#CALLS TO:
  19520. --          'NONE'
  19521. --
  19522. --#TECHNICAL DESCRIPTION:
  19523. --          WRTREC writes the receiver class data to the disk file
  19524. --          using a series of Put statements.
  19525. --
  19526. --          Note that MODREC, SLBREC, BEMREC, NPHREC, ICRREC, FNDREC,
  19527. --          KBFREC, LRCREC, NSLREC and NRPF are only written to be 
  19528. --          compatible with SIMSTAR/StratSim/StratLink data bases.  
  19529. --
  19530.       NAME: string(1..6);
  19531.       I, J, ITYPE: Integer;
  19532.       IFORM: Integer := 1;
  19533.       MODREC, NPHREC, ICRREC, KBFREC, LRCREC, NSLREC, NRPF: Integer := 0;
  19534.       SLBREC, BEMREC, FMDREC: Float := 0.0;
  19535.       INDEX:I_ARRAY(1..NUMREC);
  19536. --
  19537.       Begin
  19538. --
  19539. --BEGIN THE OUTPUT OPERATION.
  19540.       New_Line;
  19541.       Put(NUMREC, 5);
  19542.       Put(IFORM, 5);
  19543.       If NUMREC <= 0 Then
  19544.          Return;
  19545.       End If;
  19546. --
  19547.       ENSORT (NUMREC, NAMREC, INDEX);
  19548.       For I in 1..NUMREC Loop
  19549.          J := INDEX(I);
  19550.          INTEGER_TO_ALPHA(NAMREC(J), NAME);
  19551.          New_Line;
  19552.          Put(NAME);
  19553.          Put("    ");      -- Skip 4 spaces.
  19554.          ITYPE := BAND_TYPES'POS(ITPREC(J))-1;
  19555.          Put(ITYPE, 5);
  19556.          Put(MODREC, 5);
  19557.          Put(IATREC(J), 5);
  19558.          Put(LRCREC, 5);
  19559.          Put(NSLREC, 5);
  19560.          Put(FREREC(J),3,7,3);
  19561.          Put(GTREC(J),3,7,3);
  19562.          Put(BWREC(J),3,7,3);
  19563.          New_line;
  19564.          Put(NPHREC, 5);
  19565.          Put(ICRREC, 5);
  19566.          Put(KBFREC, 5);
  19567.          Put(NRPF, 5);
  19568.          Put(FMDREC,3,7,3);
  19569.          Put(SLBREC,3,7,3);
  19570.          Put(BEMREC,3,7,3);
  19571.          Put(RLLREC(J),3,7,3);
  19572.          If IATREC(J) >= 5 and IATREC(J) <= 8 Then
  19573.             New_Line;
  19574.             Put(ANTGNR(J),3,7,3);
  19575.             Put(ANTTAR(J),3,7,3);
  19576.             Put(ANTHTR(J),3,7,3);
  19577.             Put(ANTLNR(J),3,7,3);
  19578.          End If;
  19579.          New_line;
  19580.       End Loop;
  19581. --
  19582.       Return;
  19583. --
  19584.       End WRTREC;
  19585. --
  19586. --
  19587.       Procedure WRTXMT is
  19588. --
  19589. --#PURPOSE: WRTXMT writes the transmitter class data to the disk file.
  19590. --
  19591. --#AUTHOR:  J. Conrad
  19592. --
  19593. --#TYPE:    Input
  19594. --
  19595. --#PARAMETER DESCRIPTIONS:
  19596. --IN        'NONE'
  19597. --
  19598. --#CALLED BY:
  19599. --          WRITE_HANDLER
  19600. --
  19601. --#CALLS TO:
  19602. --          ENSORT
  19603. --          INTEGER_TO_ALPHA
  19604. --
  19605. --#TECHNICAL DESCRIPTION:
  19606. --          WRTXMT writes the transmitter class data to the disk file
  19607. --          using a series of Put statements.
  19608. --
  19609. --          Note that DRTXMT, CHUXMT and NXPF are only written to 
  19610. --          be compatible with SIMSTAR/StratSim/StratLink data bases.  
  19611. --
  19612.       NAME: string(1..6);
  19613.       I, J: Integer;
  19614.       IFORM: Integer := 1;
  19615.       ITYPE: Integer;
  19616.       DRTXMT, CHUXMT, TTRXMT: Float := 0.0;
  19617.       NXPF: Integer := 0;
  19618.       INDEX: I_ARRAY(1..NUMXMT);
  19619. --
  19620.       Begin
  19621. --
  19622. --BEGIN THE OUTPUT OPERATION.
  19623.       New_Line;
  19624.       Put(NUMXMT, 5);
  19625.       Put(IFORM, 5);
  19626.       If NUMXMT <= 0 Then
  19627.          Return;
  19628.       End If;
  19629. --
  19630.       ENSORT (NUMXMT, NAMXMT, INDEX);
  19631.       For I in 1..NUMXMT Loop
  19632.          J := INDEX(I);
  19633.          INTEGER_TO_ALPHA(NAMXMT(J), NAME);
  19634.          New_Line;
  19635.          Put(NAME);
  19636.          Put("    ");      -- Skip 4 spaces.
  19637.          ITYPE := BAND_TYPES'POS(ITPXMT(J))-1;
  19638.          Put(ITYPE, 5);
  19639.          Put(IATXMT(J), 5);
  19640.          Put(NXPF, 5);
  19641.          New_line;
  19642.          Put(BWXMT(J),3,7,3);
  19643.          Put(TRPXMT(J),3,7,3);
  19644.          Put(FREXMT(J),3,7,3);
  19645.          Put(DRTXMT,3,7,3);
  19646.          Put(CHUXMT,3,7,3);
  19647.          If IATXMT(J) >= 5 and IATXMT(J) <= 8 Then
  19648.             New_Line;
  19649.             Put(ANTGNX(J),3,7,3);
  19650.             Put(ANTTAX(J),3,7,3);
  19651.             Put(ANTHTX(J),3,7,3);
  19652.             Put(ANTLNX(J),3,7,3);
  19653.          End If;
  19654.       End Loop;
  19655. --
  19656.       Return;
  19657. --
  19658.       End WRTXMT;
  19659. --
  19660. --
  19661.       Procedure WRITE_HANDLER is
  19662. --
  19663. --#PURPOSE: WRITE_HANDLER is the driver for the file writing routines.
  19664. --
  19665. --#AUTHOR:  J. Conrad
  19666. --
  19667. --#TYPE:    Input
  19668. --
  19669. --#PARAMETER DESCRIPTIONS:
  19670. --          'NONE'
  19671. --
  19672. --#CALLED BY:
  19673. --          MAIN
  19674. --
  19675. --#CALLS TO:
  19676. --          WRTNOD
  19677. --          WRTREC
  19678. --          WRTXMT
  19679. --
  19680. --#TECHNICAL DESCRIPTION:
  19681. --          WRITE_HANDLER drives the various routines which write the
  19682. --          data stored in the file as specified by ARGUMENT_BUFFER.
  19683. --
  19684.       Begin
  19685. --
  19686. --OPEN FILE.
  19687.       CREATE(IUNIT, out_file, ARGUMENT_BUFFER(1..MAX)); 
  19688. --
  19689. --
  19690. --SET THE OUTPUT DEVICE.
  19691.       SET_OUTPUT(IUNIT);
  19692. --
  19693. --WRITE ALL DATA.
  19694.       Put(TITLE);
  19695.       DATA_HAS_NOT_YET_BEEN_WRITTEN := FALSE;
  19696.       WRTNOD;
  19697.       New_line;
  19698.       Put("RECEIVER CLASS DATA");
  19699.       WRTREC;
  19700.       New_line;
  19701.       Put("TRANSMITTER CLASS DATA");
  19702.       WRTXMT;
  19703. --
  19704. --RESET OUTPUT DEVICE.
  19705.       SET_OUTPUT(STANDARD_OUTPUT);
  19706. --
  19707. --CLOSE FILE.
  19708.       Close(IUNIT);
  19709. --
  19710.       Return;
  19711. --
  19712.       Exception
  19713.          When Status_Error =>
  19714.             New_line;
  19715.             Put("File handling error in WRITE_HANDLER.");
  19716.             Return;
  19717.          When Others =>
  19718.             New_line;
  19719.             Put("File handling error in WRITE_HANDLER.");
  19720.             Return;
  19721. --
  19722.       End WRITE_HANDLER;
  19723. --
  19724. --
  19725. End IOANDFILE;
  19726.        
  19727. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  19728. --PROPLINK
  19729. --::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  19730. With Text_io, system; Use Text_io, Float_io, Integer_io;
  19731. With Types; Use Types;
  19732. With Constants; Use Constants;
  19733. With Constant2; Use Constant2;
  19734. With Constant3; Use Constant3;
  19735. With Propagation_Constants; Use Propagation_constants;
  19736. With Helps; use Helps;
  19737. With Entityuti; Use Entityuti;
  19738. With Executive; Use Executive;
  19739. With Nodes; Use Nodes;
  19740. With Receivers; Use Receivers;
  19741. With transmit; Use Transmit;
  19742. With RFUTIL; use RFUTIL;
  19743. With NODELOC;
  19744. With IOandFILE;
  19745. With ELF_PROPAGATION;
  19746. With VLF_PROPAGATION;
  19747. With LF_PROPAGATION;
  19748. With MF_HF_PROPAGATION;
  19749. With VHF_UHF_SHF_EHF_PROPAGATION;
  19750. With Noise;
  19751. With Debugger2; Use Debugger2;
  19752. Procedure PROPLINK is
  19753. --
  19754. pragma SOURCE_INFO (on);
  19755. --
  19756. Noise_file: file_type;
  19757. type STATE is (GOOD,BAD);
  19758. OPERATION: STATE:=GOOD;
  19759. --
  19760.       Procedure PRINT_HANDLER is
  19761. --
  19762. --PURPOSE: PRTHND drives the master print of all data.
  19763. --
  19764. --AUTHOR:  J. Conrad
  19765. --
  19766. --TYPE:    Output
  19767. --
  19768. --PARAMETER DESCRIPTIONS:
  19769. --         'NONE'
  19770. --
  19771. --CALLED BY:
  19772. --         MAIN
  19773. --
  19774. --CALLS TO:
  19775. --         NODE_HANDLER
  19776. --         RECEIVER_HANDLER
  19777. --         TRANSMITTER_HANDLER
  19778. --
  19779. --TECHNICAL DESCRIPTION:
  19780. --         PRINT_HANDLER sets up and calls all the individual entity
  19781. --         handlers so that all data currently held are printed
  19782. --         on the selected output device.
  19783. --
  19784.       Begin
  19785.       Pragma Source_info(on);
  19786. --
  19787. --ZERO THE ARGUMENT_BUFFER SO ALL ELEMENTS WILL BE PRINTED.
  19788.       For I in ARGUMENT_BUFFER'RANGE Loop
  19789.          ARGUMENT_BUFFER(I) := ' ';
  19790.       End Loop;
  19791. --
  19792. --CALL ALL THE INDIVIDUAL ENTITY HANDLERS.
  19793.       NODES.NODE_HANDLER;
  19794.       RECEIVERS.RECEIVER_HANDLER;
  19795.       TRANSMIT.TRANSMITTER_HANDLER;
  19796. --
  19797.       Return;
  19798. --
  19799.       End PRINT_HANDLER;
  19800. --
  19801.       Procedure CHECK_FOR_MISSING_ENTITYS is
  19802. --    
  19803. --PURPOSE: This procedure checks the node array
  19804. --         for any receiver and transmitter classes that have not 
  19805. --         been added.
  19806. --
  19807. --AUTHOR:  B. Perry
  19808. --
  19809. --CALLED BY: MAIN
  19810. --
  19811. --CALLS TO : 
  19812. --           INTEGER_TO_ALPHA
  19813. --           RECEIVER_ADD
  19814. --           TRANSMITTER_ADD
  19815. --
  19816.        KNAME: string(1..6);
  19817.        K, IFLG, IERR: integer;
  19818.        begin
  19819. --
  19820. --CHECK_FOR_UNDEFINED_RECEIVERS
  19821. --
  19822.       If NUMREC >= 1 Then 
  19823.          For K in 1..NUMREC Loop
  19824.             If ITPREC (K) = UNDEFINED Then
  19825.                Loop
  19826.                   INTEGER_TO_ALPHA (NAMREC(K), KNAME);
  19827.                   New_line;
  19828.                   Put("Receiver class ");
  19829.                   Put(KNAME);
  19830.                   Put(" must be added.");
  19831.                   ITPREC(K) := ELF;
  19832.                   IATREC(K) := 0;
  19833.                   FREREC(K) := 3.0;
  19834.                   GTREC(K)  := -30.0;
  19835.                   BWREC(K)  := 1.0;
  19836.                   RLLREC(K) := 0.0;
  19837.                   ANTGNR(K) := 0.0;
  19838.                   ANTHTR(K) := 0.0;
  19839.                   ANTLNR(K) := 0.0;
  19840.                   ANTTAR(K) := 0.0;
  19841.                   RECEIVER_ADD (K, IFLG, IERR);
  19842.                   Exit When IERR = 0;
  19843.                End Loop;
  19844.             End If;
  19845.          End Loop;
  19846.       End If;
  19847. --
  19848. --CHECK FOR UNDEFINED TRANSMITTERS.
  19849. --
  19850.       If NUMXMT >= 1 Then
  19851.          For K in 1..NUMXMT Loop
  19852.             If ITPXMT(K) = UNDEFINED Then
  19853.                Loop
  19854.                   INTEGER_TO_ALPHA (NAMXMT(K), KNAME);
  19855.                   New_line;
  19856.                   Put("Transmitter class ");
  19857.                   Put(KNAME);
  19858.                   Put(" must be added.");
  19859.                   ITPXMT(K) := ELF;
  19860.                   BWXMT (K) := 1.0;
  19861.                   TRPXMT(K) := 0.0;
  19862.                   FREXMT(K) := 3.0;
  19863.                   IATXMT(K) := 0;
  19864.                   ANTGNX(K) := 0.0;
  19865.                   ANTHTX(K) := 0.0;
  19866.                   ANTLNX(K) := 0.0;
  19867.                   ANTTAX(K) := 0.0;
  19868.                   TRANSMITTER_ADD (K, IFLG, IERR);
  19869.                   Exit When IERR = 0;
  19870.                End Loop;
  19871.             End If;
  19872.          End Loop;
  19873.       End If;
  19874. --
  19875.       Return;
  19876. --
  19877.       End CHECK_FOR_MISSING_ENTITYS;
  19878.  
  19879.       Procedure RF_PROPAGATION_HANDLER is
  19880. --
  19881. --#PURPOSE: RF_PROPAGATION_HANDLER is the RF propagation prediction driver.
  19882. --
  19883. --#AUTHOR:  J. Conrad
  19884. --
  19885. --#TYPE:    Driver routine.
  19886. --
  19887. --#PARAMETER DESCRIPTIONS:
  19888. --
  19889. --          'NONE'
  19890. --
  19891. --#CALLED BY:
  19892. --          MAIN
  19893. --
  19894. --#CALLS TO:
  19895. --          ADJBW
  19896. --          ELF_HANDLER
  19897. --          INTEGER_TO_ALPHA
  19898. --          LF_HANDLER
  19899. --          LOCGRB
  19900. --          LOCUPD
  19901. --          LOS
  19902. --          MF_HF_HANDLER
  19903. --          NOISE_HANDLER
  19904. --          VHF_UHF_SHF_EHF_HANDLER
  19905. --          VLF_HANDLER
  19906. --
  19907. --
  19908. --#TECHNICAL DESCRIPTION:
  19909. --          RF_PROPAGATION_HANDLER loops over all transmitters at each node 
  19910. --          and matches the frequency with each receiver at each node.
  19911. --          RF_PROPAGATION_HANDLER then determines the link frequency
  19912. --          type and calls SIGLNK and NOISE_HANDLER to obtain the XMTR-RECVR
  19913. --          link signal strength and noise level.
  19914. --
  19915.       NAME1, NAME2: string(1..6);
  19916.       SENDER, RECEIVER, IXMT, IREC, I: integer;
  19917. --
  19918.       Begin
  19919. --
  19920.       If NUMNOD < 1 Then
  19921.          Return;
  19922.       End If;
  19923.       TIMSEC := CURRENT_TIME*60.0;
  19924. --
  19925. --LOOP OVER ALL NODES, TRANSMITTERS & RECEIVERS.
  19926.       For SENDER in 1..NUMNOD Loop
  19927.          If NXSND(SENDER) >= 1 Then
  19928.             NODELOC.LOCUPD (SENDER, TLAT, TLON, TALT);
  19929.             For IX in 1..NXSND(SENDER) Loop
  19930.                For I in 1..NUMXMT Loop
  19931.                   If IXTSND(2, IX, SENDER) = NAMXMT(I) then
  19932.                      IXMT := I;
  19933.                      Exit;
  19934.                   End if;
  19935.                End loop;
  19936.                If FREXMT(IXMT) >= 3.0 and ITPXMT(IXMT) /= HARD_WIRED Then 
  19937.                   TERP := TRPXMT(IXMT);
  19938.                   FREQ := FREXMT(IXMT);
  19939.                   FREQKC := FREQ*0.001;
  19940.                   FREQMC := FREQKC*0.001;
  19941.                   IATYPT := IATXMT(IXMT);
  19942.                   TAX := ANTTAX(IXMT);
  19943.                   GNX := ANTGNX(IXMT);
  19944.                   HTX := ANTHTX(IXMT);
  19945.                   LNX := ANTLNX(IXMT);
  19946.                   ENTITYUTI.INTEGER_TO_ALPHA (IXTSND(1,IX,SENDER), NAME1);
  19947.                   ENTITYUTI.INTEGER_TO_ALPHA (IXTSND(2,IX,SENDER), NAME2);
  19948.                   SET_OUTPUT(STANDARD_OUTPUT);
  19949.                   For I in 1..2 Loop
  19950.                      If I = 2 Then
  19951.                         SET_OUTPUT(PRINTER_OUTPUT_FILE);
  19952.                      End If;
  19953.                      New_Line;
  19954.                      Put("Transmitter ");
  19955.                      Put(NAME1);
  19956.                      New_line;
  19957.                      Put("Class       ");
  19958.                      Put(NAME2);
  19959.                      Put("   at ");
  19960.                      Put(TLAT,3,2,0);
  19961.                      Put(" deg. N., ");
  19962.                      Put(TLON,4,2,0);
  19963.                      Put(" deg. E., ");
  19964.                      Put(TALT,7,0,0);
  19965.                      Put(" km. alt.");
  19966.                      If I = 2 Then
  19967.                         SET_OUTPUT(STANDARD_OUTPUT);
  19968.                      End If;
  19969.                   End Loop;
  19970. --
  19971.                   For RECEIVER in 1..NUMNOD Loop
  19972.                      If NRSND(RECEIVER) >= 1 Then
  19973.                         NODELOC.LOCUPD (RECEIVER, RLAT, RLON, RALT);
  19974.                         For IR in 1..NRSND(RECEIVER) Loop
  19975.                            For I in 1..NUMREC Loop
  19976.                               If IRCSND(2, IR, RECEIVER) = NAMREC(I) then
  19977.                                  IREC := I;
  19978.                                  Exit;
  19979.                               End if;
  19980.                            End loop;
  19981.                            NLTYP := ITPREC(IREC);
  19982.                            BW := BWREC(IREC);
  19983.                            GOT := GTREC(IREC);
  19984.                            RLL := RLLREC(IREC);
  19985.                            IATYPR := IATREC(IREC);
  19986.                            TAR := ANTTAR(IREC);
  19987.                            GNR := ANTGNR(IREC);
  19988.                            HTR := ANTHTR(IREC);
  19989.                            LNR := ANTLNR(IREC);
  19990.                            If FREREC(IREC) >= 3.0 and 
  19991.                               ITPREC(IREC) /= HARD_WIRED and
  19992.                               ADJBW (FREQ, BW, FREREC(IREC), BW) > 0.0 Then
  19993.                               ENTITYUTI.INTEGER_TO_ALPHA (IRCSND(1,IR,
  19994.                                            RECEIVER), NAME1);
  19995.                               ENTITYUTI.INTEGER_TO_ALPHA (IRCSND(2,IR,
  19996.                                            RECEIVER), NAME2);
  19997.                               For I in 1..2 Loop
  19998.                                  If I = 2 Then
  19999.                                     SET_OUTPUT(PRINTER_OUTPUT_FILE);
  20000.                                  End If;
  20001.                                  New_Line;
  20002.                                  Put("     Receiver ");
  20003.                                  Put(NAME1);
  20004.                                  New_line;
  20005.                                  Put("     Class    ");
  20006.                                  Put(NAME2);
  20007.                                  Put("   at ");
  20008.                                  Put(RLAT,3,2,0);
  20009.                                  Put(" deg. N., ");
  20010.                                  Put(RLON,4,2,0);
  20011.                                  Put(" deg. E., ");
  20012.                                  Put(RALT,7,0,0);
  20013.                                  Put(" km. alt.");
  20014.                                  If I = 2 Then
  20015.                                     SET_OUTPUT(STANDARD_OUTPUT);
  20016.                                  End If;
  20017.                               End Loop;
  20018. --
  20019. --IF LINK IS VHF OR ABOVE, SEE IF LINE-OF-SIGHT EXISTS AND IF NOT,
  20020. --  RETURN A SIGNAL OF -99999.9.
  20021.                               SIGNAL := -99999.9;
  20022.                               SIGNOS := -99999.9;
  20023.                               If (FREQ >= 3.0E7 and
  20024.                                   LOS (TLAT*RADIANS_PER_DEGREE,  
  20025.                                        TLON*RADIANS_PER_DEGREE,  TALT,
  20026.                                        RLAT*RADIANS_PER_DEGREE, 
  20027.                                        RLON*RADIANS_PER_DEGREE, RALT)) or
  20028.                                       (FREQ < 3.0E7) Then  
  20029. --
  20030. --COMPUTE THE BEARING AND RANGE
  20031.                                  NODELOC.LOCGRB (TLAT, TLON, RLAT, RLON, 
  20032.                                          BRNG1, BRNG2, DPATH);
  20033. --
  20034. --USE THE APPROPRIATE RF PREDICTION MODULE
  20035.                                  Case NLTYP is
  20036.                                     when ELF =>ELF_PROPAGATION.ELF_HANDLER;
  20037.                                     when VLF =>VLF_PROPAGATION.VLF_HANDLER;
  20038.                                     when LF  =>LF_PROPAGATION.LF_HANDLER;
  20039.                                     when MF|HF =>
  20040.                                        MF_HF_PROPAGATION.MF_HF_HANDLER;
  20041.                                     when VHF|UHF|SHF|EHF =>
  20042.                          VHF_UHF_SHF_EHF_PROPAGATION.VHF_UHF_SHF_EHF_HANDLER;
  20043.                                     when others => null;
  20044.                                  End Case;
  20045. --
  20046. --COMPUTE THE NOISE LEVEL
  20047.                                  NOISE.NOISE_HANDLER;
  20048. --
  20049.                               End If;
  20050.                               For I in 1..2 Loop
  20051.                                  If I = 2 Then
  20052.                                     SET_OUTPUT(PRINTER_OUTPUT_FILE);
  20053.                                  End If;
  20054.                                  New_Line;
  20055.                                  Put("           Signal Strength = ");
  20056.                                  Put(SIGNAL,3,7,3);
  20057.                                  If FREQ <= 3.0E5 Then
  20058.                                     Put(" dB/uV/m");
  20059.                                  Else
  20060.                                     Put(" dBW");
  20061.                                  End If;
  20062.                                  New_Line;
  20063.                                  Put("           Noise Strength = ");
  20064.                                  Put(SIGNOS,3,7,3);
  20065.                                  If FREQ <= 3.0E5 Then
  20066.                                     Put(" dB/uV/m/Hz");
  20067.                                  Else
  20068.                                     Put(" dBW/HZ");
  20069.                                  End If;
  20070.                                  If I = 2 Then
  20071.                                     SET_OUTPUT(STANDARD_OUTPUT);
  20072.                                  End If;
  20073.                               End Loop;
  20074.                            End If;
  20075.                         End Loop;
  20076.                      End If;
  20077.                   End Loop;
  20078.                End If;
  20079.             End Loop;
  20080.          End If;
  20081.       End Loop;
  20082. --
  20083.       Return;
  20084. --
  20085.       End RF_PROPAGATION_HANDLER;
  20086. --
  20087. --
  20088. --
  20089. Begin -- MAIN PROGRAM.
  20090. --
  20091. --PURPOSE: PROPLINK is the main routine for the stand-alone RF
  20092. --         propagation prediction code -- PROP_LINK.
  20093. --
  20094. --AUTHOR:  J. Conrad, StratCom Systems, Inc.
  20095. --
  20096. --TYPE:   Executive
  20097. --
  20098. --PARAMETER DESCRIPTIONS:
  20099. --         'NONE'
  20100. --
  20101. --CALLED BY:
  20102. --         'NONE'
  20103. --
  20104. --CALLS TO:
  20105. --         COMMAND_LINE_PROCESSOR 
  20106. --         CHECK_FOR_MISSING_ENTITYS
  20107. --         INITIALIZE_NODES 
  20108. --         BLANK_CHECK
  20109. --         NODE_HANDLER
  20110. --         PARSE
  20111. --         PRINT_HANDLER
  20112. --         READ_HANDLER
  20113. --         RECEIVER_HANDLER 
  20114. --         RF_PROPAGATION_HANDLER
  20115. --         TRANSMITTER_HANDLER
  20116. --         WRITE_HANDLER
  20117. --
  20118. --TECHNICAL DESCRIPTION:
  20119. --
  20120. --  This is the main program for the stand-alone RF propagation
  20121. --  prediction code -- PROP_LINK.  This software is based on the
  20122. --  FORTRAN algorithms contained in SIMSTAR, the U.S. Air Force's
  20123. --  Dynamic Multi-Message Simulator.
  20124. --
  20125. --
  20126. --INITIALIZE NODE DATA.
  20127.       INITIALIZE_NODES;
  20128. --CLEAR SCREEN AND ANNOUNCE PROGRAM.
  20129.       For I in 1..12 loop
  20130.          New_line;
  20131.       end loop;
  20132.       Put("                                    PROP_LINK");
  20133.       New_line;New_line;New_line;
  20134.       Put("                       --- Ada RF Propagation Predictor ---"); 
  20135.       New_line;New_line;
  20136.       Put("                                   Version 1.0");
  20137.       New_line;New_line;New_line;
  20138.       Put("                                  Developed by:");
  20139.       New_line;New_line;
  20140.       Put("                             IWG Corp. (Bruce Perry)");
  20141.       New_line;New_line;
  20142.       Put("                    Under Government Contract N66001-85-C-0042");
  20143.       New_line;New_line;New_line;New_line;
  20144. --
  20145. --    INITIALIZE TITLE
  20146.    for I in 1..80 loop
  20147.       TITLE(I):=' ';
  20148.    end loop;
  20149. --
  20150. --    MAIN COMMAND LOOP
  20151.    loop
  20152. <<COMMANDER>>     
  20153.       COMMAND_LINE_PROCESSOR; 
  20154. --      Exception
  20155. --         when CONSTRAINT_ERROR =>
  20156. --            Goto COMMANDER;
  20157. --      End;
  20158. --
  20159.       Case CURRENT_COMMAND is
  20160. --
  20161.          When READ => IOANDFILE.READ_HANDLER;
  20162.          When WRITE =>IOANDFILE.WRITE_HANDLER;
  20163.          When PRINT => New_line;
  20164.             Put("Enter the filename of the printer output file: ");
  20165.             Get_line(FILE_NAME, MAX);
  20166.             Create(PRINTER_OUTPUT_FILE, out_file, FILE_NAME(1..MAX));
  20167.             Case CURRENT_ENTITY is
  20168.                When RECEIVER => RECEIVER_HANDLER;
  20169.                When TRANSMITTER => TRANSMITTER_HANDLER;
  20170.                When NODE => NODE_HANDLER;
  20171.                When others => PRINT_HANDLER;
  20172.             End Case;
  20173.             Close(PRINTER_OUTPUT_FILE);
  20174.          When STOP => If DATABASE_HAS_BEEN_MODIFIED and 
  20175.                          DATA_HAS_NOT_YET_BEEN_WRITTEN Then
  20176.                             New_line;
  20177.                             Put("WARNING...Data has been added/modified");
  20178.                             Put(" but not yet saved.");
  20179.                             DATA_HAS_NOT_YET_BEEN_WRITTEN := FALSE;
  20180.                             Goto COMMANDER;
  20181.                       End If;
  20182.                       exit; 
  20183.          When GO => New_line;
  20184.             Put("Enter the filename of the printer output file: ");
  20185.             Get_line(FILE_NAME, MAX);
  20186.             Create(PRINTER_OUTPUT_FILE, out_file, 
  20187.                    FILE_NAME(1..MAX));
  20188.             New_line;
  20189.             Put("Enter the GMT reference time as would be");
  20190.             Put(" specified on a 24 hour clock");
  20191.             New_line;
  20192.             Put("(e.g., 6:30 PM as 1830) or type ENTER key");
  20193.             Put(" to accept default value of: ");
  20194.             Put(INTEGER(REFERENCE_TIME));
  20195.             New_line;
  20196.             Get_LINE(ARGUMENT_BUFFER, MAX);
  20197.             If not BLANK_CHECK(ARGUMENT_BUFFER(1..MAX)) Then
  20198.                NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  20199.                PARSE (ARGUMENT_BUFFER(1..MAX));
  20200.                If NUMBER_OF_VARIABLES_TO_EXTRACT = 
  20201.                   NUMBER_OF_VARIABLES_EXTRACTED Then
  20202.                   REFERENCE_TIME:= XARRAY(1);
  20203.                End if;
  20204.             End If;
  20205.             New_line;
  20206.             Put("Enter the minutes since GMT reference time or");
  20207.             Put(" type ENTER key to accept the");
  20208.             New_line;
  20209.             Put(" default value of: ");
  20210.             Put(INTEGER(CURRENT_TIME));
  20211.             New_line;
  20212.             Get_line(ARGUMENT_BUFFER, MAX);
  20213.             If not BLANK_CHECK(ARGUMENT_BUFFER(1..MAX)) Then
  20214.                NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  20215.                PARSE (ARGUMENT_BUFFER(1..MAX));
  20216.                If NUMBER_OF_VARIABLES_TO_EXTRACT = 
  20217.                   NUMBER_OF_VARIABLES_EXTRACTED Then
  20218.                   CURRENT_TIME:= XARRAY(1);
  20219.                End if;
  20220.             End If;
  20221.             New_line;
  20222.             Put("Enter the month as a digit between 1 and 12");
  20223.             Put("(e.g., June = 6) or type ENTER");
  20224.             New_line;
  20225.             Put("to accept the default value of: ");
  20226.             Put(MONTH);
  20227.             New_line;
  20228.             Get_line(ARGUMENT_BUFFER,MAX);
  20229.             If not BLANK_CHECK(ARGUMENT_BUFFER(1..MAX)) Then
  20230.                NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  20231.                PARSE (ARGUMENT_BUFFER(1..MAX));
  20232.                If (NUMBER_OF_VARIABLES_TO_EXTRACT = 
  20233.                    NUMBER_OF_VARIABLES_EXTRACTED) and
  20234.                    (INTEGER(XARRAY(1)) >= 1) and (INTEGER(XARRAY(1)) <= 12) Then
  20235.                    MONTH:= INTEGER(XARRAY(1));
  20236.                End if;
  20237.             End If;
  20238.             NSEAS := (MONTH - 1) / 3;
  20239.             If NSEAS <= 0 Then
  20240.                NSEAS := 4;
  20241.             End If;
  20242.             Case NSEAS is
  20243.                 When 1 => FILE_NAME(1..10):="SPRING.DAT";
  20244.                 When 2 => FILE_NAME(1..10):="SUMMER.DAT";
  20245.                 When 3 => FILE_NAME(1..10):="FALL.DAT  ";
  20246.                 When 4 => FILE_NAME(1..10):="WINTER.DAT";
  20247.                 When others => Put("BAD MONTH");NEW_LINE; goto COMMANDER;
  20248.             End Case;
  20249.  
  20250.             begin
  20251.                Open (NOISE_FILE, IN_FILE, FILE_NAME);
  20252.                Close (NOISE_FILE);
  20253.             Exception
  20254.                when NAME_ERROR =>
  20255.                   New_line; 
  20256.                   Put("WARNING...The noise data file for this month");
  20257.                   Put_line(" (season) cannot be found.");
  20258.                   OPERATION := BAD;
  20259.             End;
  20260.             If OPERATION=BAD then 
  20261.                Goto COMMANDER; 
  20262.                OPERATION := GOOD;
  20263.             end if;
  20264.             New_line;
  20265.             Put("Enter the sunspot activity index (Wolf number)");
  20266.             Put_line(" or type the ENTER key to");
  20267.             Put(" accept the default value of: ");
  20268.             Put(AVERAGE_SUN_SPOT_NUMBER);
  20269.             New_line;
  20270.             Get_line(ARGUMENT_BUFFER,MAX);
  20271.             If not BLANK_CHECK(ARGUMENT_BUFFER(1..MAX)) Then
  20272.                NUMBER_OF_VARIABLES_TO_EXTRACT := 1;
  20273.                PARSE (ARGUMENT_BUFFER(1..MAX));
  20274.                If NUMBER_OF_VARIABLES_TO_EXTRACT = 
  20275.                   NUMBER_OF_VARIABLES_EXTRACTED Then
  20276.                   AVERAGE_SUN_SPOT_NUMBER := INTEGER(XARRAY(1));
  20277.                End if;
  20278.             End If;
  20279. --COMPUTE LINK SIGNAL AND NOISE LEVELS.
  20280.             New_line;
  20281.             Put("GMT = ");
  20282.             Put(INTEGER(REFERENCE_TIME),4);
  20283.             Put(", Minutes since GMT = ");
  20284.             Put(INTEGER(CURRENT_TIME),4);
  20285.             Put(", Month = ");
  20286.             Put(MONTH,2);
  20287.             Put(", Sun Spot Activity Index = ");
  20288.             Put(AVERAGE_SUN_SPOT_NUMBER,3);
  20289. --
  20290.             SET_OUTPUT(PRINTER_OUTPUT_FILE);
  20291.             New_line;
  20292.             Put("GMT = ");
  20293.             Put(INTEGER(REFERENCE_TIME),4);
  20294.             Put(", Minutes since GMT = ");
  20295.             Put(INTEGER(CURRENT_TIME),4);
  20296.             Put(", Month = ");
  20297.             Put(MONTH,2);
  20298.             Put(", Sun Spot Activity Index = ");
  20299.             Put(AVERAGE_SUN_SPOT_NUMBER,3);
  20300. --
  20301.             begin
  20302.                RF_PROPAGATION_HANDLER;
  20303.             exception
  20304.                when use_error => 
  20305.                   New_line;
  20306.                   put_line("Cannot write output file - check storage space");
  20307.                when others =>
  20308.                   set_output(STANDARD_OUTPUT);
  20309.                   New_line;
  20310.                   put_line("Error in RF propagation - check data");
  20311.             end;
  20312.             Close(PRINTER_OUTPUT_FILE);
  20313.             SET_OUTPUT(STANDARD_OUTPUT);
  20314. --
  20315.          When VIEW|ADD|DEL|MODIFY=> New_line;
  20316.             Case CURRENT_ENTITY is
  20317.                When RECEIVER => RECEIVER_HANDLER;
  20318.                When TRANSMITTER => TRANSMITTER_HANDLER;
  20319.                When NODE => NODE_HANDLER;
  20320.                   CHECK_FOR_MISSING_ENTITYS;
  20321.                When ENTITY_ERROR  => Null;
  20322.                When others => Null;
  20323.             End Case;
  20324.       End Case;
  20325. --
  20326.    End loop;
  20327.    Exception
  20328.       when use_error => 
  20329.          New_line;
  20330.          put_line("Cannot write output file - check storage space");
  20331.       when others => system.report_error;
  20332. End PROPLINK;
  20333.