Rank [ 20]: Calc 0.000003 s Rank [ 35]: Calc 0.000003 s Rank [ 10]: Calc 0.000010 s Rank [ 17]: Calc 0.000005 s Rank [ 32]: Calc 0.000003 s,而且rank不固定,一般就是rank 10 和 rank 52; 但尽管有很多,比前者时间还是少很多 对于第二个Surf_Wave 调用 Interp_points,我发现前四个rank时间最长,比较固定,就是下面四个rank Rank [ 27]: Calc 0.331978 s Rank [ 35]: Calc 0.242219 s Rank [ 28]: Calc 0.242132 s Rank [ 36]: Calc 0.197024 s 因此下面surf_wave是核心
479 lines
19 KiB
Python
Executable File
479 lines
19 KiB
Python
Executable File
|
|
##################################################################
|
|
##
|
|
## AMSS-NCKU Numerical Relativity Startup Program
|
|
## Author: Xiaoqu
|
|
## 2024/03/19
|
|
## Modified: 2025/12/09
|
|
##
|
|
##################################################################
|
|
|
|
## Guard against re-execution by multiprocessing child processes.
|
|
## Without this, using 'spawn' or 'forkserver' context would cause every
|
|
## worker to re-run the entire script, spawning exponentially more
|
|
## workers (fork bomb).
|
|
if __name__ != '__main__':
|
|
import sys as _sys
|
|
_sys.exit(0)
|
|
|
|
|
|
##################################################################
|
|
|
|
## Print program introduction
|
|
|
|
import print_information
|
|
|
|
print_information.print_program_introduction()
|
|
|
|
##################################################################
|
|
|
|
### Pre-run prompts
|
|
#
|
|
#print( " Simulation will be started, please confirm you have set the correct parameters in the script file " )
|
|
#print( " AMSS_NCKU_Input.py " )
|
|
#print( " If parameters have been set correctly, press Enter to continue !!! " )
|
|
#print( " If you have not set parameters, press Ctrl+C to abort the simulation and adjust the parameters " )
|
|
#print( " in script file AMSS_NCKU_Input.py !!! " )
|
|
#
|
|
### Wait for user input (press Enter) to proceed
|
|
#inputvalue = input()
|
|
#print()
|
|
|
|
|
|
##################################################################
|
|
|
|
import AMSS_NCKU_Input as input_data
|
|
|
|
##################################################################
|
|
|
|
## Create directories to store program run data
|
|
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import time
|
|
|
|
## Set the output directory according to the input file
|
|
File_directory = os.path.join(input_data.File_directory)
|
|
|
|
## If the specified output directory exists, ask the user whether to continue
|
|
if os.path.exists(File_directory):
|
|
print( " Output dictionary has been existed !!! " )
|
|
print( " If you want to overwrite the existing file directory, please input 'continue' in the terminal !! " )
|
|
print( " If you want to retain the existing file directory, please input 'stop' in the terminal to stop the " )
|
|
print( " simulation. Then you can reset the output dictionary in the input script file AMSS_NCKU_Input.py !!! " )
|
|
print( )
|
|
## Prompt whether to overwrite the existing directory
|
|
while True:
|
|
try:
|
|
## inputvalue = input()
|
|
inputvalue = "continue"
|
|
## If the user agrees to overwrite, proceed and remove the existing directory
|
|
if ( inputvalue == "continue" ):
|
|
print( " Continue the calculation !!! " )
|
|
print( )
|
|
break
|
|
## If the user chooses not to overwrite, exit and keep the existing directory
|
|
elif ( inputvalue == "stop" ):
|
|
print( " Stop the calculation !!! " )
|
|
sys.exit()
|
|
## If the user input is invalid, prompt again
|
|
else:
|
|
print( " Please input your choice !!! " )
|
|
print( " Input 'continue' or 'stop' in the terminal !!! " )
|
|
except ValueError:
|
|
print( " Please input your choice !!! " )
|
|
print( " Input 'continue' or 'stop' in the terminal !!! " )
|
|
|
|
## Remove the existing output directory if present
|
|
shutil.rmtree(File_directory, ignore_errors=True)
|
|
|
|
## Create the output directory
|
|
os.mkdir(File_directory)
|
|
|
|
## Copy the Python input file into the run directory
|
|
shutil.copy("AMSS_NCKU_Input.py", File_directory)
|
|
|
|
# Generate subdirectories to store various output files
|
|
|
|
output_directory = os.path.join(File_directory, "AMSS_NCKU_output")
|
|
os.mkdir(output_directory)
|
|
|
|
binary_results_directory = os.path.join(output_directory, input_data.Output_directory)
|
|
os.mkdir(binary_results_directory)
|
|
|
|
figure_directory = os.path.join(File_directory, "figure")
|
|
os.mkdir(figure_directory)
|
|
|
|
print( " Output directory has been generated " )
|
|
print( )
|
|
|
|
|
|
##################################################################
|
|
|
|
## Output related parameter information
|
|
|
|
import setup
|
|
|
|
## Print and save input parameter information
|
|
setup.print_input_data( File_directory )
|
|
setup.generate_AMSSNCKU_input()
|
|
|
|
#print( )
|
|
#print( " Please check whether the grid boxes and their resolution are appropriate " )
|
|
#print( " If the grid boxes and their resolution are not set properly, press Ctrl+C to abort. " )
|
|
#print( " Adjust the grid levels and the number of grid points per level before retrying. " )
|
|
#print( " If the grid boxes and resolution are correct, press Enter to continue. " )
|
|
#inputvalue = input() ## Wait for user input (press Enter) to proceed
|
|
#print()
|
|
|
|
setup.print_puncture_information()
|
|
|
|
|
|
##################################################################
|
|
|
|
## Generate AMSS-NCKU program input files based on the configured parameters
|
|
|
|
print( )
|
|
print( " Generating the AMSS-NCKU input parfile for the ABE executable. " )
|
|
print( )
|
|
|
|
## Generate cgh-related input files from the grid information
|
|
|
|
import numerical_grid
|
|
|
|
numerical_grid.append_AMSSNCKU_cgh_input()
|
|
|
|
print( )
|
|
print( " The input parfile for AMSS-NCKU C++ executable file ABE has been generated. " )
|
|
print( " However, the input relevant to TwoPuncture need to be appended later. " )
|
|
print( )
|
|
|
|
|
|
##################################################################
|
|
|
|
## Plot the initial grid configuration
|
|
|
|
print( )
|
|
print( " Schematically plot the numerical grid structure. " )
|
|
print( )
|
|
|
|
numerical_grid.plot_initial_grid()
|
|
|
|
|
|
##################################################################
|
|
|
|
## Generate AMSS-NCKU macro files according to the numerical scheme and parameters
|
|
|
|
print( )
|
|
print( " Automatically generating the macro file for AMSS-NCKU C++ executable file ABE " )
|
|
print( " (Based on the finite-difference numerical scheme) " )
|
|
print( )
|
|
|
|
import generate_macrodef
|
|
|
|
generate_macrodef.generate_macrodef_h()
|
|
print( " AMSS-NCKU macro file macrodef.h has been generated. " )
|
|
|
|
generate_macrodef.generate_macrodef_fh()
|
|
print( " AMSS-NCKU macro file macrodef.fh has been generated. " )
|
|
|
|
|
|
##################################################################
|
|
|
|
# Compile the AMSS-NCKU program according to user requirements
|
|
|
|
# Prompt about compiling and running AMSS-NCKU
|
|
print( )
|
|
print( " Preparing to compile and run the AMSS-NCKU code as requested " )
|
|
print( " Compiling the AMSS-NCKU code based on the generated macro files " )
|
|
print( )
|
|
#inputvalue = input()
|
|
#print()
|
|
|
|
AMSS_NCKU_source_path = "AMSS_NCKU_source"
|
|
AMSS_NCKU_source_copy = os.path.join(File_directory, "AMSS_NCKU_source_copy")
|
|
|
|
###############################
|
|
|
|
## If AMSS_NCKU source folder is missing, create it and prompt the user
|
|
|
|
# if not os.path.exists(destination_folder):
|
|
# os.makedirs(destination_folder)
|
|
|
|
if not os.path.exists(AMSS_NCKU_source_path):
|
|
os.makedirs(AMSS_NCKU_source_path)
|
|
print( " The AMSS-NCKU source files are incomplete; copy all source files into ./AMSS_NCKU_source. " )
|
|
print( " Press Enter to continue. " )
|
|
## Wait for user input (press Enter) to proceed
|
|
inputvalue = input()
|
|
|
|
###############################
|
|
|
|
# Copy AMSS-NCKU source files to prepare for compilation
|
|
shutil.copytree(AMSS_NCKU_source_path, AMSS_NCKU_source_copy)
|
|
|
|
# (Comment) Example: copy the src folder to destination
|
|
# shutil.copytree(src, dst)
|
|
|
|
# Copy the generated macro files into the AMSS_NCKU source folder
|
|
|
|
macrodef_h_path = os.path.join(File_directory, "macrodef.h")
|
|
macrodef_fh_path = os.path.join(File_directory, "macrodef.fh")
|
|
|
|
shutil.copy2(macrodef_h_path, AMSS_NCKU_source_copy)
|
|
shutil.copy2(macrodef_fh_path, AMSS_NCKU_source_copy)
|
|
|
|
# Notes on copying files:
|
|
# shutil.copy2 preserves file metadata such as modification time.
|
|
# If you only want to copy file contents without metadata, use shutil.copy.
|
|
|
|
###############################
|
|
|
|
# Compile related programs
|
|
|
|
import makefile_and_run
|
|
|
|
## Change working directory to the target source copy
|
|
os.chdir(AMSS_NCKU_source_copy)
|
|
|
|
## Build the main AMSS-NCKU executable (ABE or ABEGPU)
|
|
makefile_and_run.makefile_ABE()
|
|
|
|
## If the initial-data method is Ansorg-TwoPuncture, build the TwoPunctureABE executable
|
|
if (input_data.Initial_Data_Method == "Ansorg-TwoPuncture" ):
|
|
makefile_and_run.makefile_TwoPunctureABE()
|
|
|
|
###########################
|
|
|
|
## Change current working directory back up two levels
|
|
os.chdir('..')
|
|
os.chdir('..')
|
|
|
|
print()
|
|
|
|
##################################################################
|
|
|
|
## Copy the AMSS-NCKU executable (ABE/ABEGPU) to the run directory
|
|
|
|
if (input_data.GPU_Calculation == "no"):
|
|
ABE_file = os.path.join(AMSS_NCKU_source_copy, "ABE")
|
|
elif (input_data.GPU_Calculation == "yes"):
|
|
ABE_file = os.path.join(AMSS_NCKU_source_copy, "ABEGPU")
|
|
|
|
if not os.path.exists( ABE_file ):
|
|
print( )
|
|
print( " Lack of AMSS-NCKU executable file ABE/ABEGPU; recompile AMSS_NCKU_source manually. " )
|
|
print( " When recompilation is finished, press Enter to continue. " )
|
|
## Wait for user input (press Enter) to proceed
|
|
inputvalue = input()
|
|
|
|
## Copy the executable ABE (or ABEGPU) into the run directory
|
|
shutil.copy2(ABE_file, output_directory)
|
|
|
|
###########################
|
|
|
|
## If the initial-data method is TwoPuncture, copy the TwoPunctureABE executable to the run directory
|
|
|
|
TwoPuncture_file = os.path.join(AMSS_NCKU_source_copy, "TwoPunctureABE")
|
|
|
|
if (input_data.Initial_Data_Method == "Ansorg-TwoPuncture" ):
|
|
|
|
if not os.path.exists( TwoPuncture_file ):
|
|
print( )
|
|
print( " Lack of AMSS-NCKU executable file TwoPunctureABE; recompile TwoPunctureABE in AMSS_NCKU_source. " )
|
|
print( " When recompilation is finished, press Enter to continue. " )
|
|
inputvalue = input()
|
|
|
|
## Copy the TwoPunctureABE executable into the run directory
|
|
shutil.copy2(TwoPuncture_file, output_directory)
|
|
|
|
###########################
|
|
|
|
|
|
##################################################################
|
|
|
|
## If the initial-data method is TwoPuncture, generate the TwoPuncture input files
|
|
|
|
if (input_data.Initial_Data_Method == "Ansorg-TwoPuncture" ):
|
|
|
|
print( )
|
|
print( " Initial data is chosen as Ansorg-TwoPuncture" )
|
|
print( )
|
|
|
|
print( )
|
|
print( " Automatically generating the input parfile for the TwoPunctureABE executable " )
|
|
print( )
|
|
|
|
import generate_TwoPuncture_input
|
|
|
|
generate_TwoPuncture_input.generate_AMSSNCKU_TwoPuncture_input()
|
|
|
|
print( )
|
|
print( " The input parfile for the TwoPunctureABE executable has been generated. " )
|
|
print( )
|
|
|
|
## Generated AMSS-NCKU TwoPuncture input filename
|
|
AMSS_NCKU_TwoPuncture_inputfile = 'AMSS-NCKU-TwoPuncture.input'
|
|
AMSS_NCKU_TwoPuncture_inputfile_path = os.path.join( File_directory, AMSS_NCKU_TwoPuncture_inputfile )
|
|
|
|
## Copy and rename the file
|
|
shutil.copy2( AMSS_NCKU_TwoPuncture_inputfile_path, os.path.join(output_directory, 'TwoPunctureinput.par') )
|
|
|
|
###########################
|
|
|
|
## Run TwoPuncture to generate initial-data files
|
|
|
|
start_time = time.time() # Record start time
|
|
|
|
print()
|
|
## print( " Ready to launch the AMSS-NCKU TwoPuncture executable; press Enter to continue. " )
|
|
## inputvalue = input()
|
|
print()
|
|
|
|
## Change to the output (run) directory
|
|
os.chdir(output_directory)
|
|
|
|
## Run the TwoPuncture executable
|
|
makefile_and_run.run_TwoPunctureABE()
|
|
|
|
###########################
|
|
|
|
## Change current working directory back up two levels
|
|
os.chdir('..')
|
|
os.chdir('..')
|
|
|
|
##################################################################
|
|
|
|
## Update puncture data based on TwoPuncture run results
|
|
|
|
import renew_puncture_parameter
|
|
|
|
renew_puncture_parameter.append_AMSSNCKU_BSSN_input(File_directory, output_directory)
|
|
|
|
|
|
## Generated AMSS-NCKU input filename
|
|
AMSS_NCKU_inputfile = 'AMSS-NCKU.input'
|
|
AMSS_NCKU_inputfile_path = os.path.join(File_directory, AMSS_NCKU_inputfile)
|
|
|
|
## Copy and rename the file
|
|
shutil.copy2( AMSS_NCKU_inputfile_path, os.path.join(output_directory, 'input.par') )
|
|
|
|
|
|
print( )
|
|
print( " Successfully copy all AMSS-NCKU input parfile to target dictionary. " )
|
|
print( )
|
|
|
|
|
|
##################################################################
|
|
|
|
## Launch the AMSS-NCKU program
|
|
|
|
print()
|
|
## print(" Ready to launch AMSS-NCKU; press Enter to continue. ")
|
|
## inputvalue = input()
|
|
print()
|
|
|
|
## Change to the run directory
|
|
os.chdir( output_directory )
|
|
|
|
makefile_and_run.run_ABE()
|
|
|
|
## Change current working directory back up two levels
|
|
os.chdir('..')
|
|
os.chdir('..')
|
|
|
|
|
|
end_time = time.time()
|
|
elapsed_time = end_time - start_time
|
|
|
|
##################################################################
|
|
|
|
## Copy some basic input and log files out to facilitate debugging
|
|
|
|
## Path to the file that stores calculation settings
|
|
AMSS_NCKU_error_file_path = os.path.join(binary_results_directory, "setting.par")
|
|
## Copy and rename the file for easier inspection
|
|
shutil.copy( AMSS_NCKU_error_file_path, os.path.join(output_directory, "AMSSNCKU_setting_parameter") )
|
|
|
|
## Path to the error log file
|
|
AMSS_NCKU_error_file_path = os.path.join(binary_results_directory, "Error.log")
|
|
## Copy and rename the error log
|
|
shutil.copy( AMSS_NCKU_error_file_path, os.path.join(output_directory, "Error.log") )
|
|
|
|
## Primary program outputs
|
|
AMSS_NCKU_BH_data = os.path.join(binary_results_directory, "bssn_BH.dat" )
|
|
AMSS_NCKU_ADM_data = os.path.join(binary_results_directory, "bssn_ADMQs.dat" )
|
|
AMSS_NCKU_psi4_data = os.path.join(binary_results_directory, "bssn_psi4.dat" )
|
|
AMSS_NCKU_constraint_data = os.path.join(binary_results_directory, "bssn_constraint.dat")
|
|
## copy and rename the file
|
|
shutil.copy( AMSS_NCKU_BH_data, os.path.join(output_directory, "bssn_BH.dat" ) )
|
|
shutil.copy( AMSS_NCKU_ADM_data, os.path.join(output_directory, "bssn_ADMQs.dat" ) )
|
|
shutil.copy( AMSS_NCKU_psi4_data, os.path.join(output_directory, "bssn_psi4.dat" ) )
|
|
shutil.copy( AMSS_NCKU_constraint_data, os.path.join(output_directory, "bssn_constraint.dat") )
|
|
|
|
## Additional program outputs
|
|
if (input_data.Equation_Class == "BSSN-EM"):
|
|
AMSS_NCKU_phi1_data = os.path.join(binary_results_directory, "bssn_phi1.dat" )
|
|
AMSS_NCKU_phi2_data = os.path.join(binary_results_directory, "bssn_phi2.dat" )
|
|
shutil.copy( AMSS_NCKU_phi1_data, os.path.join(output_directory, "bssn_phi1.dat" ) )
|
|
shutil.copy( AMSS_NCKU_phi2_data, os.path.join(output_directory, "bssn_phi2.dat" ) )
|
|
elif (input_data.Equation_Class == "BSSN-EScalar"):
|
|
AMSS_NCKU_maxs_data = os.path.join(binary_results_directory, "bssn_maxs.dat" )
|
|
shutil.copy( AMSS_NCKU_maxs_data, os.path.join(output_directory, "bssn_maxs.dat" ) )
|
|
|
|
##################################################################
|
|
|
|
## Plot the AMSS-NCKU program results
|
|
|
|
print( )
|
|
print( " Plotting the txt and binary results data from the AMSS-NCKU simulation " )
|
|
print( )
|
|
|
|
|
|
import plot_xiaoqu
|
|
import plot_GW_strain_amplitude_xiaoqu
|
|
from parallel_plot_helper import run_plot_tasks_parallel
|
|
|
|
plot_tasks = []
|
|
|
|
## Plot black hole trajectory
|
|
plot_tasks.append( ( plot_xiaoqu.generate_puncture_orbit_plot, (binary_results_directory, figure_directory) ) )
|
|
plot_tasks.append( ( plot_xiaoqu.generate_puncture_orbit_plot3D, (binary_results_directory, figure_directory) ) )
|
|
|
|
## Plot black hole separation vs. time
|
|
plot_tasks.append( ( plot_xiaoqu.generate_puncture_distence_plot, (binary_results_directory, figure_directory) ) )
|
|
|
|
## Plot gravitational waveforms (psi4 and strain amplitude)
|
|
for i in range(input_data.Detector_Number):
|
|
plot_tasks.append( ( plot_xiaoqu.generate_gravitational_wave_psi4_plot, (binary_results_directory, figure_directory, i) ) )
|
|
plot_tasks.append( ( plot_GW_strain_amplitude_xiaoqu.generate_gravitational_wave_amplitude_plot, (binary_results_directory, figure_directory, i) ) )
|
|
|
|
## Plot ADM mass evolution
|
|
for i in range(input_data.Detector_Number):
|
|
plot_tasks.append( ( plot_xiaoqu.generate_ADMmass_plot, (binary_results_directory, figure_directory, i) ) )
|
|
|
|
## Plot Hamiltonian constraint violation over time
|
|
for i in range(input_data.grid_level):
|
|
plot_tasks.append( ( plot_xiaoqu.generate_constraint_check_plot, (binary_results_directory, figure_directory, i) ) )
|
|
|
|
run_plot_tasks_parallel(plot_tasks)
|
|
|
|
## Plot stored binary data
|
|
plot_xiaoqu.generate_binary_data_plot( binary_results_directory, figure_directory )
|
|
|
|
print( )
|
|
print( f" This Program Cost = {elapsed_time} Seconds " )
|
|
print( )
|
|
|
|
|
|
##################################################################
|
|
|
|
print( )
|
|
print( " The AMSS-NCKU-Python simulation is successfully finished, thanks for using !!! " )
|
|
print( )
|
|
|
|
##################################################################
|
|
|
|
|