Skip to content

Update master with the developments that went into the neXtSIM v2 paper#662

Merged
tdcwilliams merged 83 commits intomasterfrom
develop
Jan 23, 2025
Merged

Update master with the developments that went into the neXtSIM v2 paper#662
tdcwilliams merged 83 commits intomasterfrom
develop

Conversation

@einola
Copy link
Copy Markdown
Member

@einola einola commented Jan 23, 2025

This PR contains the most recent developments that made it into the neXtSIM v2 paper. This includes

  • Fixes to the penetrating shortwave scheme
  • Checks on reading in MLD
  • Updates for reading in forcing files
  • The melt pond scheme
  • The impact of atmospheric stability on ice-ocean drag

einola and others added 30 commits May 30, 2023 15:39
This addresses issue #634, by adding I (the penetrating short-wave
radiation) as an output to IABulkFluxes and using this in the Winton and
Semtner models.
The value of I_0 is quite uncertain it seems, but let's use the Winton
(2000) value for now (30%).
I put the arguments in the wrong place in the IABulkFlux function,
compared to the call. This is fixed. I also added t1 and t2 as output
variables for the moorings.
The initial code written by me and Dani. It compiles, but it needs an
option to turn on the meltpond scheme and mooring outputs.
It had a misspelling in its name - and more importantly, the
permeability was incorrectly calculated.
It's called thermo.use_meltponds
We can now output "meltpond_volume", "meltpond_lid_volume", and
"meltpond_fraction". All are averaged over the entire grid cell.
There were lots of minor problems with the initial implementation. Most
of them are now fixed. The model runs and produces not unreasonable
looking meltponds. The main remaining problems are
 - For some reason the meltpond volume recovers almost immediately after
   flushing
 - I get very deep meltponds in the oldest and most ridged ice. These
   can be deeper than the ice is thick and they never go away, because
   they don't flush and the lid becomes more than a meter thick and
   grows very slowly.
The isPermiable function now takes all temperatures into account and
selects the Assur or Notz formulation, depending on temperature.
Some code clean-up of isPermeable. No functionality change or bug
fixing.
A less convoluted and more obvious way of growing, melting, or forming a
lid on top of a melt pond.
There's a risk that the ponds become unrealistically deep. The can even
become deeper than the ice is thick. This patch prevents this, and
(arbitrarily) limits the depth to 1/3 of the ice thickness by flushing
excess water via the runoff variable. The limit can be thought out more
carefully.
I was missing the melting term for the lid. This is now fixed.
In this version, the meltponds don't affect the freshwater balance
(EMP). I also added a code to remove meltponds if the lid gets too thick
(more then 30 cms).
I simply added a constant (tunable) albedo for the fraction of ponds
without a lid (or a lid thinner than 5 cm - arbitrary number). This has
a substantial effect in initial tests, but much more testing is needed.
This adds an alb_scheme == 4 option. It simply assumes constant snow, ice, and meltpond albedos. Something like alb_ice = 0.54, alb_sn = 0.83, and alb_pnd = 0.3 makes sense.
This adds a check on the MLD in checkFieldsFast, which throws an
std::runtime_error if MLD is outside [0, 10 km]. The lower bound is
quite strict (could also be a few mm) and the upper bound is just there
because the code requires an upper bound. In reality we just want to
check the lower bound.
einola and others added 18 commits August 1, 2024 13:48
We're still in the CICE spirit, but this includes some important fixes.
This way, we don't have to calculate the specific humidity too often.
It also fits better within the code.
A correct calculation of the Obukov length this time! Some minor
additional adjustments.
I multiplied the flux with cp + cpv. Not sure why, it should just be cp.
But the default is to do it. This is really only useful for debugging!
The new drag was not given correctly to the dynamics because I forgot to
multiply with wind speed and atmospheric density(!)
This moves the calculation of some of the more complex constants out of
the element loop to save time. Also adds the limiting length scale as an
option, to put a sensible limit on the Obukov length (Richard says 100 m
is good).
I missed a factor two when transcribing the equations. Fixing this
actually improves the results!
I managed to introduce a bug in the ocean drag calculation in a
misguided attempt for minor optimisation. Remember Knuth!
I went through the constants yet again, and everything looks fine. Also
changed the default Linv limit to something that makes more sense (and
what I've used for my tests the whole time).
It should be the Mellor and Kantha one, as this is implied in the paper
we're writing.
Change the default value of melt_type
@einola einola requested a review from tdcwilliams January 23, 2025 09:33
@einola einola marked this pull request as draft January 23, 2025 09:34
@einola einola marked this pull request as ready for review January 23, 2025 10:02
Copy link
Copy Markdown
Contributor

@tdcwilliams tdcwilliams left a comment

Choose a reason for hiding this comment

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

some minor clarifications to add + typos

Comment thread model/gridoutput.hpp
longName = "Meltpond fraction";
stdName = "meltpond_fraction";
Units = "1";
cell_methods = "area: mean";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is this area fraction, and is it fraction of the total grid area or just of the ice-covered area? Perhaps change the long name to "Meltpond area fraction"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ps if it is the fraction of ice-covered area use cell_methods = "area: mean where ice";

  • same for the other new melt-pond and drag variables

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

after reading the rest of the code the drags should be "area: mean where ice" but the melt pond variables can stay as "area: mean"

Comment thread model/options.cpp
("thermo.force_neutral_atmosphere", po::value<bool>()->default_value(false),
"Don't modify the neutral (default) atmospheric drag coefficient to take atmospheric stability into account.")
("thermo.limiting_lengthscale", po::value<double>()->default_value( 1. ),
"A limit for the Obukov lenght (m).")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
"A limit for the Obukov lenght (m).")
"A limit for the Obukov length (m).")

Comment thread model/finiteelement.cpp
M_age_det[i] += dt*M_conc[i];
double w_age = old_conc <= 0? 0.: std::min(old_conc/M_conc[i], 1.);
// no ice => w_age = 0 => age = dt
// melting => old_conc > M_conc => w_age = 1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// melting => old_conc > M_conc => w_age = 1
// melting => old_conc > M_conc => w_age = 1 => age += dt

Comment thread model/finiteelement.cpp
double del_vi_thick = M_thick[i] - old_vol;
w_age = old_vol <= 0 ? 0. : std::min(old_vol/M_thick[i], 1.);
// no ice => w_age = 0 => age = dt
// melting => old_vol > M_thick => w_age = 1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// melting => old_vol > M_thick => w_age = 1
// melting => old_vol > M_thick => w_age = 1 => => age += dt

Comment thread model/finiteelement.cpp
psih = 2.*std::log(0.5*(1.+x*x));
}

// 4. The drag coefficients: ( \frac{k}{\ln{z/z_0} - \Pshi} )^2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// 4. The drag coefficients: ( \frac{k}{\ln{z/z_0} - \Pshi} )^2
// 4. The drag coefficients: ( \frac{k}{\ln{z/z_0} - \Psi} )^2

Comment thread model/finiteelement.cpp
// double const roff = (0.85 - 0.7*M_conc[cpt]) ; Holland et al. 2012
M_pond_volume[cpt] += (1-roff)*availableWater*M_conc[cpt];

// Flush the pond if there's not enough ice. Skip everyting if there's no pond.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Flush the pond if there's not enough ice. Skip everyting if there's no pond.
// Flush the pond if there's not enough ice. Skip everything if there's no pond.

Comment thread model/finiteelement.cpp
D_pond_fraction[cpt] = std::sqrt(M_pond_volume[cpt]/dep2frac);

// Make sure there is no pond on snow
D_pond_fraction[cpt] = std::min(D_pond_fraction[cpt], 1.-hs/(hs+0.2));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if hs = 0, D_pond_fraction = 1?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, but it can only happen that D_pond_fraction = 1 if hs = 0.

Comment thread model/finiteelement.cpp
M_lid_volume[cpt] += delLidVolume;
M_pond_volume[cpt] -= delLidVolume;

// Remove lid if the pond is frozen solid or if it's too thick
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should M_thick and/or M_h_young increase if pond freezes solid?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, the pond volume is just an inactive tracer. It doesn't hold any mass.

@einola
Copy link
Copy Markdown
Member Author

einola commented Jan 23, 2025

Because of branch protection (both master and develop are protected), it's best to merge this as it is and then fix everything in a separate PR.

@einola einola requested a review from tdcwilliams January 23, 2025 12:08
@tdcwilliams tdcwilliams merged commit 9383d90 into master Jan 23, 2025
einola added a commit that referenced this pull request Jan 24, 2025
Only changes to comments and metadata for output files.
tdcwilliams added a commit that referenced this pull request Jan 26, 2025
einola added a commit that referenced this pull request Jan 28, 2025
Merge pull request #662 from nansencenter/develop
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.

3 participants