mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Merge pull request #1562 from pshriwise/filter_create_template
Templated Filter::create
This commit is contained in:
commit
37ac486f33
7 changed files with 221 additions and 29 deletions
|
|
@ -31,6 +31,15 @@ public:
|
|||
Filter();
|
||||
virtual ~Filter();
|
||||
|
||||
//! Create a new tally filter
|
||||
//
|
||||
//! \tparam T Type of the filter
|
||||
//! \param[in] id Unique ID for the filter. If none is passed, an ID is
|
||||
//! automatically assigned
|
||||
//! \return Pointer to the new filter object
|
||||
template<typename T>
|
||||
static T* create(int32_t id = -1);
|
||||
|
||||
//! Create a new tally filter
|
||||
//
|
||||
//! \param[in] type Type of the filter
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <cstring> // for strcpy
|
||||
#include <string>
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/constants.h" // for MAX_LINE_LEN;
|
||||
#include "openmc/error.h"
|
||||
|
|
@ -67,6 +69,20 @@ Filter::~Filter()
|
|||
model::filter_map.erase(id_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Filter::create(int32_t id) {
|
||||
static_assert(std::is_base_of<Filter, T>::value,
|
||||
"Type specified is not derived from openmc::Filter");
|
||||
// Create filter and add to filters vector
|
||||
auto filter = std::make_unique<T>();
|
||||
auto ptr_out = filter.get();
|
||||
model::tally_filters.emplace_back(std::move(filter));
|
||||
// Assign ID
|
||||
model::tally_filters.back()->set_id(id);
|
||||
|
||||
return ptr_out;
|
||||
}
|
||||
|
||||
Filter* Filter::create(pugi::xml_node node)
|
||||
{
|
||||
// Copy filter id
|
||||
|
|
@ -92,59 +108,55 @@ Filter* Filter::create(pugi::xml_node node)
|
|||
Filter* Filter::create(const std::string& type, int32_t id)
|
||||
{
|
||||
if (type == "azimuthal") {
|
||||
model::tally_filters.push_back(std::make_unique<AzimuthalFilter>());
|
||||
return Filter::create<AzimuthalFilter>(id);
|
||||
} else if (type == "cell") {
|
||||
model::tally_filters.push_back(std::make_unique<CellFilter>());
|
||||
return Filter::create<CellFilter>(id);
|
||||
} else if (type == "cellborn") {
|
||||
model::tally_filters.push_back(std::make_unique<CellbornFilter>());
|
||||
return Filter::create<CellbornFilter>(id);
|
||||
} else if (type == "cellfrom") {
|
||||
model::tally_filters.push_back(std::make_unique<CellFromFilter>());
|
||||
return Filter::create<CellFromFilter>(id);
|
||||
} else if (type == "cellinstance") {
|
||||
model::tally_filters.push_back(std::make_unique<CellInstanceFilter>());
|
||||
return Filter::create<CellInstanceFilter>(id);
|
||||
} else if (type == "distribcell") {
|
||||
model::tally_filters.push_back(std::make_unique<DistribcellFilter>());
|
||||
return Filter::create<DistribcellFilter>(id);
|
||||
} else if (type == "delayedgroup") {
|
||||
model::tally_filters.push_back(std::make_unique<DelayedGroupFilter>());
|
||||
return Filter::create<DelayedGroupFilter>(id);
|
||||
} else if (type == "energyfunction") {
|
||||
model::tally_filters.push_back(std::make_unique<EnergyFunctionFilter>());
|
||||
return Filter::create<EnergyFunctionFilter>(id);
|
||||
} else if (type == "energy") {
|
||||
model::tally_filters.push_back(std::make_unique<EnergyFilter>());
|
||||
return Filter::create<EnergyFilter>(id);
|
||||
} else if (type == "energyout") {
|
||||
model::tally_filters.push_back(std::make_unique<EnergyoutFilter>());
|
||||
return Filter::create<EnergyoutFilter>(id);
|
||||
} else if (type == "legendre") {
|
||||
model::tally_filters.push_back(std::make_unique<LegendreFilter>());
|
||||
return Filter::create<LegendreFilter>(id);
|
||||
} else if (type == "material") {
|
||||
model::tally_filters.push_back(std::make_unique<MaterialFilter>());
|
||||
return Filter::create<MaterialFilter>(id);
|
||||
} else if (type == "mesh") {
|
||||
model::tally_filters.push_back(std::make_unique<MeshFilter>());
|
||||
return Filter::create<MeshFilter>(id);
|
||||
} else if (type == "meshsurface") {
|
||||
model::tally_filters.push_back(std::make_unique<MeshSurfaceFilter>());
|
||||
return Filter::create<MeshSurfaceFilter>(id);
|
||||
} else if (type == "mu") {
|
||||
model::tally_filters.push_back(std::make_unique<MuFilter>());
|
||||
return Filter::create<MuFilter>(id);
|
||||
} else if (type == "particle") {
|
||||
model::tally_filters.push_back(std::make_unique<ParticleFilter>());
|
||||
return Filter::create<ParticleFilter>(id);
|
||||
} else if (type == "polar") {
|
||||
model::tally_filters.push_back(std::make_unique<PolarFilter>());
|
||||
return Filter::create<PolarFilter>(id);
|
||||
} else if (type == "surface") {
|
||||
model::tally_filters.push_back(std::make_unique<SurfaceFilter>());
|
||||
return Filter::create<SurfaceFilter>(id);
|
||||
} else if (type == "spatiallegendre") {
|
||||
model::tally_filters.push_back(std::make_unique<SpatialLegendreFilter>());
|
||||
return Filter::create<SpatialLegendreFilter>(id);
|
||||
} else if (type == "sphericalharmonics") {
|
||||
model::tally_filters.push_back(std::make_unique<SphericalHarmonicsFilter>());
|
||||
return Filter::create<SphericalHarmonicsFilter>(id);
|
||||
} else if (type == "universe") {
|
||||
model::tally_filters.push_back(std::make_unique<UniverseFilter>());
|
||||
return Filter::create<UniverseFilter>(id);
|
||||
} else if (type == "zernike") {
|
||||
model::tally_filters.push_back(std::make_unique<ZernikeFilter>());
|
||||
return Filter::create<ZernikeFilter>(id);
|
||||
} else if (type == "zernikeradial") {
|
||||
model::tally_filters.push_back(std::make_unique<ZernikeRadialFilter>());
|
||||
return Filter::create<ZernikeRadialFilter>(id);
|
||||
} else {
|
||||
throw std::runtime_error{"Unknown filter type: " + type};
|
||||
throw std::runtime_error{fmt::format("Unknown filter type: {}", type)};
|
||||
}
|
||||
|
||||
// Assign ID
|
||||
model::tally_filters.back()->set_id(id);
|
||||
|
||||
return model::tally_filters.back().get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Filter::set_id(int32_t id)
|
||||
|
|
|
|||
0
tests/regression_tests/cpp_driver/__init__.py
Normal file
0
tests/regression_tests/cpp_driver/__init__.py
Normal file
35
tests/regression_tests/cpp_driver/driver.cpp
Normal file
35
tests/regression_tests/cpp_driver/driver.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/tallies/filter.h"
|
||||
#include "openmc/tallies/filter_cell.h"
|
||||
#include "openmc/tallies/tally.h"
|
||||
|
||||
using namespace openmc;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
openmc_init(argc, argv, nullptr);
|
||||
|
||||
// create a new cell filter
|
||||
auto cell_filter = Filter::create<CellFilter>();
|
||||
|
||||
// add all cells to the cell filter
|
||||
std::vector<int32_t> cell_indices;
|
||||
for (auto& entry : openmc::model::cell_map) {
|
||||
cell_indices.push_back(entry.second);
|
||||
}
|
||||
// sort to make sure the cell bins appear in the same
|
||||
// order as the test relying on the openmc exe
|
||||
std::sort(cell_indices.begin(), cell_indices.end());
|
||||
cell_filter->set_cells(cell_indices);
|
||||
|
||||
// create a new tally
|
||||
auto tally = Tally::create();
|
||||
std::vector<Filter*> filters = {cell_filter};
|
||||
tally->set_filters(filters);
|
||||
tally->set_scores({"flux"});
|
||||
|
||||
openmc_run();
|
||||
openmc_finalize();
|
||||
return 0;
|
||||
}
|
||||
26
tests/regression_tests/cpp_driver/inputs_true.dat
Normal file
26
tests/regression_tests/cpp_driver/inputs_true.dat
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<geometry>
|
||||
<cell id="1" material="1" region="-1" universe="1" />
|
||||
<cell id="2" material="2" region="1 -2" universe="1" />
|
||||
<surface coeffs="0.0 0.0 1.5" id="1" type="z-cylinder" />
|
||||
<surface boundary="reflective" coeffs="0.0 0.0 3.0" id="2" type="z-cylinder" />
|
||||
</geometry>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<materials>
|
||||
<material depletable="true" id="1" name="fuel">
|
||||
<density units="g/cc" value="11" />
|
||||
<nuclide ao="1.0" name="U235" />
|
||||
</material>
|
||||
<material id="2" name="water">
|
||||
<density units="g/cc" value="1.0" />
|
||||
<nuclide ao="2.0" name="H1" />
|
||||
<nuclide ao="1.0" name="O16" />
|
||||
</material>
|
||||
</materials>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<settings>
|
||||
<run_mode>eigenvalue</run_mode>
|
||||
<particles>100</particles>
|
||||
<batches>10</batches>
|
||||
<inactive>1</inactive>
|
||||
</settings>
|
||||
7
tests/regression_tests/cpp_driver/results_true.dat
Normal file
7
tests/regression_tests/cpp_driver/results_true.dat
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
k-combined:
|
||||
1.857752E+00 2.922425E-02
|
||||
tally 1:
|
||||
5.337194E+01
|
||||
3.209877E+02
|
||||
1.621671E+02
|
||||
2.939588E+03
|
||||
103
tests/regression_tests/cpp_driver/test.py
Normal file
103
tests/regression_tests/cpp_driver/test.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
from pathlib import Path
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import textwrap
|
||||
|
||||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.regression_tests import config
|
||||
from tests.testing_harness import PyAPITestHarness
|
||||
|
||||
|
||||
@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.3 FATAL_ERROR)
|
||||
project(openmc_cpp_driver CXX)
|
||||
add_executable(cpp_driver driver.cpp)
|
||||
find_package(OpenMC REQUIRED HINTS {})
|
||||
target_link_libraries(cpp_driver OpenMC::libopenmc)
|
||||
""".format(openmc_dir)))
|
||||
|
||||
# Create temporary build directory and change to there
|
||||
local_builddir = Path('build')
|
||||
local_builddir.mkdir(exist_ok=True)
|
||||
os.chdir(str(local_builddir))
|
||||
|
||||
if config['mpi']:
|
||||
os.environ['CXX'] = 'mpicxx'
|
||||
|
||||
try:
|
||||
print("Building driver")
|
||||
# Run cmake/make to build the shared libary
|
||||
subprocess.run(['cmake', os.path.pardir], check=True)
|
||||
subprocess.run(['make'], check=True)
|
||||
os.chdir(os.path.pardir)
|
||||
|
||||
yield "./build/cpp_driver"
|
||||
|
||||
finally:
|
||||
# Remove local build directory when test is complete
|
||||
shutil.rmtree('build')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def model():
|
||||
model = openmc.model.Model()
|
||||
|
||||
# materials
|
||||
u235 = openmc.Material(name="fuel")
|
||||
u235.add_nuclide('U235', 1.0, 'ao')
|
||||
u235.set_density('g/cc', 11)
|
||||
|
||||
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)
|
||||
|
||||
mats = openmc.Materials([u235, water])
|
||||
model.materials = mats
|
||||
|
||||
# geometry
|
||||
fuel_or = openmc.ZCylinder(r=1.5)
|
||||
coolant_or = openmc.ZCylinder(r=3.0, boundary_type='reflective')
|
||||
|
||||
fuel = openmc.Cell(fill=u235, region=-fuel_or)
|
||||
coolant = openmc.Cell(fill=water, region=+fuel_or & -coolant_or)
|
||||
|
||||
model.geometry = openmc.Geometry([fuel, coolant])
|
||||
|
||||
model.settings.particles = 100
|
||||
model.settings.batches = 10
|
||||
model.settings.inactive = 1
|
||||
|
||||
return model
|
||||
|
||||
|
||||
class ExternalDriverTestHarness(PyAPITestHarness):
|
||||
|
||||
def __init__(self, executable, statepoint_name, model=None):
|
||||
super().__init__(statepoint_name, model)
|
||||
self.executable = executable
|
||||
|
||||
def _run_openmc(self):
|
||||
if config['mpi']:
|
||||
mpi_args = [config['mpiexec'], '-n', config['mpi_np']]
|
||||
openmc.run(openmc_exec=self.executable,
|
||||
mpi_args=mpi_args,
|
||||
event_based=config['event'])
|
||||
else:
|
||||
openmc.run(openmc_exec=self.executable,
|
||||
event_based=config['event'])
|
||||
|
||||
|
||||
def test_cpp_driver(cpp_driver, model):
|
||||
harness = ExternalDriverTestHarness(cpp_driver, 'statepoint.10.h5', model)
|
||||
harness.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue