Merge pull request #1562 from pshriwise/filter_create_template

Templated Filter::create
This commit is contained in:
Paul Romano 2020-05-18 06:49:21 -05:00 committed by GitHub
commit 37ac486f33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 221 additions and 29 deletions

View file

@ -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

View file

@ -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)

View 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;
}

View 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>

View 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

View 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()