-
Notifications
You must be signed in to change notification settings - Fork 111
Add multiple parallel slices #1345
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
Changes from all commits
f667ea6
a972f59
a487a71
a66fb84
21d400c
bb6fd5c
d1449bb
f7fc1d8
4064d23
901b8c1
a215003
1b0d149
4d065b3
bc133ec
ebcf7dd
6e6dcd6
c24dc66
7c34454
5e6672f
1cbf133
1e0a614
4978387
af2ca9b
7c41f59
13b68c1
33155db
e743a52
6d95e43
49de89c
1e3b546
6820604
971d67e
a7b1bd6
6fb8319
3e62a35
35cdc72
69aea25
2074b70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ public: | |
| * Merges the yup and ydown() fields of f, so that | ||
| * f.yup() = f.ydown() = f | ||
| */ | ||
| void calcYUpDown(Field3D &f) override {f.mergeYupYdown();} | ||
| void calcYUpDown(Field3D &f) override; | ||
|
|
||
| /*! | ||
| * The field is already aligned in Y, so this | ||
|
|
@@ -125,7 +125,7 @@ public: | |
| } | ||
|
|
||
| /// A 3D array, implemented as nested vectors | ||
| using arr3Dvec = std::vector<std::vector<std::vector<dcomplex>>>; | ||
| using arr3Dvec = std::vector<std::vector<Array<dcomplex>>>; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would #1505 help with this? What's the motivation for just changing the inner to an Array rather than the other nested levels?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, likely. I only needed the inner one to be an |
||
| private: | ||
| Mesh &mesh; ///< The mesh this paralleltransform is part of | ||
|
|
||
|
|
@@ -137,8 +137,19 @@ private: | |
| /// Cache of phase shifts for transforming from field-aligned coordinates to X-Z orthogonal coordinates | ||
| arr3Dvec fromAlignedPhs; | ||
|
|
||
| arr3Dvec yupPhs; ///< Cache of phase shifts for calculating yup fields | ||
| arr3Dvec ydownPhs; ///< Cache of phase shifts for calculating ydown fields | ||
| /// Helper POD for parallel slice phase shifts | ||
| struct ParallelSlicePhase { | ||
| arr3Dvec phase_shift; | ||
| int y_offset; | ||
| }; | ||
|
|
||
| /// Cache of phase shifts for the parallel slices. Slices are stored | ||
| /// in the following order: | ||
|
ZedThree marked this conversation as resolved.
|
||
| /// {+1, ..., +n, -1, ..., -n} | ||
| /// slice[i] stores offset i+1 | ||
| /// slice[2*i + 1] stores offset -(i+1) | ||
| /// where i goes from 0 to (n-1), with n the number of y guard cells | ||
| std::vector<ParallelSlicePhase> parallel_slice_phases; | ||
|
|
||
| /*! | ||
| * Shift a 2D field in Z. | ||
|
|
@@ -185,11 +196,19 @@ private: | |
| * @param[in] phs Phase shift, assumed to have length (mesh.LocalNz/2 + 1) i.e. the number of modes | ||
| * @param[out] out A 1D array of length mesh.LocalNz, already allocated | ||
| */ | ||
| void shiftZ(const BoutReal *in, const std::vector<dcomplex> &phs, BoutReal *out) const; | ||
| void shiftZ(const BoutReal *in, const Array<dcomplex> &phs, BoutReal *out) const; | ||
|
|
||
| /// Calculate and store the phases for to/from field aligned and for | ||
| /// the parallel slices using zShift | ||
| void cachePhases(); | ||
|
|
||
| /// Shift a 3D field \p f in Z to all the parallel slices in \p phases | ||
| /// | ||
| /// @param[in] f The field to shift | ||
| /// @param[in] phases The phase and offset information for each parallel slice | ||
| /// @return The shifted parallel slices | ||
| std::vector<Field3D> shiftZ(const Field3D& f, | ||
| const std::vector<ParallelSlicePhase>& phases) const; | ||
| }; | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,8 @@ class Mesh; // #include "bout/mesh.hxx" | |
|
|
||
| #include "bout/field_visitor.hxx" | ||
|
|
||
| #include <vector> | ||
|
|
||
| /// Class for 3D X-Y-Z scalar fields | ||
| /*! | ||
| This class represents a scalar field defined over the mesh. | ||
|
|
@@ -228,35 +230,37 @@ class Field3D : public Field, public FieldData { | |
|
|
||
| /// Check if this field has yup and ydown fields | ||
| bool hasYupYdown() const { | ||
| return (yup_field != nullptr) && (ydown_field != nullptr); | ||
| return !yup_fields.empty() and !ydown_fields.empty(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we added a I'd been deleting yup/ydown fields on #1176, but now I've changed that to calling
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might just be cleaner to delete the parallel slices where we need to invalidate them. I'm not sure there's anything to be gained from keeping them
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 am I right in thinking that the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| /// Return reference to yup field | ||
| Field3D& yup() { | ||
| ASSERT2(yup_field != nullptr); // Check for communicate | ||
| return *yup_field; | ||
| Field3D &yup(std::vector<Field3D>::size_type index = 0) { | ||
| ASSERT2(index < yup_fields.size()); | ||
| return yup_fields[index]; | ||
| } | ||
| /// Return const reference to yup field | ||
| const Field3D& yup() const { | ||
| ASSERT2(yup_field != nullptr); | ||
| return *yup_field; | ||
| const Field3D &yup(std::vector<Field3D>::size_type index = 0) const { | ||
| ASSERT2(index < yup_fields.size()); | ||
| return yup_fields[index]; | ||
| } | ||
|
|
||
| /// Return reference to ydown field | ||
| Field3D& ydown() { | ||
| ASSERT2(ydown_field != nullptr); | ||
| return *ydown_field; | ||
| Field3D &ydown(std::vector<Field3D>::size_type index = 0) { | ||
| ASSERT2(index < ydown_fields.size()); | ||
| return ydown_fields[index]; | ||
| } | ||
|
|
||
| /// Return const reference to ydown field | ||
| const Field3D& ydown() const { | ||
| ASSERT2(ydown_field != nullptr); | ||
| return *ydown_field; | ||
| const Field3D &ydown(std::vector<Field3D>::size_type index = 0) const { | ||
| ASSERT2(index < ydown_fields.size()); | ||
| return ydown_fields[index]; | ||
| } | ||
|
|
||
| /// Return yup if dir=+1, and ydown if dir=-1 | ||
| Field3D& ynext(int dir); | ||
| const Field3D& ynext(int dir) const; | ||
| /// Return the parallel slice at \p offset | ||
| /// | ||
| /// \p offset of 0 returns the main field itself | ||
| Field3D& ynext(int offset); | ||
| const Field3D& ynext(int offset) const; | ||
|
|
||
| /// Set variable location for staggered grids to @param new_location | ||
| /// | ||
|
|
@@ -462,8 +466,8 @@ class Field3D : public Field, public FieldData { | |
| swap(first.nz, second.nz); | ||
| swap(first.location, second.location); | ||
| swap(first.deriv, second.deriv); | ||
| swap(first.yup_field, second.yup_field); | ||
| swap(first.ydown_field, second.ydown_field); | ||
| swap(first.yup_fields, second.yup_fields); | ||
| swap(first.ydown_fields, second.ydown_fields); | ||
| swap(first.bndry_op, second.bndry_op); | ||
| swap(first.boundaryIsCopy, second.boundaryIsCopy); | ||
| swap(first.boundaryIsSet, second.boundaryIsSet); | ||
|
|
@@ -487,8 +491,8 @@ private: | |
| /// Time derivative (may be nullptr) | ||
| Field3D *deriv{nullptr}; | ||
|
|
||
| /// Pointers to fields containing values along Y | ||
| Field3D *yup_field{nullptr}, *ydown_field{nullptr}; | ||
| /// Fields containing values along Y | ||
| std::vector<Field3D> yup_fields{}, ydown_fields{}; | ||
| }; | ||
|
|
||
| // Non-member overloaded operators | ||
|
|
||
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.
This hasn't changed, but this condition means that Field2D always goes through the "aligned" branch. It should actually equally be able to go through the orthogonal branch without any issue now (the previous case was that
f.yup() != &fwould always be false forField2Dso it would always go through the second branch anyway, so the Field3D check was just a compile-time way of ensuring this). I'm not sure which is preferred/more efficient etc. but might be worth experimenting with.Secondly I think you proposed providing alternative names rather than yup/ydown -- is it worth using the new name in the function here (i.e.
f.hasParallelSlices()rather thanf.hasYupYdown()), or have these renames not happened yet?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.
It would be nice to be able to treat them the same!
Renames haven't happened, I was thinking of doing them in another PR in case there was any discussion on the names, but happy to just do them here (names can always be changed before the next release)