How do I…?¶
Contents
Create and use configuration flags and parameters¶
Edit
src/pism_config.cdl
. Each flag or parameter is stored as a NetCDF attribute and should have a corresponding “_doc
” attribute describing its meaning and the “_type
” defining the type. All scalar parameters have to have “_units
” set as well.
pism_config:constants.standard_gravity = 9.81;
pism_config:constants.standard_gravity_doc = "acceleration due to gravity on Earth geoid";
pism_config:constants.standard_gravity_type = "scalar";
pism_config:constants.standard_gravity_units = "meter second-2";
One can access these parameters using the
Config
class.IceModel
and all classes derived fromComponent
have an pointer to an instance of this class as a data memberm_config
, so no additional code is necessary to initialize the configuration database.
To use a scalar parameter, do
double g = m_config->get_number("constants.standard_gravity");
To use a flag, do
bool compute_age = config->get_flag("age.enabled");
Note
It is best to avoid calling
m_config->get_...()
from within loops: looking up a parameter by its name is slow.Please see Configuration parameters for a list of flags and parameters currently used in PISM.
Create and use additional variables¶
Creating array::Array instances¶
PISM uses the following classes to manage 2D and 3D fields, their I/O and metadata:
|
scalar 2D fields |
|
vector 2D fields such as horizontal velocities; corresponds to 2 NetCDF variables |
|
2D time-dependent fields (used to read and store forcing data) |
|
scalar 3D fields (usually within the ice) |
Please see the documentation of these classes for more info. The base class array::Array
is
a virtual class, so code should use the above derived classes.
To create a scalar field, for example, one needs to create an instance of array::Scalar
and then set its metadata:
// land ice thickness
array::Scalar ice_thickness(grid, "thk");
ice_thickness.metadata()
.long_name("land ice thickness")
.units("m")
.standard_name("land_ice_thickness");
ice_thickness.metadata().set_number("valid_min", 0.0);
Here grid
is an IceGrid
instance, thk
is the name of the NetCDF variable,
WITH_GHOSTS
means that storage for “ghost” (“halo”) points will be allocated, and “2” is
the number of ghosts (in other words: required stencil width).
The array::Array::set_attrs()
call sets commonly used NetCDF variable attributes seen in
PISM output files:
|
the (descriptive) long name used for plotting, etc (a free-form string) |
|
units used in the code; does not have to match units in a file. |
|
CF standard name, if defined, or an empty string. |
The ice_thickness.metadata()
call above allows accessing variable metadata and
adding arbitrary attributes. See VariableMetadata
for details.
The CF convention covers some attribute semantics, including valid_min
in this example.
PISM will automatically convert units from ones present in an input file into internal
units defines by the set_attrs()
call above.
If you want PISM to save data in units other than internal ones, first set these “output” units:
ice_thickness.metadata().output_units("km");
Read data from a file¶
There are at least three cases of “reading data from a file”:
reading a field stored in an input file on a grid matching the one used by the current run (restarting a run),
reading a field stored in an input file on a different grid, interpolating onto the current grid (bootstrapping), and
reading a field stored in a file other than the input file using interpolation (assuming that grids are compatible but not identical)
// case 1, using a file name
unsigned int time = 0;
std::string filename = "filename.nc";
ice_thickness.read(filename, time);
// case 1, using an existing File instance (file is already open)
File file(communicator, "guess_mode", filename, PISM_READONLY);
ice_thickness.read(file, time);
RegriddingFlag flag = OPTIONAL;
double default_value = 0.0;
// cases 2 and 3 (interpolation)
ice_thickness.regrid(filename, flag, default_value);
// cases 2 and 3 (interpolation) using an existing File instance
ice_thickness.regrid(file, flag, default_value);
When interpolating (“regridding”) a field, the flag
specifies whether a variable is
required (flag
is CRITICAL
or CRITICAL_FILL_MISSING
) or optional (flag
is
OPTIONAL
or OPTIONAL_FILL_MISSING
). PISM will stop with an error message if a
required variable is not found in an input file.
Flag values of CRITICAL_FILL_MISSING
and OPTIONAL_FILL_MISSING
replaces “missing”
values matching the _FillValue
attribute by the default value.
If flag
is OPTIONAL
or OPTIONAL_FILL_MISSING
PISM will fill the variable with
default_value
if it was not found in the file.
Write data to a file¶
array::Array::define()
will define all spatial dimensions used by a variable. However, we
usually need to “prepare” a file by defining the time dimension and appending a value to
the time variable.
File file(m_grid->com, m_config->get_string("output.format"),
filename, PISM_READWRITE_CLOBBER, m_grid->ctx()->pio_iosys_id());
io::define_time(file, *m_grid->ctx());
io::append_time(file, *m_grid->ctx()->config(), current_time);
When a file is opened with the mode PISM_READWRITE_CLOBBER
, PISM checks if this file is
present overwrites if it is; to append to an existing file, use PISM_READWRITE
. To move
the file aside (appending “~
” to the file name), use PISM_READWRITE_MOVE
.
A newly-created file is “empty” and contains no records. The io::append_time()
call
creates a record corresponding to the current_time
(in seconds).
To write a field to an already “prepared” file, call
precip.write("filename.nc");
// or, if the file is already open and a File instance is available:
precip.write.(file);
Read scalar forcing data¶
PISM uses instances of the ScalarForcing
class to read scalar forcing data; please see
pism::surface::Delta_T
for an example.
Read 2D forcing fields¶
PISM uses instances of the array::Forcing
class to read 2D forcing fields that vary in
time; please see pism::surface::Given
for an example.
Previous | Up | Next |