!---------------------------------------------------------------------- ! NEMO system team, System and Interface for oceanic RElocable Nesting !---------------------------------------------------------------------- ! ! MODULE: att ! ! DESCRIPTION: !> @brief !> This module manage attribute of variable or file. !> !> @details !> define type TATT:
!> @code !> TYPE(TATT) :: tl_att !> @endcode !> !> the attribute value inside attribute structure will be !> character or real(8) 1D array.
!> However the attribute value could be initialized with:
!> - character !> - scalar (real(4), real(8), integer(4) or integer(8)) !> - array 1D (real(4), real(8), integer(4) or integer(8)) !> !> to initialize an attribute structure :
!> @code !> tl_att=att_init('attname',value) !> @endcode !> - value is a character, scalar value or table of value !> !> to print attribute information of one or array of attribute structure:
!> @code !> CALL att_print(td_att) !> @endcode !> !> to clean attribute structure:
!> @code !> CALL att_clean(td_att) !> @endcode !> !> to copy attribute structure in another one (using different memory cell):
!> @code !> tl_att2=att_copy(tl_att1) !> @endcode !> @note as we use pointer for the value array of the attribute structure, !> the use of the assignment operator (=) to copy attribute structure !> create a pointer on the same array. !> This is not the case with this copy function. !> !> to get attribute index, in an array of attribute structure:
!> @code !> il_index=att_get_index( td_att, cd_name ) !> @endcode !> - td_att array of attribute structure !> - cd_name attribute name !> !> to get attribute id, read from a file:
!>@code !> il_id=att_get_id( td_att, cd_name ) !>@endcode !> - td_att array of attribute structure !> - cd_name attribute name !> !> to get attribute name !> - tl_att\%c_name !> !> to get character length or the number of value store in attribute !> - tl_att\%i_len !> !> to get attribute value:
!> - tl_att\%c_value (for character attribute) !> - tl_att\%d_value(i) (otherwise) !> !> to get the type number (based on NETCDF type constants) of the !> attribute:
!> - tl_att\%i_type !> !> to get attribute id (read from file):
!> - tl_att\%i_id !> !> @author J.Paul ! REVISION HISTORY: !> @date November, 2013 - Initial Version !> @date November, 2014 - Fix memory leaks bug ! !> @note Software governed by the CeCILL licence (NEMOGCM/NEMO_CeCILL.txt) !---------------------------------------------------------------------- MODULE att USE netcdf ! nf90 library USE global ! global variable USE kind ! F90 kind parameter USE logger ! log file manager USE fct ! basic useful function IMPLICIT NONE ! NOTE_avoid_public_variables_if_possible ! type and variable PUBLIC :: TATT !< attribute structure ! function and subroutine PUBLIC :: att_init !< initialize attribute structure PUBLIC :: att_print !< print attribute structure PUBLIC :: att_clean !< clean attribute strcuture PUBLIC :: att_copy !< copy attribute structure PUBLIC :: att_get_index !< get attribute index, in an array of attribute structure PUBLIC :: att_get_id !< get attribute id, read from file PRIVATE :: att__clean_unit ! clean attribute strcuture PRIVATE :: att__clean_arr ! clean array of attribute strcuture PRIVATE :: att__print_unit ! print information on one attribute PRIVATE :: att__print_arr ! print information on a array of attribute PRIVATE :: att__init_c ! initialize an attribute structure with character value PRIVATE :: att__init_dp ! initialize an attribute structure with array of real(8) value PRIVATE :: att__init_dp_0d ! initialize an attribute structure with real(8) value PRIVATE :: att__init_sp ! initialize an attribute structure with array of real(4) value PRIVATE :: att__init_sp_0d ! initialize an attribute structure with real(4) value PRIVATE :: att__init_i1 ! initialize an attribute structure with array of integer(1) value PRIVATE :: att__init_i1_0d ! initialize an attribute structure with integer(1) value PRIVATE :: att__init_i2 ! initialize an attribute structure with array of integer(2) value PRIVATE :: att__init_i2_0d ! initialize an attribute structure with integer(2) value PRIVATE :: att__init_i4 ! initialize an attribute structure with array of integer(4) value PRIVATE :: att__init_i4_0d ! initialize an attribute structure with integer(4) value PRIVATE :: att__init_i8 ! initialize an attribute structure with array of integer(8) value PRIVATE :: att__init_i8_0d ! initialize an attribute structure with integer(8) value PRIVATE :: att__copy_unit ! copy attribute structure PRIVATE :: att__copy_arr ! copy array of attribute structure TYPE TATT !< attribute structure CHARACTER(LEN=lc) :: c_name = '' !< attribute name INTEGER(i4) :: i_id = 0 !< attribute id INTEGER(i4) :: i_type = 0 !< attribute type INTEGER(i4) :: i_len = 0 !< number of value store in attribute CHARACTER(LEN=lc) :: c_value = "none" !< attribute value if type CHAR REAL(dp), DIMENSION(:), POINTER :: d_value => NULL() !< attribute value if type SHORT,INT,FLOAT or DOUBLE END TYPE TATT INTERFACE att_init MODULE PROCEDURE att__init_c MODULE PROCEDURE att__init_dp MODULE PROCEDURE att__init_dp_0d MODULE PROCEDURE att__init_sp MODULE PROCEDURE att__init_sp_0d MODULE PROCEDURE att__init_i1 MODULE PROCEDURE att__init_i1_0d MODULE PROCEDURE att__init_i2 MODULE PROCEDURE att__init_i2_0d MODULE PROCEDURE att__init_i4 MODULE PROCEDURE att__init_i4_0d MODULE PROCEDURE att__init_i8 MODULE PROCEDURE att__init_i8_0d END INTERFACE att_init INTERFACE att_print MODULE PROCEDURE att__print_unit ! print information on one attribute MODULE PROCEDURE att__print_arr ! print information on a array of attribute END INTERFACE att_print INTERFACE att_clean MODULE PROCEDURE att__clean_unit MODULE PROCEDURE att__clean_arr END INTERFACE INTERFACE att_copy MODULE PROCEDURE att__copy_unit ! copy attribute structure MODULE PROCEDURE att__copy_arr ! copy array of attribute structure END INTERFACE CONTAINS !------------------------------------------------------------------- !> @brief !> This subroutine copy a array of attribute structure in another one !> @details !> see att__copy_unit !> !> @warning do not use on the output of a function who create or read an !> attribute (ex: tl_att=att_copy(att_init()) is forbidden). !> This will create memory leaks. !> @warning to avoid infinite loop, do not use any function inside !> this subroutine !> !> @author J.Paul !> @date November, 2013 - Initial Version !> @date November, 2014 !> - use function instead of overload assignment operator !> (to avoid memory leak) ! !> @param[in] td_att array of attribute structure !> @return copy of input array of attribute structure !------------------------------------------------------------------- FUNCTION att__copy_arr( td_att ) IMPLICIT NONE ! Argument TYPE(TATT), DIMENSION(:), INTENT(IN) :: td_att ! function TYPE(TATT), DIMENSION(SIZE(td_att(:))) :: att__copy_arr ! local variable ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- DO ji=1,SIZE(td_att(:)) att__copy_arr(ji)=att_copy(td_att(ji)) ENDDO END FUNCTION att__copy_arr !------------------------------------------------------------------- !> @brief !> This subroutine copy an attribute structure in another one. !> @details !> attribute value are copied in a temporary array, so input and output !> attribute structure value do not point on the same "memory cell", and so !> on are independant. !> !> @warning do not use on the output of a function who create or read an !> attribute (ex: tl_att=att_copy(att_init()) is forbidden). !> This will create memory leaks. !> @warning to avoid infinite loop, do not use any function inside !> this subroutine !> !> @author J.Paul !> @date November, 2013 - Initial Version !> @date November, 2014 !> - use function instead of overload assignment operator (to avoid memory leak) !> !> @param[in] td_att attribute structure !> @return copy of input attribute structure !------------------------------------------------------------------- FUNCTION att__copy_unit( td_att ) IMPLICIT NONE ! Argument TYPE(TATT), INTENT(IN) :: td_att ! function TYPE(TATT) :: att__copy_unit ! local variable REAL(dp), DIMENSION(:), ALLOCATABLE :: dl_value !---------------------------------------------------------------- ! copy attribute variable att__copy_unit%c_name = TRIM(td_att%c_name) att__copy_unit%i_id = td_att%i_id att__copy_unit%i_type = td_att%i_type att__copy_unit%i_len = td_att%i_len att__copy_unit%c_value = TRIM(td_att%c_value) ! copy attribute pointer in an independant variable IF( ASSOCIATED(att__copy_unit%d_value) ) DEALLOCATE(att__copy_unit%d_value) IF( ASSOCIATED(td_att%d_value) )THEN ALLOCATE( dl_value(td_att%i_len) ) dl_value(:) = td_att%d_value(:) ALLOCATE( att__copy_unit%d_value(att__copy_unit%i_len) ) att__copy_unit%d_value(:) = dl_value(:) DEALLOCATE( dl_value ) ENDIF END FUNCTION att__copy_unit !------------------------------------------------------------------- !> @brief This function return attribute index, in a array of attribute structure, !> given attribute name.
!> @details !> if attribute name do not exist, return 0. !> !> @author J.Paul !> @date Septempber, 2014 - Initial Version ! !> @param[in] td_att array of attribute structure !> @param[in] cd_name attribute name !> @return attribute index !------------------------------------------------------------------- INTEGER(i4) FUNCTION att_get_index( td_att, cd_name ) IMPLICIT NONE ! Argument TYPE(TATT), DIMENSION(:), INTENT(IN) :: td_att CHARACTER(LEN=*), INTENT(IN) :: cd_name ! local variable INTEGER(i4) :: il_size ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- att_get_index=0 il_size=SIZE(td_att(:)) DO ji=1,il_size IF( TRIM(td_att(ji)%c_name) == TRIM(cd_name) )THEN att_get_index=ji EXIT ENDIF ENDDO END FUNCTION att_get_index !------------------------------------------------------------------- !> @brief This function return attribute id, read from a file.
!> @details !> if attribute name do not exist, return 0. !> !> @author J.Paul !> @date November, 2013 - Initial Version !> @date September, 2014 - bug fix with use of id read from attribute structure ! !> @param[in] td_att array of attribute structure !> @param[in] cd_name attribute name !> @return attribute id !------------------------------------------------------------------- INTEGER(i4) FUNCTION att_get_id( td_att, cd_name ) IMPLICIT NONE ! Argument TYPE(TATT), DIMENSION(:), INTENT(IN) :: td_att CHARACTER(LEN=*), INTENT(IN) :: cd_name ! local variable INTEGER(i4) :: il_size ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- att_get_id=0 il_size=SIZE(td_att(:)) DO ji=1,il_size IF( TRIM(td_att(ji)%c_name) == TRIM(cd_name) )THEN att_get_id=td_att(ji)%i_id EXIT ENDIF ENDDO END FUNCTION att_get_id !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with character !> value. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] cd_value attribute value !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_c( cd_name, cd_value ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name CHARACTER(LEN=*), INTENT(IN) :: cd_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_c) CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cd_value)) ) att__init_c%c_name=TRIM(ADJUSTL(cd_name)) att__init_c%i_type=NF90_CHAR att__init_c%c_value=TRIM(ADJUSTL(cd_value)) att__init_c%i_len=LEN( TRIM(ADJUSTL(cd_value)) ) END FUNCTION att__init_c !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of real(8) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @dtae November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] dd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_dp( cd_name, dd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name REAL(dp), DIMENSION(:), INTENT(IN) :: dd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_dp) ! array size il_len=size(dd_value(:)) cl_value="(/" DO ji=1,il_len-1 cl_value=TRIM(cl_value)//TRIM(fct_str(dd_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(dd_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_dp%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_dp%i_type=id_type ELSE att__init_dp%i_type=NF90_DOUBLE ENDIF IF( ASSOCIATED(att__init_dp%d_value) )THEN DEALLOCATE(att__init_dp%d_value) ENDIF ALLOCATE(att__init_dp%d_value(il_len)) att__init_dp%d_value(:)=dd_value(:) att__init_dp%i_len=il_len END FUNCTION att__init_dp !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> real(8) value !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] dd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_dp_0d( cd_name, dd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name REAL(dp), INTENT(IN) :: dd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_dp_0d) cl_value="(/"//TRIM(fct_str(dd_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_dp_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_dp_0d%i_type=id_type ELSE att__init_dp_0d%i_type=NF90_DOUBLE ENDIF IF( ASSOCIATED(att__init_dp_0d%d_value) )THEN DEALLOCATE(att__init_dp_0d%d_value) ENDIF ALLOCATE(att__init_dp_0d%d_value(1)) att__init_dp_0d%d_value(1)=dd_value att__init_dp_0d%i_len=1 END FUNCTION att__init_dp_0d !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of real(4) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] rd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_sp( cd_name, rd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name REAL(sp), DIMENSION(:), INTENT(IN) :: rd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_sp) ! array size il_len=size(rd_value(:)) cl_value="(/" DO ji=1,il_len-1 cl_value=TRIM(cl_value)//TRIM(fct_str(rd_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(rd_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_sp%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_sp%i_type=id_type ELSE att__init_sp%i_type=NF90_FLOAT ENDIF IF( ASSOCIATED(att__init_sp%d_value) )THEN DEALLOCATE(att__init_sp%d_value) ENDIF ALLOCATE(att__init_sp%d_value(il_len)) att__init_sp%d_value(:)=REAL(rd_value(:),dp) att__init_sp%i_len=il_len END FUNCTION att__init_sp !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> real(4) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] rd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_sp_0d( cd_name, rd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name REAL(sp), INTENT(IN) :: rd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_sp_0d) cl_value="(/"//TRIM(fct_str(rd_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_sp_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_sp_0d%i_type=id_type ELSE att__init_sp_0d%i_type=NF90_FLOAT ENDIF IF( ASSOCIATED(att__init_sp_0d%d_value) )THEN DEALLOCATE(att__init_sp_0d%d_value) ENDIF ALLOCATE(att__init_sp_0d%d_value(1)) att__init_sp_0d%d_value(1)=REAL(rd_value,dp) att__init_sp_0d%i_len=1 END FUNCTION att__init_sp_0d !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of integer(1) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] bd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i1( cd_name, bd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i1), DIMENSION(:), INTENT(IN) :: bd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i1) ! array size il_len=size(bd_value(:)) cl_value="(/" DO ji=1,il_len-1 cl_value=TRIM(cl_value)//TRIM(fct_str(bd_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(bd_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i1%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i1%i_type=id_type ELSE att__init_i1%i_type=NF90_BYTE ENDIF IF( ASSOCIATED(att__init_i1%d_value) )THEN DEALLOCATE(att__init_i1%d_value) ENDIF ALLOCATE(att__init_i1%d_value(il_len)) att__init_i1%d_value(:)=REAL(bd_value(:),dp) att__init_i1%i_len=il_len END FUNCTION att__init_i1 !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> integer(1) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] bd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i1_0d( cd_name, bd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i1), INTENT(IN) :: bd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type !local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i1_0d) cl_value="(/"//TRIM(fct_str(bd_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attibute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i1_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i1_0d%i_type=id_type ELSE att__init_i1_0d%i_type=NF90_BYTE ENDIF IF( ASSOCIATED(att__init_i1_0d%d_value) )THEN DEALLOCATE(att__init_i1_0d%d_value) ENDIF ALLOCATE(att__init_i1_0d%d_value(1)) att__init_i1_0d%d_value(1)=REAL(bd_value,dp) att__init_i1_0d%i_len=1 END FUNCTION att__init_i1_0d !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of integer(2) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] sd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i2( cd_name, sd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i2), DIMENSION(:), INTENT(IN) :: sd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i2) ! array size il_len=size(sd_value(:)) cl_value="(/" DO ji=1,il_len-1 cl_value=TRIM(cl_value)//TRIM(fct_str(sd_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(sd_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i2%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i2%i_type=id_type ELSE att__init_i2%i_type=NF90_SHORT ENDIF IF( ASSOCIATED(att__init_i2%d_value) )THEN DEALLOCATE(att__init_i2%d_value) ENDIF ALLOCATE(att__init_i2%d_value(il_len)) att__init_i2%d_value(:)=REAL(sd_value(:),dp) att__init_i2%i_len=il_len END FUNCTION att__init_i2 !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> integer(2) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] sd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i2_0d( cd_name, sd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i2), INTENT(IN) :: sd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type !local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i2_0d) cl_value="(/"//TRIM(fct_str(sd_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attibute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i2_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i2_0d%i_type=id_type ELSE att__init_i2_0d%i_type=NF90_SHORT ENDIF IF( ASSOCIATED(att__init_i2_0d%d_value) )THEN DEALLOCATE(att__init_i2_0d%d_value) ENDIF ALLOCATE(att__init_i2_0d%d_value(1)) att__init_i2_0d%d_value(1)=REAL(sd_value,dp) att__init_i2_0d%i_len=1 END FUNCTION att__init_i2_0d !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of integer(4) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] id_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i4( cd_name, id_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i4), DIMENSION(:), INTENT(IN) :: id_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i4) ! array size il_len=size(id_value(:)) cl_value="(/" DO ji=1,il_len-1 cl_value=TRIM(cl_value)//TRIM(fct_str(id_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(id_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attribute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i4%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i4%i_type=id_type ELSE att__init_i4%i_type=NF90_INT ENDIF IF( ASSOCIATED(att__init_i4%d_value) )THEN DEALLOCATE(att__init_i4%d_value) ENDIF ALLOCATE(att__init_i4%d_value(il_len)) att__init_i4%d_value(:)=REAL(id_value(:),dp) att__init_i4%i_len=il_len END FUNCTION att__init_i4 !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> integer(4) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version !> !> @param[in] cd_name attribute name !> @param[in] id_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i4_0d( cd_name, id_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i4), INTENT(IN) :: id_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type !local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i4_0d) cl_value="(/"//TRIM(fct_str(id_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attibute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i4_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i4_0d%i_type=id_type ELSE att__init_i4_0d%i_type=NF90_INT ENDIF IF( ASSOCIATED(att__init_i4_0d%d_value) )THEN DEALLOCATE(att__init_i4_0d%d_value) ENDIF ALLOCATE(att__init_i4_0d%d_value(1)) att__init_i4_0d%d_value(1)=REAL(id_value,dp) att__init_i4_0d%i_len=1 END FUNCTION att__init_i4_0d !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with array !> of integer(8) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] kd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i8( cd_name, kd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i8), DIMENSION(:), INTENT(IN) :: kd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value INTEGER(i4) :: il_len CHARACTER(LEN=lc) :: cl_value ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i8) ! array size il_len=size(kd_value(:)) cl_value="(/" DO ji=1,il_len cl_value=TRIM(cl_value)//TRIM(fct_str(kd_value(ji)))//"," ENDDO cl_value=TRIM(cl_value)//TRIM(fct_str(kd_value(il_len)))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attibute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i8%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i8%i_type=id_type ELSE att__init_i8%i_type=NF90_INT ENDIF IF( ASSOCIATED(att__init_i8%d_value) )THEN DEALLOCATE(att__init_i8%d_value) ENDIF ALLOCATE(att__init_i8%d_value(il_len)) att__init_i8%d_value(:)=REAL(kd_value(:),dp) att__init_i8%i_len=il_len END FUNCTION att__init_i8 !------------------------------------------------------------------- !> @brief This function initialize an attribute structure with !> integer(8) value. !> @details !> Optionaly you could specify the type of the variable to be saved. !> !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[in] cd_name attribute name !> @param[in] kd_value attribute value !> @param[in] id_type type of the variable to be saved !> @return attribute structure !------------------------------------------------------------------- TYPE(TATT) FUNCTION att__init_i8_0d( cd_name, kd_value, id_type ) IMPLICIT NONE ! Argument CHARACTER(LEN=*), INTENT(IN) :: cd_name INTEGER(i8), INTENT(IN) :: kd_value INTEGER(i4) , INTENT(IN), OPTIONAL :: id_type ! local value CHARACTER(LEN=lc) :: cl_value !---------------------------------------------------------------- ! clean attribute CALL att_clean(att__init_i8_0d) cl_value="(/"//TRIM(fct_str(kd_value))//"/)" CALL logger_trace( & & " ATT INIT: attribute name: "//TRIM(ADJUSTL(cd_name))//& & " attibute value "//TRIM(ADJUSTL(cl_value)) ) att__init_i8_0d%c_name=TRIM(ADJUSTL(cd_name)) IF( PRESENT(id_type) )THEN att__init_i8_0d%i_type=id_type ELSE att__init_i8_0d%i_type=NF90_INT ENDIF IF( ASSOCIATED(att__init_i8_0d%d_value) )THEN DEALLOCATE(att__init_i8_0d%d_value) ENDIF ALLOCATE(att__init_i8_0d%d_value(1)) att__init_i8_0d%d_value(1)=REAL(kd_value,dp) att__init_i8_0d%i_len=1 END FUNCTION att__init_i8_0d !------------------------------------------------------------------- !> @brief This subroutine print informations of an array of attribute. !> !> @author J.Paul !> @date June, 2014 - Initial Version !> !> @param[in] td_att array of attribute structure !------------------------------------------------------------------- SUBROUTINE att__print_arr(td_att) IMPLICIT NONE ! Argument TYPE(TATT), DIMENSION(:), INTENT(IN) :: td_att ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- DO ji=1,SIZE(td_att(:)) CALL att_print(td_att(ji)) ENDDO END SUBROUTINE att__print_arr !------------------------------------------------------------------- !> @brief This subroutine print attribute information. !> !> @author J.Paul !> @date November, 2013 - Initial Version !> @date September, 2014 - take into account type of attribute. ! !> @param[in] td_att attribute structure !------------------------------------------------------------------- SUBROUTINE att__print_unit(td_att) IMPLICIT NONE ! Argument TYPE(TATT), INTENT(IN) :: td_att ! local vairbale CHARACTER(LEN=lc) :: cl_type CHARACTER(LEN=lc) :: cl_value INTEGER(i8) :: kl_tmp INTEGER(i2) :: sl_tmp INTEGER(i1) :: bl_tmp REAL(sp) :: rl_tmp REAL(dp) :: dl_tmp ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- SELECT CASE( td_att%i_type ) CASE(NF90_CHAR) cl_type='CHAR' CASE(NF90_BYTE) cl_type='BYTE' CASE(NF90_SHORT) cl_type='SHORT' CASE(NF90_INT) cl_type='INT' CASE(NF90_FLOAT) cl_type='FLOAT' CASE(NF90_DOUBLE) cl_type='DOUBLE' CASE DEFAULT cl_type='' END SELECT SELECT CASE( td_att%i_type ) CASE(NF90_CHAR) cl_value=td_att%c_value CASE(NF90_BYTE) IF( td_att%i_len > 1 )THEN cl_value='(/' DO ji=1,td_att%i_len-1 bl_tmp=INT(td_att%d_value(ji),i1) cl_value=TRIM(cl_value)//TRIM(fct_str(bl_tmp))//',' ENDDO bl_tmp=INT(td_att%d_value(td_att%i_len),i1) cl_value=TRIM(cl_value)//TRIM(fct_str(bl_tmp))//'/)' ELSE cl_value='(/'//TRIM(fct_str(td_att%d_value(1)))//'/)' ENDIF CASE(NF90_SHORT) IF( td_att%i_len > 1 )THEN cl_value='(/' DO ji=1,td_att%i_len-1 sl_tmp=INT(td_att%d_value(ji),i2) cl_value=TRIM(cl_value)//TRIM(fct_str(sl_tmp))//',' ENDDO sl_tmp=INT(td_att%d_value(td_att%i_len),i2) cl_value=TRIM(cl_value)//TRIM(fct_str(sl_tmp))//'/)' ELSE cl_value='(/'//TRIM(fct_str(td_att%d_value(1)))//'/)' ENDIF CASE(NF90_INT) IF( td_att%i_len > 1 )THEN cl_value='(/' DO ji=1,td_att%i_len-1 kl_tmp=INT(td_att%d_value(ji),i8) cl_value=TRIM(cl_value)//TRIM(fct_str(kl_tmp))//',' ENDDO kl_tmp=INT(td_att%d_value(td_att%i_len),i8) cl_value=TRIM(cl_value)//TRIM(fct_str(kl_tmp))//'/)' ELSE cl_value='(/'//TRIM(fct_str(td_att%d_value(1)))//'/)' ENDIF CASE(NF90_FLOAT) IF( td_att%i_len > 1 )THEN cl_value='(/' DO ji=1,td_att%i_len-1 rl_tmp=REAL(td_att%d_value(ji),sp) cl_value=TRIM(cl_value)//TRIM(fct_str(rl_tmp))//',' ENDDO rl_tmp=REAL(td_att%d_value(td_att%i_len),sp) cl_value=TRIM(cl_value)//TRIM(fct_str(rl_tmp))//'/)' ELSE cl_value='(/'//TRIM(fct_str(td_att%d_value(1)))//'/)' ENDIF CASE(NF90_DOUBLE) IF( td_att%i_len > 1 )THEN cl_value='(/' DO ji=1,td_att%i_len-1 dl_tmp=REAL(td_att%d_value(ji),dp) cl_value=TRIM(cl_value)//TRIM(fct_str(dl_tmp))//',' ENDDO dl_tmp=REAL(td_att%d_value(td_att%i_len),dp) cl_value=TRIM(cl_value)//TRIM(fct_str(dl_tmp))//'/)' ELSE cl_value='(/'//TRIM(fct_str(td_att%d_value(1)))//'/)' ENDIF CASE DEFAULT cl_value="none" END SELECT WRITE(*,'((3x,a,a),(/6x,a,i2.2),(a,a),(a,a))')& & " attribute : ",TRIM(ADJUSTL(td_att%c_name)), & & " id : ",td_att%i_id, & & " type : ",TRIM(ADJUSTL(cl_type)), & & " value : ",TRIM(ADJUSTL(cl_value)) END SUBROUTINE att__print_unit !------------------------------------------------------------------- !> @brief !> This subroutine clean attribute strcuture. ! !> @author J.Paul !> @date November, 2013 - Initial Version ! !> @param[inout] td_att attribute strcuture !------------------------------------------------------------------- SUBROUTINE att__clean_unit( td_att ) IMPLICIT NONE ! Argument TYPE(TATT), INTENT(INOUT) :: td_att ! local variable TYPE(TATT) :: tl_att ! empty attribute structure !---------------------------------------------------------------- CALL logger_trace( & & " CLEAN: reset attribute "//TRIM(td_att%c_name) ) IF( ASSOCIATED(td_att%d_value) )THEN ! clean value DEALLOCATE(td_att%d_value) ENDIF ! replace by empty structure td_att=att_copy(tl_att) END SUBROUTINE att__clean_unit !------------------------------------------------------------------- !> @brief !> This subroutine clean array of attribute strcuture. ! !> @author J.Paul !> @date September, 2014 - Initial Version ! !> @param[inout] td_att attribute strcuture !------------------------------------------------------------------- SUBROUTINE att__clean_arr( td_att ) IMPLICIT NONE ! Argument TYPE(TATT), DIMENSION(:), INTENT(INOUT) :: td_att ! local variable ! loop indices INTEGER(i4) :: ji !---------------------------------------------------------------- DO ji=SIZE(td_att(:)),1,-1 CALL att_clean(td_att(ji) ) ENDDO END SUBROUTINE att__clean_arr END MODULE att