mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 05:35:49 -04:00
Merge pull request #1820 from paulromano/translational-periodic-fix
Fix for translational periodic boundary conditions
This commit is contained in:
commit
abf30b39b6
12 changed files with 169 additions and 121 deletions
18
.github/actions/fix-etc-hosts/action.yml
vendored
18
.github/actions/fix-etc-hosts/action.yml
vendored
|
|
@ -1,18 +0,0 @@
|
|||
name: Fix /etc/hosts
|
||||
description: |
|
||||
Workaround for
|
||||
"Reverse name lookup is broken for current hostname in ubuntu-latest VMs",
|
||||
reported as https://github.com/actions/virtual-environments/issues/3185
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- run: |
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
# Ensure that reverse lookups for current hostname are handled properly
|
||||
# Add the current IP address, long hostname and short hostname record to /etc/hosts file
|
||||
eth0_ip_addr=$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
|
||||
hostname_fqdn=$(hostname -f)
|
||||
hostname_short=$(hostname -s)
|
||||
echo -e "${eth0_ip_addr}\t${hostname_fqdn} ${hostname_short}" | sudo tee -a /etc/hosts
|
||||
fi
|
||||
shell: bash
|
||||
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
|
|
@ -78,8 +78,6 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: ./.github/actions/fix-etc-hosts
|
||||
|
||||
-
|
||||
name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
|
|
@ -97,12 +95,11 @@ jobs:
|
|||
shell: bash
|
||||
run: |
|
||||
sudo apt -y update
|
||||
sudo apt install -y mpich \
|
||||
libmpich-dev \
|
||||
sudo apt install -y libopenmpi-dev \
|
||||
libnetcdf-dev \
|
||||
libpnetcdf-dev \
|
||||
libhdf5-serial-dev \
|
||||
libhdf5-mpich-dev \
|
||||
libhdf5-openmpi-dev \
|
||||
libeigen3-dev
|
||||
-
|
||||
name: install
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,8 @@ void read_surfaces(pugi::xml_node node)
|
|||
// Compute the dot product of the surface normals
|
||||
Direction norm1 = surf1.normal({0, 0, 0});
|
||||
Direction norm2 = surf2.normal({0, 0, 0});
|
||||
norm1 /= norm1.norm();
|
||||
norm2 /= norm2.norm();
|
||||
double dot_prod = norm1.dot(norm2);
|
||||
|
||||
// If the dot product is 1 (to within floating point precision) then the
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#ifdef OPENMC_MPI
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
|
||||
#include "openmc/capi.h"
|
||||
#include "openmc/cell.h"
|
||||
#include "openmc/error.h"
|
||||
#include "openmc/geometry.h"
|
||||
#include "openmc/message_passing.h"
|
||||
#include "openmc/summary.h"
|
||||
|
|
@ -11,7 +15,13 @@
|
|||
using namespace openmc;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
openmc_init(argc, argv, nullptr);
|
||||
#ifdef OPENMC_MPI
|
||||
MPI_Comm world {MPI_COMM_WORLD};
|
||||
int err = openmc_init(argc, argv, &world);
|
||||
#else
|
||||
int err = openmc_init(argc, argv, nullptr);
|
||||
#endif
|
||||
if (err) fatal_error(openmc_err_msg);
|
||||
|
||||
// create a new cell filter
|
||||
auto cell_filter = Filter::create<CellFilter>();
|
||||
|
|
@ -57,5 +67,10 @@ int main(int argc, char** argv) {
|
|||
|
||||
openmc_run();
|
||||
openmc_finalize();
|
||||
|
||||
#ifdef OPENMC_MPI
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,58 +1,53 @@
|
|||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import PyAPITestHarness
|
||||
|
||||
|
||||
class PeriodicTest(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
# Define materials
|
||||
water = openmc.Material(1)
|
||||
water.add_nuclide('H1', 2.0)
|
||||
water.add_nuclide('O16', 1.0)
|
||||
water.add_s_alpha_beta('c_H_in_H2O')
|
||||
water.set_density('g/cc', 1.0)
|
||||
@pytest.fixture
|
||||
def box_model():
|
||||
model = openmc.model.Model()
|
||||
# Define materials
|
||||
water = openmc.Material()
|
||||
water.add_nuclide('H1', 2.0)
|
||||
water.add_nuclide('O16', 1.0)
|
||||
water.add_s_alpha_beta('c_H_in_H2O')
|
||||
water.set_density('g/cc', 1.0)
|
||||
|
||||
fuel = openmc.Material(2)
|
||||
fuel.add_nuclide('U235', 1.0)
|
||||
fuel.set_density('g/cc', 4.5)
|
||||
fuel = openmc.Material()
|
||||
fuel.add_nuclide('U235', 1.0)
|
||||
fuel.set_density('g/cc', 4.5)
|
||||
|
||||
materials = openmc.Materials((water, fuel))
|
||||
materials.default_temperature = '294K'
|
||||
materials.export_to_xml()
|
||||
# Define geometry
|
||||
x_min = openmc.XPlane(surface_id=1, x0=0., boundary_type='periodic')
|
||||
x_max = openmc.XPlane(surface_id=2, x0=5., boundary_type='reflective')
|
||||
|
||||
# Define geometry
|
||||
x_min = openmc.XPlane(surface_id=1, x0=0., boundary_type='periodic')
|
||||
x_max = openmc.XPlane(surface_id=2, x0=5., boundary_type='reflective')
|
||||
y_min = openmc.YPlane(surface_id=3, y0=0., boundary_type='periodic')
|
||||
y_max = openmc.YPlane(surface_id=4, y0=5., boundary_type='reflective')
|
||||
y_min.periodic_surface = x_min
|
||||
|
||||
y_min = openmc.YPlane(surface_id=3, y0=0., boundary_type='periodic')
|
||||
y_max = openmc.YPlane(surface_id=4, y0=5., boundary_type='reflective')
|
||||
y_min.periodic_surface = x_min
|
||||
z_min = openmc.ZPlane(surface_id=5, z0=-5., boundary_type='periodic')
|
||||
z_max = openmc.Plane(surface_id=6, a=0, b=0, c=1, d=5.,
|
||||
boundary_type='periodic')
|
||||
z_cyl = openmc.ZCylinder(surface_id=7, x0=2.5, y0=0., r=2.0)
|
||||
|
||||
z_min = openmc.ZPlane(surface_id=5, z0=-5., boundary_type='periodic')
|
||||
z_max = openmc.Plane(surface_id=6, a=0, b=0, c=1, d=5.,
|
||||
boundary_type='periodic')
|
||||
z_cyl = openmc.ZCylinder(surface_id=7, x0=2.5, y0=0., r=2.0)
|
||||
outside_cyl = openmc.Cell(1, fill=water, region=(
|
||||
+x_min & -x_max & +y_min & -y_max & +z_min & -z_max & +z_cyl))
|
||||
inside_cyl = openmc.Cell(2, fill=fuel, region=(
|
||||
+y_min & +z_min & -z_max & -z_cyl))
|
||||
root_universe = openmc.Universe(0, cells=(outside_cyl, inside_cyl))
|
||||
model.geometry = openmc.Geometry(root_universe)
|
||||
|
||||
outside_cyl = openmc.Cell(1, fill=water, region=(
|
||||
+x_min & -x_max & +y_min & -y_max & +z_min & -z_max & +z_cyl))
|
||||
inside_cyl = openmc.Cell(2, fill=fuel, region=(
|
||||
+y_min & +z_min & -z_max & -z_cyl))
|
||||
root_universe = openmc.Universe(0, cells=(outside_cyl, inside_cyl))
|
||||
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root_universe
|
||||
geometry.export_to_xml()
|
||||
|
||||
# Define settings
|
||||
settings = openmc.Settings()
|
||||
settings.particles = 1000
|
||||
settings.batches = 4
|
||||
settings.inactive = 0
|
||||
settings.source = openmc.Source(space=openmc.stats.Box(
|
||||
(0, 0, 0), (5, 5, 0)))
|
||||
settings.export_to_xml()
|
||||
# Define settings
|
||||
model.settings.particles = 1000
|
||||
model.settings.batches = 4
|
||||
model.settings.inactive = 0
|
||||
model.settings.source = openmc.Source(space=openmc.stats.Box(
|
||||
(0, 0, 0), (5, 5, 0))
|
||||
)
|
||||
return model
|
||||
|
||||
|
||||
def test_periodic():
|
||||
harness = PeriodicTest('statepoint.4.h5')
|
||||
def test_periodic(box_model):
|
||||
harness = PyAPITestHarness('statepoint.4.h5', box_model)
|
||||
harness.main()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<geometry>
|
||||
<cell id="1" material="1" region="9 10 -11 12" universe="0" />
|
||||
<cell id="2" material="2" region="9 10 -12" universe="0" />
|
||||
<surface boundary="periodic" coeffs="0.4999999999999999 0.8660254037844387 0.0 0.0" id="9" type="plane" />
|
||||
<surface boundary="periodic" coeffs="0.4999999999999999 -0.8660254037844387 0.0 0.0" id="10" type="plane" />
|
||||
<surface boundary="reflective" coeffs="5.0" id="11" type="x-plane" />
|
||||
<surface coeffs="2.598076211353316 1.4999999999999998 2.0" id="12" type="z-cylinder" />
|
||||
<cell id="1" material="1" region="1 2 -3 4" universe="0" />
|
||||
<cell id="2" material="2" region="1 2 -4" universe="0" />
|
||||
<surface boundary="periodic" coeffs="0.4999999999999999 0.8660254037844387 0.0 0.0" id="1" type="plane" />
|
||||
<surface boundary="periodic" coeffs="0.4999999999999999 -0.8660254037844387 0.0 0.0" id="2" type="plane" />
|
||||
<surface boundary="reflective" coeffs="5.0" id="3" type="x-plane" />
|
||||
<surface coeffs="2.598076211353316 1.4999999999999998 2.0" id="4" type="z-cylinder" />
|
||||
</geometry>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<materials>
|
||||
|
|
|
|||
|
|
@ -1,62 +1,59 @@
|
|||
import openmc
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import PyAPITestHarness
|
||||
|
||||
|
||||
class Periodic6FoldTest(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
# Define materials
|
||||
water = openmc.Material(1)
|
||||
water.add_nuclide('H1', 2.0)
|
||||
water.add_nuclide('O16', 1.0)
|
||||
water.add_s_alpha_beta('c_H_in_H2O')
|
||||
water.set_density('g/cc', 1.0)
|
||||
@pytest.fixture
|
||||
def model():
|
||||
model = openmc.model.Model()
|
||||
|
||||
fuel = openmc.Material(2)
|
||||
fuel.add_nuclide('U235', 1.0)
|
||||
fuel.set_density('g/cc', 4.5)
|
||||
# Define materials
|
||||
water = openmc.Material()
|
||||
water.add_nuclide('H1', 2.0)
|
||||
water.add_nuclide('O16', 1.0)
|
||||
water.add_s_alpha_beta('c_H_in_H2O')
|
||||
water.set_density('g/cc', 1.0)
|
||||
|
||||
materials = openmc.Materials((water, fuel))
|
||||
materials.default_temperature = '294K'
|
||||
materials.export_to_xml()
|
||||
fuel = openmc.Material()
|
||||
fuel.add_nuclide('U235', 1.0)
|
||||
fuel.set_density('g/cc', 4.5)
|
||||
|
||||
# Define the geometry. Note that this geometry is somewhat non-sensical
|
||||
# (it essentially defines a circle of half-cylinders), but it is
|
||||
# designed so that periodic and reflective BCs will give different
|
||||
# answers.
|
||||
theta1 = (-1/6 + 1/2) * np.pi
|
||||
theta2 = (1/6 - 1/2) * np.pi
|
||||
plane1 = openmc.Plane(a=np.cos(theta1), b=np.sin(theta1),
|
||||
boundary_type='periodic')
|
||||
plane2 = openmc.Plane(a=np.cos(theta2), b=np.sin(theta2),
|
||||
boundary_type='periodic')
|
||||
# Define the geometry. Note that this geometry is somewhat non-sensical
|
||||
# (it essentially defines a circle of half-cylinders), but it is
|
||||
# designed so that periodic and reflective BCs will give different
|
||||
# answers.
|
||||
theta1 = (-1/6 + 1/2) * np.pi
|
||||
theta2 = (1/6 - 1/2) * np.pi
|
||||
plane1 = openmc.Plane(a=np.cos(theta1), b=np.sin(theta1),
|
||||
boundary_type='periodic')
|
||||
plane2 = openmc.Plane(a=np.cos(theta2), b=np.sin(theta2),
|
||||
boundary_type='periodic')
|
||||
|
||||
x_max = openmc.XPlane(x0=5., boundary_type='reflective')
|
||||
x_max = openmc.XPlane(x0=5., boundary_type='reflective')
|
||||
|
||||
z_cyl = openmc.ZCylinder(x0=3*np.cos(np.pi/6), y0=3*np.sin(np.pi/6),
|
||||
r=2.0)
|
||||
z_cyl = openmc.ZCylinder(x0=3*np.cos(np.pi/6), y0=3*np.sin(np.pi/6),
|
||||
r=2.0)
|
||||
|
||||
outside_cyl = openmc.Cell(1, fill=water, region=(
|
||||
+plane1 & +plane2 & -x_max & +z_cyl))
|
||||
inside_cyl = openmc.Cell(2, fill=fuel, region=(
|
||||
+plane1 & +plane2 & -z_cyl))
|
||||
root_universe = openmc.Universe(0, cells=(outside_cyl, inside_cyl))
|
||||
outside_cyl = openmc.Cell(1, fill=water, region=(
|
||||
+plane1 & +plane2 & -x_max & +z_cyl))
|
||||
inside_cyl = openmc.Cell(2, fill=fuel, region=(
|
||||
+plane1 & +plane2 & -z_cyl))
|
||||
root_universe = openmc.Universe(0, cells=(outside_cyl, inside_cyl))
|
||||
model.geometry = openmc.Geometry(root_universe)
|
||||
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root_universe
|
||||
geometry.export_to_xml()
|
||||
|
||||
# Define settings
|
||||
settings = openmc.Settings()
|
||||
settings.particles = 1000
|
||||
settings.batches = 4
|
||||
settings.inactive = 0
|
||||
settings.source = openmc.Source(space=openmc.stats.Box(
|
||||
(0, 0, 0), (5, 5, 0)))
|
||||
settings.export_to_xml()
|
||||
# Define settings
|
||||
model.settings = openmc.Settings()
|
||||
model.settings.particles = 1000
|
||||
model.settings.batches = 4
|
||||
model.settings.inactive = 0
|
||||
model.settings.source = openmc.Source(space=openmc.stats.Box(
|
||||
(0, 0, 0), (5, 5, 0))
|
||||
)
|
||||
return model
|
||||
|
||||
|
||||
def test_periodic():
|
||||
harness = Periodic6FoldTest('statepoint.4.h5')
|
||||
def test_periodic(model):
|
||||
harness = PyAPITestHarness('statepoint.4.h5', model)
|
||||
harness.main()
|
||||
|
|
|
|||
0
tests/regression_tests/periodic_hex/__init__.py
Normal file
0
tests/regression_tests/periodic_hex/__init__.py
Normal file
24
tests/regression_tests/periodic_hex/inputs_true.dat
Normal file
24
tests/regression_tests/periodic_hex/inputs_true.dat
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<geometry>
|
||||
<cell id="1" material="1" region="-1 2 -3 -4 5 6" universe="1" />
|
||||
<surface boundary="periodic" coeffs="8.660254037844386" id="1" periodic_surface_id="2" type="x-plane" />
|
||||
<surface boundary="periodic" coeffs="-8.660254037844386" id="2" periodic_surface_id="1" type="x-plane" />
|
||||
<surface boundary="periodic" coeffs="0.5773502691896257 1.0 0.0 10.0" id="3" periodic_surface_id="6" type="plane" />
|
||||
<surface boundary="periodic" coeffs="-0.5773502691896257 1.0 0.0 10.0" id="4" periodic_surface_id="5" type="plane" />
|
||||
<surface boundary="periodic" coeffs="-0.5773502691896257 1.0 0.0 -10.0" id="5" periodic_surface_id="4" type="plane" />
|
||||
<surface boundary="periodic" coeffs="0.5773502691896257 1.0 0.0 -10.0" id="6" periodic_surface_id="3" type="plane" />
|
||||
</geometry>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<materials>
|
||||
<material depletable="true" id="1">
|
||||
<density units="g/cc" value="4.5" />
|
||||
<nuclide ao="1.0" name="U235" />
|
||||
</material>
|
||||
</materials>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<settings>
|
||||
<run_mode>eigenvalue</run_mode>
|
||||
<particles>1000</particles>
|
||||
<batches>5</batches>
|
||||
<inactive>0</inactive>
|
||||
</settings>
|
||||
2
tests/regression_tests/periodic_hex/results_true.dat
Normal file
2
tests/regression_tests/periodic_hex/results_true.dat
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
k-combined:
|
||||
2.276564E+00 7.905769E-04
|
||||
28
tests/regression_tests/periodic_hex/test.py
Normal file
28
tests/regression_tests/periodic_hex/test.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import openmc
|
||||
import pytest
|
||||
|
||||
from tests.testing_harness import PyAPITestHarness
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def hex_model():
|
||||
model = openmc.model.Model()
|
||||
|
||||
fuel = openmc.Material()
|
||||
fuel.add_nuclide('U235', 1.0)
|
||||
fuel.set_density('g/cc', 4.5)
|
||||
|
||||
hex_region = openmc.model.hexagonal_prism(10.0, boundary_type='periodic')
|
||||
cell = openmc.Cell(fill=fuel, region=hex_region)
|
||||
model.geometry = openmc.Geometry([cell])
|
||||
|
||||
# Define settings
|
||||
model.settings.particles = 1000
|
||||
model.settings.batches = 5
|
||||
model.settings.inactive = 0
|
||||
return model
|
||||
|
||||
|
||||
def test_periodic_hex(hex_model):
|
||||
harness = PyAPITestHarness('statepoint.5.h5', hex_model)
|
||||
harness.main()
|
||||
|
|
@ -24,9 +24,15 @@ if [[ $LIBMESH = 'y' ]]; then
|
|||
./tools/ci/gha-install-libmesh.sh
|
||||
fi
|
||||
|
||||
# Install mpi4py for MPI configurations
|
||||
# For MPI configurations, make sure mpi4py and h5py are built against the
|
||||
# correct version of MPI
|
||||
if [[ $MPI == 'y' ]]; then
|
||||
pip install --no-binary=mpi4py mpi4py
|
||||
|
||||
export CC=mpicc
|
||||
export HDF5_MPI=ON
|
||||
export HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/openmpi
|
||||
pip install --no-binary=h5py h5py
|
||||
fi
|
||||
|
||||
# Build and install OpenMC executable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue