|
| 1 | +import pathsim |
| 2 | +from pathsim import Simulation, Connection |
| 3 | +import numpy as np |
| 4 | +import matplotlib.pyplot as plt |
| 5 | +import pathview |
| 6 | + |
| 7 | +from tritium_model import ( |
| 8 | + neutron_rate, |
| 9 | + total_irradiation_time, |
| 10 | + k_top, |
| 11 | + baby_model, |
| 12 | + measured_TBR, |
| 13 | +) |
| 14 | + |
| 15 | +# Create global variables |
| 16 | +A_OV = (baby_model.A_wall.to("m^2")).magnitude |
| 17 | +A_IV = (baby_model.A_top.to("m^2")).magnitude |
| 18 | +baby_vol = (baby_model.volume.to("m^3")).magnitude |
| 19 | +IV_to_OV_ratio = 70 / 12 |
| 20 | +k_IV = k_top.to("m/s").magnitude * 0.6 |
| 21 | +k_OV = k_IV / (IV_to_OV_ratio) |
| 22 | +# neutron_rate = (350 / 250) * 1.3e09 |
| 23 | +neutron_rate = neutron_rate.to("n/s").magnitude |
| 24 | +irradiation_time = total_irradiation_time.to("s").magnitude |
| 25 | + |
| 26 | + |
| 27 | +tbr = measured_TBR.to("dimensionless").magnitude |
| 28 | + |
| 29 | +IV_gas_residence_time = 0.01 * baby_vol / (A_IV * k_IV) |
| 30 | +OV_gas_residence_time = 3 * baby_vol / (A_OV * k_OV) |
| 31 | + |
| 32 | +# Create blocks |
| 33 | +blocks, events = [], [] |
| 34 | + |
| 35 | +x_1_4 = pathsim.blocks.amplifier.Amplifier(gain=-1) |
| 36 | +blocks.append(x_1_4) |
| 37 | + |
| 38 | +neutron_rate_6 = pathsim.blocks.adder.Adder() |
| 39 | +blocks.append(neutron_rate_6) |
| 40 | + |
| 41 | +tbr_7 = pathsim.blocks.amplifier.Amplifier(gain=tbr) |
| 42 | +blocks.append(tbr_7) |
| 43 | + |
| 44 | +baby_8 = pathview.custom_pathsim_blocks.Process( |
| 45 | + residence_time=baby_vol / (k_IV * A_IV + k_OV * A_OV), |
| 46 | +) |
| 47 | +blocks.append(baby_8) |
| 48 | + |
| 49 | +iv_vial_activity_21 = pathsim.blocks.scope.Scope( |
| 50 | + labels=[ |
| 51 | + "IV bubbler (vial1)", |
| 52 | + "IV bubbler (vial2)", |
| 53 | + "IV bubbler (vial3)", |
| 54 | + "IV bubbler (vial4)", |
| 55 | + ] |
| 56 | +) |
| 57 | +blocks.append(iv_vial_activity_21) |
| 58 | + |
| 59 | +soluble_vs_insoluble_1 = pathview.custom_pathsim_blocks.Splitter2(f1=0.01, f2=0.99) |
| 60 | +blocks.append(soluble_vs_insoluble_1) |
| 61 | + |
| 62 | +iv_bubbler_23 = pathview.custom_pathsim_blocks.Bubbler( |
| 63 | + conversion_efficiency=0.95, |
| 64 | + vial_efficiency=0.9, |
| 65 | + replacement_times=np.array([0.4, 0.6, 1, 1.5, 2.5, 4]) * 24 * 3600, |
| 66 | +) |
| 67 | +events_iv_bubbler_23 = iv_bubbler_23.create_reset_events() |
| 68 | +events += events_iv_bubbler_23 |
| 69 | +blocks.append(iv_bubbler_23) |
| 70 | + |
| 71 | +iv_vs_ov_24 = pathview.custom_pathsim_blocks.Splitter2( |
| 72 | + f1=k_IV / (k_IV + k_OV), f2=k_OV / (k_IV + k_OV) |
| 73 | +) |
| 74 | +blocks.append(iv_vs_ov_24) |
| 75 | + |
| 76 | +soluble_vs_insoluble_25 = pathview.custom_pathsim_blocks.Splitter2(f1=0.01, f2=0.99) |
| 77 | +blocks.append(soluble_vs_insoluble_25) |
| 78 | + |
| 79 | +ov_bubbler_26 = pathview.custom_pathsim_blocks.Bubbler( |
| 80 | + conversion_efficiency=0.95, |
| 81 | + vial_efficiency=0.9, |
| 82 | + replacement_times=np.array([1, 2.5, 4]) * 24 * 3600, |
| 83 | +) |
| 84 | +events_ov_bubbler_26 = ov_bubbler_26.create_reset_events() |
| 85 | +events += events_ov_bubbler_26 |
| 86 | +blocks.append(ov_bubbler_26) |
| 87 | + |
| 88 | +environment_27 = pathview.custom_pathsim_blocks.Integrator() |
| 89 | +blocks.append(environment_27) |
| 90 | + |
| 91 | +ov_vial_activity_28 = pathsim.blocks.scope.Scope( |
| 92 | + labels=[ |
| 93 | + "OV bubbler (vial1)", |
| 94 | + "OV bubbler (vial2)", |
| 95 | + "OV bubbler (vial3)", |
| 96 | + "OV bubbler (vial4)", |
| 97 | + ] |
| 98 | +) |
| 99 | +blocks.append(ov_vial_activity_28) |
| 100 | + |
| 101 | +baby_inventory_30 = pathsim.blocks.scope.Scope(labels=["BABY (inv)"]) |
| 102 | +blocks.append(baby_inventory_30) |
| 103 | + |
| 104 | +stepsource_31 = pathsim.blocks.sources.StepSource( |
| 105 | + amplitude=neutron_rate, tau=irradiation_time |
| 106 | +) |
| 107 | +blocks.append(stepsource_31) |
| 108 | + |
| 109 | +stepsource_32 = pathsim.blocks.sources.StepSource(amplitude=neutron_rate, tau=0) |
| 110 | +blocks.append(stepsource_32) |
| 111 | + |
| 112 | +neutron_source_33 = pathsim.blocks.scope.Scope(labels=["Neutron rate"]) |
| 113 | +blocks.append(neutron_source_33) |
| 114 | + |
| 115 | +cumulative_release_34 = pathsim.blocks.scope.Scope(labels=["IV", "OV"]) |
| 116 | +blocks.append(cumulative_release_34) |
| 117 | + |
| 118 | +iv_35 = pathview.custom_pathsim_blocks.Integrator() |
| 119 | +blocks.append(iv_35) |
| 120 | + |
| 121 | +ov_36 = pathview.custom_pathsim_blocks.Integrator() |
| 122 | +blocks.append(ov_36) |
| 123 | + |
| 124 | +iv_gas_37 = pathview.custom_pathsim_blocks.Process( |
| 125 | + residence_time=IV_gas_residence_time, |
| 126 | +) |
| 127 | +blocks.append(iv_gas_37) |
| 128 | + |
| 129 | +ov_gas_38 = pathview.custom_pathsim_blocks.Process( |
| 130 | + residence_time=OV_gas_residence_time, |
| 131 | +) |
| 132 | +blocks.append(ov_gas_38) |
| 133 | + |
| 134 | + |
| 135 | +# Create events |
| 136 | + |
| 137 | + |
| 138 | +# Create connections |
| 139 | + |
| 140 | +connections = [ |
| 141 | + Connection(x_1_4[0], neutron_rate_6[0]), |
| 142 | + Connection(neutron_rate_6[0], tbr_7[0]), |
| 143 | + Connection(tbr_7[0], baby_8[0]), |
| 144 | + Connection(soluble_vs_insoluble_1["source1"], iv_bubbler_23["sample_in_soluble"]), |
| 145 | + Connection(soluble_vs_insoluble_1["source2"], iv_bubbler_23["sample_in_insoluble"]), |
| 146 | + Connection(iv_bubbler_23["vial1"], iv_vial_activity_21[0]), |
| 147 | + Connection(iv_bubbler_23["vial2"], iv_vial_activity_21[1]), |
| 148 | + Connection(iv_bubbler_23["vial3"], iv_vial_activity_21[2]), |
| 149 | + Connection(iv_bubbler_23["vial4"], iv_vial_activity_21[3]), |
| 150 | + Connection(baby_8["mass_flow_rate"], iv_vs_ov_24[0]), |
| 151 | + Connection(soluble_vs_insoluble_25["source1"], ov_bubbler_26["sample_in_soluble"]), |
| 152 | + Connection( |
| 153 | + soluble_vs_insoluble_25["source2"], ov_bubbler_26["sample_in_insoluble"] |
| 154 | + ), |
| 155 | + Connection(iv_bubbler_23["sample_out"], environment_27[0]), |
| 156 | + Connection(ov_bubbler_26["sample_out"], environment_27[1]), |
| 157 | + Connection(ov_bubbler_26["vial1"], ov_vial_activity_28[0]), |
| 158 | + Connection(ov_bubbler_26["vial2"], ov_vial_activity_28[1]), |
| 159 | + Connection(ov_bubbler_26["vial3"], ov_vial_activity_28[2]), |
| 160 | + Connection(ov_bubbler_26["vial4"], ov_vial_activity_28[3]), |
| 161 | + Connection(baby_8["inv"], baby_inventory_30[0]), |
| 162 | + Connection(stepsource_31[0], x_1_4[0]), |
| 163 | + Connection(stepsource_32[0], neutron_rate_6[1]), |
| 164 | + Connection(neutron_rate_6[0], neutron_source_33[0]), |
| 165 | + Connection(iv_35[0], cumulative_release_34[0]), |
| 166 | + Connection(ov_36[0], cumulative_release_34[1]), |
| 167 | + Connection(iv_vs_ov_24["source1"], iv_gas_37[0]), |
| 168 | + Connection(iv_gas_37["mass_flow_rate"], iv_35[0]), |
| 169 | + Connection(iv_gas_37["mass_flow_rate"], soluble_vs_insoluble_1[0]), |
| 170 | + Connection(iv_vs_ov_24["source2"], ov_gas_38[0]), |
| 171 | + Connection(ov_gas_38["mass_flow_rate"], ov_36[0]), |
| 172 | + Connection(ov_gas_38["mass_flow_rate"], soluble_vs_insoluble_25[0]), |
| 173 | +] |
| 174 | + |
| 175 | +# Create simulation |
| 176 | +my_simulation = Simulation( |
| 177 | + blocks, |
| 178 | + connections, |
| 179 | + events=events, |
| 180 | + Solver=pathsim.solvers.SSPRK22, |
| 181 | + dt=100, |
| 182 | + dt_max=1.0, |
| 183 | + dt_min=1e-6, |
| 184 | + iterations_max=100, |
| 185 | + log=True, |
| 186 | + tolerance_fpi=1e-6, |
| 187 | + **{"tolerance_lte_rel": 1e-4, "tolerance_lte_abs": 1e-9}, |
| 188 | +) |
| 189 | + |
| 190 | +if __name__ == "__main__": |
| 191 | + my_simulation.run(8 * 24 * 3600) |
| 192 | + |
| 193 | + # Optional: Plotting results |
| 194 | + scopes = [block for block in blocks if isinstance(block, pathsim.blocks.Scope)] |
| 195 | + fig, axs = plt.subplots( |
| 196 | + nrows=len(scopes), sharex=True, figsize=(10, 5 * len(scopes)) |
| 197 | + ) |
| 198 | + for i, scope in enumerate(scopes): |
| 199 | + plt.sca(axs[i] if len(scopes) > 1 else axs) |
| 200 | + time, data = scope.read() |
| 201 | + # plot the recorded data |
| 202 | + for p, d in enumerate(data): |
| 203 | + lb = scope.labels[p] if p < len(scope.labels) else f"port {p}" |
| 204 | + plt.plot(time, d, label=lb) |
| 205 | + plt.legend() |
| 206 | + plt.xlabel("Time") |
| 207 | + plt.show() |
0 commit comments