From bf71c297e311650f9fc1dee84a717830ac33a5bf Mon Sep 17 00:00:00 2001 From: Marco Garten Date: Fri, 18 Oct 2024 14:54:15 -0700 Subject: [PATCH] Added automated test based on LPI example Even though the laser ion test is named as a dependency it is running this test again. That should ideally be avoided. It would be good to just run the analysis script as test. --- .../laser_ion/CMakeLists.txt | 21 +++++++ .../laser_ion/analysis_time_avg_diags.py | 62 +++++++++++++++++++ .../laser_ion/inputs_test_2d_laser_ion_acc | 7 ++- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100755 Examples/Physics_applications/laser_ion/analysis_time_avg_diags.py diff --git a/Examples/Physics_applications/laser_ion/CMakeLists.txt b/Examples/Physics_applications/laser_ion/CMakeLists.txt index b259421d709..9bcf0a60370 100644 --- a/Examples/Physics_applications/laser_ion/CMakeLists.txt +++ b/Examples/Physics_applications/laser_ion/CMakeLists.txt @@ -11,6 +11,16 @@ add_warpx_test( OFF # dependency ) +add_warpx_test( + test_2d_laser_ion_acc_time_avg # name + 2 # dims + 2 # nprocs + inputs_test_2d_laser_ion_acc # inputs; will not be used b/c dependent test + analysis_time_avg_diags.py # analysis + diags/diagTimeAvg/ # output + test_2d_laser_ion_acc # dependency +) + add_warpx_test( test_2d_laser_ion_acc_picmi # name 2 # dims @@ -20,3 +30,14 @@ add_warpx_test( diags/diagInst/ # output OFF # dependency ) + +# We do not have an intervals parser for PICMI yet which would accept more than a single integer for the output period +#add_warpx_test( +# test_2d_laser_ion_acc_time_avg_picmi # name +# 2 # dims +# 2 # nprocs +# inputs_test_2d_laser_ion_acc_picmi.py # inputs +# analysis_time_avg_diags.py # analysis +# diags/diagTimeAvg/ # output +# test_2d_laser_ion_acc_picmi # dependency +#) diff --git a/Examples/Physics_applications/laser_ion/analysis_time_avg_diags.py b/Examples/Physics_applications/laser_ion/analysis_time_avg_diags.py new file mode 100755 index 00000000000..3a24af91d0d --- /dev/null +++ b/Examples/Physics_applications/laser_ion/analysis_time_avg_diags.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import sys +import numpy as np +import openpmd_api as io + + +def load_field_from_iteration(series, iteration : int, field : str, coord : str = None) -> np.ndarray: + """Load iteration of field data from file.""" + + it = series.iterations[iteration] + field_obj = it.meshes[f"{field}"] + + if field_obj.scalar: + field_data = field_obj[io.Mesh_Record_Component.SCALAR].load_chunk() + elif coord in [item[0] for item in list(field_obj.items())]: + field_data = field_obj[coord].load_chunk() + else: + raise Exception(f"Specified coordinate: f{coord} is not available for field: f{field}.") + series.flush() + + return field_data + + +def main(): + + field = "E" + coord = "z" + avg_period_steps = 5 + avg_output_step = 100 + + path_tpl_inst = "diags/diagInst/openpmd_%T.h5" + + dir_avg = sys.argv[1] + path_tpl_avg = f"{dir_avg}/openpmd_%T.h5" + + si = io.Series(path_tpl_inst, io.Access.read_only) + sa = io.Series(path_tpl_avg, io.Access.read_only) + + ii0 = si.iterations[0] + fi0 = ii0.meshes[field][coord] + shape = fi0.shape + + data_inst = np.zeros(shape) + + for i in np.arange(avg_output_step-avg_period_steps+1,avg_output_step+1): + data_inst += load_field_from_iteration(si, i, field, coord) + + data_inst = data_inst / avg_period_steps + + data_avg = load_field_from_iteration(sa, avg_output_step, field, coord) + + # Compare the data + if np.allclose(data_inst, data_avg): + print("Test passed: actual data is close to expected data.") + else: + print("Test failed: actual data is not close to expected data.") + sys.exit(1) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Examples/Physics_applications/laser_ion/inputs_test_2d_laser_ion_acc b/Examples/Physics_applications/laser_ion/inputs_test_2d_laser_ion_acc index a29da92ce80..d69ed6dc375 100644 --- a/Examples/Physics_applications/laser_ion/inputs_test_2d_laser_ion_acc +++ b/Examples/Physics_applications/laser_ion/inputs_test_2d_laser_ion_acc @@ -202,7 +202,8 @@ laser1.profile_focal_distance = 4.0e-6 # focal distance from the antenna [m] # diagnostics.diags_names = diagInst diagTimeAvg openPMDfw openPMDbw -diagInst.intervals = 100 +# instantaneous field and particle diagnostic +diagInst.intervals = 100,96:100 # second interval only for CI testing the time-averaged diags diagInst.diag_type = Full diagInst.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz rho rho_electrons rho_hydrogen # reduce resolution of output fields @@ -213,10 +214,12 @@ diagInst.hydrogen.plot_filter_function(t,x,y,z,ux,uy,uz) = (uz>=0) * (x<1.0e-6) diagInst.format = openpmd diagInst.openpmd_backend = h5 +# time-averaged particle and field diagnostic diagTimeAvg.intervals = 100 diagTimeAvg.diag_type = TimeAveraged diagTimeAvg.time_average_mode = dynamic_start -diagTimeAvg.average_period_time = 2.67e-15 # period of 800 nm light waves +#diagTimeAvg.average_period_time = 2.67e-15 # period of 800 nm light waves +diagTimeAvg.average_period_steps = 5 # use only either `time` or `steps` diagTimeAvg.write_species = 0 diagTimeAvg.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz rho rho_electrons rho_hydrogen # reduce resolution of output fields