Skip to content

Commit 9aec9e8

Browse files
committed
Extend the 'random' generation option to the triangular APEX case
I.e. to the case where the newly introduced attribute (shape_code_) is set to 1
1 parent e8be0a0 commit 9aec9e8

File tree

1 file changed

+107
-8
lines changed

1 file changed

+107
-8
lines changed

source/geometries/APEX.cc

Lines changed: 107 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)