//- ****************************************************************************
//-
//- Copyright 2009 National Technology & Engineering Solutions of Sandia, LLC
//- (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
//- Government retains certain rights in this software.
//-
//- BSD Open Source License
//- All rights reserved.
//-
//- Redistribution and use in source and binary forms, with or without
//- modification, are permitted provided that the following conditions are met:
//-
//-   1. Redistributions of source code must retain the above copyright notice,
//-      this list of conditions and the following disclaimer.
//-
//-   2. Redistributions in binary form must reproduce the above copyright
//-      notice, this list of conditions and the following disclaimer in the
//-      documentation and/or other materials provided with the distribution.
//-
//-   3. Neither the name of the copyright holder nor the names of its
//-      contributors may be used to endorse or promote products derived from
//-      this software without specific prior written permission.
//-
//- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
//- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//- POSSIBILITY OF SUCH DAMAGE.
//-
//- ****************************************************************************

//- Unauthorized reproduction or distribution of this program, or any
//- portion of it, may result in civil and criminal penalties, and will be
//- prosecuted to the maximum extent possible under the law.
//-

//! \file
//!
//! FILE slbm_F_shell.h
//!
//! DESCRIPTION
//! Prototypes for the SLBM Fortran Shell Interface
//!
//!
//! A Fortran Interface to the SLBM C++ library, providing access to all supported functionality.
//!
//! The slbm_F_shell Interface (written in C++) manages a connection to the C++ SLBM
//! library and provides Fortran compatible functions. To make this work, 4 conditions
//! must be met:
//! <br>1) The C++ shared objects libslbm.so and libslbmFshell.so must both be accessible via the LD_LIBRARY_PATH.
//! <br>2) The Fortran application must be linked to libslbmFshell.so
//! <br>3) The Fortran application must execute the command: slbm_create();
//! <br>4) The Fortran application must execute the command: slbm_load_velocity_model_binary();
//!
//!If all of these conditions are successfully met, then the the Fortran application can use the slbm_F_shell
//!interface through the shared object library libslbmFshell.so to access all the methods described in this document.
//!
//!Almost all methods in the Fortran interface have a parameter int* err that is set to 0 if the method
//!completed successfully or to a positive error code if the method generated some sort of error.
//!Applications should check the value of err after each call.  If err is  > 0 then method slbm_get_error_message()
//!can be called to retrieve an errorMessage that provides information about the error.  Some of the most
//!important error codes are listed in the followng table.
//!
//! <table border="2" cellspacing = "0" cellpadding="5">
//! <tr><td><b>Code</b></td><td><b>Function</b></td><td><b>Message</b></td></tr>
//! <tr><td>106</td><td>Grid::reaDataBuffererFromFile</td><td>Could not open velocity model file.</td></tr>
//! <tr><td>200</td><td>GreatCircle_Xg constructor</td><td>Pg/Lg not valid because source or receiver is below the Moho.</td></tr>
//! <tr><td>201</td><td>GreatCircle_Xn::computeTravelTime</td><td>Source-receiver separation exceeds maximum value.</td></tr>
//! <tr><td>202</td><td>GreatCircle_Xn::computeTravelTime</td><td>Source depth exceeds maximum value.</td></tr>
//! <tr><td>203</td><td>GreatCircle_Xn::computeTravelTimeCrust</td><td>Horizontal offset below the source plus horizontal offset below the receiver is greater than the source-receiver separation</td></tr>
//! <tr><td>300</td><td>GreatCircle_Xn::computeTravelTimeCrust</td><td>nIterations == 10000</td></tr>
//! <tr><td>301</td><td>GreatCircle_Xn::computeTravelTimeCrust</td><td>c*H is greater than ch_max.</td></tr>
//! <tr><td>302</td><td>GreatCircle_Xn::computeTravelTimeMantle</td><td>Could not converge on stable ray parameter.</td></tr>
//! <tr><td>303</td><td>GreatCircle_Xn::computeTravelTimeMantle</td><td>search for minimum H failed.</td></tr>
//! <tr><td>304</td><td>GreatCircle_Xn::computeTravelTimeMantle</td><td>c*H > ch_max.</td></tr>
//! <tr><td>305</td><td>GreatCircle_Xn::brent</td><td>Too many iterations.</td></tr>
//! <tr><td>400</td><td>GreatCircle_Xg::computeTravelTime</td><td>computeTravelTimeTaup() and computeTravelTimeHeadwave() both returned NA_VALUE.</td></tr>
//! <tr><td>401</td><td>GreatCircle_Xn::computeTravelTime</td><td>Receiver depth below Moho is illegal.</td></tr>
//! <tr><td>402</td><td>GreatCircle_Xn::computeTravelTimeCrust</td><td>Source is too close to the receiver.</td></tr>
//! </table>
//!
//!The libslbmFshell.so maintains a C++ Grid object, which manages interaction with the Earth model.
//!The Earth model is loaded by calling the slbm_load_velocity_model_binary(String) method, described below.
//!This Grid object remains in memory until deleted with the command slbm_delete(), or a different
//!Earth model is loaded with another call to slbm_load_velocity_model_binary(String).
//!
//!libslbmFshell.so also maintains a single instance of a C++ GreatCircle object which is instantiated
//!with a call to slbm_create_great_circle(). Once instantiated, many slbm_F_shell methods can retrieve information
//!from this GreatCircle object, such as slbm_get_travel_time(), slbm_get_weights(), and more. Once instantiated, the
//!GreatCircle can be interrogated until it is replaced with another GreatCircle by a subsequent call to
//!slbm_create_great_circle(), or is deleted by slbm_clear().
//!
//!The Grid object stores a vector of map objects which associates the phase and Location of a CrustalProfile
//!object with a pointer to the instance of the CrustalProfile. When slbm_create_great_circle() is called with a latitude,
//!longitude and depth which has been used before, the Grid object will return a pointer to the existing
//!CrustalProfile object, thereby enhancing performance. This vector of maps is cleared when slbm_clear() is called.
//!The implications of all this is that applications that loop over many calls to slbm_create_great_circle() will see a
//!performance improvement if slbm_clear() is not called within the loop. However, for problems where the number of
//!sources and/or receivers is so large that memory becomes an issue, applications could call slbm_clear() within
//!the loop to save memory.
//!
//!All calculations assume the Earth is defined by a GRS80 ellipsoid. For a description of how points along a
//!great circle are calculated see <A href="../../../doc/geovectors.pdf">geovectors.pdf</A>

#ifndef SLBM_F_SHELL_H
#define SLBM_F_SHELL_H

#include "SLBMGlobals.h"

/**
 * MAX_POINTS refers to the maximum number of points that will
 * be positioned along the headwave interface.
 */
static const int MAX_POINTS = 1000;

/**
 * MAX_NODES refers to the maximum number of grid nodes that contribute
 * to the interpolation of data at a single point along the headwave
 * interface.  The actual number of contributing nodes will be 3 for
 * linear interpolation and anywhere from 1 to 5 for natural_neighbor
 * interpolation.
 */
static const int MAX_NODES = 5;

#ifdef __cplusplus
extern "C"
{
#endif

    // Definition of dllimport and dllexport here for Windows only
//--------------------------
#if defined(_WIN32) || defined(WIN32)

  // exports when building SLBM dll, imports when linking to header files in
  // SLBM (Note that SLBM_EXPORTS should be defined when building a SLBM
  // DLL, and should  not be defined when linking with the SLBM DLL)
  #ifdef  SLBM_FORT_SHELL_EXPORTS
  #define SLBM_FORT_SHELL_EXP_IMP __declspec(dllexport)
  #else
  #define SLBM_FORT_SHELL_EXP_IMP __declspec(dllimport)
  #endif

  // exports DLL for classes and functions that ONLY export
  // (Note that this is mainly used for templated classes that are not imported)
  #define SLBM_FORT_SHELL_EXP     __declspec(dllexport)

#else  // Sun does not need these

  #define SLBM_FORT_SHELL_EXP_IMP
  #define SLBM_FORT_SHELL_EXP

#endif

//! \brief Retrieve the SLBM Version number.
//!
//! Retrieve the SLBM Version number.
//! @param version
//! @param size number of characters allocated for version
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_version(char* version, int* size, int* err);

//! \brief Retrieve error message.
//!
//! Retrieves last error message. This method should be called
//! following any function call that returns a "1" error flag.
//! The string is populated with the text obtained from the SLBMException
//! emessage attribute.
//! @param errorMessage a char pointer to contain the err message. NOTE: user should
//! allocate storage for approximately 500 chars.
//! @param size number of characters allocated for errorMessage.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_error_message( char* errorMessage, int* size);

//! \brief Instantiate a SLBM Interface object.
//!
//! Instantiate a SLBM Interface object.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_create (int* err);

//! \brief Instantiate a SLBM Interface object with fixed earth radius.
//!
//! Instantiate a SLBM Interface object fixing the earth radius to the double value
//! passed in argument list.
//! @param radius constant value of earth radius, in km (usually 6371.)
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_create_fixed_earth_radius (double* radius, int* err);

//! \brief Load the velocity model into memory from
//! the specified file or directory.  This method
//! automatically determines the format of the model.
//!
//! Load the velocity model into memory from the specified
//! file or directory.  This method
//! automatically determines the format of the model and
//! hence is able to load all model formats.
//!
//! @param modelFileName the path to the file or directory
//! that contains the model.
//! @param nameLength
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_load_velocity_model(const char* modelFileName, int* nameLength, int* err);

//! \brief Save the velocity model currently in memory to
//! the specified file in format 4.
//!
//! Save the velocity model currently in memory to
//! the specified file in format 4.
//! @param modelFileName the full or relative path plus
//! file name of the file to which the earth model is to
//! be written.
//! @param nameLength
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_save_velocity_model(const char* modelFileName, int* nameLength, int* err);

//! \brief Save the velocity model currently in memory to
//! the specified file.
//!
//! Save the velocity model currently in memory to
//! the specified file or directory.
//!
//! <p>The following formats are supported:
//! <ol>
//! <li>SLBM version 1 ascii file.  All model information is
//! output to a single file in ascii format.
//! This format was available in SLBM version 2, but never used.
//!
//! <li>SLBM version 2 directory format. Model information is
//! output to a number of different files and directories, mostly
//! in binary format.  This format was used almost exclusively in
//! SLBM version 2.
//!
//! <li>SLBM version 3 directory format. Model information is
//! output to a number of different files and directories, mostly
//! in binary format.  This format is very similar to format 2
//! with the difference being that the model tessellation and values
//! are stored in GeoTess format instead of the custom SLBM format.
//!
//! <li>SLBM version 3 single-file format.  This is the default+preferred
//! format.  All model information is written to a single file.
//! If the modelFileName extension is '.ascii' the file is written
//! in ascii format, otherwise it is written in binary format.
//! </ol>
//!
//! See SLBM_Design.pdf in the main documentation directory
//! for detailed information about model output formats.
//!
//! <p>Models stored in SLBM version 1 and 2 formats (formats 1 and 2)
//! only support linear interpolation.  Models stored in SLBM
//! version 3 formats (formats 3 and 4) support both linear
//! and natural neighbor interpolation.
//!
//! @param modelFileName the full or relative path to the
//! file or directory to which the earth model is to
//! be written.  For formats 2 and 3, the directory will be
//! created if it does not exist.
//! @param nameLength
//! @param format the desired format of the output.
//! If omitted, defaults to 4: all model information written to a single
//! file.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_save_velocity_model_f(const char* modelFileName, int* nameLength, int* format, int* err);

//! \brief Deletes the SlbmInterface object instantiated with the call
//! slbm_create().
//!
//! Deletes the SlbmInterface object instaniated with the call
//! slbm_create().
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_delete (int* err);

//! \brief Load the velocity model into memory from
//! the specified file or directory.  This method
//! automatically determines the format of the model.
//!
//! Load the velocity model into memory from the specified
//! file or directory.  This method
//! automatically determines the format of the model and
//! hence is able to load all model formats.
//!
//! <p>This method is deprecated in SLBM versions 3 and higher
//! and is provided only for backward compatibility
//! with previous versions of SLBM.  It simply calls
//! loadVelocityModel(modelPath).
//!
//! @param modelDirectory
//! @param nameLength
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_load_velocity_model_binary(const char* modelDirectory, int* nameLength, int* err );

//! \brief Deprecated.  Use saveVelocityModel() instead.
//! Specify the directory into which the model that is
//! currently in memory should be written the next time
//! that saveVelocityModelBinary() is called.
//!
//! This method is deprecated and is provided only for backward
//! compatibility with previous versions of SLBM.  Use method
//! saveVelocityModel() instead.
//! <p>Specify the directory into which the model that is
//! currently in memory should be written the next time
//! that saveVelocityModelBinary() is called.  The model
//! will be written in format 3, which is the SLBM version 3
//! binary directory format (GeoTess).
//! @param directoryName the name of the directory where model
//! files are to be written.  The directory will be
//! created if it does not exist.
//! @param dirNameLength
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_specify_output_directory(const char* directoryName, int* dirNameLength, int* err );

//! \brief Deprecated.  Use saveVelocityModel() instead.
//! Write the model in format 3 to directory
//! previously specified with a call to specifyOutputDirectory().
//!
//! This method is deprecated and is provided only for backward
//! compatibility with previous versions of SLBM.  Use method
//! saveVelocityModel() instead.
//! <p>The model is written in format 3 to the directory previously
//! specified with a call to specifyOutputDirectory().
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_save_velocity_model_binary( int* err);

//! \brief Instantiate a new GreatCircle object between
//! two locations.
//!
//! Instantiate a new GreatCircle object between
//! two locations.
//! @param phase the phase that this GreatCircle is to
//! support.  Recognized phases are Pn, Sn, Pg and Lg.
//! @param sourceLat the geographic latitude of the source
//! in radians.
//! @param sourceLon the longitude of source in radians.
//! @param sourceDepth the depth of the source in km.
//! @param receiverLat the geographic latitude of the receiver
//! in radians.
//! @param receiverLon the longitude of the receiver in radians.
//! @param receiverDepth the depth of the receiver in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_create_great_circle (int* phase, double* sourceLat, double* sourceLon, double* sourceDepth,
                                    double* receiverLat, double* receiverLon, double* receiverDepth, int* err);

//! \brief Returns true if the current GreatCirlce object has
//! been instantiated and is ready to be interrogated.
//!
//! Returns true if the current GreatCirlce object has
//! been instantiated and is ready to be interrogated.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_is_valid (int* err);

//! \brief Delete the current GreatCircle object from memory and
//! clear the pool of stored CrustalProfile objects.
//! The model Grid is not deleted and remains accessible.
//!
//! Delete the current GreatCircle object from memory and
//! clear the pool of stored CrustalProfile objects.
//! The model Grid is not deleted and remains accessible.
//!
//! The Grid object owned by SlbmInterface stores a vector of map objects which associates
//! the phase and Location of a CrustalProfile object with a pointer to the instance
//! of the CrustalProfile.  When createGreatCircle() is called with a latitude,
//! longitude and depth which has been used before, the Grid object will return a
//! pointer to the existing CrustalProfile object, thereby enhancing performance.
//! This vector of maps is cleared when SlbmInterface::clear() is called.  The
//! implications of all this is that applications that loop over many calls to
//! createGreatCircle() will see a performance improvement if clear() is not called
//! within the loop.  However, for problems with a huge number of sources and or receivers,
//! if memory becomes an issue, applications could call clear() within the loop
//! to save memory.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void  slbm_clear (int* err);

//! \brief Retrieve the source-receiver separation, in radians.
//!
//! Retrieve the source-receiver separation, in radians.
//! @param dist the source-receiver separation is returned
//! in distance.  If the GreatCircle is invalid, distance
//! will equal BaseObject::NA_VALUE.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_distance (double* dist, int* err);

//! \brief Retrieve horizontal offset below the source, in radians.
//!
//! Retrieve horizontal offset below the source, in radians.
//! This is the angular distance between the location of the
//! source and the source pierce point where the ray impinged
//! on the headwave interface.
//! @param dist the horizontal offset below the source, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_source_distance(double* dist, int* err);

//! \brief Retrieve horizontal offset below the receiver, in radians.
//!
//! Retrieve horizontal offset below the receiver, in radians.
//! This is the angular distance between the location of the
//! receiver and the receiver pierce point where the ray impinged
//! on the headwave interface.
//! @param dist the horizontal offset below the receiver, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_receiver_distance(double* dist, int* err);

//! \brief Retrieve angular distance traveled by the ray
//! below the headwave interface, in radians.
//!
//! Retrieve the angular distance traveled by the ray
//! below the headwave interface, in radians.
//! This is the total distance minus the horizontal offsets
//! below the source and receiver.  getSourceDistance() +
//! getReceiverDistance() + getHeadwaveDistance() =
//! getDistance().
//! @param dist the angular distance traveled by the ray
//! below the headwave interface, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_head_wave_distance(double* dist, int* err);

//! \brief Retrieve horizontal distance traveled by the ray
//! below the headwave interface, in radians.
//!
//! Retrieve horizontal distance traveled by the ray
//! below the headwave interface, in km.
//! This is the sum of path_increment(i) * R(i) where path_increment(i) is the
//! angular distance traveled by the ray in each angular
//! distance increment along the head wave interface, and R(i)
//! is the radius of the head wave interface in that same
//! horizontal increment.
//! @param dist the horizontal distance traveled by the ray
//! below the headwave interface, in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_head_wave_distance_km(double* dist, int* err);
//! \brief Retrieve the total travel time for the GreatCircle,
//! in seconds.
//!
//! Retrieve the total travel time for the GreatCircle,
//! in seconds.
//! @param travelTime the total travel time in seconds is returned
//! in travelTime.  If the GreatCircle is invalid, travelTime
//! will equal BaseObject::NA_VALUE.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_travel_time (double* travelTime, int* err);

//! \brief Retrieve the total travel time and the 4 components that
//! contribute to it for the current GreatCircle.
//!
//! Retrieve the total travel time and the 4 components that
//! contribute to it for the current GreatCircle.
//! If the greatCircle is invalid, tTotal and all the
//! components will equal BaseObject::NA_VALUE.
//!
//! @param tTotal the total travel time, in seconds.
//! @param tSource the crustal travel time below the source, in seconds.
//! @param tReceiver the crustal travel time below the receiver, in seconds.
//! @param tHeadwave the head wave travel time, in seconds.
//! @param tGradient the Zhao gradient correction term, in seconds.
//! For GreatCircle objects that support Pg and Lg, this is always 0.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_travel_time_components (double* tTotal, double* tSource, double* tReceiver, double* tHeadwave, double* tGradient, int* err);

//! \brief Retrieve the weight assigned to each grid node that
//! was touched by the GreatCircle.
//!
//! Retrieve the weight assigned to each grid node that
//! was touched by the GreatCircle.
//!
//! A map which associates an instance of a GridProfile object with a
//! double <I>weight</I> is initialized.  Then every LayerProfile on the head
//! wave interface between the source and
//! receiver is visited and the angular distance, <I>d</I>, that the ray
//! traveled in the horizontal segment is retrieved.  If <I>d</I> > 0,
//! then the neighboring GridProfile objects that contributed to
//! the interpolated value of the LayerProfile are visited.
//! The product of <I>d * R * C</I>  is added to the weight associated
//! with that GridProfile object, where <I>R</I> is the radius of the
//! head wave interface for the LayerProfile object being evaluated,
//! and <I>C</I> is the interpolation coefficient for the
//! GridProfile - LayerProfile pair under consideration.
//! Then, all the GridProfile objects in the map are visited, the
//! grid node IDs extracted into int array <I>nodeId</I>, and the
//! <I>weight</I> extracted into double array <I>weight</I>.
//!
//! Note: Only grid nodes touched by this GreatCircle are included in the
//! output.  Each grid node is included only once, even though more than
//! one LayerProfile object may have contributed some weight to it.
//! The sum of all the weights will equal the horizontal distance
//! traveled by the ray along the head wave interface, from the source
//! pierce point to the receiver pierce point, in km.
//! @param nodeId the node IDs of all the grid nodes touched by the
//! current GreatCircle.
//!
//! @param weight the weights of all the grid nodes touched by the
//! current GreatCircle.  Calling application must dimension this
//! array large enough to handle any possible size.
//! @param nWeights the number of elements in nodeId and weight.
//! Calling application must dimension this
//! array large enough to handle any possible size.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_weights (int nodeId[], double weight[], int* nWeights, int* err);

//! \brief Retrieve the node IDs and the interpolation
//! coefficients for the source CrustalProfile.
//!
//! Retrieve the node IDs and the interpolation
//! coefficients for the source CrustalProfile.  There will be
//! BaseObject::nCoefficients of each.  The sum of the weights
//! will equal 1.
//! @param nodeids[] the nodeIds that influenced the interpolated values
//! at the source.
//! @param weights[] the interpolation coefficients applied to the grid
//! nodes that influenced the interpolated values at the source.
//! @param nWeights number of weights returned in the weights array
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_weights_source(int nodeids[], double weights[], int* nWeights, int* err);

//! \brief Retrieve the node IDs and the interpolation
//! coefficients for the receiver CrustalProfile.
//!
//! Retrieve the node IDs and the interpolation
//! coefficients for the receiver CrustalProfile.  There will be
//! BaseObject::nCoefficients of each.  The sum of the weights
//! will equal 1.
//! @param nodeids[] the nodeIds that influenced the interpolated values
//! at the receiver.
//! @param weights[] the interpolation coefficients applied to the grid
//! nodes that influenced the interpolated values at the receiver.
//! @param nWeights number of weights returned in the weights array
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_weights_receiver(int nodeids[], double weights[], int* nWeights, int* err);

//! \brief Retrieve the number of Grid nodes in the Earth model.
//!
//! Retrieve the number of Grid nodes in the Earth model.
//! @param numGridNodes the number of elements in the grid
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_n_grid_nodes(int* numGridNodes, int* err);

//! \brief Retrieve the number of LayerProfile objects positioned along
//! the head wave interface.
//!
//! Retrieve the number of LayerProfile objects positioned along
//! the head wave interface.  It is useful to call this method
//! before calling getGreatCircleData() since the value returned
//! by this method will be the number of elements that will be
//! populated in parameters headWaveVelocity[], neighbors[] and
//! coefficients[].
//! @param nHeadWavePoints
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_n_head_wave_points(int* nHeadWavePoints, int* err);

//! \brief Retrieve the lat (radians), lon (radians),
//! interface depths (km), P and S wave interval velocities (km/sec)
//! and P and S mantle gradient (1/sec) information
//! associated with a specified node in the velocity grid.
//!
//! Retrieve the interface depth, velocity and gradient
//! information associated with a specified node in the
//! velocity grid.
//! @param nodeId the node ID of the grid point in the model
//! (zero based index).
//! @param latitude the latitude of the grid node in radians.
//! @param longitude the longitude of the grid node in radians.
//! @param depth the depths of all the model interfaces, in km.
//! @param pvelocity an array containing the P velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param svelocity an array containing the S velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param gradient a 2-element array containing the P and S
//! velocity gradients in the mantle, in 1/sec.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_grid_data(int* nodeId, double* latitude, double* longitude, double* depth, double* pvelocity, double* svelocity, double* gradient, int* err);

//! \brief Modify the velocity and gradient information
//! associated with a specified node in the Grid.
//!
//! Modify the velocity and gradient information
//! associated with a specified node in the Grid.
//! @param nodeId the node number of the grid point in the model.
//! (zero based index).
//! @param depth an array containing the depths of the tops of all the
//! intervals at the specified grid node, in km.
//! @param pvelocity an array containing the P velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param svelocity an array containing the S velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param gradient a 2-element array containing the P and S
//! velocity gradients in the mantle, in 1/sec.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_grid_data(int* nodeId, double* depth, double* pvelocity, double* svelocity, double* gradient, int* err);

//! \brief Retrieve the data required for input to the travel time
//! calculation, for the current GreatCircle object.
//!
//! Retrieve the data required for input to the travel time
//! calculation, for the current GreatCircle object.
//!
//! All the one dimensional arrays can be dimensioned to any size that the
//! developer thinks will be large enough to hold all the values that will result.
//!
//!	The 2D arrays, neighbors and coefficients, must
//! be dimensioned to be exactly MAX_POINTS by nCoefficients.  nCoefficients is
//! defined in BaseObject.h and is the number of points that define a cell.  For
//! quadrilateral cells, nCoefficients = 4, for triangular cells, nCoefficients = 3.
//! At the time of this release, quadrilateral cells are being used and
//! nCoefficients is 4 (but this may change!).  MAX_POINTS is
//! defined in this file, and must be as large or larger than the number of
//! points along the head wave interface.  For a great circle path where the
//! source-receiver separation is delta and the angular spacing of the
//! nodes along the head wave interface is path_increment, then MAX_POINTS must be at
//! least delta / path_increment.  If MAX_POINTS needs to be increased, it must be changed
//! in this file and slbm_F_shell recompiled (SLBM will not
//! need to be recompiled, however).
//!
//! @param phase the phase supported by the current GreatCircle.  Will be one of
//! 0=Pn, 1=Sn, 2=Pg, 3=Lg.
//! @param path_increment the actual horizontal separation of the LayerProfile
//! objects along the head wave interface, in radians.  The actual
//! separation will be reduced from the value requested in the call to
//! createGreatCircle() in order that some number of equal sized increments
//! will exactly fit between the source and receiver.
//! @param sourceDepth the depths of all the model interfaces below the source, in km.
//! @param sourceVelocity the P or S velocity of each interval below the source, in km/sec.
//! @param receiverDepth the depths of all the model interfaces below the receiver, in km.
//! @param receiverVelocity the P or S velocity of each interval below the
//! receiver, in km/sec.
//! @param headWaveVelocity the P or S velocity at the center of each
//! horizontal segment between the source and the receiver, in km/sec.
//! The first horizontal segment starts at the source, the last horizontal
//! segment ends at the receiver, and each one is of size path_increment.  The head
//! wave velocities are interpolated at the center of each of these horizontal
//! segments, just below the head wave interface.
//! @param gradient the P or S velocity gradient in the mantle at the center
//! of each horizontal segment of the head wave, in 1/sec.  For Pg and Lg,
//! the values will be BaseObject::NA_VALUE.
//! @param npoints the number of horizontal increments sampled along the
//! head wave interface.  To discover this number before calling this method
//! call getNHeadWavePoints().
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_great_circle_data (
        int* phase,
        double* path_increment,
        double sourceDepth[slbm::NLAYERS],
        double sourceVelocity[slbm::NLAYERS],
        double receiverDepth[slbm::NLAYERS],
        double receiverVelocity[slbm::NLAYERS],
        double headWaveVelocity[MAX_POINTS],
        double gradient[MAX_POINTS],
        //int neighbors[MAX_POINTS][slbm::nCoefficients],
        //double coefficients[MAX_POINTS][slbm::nCoefficients],
        int* npoints,
        int* err);

SLBM_FORT_SHELL_EXP_IMP void slbm_get_great_circle_node_info (
        int nodes[MAX_POINTS][MAX_NODES],
        double coefficients[MAX_POINTS][MAX_NODES],
        int* npoints, int nnodes[MAX_POINTS], int* err);

//! \brief Retrieve interpolated data from the earth model at a single
//! specified latitude, longitude.
//!
//! Retrieve interpolated data from the earth model at a single
//! specified latitude, longitude.
//! @param lat the latitude where information is to be interpolated,
//! in radians.
//! @param lon the longitude where information is to be interpolated,
//! in radians.
//! @param nodeId the nodeIds of the grid nodes that were involved
//! in the interpolation.
//! @param coefficients the interpolation coefficients that were applied to
//! the information from the neighboring grid nodes.
//! @param nnodes the number of nodes that contributed to interpolation of
//! data.  This is the size of arrays nodeId and coefficients.
//! @param depth the depths of the tops of the interfaces in the Earth model,
//! in km.  There will be one of these for each layer of the model.
//! @param pvelocity the P velocities of each layer of the model, in km/sec.
//! @param svelocity the S velocities of each layer of the model, in km/sec.
//! @param pgradient the mantle P velocity gradient, in 1/sec.
//! @param sgradient the mantle S velocity gradient, in 1/sec.
//! @return true if successful.  If not successful, nodeIds are all -1 and
//! all other returned arrays are populated with BaseObject::NA_VALUE.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_interpolated_point (double* lat, double* lon,
        int* nodeId, double* coefficients, int* nnodes, double* depth, double* pvelocity,
        double* svelocity, double* pgradient, double* sgradient, int* err);

//! \brief Specify the latitude and longitude range in radians for active nodes.
//!
//! Specify the latitude and longitude range in radians for active nodes.
//! Active nodes are defined as follows:  for each triangle in the
//! tessellation, if any of the 3 nodes that define the triangle is
//! within the latitude longitude range specified by this method, then
//! all 3 nodes are defined to be active nodes.
//! Lats and lons must be specified in radians.
//! @param latmin minimum latitude in radians
//! @param lonmin minimum longitude in radians
//! @param latmax maximum latitude in radians
//! @param lonmax maximum longitude in radians
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_initialize_active_nodes(double* latmin, double* lonmin, double* latmax, double* lonmax, int* err);

//! \brief Retrieve the number of active nodes in the Grid.
//!
//! Retrieve the number of active nodes in the Grid.
//! @param nNodes
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_n_active_nodes(int* nNodes, int* err);

//! \brief Retrieve the grid node ID that corresponds to a specified
//! active node ID.
//!
//! Retrieve the grid node ID that corresponds to a specified
//! active node ID.
//! @param activeNodeId
//! @param gridNodeId
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_grid_node_id(int* activeNodeId, int* gridNodeId, int* err);	//+

//! \brief Retrieve the active node ID that corresponds to a specified grid node ID.
//!
//! Retrieve the active node ID that corresponds to a specified
//! grid node ID.
//! @param gridNodeId
//! @param activeNodeId
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_id(int* gridNodeId, int* activeNodeId, int* err);	//+

//! \brief Retrieve the number of times that node
//! has been 'touched' by a GreatCircle object.
//!
//! Retrieve the number of times that node
//! has been 'touched' by a GreatCircle object.
//! @param nodeId
//! @param hitCount
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_node_hit_count(int* nodeId, int* hitCount, int* err);	//+

//! \brief Retrieve the node IDs of the nodes that surround the
//! specified node.
//!
//! Retrieve the node IDs of the nodes that surround the specified node.
//! <p>The caller must supply int array neighbors which is dimensioned large
//! enough to hold the maximum number of neighbors that a node can have,
//! which is 8.  The actual number of neighbors is returned in nNeighbors.
//! @param nid
//! @param neighbors
//! @param nNeighbors length of neighbors array
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_node_neighbors(int* nid, int neighbors[], int* nNeighbors, int* err);

//! \brief Retrieve the node IDs of the nodes that surround the
//! specified node.
//!
//! Retrieve the node IDs of the nodes that surround the specified node.
//! <p>The caller must supply int array neighbors which is dimensioned large
//! enough to hold the maximum number of neighbors that a node can have,
//! which is 8.  The actual number of neighbors is returned in nNeighbors.
//! @param nid
//! @param neighbors
//! @param distance
//! @param azimuth
//! @param nNeighbors length of neighbors array
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_node_neighbor_info(int* nid, int neighbors[], double distance[], double azimuth[],
                                    int* nNeighbors, int* err);

//! \brief Retrieve the angular separation of two grid nodes, in radians.
//!
//! Retrieve the angular separation of two grid nodes, in radians.
//! @param node1
//! @param node2
//! @param distance
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_node_separation(int* node1, int* node2, double* distance, int* err);	//+

//! \brief Retrieve the azimuth from grid node1 to grid node2, radians.
//!
//! Retrieve the azimuth from grid node1 to grid node2, radians.
//! @param node1
//! @param node2
//! @param azimuth
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_node_azimuth(int* node1, int* node2, double* azimuth, int* err);	//+

//! \brief Calculate a traveltime uncertainty value (seconds) as a function of distance
//! in radians for a supported seismic phase (Pn, Sn, Pg, & Lg).
//!
//! Calculate a traveltime uncertainty value (seconds) as a function of distance
//! in radians for a supported seismic phase (Pn, Sn, Pg, & Lg).
//! @param phase Pn = 0, Sn = 1, Pg = 2, Lg = 3
//! @param distance the angular distance in radians
//! @param uncertainty the model uncertainty (seconds) associated with the angular distance and phase
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_traveltime_uncertainty( int* phase, double* distance, double* uncertainty, int* err );

//! \brief Retrieve travel time uncertainty in sec. This function will call either
//! the path-dependent or 1D uncertainty, depending on the model file being used.
//!
//! Retrieve travel time uncertainty in sec. This function will call either
//! the path-dependent or 1D uncertainty, depending on the model file being used.
//! @param tt_uncertainty uncertainty of the travel time, in seconds..
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_tt_uncertainty(double* tt_uncertainty, int* err );

//! \brief Retrieve travel time uncertainty in sec. This function will call either
//! the path-dependent or 1D uncertainty, depending on the model file being used.
//! This function includes randomError in the computation.
//!
//! Retrieve travel time uncertainty in sec. This function will call either
//! the path-dependent or 1D uncertainty, depending on the model file being used.
//! This function includes randomError in the computation.
//! @param tt_uncertainty uncertainty of the travel time, in seconds..
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_tt_uncertainty_randerr(double* tt_uncertainty, int* err );

//! \brief Retrieve travel time uncertainty in sec.
//! This function will return the non-path-dependent 1D uncertainty regardless
//! of the model in use.
//!
//! Retrieve travel time uncertainty in sec
//! using the phase and distance specified in last call to getGreatCircle().
//! This function will return the non-path-dependent 1D uncertainty regardless
//! of the model in use.
//! @param tt_uncertainty uncertainty of the travel time, in seconds..
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_tt_uncertainty1d(double* tt_uncertainty, int* err );

//! \brief Retrieve some of the parameters that contribute to the calculation of
//! of total travel time using the Zhao algorithm.
//!
//! Retrieve some of the parameters that contribute to the calculation of
//! of total travel time using the Zhao algorithm.  This method only returns
//! meaningful results for phases Pn and Sn.  For Pg and Lg, all the parameters
//! of type double are returned with values BaseObject::NA_VALUE and udSign is
//! returned with value of -999.
//! @param Vm the velocity at the top of the mantle averaged along the Moho
//! between the source and receiver pierce points.
//! @param Gm the velocity gradient at the top of the mantle averaged along the Moho
//! between the source and receiver pierce points.
//! @param H the turning depth of the ray relative to the Moho
//! @param C a constant whose product with V0 gives the mantle velocity gradient
//! for a flat Earth. V0 is the velocity of the top of the mantle averaged over
//! the whole model.
//! @param Cm a constant whose product with Vm gives the mantle velocity gradient
//! for a flat Earth.
//! @param udSign a value of 0 indicates the source is in the crust.
//! +1 indicates the ray leaves a mantle source in the downgoing
//! direction.  -1 indicates the ray leaves a mantle source in an upgoing direction.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_zhao_parameters(double* Vm, double* Gm, double* H, double* C, double* Cm, int* udSign, int* err );

//! \brief Retrieve the weight assigned to each active node that
//! was touched by the GreatCircle.
//!
//! \brief Retrieve the weight assigned to each active node that
//! Retrieve the weight assigned to each  node that
//! was touched by the GreatCircle.
//!
//! <p>A map which associates an instance of a GridProfile object with a
//! double <I>weight</I> is initialized.  Then every LayerProfile on the head
//! wave interface between the source and
//! receiver is visited and the angular distance, <I>d</I>, that the ray
//! traveled in the horizontal segment is retrieved.  If <I>d</I> > 0,
//! then the neighboring GridProfile objects that contributed to
//! the interpolated value of the LayerProfile are visited.
//! The product of <I>d * R * C</I>  is added to the weight associated
//! with that GridProfile object, where <I>R</I> is the radius of the
//! head wave interface for the LayerProfile object being evaluated,
//! and <I>C</I> is the interpolation coefficient for the
//! GridProfile - LayerProfile pair under consideration.
//! Then, all the GridProfile objects in the map are visited, the
//! grid node IDs extracted into int array <I>nodeId</I>, and the
//! <I>weight</I> extracted into double array <I>weight</I>.
//!
//! <p>Note: Only grid nodes touched by this GreatCircle are included in the
//! output.  Each grid node is included only once, even though more than
//! one LayerProfile object may have contributed some weight to it.
//! The sum of all the weights will equal the horizontal distance
//! traveled by the ray along the head wave interface, from the source
//! pierce point to the receiver pierce point, in km.
//! @param nodeId the active node IDs of all the grid nodes touched by the
//! current GreatCircle.
//!
//! @param weight the weights of all the grid nodes touched by the
//! current GreatCircle.  Calling application must dimension this
//! array large enough to handle any possible size.
//! @param nWeights the number of elements in nodeId and weight.
//! Calling application must dimension this
//! array large enough to handle any possible size.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_weights(int nodeId[], double weight[], int* nWeights, int* err );

//! \brief Retrieve the active node IDs and the interpolation
//! coefficients for the source CrustalProfile.
//!
//! Retrieve the active node IDs and the interpolation
//! coefficients for the source CrustalProfile.  There will be
//! anywhere from 1 to 5 of each.  The sum of the weights
//! will equal 1.
//! @param nodeids
//! @param weights
//! @param nweights size of nodeids and weights
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_weights_src(int nodeids[], double weights[], int* nweights, int* err );

//! \brief Retrieve the active node IDs and the interpolation
//! coefficients for the receiver CrustalProfile.
//!
//! Retrieve the active node IDs and the interpolation
//! coefficients for the receiver CrustalProfile.  There will be
//! anywhere from 1 to 5 of each.  The sum of the weights
//! will equal 1.
//! @param nodeids
//! @param weights
//! @param nweights size of nodeids and weights
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_weights_rcvr(int nodeids[], double weights[], int* nweights, int* err );


//! \brief Retrieve the node IDs of the nodes that surround the specified node.
//!
//! Retrieve the node IDs of the nodes that surround the specified node.
//! @param nid the id of the node whose neighbors are being requested
//! @param neighbors array of node ids that are the neighbors of nid
//! @param nNeighbors the length of neighbors array
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_neighbors( int* nid, int neighbors[], int* nNeighbors, int* err );

//! \brief Retrieve the node IDs of the nodes that surround the
//! specified node.
//!
//! Retrieve the node IDs of the nodes that surround the specified node.
//! <p>The caller must supply int array neighbors which is dimensioned large
//! enough to hold the maximum number of neighbors that a node can have,
//! which is 8.  The actual number of neighbors is returned in nNeighbors.
//! @param nid
//! @param neighbors
//! @param distance
//! @param azimuth
//! @param nNeighbors
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_neighbor_info(int* nid, int neighbors[], double distance[],
    double azimuth[], int* nNeighbors, int* err );

//! \brief Retrieve the lat (radians), lon (radians),
//! interface depths (km), P and S wave interval velocities (km/sec)
//! and P and S mantle gradient (1/sec) information
//! associated with a specified active node in the velocity grid.
//!
//! Retrieve the interface depth, velocity and gradient
//! information associated with a specified active node in the
//! velocity grid.
//! @param nodeId the active node ID of the grid point in the model
//! (zero based index).
//! @param latitude the latitude of the grid node in radians.
//! @param longitude the longitude of the grid node in radians.
//! @param depth the depths of all the model interfaces, in km.
//! @param pvelocity an array containing the P velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param svelocity an array containing the S velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param gradient a 2-element array containing the P and S
//! velocity gradients in the mantle, in 1/sec.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_active_node_data(	int* nodeId,
                                    double* latitude,
                                    double* longitude,
                                    double depth[slbm::NLAYERS],
                                    double pvelocity[slbm::NLAYERS],
                                    double svelocity[slbm::NLAYERS],
                                    double gradient[2], int* err );

//! \brief Modify the velocity and gradient information
//! associated with a specified active node in the Grid.
//!
//! Modify the velocity and gradient information
//! associated with a specified active node in the Grid.
//! @param nodeId the node number of the grid point in the model.
//! (zero based index).
//! @param depth an array containing the depths of the tops of the
//! layers, in km
//! @param depth an array containing the depths of the tops of the
//! layers, in km
//! @param pvelocity an array containing the P velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param svelocity an array containing the S velocities of all the
//! intervals at the specified grid node, in km/sec.
//! @param gradient a 2-element array containing the P and S
//! velocity gradients in the mantle, in 1/sec.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_active_node_data(	int* nodeId,
                                    double depth[slbm::NLAYERS],
                                    double pvelocity[slbm::NLAYERS],
                                    double svelocity[slbm::NLAYERS],
                                    double gradient[2], int* err );

//! \brief Set the value of chMax.  c is the zhao c parameter and h is
//! the turning depth of the ray below the moho.  Zhao method only valid
//! for c*h << 1. When c*h > chMax, then slbm will throw an exception.
//!
//! Set the value of chMax.  c is the zhao c parameter and h is
//! the turning depth of the ray below the moho.  Zhao method only valid
//! for c*h << 1. When c*h > chMax, then slbm will throw an exception.
//! This call modifies global parameter BaseObject::ch_max
//! @param chMax
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_ch_max( double* chMax, int* err );

//! \brief Retrieve the current value of chMax.  c is the zhao c parameter
//! and h is the turning depth of the ray below the moho.  Zhao method only valid
//! for c*h << 1. When c*h > chMax, then slbm will throw an exception.
//!
//! Retrieve the current value of chMax.  c is the zhao c parameter and h is
//! the turning depth of the ray below the moho.  Zhao method only valid
//! for c*h << 1. When c*h > chMax, then slbm will throw an exception.
//! This call retrieves global parameter BaseObject::ch_max
//! @param chMax
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_ch_max( double* chMax, int* err );

//! \brief Retrieve the average P or S wave mantle velocity that is specified
//! in the model input file, in km/sec.
//!
//! Retrieve the average P or S wave mantle velocity that is specified
//! in the model input file.  This value is used in the calculation of
//! the Zhao c parameter.
//! @param type specify either BaseObject::PWAVE or BaseObject::SWAVE.
//! @param velocity the P or S wave velocity is returned in this parameter,
//! in km/sec.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_average_mantle_velocity( int* type, double* velocity, int* err );

//! \brief Set the average P or S wave mantle velocity that is recorded
//! in the model input file, in km/sec.
//!
//! Set the average P or S wave mantle velocity that is specified
//! in the model input file.  This value is used in the calculation of
//! the Zhao c parameter.
//! @param type specify either BaseObject::PWAVE or BaseObject::SWAVE.
//! @param velocity the P or S wave velocity that is to be set,
//! in km/sec.  This value will be stored in the model file, if the
//! model file is written to file by a call to saveVelocityModel()
//! subsequent to a call to this method.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_average_mantle_velocity( int* type, double* velocity, int* err );

//! \brief Retrieve the tessellation ID of the model currently in memory.
//!
//! Retrieve the tessellation ID of the model currently in memory. Usually 32 characters long.
//! @param tessId
//! @param size number of characters allocated for tessId
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_tess_id( char* tessId, int* size, int* err );

//! \brief Retrieve the fraction of the path length of the current
//! GreatCircle object that is within the currently defined active region.
//!
//! Retrieve the fraction of the path length of the current
//! GreatCircle object that is within the currently defined active region.
//! @param fractionActive
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_fraction_active ( double* fractionActive, int* err );

//! \brief Set the maximum source-receiver separation for Pn/Sn phase,
//! in radians.
//!
//! Set the maximum source-receiver separation for Pn/Sn phase,
//! in radians.  Source-receiver separations greater than the specified
//! value will result in an exception being thrown in createGreatCircle().
//! Default value is PI radians.
//! @param maxDistance
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_max_distance ( const double* maxDistance, int* err );

//! \brief Retrieve the current value for the maximum source-receiver
//! separation, in radians.
//!
//! Retrieve the current value for the maximum source-receiver
//! separation, in radians.
//! @param maxDistance
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_max_distance ( double* maxDistance, int* err );

//! \brief Set the maximum source depth for Pn/Sn phase,
//! in km.
//!
//! Set the maximum source depth for Pn/Sn phase,
//! in km.  Source depths greater than the specified
//! value will result in an exception being thrown in createGreatCircle().
//! Default value is 9999 km.
//! @param maxDepth
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_max_depth ( const double* maxDepth, int* err );

//! \brief Retrieve the current value for the maximum source depth, in km.
//!
//! Retrieve the current value for the maximum source depth, in km.
//! @param maxDepth
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_max_depth ( double* maxDepth, int* err );

//! \brief Retrieve information about Pg/Lg travel time calculations.
//!
//! Retrieve information about Pg/Lg travel time calculations.  This method
//! only returns useful information when the phase is Pg or Lg.  For Pn and
//! Sn, all information is returned as SLBMGlobals::NA_VALUE.
//! @param tTotal is the total travel time in seconds.  It will be exactly
//! equal to the lesser of tTaup or tHeadwave, except that if tTaup is equal
//! to SLBMGlobals::NA_VALUE, then tTotal will equal tHeadwave.
//! @param tTaup is the taup travel time in seconds.  If this value is equal
//! to SLBMGlobals::NA_VALUE, it means that the taup calculation failed for
//! some reason (shadow zones, etc.).
//! @param tHeadwave is the headwave travel time in secods
//! @param pTaup TauP ray parameter.
//! @param pHeadwave headwave ray parameter.
//! @param trTaup is the radius at which the taup ray turned, in km.
//! @param trHeadwave is the radius at which the headwave ray turned, in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_pg_lg_components ( double* tTotal, double* tTaup,
            double* tHeadwave, double* pTaup, double* pHeadwave,
            double* trTaup, double* trHeadwave, int* err );

// new gtb 16Jan2009
//-------------------------------------------------------------------------
//! \brief Retrieve the derivative of travel time wrt to source latitude,
//! in seconds/radian.
//!
//! Retrieve the derivative of travel time wrt to source latitude,
//! in seconds/radian.
//! @param dtt_dlat the derivative of travel time wrt to source latitude.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_dtt_dlat(double* dtt_dlat, int* err );

//! \brief Retrieve the derivative of travel time wrt to source longitude,
//! in seconds/radian.
//!
//! Retrieve the derivative of travel time wrt to source longitude,
//! in seconds/radian.
//! @param dtt_dlon the derivative of travel time wrt to source longitude.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_dtt_dlon(double* dtt_dlon, int* err );

//! \brief Retrieve the derivative of travel time wrt to source depth,
//! in seconds/km.
//!
//! Retrieve the derivative of travel time wrt to source depth,
//! in seconds/km.
//! @param dtt_ddepth the derivative of travel time wrt to source depth.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_dtt_ddepth(double* dtt_ddepth, int* err );

////! \brief Retrieve the derivative of horizontal slowness wrt to source-receiver
////! separation, in seconds/radian.
////!
////! Retrieve the derivative of horizontal slowness wrt to source-receiver
////! separation, in seconds/radian.
////! @param dsh_ddist the derivative of horizontal slowness wrt to source-receiver
////! separation, in seconds/radian.
////! @param err "0" if this call was successful, positive error code if this call generated an error.
//SLBM_FORT_SHELL_EXP_IMP void slbm_get_dsh_ddist(double* dsh_ddist, int* err );
//
////! \brief Retrieve the derivative of horizontal slowness wrt to source latitude,
////! in seconds/radian.
////!
////! Retrieve the derivative of horizontal slowness wrt to source latitude,
////! in seconds/radian.
////! @param dsh_dlat the derivative of horizontal slowness wrt to source latitude.
////! @param err "0" if this call was successful, positive error code if this call generated an error.
//SLBM_FORT_SHELL_EXP_IMP void slbm_get_dsh_dlat(double* dsh_dlat, int* err );
//
////! \brief Retrieve the derivative of horizontal slowness wrt to source longitude,
////! in seconds/radian.
////!
////! Retrieve the derivative of horizontal slowness wrt to source longitude,
////! in seconds/radian.
////! @param dsh_dlon the derivative of horizontal slowness wrt to source longitude.
////! @param err "0" if this call was successful, positive error code if this call generated an error.
//SLBM_FORT_SHELL_EXP_IMP void slbm_get_dsh_dlon(double* dsh_dlon, int* err );
//
////! \brief Retrieve the derivative of horizontal slowness wrt to source depth,
////! in seconds/km.
////!
////! Retrieve the derivative of horizontal slowness wrt to source depth,
////! in seconds/km.
////! @param dsh_ddepth the derivative of horizontal slowness wrt to source depth.
////! @param err "0" if this call was successful, positive error code if this call generated an error.
//SLBM_FORT_SHELL_EXP_IMP void slbm_get_dsh_ddepth(double* dsh_ddepth, int* err );

//! \brief Retrieve the horizontal slowness, i.e., the derivative of travel time
//! wrt to receiver-source distance, in seconds/radian.
//!
//! Retrieve the horizontal slowness, in seconds/radian.
//! @param slowness the derivative of travel time wrt to source latitude.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_slowness(double* slowness, int* err );

//! \brief Retrieve uncertainty of the slowness, in seconds/radian
//! for specified phase, distance in radians.
//!
//! Retrieve uncertainty of the slowness, in seconds/radian
//! for specified phase, distance in radians.
//! @param phase Pn = 0, Sn = 1, Pg = 2, Lg = 3
//! @param distance the angular distance in radians
//! @param uncertainty the model uncertainty (seconds) associated with the angular distance and phase
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_slowness_uncertainty( int* phase, double* distance, double* uncertainty, int* err );

//! \brief Retrieve uncertainty of the slowness, in seconds/radian
//! using the phase and distance specified in last call to createGreatCircle().
//!
//! Retrieve uncertainty of the slowness, in seconds/radian
//! using the phase and distance specified in last call to createGreatCircle().
//! @param slowness_uncertainty uncertainty of the slowness, in seconds/radian.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_sh_uncertainty(double* slowness_uncertainty, int* err );

// new sb 8/2011  version 2.7.0
//-------------------------------------------------------------------------

//! \brief Retrieve the latitude  and longitude of the moho pierce point below the source,
//! in radians.
//!
//! Retrieve the latitude  and longitude of the moho pierce point below the source,
//! in radians.  For Pg, Lg and sources in the mantle an exception is thrown.
//! @param lat the latitude of the source pierce point, in radians.
//! @param lon the longitude of the source pierce point, in radians.
//! @param depth moho depth in km below sea level
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP  void slbm_get_pierce_point_source(double* lat, double* lon, double* depth, int* err);

//! \brief Retrieve the latitude  and longitude of the moho pierce point below the receiver,
//! in radians.
//!
//! Retrieve the latitude  and longitude of the moho pierce point below the receiver,
//! in radians.  For Pg, Lg  an exception is thrown.
//! @param lat the latitude of the receiver pierce point, in radians.
//! @param lon the longitude of the receiver pierce point, in radians.
//! @param depth moho depth in km below sea level
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP  void slbm_get_pierce_point_receiver(double* lat, double* lon, double* depth, int* err);

//! \brief Retrieve the latitudes, longitudes and depths of all the profile positions
//! along the moho.
//!
//! Retrieve the latitudes, longitudes and depths of all the profile positions
//! along the moho.  Profile positions are located at the center of each segment
//! of the head wave interface between the source and receiver.  The first position
//! is located path_increment/2 radians from the source, the last profile position is located
//! path_increment/2 radians from the receiver, and the others are spaced path_increment radians apart.
//! @param lat the latitude at the center of each headwave segment, in radians.
//! @param lon the longitude at the center of each headwave segment, in radians.
//! @param depth the depth of the headwave interface at the center of each headwave segment, in km.
//! @param npoints the number of horizontal increments sampled along the
//! head wave interface.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_great_circle_locations (
    double lat[MAX_POINTS], double lon[MAX_POINTS], double depth[MAX_POINTS], int* npoints, int* err);

//! \brief Retrieve an array of lat, lon points along a great circle
//! path between two specified points, a and b.
//!
//! Retrieve an array of lat, lon points along a great circle path
//! between two specified points. The great circle path between a and b is
//! divided into npoints-1 equal size cells and the computed points are
//! located at the boundaries of those cells.  First point will
//! coincide with point a and last point with point b.
//! @param aLat the latitude of the first specified point, in radians.
//! @param aLon the longitude of the first specified point, in radians.
//! @param bLat the latitude of the second specified point, in radians.
//! @param bLon the longitude of the second specified point, in radians.
//! @param npoints the desired number of points along the great circle,
//! in radians.
//! @param latitude the latitudes of the points along the great circle, in radians.
//! @param longitude the longitudes of the points along the great circle, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_great_circle_points (double* aLat, double* aLon,
        double* bLat, double* bLon, int* npoints,
        double latitude[MAX_POINTS], double longitude[MAX_POINTS], int* err);

//! \brief Retrieve an array of lat, lon points along a great circle
//! path between two specified points, a and b.
//!
//! Retrieve an array of lat, lon points along a great circle path
//! between two specified points. The great circle path between a and b is
//! divided into npoints equal size cells and the computed points are
//! located at the centers of those cells.
//! @param aLat the latitude of the first specified point, in radians.
//! @param aLon the longitude of the first specified point, in radians.
//! @param bLat the latitude of the second specified point, in radians.
//! @param bLon the longitude of the second specified point, in radians.
//! @param npoints the desired number of points along the great circle,
//! in radians.
//! @param latitude the latitudes of the points along the great circle, in radians.
//! @param longitude the longitudes of the points along the great circle, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_great_circle_points_on_centers (double* aLat, double* aLon,
        double* bLat, double* bLon, int* npoints,
        double latitude[MAX_POINTS], double longitude[MAX_POINTS], int* err);

//! \brief compute distance and azimuth between two points, A and B
//! (all quantities are in radians).
//!
//! compute distance and azimuth between two points, A and B
//! (all quantities are in radians). Computed distance will range
//! between 0 and PI and azimuth will range from -PI to PI.
//! If distance is zero, or if A is located at north or south
//! pole, azimuth will be set to naValue.
//! @param aLat the latitude of the first specified point, in radians.
//! @param aLon the longitude of the first specified point, in radians.
//! @param bLat the latitude of the second specified point, in radians.
//! @param bLon the longitude of the second specified point, in radians.
//! @param distance from point A to point B, in radians.
//! @param azimuth from point A to point B, in radians.
//! @param naValue value to return if result is invalid, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_dist_az(double* aLat, double* aLon,
                                              double* bLat, double* bLon,
                                              double* distance, double* azimuth,
                                              double* naValue, int* err );

//! \brief Find point B that is the specified distance and azimuth
//! from point A.  All quantities are in radians.
//!
//!Find point B that is the specified distance and azimuth
//! from point A.  All quantities are in radians.
//! @param aLat the latitude of the first specified point, in radians.
//! @param aLon the longitude of the first specified point, in radians.
//! @param distance from point A to point B, in radians.
//! @param azimuth from point A to point B, in radians.
//! @param bLat the latitude of the second specified point, in radians.
//! @param bLon the longitude of the second specified point, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_move_point(double* aLat, double* aLon,
    double* distance, double* azimuth, double* bLat, double* bLon, int* err );

//! \brief Retrieve del_distance in radians.
//!
//! Retrieve current value of del_distance, in radians.  This is the horizontal separation
//! between two points used to compute horizontal slowness and the derivative of travel time
//! with respect to lat and lon.
//! @param delDistance horizontal separation in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_del_distance(double* delDistance, int* err );

//! \brief Set the value of del_distance, radians.
//!
//! Set the value of del_distance, in radians.  This is the horizontal separation
//! between two points used to compute horizontal slowness and the derivative of travel time
//! with respect to lat and lon.
//! @param delDistance horizontal separation in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_del_distance( double* delDistance, int* err );

//! \brief Retrieve del_depth in km.
//!
//! Retrieve current value of del_depth, in km.  This is the vertical separation
//! between two points used to compute the derivative of travel time with respect to depth.
//! @param delDepth vertical separation in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_del_depth(double* delDepth, int* err );

//! \brief Set the value of del_depth, in km.
//!
//! Set the value of del_depth, in km.  This is the vertical separation
//! between two points used to compute the derivative of travel time with respect to depth.
//! @param delDepth vertical separation in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_del_depth( double* delDepth, int* err );

//! \brief Retrieve rayParameter in sec/km.
//!
//! Retrieve the ray parameter in sec/km.
//! @param rayParameter in sec/km
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_rayparameter(double* rayParameter, int* err );

//! \brief Retrieve turning radius in km.
//!
//! Retrieve turning radius in km
//! @param turningRadius in km.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_turningradius(double* turningRadius, int* err );

//! \brief Set the desired spacing of great circle nodes
//! along the head wave interface, in radians.
//!
//! Set the desired spacing of great circle nodes
//! along the head wave interface, in radians.
//! The actual spacing will be
//! reduced from the requested value in order that an integral
//! number of equally spaced LayerProfile objects will exactly
//! span the source-receiver separation.  Defaults to
//! 0.1 degrees if not specified.
//!
//! @param pathIncrement the desired spacing of great circle nodes
//! along the head wave interface, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_path_increment(double* pathIncrement, int* err);

//! \brief Retrieve the current value of the spacing of great circle nodes
//! along the head wave interface, in radians.
//!
//! Retrieve the current value of the spacing of great circle nodes
//! along the head wave interface, in radians.
//! The actual spacing will be
//! reduced from the requested value in order that an integral
//! number of equally spaced LayerProfile objects will exactly
//! span the source-receiver separation.  The default value is 0.1 degrees.
//!
//! @param pathIncrement the current value of the spacing of great circle nodes
//! along the head wave interface, in radians.
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_path_increment(double* pathIncrement, int* err);

//! \brief Specify the interpolation type to use, either
//! 'linear' or 'natural_neighbor'.
//!
//! Specify the interpolation type to use, either
//! "LINEAR" or "NATUTAL_NEIGHBOR".  When using the old
//! SLBMGrid objects, LINEAR is the only option allowed.
//! @param interpolatorType
//! @param size number of characters allocated for interpolatorType
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_set_interpolator_type(const char* interpolatorType, int* size, int* err);

//! \brief Retrieve the type of interpolator currently
//! in use; either "LINEAR" or "NATUTAL_NEIGHBOR".
//! @param interpolatorType
//! @param size number of characters allocated for interpolatorType
//! @param err "0" if this call was successful, positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_get_interpolator_type(char* interpolatorType, int* size, int* err);

SLBM_FORT_SHELL_EXP_IMP void slbm_tostring(char* tostring, int* verbosity, int* size, int* err);

//! \brief Check if two models are equal
//!
//! Check if two models are equal
//! @param modelPath1 /path/to/model1.geotess
//! @param size1 length of modelPath1 stirng
//! @param modelPath2 /path/to/model2.geotess
//! @param size2 length of modelPath2 string
//! @param err "0" if the models are equal, else 1 or a positive error code if this call generated an error.
SLBM_FORT_SHELL_EXP_IMP void slbm_models_equal(const char *modelPath1, const int *size1, const char *modelPath2, const int *size2, int *err);

//-------------------------------------------------------------------------
#ifdef __cplusplus
}
#endif

#endif /* _SLBM_F_SHELL_H */
