OpenMC/tests/regression_tests/dagmc/external/test.py

128 lines
4.2 KiB
Python

from pathlib import Path
import os
import shutil
import subprocess
import textwrap
import openmc
import openmc.lib
import pytest
from tests.regression_tests import config
from tests.testing_harness import PyAPITestHarness
pytestmark = pytest.mark.skipif(
not openmc.lib._dagmc_enabled(),
reason="DAGMC is not enabled.")
# Test that an external DAGMC instance can be passed in through the C API
@pytest.fixture
def cpp_driver(request):
"""Compile the external source"""
# Get build directory and write CMakeLists.txt file
openmc_dir = Path(str(request.config.rootdir)) / 'build'
with open('CMakeLists.txt', 'w') as f:
f.write(textwrap.dedent("""
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(openmc_cpp_driver CXX)
add_executable(main main.cpp)
find_package(OpenMC REQUIRED HINTS {})
target_link_libraries(main OpenMC::libopenmc)
target_compile_features(main PUBLIC cxx_std_14)
set(CMAKE_CXX_FLAGS "-pedantic-errors")
add_compile_definitions(OPENMC_DAGMC_ENABLED=1)
""".format(openmc_dir)))
# Create temporary build directory and change to there
local_builddir = Path('build')
local_builddir.mkdir(exist_ok=True)
os.chdir(local_builddir)
mpi_arg = "On" if config['mpi'] else "Off"
try:
# Run cmake/make to build the shared libary
subprocess.run(['cmake', os.path.pardir, f'-DOPENMC_USE_MPI={mpi_arg}'], check=True)
subprocess.run(['make'], check=True)
os.chdir(os.path.pardir)
yield "./build/main"
finally:
# Remove local build directory when test is complete
shutil.rmtree('build')
os.remove('CMakeLists.txt')
@pytest.fixture
def model():
model = openmc.model.Model()
# Settings
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 100
source_box = openmc.stats.Box([-4, -4, -4],
[ 4, 4, 4])
source = openmc.IndependentSource(space=source_box)
model.settings.source = source
model.settings.temperature['default'] = 293
# Geometry
dag_univ = openmc.DAGMCUniverse("dagmc.h5m")
model.geometry = openmc.Geometry(dag_univ)
# Tallies
tally = openmc.Tally()
tally.scores = ['total']
tally.filters = [openmc.CellFilter(1)]
model.tallies = [tally]
# Materials
u235 = openmc.Material(name="no-void fuel")
u235.add_nuclide('U235', 1.0, 'ao')
u235.set_density('g/cc', 11)
u235.id = 40
water = openmc.Material(name="water")
water.add_nuclide('H1', 2.0, 'ao')
water.add_nuclide('O16', 1.0, 'ao')
water.set_density('g/cc', 1.0)
water.add_s_alpha_beta('c_H_in_H2O')
water.id = 41
mats = openmc.Materials([u235, water])
model.materials = mats
return model
class ExternalDAGMCTest(PyAPITestHarness):
def __init__(self, executable, statepoint_name, model):
super().__init__(statepoint_name, model)
self.executable = executable
def _run_openmc(self):
"""
Just test if results generated with the external C++ API are
self-consistent with the internal python API.
We generate the "truth" results with the python API but
the main test produces the results file by running the
executable compiled from main.cpp. This future-proofs
the test - we only care that the two routes are equivalent.
"""
if config['update']:
# Generate the results file with internal python API
openmc.run(openmc_exec=config['exe'], event_based=config['event'])
elif config['mpi']:
mpi_args = [config['mpiexec'], '-n', config['mpi_np']]
# Run main cpp executable with MPI
openmc.run(openmc_exec=self.executable,
mpi_args=mpi_args,
event_based=config['event'])
else:
# Run main cpp executable
openmc.run(openmc_exec=self.executable,
event_based=config['event'])
def test_external_dagmc(cpp_driver, model):
harness = ExternalDAGMCTest(cpp_driver, 'statepoint.5.h5', model)
harness.main()