Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PullRequest Full Project Review Comments [2020-01-09] #660

Open
wants to merge 1 commit into
base: deleted_code
Choose a base branch
from

Conversation

PullRequest-Agent
Copy link

@PullRequest-Agent PullRequest-Agent commented Jan 20, 2020

PR generated for professional code review sponsored by UKAEA

docker/Dockerfile Show resolved Hide resolved
docker/Dockerfile Show resolved Hide resolved

# Update core packages
RUN apt-get -y update
RUN apt-get -y upgrade
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, it's against best practices to run apt-get -y upgrade or apt-get -y dist-upgrade from within a docker container. From the dockerfile documentation [1]:

Avoid RUN apt-get upgrade and dist-upgrade, as many of the
“essential” packages from the parent images cannot upgrade
inside an unprivileged container.

If a package contained in the parent image is out-of-date,
contact its maintainers. If you know there is a particular package,
foo, that needs to be updated, use apt-get install -y foo to update automatically.

[1] https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run

python-numpy python-pip python-setuptools wget

# Get astyle
RUN if [ "${UBUNTU_VERSION}" == "18.04" ]; then \
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: I would recommend just having the 18.04 condition here. Dockerfile specifications tend to be operating system-version specific. It is probably better to fail fast here instead of trying to compensate.

@@ -0,0 +1,32 @@
#!/bin/bash

set -e
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: For dockerfiles, I often also set -x so it will print the commands as it runs [1]. This is helpful in debugging bash files when it fails. You can set both as follows:

set -ex

[1] https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html#The-Set-Builtin

docker/build_dagmc.sh Show resolved Hide resolved
docker/build_geant4.sh Show resolved Hide resolved
docker/build_moab.sh Show resolved Hide resolved
docker/travis.housekeeping.sh Show resolved Hide resolved
docker/travis.tests.sh Show resolved Hide resolved
hid_t arr_space = H5Dget_space(ds);

hsize_t arr_dims[1];
int arr_ndim = H5Sget_simple_extent_dims(arr_space, arr_dims, NULL);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arr_ndim is not used and can be omitted.

std::vector<std::string>::iterator it;

// first volumes
for (int i = 1 ; i <= DAG->num_entities(3); i++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t.

}
}
// now surfaces
for (int i = 1 ; i <= DAG->num_entities(2); i++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t.

if (verbose || fatal) {
std::cout << "More than one material for volume with id " << cellid << std::endl;
std::cout << cellid << " has the following material assignments" << std::endl;
for (int j = 0 ; j < material_props.size() ; j++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t.

if (verbose || fatal) {
std::cout << "More than one density specified for " << cellid << std::endl;
std::cout << cellid << " has the following density assignments" << std::endl;
for (int j = 0 ; j < density_props.size() ; j++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t.

void uwuw_preprocessor::property_vector(std::vector<int> props) {
if (props.size() == 0)
return;
for (int i = 0 ; i < props.size() ; i++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t.

}

// see if file exists
bool UWUW::check_file_exists(std::string filename) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed many functions throughout this code base where an object instance, typically a string or vector, is passed by value when it could be passed by reference, especially const reference. eg. this function could be changed to have the following signature for greater performance, optimization potential, and guarantee against modification of the passed-in string:

bool UWUW::check_file_exists(const std::string& filename);

material_name = "mat:" + material.metadata["name"].asString() + "/rho:" + density;
new_mat.density = atof(density.c_str());
} else {
material_name = "mat:" + material.metadata["name"].asString();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if-else could be simplified a little by doing the following part only once:

    material_name = "mat:" + material.metadata["name"].asString();

}

// used for printing & debugging only
void uwuw_preprocessor::property_vector(std::vector<int> props) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A const& to the props vector would be better.



// constructor
name_concatenator::name_concatenator() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on optimization level, it could be better to have these empty bodies in the header file so that when objects are created/destroyed it is known that no additional code needs to be called out to.

num_ebins--;

double tally_vect[num_ebins];
double error_vect[num_ebins];
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable length arrays are not supported in C++, though since they are in newer versions of C many C++ compilers support them. I'll suggest the changes required to use vectors instead here, but it's not necessarily required to use them. For these two lines, change them to:

  std::vector<double> tally_vect(num_ebins);
  std::vector<double> error_vect(num_ebins);

One more set of changes (two lines) below.

rval = mbi->tag_set_data(tally_tag, &point, 1, tally_vect);
MB_CHK_SET_ERR_RET(rval, "Failed to set the tally_tag data");
rval = mbi->tag_set_data(error_tag, &point, 1, error_vect);
MB_CHK_SET_ERR_RET(rval, "Failed to set the error_tag data");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the two array references by appending calls to vector::data(), ie.:

  rval = mbi->tag_set_data(tally_tag, &point, 1, tally_vect.data());
  rval = mbi->tag_set_data(error_tag, &point, 1, error_vect.data());

num_ebins--;

double tally_vect[num_ebins];
double error_vect[num_ebins];
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable length arrays are not supported in C++, though since they are in newer versions of C many C++ compilers support them. I'll suggest the changes required to use vectors instead here, but it's not necessarily required to use them. For these two lines, change them to:

  std::vector<double> tally_vect(num_ebins);
  std::vector<double> error_vect(num_ebins);

One more set of changes (two lines) below.

rval = mb->tag_set_data(tally_tag, &t, 1, tally_vect);
MB_CHK_SET_ERR_RET(rval, "Failed to set tally_tag " + std::to_string(rval) + " " + std::to_string(t));
rval = mb->tag_set_data(error_tag, &t, 1, error_vect);
MB_CHK_SET_ERR_RET(rval, "Failed to set error_tag " + std::to_string(rval) + " " + std::to_string(t));
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the two array references by appending calls to vector::data(), ie.:

  rval = mb->tag_set_data(tally_tag, &t, 1, tally_vect.data());
  rval = mb->tag_set_data(error_tag, &t, 1, error_vect.data());

void TrackLengthMeshTally::compute_tracklengths(const TallyEvent& event,
unsigned int ebin, double weight,
const std::vector<double>& intersections,
const std::vector<EntityHandle>& triangles) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument triangles is not used within this function.

// not implemented
std::string get_kernel_name() const {}
int get_order() const {}
int get_min_quadrature(unsigned int i) const {}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should each return a value:

  std::string get_kernel_name() const {return std::string();}
  int get_order(return 0;) const {}
  int get_min_quadrature(unsigned int i) const {return (int)i;}

moab::Interface* mbi = &mb_core;

// load default mesh
moab::ErrorCode rval = mbi->load_mesh("structured_mesh.h5m");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rval isn't used, so:

  /*moab::ErrorCode rval =*/ mbi->load_mesh("structured_mesh.h5m");

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used on the next line.


public:
// constructor
ProgressBar();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constructor not required as initialization occurs via class member initializers, so this can be removed along with the implementation in the .cpp file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor does other work, so this recommendation is not supported.

#ifndef DAGMC_PROGRESSBAR_H
#define DAGMC_PROGRESSBAR_H

#include <string>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<string> header not referenced and can be omitted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this to the CPP file to reduce header creep


private:
int current {0};
};
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest addition of bool need_final_newline {false};. See ProgressBar.cpp for more details. This is to remove superfluous newline on successful completion [part 1 of 4].

ProgressBar::ProgressBar() {
// initialize bar
set_value(0.0);
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constructor is not needed due to initialization occurring via class member initializers, so these 4 lines can be removed along with the declaration in the header file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline this with an initializer list to retain the explicit clarity that we are initializing to 0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disagree with removing the constructor since it accomplished a number of things.

}

ProgressBar::~ProgressBar() {
std::cout << "\n";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest replacing single line in destructor with the following:

  if (need_final_newline) {
    std::cout << "\n";
  }

This is to remove superfluous newline on successful completion [part 2 of 4].

bar << "|+";

// write the bar to screen
std::cout << '\r' << bar.str() << std::flush;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest adding this after the std::cout write:

    need_final_newline = true;

This is to remove superfluous newline on successful completion [part 3 of 4].

// write the bar to screen
std::cout << '\r' << bar.str() << std::flush;
if (val >= 100.0) {
std::cout << "\n";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest adding this inside the if-statement body:

    need_final_newline = false;

This is to remove superfluous newline on successful completion [part 4 of 4].


std::string filename;
int points_per_tri_edge {0};
int n_threads {0};
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be guarded as so to remove the unused variable for single-threaded builds:

#ifdef _OPENMP
  int n_threads {0};
#endif

#pragma omp parallel shared(overlap_map, num_checked)
{
#pragma omp for schedule(auto)
for (int i = 0; i < all_verts.size(); i++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t here. At a minimum this will remove a compiler warning about mismatched signed comparison against unsigned type, but it will also guard against problems that are difficult to track down if this is ever built on a less conventional platform.


EntityHandle vert = all_verts[i];
CartVect loc;
rval = MBI->get_coords(&vert, 1, loc.array());
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rval is not used and should be dropped.

// (curve edges are likely in here too,
// but it isn't hurting anything to check more locations)
#pragma omp for schedule(auto)
for (int i = 0; i < all_edges.size() ; i++) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int should be replaced with size_t here. At a minimum this will remove a compiler warning about mismatched signed comparison against unsigned type, but it will also guard against problems that are difficult to track down if this is ever built on a less conventional platform.

class OverlapTest : public::testing::Test {
protected:
virtual void SetUp();
virtual void TearDown();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of these functions should be marked with override. eg.:

    virtual void Setup() override;
    virtual void TearDown() override;

This is more of a discipline that is good to follow as it makes it more likely that mistakes with virtual/overridden functions will result in compiler errors, making them easier to address.

};

class OverlappingVolumesTest : public OverlapTest {
virtual void SetFilename() { filename = "overlap.h5m"; }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and all other SetFilename functions below should be marked with override. eg.:

    virtual void SetFilename() override { filename = "overlap.h5m"; }

This is more of a discipline that is good to follow as it makes it more likely that mistakes with virtual/overridden functions will result in compiler errors, making them easier to address.

src/mcnp/mcnp5/CMakeLists.txt Show resolved Hide resolved
src/mcnp/mcnp_funcs.cpp Show resolved Hide resolved
src/mcnp/mcnp_funcs.cpp Show resolved Hide resolved
moab::ErrorCode result = DAG->ray_fire(vol, point, dir,
next_surf, next_surf_dist, &history,
(use_dist_limit ? dist_limit : 0)
#ifdef ENABLE_RAYSTAT_DUMPS
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readibility: Probably a bit cleaner to put a variable inside the #ifdef with a value, then put that variable here as a parameter, rather than break up the function parameters with a #ifdef.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be able to move this outside of the function call, there needs to be a rework of the variables and how they are defined throughout. The variable raystat_dump is only defined if ENABLE_RAYSTAT_DUMPS is on.

src/mcnp/mcnp_funcs.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved
src/make_watertight/Arc.cpp Show resolved Hide resolved

/// goes through curve_sets and finds any curves with coincident ( dist. apart <= FACET_TOL) front and back points.
/// it then merges the curves topologically. Any merged curves aren't deleted until prepare surfaces.
moab::ErrorCode merge_curves(moab::Range curve_sets, const double FACET_TOL,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: It's very unusual to have a non-class-level static constant identifier, especially a parameter, as all upper-case (FACET_TOL). Recommend making this lower case unless it has special scientific or other significance.

src/make_watertight/CMakeLists.txt Show resolved Hide resolved
src/make_watertight/CheckWatertight.cpp Show resolved Hide resolved
src/make_watertight/CheckWatertight.cpp Show resolved Hide resolved
src/make_watertight/CheckWatertight.cpp Show resolved Hide resolved
src/make_watertight/CheckWatertight.hpp Show resolved Hide resolved
src/make_watertight/Cleanup.cpp Show resolved Hide resolved
src/make_watertight/Cleanup.cpp Show resolved Hide resolved
src/make_watertight/Cleanup.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.cpp Show resolved Hide resolved
src/make_watertight/Gen.hpp Show resolved Hide resolved
src/make_watertight/MakeWatertight.cpp Show resolved Hide resolved
src/make_watertight/MakeWatertight.cpp Show resolved Hide resolved
src/make_watertight/MakeWatertight.cpp Show resolved Hide resolved
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

//#include "G4TessellatedSolid.hh"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: Remove commented out code.

Here and throughout this file.


fdagmc = dagmc;
fvolID = volID;
fvolEntity = fdagmc->entity_by_index(3, volID);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Typically you want the constructor of a class to have a very low surface area for errors, to avoid having high compute load or exceptions happen during initialization. Constructors are called by default when doing common operations like copying vectors of values, so getting this right can have a distinct impact on performance.

A elegant, well-encapsulated constructor typically consists of just declarations and straight value assignments.

Consequently, actions like lookups into pointer objects, for-loops to copy data, etc, are best initiated at the call site or in a subsequent init() method that can be called after the constructor is initiated.

I've also seen builder patterns used to great effect [1], or having static member functions that can be called with a constructed object to do the compute-heavy work post-initialization.

In this specific case, I would leverage the default constructor and turn this into a static intializer, rather than having it be an alternative constructor.

[1] https://sourcemaking.com/design_patterns/builder/cpp/1




// virtual void ComputeDimensions (G4VPVParameterisation* p, const G4int n,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: Remove commented out code. Here and throughout the file.

ExN01ActionInitialization* actionInitialization = new ExN01ActionInitialization(workflow_data);
runManager->SetUserInitialization(actionInitialization);

// G4VUserPrimaryGeneratorAction* gen_action = new ExN01PrimaryGeneratorAction;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: Remove commented out code, here and throughout the file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually thinking about keeping those, as this is an example file ?
any thought @makeclean @gonuke @pshriwise ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I'd lean toward removing them unless there are comments added explaining why they're there for the purposes of the example. Other comments in this file seem to be explaining what each step in the example is doing, but here it seems like these were commented to ensure the example works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file is modified from a version that used to be distributed with Geant4, so it might be instructive to leave them in. However, this file is no longer distributed with Geant4, so probably not continued value.... Maybe better to create a new example based on a new standard Geant4 example, but that's out of scope for here. I would also require comments describing why these lines would be commented out in a DAGMC version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this is particularly poor timing (and poor naming) but the example01.cc (and everything else present) really feature as a complete DAG-Geant4 program, linking with uwuw for materials (and tallies in some cases). There is likely some value in refactor, to factor out DagMaterial.cc and DagTally.cc (IIRC) as libraries for handling G4 materials and G4 tally objects.

void SetTrackID(G4int track) {
fTrackID = track;
};
/*
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented out code, here and throughout the file.

}

// using each g4element make the geant4 version of each pyne material
std::map<std::string, G4Material*> get_g4materials(std::map<int, G4Element*> element_map,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I wasn't able to trace all the uses of get_g4materials up the call chain, but just a heads up that since this std::map contains pointers that are declared using new (on the heap), the ultimate owner of this data structure is responsible for explicitly delete'ing these values to avoid memory leaks.

[1] https://stackoverflow.com/a/19970551/1015951

std::cout << filepath << std::endl;
while (!end) {
pyne::Tally tally; // from file
std::cout << i << std::endl;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a label to this std::cout so the user knows what is being counted.

// load tallies from the h5m file
tally_library = workflow_data->tally_library;

// TrackLength Scorer
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented out code, here and throughout the file. More on line 414

}
end_histogram();

HM->print_histogram_collection();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory Leak: HM should be delete'd, here and for any other return values for this method.

// but CI doesnt like using the C++11 std
std::vector<G4double> bin_bounds_v;
// hence this
bin_bounds_v.assign(bin_bounds, bin_bounds + 261);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would declare 261 a constant and use it in both places (here and in bin_bounds above), or use size_of.

ExN01DetectorHit::ExN01DetectorHit()
: G4VHit(),
fTrackID(-1),
//fChamberNb(-1),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above re: removing commented out code. Here and throughout.

state.history.reset();
}
}
/*
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: Remove commented out code, or document under what conditions it can be removed.
Here and throughout the file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing it.

@gonuke @makeclean @pshriwise, any idea if this is a safe deletion ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - I think this commented out code is just the logical equivalent of the code that is now above.


if (next_surf == 0) { // if next_surface is 0 then we are lost
if (debug) {
std::cout << "!!! Lost Particle !!! " << std::endl;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an error, might be worth it to switch to using std::cerr rather than std::cout

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are reasons to leave this alone due to the (fortran) units to which fluka writes arent clear if it uses std:error - but they are fundamentally correct

}

// set position to some large value
state.old_position[0] = 9.e99;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are looking to max out this value (assuming it is a double), you can use std::numeric_limits<double>::max().

[1] https://stackoverflow.com/a/5834704/1015951

if (is_inside == 1) { // we are inside the cell tested
// test point in vol again, but reverse the direction
double new_dir[3];
new_dir[0] = -1.*dir[0];
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and throughout, there are a lot of points in the code where the three axis of a point are managed via a double[3].

May be helpful and more readable to create a struct or helper class to manage and encapsulate the point / linear algebra math logic. This class can also provide special accessor and ingestors to interact with DAG.

Encapsulating this logic can lead to less future bugs and easier readability, as well as making the code less intimidating to newcomers overall.

return;
} else if (is_inside == -1) {
std::cout << "We cannot be here" << std::endl;
exit(0);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an error, I would write this error to std::cerr and call exit(1). Typical POSIX executable exit codes are (0 = success, anything else = failure)

//---------------------------------------------------------------------------//
// Test distance to next surface or vertex for various directions
TEST_F(FluDAGTest, GFireGoodPropStep) {
// std::cout << "Calling g_fire. Start in middle of leftmost cube" << std::endl;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented out code, here and throughout the file.

@@ -0,0 +1,21 @@
message("")
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Rather than having a blank message, I would state here that the dagmc CMake is starting. Or remove the message entirely.

src/dagmc/DagMC.cpp Show resolved Hide resolved
unsigned int DagMC::interface_revision() {
unsigned int result = 0;
const char* interface_string = DAGMC_INTERFACE_REVISION;
if (strlen(interface_string) >= 5) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: It may be prudent to use string::rfind [1] to check if $Rev: exists in the string. To be super robust, you could also create a regex [2] to locate $Rev: and explicitly check if it is followed by a number

[1] http://www.cplusplus.com/reference/string/string/rfind/
[2] http://www.cplusplus.com/reference/regex/

const char* interface_string = DAGMC_INTERFACE_REVISION;
if (strlen(interface_string) >= 5) {
// start looking for the revision number after "$Rev: "
result = strtol(interface_string + 5, NULL, 10);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error Handling: If strtol returns a 0, it may have failed to parse the number successfully from the string. Specifically, if strtol returns 0 and errno is set to ERANGE, it means the number failed to parse. It may be worth it to check for this error state here.

[1] http://www.cplusplus.com/reference/cstdlib/strtol/

char file_ext[4] = "" ; // file extension

// get the last 4 chars of file .i.e .h5m .sat etc
memcpy(file_ext, &cfile[strlen(cfile) - 4], 4);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error Handling: Recommend checking strlen on cfile here to avoid potentially passing a negative value as an array index.

return MB_SUCCESS;
}

// setups of the indices for the problem, builds a list of
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete comment: Comment ends with "builds a list of". A few words likely got truncated off the end, likely "surfaces" or "volumes".

MB_CHK_SET_ERR(rval, "GeomTopoTool could not find the geometry sets");

// implicit compliment
// EntityHandle implicit_complement;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend deleting commented out code. Optionally, you can leave an additional comment labeling under what condition the code can be re-instated or deleted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pshriwise @gonuke @makeclean @kkiesling I am not sure how to handle this one, so I'll just remove this. let me know if this is not a good idea.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's fine. We've moved the notion of the implicit complement into the GTT...

ErrorCode rval = MB_SUCCESS;

// surf/vol offsets are just first handles
setOffset = std::min(*surfs.begin(), *vols.begin());
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error checking: Might be prudent to do a length check on surfs and vols here before getting these offsets.

// index by handle lists
surf_handles().resize(surfs.size() + 1);
std::vector<EntityHandle>::iterator iter = surf_handles().begin();
*(iter++) = 0;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: For clarity, it may be helpful to leave an explicit comment explaining why the first value pointed to by the iterator is unconditionally set to 0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gonuke @pshriwise just to be sure I understand what is done there,
the gold here is to build a vector of handle to make correspondance between indices and handles number for Volumes Surfaces and Group ?
Is that correct ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct. The reason for this line is that MCNP wants a 1-based index but C++ has a 0-based index. So we need to set the first value to 0 and then start at the next position in the vector (iter++) thereafter. A comment is probably useful since it took me a few minutes to remember what was happening here.

for (Range::iterator rit = surfs.begin(); rit != surfs.end(); ++rit)
entIndices[*rit - setOffset] = idx++;

vol_handles().resize(vols.size() + 1);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than explicitly pulling the iterator, setting it to 0, and incrementing it, it might be more readable to use the technique shown with group_handles() on line 409. E.g.:

vol_handles().resize(vols.size() + 1);
vol_handles()[0] = 0;
std::copy(vols.begin(), vols.end(), &vol_handles()[1]);

}

// append a new value for the property to the existing property string
unsigned int tail_len = new_string.length() + 1;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: If the + 1 is being appended here to compensate for the NULL at the end of char* new_packed_string, it would be slightly more readable to calculate new_len here, explicitly add + 1, then declare new_packed_string as new char[ new_len ]

while (idx < len) {
std::string item(str + idx);
values.push_back(item);
idx += item.length() + 1;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: By my read, the packed strings are separated by a sentinel of some type which requires a + 1 offset? maybe a NULL? If so, I would document it here for readability.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pshriwise @gonuke any idea about this ?
I don't know enough about how the string are packed here to do the right thing...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the comment in line 502 - they are packed in a single string separated by NULL which is how line 544 even works: the new std::string is initialized with a char* and reads to the NULL character

Copy link
Member

@gonuke gonuke May 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of a comment, you could add a line:

Suggested change
idx += item.length() + 1;
int null_delimiter_length = 1;
idx += item.length() + null_delimiter_length;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add that into my PR #676

Tag proptag = property_tagmap[groupkey];
const unsigned int groupsize = grp_sets.size();
for (unsigned int j = 0; j < groupsize; ++j) {
rval = append_packed_string(proptag, grp_sets[j], groupval);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should rval be checked here? Otherwise it looks like rval is never used and is overridden for every iteration of this loop.

*
* 1) The file is loaded and when we query the meshset, we find entities with the OBB_TREE tag
* 2) The OBBTreeTool assumes that any children of the entity being queried in a ray intersect sets
* operation are fair game, the surface meshesets have triangles as members, but OBB's as children
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: but OBB's as children but no querying is done -> that OBBs have children but no querying is done?

class DagMC {
public:
// Constructor
DagMC(Interface* mb_impl = NULL, double overlap_tolerance = 0., double numerical_precision = .001);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Similar to how const char* is used on line 89, it may be valuable to use const when declaring other method parameters, especially pointers. This makes it easier for the compile to find accidental re-assignment of parameter values.

ErrorCode unpack_packed_string(Tag tag, EntityHandle eh,
std::vector< std::string >& values);

std::vector<EntityHandle>& surf_handles() {return entHandles[2];}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: Would make it more readable to define 2, 3, and 4 as used here as static const int or #DEFINE types, with the identifiers indicating they are related to surfaces, volumes, and groups.

These can also be reused on line 425 below, when doing assert checks.

parse_boundary_data();
parse_tally_volume_data();
parse_tally_surface_data();
// finalise_counters();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend removing commented out code, or leaving a note indicating under what conditions it can be removed.

} else if (property == "tally") {
value = tally_data_eh[eh];
} else {
std::cout << "Not a valid property for surfaces" << std::endl;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best Practices: I would recommend sending this to std::cerr rather than std::cout. Additionally, I would recommend printing the invalid property in the error, to help the user with the invalid input.

material_props.erase(material_props.begin() + position);
} else {
// failure a volume can only have a single material associated with it
std::cout << "more than one material for volume with id " << cellid << std::endl;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above re: std::cout vs std::cerr. Recommend using std::cerr here so it is more easily caught by logging aggregators and shell formatters.

std::string grp_name = "";

// determine if we have a density property
if (!density_props[0].empty()) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validity Checking: In addition to checking that density_props is at least 1 on line 159, it may also make sense to check if density_props is not empty before density_props[0] is indexed here.

volume_material_property_data_eh[eh] = grp_name;

// not graveyard or vacuum or implicit compliment
if (grp_name.find("Graveyard") == std::string::npos && grp_name.find("Vacuum") == std::string::npos
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reducing future errors: May make sense to define "Graveyard" and "Vacuum" somewhere as constants, rather than using the strings directly here and on line 198 below. Centralizing the string in a constant rather than using "magic strings" so-to-speak stops subtle bugs from potential misspellings later.

// not graveyard or vacuum or implicit compliment
if (grp_name.find("Graveyard") == std::string::npos && grp_name.find("Vacuum") == std::string::npos
&& !(DAG->is_implicit_complement(eh))) {
// set the
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: Incomplete comment (// set the ...)

// vector of importance values
importance_assignment = importance_assignments[eh];

// set the value of each string for
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete comment: (// set the value of each string for ...)

imp_particles.insert(pair.first);
// insert into map too
if (importance_map[eh].count(pair.first) == 0) {
importance_map[eh][pair.first] = atof(pair.second.c_str());
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend using std::strtod rather than atof, for better handling of std::string and error state [1].

[1] https://stackoverflow.com/a/12369101


// vector of tally values
tally_assignment = tally_assignments[eh];
// set the value of each string for
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete comment: (// set the value of each string for)

}


// for a given property with a range of delimiters, and dimensionality
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential incomplete comment: Did you mean , get property assignments and dimensionality rather than , and dimensionality?

std::set<std::string> new_set = properties_set;

std::vector<std::set<std::string>::const_iterator> matches;
std::set<std::string>::iterator set_it, toofar, it;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best Practices: It would be better to declare set_it and toofar within the brace scope of their usage. In this case, this would be within the while loop starting on line 469.

This helps handle accidental re-assignment of variables, and also allows the compiler to better optimize variable usage to within the declared scope.

// if there were more than 2 matches
if (matches.size() > 1) {
int smallest = 0;
int len = 1e7;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best Practices: If you are looking to initialize len with the maximum possible value of int, recommend using the INT_MAX constant. This is more readable and also is compiler specific based on the bit-width of int.

}
}
// take the longest
to_delete.insert(*matches[smallest]);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Bug: I noticed here you're only inserting the smallest (or shortest) match into the to_delete set. Was it your intent to delete all matches that are not the longest (which may be more than just the smallest / shortest)? If so, you should correct that behavior here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gonuke @pshriwise @makeclean any idea about the indented behavior in here ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super familiar with this, but from the comment at the top of the method, I think it assumes (perhaps incorrectly) that only two possible versions are possible tag_name and tag_name/value. We may want to clarify or enforce this in some way.

std::map<moab::EntityHandle, std::map<std::string, double> > importance_map;

// material density pairs
// std::map<std::string, std::set<std::string> > material_density_pairs;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best practices: Remove commented-out code, or document under what condition it can be removed.

// normalise the vector
double dir_norm = (dir[0] * dir[0]) + (dir[1] * dir[1]) + (dir[2] * dir[2]);

dir[0] = dir[0] / sqrt(dir_norm);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best practices: I would create another double[3] here (maybe "dir_normalized"), rather than reassigning the parameter. Additionally, based on the current usages of dagmc_point_in_vol_dir, it doesn't look like the callers expect the parameters to be modified.

double next_surf_dist;
EntityHandle next_surf;

// normalise the vector
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: I would add a note here indicating why the vector needs to be normalized in this case.

}

TEST_F(DagmcSimpleTest, dagmc_rayfire) {
const double eps = 1e-6; // epsilon for test, faceting tol?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: tol? May be an acronym.

}

virtual void TearDown() {
// delete dgm;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Memory Leak: It looks like dgm is allocated (new'ed) for each test. It might be best to re-enable this code and delete it here.

If dgm is managed another way, it would be best to delete this commented-out code.

exit(error ? 1 : 0);
}

static const char* get_option(int& i, int argc, char* argv[]) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving Information: There are a number of argument parsing libraries that help eliminate some of this boilerplate [1][2]. Personally I'm a fan of argparse [3], however getopt also I know is good [4].

[1] https://attractivechaos.wordpress.com/2018/08/31/a-survey-of-argument-parsing-libraries-in-c-c/.
[2] https://stackoverflow.com/questions/865668/how-to-parse-command-line-arguments-in-c
[3] https://github.com/hbristow/argparse
[4] http://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Getopt.html#Getopt

DagMC* dagmc = new DagMC();

int errors = 0;
//rval = dagmc.moab_instance()->load_file( filename );
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would recommend removing commented out code here. Also on lines 368, 692, 849

return false;
}

#define RUN_TEST(A) do { \
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you have a do / while(false) loop in this macro that is effectively inert other than a brace scope change? If the purpose of this is to just create a brace level, you should be able to do that with just empty braces.

{ { 0.5, -0.5, -2.0 }, OUTSIDE, { 0.0, 0.0, 1.0} }
};

// { { 1.0, 0.0, 0.0 }, BOUNDARY}, MCNP doesn't return on boundary
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove these commented-out test fixtures.

DagMC::RayHistory history;
rval = dagmc->ray_fire(vol, point, dir, next_surf, dist, &history);
CHKERR;
if (next_surf != surfs[7] || fabs(dist - 0.91) > 1e-6) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readability: I would leave a comment explaining the value of 0.91.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pshriwise @gonuke @makeclean any idea about that one ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically a unit test, so that is the expected value of dist... perhaps

Suggested change
if (next_surf != surfs[7] || fabs(dist - 0.91) > 1e-6) {
expected_dist = 0.91
if (next_surf != surfs[7] || fabs(dist - expected_dist) > 1e-6) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

included in #676

// sets the output filename if none specified
if (out_file == "") {
int pos = dag_file.find(".h5m");
out_file = dag_file.substr(0, pos) + "_obb.h5m";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth it to check here if pos is -1, indicating that .h5m has not been found.

for k in pseudo_list:
if ("mat:" in k):
index = k.index('\n')
k = k[0:index]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best practices: Normally it's preferred to not reassign loop incriminators unless you want to modify loop behavior. I would use another variable other than k here.

doc/usersguide/tools.rst Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants