Skip to content

Commit

Permalink
Merge pull request #2934 from GEOS-ESM/feature/bmauer/fixes-#2931
Browse files Browse the repository at this point in the history
Pull UDUNITS fortran interface into develop
  • Loading branch information
bena-nasa authored Jul 31, 2024
2 parents 8cc01f8 + 35e1d06 commit 95a4c96
Show file tree
Hide file tree
Showing 15 changed files with 1,139 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Added Fortran interface to UDUNITS2
- Improve mask sampler by adding an MPI step and a LS_chunk (intermediate step)
- Update Baselibs in CI to 7.25.0
- NOTE: The docker image also updates to Intel 2024.2 and Intel MPI 2021.13
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ add_subdirectory (base)
add_subdirectory (MAPL)
add_subdirectory (gridcomps)
add_subdirectory (griddedio)
add_subdirectory (udunits2f)
if (BUILD_WITH_FARGPARSE)
add_subdirectory (docs)
add_subdirectory (benchmarks)
Expand Down
68 changes: 68 additions & 0 deletions cmake/Findudunits.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# (C) Copyright 2022- UCAR.
#
# Try to find the udunits headers and library
#
# This module defines:
#
# - udunits::udunits - The udunits shared library and include directory, all in a single target.
# - udunits_FOUND - True if udunits was found
# - udunits_INCLUDE_DIR - The include directory
# - udunits_LIBRARY - The library
# - udunits_LIBRARY_SHARED - Whether the library is shared or not
# - udunits_XML_PATH - path to udunits2.xml
#
# The following paths will be searched in order if set in CMake (first priority) or environment (second priority):
#
# - UDUNITS2_INCLUDE_DIRS & UDUNITS2_LIBRARIES - folders containing udunits2.h and libudunits2, respectively.
# - UDUNITS2_ROOT - root of udunits installation
# - UDUNITS2_PATH - root of udunits installation
#
# Notes:
# - The hint variables are capitalized because this is how they are exposed in the jedi stack.
# See https://github.com/JCSDA-internal/jedi-stack/blob/develop/modulefiles/compiler/compilerName/compilerVersion/udunits/udunits.lua for details.

find_path (
udunits_INCLUDE_DIR
udunits2.h
HINTS ${UDUNITS2_INCLUDE_DIRS} $ENV{UDUNITS2_INCLUDE_DIRS}
${UDUNITS2_ROOT} $ENV{UDUNITS2_ROOT}
${UDUNITS2_PATH} $ENV{UDUNITS2_PATH}
PATH_SUFFIXES include include/udunits2
DOC "Path to udunits2.h" )

find_file (
udunits_XML_PATH
udunits2.xml
HINTS ${UDUNITS2_XML_PATH} $ENV{UDUNITS2_XML_PATH}
${UDUNITS2_ROOT} $ENV{UDUNITS2_ROOT}
${UDUNITS2_PATH} $ENV{UDUNITS2_PATH}
PATH_SUFFIXES share share/udunits
DOC "Path to udunits2.xml" )

find_library(udunits_LIBRARY
NAMES udunits2 udunits
HINTS ${UDUNITS2_LIBRARIES} $ENV{UDUNITS2_LIBRARIES}
${UDUNITS2_ROOT} $ENV{UDUNITS2_ROOT}
${UDUNITS2_PATH} $ENV{UDUNITS2_PATH}
PATH_SUFFIXES lib64 lib
DOC "Path to libudunits library" )

# We need to support both static and shared libraries
if (udunits_LIBRARY MATCHES ".*\\.a$")
set(udunits_LIBRARY_SHARED FALSE)
else()
set(udunits_LIBRARY_SHARED TRUE)
endif()

include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (udunits DEFAULT_MSG udunits_LIBRARY udunits_INCLUDE_DIR udunits_XML_PATH)

mark_as_advanced (udunits_LIBRARY udunits_INCLUDE_DIR udunits_XML_PATH)

if(udunits_FOUND AND NOT TARGET udunits::udunits)
add_library(udunits::udunits INTERFACE IMPORTED)
set_target_properties(udunits::udunits PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${udunits_INCLUDE_DIR})
set_target_properties(udunits::udunits PROPERTIES INTERFACE_LINK_LIBRARIES ${udunits_LIBRARY})
set_property(TARGET udunits::udunits APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS})
endif()

28 changes: 28 additions & 0 deletions udunits2f/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
esma_set_this (OVERRIDE udunits2f)

set(srcs
CptrWrapper.F90
UDSystem.F90
udunits2f.F90
encoding.F90
interfaces.F90
status_codes.F90
ut_set_ignore_error_message_handler.c
)
list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

esma_add_library(${this}
SRCS ${srcs}
TYPE SHARED
)

find_package(udunits REQUIRED)
find_package(EXPAT REQUIRED)

target_link_libraries(${this} PUBLIC udunits::udunits)
target_link_libraries(${this} PUBLIC EXPAT::EXPAT)

if (PFUNIT_FOUND)
# Turning off until test with GNU can be fixed
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif ()
64 changes: 64 additions & 0 deletions udunits2f/CptrWrapper.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module ud2f_CptrWrapper
use, intrinsic :: iso_c_binding, only: c_ptr, C_NULL_PTR, c_associated
implicit none
private

public :: CptrWrapper

!================================ CPTRWRAPPER ==================================
! Base class to wrap type(c_ptr) instances used for udunits2 objects that cannot
! interface directly to fortran. Each extended class must provide a subroutine
! to free the memory associated with cptr_
type, abstract :: CptrWrapper
private
type(c_ptr) :: cptr_ = C_NULL_PTR
contains
procedure :: get_cptr
procedure :: set_cptr
procedure :: is_free
procedure :: free
procedure(I_free_memory), deferred :: free_memory
end type CptrWrapper

abstract interface

subroutine I_free_memory(this)
import :: CptrWrapper
class(CptrWrapper), intent(in) :: this
end subroutine I_Free_Memory

end interface

contains

type(c_ptr) function get_cptr(this)
class(CptrWrapper), intent(in) :: this

get_cptr = this%cptr_

end function get_cptr

subroutine set_cptr(this, cptr)
class(CptrWrapper), intent(inout) :: this
type(c_ptr), intent(in) :: cptr
this%cptr_ = cptr
end subroutine set_cptr

logical function is_free(this)
class(CptrWrapper), intent(in) :: this

is_free = .not. c_associated(this%cptr_)

end function is_free

! Free up memory pointed to by cptr_ and set cptr_ to c_null_ptr
subroutine free(this)
class(CptrWrapper), intent(inout) :: this

if(this%is_free()) return
call this%free_memory()
this%cptr_ = c_null_ptr

end subroutine free

end module ud2f_CptrWrapper
Loading

0 comments on commit 95a4c96

Please sign in to comment.