Address @paulromano and @smharper comments

This commit is contained in:
Shikhar Kumar 2018-12-11 18:00:06 -05:00
parent b4a2687af9
commit 2874b4a2f9
10 changed files with 782 additions and 959 deletions

View file

@ -201,6 +201,10 @@ Various classes may be created when performing tally slicing and/or arithmetic:
Coarse Mesh Finite Difference Acceleration
------------------------------------------
CMFD is implemented in OpenMC and allows users to accelerate fission source
convergence during inactive neutron batches. To run CMFD, the CMFDRun class
should be used.
.. autosummary::
:toctree: generated
:nosignatures:
@ -209,33 +213,6 @@ Coarse Mesh Finite Difference Acceleration
openmc.CMFDMesh
openmc.CMFDRun
CMFD is implemented in OpenMC and allows users to accelerate fission source
convergence during inactive neutron batches. To run CMFD, the CMFDRun class should
be used. The following properties can be set through the CMFDRun class:
.. autosummary::
:toctree: generated
:nosignatures:
:template: myfunction.rst
openmc.CMFDRun.cmfd_begin
openmc.CMFDRun.dhat_reset
openmc.CMFDRun.cmfd_display
openmc.CMFDRun.cmfd_downscatter
openmc.CMFDRun.cmfd_feedback
openmc.CMFDRun.cmfd_ktol
openmc.CMFDRun.cmfd_mesh
openmc.CMFDRun.norm
openmc.CMFDRun.cmfd_adjoint_type
openmc.CMFDRun.cmfd_power_monitor
openmc.CMFDRun.cmfd_run_adjoint
openmc.CMFDRun.cmfd_shift
openmc.CMFDRun.cmfd_stol
openmc.CMFDRun.cmfd_spectral
openmc.CMFDRun.cmfd_reset
openmc.CMFDRun.cmfd_write_matrices
openmc.CMFDRun.gauss_seidel_tolerance
At the minimum, a CMFD mesh needs to be specified in order to run CMFD. Once
these properties are set, an OpenMC simulation can be run with CMFD turned on
with the function:

View file

@ -120,6 +120,31 @@ extern "C" {
int openmc_zernike_filter_set_params(int32_t index, const double* x,
const double* y, const double* r);
//! Sets the fixed variables that are used for CMFD linear solver
//! \param[in] CSR format index pointer array of loss matrix
//! \param[in] length of indptr
//! \param[in] CSR format index array of loss matrix
//! \param[in] number of non-zero elements in CMFD loss matrix
//! \param[in] dimension n of nxn CMFD loss matrix
//! \param[in] spectral radius of CMFD matrices and tolerances
//! \param[in] indices storing spatial and energy dimensions of CMFD problem
//! \param[in] coremap for problem, storing accelerated regions
extern "C" void openmc_initialize_linsolver(const int* indptr, int len_indptr,
const int* indices, int n_elements,
int dim, double spectral,
const int* cmfd_indices,
const int* map);
//! Runs a Gauss Seidel linear solver to solve CMFD matrix equations
//! linear solver
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
extern "C" int openmc_run_linsolver(const double* A_data, const double* b,
double* x, double tol);
// Error codes
extern int OPENMC_E_UNASSIGNED;
extern int OPENMC_E_ALLOCATE;

View file

@ -1,113 +0,0 @@
#ifndef OPENMC_CMFD_SOLVER_H
#define OPENMC_CMFD_SOLVER_H
#include <cmath>
#include "xtensor/xtensor.hpp"
namespace openmc {
//===============================================================================
// Global variables
//===============================================================================
// CSR format index pointer array of loss matrix
extern std::vector<int> indptr;
// CSR format index array of loss matrix
extern std::vector<int> indices;
// Dimension n of nxn CMFD loss matrix
extern int dim;
// Spectral radius of CMFD matrices and tolerances
extern double spectral;
// Maximum dimension in x, y, and z directions
extern int nx;
extern int ny;
extern int nz;
// Number of energy groups
extern int ng;
// Indexmap storing all x, y, z positions of accelerated regions
extern xt::xtensor<int, 2> indexmap;
//===============================================================================
// Non-member functions
//===============================================================================
//! returns the index in CSR index array corresponding to the diagonal element
//! of a specified row
//! \param[in] row of interest
//! \return index in CSR index array corresponding to diagonal element
int get_diagonal_index(int row);
//! sets the elements of indexmap based on input coremap
//! \param[in] user-defined coremap
void set_indexmap(int* coremap);
//! solves a one group CMFD linear system
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
int cmfd_linsolver_1g(double* A_data, double* b, double* x, double tol);
//! solves a two group CMFD linear system
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
int cmfd_linsolver_2g(double* A_data, double* b, double* x, double tol);
//! solves a general CMFD linear system
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
int cmfd_linsolver_ng(double* A_data, double* b, double* x, double tol);
//! converts a matrix index to spatial and group indices
//! \param[in] iteration counter over row
//! \param[out] iteration counter for groups
//! \param[out] iteration counter for x
//! \param[out] iteration counter for y
//! \param[out] iteration counter for z
void matrix_to_indices(int irow, int& g, int& i, int& j, int& k);
//===============================================================================
// External functions
//===============================================================================
//! sets the fixed variables that are used for the linear solver
//! \param[in] CSR format index pointer array of loss matrix
//! \param[in] length of indptr
//! \param[in] CSR format index array of loss matrix
//! \param[in] number of non-zero elements in CMFD loss matrix
//! \param[in] dimension n of nxn CMFD loss matrix
//! \param[in] spectral radius of CMFD matrices and tolerances
//! \param[in] indices storing spatial and energy dimensions of CMFD problem
//! \param[in] coremap for problem, storing accelerated regions
extern "C" void openmc_initialize_linsolver(int* indptr, int len_indptr,
int* indices, int n_elements,
int dim, double spectral,
int* cmfd_indices, int* map);
//! runs a Gauss Seidel linear solver to solve CMFD matrix equations
//! linear solver
//! \param[in] CSR format data array of coefficient matrix
//! \param[in] right hand side vector
//! \param[out] unknown vector
//! \param[in] tolerance on final error
//! \return number of inner iterations required to reach convergence
extern "C" int openmc_run_linsolver(double* A_data, double* b, double* x,
double tol);
} // namespace openmc
#endif // OPENMC_CMFD_SOLVER_H

View file

@ -20,6 +20,13 @@ class _Bank(Structure):
('delayed_group', c_int)]
# Define input type for numpy arrays that will be passed into C++ functions
# Must be an int or double array, with single dimension that is contiguous
_array_1d_int = np.ctypeslib.ndpointer(dtype=np.int32, ndim=1,
flags='CONTIGUOUS')
_array_1d_dble = np.ctypeslib.ndpointer(dtype=np.double, ndim=1,
flags='CONTIGUOUS')
_dll.openmc_calculate_volumes.restype = c_int
_dll.openmc_calculate_volumes.errcheck = _error_handler
_dll.openmc_finalize.restype = c_int
@ -36,6 +43,10 @@ _dll.openmc_init.errcheck = _error_handler
_dll.openmc_get_keff.argtypes = [POINTER(c_double*2)]
_dll.openmc_get_keff.restype = c_int
_dll.openmc_get_keff.errcheck = _error_handler
_init_linsolver_argtypes = [_array_1d_int, c_int, _array_1d_int, c_int, c_int,
c_double, _array_1d_int, _array_1d_int]
_dll.openmc_initialize_linsolver.argtypes = _init_linsolver_argtypes
_dll.openmc_initialize_linsolver.restype = None
_dll.openmc_next_batch.argtypes = [POINTER(c_int)]
_dll.openmc_next_batch.restype = c_int
_dll.openmc_next_batch.errcheck = _error_handler
@ -45,6 +56,10 @@ _dll.openmc_run.restype = c_int
_dll.openmc_run.errcheck = _error_handler
_dll.openmc_reset.restype = c_int
_dll.openmc_reset.errcheck = _error_handler
_run_linsolver_argtypes = [_array_1d_dble, _array_1d_dble, _array_1d_dble,
c_double]
_dll.openmc_run_linsolver.argtypes = _run_linsolver_argtypes
_dll.openmc_run_linsolver.restype = c_int
_dll.openmc_source_bank.argtypes = [POINTER(POINTER(_Bank)), POINTER(c_int64)]
_dll.openmc_source_bank.restype = c_int
_dll.openmc_source_bank.errcheck = _error_handler

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,16 @@
#include <vector>
#include <cmath>
#include "xtensor/xtensor.hpp"
#include "openmc/cmfd_solver.h"
#include "openmc/error.h"
#include "openmc/constants.h"
#include "openmc/capi.h"
namespace openmc {
namespace cmfd {
//==============================================================================
// Global variables
//==============================================================================
@ -22,14 +27,30 @@ int nx, ny, nz, ng;
xt::xtensor<int, 2> indexmap;
} // namespace cmfd
//==============================================================================
// MATRIX_TO_INDICES converts a matrix index to spatial and group
// indices
//==============================================================================
void matrix_to_indices(int irow, int& g, int& i, int& j, int& k)
{
g = irow % cmfd::ng;
i = cmfd::indexmap(irow/cmfd::ng, 0);
j = cmfd::indexmap(irow/cmfd::ng, 1);
k = cmfd::indexmap(irow/cmfd::ng, 2);
}
//==============================================================================
// GET_DIAGONAL_INDEX returns the index in CSR index array corresponding to
// the diagonal element of a specified row
//==============================================================================
int get_diagonal_index(int row) {
for (int j = indptr[row]; j < indptr[row+1]; j++) {
if (indices[j] == row)
int get_diagonal_index(int row)
{
for (int j = cmfd::indptr[row]; j < cmfd::indptr[row+1]; j++) {
if (cmfd::indices[j] == row)
return j;
}
@ -41,15 +62,16 @@ int get_diagonal_index(int row) {
// SET_INDEXMAP sets the elements of indexmap based on input coremap
//==============================================================================
void set_indexmap(int* coremap) {
for (int z = 0; z < nz; z++) {
for (int y = 0; y < ny; y++) {
for (int x = 0; x < nx; x++) {
if (coremap[(z*ny*nx) + (y*nx) + x] != CMFD_NOACCEL) {
int counter = coremap[(z*ny*nx) + (y*nx) + x];
indexmap(counter, 0) = x;
indexmap(counter, 1) = y;
indexmap(counter, 2) = z;
void set_indexmap(const int* coremap)
{
for (int z = 0; z < cmfd::nz; z++) {
for (int y = 0; y < cmfd::ny; y++) {
for (int x = 0; x < cmfd::nx; x++) {
if (coremap[(z*cmfd::ny*cmfd::nx) + (y*cmfd::nx) + x] != CMFD_NOACCEL) {
int counter = coremap[(z*cmfd::ny*cmfd::nx) + (y*cmfd::nx) + x];
cmfd::indexmap(counter, 0) = x;
cmfd::indexmap(counter, 1) = y;
cmfd::indexmap(counter, 2) = z;
}
}
}
@ -60,23 +82,24 @@ void set_indexmap(int* coremap) {
// CMFD_LINSOLVER_1G solves a one group CMFD linear system
//==============================================================================
int cmfd_linsolver_1g(double* A_data, double* b, double* x, double tol) {
int cmfd_linsolver_1g(const double* A_data, const double* b, double* x,
double tol)
{
// Set overrelaxation parameter
double w = 1.0;
// Perform Gauss-Seidel iterations
for (int igs = 1; igs <= 10000; igs++) {
double tmpx[dim];
double err = 0.0;
// Copy over x vector
std::copy(x, x+dim, tmpx);
std::vector<double> tmpx {x, x+cmfd::dim};
// Perform red/black Gauss-Seidel iterations
for (int irb = 0; irb < 2; irb++) {
// Loop around matrix rows
for (int irow = 0; irow < dim; irow++) {
for (int irow = 0; irow < cmfd::dim; irow++) {
int g, i, j, k;
matrix_to_indices(irow, g, i, j, k);
@ -88,10 +111,10 @@ int cmfd_linsolver_1g(double* A_data, double* b, double* x, double tol) {
// Perform temporary sums, first do left of diag, then right of diag
double tmp1 = 0.0;
for (int icol = indptr[irow]; icol < didx; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = didx + 1; icol < indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = cmfd::indptr[irow]; icol < didx; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
for (int icol = didx + 1; icol < cmfd::indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
// Solve for new x
double x1 = (b[irow] - tmp1) / A_data[didx];
@ -106,12 +129,12 @@ int cmfd_linsolver_1g(double* A_data, double* b, double* x, double tol) {
}
// Check convergence
err = std::sqrt(err / dim);
err = std::sqrt(err / cmfd::dim);
if (err < tol)
return igs;
// Calculate new overrelaxation parameter
w = 1.0/(1.0 - 0.25 * spectral * w);
w = 1.0/(1.0 - 0.25 * cmfd::spectral * w);
}
// Throw error, as max iterations met
@ -125,23 +148,24 @@ int cmfd_linsolver_1g(double* A_data, double* b, double* x, double tol) {
// CMFD_LINSOLVER_2G solves a two group CMFD linear system
//==============================================================================
int cmfd_linsolver_2g(double* A_data, double* b, double* x, double tol) {
int cmfd_linsolver_2g(const double* A_data, const double* b, double* x,
double tol)
{
// Set overrelaxation parameter
double w = 1.0;
// Perform Gauss-Seidel iterations
for (int igs = 1; igs <= 10000; igs++) {
double tmpx[dim];
double err = 0.0;
// Copy over x vector
std::copy(x, x+dim, tmpx);
std::vector<double> tmpx {x, x+cmfd::dim};
// Perform red/black Gauss-Seidel iterations
for (int irb = 0; irb < 2; irb++) {
// Loop around matrix rows
for (int irow = 0; irow < dim; irow+=2) {
for (int irow = 0; irow < cmfd::dim; irow+=2) {
int g, i, j, k;
matrix_to_indices(irow, g, i, j, k);
@ -168,14 +192,14 @@ int cmfd_linsolver_2g(double* A_data, double* b, double* x, double tol) {
// Perform temporary sums, first do left of diag, then right of diag
double tmp1 = 0.0;
double tmp2 = 0.0;
for (int icol = indptr[irow]; icol < d1idx; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = indptr[irow+1]; icol < d2idx-1; icol++)
tmp2 += A_data[icol] * x[indices[icol]];
for (int icol = d1idx + 2; icol < indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = d2idx + 1; icol < indptr[irow + 2]; icol++)
tmp2 += A_data[icol] * x[indices[icol]];
for (int icol = cmfd::indptr[irow]; icol < d1idx; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
for (int icol = cmfd::indptr[irow+1]; icol < d2idx-1; icol++)
tmp2 += A_data[icol] * x[cmfd::indices[icol]];
for (int icol = d1idx + 2; icol < cmfd::indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
for (int icol = d2idx + 1; icol < cmfd::indptr[irow + 2]; icol++)
tmp2 += A_data[icol] * x[cmfd::indices[icol]];
// Adjust with RHS vector
tmp1 = b[irow] - tmp1;
@ -196,12 +220,12 @@ int cmfd_linsolver_2g(double* A_data, double* b, double* x, double tol) {
}
// Check convergence
err = std::sqrt(err / dim);
err = std::sqrt(err / cmfd::dim);
if (err < tol)
return igs;
// Calculate new overrelaxation parameter
w = 1.0/(1.0 - 0.25 * spectral * w);
w = 1.0/(1.0 - 0.25 * cmfd::spectral * w);
}
// Throw error, as max iterations met
@ -215,29 +239,30 @@ int cmfd_linsolver_2g(double* A_data, double* b, double* x, double tol) {
// CMFD_LINSOLVER_NG solves a general CMFD linear system
//==============================================================================
int cmfd_linsolver_ng(double* A_data, double* b, double* x, double tol) {
int cmfd_linsolver_ng(const double* A_data, const double* b, double* x,
double tol)
{
// Set overrelaxation parameter
double w = 1.0;
// Perform Gauss-Seidel iterations
for (int igs = 1; igs <= 10000; igs++) {
double tmpx[dim];
double err = 0.0;
// Copy over x vector
std::copy(x, x+dim, tmpx);
std::vector<double> tmpx {x, x+cmfd::dim};
// Loop around matrix rows
for (int irow = 0; irow < dim; irow++) {
for (int irow = 0; irow < cmfd::dim; irow++) {
// Get index of diagonal for current row
int didx = get_diagonal_index(irow);
// Perform temporary sums, first do left of diag, then right of diag
double tmp1 = 0.0;
for (int icol = indptr[irow]; icol < didx; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = didx + 1; icol < indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[indices[icol]];
for (int icol = cmfd::indptr[irow]; icol < didx; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
for (int icol = didx + 1; icol < cmfd::indptr[irow + 1]; icol++)
tmp1 += A_data[icol] * x[cmfd::indices[icol]];
// Solve for new x
double x1 = (b[irow] - tmp1) / A_data[didx];
@ -251,12 +276,12 @@ int cmfd_linsolver_ng(double* A_data, double* b, double* x, double tol) {
}
// Check convergence
err = std::sqrt(err / dim);
err = std::sqrt(err / cmfd::dim);
if (err < tol)
return igs;
// Calculate new overrelaxation parameter
w = 1.0/(1.0 - 0.25 * spectral * w);
w = 1.0/(1.0 - 0.25 * cmfd::spectral * w);
}
// Throw error, as max iterations met
@ -266,50 +291,40 @@ int cmfd_linsolver_ng(double* A_data, double* b, double* x, double tol) {
return -1;
}
//==============================================================================
// MATRIX_TO_INDICES converts a matrix index to spatial and group
// indices
//==============================================================================
void matrix_to_indices(int irow, int& g, int& i, int& j, int& k) {
g = irow % ng;
i = indexmap(irow/ng, 0);
j = indexmap(irow/ng, 1);
k = indexmap(irow/ng, 2);
}
//==============================================================================
// OPENMC_INITIALIZE_LINSOLVER sets the fixed variables that are used for the
// linear solver
//==============================================================================
extern "C"
void openmc_initialize_linsolver(int* indptr, int len_indptr, int* indices,
int n_elements, int dim, double spectral,
int* cmfd_indices, int* map) {
void openmc_initialize_linsolver(const int* indptr, int len_indptr,
const int* indices, int n_elements, int dim,
double spectral, const int* cmfd_indices,
const int* map)
{
// Store elements of indptr
for (int i = 0; i < len_indptr; i++)
openmc::indptr.push_back(indptr[i]);
cmfd::indptr.push_back(indptr[i]);
// Store elements of indices
for (int i = 0; i < n_elements; i++)
openmc::indices.push_back(indices[i]);
cmfd::indices.push_back(indices[i]);
// Set dimenion of CMFD problem and specral radius
openmc::dim = dim;
openmc::spectral = spectral;
cmfd::dim = dim;
cmfd::spectral = spectral;
// Set number of groups
openmc::ng = cmfd_indices[3];
cmfd::ng = cmfd_indices[3];
// Set problem dimensions and indexmap if 1 or 2 group problem
if (openmc::ng == 1 || openmc::ng == 2) {
openmc::nx = cmfd_indices[0];
openmc::ny = cmfd_indices[1];
openmc::nz = cmfd_indices[2];
if (cmfd::ng == 1 || cmfd::ng == 2) {
cmfd::nx = cmfd_indices[0];
cmfd::ny = cmfd_indices[1];
cmfd::nz = cmfd_indices[2];
// Resize indexmap and set its elements
openmc::indexmap.resize({static_cast<size_t>(dim), 3});
cmfd::indexmap.resize({static_cast<size_t>(dim), 3});
set_indexmap(map);
}
}
@ -320,8 +335,10 @@ void openmc_initialize_linsolver(int* indptr, int len_indptr, int* indices,
//==============================================================================
extern "C"
int openmc_run_linsolver(double* A_data, double* b, double* x, double tol) {
switch (ng) {
int openmc_run_linsolver(const double* A_data, const double* b, double* x,
double tol)
{
switch (cmfd::ng) {
case 1:
return cmfd_linsolver_1g(A_data, b, x, tol);
case 2:

View file

@ -59,8 +59,6 @@ element settings {
element dagmc { xsd:boolean }? &
element run_cmfd { xsd:boolean }? &
element run_mode { xsd:string }? &
element seed { xsd:positiveInteger }? &

View file

@ -687,11 +687,6 @@ void read_settings_xml()
}
}
// Check for cmfd run
if (check_for_node(root, "run_cmfd")) {
cmfd_run = get_node_value_bool(root, "run_cmfd");
}
// Resonance scattering parameters
if (check_for_node(root, "resonance_scattering")) {
xml_node node_res_scat = root.child("resonance_scattering");

View file

@ -23,7 +23,4 @@
</mesh>
<entropy_mesh>10</entropy_mesh>
<!-- Run CMFD -->
<run_cmfd>true</run_cmfd>
</settings>

View file

@ -23,7 +23,4 @@
</mesh>
<entropy_mesh>10</entropy_mesh>
<!-- Run CMFD -->
<run_cmfd>true</run_cmfd>
</settings>