-
Notifications
You must be signed in to change notification settings - Fork 59
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
CLN: refactor C++/pybind11 single variables to structs #1294
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1294 +/- ##
==========================================
+ Coverage 80.02% 81.12% +1.09%
==========================================
Files 98 94 -4
Lines 13680 12481 -1199
Branches 2203 1882 -321
==========================================
- Hits 10948 10125 -823
+ Misses 1999 1692 -307
+ Partials 733 664 -69 ☔ View full report in Codecov by Sentry. |
21152af
to
4e86605
Compare
4e86605
to
7d0d54e
Compare
@@ -41,7 +41,7 @@ BreakBeforeBraces: Mozilla | |||
BreakBeforeInheritanceComma: true | |||
BreakBeforeTernaryOperators: true | |||
BreakConstructorInitializersBeforeComma: false | |||
BreakConstructorInitializers: BeforeComma | |||
BreakConstructorInitializers: AfterColon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The appearance of simple constructors did not look good with former setting:
Before:
Point()
: x(0)
, y(0)
, z(0)
{
}
After:
Point() : x(0), y(0), z(0) {}
const double bot_yinc, | ||
const double bot_rotation, | ||
const py::array_t<double> &bot_values); | ||
get_gridprop_value_between_surfaces(const Grid &grd, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example when the function signature gets much shorter and easier to maintain
if num_threads < available_threads / 2: | ||
assert np.array_equal(top, keep_top_store["keep_top"]), ( | ||
f"Mismatch with {num_threads} threads" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted this test as it is flaky depending on the actual threads available (consider this is a "hot-fix"; a deeper understanding of cause of flakiness should be considered, but with rather low-priority)
{ corners.lower_se.x, corners.lower_se.y, corners.lower_se.z }, | ||
{ corners.lower_nw.x, corners.lower_nw.y, corners.lower_nw.z }, | ||
{ corners.lower_ne.x, corners.lower_ne.y, corners.lower_ne.z } } | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know if it is important, but for clarity it could be an idea to implement an iterator over the corners in CellCorners (I assume that is possible in C++). It could consist of two iterators for the top and base quadrilaterals (I noticed that somewhere else an anti-clockwise ordering was used).
But that is pretty much what CellCorners.arrange_corners() does😊
c2 = [100.0, 50.0, 0.0] | ||
c3 = [75.0, 100.0, 0.0] | ||
c4 = [100.0, 100.0, 0.55] | ||
"""Test the interpolate_z_4p_regular function, which returns a float from C++.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I like these kinds of drawings directly in the code 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some really nice object-oriented clean-up here, far easier to read, debug, apply, and to add new functionalities. Good to go from my side 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much nicer function signatures. A lot of progress toward the C++ representation of these objects. Nice work
m_cube.def("cube_stats_along_z", &cube_stats_along_z, | ||
"Compute various statistics for cube along the Z axis, returning maps."); | ||
py::class_<Cube>(m_cube, "Cube") | ||
.def(py::init<>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.def(py::init<>()) |
Is there a use case for the default constructor here? (It would allow making a C++ cube like _internal.cube.Cube()
). Probably we don't want this since empty constructors were deprecated anyway, and should expect its made from the Python object only. Unless of course it breaks something when removed..
struct Points // placeholder. Consider naming it PointSet for clarity | ||
{ | ||
std::vector<Point> points; | ||
|
||
// Default constructor | ||
Points() = default; | ||
|
||
// Constructor that takes a vector of points | ||
Points(const std::vector<Point> &points) : points(points) {} | ||
|
||
// Method to add a point to the points | ||
void add_point(const Point &point) { points.push_back(point); } | ||
|
||
// Method to get the number of points | ||
size_t size() const { return points.size(); } | ||
}; // struct Points |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing and adding when it's being used (i.e. don't add dead code)
struct Polygons // placeholder. Consider naming it PolygonSet for clarity | ||
{ | ||
std::vector<Polygon> polygons; | ||
std::vector<int> ids; | ||
|
||
// Default constructor | ||
Polygons() = default; | ||
|
||
// Method to add a polygon with an ID | ||
void add_polygon(const Polygon &polygon, int id) | ||
{ | ||
polygons.push_back(polygon); | ||
ids.push_back(id); | ||
} | ||
|
||
// Method to get the number of polygons | ||
size_t size() const { return polygons.size(); }; | ||
}; // struct Pol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing and adding when it's being used (i.e. don't add dead code)
@@ -0,0 +1,337 @@ | |||
// separate header file for structs etc used in xtgeo to avoid circular dependencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit worried this header becomes a kitchen sink
// Default constructor | ||
Polygon() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a default constructor Polygon()
needed here? Could set it to delete
if it should always be created with an array
assert grd.dimensions == bulkvol.dimensions | ||
assert np.allclose(cellvol_rms.values, bulkvol.values) | ||
# assert grd.dimensions == bulkvol.dimensions | ||
# assert np.allclose(cellvol_rms.values, bulkvol.values) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still meant to be commented out?
print(bulkvol.values.size) | ||
for i, val in enumerate(bulkvol.values.flatten().tolist()): | ||
print(i, val) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debugging prints?
assert isinstance(corners, list) | ||
print(corners) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug print?
volume = _internal.geometry.hexahedron_volume(corners, prec) | ||
assert volume == pytest.approx(468.75, rel=1e-3) # 468.75 is RMS' value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the volume check no longer relevant?
// Constructor that takes a Python object and a metadata_only flag | ||
RegularSurface(const py::object &rs, bool metadata_only = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused about metadata only, maybe because of thinking so much about dataio... it's meant just to take fields but not the full value-data?
Resolves #1295
Before we transfer more code from C/swig or make too much new code in the C++/pybind11 domain, a refactoring to structs which provide simple "shadow classes" for most important attributes from e.g
RegularSurface()
andGrid()
is done.It should give an easier to read and a more maintainable code, although I would think that further improvements are possible (perhaps doing it step-wise). In general C++
struct
what applied instead ofclass
at this stage, but it should be fairly simple to convert the structs to classes in a later stage, if needed.Although many files are changed (due to massive dependencies), the PR shall not change any current functionality for the end user. In terms of CPU speed, a coarse comparison indicates no significant changes in on the overall test suite.