S-coordinates - issues with top and bottom cells #1071
Replies: 41 comments
-
Thanks for reporting this Issue. I'd be happy to have a closer look into what's going on, but it would be much faster if you can also give me access to the netcdf files you're using. Can you send them to me, e.g. via a wetransfer link or similar? My email address is [email protected] |
Beta Was this translation helpful? Give feedback.
-
Thanks Erik, I'm out of the office at the moment so haven't got access to my files but I'll send them over tomorrow! |
Beta Was this translation helpful? Give feedback.
-
Further to the email I sent you, I should have mentioned that I had to make a slight change to parcels/plotting.py to get the script to run. I had to change line 301 to:
Because |
Beta Was this translation helpful? Give feedback.
-
Thanks for sending the file. Having had a quick look, I think that indeed you should defined your velocities on However, you'll then run into the Note that @delandmeterp clearly is the expert on all matters related to Grids, but he's away from email until mid-August. So if we haven't fixed it by then, he might be able to help you out |
Beta Was this translation helpful? Give feedback.
-
Sorry for the slow reply. I've also unfortunately not managed to get very far with that code; it indeed gives the data the correct dimensions so the index error disappears, but the processed fieldset is still not suitable for particle tracking and I'm really not sure why! What confuses me is that here @delandmeterp reports his code (which I've more or less copied) working smoothly with ROMS output, which uses the same grid and an almost-identical output format as Croco. So I'm not sure why it suddenly isn't working here. In any case, if I get the time then I'll keep trying but I'll probably have to wait for @delandmeterp. Thank you for your advice though! |
Beta Was this translation helpful? Give feedback.
-
Thanks @Plagioclase for getting in touch. I don't know how Croco differs from the ROMS output we used, but here is the code that we used to get parcels running with ROMS output. There is a bunch of extra code that could probably be stripped down, but perhaps you see what is different to yours. Let me know how you go.
|
Beta Was this translation helpful? Give feedback.
-
Thanks for your reply @jaseeverett. If I understand your code correctly, are you extracting and essentially flattening the uppermost s-layer and using that as a 2D grid? |
Beta Was this translation helpful? Give feedback.
-
Do you mean here:
We are actually only using the surface layer (29th layer) for our dispersion. So we aren't squashing it. We are only using 1 layer. |
Beta Was this translation helpful? Give feedback.
-
Perhaps I'm completely confused (which is possible) but if you're using the surface s-layer for dispersion, does the depth this corresponds to not depend on the bathymetry depth? If the u/v velocities are defined at the sigma-rho coordinates (which I thought they were), then the shallowest layer has sigma != 0 and will therefore have a dependence on h? That's what I meant by flattening. If you are focusing on surface dispersion as I believe you are then that may be a reasonable approximation but I unfortunately need the depth dimension as well! |
Beta Was this translation helpful? Give feedback.
-
Using a modified script, it appears to be working now:
Modifications were required to lines 1491 and 1502 of field.py to apply these routines to C-grids. Other than that it seems to be working very well, the initial outputs at least look qualitatively reasonable. |
Beta Was this translation helpful? Give feedback.
-
Well done @Plagioclase ! Thanks! |
Beta Was this translation helpful? Give feedback.
-
1491: 1502:
I will put in the disclaimer that whilst testing the particle tracking I have come across some "out of bounds errors" with particles emerging at positive depths. I suspect that there's probably a simple explanation for this and that the integration of the CROCO output into OceanParcels is working fine, but I haven't got the time at the moment to test this. Will update when I do! |
Beta Was this translation helpful? Give feedback.
-
@Plagioclase |
Beta Was this translation helpful? Give feedback.
-
Hi @CKehl, |
Beta Was this translation helpful? Give feedback.
-
Hello, I am a bit late for this discussion but my current issues with reading ROMS files in parcels is very likely to be linked to this topic. I have a ROMS file that I am trying to use, following the usefull scripts provided by Plagioclase and Delandmeter in issues #502 and #620. First I had to create a variable that contains depth of sigma levels (varying in time) which I did using (same nomenclature than code of plagioclase) :
First thing I am not sure of is that in the Parcels documentation we can find : "To interpolate U, V velocities on the C-grid, Parcels needs to read the f-nodes, which are located on the corners of the cells. (for indexing details: https://www.nemo-ocean.eu/doc/img360.png ) In 3D, the depth is the one corresponding to W nodes" If it is right, why is it needed to interpolate depth at psi points (like plagioclase did) ? isn't the depth at w points sufficient for parcels to read the grid ? I tried boths ways but none of them gave satisfactory responses. Then I had index issue due to the fact that u, v, w field had the following dimensions : Finally I am experiencing problems, for instance when trying to show fields
or when I try to execute the run. I always have out of bond issues whatever the position of particles (I checked and depth/lat lon is correct) but given the error above I suppose it has more to do with horizontal positioning of particles in the grid. I don't know if this issue is correlated to my definition of the depth grid but any help would be appreciated. I can provide my python script, drifters file and roms data (data + grid files) if needed. Hugo |
Beta Was this translation helpful? Give feedback.
-
Hi @erikvansebille, thanks for your answer, could you provide a feedback about parcels documentation regarding from_c_grid method ? "To interpolate U, V velocities on the C-grid, Parcels needs to read the f-nodes, which are located on the corners of the cells. (for indexing details: https://www.nemo-ocean.eu/doc/img360.png ) In 3D, the depth is the one corresponding to W nodes" The depth mesh expected by parcels does correspond to the depth of W nodes or f/psi nodes (corner of the cell) as suggested by @Plagioclase ? |
Beta Was this translation helpful? Give feedback.
-
Hi @HugoDENISFR. The reason is that the interpolation on C-grids (where velocities should be interpolated as fluxes across faces) is linear in only one of the dimensions: U is linearly interpolated in the lon-direction, V is linearly interpolated in the lat-direction and W is linearly interpolated in the depth direction. So Parcels needs to know the corner of the grid cell, see also Figure 4 of this GMD paper. Perhaps it's easiest to refer to the code, so that you can see what's going on. For Scipy interpolation (JIT is identical, but in C), it's at https://github.com/OceanParcels/parcels/blob/master/parcels/field.py#L878-L882: elif self.interp_method == 'cgrid_velocity':
# evaluating W velocity in c_grid
f0 = self.data[ti, zi, yi+1, xi+1]
f1 = self.data[ti, zi+1, yi+1, xi+1]
return (1-zeta) * f0 + zeta * f1 Does this help? |
Beta Was this translation helpful? Give feedback.
-
Thanks for your answer, @erikvansebille. It looks to me like there are two challenges facing implementing Parcels for very large datasets in CROCO. The first issue is in common with ROMS, namely the fact that s-grids are time-varying. Calculating the time-varying 4D grids required for Parcels will be possible for short/coarse runs but highly problematic for large runs. These 4D grids would have similar dimensions to the U/V files which could be on the order of TBs, which would be computationally expensive and I'm not even sure if plain python can do that. Two ways I can think of getting around this is (1) if the errors introduced by neglecting the time-varying grid are small or (2) if it's possible to recalculate these grids online. I'm not sure how difficult the latter would be. The second issue appears to be unique to CROCO (inherited from ROMS AGRIF) - apologies for the confusion I caused above, I didn't realise that the w output is different between CROCO and ROMS. For some reason, CROCO outputs the true vertical velocity at rho vertical levels (not w vertical levels), so the U/V/W output from CROCO isn't staggered in the vertical and is therefore not supplied at the sea surface or sea floor. @JamiePringle pointed out that w can be calculated from u/v when CROCO is run in hydrostatic mode but like the first problem, for very large datasets this would be very expensive. Can Parcels deal with a non-standard c(ish)-grid where the vertical velocity isn't staggered? |
Beta Was this translation helpful? Give feedback.
-
Several comments on the above. The fundamental issue is that the ROMS grid goes from the bottom to z=zeta, the free surface. Also, in a hydrostatic model, w and omega are purely diagnostic quantities. So first, if CROCO is not too different from ROMS, there is no reason to store the vertical grids each output (though that option does exist in the ROMS code). The change in the vertical grid can be entirely diagnosed from the free surface elevation zeta. Please see ROMS wiki on the vertical coordinate equations 1 and 2 for the equations for the grid. The standard pyroms toolbox has these routines encoded, and for a ROMS grid object romsGrid, you can get the the z coordinate of the w points from romsGrid.vgrid.z_w(), and this routine takes zeta as an argument to give you the instantaneous z grid. Or you can write your own code to give z -- it is easy and the transformations are well documented. Second, W can be calculated from u and v. I have a code that does so in python, as does Rob Hetland. The calculation is not very expensive. Mine follows wvelocity.F, his is pythonic and much faster. Both to be precise need to have the time derivative of the free surface zeta to the the velocity right near the free surface. You have three choices for that 1) calculate the time derivative zeta_t from the history file. This will be bad unless the history is saved very frequently. 2) Save zeta_t from the model run. This does not help you if using someone else's precomputed run. 3) ignore zeta_t in the calculation of w. This might be your best option. If you ignore zeta_t in the calculation of w, then you MUST ignore the time variation of the z coordinate. If you think about this at the surface, if zeta_t=0, i.e. the free-surface is not changing height, then w=0 at the surface AND the location of the surface point is not changing in time. If you look at the code in wvelocity.F, you can see that this effect extends in the vertical linearly through the water column, becoming 0 at the bottom. So it might be that your best bet, if you are working with pre-existing model files, is to compute w assuming that zeta_t=0, and then calculate z_w and z_r, the vertical grids on w and rho points, assuming zeta=0 and is unchanging. Conversely, if you use the model's computation of w, then you MUST include the effect of the time changing vertical coordinate, for otherwise your particles will leave through the surface, and similar (though less evident) errors will occur elsewhere in the water column, most strongly near the surface. To see why, think of a particle at the free surface. If the free surface is going up, there will be a positive w at the surface. If you neglect the change in the z coordinate, the particle will go sailing off into the sky... If you save omega, you can easily compute w either assuming a constant zeta=0 or a non-zero zeta_t. If you calculate W or Omega from U and V, then there will be some error if the history files are saved with 32 bits instead of 64. I don't find it too bad in my tests. Jamie |
Beta Was this translation helpful? Give feedback.
-
Jamie thank you for these suggestions. If I understand you correctly, a workflow could be as follows:
I'm not used to using python with extremely large datasets, do you know if the scripts that you/Rob Hetland have written to calculate W can deal with datasets on the order of TBs (or otherwise if this is something that is physically possible)? This is the reason why I've been hesitant about steps that require significant preprocessing of data (and why online processing is so helpful) since file size is already the limiting step in terms of what I can do, and I assume that this is a general problem. |
Beta Was this translation helpful? Give feedback.
-
Roughly, but
If you have computers that can read in a single time-step of the model fields, calculating W and omega is quick, and usually much less time consuming then reading in the fields. W and omega depend on a single time slice of U and V. Certainly, any computer that can run the model can compute W and Omega. Remember it is not the size of the total data set, just the size of single time record. Since it seems that CROCO has diverged substantially from ROMS, I STRONGLY suggest you confirm that there calculation of omega is the same as in ROMS. This should be easy to see in the source code for CROCO. In roms, omega is diagnosed in omega.F, is calculated to have units of m^3/s, and is called W, where W=[Hz/(pm*pn)]*omega. pm=1/dx, pn=1/dy. I think with ocean parcels you can store the W field in a different file from the other fields. Jamie Caveat: I have not yet done this with oceanParcels, I have been using tracmass and ariane. I hope to use oceanParcels with ROMS sometime later this summer. I have been using tracmass with Mercator. |
Beta Was this translation helpful? Give feedback.
-
Hi everyone, hope you had a great week-end ! First of all, Thanks a lot @Plagioclase for sharing your code with us, it helped me a lot running parcels with my ROMS dataset which gave pretty good results ! I am comparing the output with another Lagrangian model (Ichthyop) and both gave alike results (even though differencies tend to accumulate over time) which is reassuring regarding the implementation. However I still have a small issue that and I can't figure out what I am doing wrong. I am pretty sure it has to do with the I think this parameter is not taken into account most of the time when I run my simulation because it doesn't change the output of the run without it and I obtain a dispersion pattern that is opposite to what I expect (for instance particles going west whereas I expect them to go east with a very similar trajectory). It may have to do with the order in which I pass the different commands (might be erased by another one) but I can't figure out what is the problem. I was once able to get the expected dispersal (particles going in the right direction according to the prediction of Ichthyop) without really knowing what I had done to make it work and since then I wasn't able to reproduce this output despite the fact that my code hasn't changed. Here is the order in which I pass the different commands :
If any of you have an idea of what I have to change in this code, I would be glad to hear about it. Hugo |
Beta Was this translation helpful? Give feedback.
-
Dear @HugoDENISFR. Your code seems to be ok. Do you mean that the In other words: do the results 'swap' if you change to |
Beta Was this translation helpful? Give feedback.
-
No you are right, I was wrong the outputs are slightly different. Still, I don't understand the radical change in outputs when changing AdvectionRK4 for AdvectionRK4_3D. I would expect that taking into account vertical advection would change a bit the trajectories and depth of particles (like I obtain in other models such as Ichthyop or Opendrift) and not reverse the whole trajectory (see below). So there is clearly something I am missing and maybe not due to vertical motion as I thought before. With Advection RK4_3D (same inititial positions, fields, etc...) -> |
Beta Was this translation helpful? Give feedback.
-
Sorry, I am not sure what I'm seeing in these figures.. Could you provide a minimal working example? That is a much more tractable way for us to explore/fix a potential bug |
Beta Was this translation helpful? Give feedback.
-
@HugoDENISFR, I had a similar issue with the horizontal current components being the wrong way round. The solution (if I recall correctly) was to change the sign of the depths you write to the depths file - see if that works. |
Beta Was this translation helpful? Give feedback.
-
Thanks again @Plagioclase , it worked ! Cheers, Hugo |
Beta Was this translation helpful? Give feedback.
-
Hello everyone, Hope you are all well since the last discussion. I used for several simulations the code version for ROMS dataset and it worked well. However I came across several errors where particles reached the bottom of the water column which make me think again about the implementation and there is something I am a bit uncertain about : In my ROMS dataset there are n+1 s_w levels and n s_rho levels. Thus u,v and w have n values in the vertical axis. However Parcels doesn't work if the vertical dimensions of my sigma_levels and u,v,w variables don't match. I am not sure why but from what I have seen, it is due to the way NEMO grid is designed (same number of t-points and w-points in NEMO). The work around I had use was to delete the bottom sigma levels. Therefore the sigma grid and fields had the same vertical dimension. Because of these errors I am a bit uncertain about if this is the good way of doing this or not. And because of what @JamiePringle said, adding a layer of u,v,w with null velocities to my dataset at the top or bottom doesn't seem a good idea in a physical point of view. If you have any thoughts about this, I would be glad to hear them ! |
Beta Was this translation helpful? Give feedback.
-
Dear all, |
Beta Was this translation helpful? Give feedback.
-
Hello all, Thank you for this discussion! It really helped me understand which vertical velocities from ROMS to use. This makes perfect sense. However, when loading the 4D depth variable to the fieldset with "fieldset.from_c_grid_dataset" to then attribute depth to U, V and W using the recently-implemented method "set_depth_from_field", this field has "interp_method='cgrid_tracer'". Does this mean that during the computation of particle depth in the simulation, depth will also be interpolated based on c-grid interpolation scheme? If that's the case, the loading of depth variable should be done in the original horizontal coordinates (without previous interpolation to psi points as suggested above, right? I tried running parcels using depth at w points (vertically) and: a) at the original horizontal rho-points and b) horizontally interpolated to psi. No error was raised with a) or b), but the results were slighly different (colors in the trajectories indicate depth): Looking forward for getting some feedback on this! |
Beta Was this translation helpful? Give feedback.
-
Firstly, thank you so much for producing OceanParcels (and all of the documentation) - fabulous work!
I'm trying to use fields from Croco (a version of ROMS) which uses an s-coordinate system. Following this discussion and using the s-coordinate functions described on this page (currently using the old ROMS function for legacy reasons), I've produced a sigma-depth file using the code at the bottom of this post (adapted from the code Philippe wrote in the discussion above).
The problem is that whilst this is running, I'm getting "OutOfBoundsError" when I initialise shallow (<5m) particles. I've been sloppy and for testing purposes I'm currently using a snapshot as my zeta field rather than a time-mean or time-evolving zeta, but this doesn't explain why particles initialised at -4m are 'out of bounds', and it isn't related to the vertical velocity because I have the same issue with 2D advection.
I'm pretty certain that the reason why this isn't working is because I'm currently using the sigma/stretching function values at the rho points rather than the zeta points, so the shallowest values in my depth-sigma field is as deep as -3.5m rather than zeta which is what I assume it's supposed to be. But I'm not sure what to do about this because Croco returns u/v fields at the rho depth level, and if I change the coordinates I'm inputting into the dimensions list to use the n+1 w depths rather than the n u/v/rho depths, I get a "index X is out of bounds..." error.
I'm a bit perplexed at the moment, assistance would be greatly appreciated!
Beta Was this translation helpful? Give feedback.
All reactions