2.6.3. Point Source
This tutorial places an isotropic point source inside a two-dimensional transport domain.
2.6.3.1. Build the transport domain
PointSource accepts a physical location and one strength per energy group. The source is placed away from mesh lines so that it belongs unambiguously to one cell. Unlike a volumetric source, its total strength does not scale with cell volume.
[ ]:
from mpi4py import MPI
from pyopensn.aquad import GLCProductQuadrature2DXY
from pyopensn.context import Finalize
from pyopensn.mesh import OrthogonalMeshGenerator
from pyopensn.solver import DiscreteOrdinatesProblem, SteadyStateSourceSolver
from pyopensn.source import PointSource
from pyopensn.xs import MultiGroupXS
rank = MPI.COMM_WORLD.rank
nodes = [-1.0 + i / 10.0 for i in range(21)]
mesh = OrthogonalMeshGenerator(node_sets=[nodes, nodes]).Execute()
mesh.SetOrthogonalBoundaries()
mesh.SetUniformBlockID(0)
xs = MultiGroupXS()
xs.CreateSimpleOneGroup(sigma_t=1.0, c=0.0)
quadrature = GLCProductQuadrature2DXY(
n_polar=2, n_azimuthal=8, scattering_order=0
)
2.6.3.2. Define the source
The point source is fully specified by its physical location and one strength for each energy group.
[ ]:
source = PointSource(
location=[0.037, -0.041, 0.0], strength=[1.0]
)
2.6.3.3. Configure and solve the problem
[ ]:
problem = DiscreteOrdinatesProblem(
mesh=mesh,
num_groups=1,
groupsets=[
{
"groups_from_to": (0, 0),
"angular_quadrature": quadrature,
"inner_linear_method": "petsc_gmres",
"l_abs_tol": 1.0e-10,
"l_max_its": 100,
}
],
xs_map=[{"block_ids": [0], "xs": xs}],
point_sources=[source],
boundary_conditions=[
{"name": "xmin", "type": "reflecting"},
{"name": "xmax", "type": "reflecting"},
{"name": "ymin", "type": "reflecting"},
{"name": "ymax", "type": "reflecting"},
],
)
solver = SteadyStateSourceSolver(problem=problem, compute_balance=True)
solver.Initialize()
solver.Execute()
2.6.3.4. Verify the point-source strength
The point source has total strength one. With reflecting boundaries and a purely absorbing material, all source particles must eventually contribute to absorption.
[ ]:
balance = solver.ComputeBalanceTable()
production = balance["production_rate"]
absorption = balance["absorption_rate"]
balance_error = abs(production - absorption)
if rank == 0:
print(f"Point-source production rate={production:.8e}")
print(f"Point-source absorption rate={absorption:.8e}")
print(f"Point-source balance error={balance_error:.8e}")
assert abs(production - 1.0) < 1.0e-8
assert balance_error < 1.0e-8
if "opensn_console" not in globals():
from IPython import get_ipython
if get_ipython() is not None:
Finalize()
MPI.Finalize()