Boundary conditions fixes - #1319
Conversation
When iterating over flags from h5cc, the HDF5_{CPPFLAGS,LDFLAGS,LIBS}
variables were assembled in reverse order. This causes problems when
linking against static libraries.
Fixes #961
Fix order of HDF5 flags
Now consistently treats CELL_DEFAULT
If the simulation is restarted (`restart`), and the old dump files have already been squashed, dump on restart is enabled by default. This patch checks whether the two times are the same, and if so, does not duplicate that time slice.
For some reason the time index is called `x2` - and thus this condition is not matched. This fixes this, as the newly created output should be more reliable in this regard.
`glob` was previously not correctly imported, if append mode was disabled, but delete was enabled.
coordinates. Replaces throw with ASSERT
* master: AX_LIB_HDF5: fix order of flags
Advective and flux derivatives, which take v and f as inputs, had cases using yup/ydown fields for one of v and f, but not the other. These do not make sense as multiplication of a field in field-aligned coordinates with another in non-field-aligned coordinates is incorrect. Delete last of these cases and fall back to converting both v and f to field-aligned if either does not have yup/ydown fields. Also add some comments where mixed cases were removed before.
In several y-derivatives where we have to convert the input to field-aligned coordinates, the result was not transformed back to the original coordinates. Also remove uses of global 'mesh' in Vpar_Grad_par_LCtoC()
Was previously a typo that resulted in using non-field-aligned f in VDDY, which is incorrect.
The location of the result will in future need to be set before shifting it from field-aligned coordinates, if this is necessary. So it is safer to set the location to outloc as soon as 'Field3D result' is declared. Also in a couple of places just 'return apply*diff(...)' instead of creating an unneeded intermediate variable 'result'.
* next: Move handling of outloc==CELL_DEFAULT above location checks Use ASSERT1 instead of ASSERT0 for location checking in derivatives Remove unnecessary conditionals in applyXdiff() Tidy up division in D2DYDZ Simplify location checking in index_derivs.cxx Remove mixed yup/ydown-fieldaligned cases in advective/flux derivatives Move checks for no guard cells to ASSERT1 at top of functions Add ASSERT1s to check that location of Coordinates is outloc Add missing outloc argument in indexFDDY(Field2D,Field2D) Check 'vloc != diffloc' in indexFDDX Use RGN_NOY for y-derivative in D2DXDY(Field2D) Fix location of Bxy in Div_par_flux Fix location checking in VDD* and FDD* Fix staggering in SPLIT branch of FDD* Fix staggering in Div_par_K_Grad_par Don't use global mesh in bracket_location Correct dy in D2DYDZ Fix sign in Div_par_flux Fix Bxy location in Div_par
Ensure location of result set in vecops routines
| /////////////////// ASSIGNMENT //////////////////// | ||
|
|
||
| Vector2D & Vector2D::operator=(const Vector2D &rhs) { | ||
| fielddatamesh = rhs.fielddatamesh; |
There was a problem hiding this comment.
I don't recall seeing similar statements for operator= in the fields, should there be?
There was a problem hiding this comment.
I think there should be... I will add.
@ZedThree could you push the changes you just made please?
There was a problem hiding this comment.
While looking at Field3D::operator=(const Field2D &rhs), I have a question; should we set fieldmesh = rhs.getMesh();, or ASSERT1(fieldmesh == rhs.getMesh()); in this operator?
There was a problem hiding this comment.
Since Field2D has nz=1, we can't correctly set nz for the Field3D in Field3D::operator=(const Field2D &rhs) (as is done in Field3D::operator=(const Field3D &rhs)), so I think we have to assert rather than copying the Mesh* pointer.
There was a problem hiding this comment.
I think to be consistent with other places this should probably be an assert. If it is an assert we should ensure we assert for Field3D::operator=(const Field3D &rhs) etc. as well to be consistent.
More location/method fixes for derivatives
…ft-global-option Check TwistShift==true in ShiftedMetric, add ShiftWithoutTwist option to bypass
|
I had forgotten how horrifying the boundary conditions code is. Slightly regretting saying anything now... @johnomotani I believe you've done the following in each
CELL_LOC loc = f.getLocation();
if(mesh->StaggerGrids && loc != CELL_CENTRE) {
There are now three top-level branches in each
Is that correct? |
|
@ZedThree yes, exactly. |
|
|
||
| // Copy the data and data sizes | ||
| fieldmesh = rhs.fieldmesh; | ||
| fielddatamesh = rhs.fielddatamesh; |
There was a problem hiding this comment.
Do we need to check that fieldmesh/fielddatamesh are identical? If so why do we need two variables?
There was a problem hiding this comment.
They definitely should be the same. We should ASSERT1 in Field2D and Field3D.
There are two because there's one in each of the two base classes. I think this points towards our class hierarchy being a little weird
There was a problem hiding this comment.
I was wondering if this might be an opportunity to address the class structure? We're currently introducing more opportunities to form an inconsistent state (albeit with appropriate checks to try to guard against this). All vectors and fields apart from fieldperp have fielddata and all fields have Field. I'd guess FieldPerp should also have fielddata (and if not why not?) and if so then it looks like FieldData is the generic stuff to all field like objects (which would presumably include getting the single relevant mesh) whilst Field provides the things fields have that vectors don't (coordinates, anything else?).
There was a problem hiding this comment.
Or could Field inherit from FieldData?
| } | ||
|
|
||
| Vector3D & Vector3D::operator=(const Vector2D &rhs) { | ||
| fielddatamesh = rhs.x.getMesh(); |
There was a problem hiding this comment.
Should this be getDataMesh() for consistency? (I know they should return the same thing)
| @@ -23,88 +23,92 @@ | |||
| lead to an out of bounds access error later but we add it here to provide a | |||
| more explanatory message. | |||
| */ | |||
| void verifyNumPoints(BoundaryRegion *region, int ptsRequired) { | |||
| TRACE("Verifying number of points available for BC"); | |||
| namespace { | |||
There was a problem hiding this comment.
Are all the changes in this file separate from the FieldData gaining a mesh pointer?
There was a problem hiding this comment.
I guess the changes are separate in the sense that they could all be made without adding a mesh pointer to FieldData, but the mesh pointer in FieldData is required for the boundary conditions to work correctly when the fieldmesh is not the same as the global mesh.
- in verifyNumPoints we need to get localmesh from the
BoundaryRegion *region;BoundaryRegion*s are created in a method ofFieldData;FieldDatahad to gain a mesh pointer so thatBoundaryRegion*s aren't always created with the globalmesh. - the
BoundaryRegion* bndryof theBoundaryOps could previously be wrong if the global and localMeshare different (e.g. wrong number of points, or wrong number of guard cells, etc.).
| for(; !bndry->isDone(); bndry->next1d()) { | ||
| BoutReal xnorm = 0.5*( localmesh->GlobalX(bndry->x) | ||
| + localmesh->GlobalX(bndry->x - bndry->bx) ); | ||
| BoutReal ynorm = localmesh->GlobalY(bndry->y); |
There was a problem hiding this comment.
Should we introduce Mesh::GlobalZ for symmetry?
| } | ||
| } | ||
| } else { | ||
| // CELL_CENTRE or CELL_ZLOW |
There was a problem hiding this comment.
Do we not care about the Z location in the CELL_ZLOW case for 3D fields?
There was a problem hiding this comment.
That's a good point... If we're using a constant rather than an expression for the value of the boundary condition, then we don't care about Z location, because there are no z-boundaries. But generally, we need to change the argument to fg->generate(), so there should be a separate CELL_ZLOW case :disappointed. I'll go fix this...
There was a problem hiding this comment.
Going through all the boundary operators again will be painful... There's a lot of cut-and-paste code in boundary_standard.cxx, we could probably cut it down massively by having a single set of BoundaryOp::apply() methods implemented for the BoundaryOp class, and just having the single point stencils, one staggered and one unstaggered, for each derived class.
That would change quite a lot of code (on the other hand, I've touched most of the lines in boundary_standard.cxx already, at least for whitespace) so maybe you'd rather put off until 4.3. Also, since probably nobody is using CELL_ZLOW it doesn't matter too much if it stays broken for a little while longer (at least it's less broken now, constant value boundary conditions work).
I don't like leaving things broken though, so I'll try to make a fixed version, but I'll put it in a new PR.
There was a problem hiding this comment.
I think we're going to put this PR off till 4.3 -- there's a few questions about Field/FieldData and the classes that do and don't inherit from them that we really need to resolve, and that will involve some possibly major structural changes.
All the boundary stuff needs a thorough look through and rethink as well. Can we use Region, or a subclass instead of BoundaryRegion? Is there a way we can template the boundary conditions on simple kernels and stencils? @d7919 has been doing something like this for derivatives, so maybe we can extend that work to here as well.
* v4.2-rc: (58 commits) Invert conditional in Div_par and Div_par_flux Make test-yupdown work with new test for TwistShift=true Check TwistShift==true in ShiftedMetric Remove output location from Curl properly Fix whitespace in vecops header Deprecate Curl overloads that take a location Fix locations of Jacobian in Div Set yup/ydown fields for Div_par_flux() Use curly braces with if statements Fix V_dot_Grad documentation Use std::map::emplace to avoid naming complicated type with insert Add method argument to Grad2_par2 Remove const on arguments passed by value Remove bracket_location() function, replace with ASSERT1 Tidying up more location setting in derivatives Remove unnecessary interp_to in Grad2_par2 Make mesh::getRegion?? const Add const(_iterator) overload of Region::begin/end Provide `getRegion` method on Fields to return the requested Region from fieldmesh Fix some sphinx whitespace/code blocks ...
Rename Mesh::coordinates -> Mesh::getCoordinates; deprecate old name
Previously, fields at CELL_ZLOW had nothing done by any boundary condition operator. This commit passes them through to the unstaggered case, which is correct since there are no z-boundaries so no special handling is needed.
Requires adding a Mesh* pointer and getDataMesh() method to FieldData, so that FieldData::setBoundary() can use the local mesh. getDataMesh() method is needed in case the FieldData is constructed before the global mesh is created (i.e. when Field3D, etc. are declared in global scope). It must not be called getMesh() because that would clash with the method of Field.
Give default argument 'Mesh* m = nullptr' for FieldData::FieldData constructor so that it is backward compatible. Method FieldData::getDataMesh() does not need to be virtual, since it is unlikely to be overridden.
Also move FieldData ctor into header
In places where fieldmesh and fielddatamesh are set from separate pointers, check that their values are equal. Also, for consistency set fielddatamesh from *.fielddatamesh or *.getDataMesh(), rather than fieldmesh or getMesh().
67773e9 to
df110a0
Compare
|
Replaced by #1334 |
Fixes 2 bugs:
CELL_ZLOWdid nothing, because the conditionals missed CELL_ZLOW.