All notable changes to the Community Firn Model should be documented in this file. Contributors to the CFM who are unfamiliar with changelogs should review the notes at the end of this document.
TL;DR: Write down the changes that you made to the the model in this document and update the version number here and in main.py, then update master on github.
To run the update: git commit -a -m "updating to vX.Y.Z. Details in changelog." git push git tag -a vX.Y.Z -m "CFM version vX.Y.Z" git push origin vX.Y.Z
Then, on github do a release, which will trigger an updated DOI.
1.1.11
https://communityfirnmodel.readthedocs.io/en/latest/
-
Issues
- If data is not written at each time step, dH that is saved/written to file does not represent the change since the last write.
-
Work in progress
- If data is not written at each time step, dH that is saved/written to file does not represent the change since the last write.
- Testing percolation modules from Vincent Verjans that solves Richard's equation and includes a dual-domain approach to handle preferential flow (these modules are included but may not work properly yet)
- Melt will likely be changed to have its own class
- Documentation for the CFM
- Goujon physics work, but could possibly be implemented more elegantly (it would be nice to avoid globals)
- Not exactly in progress, but at some point adding a log file that gets saved in the results folder would be a good idea.
- This release fixes an issue in the estimated surface elevation change dh, which was not accounting properly for elevation change due to sublimation and melt processes (it was just considerine dh due to firn compaction and new snow acccumulation). The new code explicitly includes dh_melt and dh_acc, which are the elevation change (for that time step) due to melt and accumulation + sublimation. The elevation change calculation should be considered to be in beta.
- firn_density_nospin.py, melt.py, sublim.py firn_density_nospin's update_dh function is now: dH = (sdz_new - sdz_old) + dh_acc + dh_melt - (iceout * t[iii]) The sdz terms are the sum of the layer thicknesses before and after compaction (different is thus dh from firn compaction); dh_acc is the elevation change due to new snow accumulation minus the sublimated volume; dh_melt is the elevation decrease due to surface melt; iceout (rate of m ice e.q./year) times the time step size is the elevation change due to ice flow. Note that this assumes steady state, and that the ice flow is calculated using the spin up climate (iceout is set to be the mean ice-equivalent accumulation rate during the spin up), unless set explicitly in the config file.
dh_melt is calculated in melt.py, and dh_acc is calculated using dh_sub, which is now returned by sublim.py.
- Version 1.1.10 is a minor update to fix an issue with the strain softening routine introduced in v1.1.9. (The code would throw an error if InputFileNamedudx was not in the .json).
- There is a small update to the documentation regarding BCO outputs.
- Version 1.1.9 is an update to add strain softening as described by Oraschewski and Grinsted (2021; https://doi.org/10.5194/tc-2021-240)
- This is a minor update. The main point is to add example .csv files and update the input climate .pkl file. The example .csv files were made using the .pkl files, so the outputs should match.
- There is a readme.txt file in the CFMinput_example directory with some details about those forcing files.
- isotopeDiffusion.py This file had not been updated to deal with the 'updatedStartDate' feature, which it now does. Current fuctionality limits its use to using .csv files as inputs.
- Documentation: I updated the model output documentation.
- This update fixes an issue where sublimation was automatically turned off.
- Hopefully this is a short-lived release; the next release should include an improved enthaply solver to avoid the ICT threshold error and still run quickly. A surface energy balance module is also in development.
- firn_density_nospin.py, sublim.py firn_density_nospin had a line that set any accumulation below a threshold to 0. This prevented sublimation from occuring because sublimation flux was inferred from the assumption that any negative values in the accumulation input was sublimation. The code now explicitly takes sublimation inputs, either through a field in the input dictionary (climateTS in firn_density_nospin.py) or a .csv file ('InputFileNameSublim' in .json). The .json should now include a boolean key/value 'SUBLIM' (default True). If that key is not in .json the code will automatically set to be true. (The design is that sublimation can be turned off, but only deliberately.) The code retains the ability to infer sublimation from negative values of accumulation (it does this if (1) inputs come from climateTS but SUBLIM is not a field in climateTS; or (2) if 'InputFileNameSublim' is NOT in the .json.)
- Note that sublim.py still does not alter the temperature. The reason for this presently is that we assume that the surface (skin) temperature calcuated by the forcing RCM (e.g. TS in MERRA-2) already accounts for that energy balance, so we just set the surface temperature to equal the input skin temperature at that time step.
- physics.py The viscosity calculations would throw a divide by zero error for layers that are at the ice density. This is now fixed so that those layers will have viscosity equal to zero (which is of course not true, but can be dealt with in post processing.)
- The enthalpy solver scheme's routine to correct the amount of LWC after each iteration was wrong, which caused the firn to densify too quickly when there was melt present.
- solver.py See above note. The g_liq correction at the end of the iteration loop is reverted to what was used in v1.1.2.
- There was an issue with the previous release in the order of operations within the model when melt was enabled. Prior to CFMv1.1.3, within a time step the firn first densified, then the melt routine occured, then heat diffusion, and then addition of a new snow layer with some density and temperature. Within the melt scheme, layers would melt, and the uppermost layer after melt (ie. the new surface) would take on the temperature of the old surface (which would often be colder than the melting temperature), which was not realistic. I switched the code so that that layer (called the 'partial melt' layer in the CFM) would have temperature of 273.15. However, this caused the surface temperature to always become the melting temperature, and the cold from a new snow layer would not ever diffuse into the firn if the next time step included melt. The solution was to move the diffusion to the end of the time step, so now the process goes: densification, meltwater percolation and refreezing (due to cold content), addition of new layer, heat diffusion. (Also: admitedly in reality the skin temperature should be zero during a time step when there is melt, but in model world with larger time steps, e.g. daily, there can be melt but the mean temperature for the day is still below freezing.)
- ModelOutputs.py There was an issue with the gridding feature for liquid water content, which is fixed. (The interpolation was just a linear interpolation of LWC, but it needs to be calculated by linearly interpolating the cumulative sum and then differencing to get the mass correct.)
- firn_density_nospin.py See above under notes. Heat diffusion now comes at the end of the time step loop.
- melt.py When ponding is turned on, layers that reached impermeable density during the refreeze process are now set to have zero available pore space for accomodating excess water. These layers could form above a volume of excess liquid. This change caused some nodes to have very small negative LWC, which was a rounding issue; now the code sets negative LWC to be zero.
- Addition of melt scheme parameters to .json and several small bug fixes.
- melt.py, example.json I added the 'user choices' from melt.py to the .json config file. They are:
ColeouLesaffre
(True/False; whether or not to use the ColeouLesaffre parameterization for irreducible water content);IrrVal
(float [%], default 0.02; Irreducible water content if ColeouLesaffre is false);RhoImp
(float, [kg m^-3], default 830; impermeable density threshold);DownToIce
(True/False; if True all water will permeate through any ice lenses above the firn/ice transition);Ponding
(True/False; True allows water to saturate (pond) atop impermeable layers, e.g. to form an aquifer. Otherwise water above irreducible content becomes runoff);DirectRunoff
(float; applicable if Ponding==True; fraction of excess LWC not considered for ponding but running off directly [between 0 and 1]);RunoffZuoOerlemans
(True/False; applicable if Ponding==True; computes lateral runoff following Zuo and Oerlemans (1996) Eqs.(21,22));Slope
(float, used only if RunoffZuoOerlemans==True: slope value used in Zuo and Oerlemans (1996) Eq.(22)).
- melt.py Fixed issue in the ColeouLesaffre parameterization for the case when rho = rho_ice, which put a zero in a denominator
- firn_density_nospin.py, firn_density_spin.py Fixed issue with reader.py, which now returns 4 values (associated with new feature that saves model forcing to the output file)
- There are a fair number of changes and fixes in this release, and admittedly I did a poor job of documenting them over the last few months as I worked on things. Most of the work deals with the meltwater bucket scheme and the associated enthalpy scheme.
- I have moved away from using main.py to run the CFM. Instead, I am using either (1) a script similar to main.py but that includes forcing file generation and model configuration right in that script (i.e. you edit json parameters in that script rather than in a .json file directly); or (2) a jupyter notebook to configure the run and then start the run. Please let me (Max) know if you want those scripts or notebooks prior to them making it to Github.
- diffusion.py, solver.py The enthalpy scheme was continuing to give me issues. The solver needs to iterate to converge on a solution. In order to save computing time, the iteration loop would terminate once one iteration was within some percentage threshold of the previous iteration - but that is not full convergence. It turns out that that method could lead to a mass conservation issue. There is a new variable called ICT (itercheck threshold) that determines how close one iteration needs to be to the previous one in order to terminate the loop. By default I set this to zero (full convergence), but you can change it to something like 1e-8 if you want to speed things up a little bit. (The metric I am using for convergence is the total LWC in the firn). If there are more than 100 iterations, ICT is set to 1e-8 (if initially zero), or multiplied by 10 (if ICT was initially >0). After 200 iterations, ICT is again multiplied by 10. My testing has indicated that this works, but please let me know if you are having issues with this.
- melt.py There were a few issues with the bucket scheme. In particular, there is a loop to deal with distributing water based on available pore space and cold content, which would throw an error when there was available pore space at a shallower depth then where the water existed. Also, the code that allows ponding atop impermeable layers did not remove 'excess' water (more than could be accomodated with full saturation), which led to mass conservation issues. Finally, the temperature of the uppermost node where melt occurs (the PM, or partial melt, layer) did not previously have its temperature set to the melting temperature; it now does.
- ModelOutputs.py, writer.py the output file now by default includes the original forcing data (including spin up period) that was fed to the CFM. This facilitates reproducibility. The columns in the 'forcing' output variable are: [decimal time, skin temperature, smb, melt, rain].
- The main work in this release is improving the enthalpy scheme for resolving heat diffusion when there is liquid water present. I cannot say for certain how 'wrong' the previous scheme was (I don't think it was too wrong!), but Vincent Verjans identified that with the new meltwater schemes water would refreeze more quickly than expected. The newest code is actually slower because the solver needs to iterate to find a solution; previously I used a set value of iterations, but now a while loop ensures that the iterations continue until convergence.
- diffusion.py, solver.py See note above regarding the enthalpy routine.
- ModelOutputs.py GridOutputs is now compatible with melt functions.
- The outputs from running the melt module have been reduced to three: LWC (liquid water content, in each model node, at each timestep [m w.e.]); refreeze (total refreezing within the firn at each time step [m w.e.]); and runoff (total runoff from the firn at each timestep [m w.e.]). Note that this assumes a 1m x 1m firn column, so if you want total runoff for e.g. a MERRA-2 grid cell, you will need to multiply by the area of the grid cell.
- This release could be buggy; it is the first release of two new liquid water schemes developed by Vincent Verjans. My limited testing indicates that they are working, but I am still working on testing. Please let me know if you encounter errors.
- I am still working on making the pre-CFM workflow smooth; i.e. taking data directly from an RCM, creating a timeseries of the climate varibles, and passing those to the CFM (scripts: siteClimate_from_RCM.py, RCMpkl_to_spin.py). If you are using these (or interested), please let me know if you have suggestions on how to make this workflow easier.
- melt.py Previously there were two bucket schemes (one written by Vincent Verjans, and one written by Max Stevens). Vincent wrote a new bucket scheme that took the best of each of those, so now there is one bucket scheme that we think works as accurately as a bucket scheme could. It has more options than the previous schemes, e.g. set the density and/or thickness of impermeable layers; set the irreducible saturation. At present, you need to dig into the code to change them, but these will be integrated into a .json in a future release.
- melt.py Vincent also wrote a meltwater scheme that uses Darcy flow. The details are on the CFM's readthedocs page. FYI: It is slow compared to the bucket scheme because it uses a sub-time step.
- darcy_funcs.py This is a new file that contains functions needed to make the darcy scheme work.
- firn_density_nospin.py There are more changes than this (I have been very lazy with documentation recently! Sorry!), but the main fix is adding a bit of code to deal with the instance when the forcing data are passed in a dictionary (i.e. climateTS) but spinUpdate is false. This is implemented around line 185.
- This is the first major change to the code structure that warrants going from 1.0 to 1.1. Previously, the spin up was done by calling firn_density_spin, getting the output, and then calling firn_density_nospin. This was a bit clunky, because (1) if you were writing your own API (i.e. not using main.py), you would have to call both of those; and (2) if you were using a variable climate spinup, firn_density_spin was just a formality to create an initial condition.
- I have now wrapped firn_density_spin into firn_density_nospin. If the model needs to spin up or needs an initial condition, it is called; otherwise it is bypassed. THE UPSHOT IS THAT YOU ONLY NEED TO CREATE AN INSTANCE OF firn_density_nospin IN YOUR API. The behavior of the CFM should be the same as before.
- You can now input climate data from a dictionary into firn_density_nospin.
- RCMpkl_to_spin.py This new script takes climate data that is packaged in a pandas dataframe and creates a time series (including spin up) that forces the CFM. Returns a dictionary.
- siteClimate_from_RCM.py This script takes climate data from an RCM or analysis product for a specified lat/lon and puts it in a dataframe, which in turn will feed into RCMpkl_to_spin.py.
- firnbatch_generic.py This script is an alternative API to using main.py - it is useful to batch a bunch of runs when you have a common (baseline) .json file and need to change something slightly for each run.
- See Notes above for an overview.
- main.py Now it only calls firn_density_nospin.
- main.py Changed so that it can now take a pickled pandas dataframe (specified in .json; key: 'input_type') as opposed to .csv files; calls new script 'RCMpkl_to_spin' to generate a spin up time series. That spin up series is put in a dictionary, which is passed to firn_density_nospin
- firn_density_nospin.py Now calls firn_density_spin if no spin file is found, of if NewSpin=True in the .json, or if -n is included as an argument when calling main.py. Otherwise spin up is skipped and uses the spin file for the initial condition.
- firn_density_nospin.py The 'stpsPerYear' parameter in the .json is no longer needed if 'timesetup' is set to exact. In this case, CFM looks at the input climate files and figures out the time step size and updates 'stpsPerYear'; for 'exact' runs, it is only used to calculate the number of nodes in the grid in firn_density_spin. If 'timestep' is 'interp', the model behavior is the same as before (you need to set stpsPerYear correctly.)
- "NewSpin" true/false - this is whether or not you want to redo the spin if a spinup file exists already. Default false.
- "input_type" 'dataframe' or 'csv' - if the inputs to CFM come from a csv (as has been the case until now) or from a dataframe. Default csv. This only matters at the main.py level. If you write your own API to firn_density_nospin you can pass a dictionary as the climateTS argument passed to firn_density_nospin (as is done with firnbatch_generic.py).
- "DFresample" pandas Timedelta (string) - the resampling frequency (e.g. '5D') for the climate input data.
- "DFfile" filename as string - the filename, located in "InputFileFolder", of the dataframe to load if "input_type" is 'dataframe'.
- firn_density_nospin.py (and outputs): The DIP output now includes an additional column (the last), which is the DIP to a specific depth horizon (DIPhz). This is specified in the .json with key "DIPhorizon". This feature is helpful because the bottom of the model domain at each time step can change through time, which results in inconsistencies in how the (total) DIP changes through time. The default value for DIPhorizon is 80% of the initial bottom of the domain (e.g. if the model domain was initially 200m, the DIPhorizon is 160m). If the firn thickness changes and the bottom of the domain becomes less than DIPhorizon, the DIPhz value output will be NaN. In this case, the density and depth outputs can be used to calculate DIP to any depth horizon. (This is the previous model behavior.) The very first value in the DIPhz column is the horizon depth.
- ModelOutputs.py When using the grid outputs option, previous behavior was that values would be extrapolated using the same value for all points outside the interpolation. For example, if the output grid was 0 to 150 m, but the actual model domain only went to 140 m, the same values for density, temperature, etc. would be assigned to the outputs for all depths beyond 140m. Now they are filled in using NaN.
- physics.py B. Medley at NASA GSFC re-ran her calibration, and the model parameters have changed slightly.
- firn_density_nospin.py The CFM would include 'dr2_dt' in the outputs associated with grain size. That variable was initialized, but not updated in the main code (time-stepping loop), which led to the saved file including a bix matrix of zeros. For now this has been disabled (i.e. there is no 'dr2_dt' at all.)
- there is only one quick fix in this release.
- Related to this fix, I should note that I use 365.25 to calculate seconds in a year. So, when creating forcing files from climate data, which requires calculating mass fluxes in units of m/year, you should use 365.25 days per year. (And, this then gets divided out when you use 'exact' time stepping.) If you have any suggestions on how to improve this, please let me know! The reality is that it is a bit challenging because each year does not have the same number of seconds due to leap years.
- firn_density_nospin.py Using 'exact' time setup still used the 'stpsPerYear' in the .json file to figure out the specific amount of accumulation (and melt, and rain) at each time step. This led to small errors in the calculated accumulation rate (especially if the time step size was slightly different for each time step.) It now uses the delta time (dt) value to calculate those mass fluxes.
- This release is a bit preemptive, but pushing it now to fix issue with timing of temperature diffusion and new surface temperature in time loop.
- A few major changes in this release:
- The way that the CFM saves its outputs and writes to file has been updated (including a new module, ModelOuputs.py)
- The regridding scheme has been updated by Vincent Verjans to add a third subgrid.
- ModelOutputs.py, firn_density_nospin.py ModelOutputs.py is a new module that takes the place of a bunch of code in firn_density_nospin.py. Previously, firn_density_nospin initialized arrays for each variable so be saved/written to file (e.g self.rho_out). ModelOutputs is a class, and it sets up a dictionary to contain all of the output arrays. These arrays are updated at each time step by calling ModelOutputs. The upshot is that firn_density_nospin is cleaned up a fair bit and it is easier to add new features that you might want to write to file.
- diffusion.py Added thermal conductivity parameterization from Calonne et al. (2019) (which is the new default).
- writer.py With the new ModelOutputs module, writer.py now loops through the variables to write with a generic line of code, rather than unique bits of code for each variable.
- regrid.py regrid now splits the grid into 3 subgrids of different resolutions. This new scheme is very similar to the original regrid scheme. The difference is that it uses a coarser resolution below grid2, in a grid called grid22. There is still grid1 (high resolution), then grid2 at a coarse resolution and then grid22 at a very coarse resolution. Below grid22, there is the grid23 which is again the same resolution as grid2. As before, the grid3 provides the stock of layers to be removed at each accumulation event. To use this, you need to add 3 new keys to the .json: "multnodestocombine" specifies how many nodes in grid2 to combine to make grid22; "grid2bottom" specifies the depth of the grid2 to grid22 transition. More information about the doublegrid feature is in the CFM documentation.
- writer.py, ModelOutputs.py There is now an option to grid your outputs onto a common grid, which can save some space on your hard drive. Add 'grid_outputs' (True/False) to the .json to enable it, and add 'grid_output_res' to the resolution to specify the resolution (in meters) that you want the grid to be at (e.g. 0.1 will make a 10-cm grid.)
- diffusion.py Calonne 2019 is now the default thermal conductivity.
- firn_density_nospin.py Order of operations in the time-stepping loop has been changed (reverted) - the surface temperature was updated before diffusion was called, which resulted in getting slightly different answers when using doublegrid.
- regrid.py Previously, the CFM did not account for changes in self.gridtrack due to removal of nodes by melt/sublimation. This is fixed for the sublime and bucketVV schemes.
- melt.py, bucketVV When the melt amount was such that the pm_dz became extremely small, the model crashed. pm_dz is now forced to be at least 1e-6 m thick.
- melt.py, bucketVV* A previous update got rid of a for loop in bucketVV when calculating runoff. There was a small error that computed the runoff term as a vector instead of a scalar.
-
This is a long overdue release, and there will likely be a number of changes that are not documented here. I am pretty confident that nothing should break from 1.0.5 to 1.0.6.
-
The CFM paper to cite has finally been published; it is at https://doi.org/10.5194/gmd-13-4355-2020
- physics.py The NASA Goddard densification model (Medley et al. 2020) has been added.
- diffusion.py There is now a function that allows the user to choose which parameterization for conductivity to use. There a quite a few! The .json configuration file needs a new key, 'conductivity', to utilize this functionality. Default is 'Anderson'.
- firn_density_nospin.py New functionality to use firn temperature observations (e.g. from a thermistor string)
- firn_density_nospin.py New functionality to turn off densification (in case e.g. you only want to model temperature)
- radiation penetration Still in progress!
- firn_density_nospin.py New functionality to set output bit size. Previous and current default is float32. Add key 'output_bits' to .json file to specify. Recommend keeping at float32 except in the case that you might be feeding the results into another model run.
- firn_density_nospin.py, writer.py New functionality to write to the spin file during the 'main' (non-spin) run, which allows you to run a long model run (e.g. effective spin up with a reference, variable climate). Then, future runs can reuse that effective spin up. See documentation for more information. Two new keys in the .json file for this: 'spinUpdate' (boolean) and 'spinUpdateDate' (float).
- physics.py Morris and Wingham (2014) physics has a bug (the units were wrong on the deltaE parameter)
- firn_density_nospin.py the final step of the model run now gets written - prior behavior was that the time steps to write were by interval, e.g. every 3rd time step. New behavior will now write the final time step no matter what.
-
This release includes quite a number of changes, which I admittedly did a poor job documenting. The biggest change is the directory structure (sorry if this causes things to break for you, but it simplifies things in the long haul.) CFM_main was moved out of directory firnmodel and is now just a subdirectory just below CommunityFirnModel. Directory gasmodel is gone (all that code was in the firn air module, so it was legacy code). Directory firnmodel is also gone.
-
The other notable changes are: fixing Morris (2014) physics; changing the way the timestepping is set up and handled; and isotope diffusion now is its own class.
-
I have begun to start documenting the CFM using readthedocs.io, so there is now a directory under CommunityFirnModel called docs which holds that documentation information. Please let me know if you have suggestions.
- physics.py Barnola physics had an error where the exponent n for zone 2 densification was always 3; it should be 1 (and now is) when the stress is less than 0.1 MPa.
- physics.py Fixed Morris (2014) physics based on correspondence with L. Morris (spring 2019)
- isotopeDiffusion.py Isotope diffusion is now in a class. Each isotope (dD and d18O) gets its own instance. This module took the code previously in diffusion.py (written by Emma Kahle). There are several bug fixes (notably b in the tortuosity factor, Johnsen 2000 eqn. 18), and diffusion length is now included as an output.
- merge.py Code to merge very thin layers into a thicker layer.
- fcts_snowpackflow.py, prefflow_snowpack.py, re_snowpack.py Scripts for Vincent Verjans' implemention of the reynolds equation and preferential flow (not yet fully tested for compatibility in master branch.)
- sublim.py Script to include sublimation as a process.
- firn_density_nospin.py, firn_density_spin.py Previously the CFM took time steps of size dt that were the same size. Now dt is a vector and can vary. There is new field 'timesetup' in the .json configuration file, which can be 'exact', 'interp', or 'retmip'. 'interp' is the old method; the model takes the start and end dates from the input files and the number of timesteps per year from the .json to put together (uniform dt) vector of modeltimes. 'exact' actually takes the series of decimal years (e.g. 2015.12, 2015.24, 2015.37) from the input files and uses the spacing between those dates to get dt. 'retmip' is specific to the retmip experiment - its functionality is not tested within the main framework and it may be removed in the future.
- This release includes several components: I fixed implementation of Morris and Wingham (2014) physics, changed how mean temperature is calculated, added a corrected/modified DH calculation, and changed how T10m is calculated. There may be a few things (e.g. random print statements) that are hanging around. I am still working on implementing V. Verjans melt schemes.
- physics.py, firn_density_spin.py, firn_density_nospin.py A number of the models use the mean annual surface temperature in their calculations (e.g. the Arthern family, Li and Zwally). On short time scales, this is generally equal to the mean of the entire temperature input. In longer simulations it changes through time. self.T_mean is now calculated at the beginning of firn_density_nospin as the mean temperature of the last 10 years. This should be quite close to the value of T10m if there is no melt. I am still working on how to implement this; it currently uses a Hamming filter with pandas 'rolling' feature.
- diffusion.py T10m previously used an interpolation to find the temperature at 10m exactly; it now is just the temperature at the first node at 10m depth or greater. It should be slightly faster.
- physics.py I fixed how the Morris and Wingham (2014) model was coded. There was an error in the original text. I fixed it based on correspondence with L. Morris in May 2019. Email me ([email protected]) if you want more detail; it will be published in a forthcoming paper.
- firn_density_nospin.py DH is calculated based on compaction at each time step, the thickness of the new snow layer, and the thickness of ice (called iceout in the model) that is removed at each time step. If the bottom of the model domain is less than ice density, the CFM did not account for the additional compaction that occured between the bottom of the firn and the ice (917) density horizon. I added a 2 new fields, DHcorr and DHcorrC, that is added to the 'DIP' model output, which mirror the previous fields DH and DHc (elevation change since last time step and cumulative since begining of when output begins writing).
- This release fixes several bugs. (I am working on implementing V. Verjan's preferential flow melt routine; there are several things that may you may notice related to that in this release, e.g. a note about 'merging' and 'Reeh01' in the .json file. This will be fixed in version 1.0.4.)
- physics.py HLSigfus was changed slightly so that boolean masks are created for the different zones, which makes the code easier to read. HLdynamic (instant version) was changed so that in the case of negative accumulation, A_instant is set to zero.
- firn_density_nospin.py Changed dH calculation to set to be zero at the first write time step.
- firn_density_nospin.py Added comp_firn as an additional variable written with DIP. It is the total firn compaction during the previous time step, not including the ice dynamics or new accumulation (i.e. the summed thickness change of all of the layers).
- firn_density_nospin.py Variable crate_out has been changed to comp_out to reflect that it is just compaction, not the rate.
- writer.py Output name has changed from 'compaction_rate' to 'compaction'
- firn_density_nospin.py and firn_density_spin.py Changed the 'SeasonalTCycle' feature to exit model run if turned on and hemisphere is not selected.
- constants.py Latent heat and specific heat were incorrectly converted to kJ units - fixed, and values were changed to be consistent with Cuffey and Paterson. Note that specific heat changes with temperature; it can be set to reflect that in diffusion.py (Thanks to Jiajin Chen and Gang Hai for pointing this out.)
- firn_density_spin.py the seasonalTcycle feature was hard coded to be only for Greenland (it had been updated to be modular in firn_density_nospin) - now 'spin' matches 'nospin'.
- melt.py, in def percolation_bucket: The compaction output was incorrect because the partial melt (PM) was given a new thickness (in dzn) of zero. Fixed so that the boxes the melt entirely get a value of zero in dzn but the PM box gets its new thickness after melt
- general Running the example, using example.json, did not work because bdot_type was set in it to instant, and the example smb file contains a negative value. firn_density_nospin.py now prints an error and exits if this happens and example.json is set to bdot_type = 'mean'.
- physics.py, firn_density_nospin.py, writer.py Added code to calculate the firn viscosity predicted by each model and optionally write that to file (Brita Horlings contribution).
- firn_density_nospin.py Added Li2015, which uses a different value for beta than Li and Zwally 2011.
- firn_density_spin.py Added 'manualclimate', which must also be added to .json file to use. It allows the user to set the long-term temperature and accumulation rate manually; helpful e.g. in the case of short model runs.
- firn_density_nospin.py Added 'manual_iceout', which must also be added to .json file to use. It allows the user to set the long-term ice-dynamic thinning manually, e.g. the vertical ice velocity at the bottom of the firn column; helpful e.g. if it is different than the mean accumulation rate for the modeled period.
- example.json several new fields were added.
- melt.py Max's original bucket scheme, which did not work well, was removed.
- diffusion.py The enthalpy method has been redone using a source-based method. The code is based on work from Voller and Swaminathan, 1990. The function in diffusion.py is called enthalpyDiff(). The prior code is still there (for now) and is called enthalpyDiff_old.
- melt.py: An additional bucket scheme, coded by Vincent Verjans, has been added. It is meant to be used with standard heat diffusion. Testing is underway to use it with the enthalpy diffusion method. To use this method (for now) you need to comment/uncomment in firn_density_nospin.py.
-
diffusion.py, solver.py: Previously, Gamma_P in diffusion.py was defined as
Gamma_P = K_firn / (c_firn)
. This, however, assumes that c_firn is constant, but it is not (varies with temperature). Now,Gamma_P = K_firn
. A new variable, c_vol, is added - it is the heat capacity:c_vol = rho * c_firn
. This comes into solver.py where a_P_0 is defined: previously it wasa_P_0 = tot_rho * dZ / dt
, but now it isa_P_0 = c_vol * dZ / dt
. -
plotter.py: Changed to be simpler and more generic.
-
User can now initialize the model using density and temperature measurements, rather than using the firn profile predicted by the spin-up climate. Two fields need to be added to the .json file. The .csv file with the input data is column-wise. The first column is depth, the second is density, and the third is temperature.
- example.json: field "initfirnFile", (filename.csv)
- example.json: field "initprofile", (true/false)
-
There is now an option to write refrozen and runoff (writer.py)
-
example.json: field "SeasonalThemi", (north/south), which specifies the hemisphere that the model run is simulating. This only works in concert with with SeasonalTCycle: true
-
example.json: field "coreless", (true/false): if SeasonalTCycle: true and hemisphere is south, the user can choose to implement a 'coreless winter' seasonal temperature cycle.
-
All files: Added #/usr/bin/env python at start
-
All files: Converted all tabs to spaces (python standard)
- There was an issue that during time steps with no accumulation self.dzNew was not set to zero, leading to the model over-predicting surface-elevation changes when there are small time steps (i.e. many with zero accumulation). Thanks to Brooke Medley for pointing this out.
A changelog is meant to keep a record of changes that are made to software. Any changes made should be recorded here. When you are working on the code, I recommend keeping this file open and logging changes as you make them. You should (1) keep a version of changelog.md that is exclusive to your branch and (2) keep a running list at the top of what features you are working on. When you push your code to master, update this file (i.e. the version on your branch) to reflect what it should look like on the master branch.
If the changes are pushed to the master branch, the version should be updated.
Changes should be categorized into Added, Changed, Deprecated, Removed, or Fixed. Because there are numerous files in the CFM that can be changed, the affected file should be listed in italics prior to the change when appropriate. E.g.
- constants.py Added specific heat of water
Changes to the .json files (most frequently new fields that are added to the configuration .json files) should be updated in the file example.json, as then recorded in this document specifying the addition/change, e.g.
- example.json Added field initprofile, (true/false) which specifies whether to use an initial condition from depth/density/temperature measurements, rather than a spin up climate
Any push to the master branch should get a new version, which should be changed in main.py as well as in this changelog and readme.md. Small changes warrant changing the version in the 3rd digit (i.e. 1.0.X), and larger changes warrant changing the 2nd digit (i.e. 1.X.0). I am not sure what a version 2 of the CFM would look like.
I used information from KeepAChangeLog for this document.