diff --git a/perl/Galacticus/Build/SourceTree.pm b/perl/Galacticus/Build/SourceTree.pm index a62dd6118..32e3eec1c 100644 --- a/perl/Galacticus/Build/SourceTree.pm +++ b/perl/Galacticus/Build/SourceTree.pm @@ -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; diff --git a/perl/Galacticus/Build/SourceTree/Process/EventHooksStatic.pm b/perl/Galacticus/Build/SourceTree/Process/EventHooksStatic.pm new file mode 100644 index 000000000..b8c5515f6 --- /dev/null +++ b/perl/Galacticus/Build/SourceTree/Process/EventHooksStatic.pm @@ -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; diff --git a/scripts/build/useDependencies.pl b/scripts/build/useDependencies.pl index ddb80dbee..4540de41a 100755 --- a/scripts/build/useDependencies.pl +++ b/scripts/build/useDependencies.pl @@ -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'}} ) { @@ -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 ); diff --git a/source/events.hooks.F90 b/source/events.hooks.F90 index 11bb5b0de..24ad26ad4 100644 --- a/source/events.hooks.F90 +++ b/source/events.hooks.F90 @@ -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 !![ @@ -675,9 +676,7 @@ function dependencyRegExConstructor(direction,label) result(self) end function dependencyRegExConstructor !![ - - eventsHooksWaitTimes - + !!] end module Events_Hooks diff --git a/source/instruments.filters.F90 b/source/instruments.filters.F90 index 0df0745dd..a67dd5eb8 100644 --- a/source/instruments.filters.F90 +++ b/source/instruments.filters.F90 @@ -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 !!{ @@ -376,9 +375,7 @@ subroutine Filter_Response_Load(filterName) end subroutine Filter_Response_Load !![ - - Filters_Output - + !!] subroutine Filters_Output() !!{ diff --git a/source/merger_trees.evolve.timesteps.history.F90 b/source/merger_trees.evolve.timesteps.history.F90 index f1a0e9ddb..d1c3c0fb5 100644 --- a/source/merger_trees.evolve.timesteps.history.F90 +++ b/source/merger_trees.evolve.timesteps.history.F90 @@ -194,11 +194,11 @@ 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 @@ -206,11 +206,11 @@ 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) !![ diff --git a/source/output.HDF5.open.F90 b/source/output.HDF5.open.F90 index ab67500f6..d1bdbda8c 100644 --- a/source/output.HDF5.open.F90 +++ b/source/output.HDF5.open.F90 @@ -55,13 +55,6 @@ subroutine Output_HDF5_Open_File(parameters) use :: MPI_Utilities , only : mpiSelf #endif use :: String_Handling , only : operator(//) - !![ - - !!] - include 'output.open.modules.inc' - !![ - - !!] implicit none type (inputParameters), intent(inout) :: parameters integer(hsize_t ) :: chunkSize @@ -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 'output.open.inc' - !![ - - !!] - + ! Flag that the file is now open. outputFileIsOpen=.true. end if @@ -203,13 +192,6 @@ subroutine Output_HDF5_Close_File use :: File_Utilities , only : File_Rename use :: HDF5_Access , only : hdf5Access use :: ISO_Varying_String, only : operator(/=) - !![ - - !!] - include 'output.HDF5.pre_close_tasks.moduleUse.inc' - !![ - - !!] implicit none ! Perform any final tasks prior to shutdown. @@ -217,12 +199,8 @@ subroutine Output_HDF5_Close_File !$omp critical (Output_HDF5_Close_File) if (outputFileIsOpen) then !![ - - !!] - include 'output.HDF5.pre_close_tasks.inc' - !![ - - + + !!] ! Close the file. !$ call hdf5Access%set() diff --git a/source/output.build.F90 b/source/output.build.F90 index b04409f3d..46fde7629 100644 --- a/source/output.build.F90 +++ b/source/output.build.F90 @@ -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') @@ -110,13 +110,11 @@ function Output_Build_String() Output_Build_String=Output_Build_String//":CPPCOMPILER_VERSION["//CPPCOMPILER_VERSION//"]" return end function Output_Build_String - + !![ - - Output_Build_Output - + !!] - subroutine Output_Build_Output + subroutine Output_Build_Output() !!{ Output build information to the main output file. !!} diff --git a/source/output.version.F90 b/source/output.version.F90 index 6d2a14c9e..dd3dfb614 100644 --- a/source/output.version.F90 +++ b/source/output.version.F90 @@ -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' @@ -82,9 +82,7 @@ function Version_String() end function Version_String !![ - - Version_Output - + !!] subroutine Version_Output !!{ @@ -182,9 +180,7 @@ subroutine Version_Output end subroutine Version_Output !![ - - Version_Finalize - + !!] subroutine Version_Finalize() !!{ diff --git a/source/utility.OpenMP.F90 b/source/utility.OpenMP.F90 index 6ef5180a1..2674a1caf 100644 --- a/source/utility.OpenMP.F90 +++ b/source/utility.OpenMP.F90 @@ -26,14 +26,11 @@ module OpenMP_Utilities Implements useful OpenMP utilities. !!} private - public :: OpenMP_Critical_Wait_Times contains !![ - - OpenMP_Critical_Wait_Times - + !!] subroutine OpenMP_Critical_Wait_Times() !!{ diff --git a/source/utility.memory_reporting.F90 b/source/utility.memory_reporting.F90 index e638b9d28..85d2d918a 100644 --- a/source/utility.memory_reporting.F90 +++ b/source/utility.memory_reporting.F90 @@ -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. @@ -269,9 +269,7 @@ subroutine codeUsageGet() end subroutine codeUsageGet !![ - - outputMemoryUsageMaximum - + !!] subroutine outputMemoryUsageMaximum() !!{