Skip to content

Commit

Permalink
Create the folder ComponentSpecParser that has the submodules for map…
Browse files Browse the repository at this point in the history
…l3g_ComponentSpecParser
  • Loading branch information
JulesKouatchou committed May 10, 2024
1 parent 88c08ca commit 907001b
Show file tree
Hide file tree
Showing 9 changed files with 734 additions and 0 deletions.
1 change: 1 addition & 0 deletions generic3g/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ add_subdirectory(registry)
add_subdirectory(connection)
add_subdirectory(actions)
add_subdirectory(couplers)
add_subdirectory(ComponentSpecParser)

target_include_directories (${this} PUBLIC
$<BUILD_INTERFACE:${MAPL_SOURCE_DIR}/include>)
Expand Down
10 changes: 10 additions & 0 deletions generic3g/ComponentSpecParser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
target_sources(MAPL.generic3g PRIVATE

parse_child.F90
parse_children.F90
parse_connections.F90
parse_var_specs.F90
parse_geometry_spec.F90
parse_component_spec.F90
parse_setservices.F90
)
64 changes: 64 additions & 0 deletions generic3g/ComponentSpecParser/parse_child.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "MAPL_ErrLog.h"

submodule (mapl3g_ComponentSpecParser) parse_child_smod

contains

module function parse_child(hconfig, rc) result(child)
type(ChildSpec) :: child
type(ESMF_HConfig), intent(in) :: hconfig
integer, optional, intent(out) :: rc

integer :: status
class(AbstractUserSetServices), allocatable :: setservices

character(*), parameter :: dso_keys(*) = [character(len=9) :: 'dso', 'DSO', 'sharedObj', 'sharedobj']
character(*), parameter :: userProcedure_keys(*) = [character(len=10) :: 'SetServices', 'setServices', 'setservices']
integer :: i
character(:), allocatable :: dso_key, userProcedure_key, try_key
logical :: dso_found, userProcedure_found
logical :: has_key
logical :: has_config_file
character(:), allocatable :: sharedObj, userProcedure, config_file


dso_found = .false.
! Ensure precisely one name is used for dso
do i = 1, size(dso_keys)
try_key = trim(dso_keys(i))
has_key = ESMF_HconfigIsDefined(hconfig, keyString=try_key, _RC)
if (has_key) then
_ASSERT(.not. dso_found, 'multiple specifications for dso in hconfig for child')
dso_found = .true.
dso_key = try_key
end if
end do
_ASSERT(dso_found, 'Must specify a dso for hconfig of child')
sharedObj = ESMF_HconfigAsString(hconfig, keyString=dso_key, _RC)

userProcedure_found = .false.
do i = 1, size(userProcedure_keys)
try_key = userProcedure_keys(i)
if (ESMF_HconfigIsDefined(hconfig, keyString=try_key)) then
_ASSERT(.not. userProcedure_found, 'multiple specifications for dso in hconfig for child')
userProcedure_found = .true.
userProcedure_key = try_key
end if
end do
userProcedure = 'setservices_'
if (userProcedure_found) then
userProcedure = ESMF_HconfigAsString(hconfig, keyString=userProcedure_key,_RC)
end if

has_config_file = ESMF_HconfigIsDefined(hconfig, keyString='config_file', _RC)
if (has_config_file) then
config_file = ESMF_HconfigAsString(hconfig, keyString='config_file',_RC)
end if

setservices = user_setservices(sharedObj, userProcedure)
child = ChildSpec(setservices, config_file=config_file)

_RETURN(_SUCCESS)
end function parse_child

end submodule parse_child_smod
46 changes: 46 additions & 0 deletions generic3g/ComponentSpecParser/parse_children.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "MAPL_ErrLog.h"

submodule (mapl3g_ComponentSpecParser) parse_children_smod

contains

module function parse_children(hconfig, rc) result(children)
type(ChildSpecMap) :: children
type(ESMF_HConfig), intent(in) :: hconfig
integer, optional, intent(out) :: rc

integer :: status
logical :: has_children
logical :: is_map
type(ESMF_HConfig) :: children_cfg, child_cfg
type(ESMF_HConfigIter) :: iter, iter_begin, iter_end
type(ChildSpec) :: child_spec
character(:), allocatable :: child_name


has_children = ESMF_HConfigIsDefined(hconfig, keyString=COMPONENT_CHILDREN_SECTION, _RC)
_RETURN_UNLESS(has_children)

children_cfg = ESMF_HConfigCreateAt(hconfig, keyString=COMPONENT_CHILDREN_SECTION, _RC)
is_map = ESMF_HConfigIsMap(children_cfg, _RC)

_ASSERT(is_map, 'children spec must be mapping')

iter_begin = ESMF_HCOnfigIterBegin(children_cfg, _RC)
iter_end = ESMF_HConfigIterEnd(children_cfg, _RC)
iter = iter_begin
do while (ESMF_HConfigIterLoop(iter, iter_begin, iter_end))
child_name = ESMF_HConfigAsStringMapKey(iter, _RC)
child_cfg = ESMF_HConfigCreateAtMapVal(iter, _RC)
child_spec = parse_child(child_cfg, _RC)
call children%insert(child_name, child_spec)
call ESMF_HConfigDestroy(child_cfg, _RC)
end do

call ESMF_HConfigDestroy(children_cfg, _RC)

_RETURN(_SUCCESS)
end function parse_children

end submodule parse_children_smod

31 changes: 31 additions & 0 deletions generic3g/ComponentSpecParser/parse_component_spec.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "MAPL_ErrLog.h"

submodule (mapl3g_ComponentSpecParser) parse_component_spec_smod

contains

module function parse_component_spec(hconfig, rc) result(spec)
type(ComponentSpec) :: spec
type(ESMF_HConfig), target, intent(inout) :: hconfig
integer, optional, intent(out) :: rc

integer :: status
logical :: has_mapl_section
type(ESMF_HConfig) :: mapl_cfg

has_mapl_section = ESMF_HConfigIsDefined(hconfig, keyString=MAPL_SECTION, _RC)
_RETURN_UNLESS(has_mapl_section)
mapl_cfg = ESMF_HConfigCreateAt(hconfig, keyString=MAPL_SECTION, _RC)

spec%geometry_spec = parse_geometry_spec(mapl_cfg, _RC)
spec%var_specs = parse_var_specs(mapl_cfg, _RC)
spec%connections = parse_connections(mapl_cfg, _RC)
spec%children = parse_children(mapl_cfg, _RC)

call ESMF_HConfigDestroy(mapl_cfg, _RC)

_RETURN(_SUCCESS)
end function parse_component_spec

end submodule parse_component_spec_smod

143 changes: 143 additions & 0 deletions generic3g/ComponentSpecParser/parse_connections.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include "MAPL_ErrLog.h"

submodule (mapl3g_ComponentSpecParser) parse_connections_smod

contains

module function parse_connections(hconfig, rc) result(connections)
type(ConnectionVector) :: connections
type(ESMF_HConfig), optional, intent(in) :: hconfig
integer, optional, intent(out) :: rc

type(ESMF_HConfig) :: conn_specs, conn_spec
class(Connection), allocatable :: conn
integer :: status, i, num_specs
logical :: has_connections

has_connections = ESMF_HConfigIsDefined(hconfig,keyString=COMPONENT_CONNECTIONS_SECTION,_RC)
_RETURN_UNLESS(has_connections)

conn_specs = ESMF_HConfigCreateAt(hconfig, keyString=COMPONENT_CONNECTIONS_SECTION, _RC)

num_specs = ESMF_HConfigGetSize(conn_specs, _RC)
do i = 1, num_specs
conn_spec = ESMF_HConfigCreateAt(conn_specs, index=i, _RC)
allocate(conn, source=parse_connection(conn_spec, rc=status)); _VERIFY(status)
call connections%push_back(conn)
deallocate(conn)
enddo

_RETURN(_SUCCESS)

contains

function parse_connection(config, rc) result(conn)
class(Connection), allocatable :: conn
type(ESMF_HConfig), optional, intent(in) :: config
integer, optional, intent(out) :: rc

integer :: status
character(:), allocatable :: src_name, dst_name
character(:), allocatable :: src_comp, dst_comp
character(:), allocatable :: src_intent, dst_intent

call get_comps(config, src_comp, dst_comp, _RC)

if (ESMF_HConfigIsDefined(config,keyString='all_unsatisfied')) then
conn = MatchConnection( &
ConnectionPt(src_comp, VirtualConnectionPt(state_intent='export', short_name='^.*$')), &
ConnectionPt(dst_comp, VirtualConnectionPt(state_intent='import', short_name='^.*$')) &
)
_RETURN(_SUCCESS)
end if

call get_names(config, src_name, dst_name, _RC)
call get_intents(config, src_intent, dst_intent, _RC)

associate ( &
src_pt => VirtualConnectionPt(state_intent=src_intent, short_name=src_name), &
dst_pt => VirtualConnectionPt(state_intent=dst_intent, short_name=dst_name) )

if (dst_intent == 'export') then
conn = ReexportConnection( &
ConnectionPt(src_comp, src_pt), &
ConnectionPt(dst_comp, dst_pt))
else
conn = SimpleConnection( &
ConnectionPt(src_comp, src_pt), &
ConnectionPt(dst_comp, dst_pt))
end if

end associate

_RETURN(_SUCCESS)
end function parse_connection

subroutine get_names(config, src_name, dst_name, rc)
type(ESMF_HConfig), intent(in) :: config
character(:), allocatable :: src_name
character(:), allocatable :: dst_name
integer, optional, intent(out) :: rc

integer :: status

associate (provides_names => &
ESMF_HConfigIsDefined(config,keyString='name') .or. &
(ESMF_HConfigIsDefined(config,keyString='src_name') .and. ESMF_HConfigIsDefined(config,keyString='dst_name')) &
)
_ASSERT(provides_names, "Must specify 'name' or 'src_name' .and. 'dst_name' in connection.")
end associate

if (ESMF_HConfigIsDefined(Config,keystring='name')) then ! replicate for src and dst
src_name = ESMF_HConfigAsString(config,keyString='name',_RC)
dst_name = src_name
_RETURN(_SUCCESS)
end if

src_name = ESMF_HConfigAsString(config,keyString='src_name',_RC)
dst_name = ESMF_HConfigAsString(config,keyString='dst_name',_RC)

_RETURN(_SUCCESS)
end subroutine get_names

subroutine get_comps(config, src_comp, dst_comp, rc)
type(ESMF_HConfig), intent(in) :: config
character(:), allocatable :: src_comp
character(:), allocatable :: dst_comp
integer, optional, intent(out) :: rc

integer :: status

_ASSERT(ESMF_HConfigIsDefined(config,keyString='src_comp'), 'Connection must specify a src component')
_ASSERT(ESMF_HConfigIsDefined(config,keyString='dst_comp'), 'Connection must specify a dst component')
src_comp = ESMF_HConfigAsString(config,keyString='src_comp',_RC)
dst_comp = ESMF_HConfigAsString(config,keyString='dst_comp',_RC)
_RETURN(_SUCCESS)
end subroutine get_comps

subroutine get_intents(config, src_intent, dst_intent, rc)
type(ESMF_HConfig), intent(in) :: config
character(:), allocatable :: src_intent
character(:), allocatable :: dst_intent
integer, optional, intent(out) :: rc

integer :: status

! defaults
src_intent = 'export'
dst_intent = 'import'

if (ESMF_HConfigIsDefined(config,keyString='src_intent')) then
src_intent = ESMF_HConfigAsString(config,keyString='src_intent',_RC)
end if
if (ESMF_HConfigIsDefined(config,keyString='dst_intent')) then
dst_intent = ESMF_HConfigAsString(config,keyString='dst_intent',_RC)
end if

_RETURN(_SUCCESS)
end subroutine get_intents

end function parse_connections

end submodule parse_connections_smod

85 changes: 85 additions & 0 deletions generic3g/ComponentSpecParser/parse_geometry_spec.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "MAPL_ErrLog.h"

submodule (mapl3g_ComponentSpecParser) parse_geometry_spec_smod

contains

! Geom subcfg is passed raw to the GeomManager layer. So little
! processing is needed here.
module function parse_geometry_spec(mapl_cfg, rc) result(geometry_spec)
type(GeometrySpec) :: geometry_spec
type(ESMF_HConfig), intent(in) :: mapl_cfg
integer, optional, intent(out) :: rc

integer :: status
logical :: has_geometry_section
logical :: has_esmf_geom
logical :: has_geometry_kind
logical :: has_geometry_provider
character(:), allocatable :: geometry_kind_str
character(:), allocatable :: provider
integer :: geometry_kind
type(ESMF_HConfig) :: geometry_cfg
type(ESMF_HConfig) :: esmf_geom_cfg
type(GeomManager), pointer :: geom_mgr
class(GeomSpec), allocatable :: geom_spec

has_geometry_section = ESMF_HConfigIsDefined(mapl_cfg,keyString=COMPONENT_GEOMETRY_SECTION, _RC)
_RETURN_UNLESS(has_geometry_section)

geometry_cfg = ESMF_HConfigCreateAt(mapl_cfg, keyString=COMPONENT_GEOMETRY_SECTION, _RC)

has_geometry_kind = ESMF_HConfigIsDefined(geometry_cfg, keyString='kind', _RC)
has_esmf_geom = ESMF_HConfigIsDefined(geometry_cfg, keyString=COMPONENT_ESMF_GEOM_SECTION, _RC)

if (.not. (has_geometry_kind .or. has_esmf_geom)) then ! default
geometry_spec = GeometrySpec(GEOMETRY_FROM_PARENT)
call ESMF_HConfigDestroy(geometry_cfg, _RC)
_RETURN(_SUCCESS)
end if

if (has_geometry_kind) then
geometry_kind_str = ESMF_HConfigAsString(geometry_cfg, keyString='kind', _RC)
end if

if (has_esmf_geom) then
esmf_geom_cfg = ESMF_HConfigCreateAt(geometry_cfg, keyString=COMPONENT_ESMF_GEOM_SECTION, _RC)
end if

if (has_geometry_kind .and. has_esmf_geom) then
_ASSERT(geometry_kind_str == 'provider', 'Geometry kind must be provider when using ESMF geom config.')
end if

if (has_esmf_geom) then
geom_mgr => get_geom_manager()
allocate(geom_spec, source=geom_mgr%make_geom_spec(esmf_geom_cfg, rc=status))
_VERIFY(status)
call ESMF_HConfigDestroy(geometry_cfg, _RC)
geometry_spec = GeometrySpec(geom_spec)
_RETURN(_SUCCESS)
end if

if (has_geometry_kind) then
select case (ESMF_UtilStringLowerCase(geometry_kind_str))
case ('none')
geometry_spec = GeometrySpec(GEOMETRY_NONE)
case ('provider')
geometry_spec = GeometrySpec(GEOMETRY_PROVIDER)
case ('from_parent')
geometry_spec = GeometrySpec(GEOMETRY_FROM_PARENT)
case ('from_child')
has_geometry_provider = ESMF_HConfigIsDefined(geometry_cfg, keystring='provider', _RC)
_ASSERT(has_geometry_provider, 'Must name provider when using GEOMETRY_FROM_CHILD')
provider = ESMF_HConfigAsString(geometry_cfg, keystring='provider', _RC)
geometry_spec = GeometrySpec(provider)
case default
_FAIL('Invalid geometry kind')
end select
call ESMF_HConfigDestroy(geometry_cfg, _RC)
end if

_RETURN(_SUCCESS)
end function parse_geometry_spec

end submodule parse_geometry_spec_smod

Loading

0 comments on commit 907001b

Please sign in to comment.