!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! FMS is distributed in the hope that it will be useful, !! !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! !! GNU General Public License for more details. !! !! !! !! You should have received a copy of the GNU General Public License !! !! along with FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MODULE diag_axis_mod ! ! Seth Underwood ! ! diag_axis_mod is an integral part ! of diag_manager_mod. It helps to create axis IDs ! that are used in register_diag_field. ! ! Users first create axis ID by calling ! diag_axis_init, then use this axis ID in ! register_diag_field. ! USE mpp_domains_mod, ONLY: domain1d, domain2d, mpp_get_compute_domain& &, mpp_get_domain_components, null_domain1d, null_domain2d,& & OPERATOR(.NE.), mpp_get_global_domain, mpp_get_domain_name USE fms_mod, ONLY: error_mesg, write_version_number, lowercase, uppercase, FATAL USE diag_data_mod, ONLY: diag_axis_type, max_subaxes, max_axes,& & max_num_axis_sets IMPLICIT NONE PRIVATE PUBLIC diag_axis_init, get_diag_axis, get_domain1d, get_domain2d,& & get_axis_length, get_axis_global_length, diag_subaxes_init,& & get_diag_axis_cart, get_diag_axis_data, max_axes, get_axis_aux,& & get_tile_count, get_axes_shift, get_diag_axis_name,& & get_axis_num, get_diag_axis_domain_name ! Module variables ! counter of number of axes defined INTEGER, DIMENSION(:), ALLOCATABLE :: num_subaxes INTEGER :: num_def_axes = 0 ! storage for axis set names CHARACTER(len=128), DIMENSION(:), ALLOCATABLE, SAVE :: Axis_sets INTEGER :: num_axis_sets = 0 ! ---- global storage for all defined axes ---- TYPE(diag_axis_type), ALLOCATABLE, SAVE :: Axes(:) LOGICAL :: module_is_initialized = .FALSE. CHARACTER(len=128) :: version =& & '$Id: diag_axis.F90,v 17.0.4.3 2009/10/05 19:11:50 sdu Exp $' CHARACTER(len=128) :: tagname =& & '$Name: mom4p1_pubrel_dec2009_nnz $' CONTAINS ! ! ! Initialize the axis, and return the axis ID. ! ! ! ! diag_axis_init initializes an axis and returns the axis ID that ! is to be used with register_diag_field. This function also ! increments the axis counter and fills in the axes ! ! Short name for axis ! Array of coordinate values ! Units for the axis ! ! Cartesian axis ("X", "Y", "Z", "T") ! ! ! Indicates the direction of the axis: ! ! ! ! Long name for the axis. ! ! ! Axis ID for the previously defined "edges axis" ! ! ! ! ! Auxiliary name, can only be geolon_t or geolat_t ! ! FUNCTION diag_axis_init(name, DATA, units, cart_name, long_name, direction,& & set_name, edges, Domain, Domain2, aux, tile_count) RESULT (indexx) CHARACTER(len=*), INTENT(in) :: name REAL, DIMENSION(:), INTENT(in) :: DATA CHARACTER(len=*), INTENT(in) :: units CHARACTER(len=*), INTENT(in) :: cart_name CHARACTER(len=*), INTENT(in), OPTIONAL :: long_name, set_name INTEGER, INTENT(in), OPTIONAL :: direction, edges TYPE(domain1d), INTENT(in), OPTIONAL :: Domain TYPE(domain2d), INTENT(in), OPTIONAL :: Domain2 CHARACTER(len=*), INTENT(in), OPTIONAL :: aux INTEGER, INTENT(in), OPTIONAL :: tile_count TYPE(domain1d) :: domain_x, domain_y INTEGER :: indexx, ierr, axlen INTEGER :: i, set, tile INTEGER :: isc, iec, isg, ieg CHARACTER(len=128) :: errmsg IF ( .NOT.module_is_initialized ) THEN CALL write_version_number( version, tagname ) ENDIF IF ( PRESENT(tile_count)) THEN tile = tile_count ELSE tile = 1 END IF ! Allocate the axes IF (.NOT. ALLOCATED(Axis_sets)) ALLOCATE(Axis_sets(max_num_axis_sets)) IF (.NOT. ALLOCATED(Axes)) ALLOCATE(Axes(max_axes)) IF (.NOT. ALLOCATED(num_subaxes)) THEN ALLOCATE(num_subaxes(max_axes)) num_subaxes = 0 END IF !---- is there an axis set? ---- IF ( PRESENT(set_name) ) THEN set = get_axis_set_num (set_name) !---- add new set name ---- IF (set == 0) THEN num_axis_sets = num_axis_sets + 1 IF ( num_axis_sets > max_num_axis_sets ) THEN WRITE (errmsg, FMT='("num_axis_sets (",I2,") exceeds max_num_axis_sets (",I2,"). ")') num_axis_sets, max_num_axis_sets ! ! num_axis_sets () exceeds max_num_axis_sets(). ! Increase max_num_axis_sets via diag_manager_nml. ! CALL error_mesg('diag_axis_mod :: diag_axis_init', & TRIM(errmsg)//' Increase max_num_axis_sets via diag_manager_nml.', FATAL) END IF set = num_axis_sets Axis_sets(set) = set_name END IF ELSE set = 0 END IF !---- see if axis already exists -- ! if this is time axis, return the ID of a previously defined ! if this is spatial axis, FATAL error DO i = 1, num_def_axes IF ( TRIM(name) == Axes(i)%name ) THEN IF ( TRIM(name) == 'Stations' .OR. TRIM(name) == 'Levels') THEN indexx = i RETURN ELSE IF ( set == Axes(i)%set ) THEN IF ( TRIM(lowercase(name)) == 'time' .OR.& & TRIM(lowercase(cart_name)) == 't' .OR.& & TRIM(lowercase(name)) == 'nv' .OR.& & TRIM(lowercase(cart_name)) == 'n' ) THEN indexx = i RETURN ELSE IF ( (lowercase(cart_name) /= 'x' .AND. lowercase(cart_name) /= 'y')& & .OR. tile /= Axes(i)%tile_count) THEN ! axis_name and axis_set already exist. CALL error_mesg('diag_axis_mod :: diag_axis_init',& & 'axis_name '//TRIM(name)//' and axis_set already exist.', FATAL) END IF END IF END IF END DO !---- register axis ---- num_def_axes = num_def_axes + 1 ! max_axes exceeded, increase it via diag_manager_nml IF (num_def_axes > max_axes) CALL error_mesg ('diag_axis_init in& & diag_axis_mod', 'max_axes exceeded, increase it via& & diag_manager_nml', FATAL) indexx = num_def_axes !---- check and then save cart_name name ---- IF ( TRIM(uppercase(cart_name)) == 'X' .OR.& & TRIM(uppercase(cart_name)) == 'Y' .OR.& & TRIM(uppercase(cart_name)) == 'Z' .OR.& & TRIM(uppercase(cart_name)) == 'T' .OR.& & TRIM(uppercase(cart_name)) == 'N' ) THEN Axes(indexx)%cart_name = TRIM(uppercase(cart_name)) ELSE ! Invalid cart_name name. CALL error_mesg('diag_axis_mod :: diag_axis_init', 'Invalid cart_name name.', FATAL) END IF !---- allocate storage for coordinate values of axis ---- IF ( Axes(indexx)%cart_name == 'T' ) THEN axlen = 0 ELSE axlen = SIZE(data(:)) END IF ALLOCATE ( Axes(indexx)%data(1:axlen) ) ! Initialize Axes(indexx) Axes(indexx)%name = TRIM(name) Axes(indexx)%data = data(1:axlen) Axes(indexx)%units = units Axes(indexx)%length = axlen Axes(indexx)%set = set ! start and end are used in subaxes information only Axes(indexx)%start = -1 Axes(indexx)%end = -1 Axes(indexx)%subaxis_name = "" Axes(indexx)%shift = 0 IF ( PRESENT(long_name) ) THEN Axes(indexx)%long_name = long_name ELSE Axes(indexx)%long_name = name END IF IF ( PRESENT(aux) ) THEN Axes(indexx)%aux = TRIM(aux) ELSE Axes(indexx)%aux = 'none' END IF !---- axis direction (-1, 0, or +1) ---- IF ( PRESENT(direction) )THEN IF ( ABS(direction) /= 1 .AND. direction /= 0 )& ! direction must be 0, +1, or -1 & CALL error_mesg('diag_axis_mod :: diag_axis_init',& & 'direction must be 0, +1 or -1',FATAL) Axes(indexx)%direction = direction ELSE Axes(indexx)%direction = 0 END IF !---- domain2d type ---- IF ( PRESENT(Domain2) .AND. PRESENT(Domain)) THEN ! Presence of both Domain and Domain2 at the same time is prohibited CALL error_mesg('diag_axis_mod :: diag_axis_init', & 'Presence of both Domain and Domain2 at the same time is prohibited', & FATAL) ELSE IF ( PRESENT(Domain2) .OR. PRESENT(Domain)) THEN IF ( Axes(indexx)%cart_name /= 'X' .AND. Axes(indexx)%cart_name /= 'Y') THEN ! Domain must not be present for an axis which is not in the X or Y direction. CALL error_mesg('diag_axis_mod :: diag_axis_init', & 'Domain must not be present for an axis which is not in the X or Y direction', & FATAL) END IF END IF Axes(indexx)%tile_count = tile IF ( PRESENT(Domain2) ) THEN Axes(indexx)%Domain2 = Domain2 CALL mpp_get_domain_components(Domain2, domain_x, domain_y, tile_count=tile_count) IF ( Axes(indexx)%cart_name == 'X' ) Axes(indexx)%Domain = domain_x IF ( Axes(indexx)%cart_name == 'Y' ) Axes(indexx)%Domain = domain_y ELSE IF ( PRESENT(Domain)) THEN !---- domain1d type ---- Axes(indexx)%Domain2 = null_domain2d ! needed since not 2-D domain Axes(indexx)%Domain = Domain ELSE Axes(indexx)%Domain2 = null_domain2d Axes(indexx)%Domain = null_domain1d END IF !--- set up the shift value for x-y axis IF ( Axes(indexx)%Domain .NE. null_domain1d ) THEN CALL mpp_get_compute_domain(Axes(indexx)%Domain, isc, iec) CALL mpp_get_global_domain(Axes(indexx)%Domain, isg, ieg) IF ( Axes(indexx)%length == ieg - isg + 2 ) THEN Axes(indexx)%shift = 1 END IF END IF !---- have axis edges been defined ? ---- Axes(indexx)%edges = 0 IF (PRESENT(edges) ) THEN IF ( edges > 0 .AND. edges < num_def_axes ) THEN ierr=0 IF ( Axes(edges)%cart_name /= Axes(indexx)%cart_name) ierr=1 IF ( Axes(edges)%length /= Axes(indexx)%length+1 ) ierr=ierr+2 IF ( Axes(edges)%set /= Axes(indexx)%set ) ierr=ierr+4 IF ( ierr > 0 ) THEN ! Edges axis does not match axis (code _CODE_). WRITE (errmsg,'("Edges axis does not match axis (code ",I1,").")') ierr CALL error_mesg ('diag_axis_mod :: diag_axis_init', errmsg, FATAL) END IF Axes(indexx)%edges = edges ELSE ! Edges axis is not defined. CALL error_mesg ('diag_axis_mod :: diag_axis_init', & 'Edges axis is not defined', FATAL) END IF END IF ! Module is now initialized module_is_initialized = .TRUE. END FUNCTION diag_axis_init ! ! ! ! Create a subaxis on a parent axis. ! ! ! ! Given the ID of a parent axis, create a subaxis and fill it with data, ! and return the ID of the corresponding subaxis. ! ! The subaxis is defined on the parent axis from start_indx ! to end_indx. ! ! ID of the parent axis ! Data of the subaxis ! Start index of the subaxis ! End index of the subaxis ! ! FUNCTION diag_subaxes_init(axis, subdata, start_indx, end_indx, domain_2d) RESULT(index) INTEGER, INTENT(in) :: axis REAL, DIMENSION(:), INTENT(in) :: subdata INTEGER, INTENT(in) :: start_indx INTEGER, INTENT(in) :: end_indx TYPE(domain2d), INTENT(in), OPTIONAL :: domain_2d INTEGER :: index INTEGER :: i, nsub_axis, direction CHARACTER(len=128) :: name, nsub_name CHARACTER(len=128) :: units CHARACTER(len=128) :: cart_name CHARACTER(len=128) :: long_name CHARACTER(len=128) :: errmsg LOGICAL :: subaxis_set ! there may be more than 1 subaxis on a parent axis, check for redundancy nsub_axis = 0 subaxis_set = .FALSE. sa_search: DO i = 1, num_subaxes(axis) IF ( start_indx == Axes(axis)%start(i) .AND. end_indx == Axes(axis)%end(i) ) THEN nsub_axis = i subaxis_set = .TRUE. !subaxis already exists name = TRIM(Axes(axis)%subaxis_name(nsub_axis)) EXIT sa_search END IF END DO sa_search IF ( nsub_axis == 0 ) THEN ! create new subaxis num_subaxes(axis) = num_subaxes(axis) + 1 IF (num_subaxes(axis) > max_subaxes) THEN ! max_subaxes (value ) is too small. Consider increasing max_subaxes. WRITE (errmsg,'("max_subaxes (value ",I4,") is too small. Consider increasing max_subaxes.")') max_subaxes CALL error_mesg ('diag_subaxes_init in diag_axis_mod',errmsg, FATAL) END IF nsub_axis = num_subaxes(axis) Axes(axis)%start(nsub_axis) = start_indx Axes(axis)%end(nsub_axis) = end_indx END IF ! Create new name for the subaxis from name of parent axis ! If subaxis already exists, get the index and return IF(subaxis_set) THEN IF ( Axes(axis)%set > 0 ) THEN index = get_axis_num(name, set_name=TRIM(Axis_sets(Axes(axis)%set))) ELSE index = get_axis_num(name) END IF ELSE ! get a new index for subaxis WRITE (nsub_name,'(I1)') nsub_axis name = TRIM(Axes(axis)%name)//'_sub'//TRIM(nsub_name) Axes(axis)%subaxis_name(nsub_axis) = name long_name = TRIM(Axes(axis)%long_name) units = TRIM(Axes(axis)%units) cart_name = TRIM(Axes(axis)%cart_name) direction = Axes(axis)%direction IF (Axes(axis)%set > 0) THEN index = diag_axis_init (TRIM(name), subdata, TRIM(units), TRIM(cart_name), TRIM(long_name), & set_name=TRIM(Axis_sets(Axes(axis)%set)), direction=direction, Domain2=domain_2d) ELSE index = diag_axis_init (TRIM(name), subdata, TRIM(units), TRIM(cart_name), TRIM(long_name), & direction=direction, Domain2=domain_2d) END IF END IF END FUNCTION diag_subaxes_init ! ! ! ! Return information about the axis with index ID ! ! ! ! Return information about the axis with index ID ! ! Axis ID ! Short name for axis ! Units for axis ! Long name for axis ! ! Cartesian axis ("x", "y", "z", "t"). ! ! ! Direction of data. (See diag_axis_init for a description of ! allowed values) ! ! ! Axis ID for the previously defined "edges axis". ! ! ! ! Array of coordinate values for this axis. ! SUBROUTINE get_diag_axis(id, name, units, long_name, cart_name,& & direction, edges, Domain, data) CHARACTER(len=*), INTENT(out) :: name, units, long_name, cart_name INTEGER, INTENT(in) :: id TYPE(domain1d), INTENT(out) :: Domain INTEGER, INTENT(out) :: direction, edges REAL, DIMENSION(:), INTENT(out) :: DATA CHARACTER(len=128) :: error_msg IF ( id < 1 .OR. id > num_def_axes ) THEN ! Illegal value for axis_id used (value ). WRITE(error_msg,'(i2)')id CALL error_mesg('get_diag_axis in diag_axis_mod', & 'Illegal value for axis_id used (value '//TRIM(error_msg)//').', FATAL) END IF name = Axes(id)%name units = Axes(id)%units long_name = Axes(id)%long_name cart_name = Axes(id)%cart_name direction = Axes(id)%direction edges = Axes(id)%edges Domain = Axes(id)%Domain IF ( Axes(id)%length > SIZE(data(:)) ) THEN ! array data is too small. CALL error_mesg ('get_diag_axis in diag_axis_mod', 'array data is too small', FATAL) ELSE data(1:Axes(id)%length) = Axes(id)%data END IF END SUBROUTINE get_diag_axis ! ! ! ! Return the axis cartesian. ! ! ! ! Return the axis cartesian ('X', 'Y', 'Z' or 'T') for the axis ID given. ! ! Axis ID ! Cartesian axis SUBROUTINE get_diag_axis_cart(id, cart_name) CHARACTER(len=*), INTENT(out) :: cart_name INTEGER, INTENT(in) :: id cart_name = Axes(id)%cart_name END SUBROUTINE get_diag_axis_cart ! ! ! ! Return the axis data. ! ! ! ! Return the axis data for the axis ID given. ! ! Axis ID ! Axis data SUBROUTINE get_diag_axis_data(id, DATA) INTEGER, INTENT(in) :: id REAL, DIMENSION(:), INTENT(out) :: DATA IF (Axes(id)%length > SIZE(data(:))) THEN ! array data is too small CALL error_mesg ('get_diag_axis_data in diag_axis_mod', 'array data is too small', FATAL) ELSE data(1:Axes(id)%length) = Axes(id)%data END IF END SUBROUTINE get_diag_axis_data ! ! ! ! Return the short name of the axis. ! ! ! ! Return the short name for the axis ID given. ! ! Axis ID ! Axis short name SUBROUTINE get_diag_axis_name (id, name) INTEGER , INTENT(in) :: id CHARACTER(len=*), INTENT(out) :: name CHARACTER(len=128) :: error_msg IF (id < 1 .OR. id > num_def_axes) THEN ! Illegal value for axis used (value ). WRITE(error_msg,'(i2)')id CALL error_mesg('get_diag_axis_name in diag_axis_mod', & 'Illegal value for axis_id used (value '//TRIM(error_msg)//').', FATAL) ELSE name = Axes(id)%name END IF END SUBROUTINE get_diag_axis_name ! ! ! ! Return the name of the axis' domain ! ! ! ! Retruns the name of the axis' domain. ! ! Axis ID ! Axis' domain name SUBROUTINE get_diag_axis_domain_name(id, name) INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(out) :: name CHARACTER(len=128) :: error_msg IF (id <1 .OR. id > num_def_axes) THEN ! ! Illegal value for axis used (value ). ! WRITE (error_msg, '(I2)') id CALL error_mesg('get_diag_axis_domain_name::diag_axis_mod',& & 'Illegal value for axis_id used (value '& &//TRIM(error_msg)//').', FATAL) END IF name = mpp_get_domain_name(Axes(id)%domain2) END SUBROUTINE get_diag_axis_domain_name ! ! ! ! Return the length of the axis. ! ! ! ! Return the length of the axis ID given. ! ! Axis ID INTEGER FUNCTION get_axis_length(id) INTEGER, INTENT(in) :: id INTEGER :: length IF ( Axes(id)%Domain .NE. null_domain1d ) THEN CALL mpp_get_compute_domain(Axes(id)%Domain,size=length) !---one extra point is needed for some case. ( like symmetry domain ) get_axis_length = length + Axes(id)%shift ELSE get_axis_length = Axes(id)%length END IF END FUNCTION get_axis_length ! ! ! ! Return the auxiliary name for the axis. ! ! ! ! Returns the auxiliary name for the axis. The only possible values for ! the auxiliary names is geolon_t or geolat_t. ! ! Axis ID FUNCTION get_axis_aux (id) RESULT (aux) INTEGER, INTENT(in) :: id CHARACTER(len=128) :: aux aux = Axes(id)%aux END FUNCTION get_axis_aux ! ! ! ! Return the global length of the axis. ! ! ! ! Returns the global length of the axis ID given. ! ! Axis ID FUNCTION get_axis_global_length(id) RESULT (length) INTEGER, INTENT(in) :: id INTEGER :: length length = Axes(id)%length END FUNCTION get_axis_global_length ! ! ! ! Return the tile count for the axis. ! ! ! ! Return the tile count for the axis IDs given. ! ! ! Axis IDs. Possible dimensions: 1 <= size(ids(:)) <= 4. ! FUNCTION get_tile_count(ids) RESULT (tile_count) INTEGER, DIMENSION(:), INTENT(in) :: ids INTEGER :: tile_count INTEGER :: i, id, flag IF ( SIZE(ids(:)) < 1 ) THEN ! input argument has incorrect size. CALL error_mesg ('get_tile_count in diag_axis_mod', 'input argument has incorrect size', FATAL) END IF tile_count = 1 flag = 0 DO i = 1, SIZE(ids(:)) id = ids(i) IF ( Axes(id)%cart_name == 'X' .OR. & Axes(id)%cart_name == 'Y' ) flag = flag + 1 ! --- both x/y axes found --- IF ( flag == 2 ) THEN tile_count = Axes(id)%tile_count EXIT END IF END DO END FUNCTION get_tile_count ! ! ! ! Return the 1D domain. ! ! ! ! Retrun the 1D domain for the axis ID given. ! ! Axis ID FUNCTION get_domain1d(id) RESULT (Domain1) INTEGER, INTENT(in) :: id TYPE(domain1d) :: Domain1 IF (Axes(id)%Domain .NE. NULL_DOMAIN1D) THEN Domain1 = Axes(id)%Domain ELSE Domain1 = NULL_DOMAIN1D ENDIF END FUNCTION get_domain1d ! ! ! ! Return the 2D domain. ! ! ! ! Return the 2D domain for the axis IDs given. ! ! ! Axis IDs. Possible dimensions: 1 <= size(ids(:)) <= 4. ! FUNCTION get_domain2d(ids) RESULT (Domain2) INTEGER, DIMENSION(:), INTENT(in) :: ids TYPE(domain2d) :: Domain2 INTEGER :: i, id, flag IF ( SIZE(ids(:)) < 1 ) THEN ! input argument has incorrect size. CALL error_mesg ('get_domain2d in diag_axis_mod', 'input argument has incorrect size', FATAL) END IF Domain2 = null_domain2d flag = 0 DO i = 1, SIZE(ids(:)) id = ids(i) IF ( Axes(id)%cart_name == 'X' .OR. Axes(id)%cart_name == 'Y' ) flag = flag + 1 ! --- both x/y axes found --- IF ( flag == 2 ) THEN IF (Axes(id)%Domain2 .NE. NULL_DOMAIN2D) Domain2 = Axes(id)%Domain2 EXIT END IF END DO END FUNCTION get_domain2d ! ! ! ! Return the value of the shift. ! ! ! ! Return the value of the shift for the axis IDs given. ! ! ! Axis IDs. Possible dimensions: 1 <= size(ids(:)) <= 4 ! ! X shift value. ! Y shift value. SUBROUTINE get_axes_shift(ids, ishift, jshift) INTEGER, DIMENSION(:), INTENT(in) :: ids INTEGER, INTENT(out) :: ishift, jshift INTEGER :: i, id !-- get the value of the shift. ishift = 0 jshift = 0 DO i = 1, SIZE(ids(:)) id = ids(i) SELECT CASE (Axes(id)%cart_name) CASE ( 'X' ) ishift = Axes(id)%shift CASE ( 'Y' ) jshift = Axes(id)%shift END SELECT END DO END SUBROUTINE get_axes_shift ! ! ! ! ! Returns index into axis table corresponding to a given axis name. ! ! ! ! Returns index into axis table corresponding to a given axis name. ! ! Axis name. ! Set name. FUNCTION get_axis_num(axis_name, set_name) RESULT (num) CHARACTER(len=*), INTENT(in) :: axis_name CHARACTER(len=*), INTENT(in), OPTIONAL :: set_name INTEGER :: num, set, n IF ( PRESENT(set_name) ) THEN set = get_axis_set_num (TRIM(set_name)) ELSE set = 0 END IF num = 0 DO n = 1, num_def_axes IF ( TRIM(axis_name) == TRIM(Axes(n)%name) .AND. Axes(n)%set == set ) THEN num = n RETURN END IF END DO END FUNCTION get_axis_num ! ! ! ! ! ! Returns index in axis set table corresponding to a given axis set name. ! ! ! ! Returns index in axis set table corresponding to a given axis set name. ! ! Set name. FUNCTION get_axis_set_num (set_name) RESULT (num) CHARACTER(len=*), INTENT(in) :: set_name INTEGER :: num, iset num = 0 DO iset = 1, num_axis_sets IF (set_name == Axis_sets(iset))THEN num = iset RETURN END IF END DO END FUNCTION get_axis_set_num ! ! END MODULE diag_axis_mod