-
Notifications
You must be signed in to change notification settings - Fork 231
Correct and test fusion module in RZ geometry #3255
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
Changes from 88 commits
1c46d5c
be57c60
1fd6f05
5cc92e5
fc3334d
d744b7a
d768660
2e5d076
029f3e1
8ce861d
f716fea
9763ad3
ea3217e
c5d067c
9549830
c0309bd
78be34e
d6639d6
24a743d
c096d29
08cd304
139eebf
c6e7c92
6ab97ec
6f7e7c0
ff08305
428a179
fa01fdd
88fcaf5
0a59ecd
821356d
ad24117
ca278c6
2cdd394
3bc13d4
eb91623
d82bb73
2a5cc53
323950d
61b0769
bbf95b8
70c5fe6
65409f4
c82c8e7
9510dee
2a41771
24d1fc7
73c8d9d
5c31035
72fb317
542d2cb
c9a8661
b228c29
00e5d09
dd1ca83
665451f
284f370
c3cff64
67d0ff1
8137f01
637ea1b
a163b8a
b11812d
eb76522
a61aef3
5b6585d
d1bd322
e29d5ab
a117150
e787250
b45e99d
471e263
4d19e2b
010c6cc
e41378d
042b5f5
8f8afd8
00055ae
a003d5c
51190a0
7d188b4
c2529a3
27994fc
e85d2c5
f1994ea
422586b
337b2ed
70a864e
55ad0e0
54ca811
65b43eb
d399ac2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,15 +66,26 @@ | |
|
|
||
| E_fusion = 17.5893*MeV_to_Joule # Energy released during the fusion reaction | ||
|
|
||
| ## Checks whether this is the 2D or the 3D test | ||
| is_RZ = "RZ" in sys.argv[1] | ||
|
|
||
| ## Some numerical parameters for this test | ||
| size_x = 8 | ||
| size_y = 8 | ||
| size_z = 16 | ||
| dV_total = size_x*size_y*size_z # Total simulation volume | ||
| if is_RZ: | ||
| dV_slice = np.pi * size_x**2 | ||
| yt_z_string = "particle_position_y" | ||
| nppcell_1 = 10000*8 | ||
| nppcell_2 = 900*8 | ||
| else: | ||
| dV_slice = size_x*size_y | ||
| yt_z_string = "particle_position_z" | ||
| nppcell_1 = 10000 | ||
| nppcell_2 = 900 | ||
| # Volume of a slice corresponding to a single cell in the z direction. In tests 1 and 2, all the | ||
| # particles of a given species in the same slice have the exact same momentum | ||
| dV_slice = size_x*size_y | ||
| dt = 1./(scc.c*np.sqrt(3.)) | ||
|
|
||
| # In test 1 and 2, the energy in cells number i (in z direction) is typically Energy_step * i**2 | ||
| Energy_step = 22.*keV_to_Joule | ||
|
|
||
|
|
@@ -89,7 +100,7 @@ def add_existing_species_to_dict(yt_ad, data_dict, species_name, prefix, suffix) | |
| data_dict[prefix+"_w_"+suffix] = yt_ad[species_name, "particle_weight"].v | ||
| data_dict[prefix+"_id_"+suffix] = yt_ad[species_name, "particle_id"].v | ||
| data_dict[prefix+"_cpu_"+suffix] = yt_ad[species_name, "particle_cpu"].v | ||
| data_dict[prefix+"_z_"+suffix] = yt_ad[species_name, "particle_position_z"].v | ||
| data_dict[prefix+"_z_"+suffix] = yt_ad[species_name, yt_z_string].v | ||
|
|
||
| def add_empty_species_to_dict(data_dict, species_name, prefix, suffix): | ||
| data_dict[prefix+"_px_"+suffix] = np.empty(0) | ||
|
|
@@ -263,8 +274,11 @@ def expected_weight_com(E_com, reactant0_density, reactant1_density, dV, dt): | |
| def check_macroparticle_number(data, fusion_probability_target_value, num_pair_per_cell): | ||
| ## Checks that the number of macroparticles is as expected for the first and second tests | ||
|
|
||
| ## The first slice 0 < z < 1 does not contribute to product species creation | ||
| numcells = dV_total - dV_slice | ||
| ## The first slice 0 < z < 1 does not contribute to alpha creation | ||
| if is_RZ: | ||
| numcells = size_x*(size_z-1) | ||
| else: | ||
| numcells = size_x*size_y*(size_z-1) | ||
| ## In these tests, the fusion_multiplier is so high that the fusion probability per pair is | ||
| ## equal to the parameter fusion_probability_target_value | ||
| fusion_probability_per_pair = fusion_probability_target_value | ||
|
|
@@ -315,7 +329,7 @@ def compute_E_com2(data): | |
| p_reactant0_sq = 2.*mass[reactant_species[0]]*(Energy_step*np.arange(size_z)**2) | ||
| return p_sq_reactant1_frame_to_E_COM_frame(p_reactant0_sq) | ||
|
|
||
| def check_fusion_yield(data, expected_fusion_number, E_com, reactant0_density, reactant1_density): | ||
| def check_fusion_yield(data, expected_fusion_number, E_com, reactant0_density, reactant1_density, dt): | ||
| ## Checks that the fusion yield is as expected for the first and second tests. | ||
| product_weight_theory = expected_weight_com(E_com/keV_to_Joule, | ||
| reactant0_density, reactant1_density, dV_slice, dt) | ||
|
|
@@ -330,24 +344,25 @@ def check_fusion_yield(data, expected_fusion_number, E_com, reactant0_density, r | |
| assert(np.all(is_close(product_weight_theory, product_weight_simulation, | ||
| rtol = 5.*relative_std_weight))) | ||
|
|
||
| def specific_check1(data): | ||
| check_isotropy(data, relative_tolerance = 3.e-2) | ||
| def specific_check1(data, dt): | ||
| if not is_RZ: | ||
| check_isotropy(data, relative_tolerance = 3.e-2) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't check for isotropy in the RZ case, since the distribution of momentum for the products is not yet correct. |
||
| expected_fusion_number = check_macroparticle_number(data, | ||
| fusion_probability_target_value = 0.002, | ||
| num_pair_per_cell = 10000) | ||
| num_pair_per_cell = nppcell_1) | ||
| E_com = compute_E_com1(data) | ||
| check_fusion_yield(data, expected_fusion_number, E_com, reactant0_density = 1., | ||
| reactant1_density = 1.) | ||
| reactant1_density = 1., dt=dt) | ||
|
|
||
| def specific_check2(data): | ||
| def specific_check2(data, dt): | ||
| check_xy_isotropy(data) | ||
| ## Only 900 particles pairs per cell here because we ignore the 10% of reactants that are at rest | ||
| expected_fusion_number = check_macroparticle_number(data, | ||
| fusion_probability_target_value = 0.02, | ||
| num_pair_per_cell = 900) | ||
| num_pair_per_cell = nppcell_2) | ||
| E_com = compute_E_com2(data) | ||
| check_fusion_yield(data, expected_fusion_number, E_com, reactant0_density = 1.e20, | ||
| reactant1_density = 1.e26) | ||
| reactant1_density = 1.e26, dt=dt) | ||
|
|
||
| def check_charge_conservation(rho_start, rho_end): | ||
| assert(np.all(is_close(rho_start, rho_end, rtol=2.e-11))) | ||
|
|
@@ -359,6 +374,7 @@ def main(): | |
| ds_start = yt.load(filename_start) | ||
| ad_end = ds_end.all_data() | ||
| ad_start = ds_start.all_data() | ||
| dt = float(ds_end.current_time - ds_start.current_time) | ||
| field_data_end = ds_end.covering_grid(level=0, left_edge=ds_end.domain_left_edge, | ||
| dims=ds_end.domain_dimensions) | ||
| field_data_start = ds_start.covering_grid(level=0, left_edge=ds_start.domain_left_edge, | ||
|
|
@@ -379,7 +395,7 @@ def main(): | |
| generic_check(data) | ||
|
|
||
| # Checks that are specific to test number i | ||
| eval("specific_check"+str(i)+"(data)") | ||
| eval("specific_check"+str(i)+"(data, dt)") | ||
|
|
||
| rho_start = field_data_start["rho"].to_ndarray() | ||
| rho_end = field_data_end["rho"].to_ndarray() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| ################################# | ||
| ####### GENERAL PARAMETERS ###### | ||
| ################################# | ||
| ## With these parameters, each cell has a size of exactly 1 by 1 by 1 | ||
| max_step = 1 | ||
| amr.n_cell = 8 16 | ||
| amr.max_grid_size = 8 | ||
| amr.blocking_factor = 8 | ||
| amr.max_level = 0 | ||
| geometry.dims = RZ | ||
| geometry.prob_lo = 0. 0. | ||
| geometry.prob_hi = 8. 16. | ||
|
|
||
| ################################# | ||
| ###### Boundary Condition ####### | ||
| ################################# | ||
| boundary.field_lo = none periodic | ||
| boundary.field_hi = pec periodic | ||
|
|
||
| ################################# | ||
| ############ NUMERICS ########### | ||
| ################################# | ||
| warpx.verbose = 1 | ||
| warpx.cfl = 1.0 | ||
|
|
||
| # Order of particle shape factors | ||
| algo.particle_shape = 1 | ||
|
|
||
| ################################# | ||
| ############ PLASMA ############# | ||
| ################################# | ||
| particles.species_names = deuterium1 tritium1 helium1 neutron1 deuterium2 tritium2 helium2 neutron2 | ||
|
|
||
| my_constants.m_deuterium = 2.01410177812*m_u | ||
| my_constants.m_tritium = 3.0160492779*m_u | ||
| my_constants.m_reduced = m_deuterium*m_tritium/(m_deuterium+m_tritium) | ||
| my_constants.keV_to_J = 1.e3*q_e | ||
| my_constants.Energy_step = 22. * keV_to_J | ||
|
|
||
| deuterium1.species_type = deuterium | ||
| deuterium1.injection_style = "NRandomPerCell" | ||
| deuterium1.num_particles_per_cell = 80000 | ||
| deuterium1.profile = constant | ||
| deuterium1.density = 1. | ||
| deuterium1.momentum_distribution_type = parse_momentum_function | ||
| ## Thanks to the floor, all particles in the same cell have the exact same momentum | ||
| deuterium1.momentum_function_ux(x,y,z) = "u = sqrt(2*m_reduced*Energy_step*(floor(z)**2))/(m_deuterium*clight); if(x*x+y*y>0.0, -u*y/sqrt(x*x+y*y), 0.0)" # azimuthal velocity | ||
| deuterium1.momentum_function_uy(x,y,z) = "u = sqrt(2*m_reduced*Energy_step*(floor(z)**2))/(m_deuterium*clight); if(x*x+y*y>0.0, u*x/sqrt(x*x+y*y), 0.0)" # azimuthal velocity | ||
| deuterium1.momentum_function_uz(x,y,z) = "0" | ||
| deuterium1.do_not_push = 1 | ||
| deuterium1.do_not_deposit = 1 | ||
|
|
||
| tritium1.species_type = tritium | ||
| tritium1.injection_style = "NRandomPerCell" | ||
| tritium1.num_particles_per_cell = 80000 | ||
| tritium1.profile = constant | ||
| tritium1.density = 1. | ||
| tritium1.momentum_distribution_type = "parse_momentum_function" | ||
| ## Thanks to the floor, all particles in the same cell have the exact same momentum | ||
| tritium1.momentum_function_ux(x,y,z) = "u = sqrt(2*m_reduced*Energy_step*(floor(z)**2))/(m_tritium*clight); if(x*x+y*y>0.0, u*y/sqrt(x*x+y*y), 0.0)" # counter-streaming azimuthal velocity | ||
| tritium1.momentum_function_uy(x,y,z) = "u = sqrt(2*m_reduced*Energy_step*(floor(z)**2))/(m_tritium*clight); if(x*x+y*y>0.0, -u*x/sqrt(x*x+y*y), 0.0)" # counter-streaming azimuthal velocity | ||
| tritium1.momentum_function_uz(x,y,z) = 0 | ||
| tritium1.do_not_push = 1 | ||
| tritium1.do_not_deposit = 1 | ||
|
|
||
| helium1.species_type = helium4 | ||
| helium1.do_not_push = 1 | ||
| helium1.do_not_deposit = 1 | ||
|
|
||
| neutron1.species_type = neutron | ||
| neutron1.do_not_push = 1 | ||
| neutron1.do_not_deposit = 1 | ||
|
|
||
| my_constants.background_dens = 1.e26 | ||
| my_constants.beam_dens = 1.e20 | ||
|
|
||
| deuterium2.species_type = deuterium | ||
| deuterium2.injection_style = "NRandomPerCell" | ||
| deuterium2.num_particles_per_cell = 8000 | ||
| deuterium2.profile = "parse_density_function" | ||
| ## A tenth of the macroparticles in each cell is made of immobile high-density background deuteriums. | ||
| ## The other nine tenths are made of fast low-density beam deuteriums. | ||
| deuterium2.density_function(x,y,z) = if(y - floor(y) < 0.1, 10.*background_dens, 10./9.*beam_dens) | ||
| deuterium2.momentum_distribution_type = "parse_momentum_function" | ||
| deuterium2.momentum_function_ux(x,y,z) = 0. | ||
| deuterium2.momentum_function_uy(x,y,z) = 0. | ||
| deuterium2.momentum_function_uz(x,y,z) = "if(y - floor(y) < 0.1, | ||
| 0., sqrt(2*m_deuterium*Energy_step*(floor(z)**2))/(m_deuterium*clight))" | ||
| deuterium2.do_not_push = 1 | ||
| deuterium2.do_not_deposit = 1 | ||
|
|
||
| tritium2.species_type = tritium | ||
| tritium2.injection_style = "NRandomPerCell" | ||
| tritium2.num_particles_per_cell = 800 | ||
| tritium2.profile = constant | ||
| tritium2.density = background_dens | ||
| tritium2.momentum_distribution_type = "constant" | ||
| tritium2.do_not_push = 1 | ||
| tritium2.do_not_deposit = 1 | ||
|
|
||
| helium2.species_type = helium4 | ||
| helium2.do_not_push = 1 | ||
| helium2.do_not_deposit = 1 | ||
|
|
||
| neutron2.species_type = neutron | ||
| neutron2.do_not_push = 1 | ||
| neutron2.do_not_deposit = 1 | ||
|
|
||
| ################################# | ||
| ############ COLLISION ########## | ||
| ################################# | ||
| collisions.collision_names = DTF1 DTF2 | ||
|
|
||
| DTF1.species = deuterium1 tritium1 | ||
| DTF1.product_species = helium1 neutron1 | ||
| DTF1.type = nuclearfusion | ||
| DTF1.fusion_multiplier = 1.e50 | ||
|
|
||
| DTF2.species = deuterium2 tritium2 | ||
| DTF2.product_species = helium2 neutron2 | ||
| DTF2.type = nuclearfusion | ||
| DTF2.fusion_multiplier = 1.e15 | ||
| DTF2.fusion_probability_target_value = 0.02 | ||
|
|
||
| # Diagnostics | ||
| diagnostics.diags_names = diag1 | ||
| diag1.intervals = 1 | ||
| diag1.diag_type = Full | ||
| diag1.fields_to_plot = rho |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -90,4 +90,4 @@ | |
| "particle_position_z": 819255.8152412223, | ||
| "particle_weight": 1.0239999999424347e+29 | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| { | ||
| "deuterium1": { | ||
| "particle_cpu": 5120000.0, | ||
| "particle_id": 26214405120000.0, | ||
| "particle_momentum_x": 1.8388106511899905e-13, | ||
| "particle_momentum_y": 1.837868790009435e-13, | ||
| "particle_momentum_z": 0.0, | ||
| "particle_position_x": 40959919.499819286, | ||
| "particle_position_y": 81919224.48541151, | ||
| "particle_theta": 32166860.23003994, | ||
| "particle_weight": 3216.984554806547 | ||
| }, | ||
| "deuterium2": { | ||
| "particle_cpu": 512000.0, | ||
| "particle_id": 10747904512000.0, | ||
| "particle_momentum_x": 0.0, | ||
| "particle_momentum_y": 0.0, | ||
| "particle_momentum_z": 3.336364094249911e-14, | ||
| "particle_position_x": 4095908.9083809257, | ||
| "particle_position_y": 8192069.080030457, | ||
| "particle_theta": 3216444.348910214, | ||
| "particle_weight": 3.1898417901971444e+29 | ||
| }, | ||
| "helium1": { | ||
| "particle_cpu": 20316.0, | ||
| "particle_id": 412875410532.0, | ||
| "particle_momentum_x": 1.858124399143442e-15, | ||
| "particle_momentum_y": 1.876715110797694e-15, | ||
| "particle_momentum_z": 1.7098432207359157e-15, | ||
| "particle_position_x": 152920.23233108618, | ||
| "particle_position_y": 323733.9138644398, | ||
| "particle_theta": 120064.13771707338, | ||
| "particle_weight": 1.603083276067953e-27 | ||
| }, | ||
| "helium2": { | ||
| "particle_cpu": 17912.0, | ||
| "particle_id": 368771109674.0, | ||
| "particle_momentum_x": 1.5195006688950936e-15, | ||
| "particle_momentum_y": 1.52430083815551e-15, | ||
| "particle_momentum_z": 1.7654865863613367e-15, | ||
| "particle_position_x": 136867.63803188328, | ||
| "particle_position_y": 286903.30393175944, | ||
| "particle_theta": 107912.20520382549, | ||
| "particle_weight": 2.0862696876352987e+19 | ||
| }, | ||
| "lev=0": { | ||
| "rho": 0.0 | ||
| }, | ||
| "neutron1": { | ||
| "particle_cpu": 20316.0, | ||
| "particle_id": 413607415812.0, | ||
| "particle_momentum_x": 1.7160671487712845e-15, | ||
| "particle_momentum_y": 1.7154753069055672e-15, | ||
| "particle_momentum_z": 1.7098432207359157e-15, | ||
| "particle_position_x": 152920.23233108618, | ||
| "particle_position_y": 323733.9138644398, | ||
| "particle_theta": 120064.13771707338, | ||
| "particle_weight": 1.603083276067953e-27 | ||
| }, | ||
| "neutron2": { | ||
| "particle_cpu": 17912.0, | ||
| "particle_id": 369350387194.0, | ||
| "particle_momentum_x": 1.5195006688950936e-15, | ||
| "particle_momentum_y": 1.52430083815551e-15, | ||
| "particle_momentum_z": 1.5463311225724366e-15, | ||
| "particle_position_x": 136867.63803188328, | ||
| "particle_position_y": 286903.30393175944, | ||
| "particle_theta": 107912.20520382549, | ||
| "particle_weight": 2.0862696876352987e+19 | ||
| }, | ||
| "tritium1": { | ||
| "particle_cpu": 5120000.0, | ||
| "particle_id": 78643205120000.0, | ||
| "particle_momentum_x": 1.8384658063720362e-13, | ||
| "particle_momentum_y": 1.8381593257898129e-13, | ||
| "particle_momentum_z": 0.0, | ||
| "particle_position_x": 40961278.052658774, | ||
| "particle_position_y": 81919046.8061561, | ||
| "particle_theta": 32163925.891884565, | ||
| "particle_weight": 3217.0912552970394 | ||
| }, | ||
| "tritium2": { | ||
| "particle_cpu": 51200.0, | ||
| "particle_id": 1103626291200.0, | ||
| "particle_momentum_x": 0.0, | ||
| "particle_momentum_y": 0.0, | ||
| "particle_momentum_z": 0.0, | ||
| "particle_position_x": 409793.9651940968, | ||
| "particle_position_y": 819237.3558155322, | ||
| "particle_theta": 321974.4557387621, | ||
| "particle_weight": 3.218514276139388e+29 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2216,6 +2216,22 @@ compileTest = 0 | |||||
| doVis = 0 | ||||||
| analysisRoutine = Examples/Modules/nuclear_fusion/analysis_deuterium_tritium_fusion.py | ||||||
|
|
||||||
| [Deuterium_Tritium_Fusion_RZ] | ||||||
| buildDir = . | ||||||
| inputFile = Examples/Modules/nuclear_fusion/inputs_deuterium_tritium_rz | ||||||
| runtime_params = warpx.do_dynamic_scheduling=0 warpx.serialize_initial_conditions=1 | ||||||
| dim = 2 | ||||||
| addToCompileString = | ||||||
| cmakeSetupOpts = -DWarpX_DIMS=RZ | ||||||
| restartTest = 0 | ||||||
| useMPI = 1 | ||||||
| numprocs = 2 | ||||||
| useOMP = 1 | ||||||
| numthreads = 2 | ||||||
|
||||||
| numthreads = 2 | |
| numthreads = 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other way to do this (which I personally find a little more robust, because it does not rely on the test's name) is to parse the output file
warpx_used_inputsand determine the geometry from there: