@@ -1575,14 +1575,113 @@ namespace nexus{
15751575 z_pos = gen_z_ +(random_radius*cos (random_angle));
15761576 }
15771577 else { // Default behaviour is that of generation_region_=="random"
1578- x_pos = UniformRandomInRange (
1579- plate_length_/2 .,
1580- -1 .*plate_length_/2 .
1581- );
1582- z_pos = UniformRandomInRange (
1583- plate_width_/2 .,
1584- -1 .*plate_width_/2 .
1585- );
1578+
1579+ if (shape_code_==0 )
1580+ {
1581+ x_pos = UniformRandomInRange (
1582+ plate_length_/2 .,
1583+ -1 .*plate_length_/2 .
1584+ );
1585+ z_pos = UniformRandomInRange (
1586+ plate_width_/2 .,
1587+ -1 .*plate_width_/2 .
1588+ );
1589+ }
1590+ else if (shape_code_==1 )
1591+ {
1592+ // The parameterization in the body of this conditional block takes into
1593+ // account that the triangle point which is placed at the coordinates
1594+ // system origin is the point which
1595+ //
1596+ // 1) belongs to the symmetry axis of the isosceles triangle, and
1597+ // 2) is placed at half the triangle height (plate_width_) from the base of the triangle
1598+ //
1599+ // Note that this parameterization is different to the one used in the
1600+ // WLSPlate::GenerateVertex() method (at the time of writing).
1601+ //
1602+ // The situation that we got now is something like this:
1603+ //
1604+ // +z
1605+ // /\
1606+ // |
1607+ // |
1608+ // x
1609+ // z_1(x) / | \ z_2(x)
1610+ // |
1611+ // -x <--------------/----+----\------------------> +x
1612+ // |
1613+ // /________|________\
1614+ // |
1615+ // |
1616+ // |
1617+ // v
1618+ // -z
1619+ //
1620+ // Imagine that we parameterize the left (resp. right) side of the triangle with
1621+ // the function z_1(x) (resp. z_2(x)). This dependency can be inverted to find
1622+ // x_1(z) (resp. x_2(z)). Then, after having generated a random z_pos, in the
1623+ // (-plate_width_/2., plate_width_/2.) range, we can calculate x_1(z_pos), which
1624+ // is basically the (negative) half-width of the isosceles triangle at a height
1625+ // given by the sampled z_pos. Now, to not bias the generation of the vertex
1626+ // towards the upper peak of the triangle, we need to accept the generated z_pos
1627+ // with a probability proportional to the ratio of the computed margin to half
1628+ // of the triangle base. Since the margin we computed is negative, we just invert
1629+ // its sign and compute its ratio to (plate_length_/2.). Note that the rejection
1630+ // probability approaches 0, when the generated z_pos landed very close to the
1631+ // triangle base, and it is almost 1 when the generated z_pos is very close to
1632+ // the triangle peak. This is as it should be, since the area near the base of
1633+ // the triangle is much bigger than the area near the peak, and a random generation
1634+ // should give an uniform superficial density of photon hits throughout the
1635+ // triangle surface.
1636+
1637+ G4double negative_margin;
1638+ G4bool accepted_z_pos = false ;
1639+
1640+ while (!accepted_z_pos)
1641+ {
1642+ z_pos = UniformRandomInRange (
1643+ (plate_width_/2 .)-tolerance,
1644+ (-1 .*plate_width_/2 .)+tolerance
1645+ );
1646+
1647+ negative_margin = ((z_pos*plate_length_)/(2 .*plate_width_))-(plate_length_/4 );
1648+
1649+ if (UniformRandomInRange (1 ., 0 .) < (-1 .*negative_margin)/(plate_length_/2 .))
1650+ {
1651+ accepted_z_pos = true ;
1652+ }
1653+ }
1654+
1655+ // Under the assumption that the triangle height (plate_width_) is
1656+ // bigger than the tolerance (t), i.e. plate_width_>t, and that the
1657+ // tolerance is smaller than 1.0, then you can prove that, for
1658+ //
1659+ // ((z_pos*plate_length_)/(2.*plate_width_))-(plate_length_/4)+(k*tolerance) < 0 (1)
1660+ //
1661+ // to hold in the whole range of
1662+ //
1663+ // z_pos \in [(-plate_width_/2.)+tolerance, (plate_width_/2.)-tolerance],
1664+ //
1665+ // (which is the range of random generation of z_pos), it is needed
1666+ // that k < plate_length_/(2*plate_width_). The reason why we need
1667+ // the inequality (1) above is that UniformRandomInRange(x, y) works
1668+ // for x>y (otherwise we are inverting the range, which makes no sense).
1669+ // That's why we are introducing the factor k in the range limits of
1670+ // the x_pos random generation.
1671+
1672+ G4double k = 0.5 * plate_length_/(2 .*plate_width_); // Smaller than plate_length_/(2*plate_width_)
1673+ negative_margin += k*tolerance;
1674+
1675+ x_pos = UniformRandomInRange (
1676+ -1 .*negative_margin,
1677+ negative_margin
1678+ );
1679+ }
1680+ else
1681+ {
1682+ G4Exception (" [APEX]" , " GenerateVertex()" ,
1683+ FatalException, " The given shape code is not recognized." );
1684+ }
15861685 }
15871686 return G4ThreeVector (x_pos, y_pos, z_pos);
15881687 }
0 commit comments