Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an eventHookStatic directive #759

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions perl/Galacticus/Build/SourceTree.pm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use Galacticus::Build::SourceTree::Process::HDF5FCInterop;
use Galacticus::Build::SourceTree::Process::Constructors;
use Galacticus::Build::SourceTree::Process::ConditionalCall;
use Galacticus::Build::SourceTree::Process::EventHooks;
use Galacticus::Build::SourceTree::Process::EventHooksStatic;
use Galacticus::Build::SourceTree::Process::ParameterMigration;
use Galacticus::Build::SourceTree::Process::Dependencies;
use Galacticus::Build::SourceTree::Process::ClassDocumentation;
Expand Down
111 changes: 111 additions & 0 deletions perl/Galacticus/Build/SourceTree/Process/EventHooksStatic.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Contains a Perl module which implements processing of static event directives.

package Galacticus::Build::SourceTree::Process::EventHooksStatic;
use strict;
use warnings;
use utf8;
use Cwd;
use lib $ENV{'GALACTICUS_EXEC_PATH'}."/perl";
use Data::Dumper;
use XML::Simple;
use Storable;
use List::ExtraUtils;
use Galacticus::Build::Directives;

# Insert hooks for our functions.
$Galacticus::Build::SourceTree::Hooks::processHooks{'eventHooksStatic'} = \&Process_EventHooksStatic;

sub Process_EventHooksStatic {
# Get the tree.
my $tree = shift();
# Get an XML parser.
my $xml = new XML::Simple();
# Get code directive locations if we do not have them.
our $directiveLocations = $xml->XMLin($ENV{'BUILDPATH'}."/directiveLocations.xml")
unless ( $directiveLocations );
# Initialize event hook names.
our @eventHookNames;
unless ( @eventHookNames ) {
if ( -e $ENV{'BUILDPATH'}."/eventHooksStatic.blob" ) {
@eventHookNames = @{retrieve($ENV{'BUILDPATH'}."/eventHooksStatic.blob")};
} else {
@eventHookNames = map {$_->{'name'}} map {&Galacticus::Build::Directives::Extract_Directives($_,'eventHookStatic')} &List::ExtraUtils::as_array($directiveLocations->{'eventHookStatic'}->{'file'});
store(\@eventHookNames,$ENV{'BUILDPATH'}."/eventHooksStatic.blob");
}
}
# Walk the tree, looking for hook directives.
my $node = $tree;
my $depth = 0;
my $moduleNode;
my @functions;
while ( $node ) {
# Locate the containing module.
$moduleNode = $node
if ( $node->{'type'} eq "module" );
# Handle eventHookStatic directives by creating code to call any hooked functions.
if ( $node->{'type'} eq "eventHookStatic" && ! $node->{'directive'}->{'processed'} ) {
$node->{'directive'}->{'processed'} = 1;
# Find locations of all matching directives.
my @eventHookedLocations = &List::ExtraUtils::as_array($directiveLocations->{$node->{'directive'}->{'name'}}->{'file'})
if ( exists($directiveLocations->{$node->{'directive'}->{'name'}}) );
# Iterate over event hook locations, finding names of hooked functions and the modules in which they are contained.
my @hookedFunctions;
foreach my $eventHookedLocation ( @eventHookedLocations ) {
my $eventHookedTree = &Galacticus::Build::SourceTree::ParseFile($eventHookedLocation);
my $eventHookedNode = $eventHookedTree;
my $eventHookedDepth = 0;
my $moduleName;
my $functionName;
while ( $eventHookedNode ) {
$moduleName = $eventHookedNode->{'name'}
if ( $eventHookedNode->{'type'} eq "module" );
$functionName = $eventHookedNode->{'directive'}->{'function'}
if ( $eventHookedNode->{'type'} eq $node->{'directive'}->{'name'} );
$eventHookedNode = &Galacticus::Build::SourceTree::Walk_Tree($eventHookedNode,\$eventHookedDepth);
}
die("Galacticus::Build::SourceTree::Process::EventHooksStatic: unable to find module containing hooked function")
unless ( defined($moduleName ) );
die("Galacticus::Build::SourceTree::Process::EventHooksStatic: unable to find name of hooked function" )
unless ( defined($functionName) );
push(@hookedFunctions,{function => $functionName, module => $moduleName});
}
# Insert the code.
my $newNode =
{
type => "code",
content => join("\n",map {"call ".$_->{'function'}."()"} @hookedFunctions)."\n",
firstChild => undef(),
source => "Galacticus::Build::SourceTree::Process::EventHooksStatic::Process_EventHooksStatic()",
line => 1
};
&Galacticus::Build::SourceTree::InsertAfterNode($node,[$newNode]);
my $usesNode =
{
type => "moduleUse",
moduleUse => {},
source => "Galacticus::Build::SourceTree::Process::EventHooksStatic::Process_EventHooksStatic()",
line => 1
};
$usesNode->{'moduleUse'}->{$_->{'module'}} = {intrinsic => 0, only => {$_->{'function'} => 1}}
foreach ( @hookedFunctions );
&Galacticus::Build::SourceTree::Parse::ModuleUses::AddUses($node->{'parent'},$usesNode);
}
# Look for event hooked functions.
if ( (grep {$node->{'type'} eq $_} @eventHookNames) && ! $node->{'directive'}->{'processed'} ) {
$node->{'directive'}->{'processed'} = 1;
push(@functions,$node->{'directive'}->{'function'});
}
$node = &Galacticus::Build::SourceTree::Walk_Tree($node,\$depth);
}
# Set visibilities for hooked functions.
if ( scalar(@functions) > 0 ) {
if ( defined($moduleNode) ) {
&Galacticus::Build::SourceTree::SetVisibility($moduleNode,$_,"public")
foreach ( @functions );
} else {
die("Galacticus::Build::SourceTree::Process::EventHooksStatic::Process_EventHooksStatic(): hooked function is not in a module");
}
}
}

1;
21 changes: 20 additions & 1 deletion scripts/build/useDependencies.pl
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
# Extract lists of directives from this file which require special handling.
my $directives;
@{$directives->{$_}} = &Galacticus::Build::Directives::Extract_Directives($sourceFile->{'fullPathFileName'},$_)
foreach ( "functionClass", "inputParameter", "enumeration", "eventHook", "eventHookManager" );
foreach ( "functionClass", "inputParameter", "enumeration", "eventHook", "eventHookStatic", "eventHookManager" );
# Special handling for functionClass directives - add implementation files to the list of files to scan.
if ( scalar(@{$directives->{'functionClass'}}) > 0 ) {
foreach my $functionClass ( @{$directives->{'functionClass'}} ) {
Expand All @@ -203,6 +203,25 @@
($usesPerFile->{'eventHooksManager'}->{'objectFileName'} = $workSubDirectoryName.$sourceFile ->{'fileName'}) =~ s/\.(f|f90|c|cpp)$/.o/i;
$usesPerFile ->{'eventHooksManager'}->{'fileIdentifier'} = $fileIdentifier ;
}
# Accumulate dependencies for static event hook modules.
if ( scalar(@{$directives->{'eventHookStatic'}}) > 0 ) {
foreach my $eventHookStatic ( @{$directives->{'eventHookStatic'}} ) {
foreach my $eventHookedStaticFile ( &List::ExtraUtils::as_array($locations->{$eventHookStatic->{'name'}}->{'file'}) ) {
my $moduleName;
open(my $file,$eventHookedStaticFile) or die "Can't open input file: $eventHookedStaticFile";
while (my $line = <$file>) {
if ( $line =~ m/^\s*module\s+([a-zA-Z0-9_]+)/ ) {
$moduleName = $1;
last;
}
}
close($file);
die("useDependencies.pl: unable to locate containing module for static event '".$eventHookStatic->{'name'}."' in file '".$eventHookedStaticFile."'")
unless ( defined($moduleName) );
push(@{$usesPerFile->{$fileIdentifier}->{'modulesUsed'}},$workDirectoryName.lc($moduleName).".mod");
}
}
}
# Add dependence on input parameters module if necessary.
push(@{$usesPerFile->{$fileIdentifier}->{'modulesUsed'}},$workDirectoryName."input_parameters.mod")
if ( scalar(@{$directives->{'functionClass'}}) > 0 || scalar(@{$directives->{'inputParameter'}}) > 0 );
Expand Down
7 changes: 3 additions & 4 deletions source/events.hooks.F90
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Handles hooking of object function class into events.
use :: Regular_Expressions, only : regEx
use :: Locks , only : ompLock, ompReadWriteLock
private
public :: hook, hookUnspecified, dependencyExact, dependencyRegEx, eventsHooksInitialize, eventsHooksFutureThread, eventsHooksAtLevelToAllLevels
public :: hook , hookUnspecified , dependencyExact , dependencyRegEx, &
& eventsHooksInitialize, eventsHooksFutureThread, eventsHooksAtLevelToAllLevels

!![
<enumeration>
Expand Down Expand Up @@ -675,9 +676,7 @@ function dependencyRegExConstructor(direction,label) result(self)
end function dependencyRegExConstructor

!![
<hdfPreCloseTask>
<unitName>eventsHooksWaitTimes</unitName>
</hdfPreCloseTask>
<outputFileClose function="eventsHooksWaitTimes"/>
!!]

end module Events_Hooks
9 changes: 3 additions & 6 deletions source/instruments.filters.F90
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ module Instruments_Filters
use :: Locks , only : ompReadWriteLock
implicit none
private
public :: Filter_Get_Index , Filter_Response , Filter_Extent , Filter_Vega_Offset , &
& Filter_Name , Filter_Wavelength_Effective, Filters_Output, Filter_Response_Function, &
& Filters_Initialize
public :: Filter_Get_Index, Filter_Response , Filter_Extent , Filter_Vega_Offset , &
& Filter_Name , Filter_Wavelength_Effective, Filters_Initialize, Filter_Response_Function

type filterType
!!{
Expand Down Expand Up @@ -376,9 +375,7 @@ subroutine Filter_Response_Load(filterName)
end subroutine Filter_Response_Load

!![
<hdfPreCloseTask>
<unitName>Filters_Output</unitName>
</hdfPreCloseTask>
<outputFileClose function="Filters_Output"/>
!!]
subroutine Filters_Output()
!!{
Expand Down
8 changes: 4 additions & 4 deletions source/merger_trees.evolve.timesteps.history.F90
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,23 @@ subroutine historyAutoHook(self)
!!{
Create a hook to the HDF5 pre-close event to allow us to finalize and write out our data.
!!}
use :: Events_Hooks, only : hdf5PreCloseEventGlobal
use :: Events_Hooks, only : outputFileCloseEventGlobal
implicit none
class(mergerTreeEvolveTimestepHistory), intent(inout) :: self

call hdf5PreCloseEventGlobal%attach(self,historyWrite,label='mergerTreeEvolveTimestepHistory')
call outputFileCloseEventGlobal%attach(self,historyWrite,label='mergerTreeEvolveTimestepHistory')
return
end subroutine historyAutoHook

subroutine historyDestructor(self)
!!{
Destructor for the {\normalfont \ttfamily history} merger tree evolution timestep class.
!!}
use :: Events_Hooks, only : hdf5PreCloseEventGlobal
use :: Events_Hooks, only : outputFileCloseEventGlobal
implicit none
type(mergerTreeEvolveTimestepHistory), intent(inout) :: self

if (hdf5PreCloseEventGlobal%isAttached(self,historyWrite)) call hdf5PreCloseEventGlobal%detach(self,historyWrite)
if (outputFileCloseEventGlobal%isAttached(self,historyWrite)) call outputFileCloseEventGlobal%detach(self,historyWrite)
!![
<objectDestructor name="self%cosmologyFunctions_" />
<objectDestructor name="self%starFormationRateDisks_" />
Expand Down
32 changes: 5 additions & 27 deletions source/output.HDF5.open.F90
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,6 @@ subroutine Output_HDF5_Open_File(parameters)
use :: MPI_Utilities , only : mpiSelf
#endif
use :: String_Handling , only : operator(//)
!![
<include directive="outputFileOpenTask" type="moduleUse">
!!]
include 'output.open.modules.inc'
!![
</include>
!!]
implicit none
type (inputParameters), intent(inout) :: parameters
integer(hsize_t ) :: chunkSize
Expand Down Expand Up @@ -180,15 +173,11 @@ subroutine Output_HDF5_Open_File(parameters)
! Set default chunking and compression levels.
call IO_HDF5_Set_Defaults(hdf5ChunkSize,hdf5CompressionLevel)

! Call all routines that requested to output to the file on start up.
! Call all functions that requested to output to the file on start up.
!![
<include directive="outputFileOpenTask" type="functionCall" functionType="void">
<eventHookStatic name="outputFileOpen"/>
!!]
include 'output.open.inc'
!![
</include>
!!]


! Flag that the file is now open.
outputFileIsOpen=.true.
end if
Expand All @@ -203,26 +192,15 @@ subroutine Output_HDF5_Close_File
use :: File_Utilities , only : File_Rename
use :: HDF5_Access , only : hdf5Access
use :: ISO_Varying_String, only : operator(/=)
!![
<include directive="hdfPreCloseTask" type="moduleUse">
!!]
include 'output.HDF5.pre_close_tasks.moduleUse.inc'
!![
</include>
!!]
implicit none

! Perform any final tasks prior to shutdown.
if (outputFileIsOpen) then
!$omp critical (Output_HDF5_Close_File)
if (outputFileIsOpen) then
!![
<include directive="hdfPreCloseTask" type="functionCall" functionType="void">
!!]
include 'output.HDF5.pre_close_tasks.inc'
!![
</include>
<eventHook name="hdf5PreClose"/>
<eventHookStatic name="outputFileClose"/>
<eventHook name="outputFileClose"/>
!!]
! Close the file.
!$ call hdf5Access%set()
Expand Down
10 changes: 4 additions & 6 deletions source/output.build.F90
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module Output_Build
use, intrinsic :: ISO_C_Binding, only : c_ptr
implicit none
private
public :: Output_Build_Output, Output_Build_String
public :: Output_Build_String

interface
function GSL_Get_Version() bind(c,name='GSL_Get_Version')
Expand Down Expand Up @@ -110,13 +110,11 @@ function Output_Build_String()
Output_Build_String=Output_Build_String//":CPPCOMPILER_VERSION["//CPPCOMPILER_VERSION//"]"
return
end function Output_Build_String

!![
<outputFileOpenTask>
<unitName>Output_Build_Output</unitName>
</outputFileOpenTask>
<outputFileOpen function="Output_Build_Output"/>
!!]
subroutine Output_Build_Output
subroutine Output_Build_Output()
!!{
Output build information to the main output file.
!!}
Expand Down
10 changes: 3 additions & 7 deletions source/output.version.F90
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module Output_Versioning
use, intrinsic :: ISO_C_Binding, only : c_char, c_size_t
implicit none
private
public :: Version_Output, Version_Finalize, Version_String, Version
public :: Version_String, Version

! Include the automatically generated Git revision number.
include 'output.version.revision.inc'
Expand Down Expand Up @@ -82,9 +82,7 @@ function Version_String()
end function Version_String

!![
<outputFileOpenTask>
<unitName>Version_Output</unitName>
</outputFileOpenTask>
<outputFileOpen function="Version_Output"/>
!!]
subroutine Version_Output
!!{
Expand Down Expand Up @@ -182,9 +180,7 @@ subroutine Version_Output
end subroutine Version_Output

!![
<hdfPreCloseTask>
<unitName>Version_Finalize</unitName>
</hdfPreCloseTask>
<outputFileClose function="Version_Finalize"/>
!!]
subroutine Version_Finalize()
!!{
Expand Down
5 changes: 1 addition & 4 deletions source/utility.OpenMP.F90
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ module OpenMP_Utilities
Implements useful OpenMP utilities.
!!}
private
public :: OpenMP_Critical_Wait_Times

contains

!![
<hdfPreCloseTask>
<unitName>OpenMP_Critical_Wait_Times</unitName>
</hdfPreCloseTask>
<outputFileClose function="OpenMP_Critical_Wait_Times"/>
!!]
subroutine OpenMP_Critical_Wait_Times()
!!{
Expand Down
6 changes: 2 additions & 4 deletions source/utility.memory_reporting.F90
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Memory_Reporting
use, intrinsic :: ISO_C_Binding, only : c_size_t , c_int
implicit none
private
public :: reportMemoryUsage, outputMemoryUsageMaximum
public :: reportMemoryUsage

! Code memory size initialization status.
logical :: codeMemoryUsageInitialized =.false.
Expand Down Expand Up @@ -269,9 +269,7 @@ subroutine codeUsageGet()
end subroutine codeUsageGet

!![
<hdfPreCloseTask>
<unitName>outputMemoryUsageMaximum</unitName>
</hdfPreCloseTask>
<outputFileClose function="outputMemoryUsageMaximum"/>
!!]
subroutine outputMemoryUsageMaximum()
!!{
Expand Down
Loading