Compute the weight for the given event.
67{
68
70
71
72
73 auto hf_vtx_vec = marley_hepmc3::get_vertices_with_status(
74 marley_hepmc3::NUHEPMC_HF_DECAY_VERTEX, ev );
75
76
77 for ( const auto& vtx : hf_vtx_vec ) {
78
79
80
81 bool decayed_to_continuum = false;
82
83 const auto& in_vec = vtx->particles_in();
84 const auto& out_vec = vtx->particles_out();
85
86
87 if ( in_vec.size() != 1u || out_vec.size() != 2u ) {
88 throw marley::Error( "Hauser-Feshbach vertex encountered that"
89 " is not a binary decay" );
90 }
91
92
93 auto width_tot_attr = vtx->attribute< HepMC3::DoubleAttribute >(
94 "TotalWidth" );
95 double width_tot = width_tot_attr->value();
96
97 auto width_ec_attr = vtx->attribute< HepMC3::DoubleAttribute >(
98 "ECWidth" );
99 double width_ec = width_ec_attr->value();
100
101
102 auto width_sp_attr = vtx->attribute< HepMC3::DoubleAttribute >(
103 "SPWidth" );
104 double width_sp = 0.;
105 if ( width_sp_attr ) {
106 decayed_to_continuum = true;
107 width_sp = width_sp_attr->value();
108 }
109
110
111 const auto& mother = in_vec.front();
112
113
114
115 auto Exi_attr = mother->attribute< HepMC3::DoubleAttribute >( "Ex" );
116 double Exi = Exi_attr->value();
117
118 auto twoJi_attr = mother->attribute< HepMC3::IntAttribute >( "twoJ" );
119 int twoJi = twoJi_attr->value();
120
121 auto Pi_attr = mother->attribute< HepMC3::IntAttribute >( "parity" );
122 marley::Parity Pi( Pi_attr->value() );
123
124
125
126
127 const auto& emitted_particle = out_vec.front();
128 const auto& daughter = out_vec.back();
129
130 int emitted_pdg = emitted_particle->pid();
131
132
133
134 auto Exf_attr = daughter->attribute< HepMC3::DoubleAttribute >( "Ex" );
135 double Exf = Exf_attr->value();
136
137 auto twoJf_attr = daughter->attribute< HepMC3::IntAttribute >( "twoJ" );
138 int twoJf = twoJf_attr->value();
139
140 auto Pf_attr = daughter->attribute< HepMC3::IntAttribute >( "parity" );
141 marley::Parity Pf( Pf_attr->value() );
142
143
144 marley::HauserFeshbachDecay hf_alt( mother, Exi, twoJi, Pi, *
sdb_ );
145
146
147 double width_tot_alt = hf_alt.total_width();
148
149
150
151 const auto& ec_vec = hf_alt.exit_channels();
152 auto ec_iter = std::find_if( ec_vec.cbegin(), ec_vec.cend(),
153 [ emitted_pdg, decayed_to_continuum, Exf ](
154 const std::unique_ptr< marley::ExitChannel >& test_ec ) -> bool
155 {
156 if ( emitted_pdg != test_ec->emitted_particle_pdg() ) return false;
157
158 if ( decayed_to_continuum ) {
159 if ( !test_ec->is_continuum() ) return false;
160 else return true;
161 }
162
163
165
166 const auto* dec = dynamic_cast<
167 const marley::DiscreteExitChannel* >( test_ec.get() );
168 if ( !dec ) return false;
169
170
171
172 const auto& lev = dec->get_final_level();
173 double Ex_level = lev.energy();
174
175
176
177 if ( std::abs(Exf - Ex_level) > PRETTY_SMALL ) return false;
178 return true;
179 }
180 );
181
182 if ( ec_iter == ec_vec.cend() ) {
183 MARLEY_LOG( WARN, "physics.opticalmodel" )
184 << "Could not find ExitChannel during reweighting";
186 continue;
187 }
188
189
190
191 double width_ec_alt = ( *ec_iter )->width();
192
193
194
195 double width_sp_alt = 0.;
196 if ( decayed_to_continuum ) {
197
198
199
200 const auto& cec = dynamic_cast<
201 const marley::ContinuumExitChannel& >( *(*ec_iter) );
202 cec.differential_width( Exf, true );
203
204
205 int mpol = 0, two_j_frag = 0, orb_l = 0;
206 bool emitted_gamma = false;
207 auto mpol_attr = vtx->attribute< HepMC3::IntAttribute >(
208 "multipolarity" );
209 if ( mpol_attr ) {
210 emitted_gamma = true;
211 mpol = mpol_attr->value();
212 }
213 else {
214 auto two_j_frag_attr = vtx->attribute< HepMC3::IntAttribute >(
215 "two_j_frag" );
216 auto orb_l_attr = vtx->attribute< HepMC3::IntAttribute >( "orb_l" );
217
218
219
220 two_j_frag = two_j_frag_attr->value();
221 orb_l = orb_l_attr->
value();
222 }
223
224
225
226 const auto& spw_vec = cec.get_spw_table();
227 auto spw_iter = std::find_if( spw_vec.cbegin(), spw_vec.cend(),
228 [ twoJf, Pf, emitted_gamma, mpol, two_j_frag, orb_l ](
229 const std::unique_ptr< marley::ContinuumExitChannel
230 ::SpinParityWidth >& spw ) -> bool
231 {
232 if ( Pf != spw->Pf ) return false;
233 if ( twoJf != spw->twoJf ) return false;
234 if ( emitted_gamma ) {
235 const auto* g_spw = static_cast< const marley
236 ::GammaContinuumExitChannel::GammaSpinParityWidth* >(
237 spw.get() );
238 if ( !g_spw ) return false;
239 if ( mpol != g_spw->multipolarity ) return false;
240 }
241 else {
242
243 const auto* f_spw = static_cast< const marley
244 ::FragmentContinuumExitChannel::FragmentSpinParityWidth* >(
245 spw.get() );
246 if ( !f_spw ) return false;
247 if ( two_j_frag != f_spw->two_j_frag ) return false;
248 if ( orb_l != f_spw->orb_l ) return false;
249 }
250 return true;
251 }
252 );
253
254 if ( spw_iter == spw_vec.cend() ) {
255 MARLEY_LOG( WARN, "physics.opticalmodel" )
256 << "Could not find SpinParityWidth during reweighting";
258 continue;
259 }
260
261
262
263 width_sp_alt = spw_iter->get()->diff_width;
264 }
265
266
267
268 std::string bad_width_name;
269 if ( width_tot_alt <= 0. ) {
270 bad_width_name = "Alternate total_width";
271 }
272 else if ( width_tot <= 0. ) {
273 bad_width_name = "Original total width";
274 }
275 else if ( width_ec <= 0. ) {
276 bad_width_name = "Original exit channel";
277 }
278 else if ( width_ec_alt <= 0. ) {
279 bad_width_name = "Alternate exit channel";
280 }
281 else if ( decayed_to_continuum ) {
282 if ( width_sp_alt <= 0. ) bad_width_name = "Alternate spin-parity";
283 else if ( width_sp <= 0. ) bad_width_name = "Original spin-parity";
284 }
285
286 if ( !bad_width_name.empty() ) {
287 MARLEY_LOG( WARN, "physics.opticalmodel" ) << bad_width_name << " is non-positive";
289 continue;
290 }
291
292
293
294
295 double w = width_tot / width_tot_alt;
296 if ( decayed_to_continuum ) {
297 w *= width_sp_alt / width_sp;
298 }
299 else {
300 w *= width_ec_alt / width_ec;
301 }
302
303 MARLEY_LOG( DEBUG, "physics.opticalmodel" ) << "OMP reweight: vertex"
304 " weight w = " << w << " (tot_width_alt/tot_width = "
305 << width_tot_alt << "/" << width_tot << ")";
306
307
308
310
311 }
312
313 MARLEY_LOG( DEBUG, "physics.opticalmodel" ) << "OMP reweight: final event"
316}
int value() const
get the value associated to this Attribute.
virtual bool is_continuum() const =0
Returns true if this channel accesses the particle-unbound continuum of nuclear levels or false other...
virtual double weight(HepMC3::GenEvent &event, marley::Generator &gen) const override
Compute the weight for the given event.