# 1 "gsudf.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "gsudf.c"
# 220 "gsudf.c"
=pod

=head1 NAME

gsudf.gex - Writing Expression Functions as GrADS Scripts

=head1 SYNOPSIS

  ga-> display myfunc(args)

where B<myfunc> is implemented in a GrADS script file named C<myfunc.gsf>

=head1 DESCRIPTION

Traditionally, there are two kinds of functions in GrADS: script
functions and expression functions, and up to now these two did not
mix. I<Scripting functions> are user defined and called from any GrADS
script. Such functions are not directly available at the command
line, or cannot be used inside GrADS expressions. I<Expression
functions> are usually used in conjunction with the C<display> and
C<define> commands such as

   ga-> display aave(myfunc(u), global)

where C<aave> is an intrinsic function and C<myfunc> is a user
defined function.

The dynamic extension I<gsudf> allows you to write I<expression
functions> as GrADS I<script functions>. This is better explained with
the following examples.

=head1 EXAMPLES

=head2 Using I<gsudf> for Computing Wind Speed

Let us reimplement the intrinsic function C<mag> which compute the
wind speed given the C<u> and C<v> components of the wind; we will
call this new function C<speed>. The first step is to create a text
file called C<speed.gsf> with the implementation of this function:

   function speed ( u, v )
      expr = 'sqrt(' u '*' u '+' v '*' v ')'
      return expr

Notice that this function simply returns a string which will
eventually be evaluated by the GrADS expression parser; more on that
later. The second step in the implementation of this function is to
add an entry for this function in your User Defined eXtenfion (UDXT)
file:

      Type API Name Function Library
     ------ --- --------- ----------- --------------
      udf 0 speed f_gsudf gsudf.gex.so

The generic handler C<f_gsudf> in the shared library C<gsudf.gex>
executes the file C<speed.gsf>, evaluates the string output of this
function using the GrADS expression parser and returns the result. The
net effect is that C<speed.gsf>, with the help of its agent C<gsudf>,
implements a bonafide GrADS expression function.

Finally, you no longer need to initialize the I<gsudf>
package in GrADS v2.0.

   ga-> open model.ctl
   ga-> display speed(ua,va)

=head2 Returning defined variables

Although your GrADS script must always return a string, it does not
mean that all it can do is string maniputation. By using the C<define>
command one can always pre-computed intermediate values, and return
the name of the defined variable. Here is an example where the
dimension environment is modified, a variable defined in this enlarged
dimension environment, and then the dimension reset to its original
state:

   function x_cdiff ( var, dim )
      'set x 0 74'
      'define gsudf = cdiff('var','dim')'
      'set x 1 73'
      return 'gsudf'

This function enlarges the domain as to avoid missing undefined values
on the longitudinal boundaries (but not at the latitudinal boundary.)
A more generic version of this function is included with the source
distribution for this extension.

=head2 Returning an error condition

Returning an empty string will signal an error condition

   function errfunc(arg)
      say 'errfunc: error found, cannot proceed'
      return

=head1 FUNCTION PROVIDED

=head2 B<gsudf> I<[ARGUMENTS]>

=over 4

This function is not directly callable as such from GrADS. Rather it
works as a I<proxy> for the user defined functions written as GrADS
scripts. There 2 steps involved in defining your user defined function
through gsudf:

=over 4

=item 1.

For each function named I<$func>, create a script library file called
I<$func.gsf> and placed in a directory where GrADS can locate scripts
(for example, in a directory listed in your C<GASCRP> environment
variable.) The GrADS script must return a string with a valid GrADS
expression, or an empty string in case of an abnormal exit.

=item 2.

Have a corresponding entry in your User Defined eXtension (UDXT) file, e.g.,

         A
         P GrADS Library Library Short
    Type I Function Function Path Description
    ---- - ---------- ---------- -------------- -------------------------------
    udf 0 speed f_gsudf ^gsudf.gex "The mag() function as gsUDF"

=back

=back

=head1 BUGS

There is not much in terms of garbage collection. Any local variable
defined by the GrADS script implementing the expression function stays
around until explicitly undefined. To minimize memory usage explicitly
undefine any variabled you defined, and when defined variables are
involved, return your result in defined variable called B<gsudf>.

=head1 SEE ALSO

=over 4

=item *

L<http:

=item *

L<http:

=item *

L<http:

=back

=head1 AUTHOR

Arlindo da Silva (dasilva@opengrads.org)

=head1 COPYRIGHT

Copyright (C) 2007-2009 Arlindo da Silva; All Rights Reserved.

This is free software; see the source for copying conditions. There is
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

=cut
