/*
Subprogram TRUEWIND.C
Converted from IDL true wind computation code true_wind.pro.
Created: 12/17/96
Comments updated: 10/29/97
Developed by: Shawn R. Smith and Mark A. Bourassa
Programmed by: Mylene Remigio
Last updated: 9/30/2014
Direct questions to: wocemet@coaps.fsu.edu
UPDATE LOG:
9/30/2014 : Version 2 - Arturo Valery
If the true wind has speed and its coming from the north
then its direction should be 360deg. The problem was fixed
in which the programsâ€™s output showed 0deg instead of 360deg.
This routine will compute meteorological true winds (direction from
which wind is blowing, relative to true north; and speed relative to
the fixed earth).
INPUT VALUES:
num int Number of observations in input (crse, cspd, wdir,
wspd, hd) and output (adir, tdir, tspd) data
arrays.
ALL ARRAYS MUST BE OF EQUAL LENGTH.
sel int Sets option for diagnostic output. There are four
settings:
Option 4: Calculates true winds from input arrays
with no diagnostic output or warnings.
NOT RECOMMENDED.
Option 3: [DEFAULT] Diagnostic output lists the
array index and corresponding variables
that either violate the range checks or are
equal to the missing value. An additional
table lists the number of observation times
with no missing values, some (but not all)
missing values, and all missing values; as
well as similar totals for the observation
times that fail the range checks.
Range checks identify negative input
values and verify directions to be between
0 and 360 degrees.
Option 2: In addition to the default diagnostics
(option 3), a table of all input and output
values for observation times with missing
data is provided.
Option 1: Full diagnostics -- In addition to the
diagnostics provided by option 2 and 3, a
complete data chart is output. The table
contains input and output values for all
observation times passed to truewind.
crse float array Course TOWARD WHICH the vessel is moving over the
ground. Referenced to true north and the fixed earth.
cspd float array Speed of vessel over the ground. Referenced
to the fixed earth.
hd float array Heading toward which bow of vessel is pointing.
Referenced to true north.
zlr float Zero line reference -- angle between bow and
zero line on anemometer. Direction is clockwise
from the bow. (Use bow=0 degrees as default
when reference not known.)
wdir float array Wind direction measured by anemometer,
referenced to the ship.
wspd float array Wind speed measured by anemometer,referenced to
the vessel's frame of reference.
wmis float array Five element array containing missing values for
crse, cspd, wdir, wspd, and hd. In the output, the missing
value for tdir is identical to the missing value
specified in wmis for wdir. Similarly, tspd uses
the missing value assigned to wmis for wspd.
*** WDIR MUST BE METEOROLOGICAL (DIRECTION FROM)! CRSE AND CSPD MUST BE
RELATIVE TO A FIXED EARTH! ***
OUTPUT VALUES:
tdir float array True wind direction - referenced to true north
and the fixed earth with a direction from which
the wind is blowing (meteorological).
tspd float array True wind speed - referenced to the fixed earth.
adir float array Apparent wind direction (direction measured by
wind vane, relative to true north). IS
REFERENCED TO TRUE NORTH & IS DIRECTION FROM
WHICH THE WIND IS BLOWING. Apparent wind
edirection is the sum of the ship relative wind
direction (measured by wind vane relative to the
bow), the ship's heading, and the zero-line
reference angle. NOTE: The apparent wind speed
has a magnitude equal to the wind speed measured
by the anemometer (wspd).
DIAGNOSTIC OUTPUT:
nw int Number of observation times for which tdir and
tspd were calculated (without missing values)
nwpm int Number of observation times with some values
(crse, cspd, wdir, wspd, hd) missing. tdir,
tspd set to missing value.
nwam int Number of observation times with all values
(crse, cspd, wdir, wspd, hd) missing. tdir,
tspd set to missing value.
nwf int Number of observation times where the program
fails -- at least one of the values (crse, cspd,
wdir, wspd, hd) is invalid
********************************************************************************
*/
#include
#include
#include
#include "truewind.h"
void truewind(int num, int sel, float crse[], float cspd[], float
wdir[], float zlr, float hd[], float adir[], float wspd[], float
wmis[5], float tdir[], float tspd[], int nw, int nwam, int nwpm,
int nwf)
{
/* Define variables. */
int calm_flag;
int i;
float x, y, mcrse, mwdir, mtdir, dtor;
/* Initialize values.*/
x = 0;
y = 0;
nw = 0;
nwam = 0;
nwpm = 0;
nwf = 0;
dtor = pi/180; /* degrees to radians conversion */
printf("\n");
/* Loop over 'num' values. */
for(i=0; i 360)) && (crse[i] != wmis[0]) ) ||
( (cspd[i] < 0) && (cspd[i] != wmis[1]) ) ||
( ((wdir[i] < 0) || (wdir[i] > 360)) && (wdir[i] != wmis[2]) ) ||
( (wspd[i] < 0) && (wspd[i] != wmis[3]) ) ||
( ((hd[i] < 0) || (hd[i] > 360)) && (hd[i] != wmis[4]) ) )
{
/* When some or all of input data fails range check, true winds are set
to missing. Step index for input value(s) being out of range */
nwf = nwf + 1;
tdir[i] = wmis[2];
tspd[i] = wmis[3];
if( (crse[i] != wmis[0]) && (cspd[i] != wmis[1]) &&
(wdir[i] != wmis[2]) && (wspd[i] != wmis[3]) &&
(hd[i] != wmis[4]) )
/* Step index for all input values being non-missing */
{
nw = nw + 1;
}
else
{
if( (crse[i] != wmis[0]) || (cspd[i] != wmis[1]) ||
(wdir[i] != wmis[2]) || (wspd[i] != wmis[3]) ||
(hd[i] != wmis[4]) )
/* Step index for part of input values being missing */
{
nwpm = nwpm + 1;
}
else
/* Step index for all input values being missing */
{
nwam = nwam + 1;
}
}
}
/* When course, ship speed, heading, wind direction, and wind speed
are all in range and non-missing, then compute true winds. */
else if( (crse[i] != wmis[0]) && (cspd[i] != wmis[1]) &&
(wdir[i] != wmis[2]) && (wspd[i] != wmis[3]) &&
(hd[i] != wmis[4]) )
{
nw = nw + 1;
/* convert from navigational coordinates to angles commonly used
in mathematics */
mcrse = 90.0 - crse[i];
/* keep the value between 0 and 360 degrees */
if( mcrse <= 0.0 ) mcrse = mcrse + 360.0;
/* check zlr for valid value. If not valid, set equal to zero.*/
if( (zlr < 0.0) || (zlr > 360.0) ) zlr = 0.0;
/* calculate apparent wind direction */
adir[i] = hd[i] + wdir[i] + zlr;
/* keep adir between 0 and 360 degrees */
while( adir[i] >= 360.0 ) adir[i] = adir[i] - 360.0;
/* convert from meteorological coordinates to angles commonly used
in mathematics */
mwdir = 270.0 - adir[i];
/* keep the value between 0 and 360 degrees */
if( mwdir <= 0.0 ) mwdir = mwdir + 360.0;
else if( mwdir > 360.0 ) mwdir = mwdir - 360.0;
/* determined the East-West vector component and the North-South
vector component of the true wind */
x = (wspd[i] * cos(mwdir * dtor)) + (cspd[i]
* cos(mcrse * dtor));
y = (wspd[i] * sin(mwdir * dtor)) + (cspd[i]
* sin(mcrse * dtor));
/* use the two vector components to calculate the true wind speed */
tspd[i] = sqrt((x * x) + (y * y));
calm_flag = 1;
/* determine the angle for the true wind */
if(fabs(x) > 0.00001) mtdir = (atan2(y,x)) / dtor;
else
{
if(fabs(y) > 0.00001) mtdir = 180.0 - (90.0 * y) / fabs(y);
else
/* the true wind speed is essentially zero: winds are calm
and direction is not well defined */
{
mtdir = 270.0;
calm_flag = 0;
}
}
/* convert from the common mathematical angle coordinate to the
meteorological wind direction */
tdir[i] = 270.0 - mtdir;
/* make sure that the true wind angle is between 0 and 360 degrees */
while(tdir[i] < 0.0) tdir[i] = (tdir[i] + 360.0) * calm_flag;
while(tdir[i] > 360.0) tdir[i] = (tdir[i] - 360.0) * calm_flag;
/* Ensure WMO convention for tdir=360 for win from North and tspd > 0 */
if (calm_flag == 1 && (tdir[i] < 0.0001))
tdir[i] = 360.0;
x = 0.0;
y = 0.0;
}
/* When course, ship speed, apparent direction, and wind speed
are all in range but part of these input values are missing,
then set true wind direction and speed to missing. */
else
{
if( (crse[i] != wmis[0]) || (cspd[i] != wmis[1]) ||
(wdir[i] != wmis[2]) || (wspd[i] != wmis[3]) ||
(hd[i] != wmis[4]) )
{
nwpm = nwpm + 1;
tdir[i] = wmis[2];
tspd[i] = wmis[3];
}
/* When course, ship speed, apparent direction, and wind speed
are all in range but all of these input values are missing,
then set true wind direction and speed to missing. */
else
{
nwam = nwam + 1;
tdir[i] = wmis[2];
tspd[i] = wmis[3];
}
}
}
/* Output option selection for truewind.c */
switch(sel)
{
case 1: full(num, crse, cspd, wdir, zlr, hd, adir, wspd, tdir, tspd);
missing_values(num, crse, cspd, wdir, hd, wspd, tdir,
tspd, wmis);
truerr(num, crse, cspd, hd, wdir, wspd, wmis, nw, nwpm,
nwam, nwf);
break;
case 2: missing_values(num, crse, cspd, wdir, hd, wspd, tdir,
tspd, wmis);
truerr(num, crse, cspd, hd, wdir, wspd, wmis, nw, nwpm,
nwam, nwf);
break;
case 3: truerr(num, crse, cspd, hd, wdir, wspd, wmis, nw, nwpm,
nwam, nwf);
break;
case 4: break;
default: printf("Selection not valid. Using selection #3 by default.\n");
truerr(num, crse, cspd, hd, wdir, wspd, wmis, nw, nwpm,
nwam, nwf);
}
}
/*********************************************************************/
/* OUTPUT PROCEDURES */
/*********************************************************************/
/* Procedure: FULL.C
Purpose: Produces a complete data table with all values.
Accessed only when selection #1 is chosen.
*/
void full(int num, float crse[], float cspd[], float wdir[], float
zlr, float hd[], float adir[], float wspd[], float tdir[],
float tspd[])
{
int i;
printf("------------------------------------------------------------------------------------\n");
printf("\n FULL TABLE\n");
printf(" ************\n");
printf(" index course sspeed windir zeroln shiphd | appspd | appdir trudir truspd\n");
for(i=0; i 360)) && (crse[i] != wmis[0]) )
printf(" Truewinds range test failed. Course value #%d invalid.\n",(i+1));
if( (cspd[i] < 0) && (cspd[i] != wmis[1]) )
printf(" Truewinds range test failed. Vessel speed value #%d invalid.\n",(i+1));
if( ((wdir[i] < 0) || (wdir[i] > 360)) && (wdir[i] != wmis[2]) )
printf(" Truewinds range test failed. Wind direction value #%d invalid.\n",(i+1));
if( (wspd[i] < 0) && (wspd[i] != wmis[3]) )
printf(" Truewinds range test failed. Wind speed value #%d invalid.\n",(i+1));
if( ((hd[i] < 0) || (hd[i] > 360)) && (hd[i] != wmis[4]) )
printf(" Truewinds range test failed. Ship heading value #%d invalid.\n",(i+1));
}
printf("\n");
for(i=0; i