Thank you for your interest in contributing to lpjmlkit, an open-source R package for operating LPJmL and processing related data. We currently prefer contributions in the form of bug reports, feature requests, and suggestions of code improvements as issues in the lpjmlkit GitHub repository. If you want to contribute code, please follow the instructions below. Please note that due to our current worflow information on the authorship of code contributions may get lost.
+Before you start contributing to lpjmlkit, here are a few steps to get you set up:
+Fork the lpjmlkit GitHub repository to your own GitHub account.
Clone your forked repository to your local machine.
+git clone https://github.com/YourUsername/lpjmlkit.git
+cd lpjmlkit
+Install the package and its dependencies following the instructions in the documentation.
Now you’re ready to start making contributions!
+To contribute to lpjmlkit, please follow these steps:
+Your contributions will be greatly appreciated and will help make lpjmlkit even better.
+We use the the Advanced R Style Guide for R code.
+Furthermore we use the following tools to ensure code quality: * roxygen2 for documentation. * testthat for unit tests. * lintr for static code analysis.
+Please make sure that your code passes all tests and static code analysis before submitting a pull request.
+Please note that by contributing to lpjmlkit, you are expected to adhere to our Code of Conduct. We strive to maintain a welcoming and inclusive community, and we expect respectful and considerate behavior from all contributors: * Be Respectful: Treat all community members with respect and kindness. * Inclusivity: Ensure that your language and actions are inclusive and respectful of diversity. * Collaboration: Encourage a collaborative and supportive atmosphere.
+We do not tolerate: * Harassment: Any form of harassment, trolling, or offensive behavior. * Discrimination: Discrimination, derogatory comments, or exclusionary practices. * Bullying: Bullying or aggressive behavior towards others.
+Reporting Incidents
+If you witness or experience any violations, please report them to jannesbr@pik-potsdam.de. All reports will be handled confidentially and promptly.
Thank you for being part of the lpjmlkit community!
+Version 3, 19 November 2007
+Copyright (C) 2007 Free Software Foundation, Inc. https://fsf.org/
+Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
+The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.
+The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program–to make sure it remains free software for all its users.
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
+Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.
+A secondary benefit of defending all users’ freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.
+The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.
+An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.
+The precise terms and conditions for copying, distribution and modification follow.
+“This License” refers to version 3 of the GNU Affero General Public License.
+“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
+“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
+To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
+A “covered work” means either the unmodified Program or a work based on the Program.
+To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
+To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
+An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
+The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
+A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
+The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
+The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
+The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
+The Corresponding Source for a work in source code form is that same work.
+All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
+You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
+Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
+No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
+When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures.
+You may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
+You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
+You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
+A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
+You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
+A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
+A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
+“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
+If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
+The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
+Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
+“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
+When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
+Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
+All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
+If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
+Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
+You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
+However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
+Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
+Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
+You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
+Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
+An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
+You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
+A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.
+A contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
+Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
+In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
+If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
+If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
+A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
+Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
+If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
+Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.
+Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.
+The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
+Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.
+If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
+Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
+END OF TERMS AND CONDITIONS
+vignettes/lpjml-data.Rmd
+ lpjml-data.Rmd
LPJmL Data 💾 is an lpjmlkit module that groups
+around the data class LPJmLData
and aims to facilitate
+reading and processing of LPJmL inputs and outputs by combining the raw
+data with available meta data (meta files, header files or manually) to
+avoid a large overhead. It further enables easy subsetting,
+transformations and basic statistics of the data and allows export to
+common data formats.
+
LPJmL Data first requires reading LPJmL input or output data into R +by applying the read_io function (1). The returned object is of class +LPJmLData (2), for which basic statistics can be calculated (3), the +inner data can be modified (4), or exported (5) to common data +formats.
+
+read_io is a generic function to read LPJmL input and output files. It
+currently supports three different file formats, “meta”, “clm” and
+“raw”:
“meta” - Easy to use and strongly
+recommended.
+Set "output_metafile" : true
in your LPJmL run
+configuration to generate output files in “meta” format. LPJmL input
+files can also be created in “meta” format.
+# Read monthly runoff with meta file.
+runoff <- read_io("./output/mrunoff.bin.json")
“clm” - Use if “meta” is not available or in
+combination.
+Most LPJmL input files use “clm” format. To write output files in “clm”
+format set "fmt" : "clm"
in your LPJmL run configuration.
+Some optional meta data (e.g. band_names
) need to be
+specified manually while the basic information about file structure is
+derived automatically from the file header.
+# Read monthly runoff data with header.
+runoff <- read_io("./output/mrunoff.clm",
+ # If the clm version is lower than 4 set nbands and nstep
+ # manually so that month dimension is recognized correctly.
+ nbands = 1,
+ nstep = 12,
+ # Useful additional information that is not needed to read the
+ # Data.
+ variable = "runoff",
+ descr = "monthly runoff",
+ unit = "mm/month")
“raw” - Not recommended for use (with
+lpjmlkit).
+By default, LPJmL output files are written as “raw” files
+("fmt" : "raw"
in your LPJmL run configuration). These
+files include no meta data about their structure or contents and should
+therefore be combined with the "output_metafile" : true
+setting to generate a corresponding “meta” file. Otherwise, all meta
+data need to be specified by the user. Historically, some LPJmL input
+files use “raw” format.
+# Read monthly runoff raw data.
+runoff <- read_io("./output/mrunoff.bin",
+ # Specify all meta data if they differ from the function
+ # default values.
+ ...)
+
+read_io returns an object of an R6 class LPJmLData
with two
+main attributes, $data
and $meta
:
$data A class base::array
- returns
+the data array with default dimensions “cell”, “time” and “band”
+runoff$data
+# , , band = 1
+#
+# time
+# cell 1901-01-31 1901-02-28 1901-03-31 1901-04-30
+# 0 2.427786e+02 1.265680e+02 2.279087e+02 2.027685e+02
+# 1 4.189225e-14 1.032507e-16 0.000000e+00 0.000000e+00
+# 2 3.860512e-14 0.000000e+00 0.000000e+00 0.000000e+00
+# 3 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
+# 4 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
+# 5 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
$meta Meta data of class
+LPJmLMetaData
- returns the corresponding meta data
+(e.g. runoff$meta$unit
)
+runoff$meta
+# $sim_name "lu_cf"
+# $source "LPJmL C Version 5.3.001"
+# $history "./LPJmL_internal/bin/lpjml ./configurations/config_lu_cf.json"
+# $variable "runoff"
+# $descr "monthly runoff"
+# $unit "mm/month"
+# $nbands 1
+# $nyear 111
+# $firstyear 1901
+# $lastyear 2011
+# $nstep 12
+# $timestep 1
+# $ncell 67420
+# $firstcell 0
+# $cellsize_lon 0.5
+# $cellsize_lat 0.5
+# $datatype "float"
+# $scalar 1
+# $order "cellseq"
+# $bigendian FALSE
+# $format "raw"
+# $filename "runoff.bin"
+
+To get an overview of the data, LPJmLData
supports the
+usage of the base functions: length()
, dim()
,
+dimension()
, summary()
and
+plot()
. More methods can be added in the
+future.
+# Self print; also via print(runoff).
+runoff
+# $meta |>
+# .$sim_name "lu_cf"
+# .$variable "runoff"
+# .$descr "monthly runoff"
+# .$unit "mm/month"
+# .$nbands 1
+# .$nyear 111
+# .$nstep 12
+# .$timestep 1
+# .$ncell 67420
+# .$cellsize_lon 0.5
+# .$cellsize_lat 0.5
+# Note: not printing all meta data, use $meta to get all.
+# $data |>
+# dimnames() |>
+# .$cell "0" "1" "2" "3" ... "67419"
+# .$time ""1901-01-31" "1901-02-28" "1901-03-31" "1901-04-30" ... "2011-12-31"
+# .$band "1"
+# $summary()
+# 1
+# Min. : 0.0000
+# 1st Qu.: 0.0619
+# Median : 4.4320
+# Mean : 28.7658
+# 3rd Qu.: 27.5627
+# Max. :2840.9602
+# Note: summary is not weighted by grid area.
+
+# Return the dimension length of $data array; dimnames function is also available.
+dim(runoff)
+# cell time band
+# 67420 1332 1
+
+# Plot as maps or time series, depending on the dimensions.
+plot(runoff)
+
+Each LPJmLData object comes with a bundle of methods to modify its
+state: add_grid()
, transform()
and
+subset()
.
📍 add_grid()
Adds a
+$grid attribute (as an LPJmLData object) to the object,
+providing the spatial reference (longitude and latitude) for each
+cell.
+# Object- oriented (R6 class) notation (assigning grid directly to runoff)
+runoff$add_grid()
+
+# Common R notation (overwriting the original object)
+runoff <- add_grid(runoff)
+
+# Use the read_io arguments if a grid file cannot be detected automatically.
+runoff <- add_grid(runoff, "./output/grid.clm")
🔁 transform()
the
+$data
dimensions.
+Transforms the spatial dimension from “cell” to “lon” (longitude) and
+“lat” (latitude) or the temporal dimension “time” into separate “year”,
+“month”, and “day” dimensions. Combinations and back transformations are
+also possible. Transformation into the format “lon_lat” requires a
+$grid
attribute (see add_grid
above). Any
+transformation does not change the contents of the data, only the
+structure.
+# Transform into lon and lat dimensions. If add_grid has not been executed
+# before it is called implicitly.
+runoff <- transform(runoff, to = "lon_lat")
+runoff
+# [...]
+# $data |>
+# dimnames() |>
+# .$lat "-55.75" "-55.25" "-54.75" "-54.25" ... "83.75"
+# .$lon "-179.75" "-179.25" "-178.75" "-178.25" ... "179.75"
+# .$time "1901-01-31" "1901-02-28" "1901-03-31" "1901-04-30" ... "2011-12-31"
+# .$band "1"
+# [...]
+
+# Transform into year and month dimensions (day not available for monthly
+# runoff)
+runoff <- transform(runoff, to = "year_month_day")
+runoff
+# [...]
+# $data |>
+# dimnames() |>
+# .$lat "-55.75" "-55.25" "-54.75" "-54.25" ... "83.75"
+# .$lon "-179.75" "-179.25" "-178.75" "-178.25" ... "179.75"
+# .$month "1" "2" "3" "4" ... "12"
+# .$year "1901" "1902" "1903" "1904" ... "2011"
+# .$band "1"
+# [...]
+
+# Transform back to original dimensions.
+runoff <- transform(runoff, to = c("cell", "time"))
+runoff
+# [...]
+# $data |>
+# dimnames() |>
+# .$cell "0" "1" "2" "3" ... "67419"
+# .$time "1901-01-31" "1901-02-28" "1901-03-31" "1901-04-30" ... "2100-12-31"
+# .$band "1"
+# [...]
✂ subset()
the
+$data
.
+Use $data
dimensions as keys and names or indices as values
+to subset $data
. $meta
data are adjusted
+according to the subset. Applying a subset changes the contents of the
+data and cannot be reversed.
+# Subset by dimnames (character string).
+runoff <- subset(runoff, time = "1991-05-31")
+runoff
+# $meta |>
+# .$nyear 1
+# .$ncell 67420
+# .$subset TRUE
+# [...]
+# Note: not printing all meta data, use $meta to get all.
+# $data |>
+# dimnames() |>
+# .$cell "0" "1" "2" "3" ... "67419"
+# .$time "1991-05-31"
+# .$band "1"
+# [...]
+
+# Subset by indices
+runoff <- subset(runoff, cell = 28697:28700)
+runoff
+# $meta |>
+# .$nyear 1
+# .$ncell 4
+# .$subset TRUE
+# [...]
+# Note: not printing all meta data, use $meta to get all.
+# $data |>
+# dimnames() |>
+# .$cell "28696" "28697" "28698" "28699"
+# .$time "1991-05-31"
+# .$band "1"
+# [...]
+
+Finally, LPJmLData objects can be exported into common R data formats:
+array
, tibble
, raster
and
+terra
.
More export methods can be added in the future.
as_array()
Export
+$data
as an array. In addition to simply returning the
+$data
element of an LPJmLData
object, as_array
+provides functionalities to subset and aggregate $data
.
+Subsetting is conducted before aggregation.
+# Export as an array with subset of first 6 time steps and aggregation along
+# the dimension cell (mean).
+as_array(runoff,
+ subset = list(time = 1:6),
+ aggregate = list(cell = mean))
+# band
+# time 1
+# 1901-01-31 19.49611
+# 1901-02-28 20.28368
+# 1901-03-31 27.93595
+# 1901-04-30 36.90505
+# 1901-05-31 39.38885
+# 1901-06-30 32.80252
as_tibble()
Export
+$data
as a tibble
object,
+providing the same additional subsetting and aggregation functionality
+as as_array.
+# Export as a tibble with subset of first 6 time steps
+as_tibble(runoff, subset = list(time = 1:6))
+# # A tibble: 404,520 × 4
+# cell time band value
+# <fct> <fct> <fct> <dbl>
+# 1 0 1901-01-31 1 184.
+# 2 1 1901-01-31 1 0
+# 3 2 1901-01-31 1 0
+# 4 3 1901-01-31 1 0
+# 5 4 1901-01-31 1 0
+# 6 5 1901-01-31 1 0
+# 7 6 1901-01-31 1 0
+# 8 7 1901-01-31 1 0
+# 9 8 1901-01-31 1 0
+# 10 9 1901-01-31 1 0
+# # … with 404,510 more rows
🌐 as_raster()
/
+as_terra()
Export $data
as a
+raster
+or a terra
object
+(successor of raster), providing the same additional subsetting and
+aggregation functionality as as_array()
. as_raster()
+returns a RasterLayer for a single data field and a RasterBrick if the
+result contains more than one band or more than one time step.
+# Export the first time step as a RasterLayer object from the raster package.
+as_raster(runoff, subset = list(time = 1))
+# class : RasterLayer
+# dimensions : 280, 720, 201600 (nrow, ncol, ncell)
+# resolution : 0.5, 0.5 (x, y)
+# extent : -180, 180, -56, 84 (xmin, xmax, ymin, ymax)
+# crs : +proj=longlat +datum=WGS84 +no_defs # nolint:commented_code_linter.
+# source : memory
+# names : runoff
+# values : -1.682581e-13, 671.8747 (min, max)
+
+# Export the first time step as a terra SpatRaster object.
+as_terra(runoff, subset = list(time = 1))
+# class : SpatRaster
+# dimensions : 280, 720, 1 (nrow, ncol, nlyr)
+# resolution : 0.5, 0.5 (x, y)
+# extent : -180, 180, -56, 84 (xmin, xmax, ymin, ymax)
+# coord. ref. : lon/lat WGS 84 (EPSG:4326)
+# source : memory
+# name : runoff
+# min value : -1.682581e-13
+# max value : 6.718747e+02
+# unit : mm/month # nolint:commented_code_linter.
+
+# Export the first 4 times step as a RasterBrick object.
+as_raster(runoff, subset = list(time = 1:4))
+# class : RasterBrick
+# dimensions : 280, 720, 201600, 4 (nrow, ncol, ncell, nlayers)
+# resolution : 0.5, 0.5 (x, y)
+# extent : -180, 180, -56, 84 (xmin, xmax, ymin, ymax)
+# crs : +proj=longlat +datum=WGS84 +no_defs # nolint:commented_code_linter.
+# source : memory
+# names : X1901.01.31, X1901.02.28, X1901.03.31, X1901.04.30
+# min values : -1.682581e-13, -1.750495e-13, -2.918900e-13, -1.516298e-13
+# max values : 671.8747, 785.2363, 828.2853, 987.4359
+
+# Export the first 4 time steps as a terra SpatRaster object.
+as_terra(runoff, subset = list(time = 1:4))
+# class : SpatRaster
+# dimensions : 280, 720, 4 (nrow, ncol, nlyr)
+# resolution : 0.5, 0.5 (x, y)
+# extent : -180, 180, -56, 84 (xmin, xmax, ymin, ymax)
+# coord. ref. : lon/lat WGS 84 (EPSG:4326)
+# source : memory
+# names : 1901-01-31, 1901-02-28, 1901-03-31, 1901-04-30
+# min values : -1.682581e-13, -1.750495e-13, -2.918900e-13, -1.516298e-13
+# max values : 6.718747e+02, 7.852363e+02, 8.282853e+02, 9.874359e+02
+# unit : mm/month, mm/month, mm/month, mm/month
+# time (days) : 1901-01-31 to 1901-04-30
+
+More helpful functionality included with LPJmL Data:
read_meta()
to read meta information from meta and
+header files as LPJmLMetaData
objects.
+LPJmLMetaData
are usually attached to an
+LPJmLData
object but can also be used to gain information
+about an LPJmL input or output file without reading the data.
LPJmLMetaData
objects can be exported as
+as_list
and as_header
to create header objects
+or write header files.
read_header()
, write_header()
,
+get_headersize()
, get_datatype()
provide
+low-level interaction with LPJmL input and output files primarily in
+“clm” format.
+
+
+npp <- read_io(filename = "./output/npp.bin.json",
+ subset = list(year = as.character(1970:2011)))
+
+# Transform "time" into "year" and "month" dimensions.
+npp$transform(to = "year_month_day")
+
+# Plot timeseries with aggregated cell and month dimensions. Note that spatial
+# aggregation across cells is not area-weighted.
+plot(npp,
+ aggregate = list(cell = mean, month = sum))
+
+# Also available as data array.
+global_npp_trend <- as_array(npp,
+ aggregate = list(cell = mean, month = sum))
+
+runoff <- read_io(filename = "./output/runoff.bin.json",
+ subset = list(year = as.character(2002:2011)))
+
+# Usage of pipe operator operator |> (%>% via package magrittr R version < 4.1)
+runoff |>
+ # Transform the time and space dimensions ...
+ transform(to = c("year_month_day", "lon_lat")) |>
+ # ... to subset summer months as well as northern hemisphere (positive)
+ # latitudes.
+ subset(month = 6:9,
+ lat = as.character(seq(0.25, 83.75, by = 0.5))) |>
+ # for plotting sum up summer month and take the average over the years
+ plot(aggregate = list(year = mean, month = sum))
+
+gpp <- read_io(filename = "./output/gpp.bin.json",
+ subset = list(year = as.character(2002:2011)))
+
+# Transform into lon_lat format.
+gpp$transform(to = "lon_lat")
+
+# Plot GPP per latitude.
+plot(gpp, aggregate = list(time = mean, lon = mean))
+
+# Coordinates for cells around Potsdam.
+coordinates <- tibble::tibble(lat = as.character(c(52.25, 52.400922, 53.25)),
+ lon = as.character(c(12.75, 13.03638, 12.75)))
+
+# Complete pipe notation, from reading to plotting data.
+read_io(
+ filename = glue("./cftfrac.bin.json"),
+ subset = list(year = as.character(2000:2018))
+) |>
+ transform(to = "lon_lat") |>
+ # Special case for subsetting of lat and lon pairs
+ subset(coords = coordinates) |>
+ # Mean across spatial dimensions
+ plot(aggregate = list(lon = mean, lat = mean))
+
LPJmLData
and LPJmLMetaData
objects are
+closed environments, each of an R6 class, that function as a data
+container.
+Do not replicate R6 objects like
+ my_copy <- lpjml_data
+ # Instead use:
+ my_copy <- lpjml_data$clone(deep = TRUE)
Otherwise, my_copy
and lpjml_data
point to
+the same environment, and any subsetting or transformation methods
+applied to my_copy
will also affect
+lpjml_data
.
Do not try to manually overwrite either the $data
or
+any $meta
data attributes within LPJmLData
+objects. It is either not possible or can mess up the integrity of the
+object. Methods surrounded by double underscores
+($.__<method>__)
or attributes surrounded by
+underscores ($._<attribute>_
) are only for low-level
+package development and should not be used by users for their data
+handling.
When performance is important, choose R6 method notation
+runoff$transform(to = "lon_lat")
over common R notation
+transform(runoff, to = "lon_lat")
.
The “meta” format is only supported by recent LPJmL versions.
+When comparing older (< LPJmL version 5.3) output data with LPJmL 5.3
+output data it can be useful to combine meta
+("output_metafile" : true
) with the header file format
+("fmt": "clm"
), which has been supported since LPJmL
+version 4, for simplification of process pipelines.
vignettes/lpjml-runner.Rmd
+ lpjml-runner.Rmd
LPJmL Runner 🏃 is a lpjmlkit module of functions
+that have the goal to simplify the execution of simulations with LPJmL
+and further to execute complex, nested and multiple simulation sequences
+fast and less error prone without having a big (bash) script
+overhead.
+To install LPJmL, read the LPJmL
+installation instructions.
! Important ! The LPJmL Runner module only supports
+unix-based operating systems in which the working
+environment for LPJmL is configured!
+For users on the PIK cluster: Load the "lpjml"
module or
+add it to your ".profile"
.
The LPJmL Runner generally requires 3 to 4 working steps: Define a +modified parameter table (1), create the corresponding configuration +files (2), check if the these are valid for LPJmL (3 - optional) and run +or submit LPJmL with each configurations (4).
+
+Define what LPJmL configurations/parameters to be changed. Please
+familiarize yourself with available configuration options.
+The base configuration file (e.g.”lpjml_config.cjson”) can be read in
+via read_config
as a nested list object. Using the same
+syntax configurations/parameters can be changed directly in the
+corresponding configuration file or in a data frame (see example).?write_config
for more information.
+Now the central function is write_config
, create and write
+LPJmL Configuration (config) file(s) "config_*.json"
from a
+data frame with the parameters of a base config file
+"lpjml_config.cjson"
to be changed.
+?write_config
for more information.
+config_details <- write_config(my_params, model_path, sim_path)
+Check whether your config(s) are valid for LPJmL by passing the returned
+data frame to check_lpjml
. It won’t raise an error
+(dependencies might not be satisfied yet) but will print/return the
+information of lpjcheck
.
+lpjml_check(config_details, model_path, sim_path)
+Run LPJmL for each Configuration locally via run_lpjml
or
+submit as a batch job to SLURM (PIK Cluster) via
+submit_lpjml
. run_lpjml
can also be utilized
+within slurm jobs to execute multiple single cell runs.?submit_lpjml
or ?run_lpjml
for
+more information.
+# run interactively
+run_details <- run_lpjml(config_details, model_path, sim_path)
+# OR submit to SLURM
+submit_details <- submit_lpjml(config_details, model_path, sim_path)
+library(lpjmlkit)
+# Why tibble? -> https://r4ds.had.co.nz/tibbles.html
+# Tibbles also provide a better overview of the data and directly show the type
+# of each column, which is very important for integer/floating point values.
+library(tibble)
+
+model_path <- "./LPJmL_internal"
+sim_path <- "./my_runs"
+ +
Single cell (or short number of multiple cells) simulations can be +executed locally or on a login node. This mode is especially useful when +it comes to testing or comparing local data.
++
+# create parameter tibble
+params <- tibble(
+ sim_name = c("spinup", "lu", "pnv"),
+ landuse = c("no", "yes", "no"),
+ # only for demonstration
+ nspinup = c(1000, NA, NA),
+ reservoir = c(FALSE, TRUE, FALSE),
+ startgrid = c(27410, 27410, 27410),
+ river_routing = c(FALSE, FALSE, FALSE),
+ wateruse = c("no", "yes", "no"),
+ const_deposition = c(FALSE, FALSE, TRUE),
+ # run parameter: dependency sets the restart paths to the corresponding
+ # restart_filename and calculates the execution order
+ dependency = c(
+ NA, "spinup", "spinup"
+ )
+)
+
+# write config files
+config_details <- write_config(
+ x = params, # pass the defined parameter tibble
+ model_path = model_path,
+ sim_path = sim_path,
+ js_filename = "lpjml_config.cjson" # (default) the base config file
+)
+
+# read and view config
+config_lu <- read_config(
+ filename = paste0(sim_path, "/configurations/config_lu.json") # nolint:absolute_path_linter.
+)
+View(config_lu)
+
+# check config & LPJmL
+check_config(
+ x = config_details, # can be filename (vector) or tibble
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+# execute runs sequentially
+run_details <- run_lpjml(
+ config_details,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+# create parameter tibble
+params <- tibble(
+ sim_name = c("spinup_oldphen",
+ "spinup_newphen",
+ "oldphen",
+ "old_lu",
+ "lu_toolbox"),
+ # object oriented like syntax to access nested json elements
+ `input$landuse$name` = c(
+ NA,
+ NA,
+ NA,
+ NA,
+ "input_toolbox_30arcmin/cftfrac_1500-2017_64bands_f2o.clm"
+ ),
+ nspinup = c(1000, 1000, NA, NA, NA),
+ new_phenology = c(FALSE, TRUE, FALSE, TRUE, TRUE),
+ startgrid = c(27410, 27410, 27410, 27410, 27410),
+ river_routing = c(FALSE, FALSE, FALSE, FALSE, FALSE),
+ dependency = c(NA, NA, "spinup_oldphen", "spinup_newphen", "spinup_newphen")
+)
+
+# write config files
+config_details <- write_config(params, model_path, sim_path)
+
+# check config & LPJmL
+check_config(config_details, model_path, sim_path)
+
+# execute runs sequentially
+run_details <- run_lpjml(config_details, model_path, sim_path)
+ +
Global simulations are simulations on all available cells with a +coherent water cycle. It requires more computational ressources which is +why they have to be run at dedicated compute nodes, at PIK Cluster only +accessible via SLURM Job scheduler. Therefore LPJmL has to be +“submitted”.
++
+# create parameter tibble
+params <- tibble(
+ sim_name = c("spinup",
+ "old_lu",
+ "lu_toolbox"),
+ `input$landuse$name` = c(
+ NA,
+ NA,
+ "input_toolbox_30arcmin/cftfrac_1500-2017_64bands_f2o.clm"
+ ),
+ dependency = c(NA, "spinup", "spinup"),
+ # slurm option wtime: analogous to sbatch -wtime defines slurm option
+ # individually per config, overwrites submit_lpjml argument
+ # (same for sclass, ntasks, blocking or constraint)
+ wtime = c("15:00:00", "3:00:00", "3:00:00")
+)
+
+# write config files
+config_details <- write_config(
+ x = params,
+ model_path = model_path,
+ sim_path = sim_path,
+ output_list = c("vegc", "soilc", "cftfrac", "pft_harvestc", "irrig"),
+ output_list_timestep = c("annual", "annual", "annual", "annual", "monthly"),
+ output_format = "clm"
+)
+
+# check config & LPJmL
+check_config(config_details, model_path, sim_path)
+
+# submit runs to slurm
+run_details <- submit_lpjml(
+ x = config_details,
+ model_path = model_path,
+ sim_path = sim_path,
+ group = "open"
+)
+ +
You can save the generated config tibble by applying
+saveRDS
to it to reuse for a rerun or resubmission next
+time …
Also if you want do not want to submit all runs you can …
+
+# use a subset for the rows - in this example you may only want to resubmit the
+# transient runs
+run_details <- submit_lpjml(
+ x = config_details[2:3, ],
+ model_path = model_path,
+ sim_path = sim_path,
+ group = "open"
+)
a bit dirty though If you want to reuse an old spinup
+simulation, you can copy the file or create a symlink of the file to
+"<sim_path>/restart/<spinup_sim_name>/restart.lpj"
.
+Make sure the file/symlink is named "restart.lpj"
R package lpjmlkit, version 1.7.0
+ +A collection of basic functions to facilitate the work with the Dynamic Global Vegetation Model (DGVM) Lund-Potsdam-Jena managed Land (LPJmL) hosted at the Potsdam Institute for Climate Impact Research (PIK). It provides functions for performing LPJmL simulations, as well as reading, processing and writing model-related data such as inputs and outputs or configuration files. ## Overview
+LPJmL Runner only supports Unix-based operating systems that have an LPJmL version >= 4 installed. - ✍ write_config()
write config.json files using a data frame with parameters to be changed and a base configuration file - 🔍 check_config()
check if generated config.json files are valid for LPJmL simulations - ▶ run_lpjml()
run LPJmL directly (e.g. single cell simulations) or 🚀 submit_lpjml()
to SLURM (e.g. global simulations)
read_io()
read LPJmL input and output as a LPJmLData
object, containing the data array and LPJmLMetaData
+plot()
the data or get insights via summary()
and other base statstransform()
it to other time and space formatssubset()
the underlying dataas_array()
, as_tibble()
and as_raster()
/ as_terra()
to export into common R data formatsread_meta()
read meta or header files as LPJmLMetaData
objectcalc_cellarea()
to calculate the area of LPJmLData objects underlying grid or for other objects latitudesread_header()
read the header of LPJmL files, get_headersize()
get the size of a file header or create_header()
to create a header object for writing input filesget_datatype()
get information on the data type used in different LPJmL filesasub()
functionality of the subset method to be used on a base array, also to replace datalibrary(help = "lpjmlkit")
+For installation of the most recent package version an additional repository has to be added in R:
+ +The additional repository can be made available permanently by adding the line above to a file called .Rprofile
stored in the home folder of your system (Sys.glob("~")
in R returns the home directory).
After that the most recent version of the package can be installed using install.packages
:
+install.packages("lpjmlkit")
Package updates can be installed using update.packages
(make sure that the additional repository has been added before running that command):
The package comes with vignettes describing the basic functionality of the package and how to use it. You can load them with the following command (the package needs to be installed):
+ +In case of questions / problems please contact Jannes Breier jannesbr@pik-potsdam.de.
+To cite package lpjmlkit in publications use:
+Breier J, Ostberg S, Wirth S, Minoli S, Stenzel F, Müller C (2024). lpjmlkit: Toolkit for Basic LPJmL Handling. doi: 10.5281/zenodo.7773134 (URL: https://doi.org/10.5281/zenodo.7773134), R package version 1.7.0, <URL: https://github.com/PIK-LPJmL/lpjmlkit>.
+A BibTeX entry for LaTeX users is
+@Manual{,
+ title = {lpjmlkit: Toolkit for Basic LPJmL Handling},
+ author = {Jannes Breier and Sebastian Ostberg and Stephen Björn Wirth and Sara Minoli and Fabian Stenzel and Christoph Müller},
+ year = {2024},
+ note = {R package version 1.7.0},
+ doi = {10.5281/zenodo.7773134},
+ url = {https://github.com/PIK-LPJmL/lpjmlkit},
+}
A data container for LPJmL input and output. Container - because an
+LPJmLData object is an environment in which the data array as well as the
+meta data are stored after read_io()
.
+The data array can be accessed via $data
, the meta data via $meta
.
+The enclosing environment is locked and cannot be altered by any
+other than the available modify methods to ensure its integrity and
+validity.
+Use base stats methods like print()
, summary.LPJmLData()
or
+plot.LPJmLData()
to get insights and export methods like as_tibble()
+or as_raster()
to export it into common working formats.
meta
LPJmLMetaData
object to store corresponding meta data.
data
array containing the underlying data.
grid
Optional LPJmLData
object containing the underlying grid.
add_grid()
Method to add a grid to an LPJmLData
object.
+See also add_grid
...
See add_grid()
.
subset()
Method to use dimension names of LPJmLData$data
+array directly to subset each dimension to match the supplied vectors.
transform()
Method to transform inner LPJmLData$data
array
+into another space or time format.
...
See transform()
.
as_array()
Method to coerce (convert) an LPJmLData
object into an
+array.
...
See as_array()
.
as_tibble()
Method to coerce (convert) an LPJmLData
object into a
+tibble (modern data.frame).
...
See as_tibble()
.
as_raster()
Method to coerce (convert) an LPJmLData
object into a
+raster or brick object that can be used
+for any GIS-based raster operations.
...
See as_raster()
.
as_terra()
Method to coerce (convert) an LPJmLData
object into a
+rast object that can be used for any GIS-based raster
+operations.
...
See as_terra()
.
plot()
Method to plot a time-series or raster map of an LPJmLData
+object.
...
See plot.LPJmLData()
.
length()
Method to get the length of the data array of an LPJmLData
+object.
+See also length.
dim()
Method to get the dimensions of the data array of an
+LPJmLData
object.
+See also dim.
dimnames()
Method to get the dimnames (list) of the data array of an
+LPJmLData
object.
...
See dimnames.LPJmLData()
.
summary()
Method to get the summary of the data array of an
+LPJmLData
object.
new()
!Internal method only to be used for package development!
LPJmLData$new(data, meta_data = NULL)
A dedicated data class for an LPJmL input or output grid.
+LPJmLGridData serves the spatial reference for any LPJmLData objects and
+matches its spatial dimensions ("cell" or "lon", "lat") when attached as an
+grid attribute to it.\
+LPJmLGridData holds the information which longitude and latitude correspond
+to each cell center assuming WGS84 as the coordinate reference system or
+the corresponding cell index when the data comes with longitude and latitude
+dimension.
+As in LPJmLData the data array can be accessed via $data
,
+the meta data via $meta
.
lpjmlkit::LPJmLData
-> LPJmLGridData
Inherited methods
lpjmlkit::LPJmLData$.__set_data__()
lpjmlkit::LPJmLData$.__set_grid__()
lpjmlkit::LPJmLData$as_array()
lpjmlkit::LPJmLData$as_raster()
lpjmlkit::LPJmLData$as_terra()
lpjmlkit::LPJmLData$as_tibble()
lpjmlkit::LPJmLData$dim()
lpjmlkit::LPJmLData$dimnames()
lpjmlkit::LPJmLData$length()
lpjmlkit::LPJmLData$subset()
lpjmlkit::LPJmLData$summary()
lpjmlkit::LPJmLData$transform()
add_grid()
! Not allowed to add a grid to an LPJmLGridData
object.
...
See add_grid()
.
plot()
! No plot function available for LPJmLGridData
object. Use
+as_raster()
or as_terra()
(and plot()
) to visualize the grid.
...
See plot()
.
new()
!Internal method only to be used for package development!
LPJmLGridData$new(lpjml_data)
A meta data container for LPJmL input and output meta data.
+Container - because an LPJmLMetaData
object is an environment in which
+the meta data are stored after read_meta()
(or read_io()
).
+Each attribute can be accessed via $<attribute>
. To get an overview over
+available attributes, print
the object or export it as a list
+as_list()
.
+The enclosing environment is locked and cannot be altered.
sim_name
Simulation name (works as identifier in LPJmL Runner).
source
LPJmL version (character string).
history
Character string of the call used to run LPJmL. This +normally includes the path to the LPJmL executable and the path to the +configuration file for the simulation.
variable
Name of the input/output variable, e.g. "npp"
or
+"runoff"
.
descr
Description of the input/output variable.
unit
Unit of the input/output variable.
nbands
Number (numeric) of bands (categoric dimension). Please
+note that nbands
follows the convention in LPJmL, which uses the
+plural form for bands as opposed to nyear
or ncell
.
band_names
Name of the bands (categoric dimension). Not included
+if nbands = 1
.
nyear
Number (numeric) of data years in the parent LPJmLData
+object.
firstyear
First calendar year (numeric) in the parent LPJmLData
+object.
lastyear
Last calendar year (numeric) in the parent LPJmLData
+object.
nstep
Number (numeric) of intra-annual time steps. 1
for annual,
+12
for monthly, and 365
for daily data.
timestep
Number (numeric) of years between time steps.
+timestep = 5
means that output is written every 5 years.
ncell
Number (numeric) of cells in the parent LPJmLData
object.
firstcell
First cell (numeric) in the parent LPJmLData
object.
cellsize_lon
Longitude cellsize in degrees (numeric).
cellsize_lat
Latitude cellsize in degrees (numeric).
datatype
File data type (character string), e.g. "float"
. Note
+that data are converted into R-internal data type by read_io()
.
scalar
Conversion factor (numeric) applied when reading raw data
+from file. The parent LPJmLData
object contains the values after
+the application of the conversion factor.
order
Order of the data items in the file, either "cellyear"
,
+"yearcell"
, "cellindex"
, or "cellseq"
. The structure of the data
+array in the parent LPJmLData
object may differ from the original
+order in the file depending on the dim_order
parameter used in
+read_io()
.
offset
Offset (numeric) at the start of the binary file before the +actual data start.
bigendian
(Logical) Endianness refers to the order in which bytes +are stored in a multi-byte value, with big-endian storing the most +significant byte at the lowest address and little-endian storing the +least significant byte at the lowest address.
format
Binary format (character string) of the file containing the
+actual data. Either "raw"
, "clm"
(raw with header), or "cdf"
for
+NetCDF format.
filename
Name of the file containing the actual data.
subset
Logical. Whether parent LPJmLData
object is subsetted.
map
Character vector describing how to map the bands in an input
+file to the bands used inside LPJmL. May be used by read_io()
to
+construct a band_names
attribute.
version
Version of data file.
._data_dir_
Internal character string containing the directory +from which the file was loaded.
._subset_space_
Internal logical. Whether space dimensions are
+subsetted in the parent LPJmLData
object.
._fields_set_
Internal character vector of names of attributes +set by the meta file.
._time_format_
Internal character string describing the time
+dimension format, either "time"
or "year_month_day"
.
._space_format_
Internal character string describing the space
+dimension format, either "cell"
or "lon_lat"
.
._dimension_map_
Internal dictionary/list of space and time +dimension formats with categories and namings.
as_list()
Method to coerce (convert) an LPJmLMetaData
object into a
+list.
+See also as_list()
.
as_header()
Method to coerce (convert) an LPJmLMetaData
object into an LPJmL
+binary file header. More information about file headers at
+create_header()
).
...
See as_header()
.
.__update_subset__()
!Internal method only to be used for package development!
LPJmLMetaData$.__update_subset__(
+ subset,
+ cell_dimnames = NULL,
+ time_dimnames = NULL,
+ year_dimnames = NULL
+)
subset
List of subset arguments, see also subset.LPJmLData()
.
cell_dimnames
Optional list of new cell_dimnames of subset data +to update meta data. Required if spatial dimensions are subsetted.
time_dimnames
Optional list of new time_dimnames of subset data +to update meta data. Required if time dimension is subsetted.
year_dimnames
Optional list of new year_dimnames of subset data +to update meta data. Required if year dimension is subsetted.
.__transform_time_format__()
!Internal method only to be used for package development!
+ + + +.__transform_space_format__()
!Internal method only to be used for package development!
+ + + +new()
Create a new LPJmLMetaData object.
LPJmLMetaData$new(x, additional_attributes = list(), data_dir = NULL)
x
A list (not nested) with meta data.
additional_attributes
A list of additional attributes to be set
+that are not included in file header or JSON meta file. These are
+c"(band_names", "variable", "descr", "unit")
data_dir
Directory containing the file this LPJmLMetaData object +refers to. Used to "lazy load" grid.
Function to add a grid to an LPJmLData
object. The function acts
+as a read_io()
wrapper for the grid file and adds it as an
+LPJmLData
object itself to the $grid
attribute of the main object.
add_grid(x, ...)
LPJmLData object.
Arguments passed to read_io()
. Without any arguments,
+add_grid()
will search for a file name starting with "grid" in the same
+directory that x
was loaded from. This supports grid files in "meta"
+and "clm"
format. If the grid file is in "raw"
format or should be
+loaded from a different directory, supply all necessary read_io()
+parameters.
A copy of x
(LPJmLData
object) with added $grid
attribute.
Important:
if (FALSE) {
+
+# Read in vegetation carbon data with meta file
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Add grid as attribute (via grid file in output directory)
+vegc_with_grid <- add_grid(vegc)
+}
+
+
Function to coerce (convert) an LPJmLData
object into a pure
+array. Pure - because LPJmLData stores the data already as
+an array
which can be accessed via $data
.
+as_array
provides additional functionality to subset or aggregate the
+array
.
as_array(x, subset = NULL, aggregate = NULL, ...)
LPJmLData object.
List of array dimension(s) as name/key and
+corresponding subset vector as value, e.g.
+list(cell = c(27411:27415)
. More information at
+subset.LPJmLData()
.
List of array dimension(s) as name/key and
+corresponding aggregation function as value, e.g.
+list(band = sum)
.
Arguments passed to the aggregate function(s), e.g.
+na.rm = TRUE
.
an array with dimensions of object $data
with
+applied subset
and aggregate
functionality as well as dim
and
+dimnames
from the LPJmLData
object.
if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Returns array attribute of LPJmLData object directly
+vegc$data
+# time
+# cell 1901-12-31 1902-12-31 1903-12-31 1904-12-31 1905-12-31
+# 0 1.362730e+04 1.363163e+04 1.364153e+04 1.365467e+04 1.366689e+04
+# 1 1.201350e+02 1.158988e+02 1.101675e+02 1.214204e+02 1.062658e+02
+# 2 1.334261e+02 1.210387e+02 1.218128e+02 1.183210e+02 1.159934e+02
+# 3 9.744530e+01 9.586801e+01 8.365642e+01 8.193731e+01 7.757602e+01
+# 4 7.592700e+01 7.821202e+01 6.798551e+01 6.632317e+01 5.691082e+01
+# 5 1.106748e+01 1.137272e+01 1.196524e+01 1.131316e+01 9.924266e+0
+
+# Returns two-dimensional array with timeseries for the mean across cells
+# 27410:27415
+as_array(vegc,
+ subset = list(cell = 27410:27415),
+ aggregate = list(cell = mean))
+
+# band
+# time 1
+# 1901-12-31 1995.959
+# 1902-12-31 1979.585
+# 1903-12-31 1978.054
+# 1904-12-31 1935.623
+# 1905-12-31 1938.805
+
+}
+
+
Function to coerce (convert) an LPJmLMetaData
object into an
+LPJmL header object. More information at create_header()
.
as_header(x, silent = FALSE)
An LPJmLMetaData object
Logical. Whether to suppress notifications from header +conversion/initialization.
An LPJmL header object. More information at create_header()
.
if (FALSE) {
+
+vegc_meta <- read_meta(filename = "./vegc.bin.json")
+
+# Returns a list object with the structure of an LPJmL header
+as_header(vegc_meta)
+# $name
+# [1] "LPJDUMMY"
+#
+# $header
+# version order firstyear nyear firstcell
+# 4.0 4.0 1901.0 200.0 0.0
+# ncell nbands cellsize_lon scalar cellsize_lat
+# 67420.0 1.0 0.5 1.0 0.5
+# datatype nstep timestep
+# 3.0 1.0 1.0
+#
+# $endian
+# [1] "little"
+
+}
+
+
Function to coerce (convert) an LPJmLMetaData
object into a
+list.
as_list(x)
An LPJmLMetaData object
A list
+ + +if (FALSE) {
+
+vegc_meta <- read_meta(filename = "./vegc.bin.json")
+
+# Returns one dimensional array with timeseries for cells `27410:27415`
+as_list(vegc_meta)
+# $sim_name
+# [1] "lu_cf"
+#
+# $source
+# [1] "LPJmL C Version 5.3.001"
+#
+# $variable
+# [1] "vegc"
+#
+# $descr
+# [1] "vegetation carbon"
+#
+# $unit
+# [1] "gC/m2"
+#
+# $nbands
+# [1] 1
+#
+# ...
+
+}
+
+
Function to coerce (convert) an LPJmLData
object into a
+raster or brick object that allows for any
+GIS-based raster operations.
+Read more about the raster package at
+https://rspatial.github.io/raster/reference/raster-package.html.
+The successor package of raster is called terra: https://rspatial.org/.
as_raster(x, subset = NULL, aggregate = NULL, ...)
LPJmLData object
List of array dimension(s) as name/key and
+corresponding subset vector as value, e.g.list(cell = c(27411:27415))
.
+More information at subset.LPJmLData()
.
List of array dimension(s) as name/key and
+corresponding aggregation function as value, e.g. list(band = sum)
.
Arguments passed to the aggregate function(s), e.g.
+na.rm = TRUE
.
A raster or brick object with spatial extent
+and coordinates based on internal $grid
attribute and containing a lon/lat
+representation of x$data
. If multiple bands or time steps exist, a
+brick is created. Further meta information such as the
+lon/lat resolution are extracted from $meta
.
The $grid
attribute is required for spatial transformation. When
+using file_type = "meta"
, grid data are usually read automatically via
+add_grid()
if the grid file is present in the same directory. Otherwise,
+add_grid()
has to be called explicitly with the path to a matching grid
+file. Supports either multiple bands or multiple time steps. Use subset
or
+aggregate
to reduce data with multiple bands and time steps.
if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Returns a RasterBrick for all data
+as_raster(vegc)
+# class : RasterBrick
+# dimensions : 280, 720, 201600, 200 (nrow, ncol, ncell, nlayers)
+# resolution : 0.5, 0.5 (x, y)
+# extent : -180, 180, -56, 84 (xmin, xmax, ymin, ymax)
+# crs : +proj=longlat +datum=WGS84 +no_defs
+# source : memory
+# names : X1901.12.31, X1902.12.31, X1903.12.31, X1904.12.31, ...
+# min values : 0, 0, 0, 0, ...
+# max values : 28680.72, 28662.49, 28640.29, 28634.03, ...
+
+}
+
+
Function to coerce (convert) an LPJmLData
object into a
+rast object that allows GIS-based raster
+operations. Read more about the terra package at https://rspatial.org/.
as_terra(x, subset = NULL, aggregate = NULL, ...)
LPJmLData object.
List of array dimension(s) as name/key and
+corresponding subset vector as value, e.g. list(cell = c(27411:27415)
.
+More information at subset.LPJmLData()
.
List of array dimension(s) as name/key and
+corresponding aggregation function as value, e.g. list(band = sum)
.
Arguments passed to the aggregate function(s), e.g.
+na.rm = TRUE
.
A rast object with spatial extent and coordinates based
+on internal $grid
attribute and containing a lon/lat representation of
+x$data
. Further meta information such as the lon/lat resolution is
+extracted from $meta
.
The $grid
attribute is required for spatial transformation. When
+using file_type = "meta"
, grid data are usually read automatically via
+add_grid()
if the grid file is present in the same directory. Otherwise,
+add_grid()
has to be called explicitly with the path to a matching grid
+file. Supports either multiple bands or multiple time steps. Use subset
or
+aggregate
to reduce data with multiple bands and time steps.
if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Returns a SpatRaster for all data
+as_terra(vegc)
+# ...
+}
+
+
Function to coerce (convert) an LPJmLData
object into a
+tibble (modern data.frame). Read more about
+tibbles at https://r4ds.had.co.nz/tibbles.html.
+Please make sure to call lpjmlkit::as_tibble()
explicitly when also using
+the tidyverse packages tibble or dplyr.
# S3 method for LPJmLData
+as_tibble(x, subset = NULL, aggregate = NULL, value_name = "value", ...)
LPJmLData object
List of array dimension(s) as name/key and
+corresponding subset vector as value, e.g.
+list(cell = c(27411:27415))
. More information at
+subset.LPJmLData()
.
List of array dimension(s) as name/key and
+corresponding aggregation function as value, e.g.
+list(band = sum)
.
Name of value column in returned tibble
. Defaults to
+"value"
.
Arguments passed to the aggregate function(s), e.g.
+na.rm = TRUE
.
a tibble with columns corresponding to dimension
+naming of the LPJmLData$data
array and values in one value column.
if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Returns two-dimensional tibble representation of vegc$data.
+as_tibble(vegc)
+# cell time band value
+# <fct> <fct> <fct> <dbl>
+# 1 0 1901-12-31 1 13627.
+# 2 1 1901-12-31 1 120.
+# 3 2 1901-12-31 1 133.
+# 4 3 1901-12-31 1 97.4
+# 5 4 1901-12-31 1 75.9
+# 6 5 1901-12-31 1 11.1
+
+}
+
+
Subset an array with the supplied dimnames and - if defined - replace values.
+asub(x, ..., drop = TRUE)
An array with named dimensions.
One or several vectors of indices or character strings to be used
+to subset x
. Argument names refer to the dimension name to be subset,
+while argument values specify the selected elements along the respective
+dimension. Examples: cell = c(27411:27416)
, band = -c(14:16, 19:32)
,
+band = c("rainfed rice","rainfed maize")
.
Logical. If TRUE
(default), dimensions with a length of 1 are
+dropped from the result. Otherwise, they are kept.
array (or vector if drop = TRUE
and only one dimension is left)
+of the selected subset of x
.
my_array <- array(1,
+ dim = c(cell = 67, month = 12, band = 3),
+ dimnames = list(cell = 0:66,
+ month = 1:12,
+ band = c("band1", "band2", "band3")))
+my_subset <- asub(my_array,
+ band = c("band1", "band3"))
+dimnames(my_subset)[3]
+#> $band
+#> [1] "band1" "band3"
+#>
+# $ band
+# [1] "band1"
+# [2] "band3"
+
+
Calculate the cell area of LPJmL cells based on an LPJmLData
+object or latitude coordinates and grid resolution.
+Uses a spherical representation of the Earth.
calc_cellarea(
+ x,
+ cellsize_lon = 0.5,
+ cellsize_lat = cellsize_lon,
+ earth_radius = 6371000.785,
+ return_unit = "m2"
+)
LPJmLData
object with $grid
attribute, an LPJmLData object of
+variable "grid"
("LPJGRID"
) or a vector of cell-center latitude
+coordinates in degrees.
Grid resolution in longitude direction in degrees
+(default: 0.5
). If x
is an LPJmLData object the resolution will be
+taken from the meta data included in x
if available.
Grid resolution in latitude direction in degrees (default:
+same as cellsize_lon
). If x
is an LPJmLData object the resolution will be
+taken from the meta data included in x
if available.
Radius of the sphere (in \(m\)) used to calculate the +cell areas.
Character string describing the area unit of the returned
+cell areas. Defaults to "m2"
, further options: "ha"
or "km2"
.
A vector or array matching the space dimension(s) of x
if x
is an
+LPJmLData object. A vector of the same length as x
if x
is a vector of
+latitude coordinates. Cell areas are returned in the unit return_unit
.
Check if created LPJmL config JSON files (write_config()
) are
+valid and are ready to be used for simulations using lpjcheck for multiple
+files.
check_config(
+ x,
+ model_path = ".",
+ sim_path = NULL,
+ return_output = FALSE,
+ raise_error = FALSE,
+ output_path = NULL
+)
job_details
object returned by write_config()
or
+character vector providing the config file names
+(hint: returns x
as a list entry).
Character string providing the path to LPJmL
+(equal to LPJROOT
environment variable). Defaults to ".".
Character string defining path where all simulation data are
+written, including output, restart and configuration files. If NULL
,
+model_path
is used. See also write_config
Parameter affecting the output. If FALSE
print
+stdout/stderr message. If TRUE
, return the result of the check.
+Defaults to FALSE
.
Logical. Whether to raise an error if sub-process has
+non-zero exit status. Defaults to FALSE
.
Argument is deprecated as of version 1.0; use sim_path +instead.
NULL.
+if (FALSE) {
+library(tibble)
+library(lpjmlkit)
+
+model_path <- "./LPJmL_internal"
+sim_path <-"./my_runs"
+
+
+# Basic usage
+my_params <- tibble(
+ sim_name = c("scen1", "scen2"),
+ random_seed = c(12, 404),
+ `pftpar[[1]]$name` = c("first_tree", NA),
+ `param$k_temp` = c(NA, 0.03),
+ new_phenology = c(TRUE, FALSE)
+)
+
+config_details <- write_config(
+ x = my_params,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+check_config(x = config_details,
+ model_path = model_path,
+ sim_path = sim_path,
+ return_output = FALSE
+)
+}
+
Create a header from scratch in the format required by
+write_header()
.
create_header(
+ name = "LPJGRID",
+ version = 3,
+ order = 1,
+ firstyear = 1901,
+ nyear = 1,
+ firstcell = 0,
+ ncell,
+ nbands = 2,
+ cellsize_lon = 0.5,
+ scalar = 1,
+ cellsize_lat = cellsize_lon,
+ datatype = 3,
+ nstep = 1,
+ timestep = 1,
+ endian = .Platform$endian,
+ verbose = TRUE
+)
Header name attribute (default: `"LPJGRID").
CLM version to use (default: 3
).
Order of data items. See details below or LPJmL code for
+supported values. The order may be provided either as an integer value or
+as a character string (default: 1
).
Start year of data in file (default: 1901
).
Number of years of data included in file (default: 1
).
Index of first data item (default: 0
).
Number of data items per band.
Number of bands per year of data (default: 2
).
Longitude cellsize in degrees (default: 0.5
).
Conversion factor applied to data when it is read by LPJmL or
+by read_io()
(default: 1.0
).
Latitude cellsize in degrees (default: same as
+cellsize_lon
).
LPJmL data type in file. See details below or LPJmL code for
+valid data type codes (default: 3
).
Number of time steps per year. Added in header version 4 to
+separate time bands from content bands (default: 1
).
If larger than 1, outputs are averaged over timestep
years
+and only written once every timestep
years (default: 1
).
Endianness to use for file (either "big"
or "little"
, by
+default uses platform-specific endianness .Platform$endian
).
If TRUE
(the default), function provides some feedback on
+datatype and when using default values for missing parameters. If FALSE
,
+only errors are reported.
The function returns a list with 3 components:
name: The header name, e.g. "LPJGRID".
header: Vector of header values ('version', 'order', 'firstyear', +'nyear', 'firstcell', 'ncell', 'nbands', 'cellsize_lon', 'scalar', +'cellsize_lat', 'datatype', 'nstep', 'timestep').
endian: Endian used to write binary data, either "little" or "big".
File headers in input files are used by LPJmL to determine the +structure of the file and how to read it. They can also be used to describe +the structure of output files.
+Header names usually start with "LPJ" followed by a word or abbreviation +describing the type of input/output data. See LPJmL code for valid header +names.
+The version number determines the amount of header information included in +the file. All versions save the header name and header attributes 'version', +'order', 'firstyear', 'nyear', 'firstcell', 'ncell', and 'nbands'. Header +versions 2, 3 and 4 add header attributes 'cellsize_lon' and 'scalar'. Header +versions 3 and 4 add header attributes 'cellsize_lat' and 'datatype'. Header +version 4 adds attributes 'nstep' and 'timestep'.
+Valid values for order
are 1
/ "cellyear"
, 2
/ "yearcell"
, 3
/
+"cellindex"
, and 4
/ "cellseq"
. The default for LPJmL input files is
+1
. The default for LPJmL output files is 4
, except for grid output
+files which also use 1
.
By default, input files contain data for all cells, indicated by setting
+the firstcell
index to 0
. If firstcell > 0
, LPJmL assumes the first
+firstcell
cells to be missing in the data.
Valid codes for the datatype
attribute and the corresponding LPJmL data
+types are: 0
/ "byte"
(LPJ_BYTE), 1
/ "short"
(LPJ_SHORT), 2
/
+"int"
(LPJ_INT), 3
/ "float"
(LPJ_FLOAT), 4
/ "double"
+(LPJ_DOUBLE).
The default parameters of the function are valid for grid input files using +LPJ_FLOAT data type.
+read_header()
for reading headers from LPJmL input/output files.
write_header()
for writing headers to files.
header <- create_header(
+ name = "LPJGRID",
+ version = 3,
+ order = 1,
+ firstyear = 1901,
+ nyear = 1,
+ firstcell = 0,
+ ncell = 67420,
+ nbands = 2,
+ cellsize_lon = 0.5,
+ scalar = 1.0,
+ cellsize_lat = 0.5,
+ datatype = 3,
+ nstep = 1,
+ timestep = 1,
+ endian = .Platform$endian,
+ verbose = TRUE
+)
+#> Setting datatype to double with size 4.
+
+
R/detect_io_type.R
+ detect_io_type.Rd
This utility function tries to detect automatically if a
+provided file is of "clm"
, "meta"
, or "raw"
file type. NetCDFs and
+simple text formats such as ".txt" or ".csv" are also detected.
detect_io_type(filename)
Character string naming the file to check.
Character vector of length 1 giving the file type:
"cdf" for a NetCDF file (classic or NetCDF4/HDF5 format).
"clm" for a binary LPJmL input/output file with header.
"meta" for a JSON meta file describing a binary LPJmL input/output file.
"raw" for a binary LPJmL input/output file without header. This is also the +default if no other file type can be recognized.
"text" for any type of text-only file, e.g. ".txt" or ".csv"
if (FALSE) {
+detect_io_type(filename = "filename.clm")
+# [1] "clm"
+}
+
+
Function to get the dimnames (list) of the data array of an LPJmLData object.
+# S3 method for LPJmLData
+dimnames(x)
LPJmLData object
A list of the same length as dim(x). Components are character vectors +with positive length of the respective dimension of x.
+Function to search for a file containing a specific variable in a specific +directory.
+find_varfile(searchdir, variable = "grid", strict = FALSE)
Directory where to look for the variable file.
Single character string containing the variable to search for
Boolean. If set to TRUE
, file must be named "variable.",
+where "" is one or two file extensions with 3 or 4 characters, e.g.
+"grid.bin.json" if variable = "grid"
. If set to FALSE
, the function
+will first try to match the strict pattern. If unsuccessful, any filename
+that starts with "variable" will be matched.
Character string with the file name of a matched file, including the +full path.
+This function looks for file names in searchdir
that match the
+pattern
parameter in its list.files()
call. Files of type "meta" are
+preferred. Files of type "clm" are also accepted. The function returns an
+error if no suitable file or multiple files are found.
This function returns the cell index from a grid file based on +the provided extent or coordinates. If neither extent nor coordinates are +provided, the full grid will be returned. If both extent and coordinates are +provided, the function will stop and ask for only one of them. The extent +should be a vector of length 4 in the form c(lonmin, lonmax, latmin, latmax). +If the extent is not in the correct form, the function will swap the values +to correct it.
+get_cellindex(grid_filename, extent = NULL, coordinates = NULL)
A string representing the grid file name.
A numeric vector (lonmin, lonmax, latmin, latmax) containing the +longitude and latitude boundaries between which values included in the subset.
A list of two named (lon, lat) numeric vectors representing the coordinates.
The cell index from the grid file based on the provided extent or +coordinates.
+The function reads a grid file specified by grid_filename
and creates a
+data frame with columns for longitude, latitude, and cell number. The cell
+number is a sequence from 1 to the number of rows in the data frame.
If an extent
is provided, the function filters the cells to include only
+those within the specified longitude and latitude range. The extent
should
+be a numeric vector of length 4 in the form c(lonmin, lonmax, latmin, latmax).
If a list of coordinates
is provided, the function filters the cells to
+include only those that match the specified coordinates. The coordinates
+should be a list of two character vectors representing the longitude and
+latitude values as for subset()
.
If both extent
and coordinates
are provided, the function will stop and
+ask for only one of them. If neither extent
nor coordinates
are provided,
+the function will return the cell numbers for all cells in the grid.
The function also includes checks for input types and values, and gives
+specific error messages for different error conditions. For example, it
+checks if the grid_filename
exists, if the extent
vector has the correct
+length, and if the coordinates
list contains two vectors of equal length.
Provides information on the data type used in an LPJmL +input/output file based on the 'datatype' attribute included in the file +header.
+get_datatype(header, fail = TRUE)
Header list object as returned by read_header()
or
+create_header()
. Alternatively, can be a single integer just giving the
+data type code or a single character string giving one of the LPJmL type
+names c("byte", "short", "int", "float", "double")
.
Determines whether the function should fail if the datatype is
+invalid (default: TRUE
).
On success, the function returns a list object with three components:
type: R data type; can be used with what
parameter of readBin()
.
size: size of data type; can be used with size
parameter of
+readBin()
.
signed: whether or not the data type is signed; can be used with signed
+parameter of readBin()
.
If fail = FALSE
, the function returns NULL
if an invalid datatype is
+provided.
read_header()
for reading headers from LPJmL input/output files.
create_header()
for creating headers from scratch.
get_headersize()
for determining the size of file headers.
if (FALSE) {
+# Read file header
+header <- read_header("filename.clm")
+# Open file for reading
+fp <- file("filename.clm", "rb")
+# Skip over file header
+seek(fp, get_headersize(header))
+# Read in file data
+file_data <- readBin(
+ fp,
+ what = get_datatype(header)$type,
+ size = get_datatype(header)$size,
+ signed = get_datatype(header)$signed,
+ n = header$header["ncell"] * header$header["nbands"] *
+ header$header["nyear"] * header$header["nstep"],
+ endian = header[["endian"]]
+)
+# Close file
+close(fp)
+}
+
+
R/get_header_item.R
+ get_header_item.Rd
Convenience function to extract information from a header object
+as returned by read_header()
or create_header()
. Returns one item
+per call.
get_header_item(header, item)
LPJmL file header as returned by read_header()
or
+create_header()
.
Header information item to retrieve. One of c("name", "version", "order", "firstyear", "nyear", "firstcell", "ncell", "nbands", "cellsize_lon", "scalar", "cellsize_lat", "datatype", "nstep", "timestep", "endian")
.
Requested header item. Character string in case of "name" and +"endian", otherwise numeric value.
+create_header()
for creating headers from scratch and for a more
+detailed description of the LPJmL header format.
read_header()
for reading headers from LPJmL input/output files.
if (FALSE) {
+# Read file header
+header <- read_header("filename.clm")
+nyear <- get_header_item(header = header, item = "nyear")
+}
+
R/get_headersize.R
+ get_headersize.Rd
Returns the size in bytes of an LPJmL file header based on a
+header list object read by read_header()
or generated by
+create_header()
.
get_headersize(header)
Header list object as returned by read_header()
or
+create_header()
.
Integer value giving the size of the header in bytes. This can be +used when seeking in the file or to calculate the expected total file size +in combination with the number of included data values and the data type.
+read_header()
for reading a header from an LPJmL input/output file.
create_header()
for creating a header from scratch.
if (FALSE) {
+header <- read_header("filename.clm")
+size <- get_headersize(header)
+# Open file for reading
+fp <- file("filename.clm", "rb")
+# Skip over file header
+seek(fp, size)
+# Add code to read data from file
+}
+
+ All functions+ + |
+ |
---|---|
+ + | +Add grid to an LPJmLData object |
+
+ + | +Subset a named array |
+
+ + | +Coerce an LPJmLData object to an array |
+
+ + | +Coerce LPJmLMetaData to an LPJmL header object |
+
+ + | +Coerce LPJmLMetaData to a list |
+
+ + | +Coerce an LPJmLData object to a raster object |
+
+ + | +Coerce an LPJmLData object to a terra object |
+
+ + | +Coerce an LPJmLData object to a tibble |
+
+ + | +Calculate the cell area of LPJmL cells |
+
+ + | +Check the validity of LPJmL config JSON files |
+
+ + | +Create a new LPJmL input/output file header |
+
+ + | +Detect the file type of an LPJmL input/output file |
+
+ + | +Dimensions of an LPJmLData data array |
+
+ + | +Dimnames of an LPJmLData data array |
+
+ + | +Search for a variable file in a directory |
+
+ + | +Get Cell Index |
+
+ + | +Data type of an LPJmL input/output file |
+
+ + | +Determine the size of an LPJmL input/output file header |
+
+ + | +Retrieve information from an LPJmL input/output file header |
+
+ + | +Length of an LPJmLData data array |
+
+ + | +LPJmL data class |
+
+ + | +LPJmL grid data class |
+
+ + | +lpjmlkit: Toolkit for Basic LPJmL Handling |
+
+ + | +LPJmL meta data class |
+
+ + | +Compile LPJmL model |
+
+ + | +Plot an LPJmLData object |
+
+ + | +Read an LPJmL configuration file |
+
+ + | +Read LPJmL input and output grid files |
+
+ + | +Read header (any version) from LPJmL input/output file |
+
+ + | +Read LPJmL input and output files |
+
+ + | +Read an LPJmL meta file or binary file header |
+
+ + | +Run LPJmL model |
+
+ + | +Set information in an LPJmL input (or output) file header |
+
+ + | +Submit LPJmL model simulation to SLURM |
+
+ + | +Subset an LPJmLData object |
+
+ + | +LPJmLData object summary |
+
+ + | +Transform an LPJmLData object |
+
+ + | +Write LPJmL config files (JSON) |
+
+ + | +Write LPJmL header object to an LPJmL input (or output) file |
+
A collection of basic functions to facilitate the work with the Dynamic Global Vegetation Model (DGVM) Lund-Potsdam-Jena managed Land (LPJmL) hosted at the Potsdam Institute for Climate Impact Research (PIK). It provides functions for performing LPJmL simulations, as well as reading, processing and writing model-related data such as inputs and outputs or configuration files.
+Useful links:
Compiles the LPJmL source code and creates an executable by executing +"make all" on the operating system shell.
+make_lpjml(
+ model_path = ".",
+ parallel_cores = NULL,
+ make_clean = FALSE,
+ raise_error = TRUE,
+ debug = NULL
+)
Character string providing the path to LPJmL
+(equal to LPJROOT
environment variable). Defaults sto ".".
Numeric defining the number of available CPU cores for +parallelization.
Logical. If set to TRUE
, calls "make clean" first to
+remove previous installation. Defaults to FALSE
.
Logical. Whether to raise an error if sub-process has
+non-zero exit status, hence if compilation fails. Defaults to TRUE
.
NULL or Logical. Whether to compile LPJmL with "-debug" flag.
+Defaults to NULL
. If set to FALSE
or TRUE
, make_clean
is set
+automatically and compilation configuration is reset with/without "-debug".
+Also the "configure.sh" file is rewritten.
A list with process status, see run.
+if (FALSE) {
+model_path <- "./LPJmL_internal"
+make_lpjml(model_path = model_path)
+}
+
+
Function to plot a time-series or raster map of an LPJmLData
+object.
# S3 method for LPJmLData
+plot(x, subset = NULL, aggregate = NULL, raster_extent = NULL, ...)
LPJmLData object
List of array dimension(s) as name/key and
+corresponding subset vector as value, e.g. list(cell = c(27411:27416))
.
+More information at subset.LPJmLData()
.
List of array dimension(s) as name/key and
+corresponding aggregation function as value, e.g. list(band = sum)
.
Optional parameter to crop map display of spatial data.
+An extent or any object from which an Extent object can be
+extracted. Not relevant if aggregate
includes spatial dimension.
No return value; called for side effects.
+Depending on the dimensions of the LPJmLData object's internal data array +the plot will be a ...
single map plot: more than 8 "cell"
s or "lat"
& "lon"
dimensions
+available)
multiple maps plot: length of one time (e.g."time"
, "year"
,
+"month"
) or "band"
dimension > 1.
time series plot: less than 9 "cell"
s
lat/lon plot: a subsetted/aggregated "lat"
or "lon"
dimension
The plot can only handle 2-3 dimensions. Use arguments subset
and
+aggregate
to modify x$data
to the desired plot type. If more than three
+dimensions have length > 1,' plot will return an error and suggest to reduce
+the number of dimensions.
Note that the plot function aims to provide a quick overview of the data +rather than create publication-ready graphs.
+if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Plot first 9 years starting from 1901 as a raster plot
+plot(vegc)
+
+# Plot raster with mean over the whole time series
+plot(vegc,
+ aggregate = list(time = mean))
+
+# Plot only year 2010 as a raster
+plot(vegc,
+ subset = list(time = "2010"))
+
+# Plot first 10 time steps as global mean time series. Note: Aggregation
+# across cells is not area-weighted.
+plot(vegc,
+ subset = list(time = 1:10),
+ aggregate = list(cell = mean))
+
+# Plot time series for cells with LPJmL index 27410 - 27415 (C indices start
+# at 0 in contrast to R indices starting at 1).
+plot(vegc,
+ subset = list(cell = 27411:27416))
+
+}
+
+
Reads a configuration (config) file (compilable csjon/js file or json file) +and turns it into a nested list object.
+read_config(filename, from_restart = FALSE, macro = "")
Character string representing path +(if different from current working directory) and filename.
Logical defining whether config files should be read as
+from_restart (transient run) or without (spinup run). Defaults to FALSE
+(spinup run). Used only if file is not pre-compiled (no json).
Optional character string to pass one or several macros to the +pre-compiler, e.g. ("-DFROM_RESTART"). Used only if file is not +pre-compiled (no json).
A nested list object representing the LPJmL configuration read from
+filename
.
if (FALSE) {
+ config <- read_config(filename = "config_spinup.json")
+
+ config[["version"]]
+ # [1] "5.3"
+
+ config[["pftpar"]][[1]][["name"]]
+ # [1] "tropical broadleaved evergreen tree"
+
+ config[["input"]][["coord"]][["name"]]
+ # [1] "input_VERSION2/grid.bin"
+
+ # visualize configuration as tree view
+ View(config)
+}
+
Generic function to read LPJmL input & output files in different +formats. Depending on the format, arguments can be automatically detected +or have to be passed as individual arguments.
+read_grid(...)
See read_io for further arguments.
An LPJmLGridData object.
+See read_io for more details.
+if (FALSE) {
+my_grid <- read_io("grid.bin.json")
+
+}
+
R/read_header.R
+ read_header.Rd
Reads a header from an LPJmL clm file. CLM is the default +format used for LPJmL input files and can also be used for output files.
+read_header(filename, force_version = NULL, verbose = TRUE)
Filename to read header from.
Manually set clm version. The default value NULL
means
+that the version is determined automatically from the header. Set only if
+the version number in the file header is incorrect.
If TRUE
(the default), read_header
provides some feedback
+when using default values for missing parameters. If FALSE
, only errors
+are reported.
The function returns a list with 3 components:
name: Header name, e.g. "LPJGRID"; describes the type of data in the file.
header: Vector of header values ('version', 'order', 'firstyear', +'nyear', 'firstcell', 'ncell', 'nbands', 'cellsize_lon', 'scalar', +'cellsize_lat', 'datatype', 'nstep', 'timestep') describing the file +structure. If header version is <4, the header is partially filled with +default values.
endian: Endianness of file ("little"
or "big"
).
create_header()
for a more detailed description of the LPJmL header
+format.
write_header()
for writing headers to files.
if (FALSE) {
+header <- read_header("filename.clm")
+}
+
+
Generic function to read LPJmL input & output files in different +formats. Depending on the format, arguments can be automatically detected +or have to be passed as individual arguments.
+read_io(
+ filename,
+ subset = list(),
+ band_names = NULL,
+ dim_order = c("cell", "time", "band"),
+ file_type = NULL,
+ version = NULL,
+ order = NULL,
+ firstyear = NULL,
+ nyear = NULL,
+ firstcell = NULL,
+ ncell = NULL,
+ nbands = NULL,
+ cellsize_lon = NULL,
+ scalar = NULL,
+ cellsize_lat = NULL,
+ datatype = NULL,
+ nstep = NULL,
+ timestep = NULL,
+ endian = NULL,
+ variable = NULL,
+ descr = NULL,
+ unit = NULL,
+ name = NULL,
+ silent = FALSE
+)
Mandatory character string giving the file name to read, +including its path and extension.
Optional list allowing to subset data read from the file along +one or several of its dimensions. See details for more information.
Optional vector of character strings providing the band
+names or NULL
. Normally determined automatically from the meta file in
+case of output files using file_type = "meta"
.
Order of dimensions in returned LPJmLData object. Must be
+a character vector containing all of the following in any order:
+c("cell", "time", "band")
. Users may select the order most useful to
+their further data processing.
Optional character string giving the file type. This is +normally detected automatically but can be prescribed if automatic +detection is incorrect. Valid options:
"raw"
, a binary file without header.
"clm"
, a binary file with header.
"meta"
, a meta information JSON file complementing a raw or clm file.
Integer indicating the clm file header version, currently
+supports one of c(1, 2, 3, 4)
.
Integer value or character string describing the order of data
+items in the file (default in input file: 1; in output file: 4). Valid
+values for LPJmL input/output files are "cellyear"
/ 1
, "yearcell"
/
+2
, "cellindex"
/ 3
, and "cellseq"
/ 4
, although only options 1
+and 4
are supported by this function.
Integer providing the first year of data in the file.
Integer providing the number of years of data included in the
+file. These are not consecutive in case of timestep > 1
.
Integer providing the cell index of the first data item.
+0
by default.
Integer providing the number of data items per band.
Integer providing the number of bands per time step of data.
Numeric value providing the longitude cell size in +degrees.
Numeric value providing a conversion factor that needs to be +applied to raw data when reading it from file to derive final values.
Numeric value providing the latitude cell size in +degrees.
Integer value or character string describing the LPJmL data
+type stored in the file. Supported options: "byte"
/ 0
, "short"
/
+1
, "int"
/ 2
, "float"
/ 3
, or "double"
/ 4
.
Integer value defining the number of within-year time steps of
+the file. Valid values are 1
(yearly), 12
(monthly), 365
(daily).
+Defaults to 1
if not read from file ("clm" or "meta" file) or provided by
+the user.
Integer value providing the interval in years between years
+represented in the file data. Normally 1
, but LPJmL also allows averaging
+annual outputs over several years. Defaults to 1
if not read from file
+("clm" or "meta" file) or provided by user.
Endianness to use for file (either "big"
or "little"
). By
+default uses endianness determined from file header or set in meta
+information or the platform-specific endianness .Platform$endian
if not
+set.
Optional character string providing the name of the variable
+contained in the file. Included in some JSON meta files. Important: If
+file_type == "raw"
, prescribe variable = "grid"
to ensure that data
+are recognized as a grid.
Optional character string providing a more detailed description +of the variable contained in the file. Included in some JSON meta files.
Optional character string providing the unit of the data in the +file. Included in some JSON meta files.
Optional character string specifying the header name. This is
+usually read from clm headers for file_type = "clm"
but can be specified
+for the other file_type
options.
If set to TRUE
, suppresses most warnings or messages. Use
+only after testing that read_io()
works as expected with the files it is
+being used on. Default: FALSE
.
An LPJmLData object.
+The file_type
determines which arguments are mandatory or optional.
+filename
must always be provided. file_type
is usually detected
+automatically. Supply only if detected file_type
is incorrect.
In case of file_type = "meta"
, if any of the function arguments not listed
+as "mandatory" are provided and are already set in the JSON file, a warning
+is given, but they are still overwritten. Normally, you would only set meta
+attributes not set in the JSON file.
In case of file_type = "clm"
, function arguments not listed as "optional"
+are usually determined automatically from the file header included in the
+clm file. Users may still provide any of these arguments to overwrite values
+read from the file header, e.g. when they know that the values in the file
+header are wrong. Also, clm headers with versions < 4 do not contain all
+header attributes, with missing attributes filled with default values that
+may not be correct for all files.
In case of file_type = "raw"
, files do not contain any information about
+their structure. Users should provide all arguments not listed as "optional".
+Otherwise, default values valid for LPJmL standard outputs are used for
+arguments not supplied by the user. For example, the default firstyear
is
+1901, the default for nyear
, nbands
, nstep
, and timestep
is 1.
subset
can be a list containing one or several named elements. Allowed
+names are "band", "cell", and "year".
"year" can be used to return data for a subset of one or several years
+included in the file. Integer indices can be between 1 and nyear
. If
+subsetting by actual calendar years (starting at firstyear
) a
+character vector has to be supplied.
"band" can be used to return data for a subset of one or several bands +included in the file. These can be specified either as integer indices or as +a character vector if bands are named.
"cell" can be used to return data for a subset of cells. Note that integer
+indices start counting at 1, whereas character indices start counting at the
+value of firstcell
(usually 0
).
if (FALSE) {
+# First case: meta file. Reads meta information from "my_file.json" and
+# data from binary file linked in "my_file.json". Normally does not require
+# any additional arguments.
+my_data <- read_io("my_file.json")
+
+# Suppose that file data has two bands named "wheat" and "rice". `band_names`
+# are included in the JSON meta file. Select only the "wheat" band during
+# reading and discard the "rice" band. Also, read only data for years
+# 1910-1920.
+my_data_wheat <- read_io(
+ "my_file.json",
+ subset = list(band = "wheat", year = as.character(seq(1910, 1920)))
+)
+
+# Read data from clm file. This includes a header describing the file
+# structure.
+my_data_clm <- read_io("my_file.clm")
+
+# Suppose that "my_file.clm" has two bands containing data for "wheat" and
+# "rice". Assign names to them manually since the header does not include a
+# `band_names` attribute.
+my_data_clm <- read_io("my_file.clm", band_names = c("wheat", "rice"))
+
+# Once `band_names` are set, subsetting by name is possible also for
+# file_type = "clm"
+my_data_wheat <- read_io(
+ "my_file.clm",
+ band_names = c("wheat", "rice"),
+ subset = list(band = "wheat", year = as.character(seq(1910, 1920)))
+)
+
+# Read data from raw binary file. All information about file structure needs
+# to be supplied. Use default values except for nyear (1 by default), and
+# nbands (also 1 by default).
+my_data <- read_io("my_file.bin", nyear = 100, nbands = 2)
+
+# Supply band_names to be able to subset by name
+my_data_wheat <- read_io(
+ "my_file.bin",
+ band_names = c("wheat", "rice"), # length needs to correspond to `nbands`
+ subset = list(band = "wheat", year = as.character(seq(1910, 1920))),
+ nyear = 100,
+ nbands = 2,
+)
+}
+
Reads a meta JSON file or the header of a binary LPJmL input or output file.
+read_meta(filename, ...)
Character string representing path +(if different from current working directory) and filename.
Additional arguments passed to read_header
if header file is
+read.
An LPJmLMetaData
object.
if (FALSE) {
+ meta <- read_meta(filename = "mpft_npp.bin.json")
+
+ meta$sim_name
+ # [1] "LPJmL Run"
+
+ meta$firstcell
+ # [1] 27410
+
+ meta$band_names[1]
+ # [1] "tropical broadleaved evergreen tree"
+}
+
+
Runs LPJmL using "config_*.json"
files written by
+write_config()
. write_config()
returns a tibble
+that can be used as an input (see x
). It contains the details to run single
+or multiple (dependent/subsequent) model runs.
run_lpjml(
+ x,
+ model_path = ".",
+ sim_path = NULL,
+ run_cmd = "srun --propagate",
+ parallel_cores = 1,
+ write_stdout = FALSE,
+ raise_error = TRUE,
+ output_path = NULL
+)
A tibble with at least one column named "sim_name"
.
+Each simulation gets a separate row. Optional run parameters are "order"
+and "dependency"
which are used for subsequent simulations (see details).
+write_config()
returns a tibble in the required format.
+OR provide a character string (vector) with the file name of one or
+multiple generated configuration file(s).
Character string providing the path to LPJmL
+(equal to LPJROOT
environment variable). Defaults to "."
Character string defining path where all simulation data are
+written, including output, restart and configuration files. If NULL
,
+model_path
is used. See also write_config
Character string defining the command used to execute lpjml +(see details). Defaults to "srun --propagate" (compute ondes of old cluster +at PIK). Change to "mpirun" for HPC2024 at PIK.
Integer defining the number of available CPU
+cores/nodes for parallelization. Defaults to 1
(no parallelization).
+Please note that parallelization is only supported for SLURM jobs and not
+for interactive runs.
Logical. If TRUE
, stdout
as well as stderr
files
+are written. If FALSE
(default), these are printed instead. Within a
+SLURM job write_stdout
is automatically set to TRUE
.
Logical. Whether to raise an error if sub-process has
+non-zero exit status. Defaults to TRUE
.
Argument is deprecated as of version 1.0; use sim_path +instead.
See x
, extended by columns "type"
, "job_id"
and "status"
.
x:
+A tibble for x
that has been generated by
+write_config()
and can look like the following examples can
+supplied:
sim_name |
scen1_spinup |
scen2_transient |
To perform subsequent or rather dependent runs the optional run parameter
+"dependency"
needs to be provided within the initial
+tibble supplied as param
to write_config()
.
sim_name | order | dependency |
scen1_spinup | 1 | NA |
scen2_transient | 2 | scen1 _spinup |
As a shortcut it is also possible to provide the config file
+"config_*.json"
as a character string or multiple config files as a
+character string vector directly as the x
argument to run_lpjml
.
+Also be aware that the order of the supplied config files is important
+(e.g. make sure the spin-up run is run before the transient one).
run_cmd:
+The run_cmd
argument is used to define the command to execute LPJmL. This
+is needed because the LPJmL executable can not directly be used on all
+machines. Which command has to be used depends on the software installed.
+Further information on this can be found in the INSTALL file of LPJmL.
+To determine the correct command, check the lpj_submit.sh file in the bin
+directory of LPJmL. Using PIK infrastrucure the command is srun
for
+the hpc2015 and mpirun
for the hpc2024. To facilitate usage on the
+interactive (login) nodes, no command is needed for hpc2015. For the hpc2024
+the command remains mpirun
(in these cases run_lpjml
adjusts
+run_cmd
accordingly).
+if (FALSE) {
+library(tibble)
+
+model_path <- "./LPJmL_internal"
+sim_path <-"./my_runs"
+
+# Basic usage
+my_params1 <- tibble(
+ sim_name = c("scen1", "scen2"),
+ startgrid = c(27410, 27410),
+ river_routing = c(FALSE, FALSE),
+ random_seed = c(42, 404),
+ `pftpar[[1]]$name` = c("first_tree", NA),
+ `param$k_temp` = c(NA, 0.03),
+ new_phenology = c(TRUE, FALSE)
+)
+
+config_details1 <- write_config(my_params1, model_path, sim_path)
+
+ run_details1 <- run_lpjml(
+ x = config_details1,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+run_details1
+# sim_name job_id status
+# <chr> <int> <chr>
+# 1 scen1 NA run
+# 2 scen2 NA run
+
+
+# With run parameters dependency and order being set (also less other
+# parameters than in previous example)
+my_params2 <- tibble(
+ sim_name = c("scen1", "scen2"),
+ startgrid = c(27410, 27410),
+ river_routing = c(FALSE, FALSE),
+ random_seed = c(42, 404),
+ dependency = c(NA, "scen1_spinup")
+)
+
+config_details2 <- write_config(my_params2, model_path, sim_path)
+
+run_details2 <- run_lpjml(config_details2, model_path, sim_path)
+
+run_details2
+# sim_name order dependency type job_id status
+# <chr> <dbl> <chr> <chr> <chr> <chr>
+# 1 scen1_spinup 1 NA simulation NA run
+# 2 scen1_transient 2 scen1_spinup simulation NA run
+
+
+# Same but by using the pipe operator
+library(magrittr)
+
+run_details2 <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = as.integer(c(1, 42)),
+ dependency = c(NA, "scen1_spinup")
+) %>%
+ write_config(model_path, sim_path) %>%
+ run_lpjml(model_path, sim_path)
+
+
+# Shortcut approaches
+run_details3 <- run_lpjml(
+ x = "./config_scen1_transient.json",
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+run_details4 <- run_lpjml(
+ c("./config_scen1_spinup.json", "./config_scen1_transient.json"),
+ model_path,
+ sim_path
+)
+
+}
+
+
R/set_header_item.R
+ set_header_item.Rd
Convenience function to set information in a header object as
+returned by read_header()
or create_header()
. One or several
set_header_item(header, ...)
An LPJmL file header as returned by read_header()
or
+create_header()
.
Named header items to set. Can be one or several of 'name',
+'version', 'order', 'firstyear', 'nyear', 'firstcell', 'ncell', 'nbands',
+'cellsize_lon', 'scalar', 'cellsize_lat', 'datatype', 'nstep', 'timestep',
+'endian'. Parameter 'verbose' can be used to control verbosity, as in
+create_header()
.
Header header
where header items supplied through the ellipsis
+have been changed.
create_header()
for creating headers from scratch and for a more
+detailed description of the LPJmL header format.
read_header()
for reading headers from files.
header <- create_header(
+ name = "LPJGRID",
+ version = 3,
+ order = 1,
+ firstyear = 1901,
+ nyear = 1,
+ firstcell = 0,
+ ncell = 67420,
+ nbands = 2,
+ cellsize_lon = 0.5,
+ scalar = 1.0,
+ cellsize_lat = 0.5,
+ datatype = 3,
+ nstep = 1,
+ timestep = 1,
+ endian = .Platform$endian,
+ verbose = TRUE
+)
+#> Setting datatype to double with size 4.
+
+header
+#> $name
+#> [1] "LPJGRID"
+#>
+#> $header
+#> version order firstyear nyear firstcell ncell
+#> 3.0 1.0 1901.0 1.0 0.0 67420.0
+#> nbands cellsize_lon scalar cellsize_lat datatype nstep
+#> 2.0 0.5 1.0 0.5 3.0 1.0
+#> timestep
+#> 1.0
+#>
+#> $endian
+#> [1] "little"
+#>
+# $name
+# [1] "LPJGRID"
+#
+# $header
+# version order firstyear nyear firstcell ncell
+# 3.0 1.0 1901.0 1.0 0.0 67420.0
+# nbands cellsize_lon scalar cellsize_lat datatype nstep
+# 2.0 0.5 1.0 0.5 3.0 1.0
+# timestep
+# 1.0
+#
+# $endian
+# [1] "little"
+
+# Change number of cells to 1
+set_header_item(header = header, ncell = 1)
+#> $name
+#> [1] "LPJGRID"
+#>
+#> $header
+#> version order firstyear nyear firstcell ncell
+#> 3.0 1.0 1901.0 1.0 0.0 1.0
+#> nbands cellsize_lon scalar cellsize_lat datatype nstep
+#> 2.0 0.5 1.0 0.5 3.0 1.0
+#> timestep
+#> 1.0
+#>
+#> $endian
+#> [1] "little"
+#>
+# $name
+# [1] "LPJGRID"
+#
+# $header
+# version order firstyear nyear firstcell ncell
+# 3.0 1.0 1901.0 1.0 0.0 1.0
+# nbands cellsize_lon scalar cellsize_lat datatype nstep
+# 2.0 0.5 1.0 0.5 3.0 1.0
+# timestep
+# 1.0
+#
+# $endian
+# [1] "little"
+
+
LPJmL simulations are submitted to SLURM using "config*.json"
files written
+by write_config()
. write_config()
returns a
+tibble that can be used as an input (see x
). It serves the details to
+submit single or multiple (dependent/subsequent) model simulations.
submit_lpjml(
+ x,
+ model_path,
+ sim_path = NULL,
+ group = "",
+ sclass = "short",
+ ntasks = 256,
+ wtime = "",
+ blocking = "",
+ constraint = "",
+ slurm_options = list(),
+ no_submit = FALSE,
+ output_path = NULL
+)
A tibble with at least one column named "sim_name"
.
+Each simulation gets a separate row. An optional run parameter
+"dependency"
is used for subsequent simulations (see details).
+write_config()
returns a tibble in the required
+format. OR provide a character string (vector) with the file name of one or
+multiple generated config file(s).
Character string providing the path to LPJmL
+(equal to LPJROOT
environment variable).
Character string defining path where all simulation data are
+written, including output, restart and configuration files. If NULL
,
+model_path
is used. See also write_config
Character string defining the user group for which the job is +submitted.
Character string defining the job classification. Available
+options at PIK: c("short", "medium", "long", "priority", "standby", "io")
+More information at https://www.pik-potsdam.de/en. Defaults to "short"
.
Integer defining the number of tasks/threads. More information
+at https://www.pik-potsdam.de/en and
+https://slurm.schedmd.com/sbatch.html. Defaults to 256
.
Character string defining the time limit. Setting a lower time
+limit than the maximum runtime for sclass
can reduce the wait time in the
+SLURM job queue. More information at https://www.pik-potsdam.de/en and
+https://slurm.schedmd.com/sbatch.html.
Integer defining the number of cores to be blocked. More +information at https://www.pik-potsdam.de/en and +https://slurm.schedmd.com/sbatch.html.
Character string defining constraints for node selection.
+Use constraint = "haswell"
to request nodes of the type haswell with 16
+cores per node, constraint = "broadwell"
to request nodes of the type
+broadwell CPUs with 32 cores per node or constraint = "exclusive"
to
+reserve all CPUs of assigned nodes even if less are requested by ntasks
.
+Using exclusive
should prevent interference of other batch jobs with
+LPJmL. More information at https://www.pik-potsdam.de and
+https://slurm.schedmd.com/sbatch.html.
A named list of further arguments to be passed to sbatch.
+E.g. list(mail-user
= "max.mustermann@pik-potsdam.de")
+More information at https://www.pik-potsdam.de and
+https://slurm.schedmd.com/sbatch.html
Logical. Set to TRUE
to test if x
set correctly or
+FALSE
to actually submit job to SLURM.
Argument is deprecated as of version 1.0; use sim_path +instead.
See x
, extended by columns "type"
, "job_id"
and "status"
.
A tibble for x
that has been generated by
+write_config()
and can look like the following examples can
+supplied:
sim_name |
scen1_spinup |
scen2_transient |
To perform subsequent or rather dependent simulations the optional run
+parameter "dependency"
needs to be provided within the initial
+tibble supplied as param
to write_config()
.
sim_name | dependency |
scen1_spinup | NA |
scen2_transient | scen1 _spinup |
To use different SLURM settings for each run the optional SLURM options
+"sclass"
, "ntasks"
, "wtime"
, "blocking"or
constraintcan also be supplied to the initial \link[tibble]{tibble} supplied as
param to [
write_config()]. These overwrite the (default) SLURM arguments (
sclass,
ntasks,
wtime,
blockingor
constraint
)
+supplied to submit_lpjml
.
sim_name | dependency | wtime |
scen1_spinup | NA | "8:00:00" |
scen2_transient | scen1 _spinup | "2:00:00" |
As a shortcut it is also possible to provide the config file
+"config_*.json"
as a character string or multiple config files as a
+character string vector directly as the x
argument to submit_lpjml
.
+With this approach, run parameters or SLURM options cannot be taken into
+account.
+if (FALSE) {
+library(tibble)
+
+model_path <- "./LPJmL_internal"
+sim_path <-"./my_runs"
+
+
+# Basic usage
+my_params <- tibble(
+ sim_name = c("scen1", "scen2"),
+ random_seed = as.integer(c(42, 404)),
+ `pftpar[[1]]$name` = c("first_tree", NA),
+ `param$k_temp` = c(NA, 0.03),
+ new_phenology = c(TRUE, FALSE)
+)
+
+config_details <- write_config(my_params, model_path, sim_path)
+
+ run_details <- submit_lpjml(
+ x = config_details,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+run_details
+# sim_name job_id status
+# <chr> <int> <chr>
+# 1 scen1 21235215 submitted
+# 2 scen2 21235216 submitted
+
+
+# With run parameter dependency and SLURM option wtime being
+# set (also less other parameters than in previous example)
+my_params <- tibble(
+ sim_name = c("scen1", "scen2"),
+ random_seed = as.integer(c(42, 404)),
+ dependency = c(NA, "scen1_spinup"),
+ wtime = c("8:00:00", "4:00:00"),
+)
+
+config_details2 <- write_config(my_params2, model_path, sim_path)
+
+run_details2 <- submit_lpjml(config_details2, model_path, sim_path)
+
+run_details2
+# sim_name order dependency wtime type job_id status
+# <chr> <dbl> <chr> <chr> <chr> <chr> <chr>
+# 1 scen1_spinup 1 NA 8:00:00 simulation 22910240 submitted
+# 2 scen1_transient 2 scen1_spinup 4:00:00 simulation 22910241 submitted
+
+
+# Same but by using the pipe operator
+library(magrittr)
+
+run_details <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = as.integer(c(1, 42)),
+ dependency = c(NA, "scen1_spinup"),
+ wtime = c("8:00:00", "4:00:00"),
+) %>%
+ write_config(model_path, sim_path) %>%
+ submit_lpjml(model_path, sim_path)
+
+
+# Shortcut approach
+run_details <- submit_lpjml(
+ x = "./config_scen1_transient.json",
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+run_details <- submit_lpjml(
+ c("./config_scen1_spinup.json", "./config_scen1_transient.json"),
+ model_path,
+ sim_path
+)
+
+}
+
+
Function to extract a subset of the full data in an LPJmLData
object by
+applying selections along one or several of its dimensions.
# S3 method for LPJmLData
+subset(x, ...)
An LPJmLData object
One or several key-value combinations where keys represent the
+dimension names and values represent the requested elements along these
+dimensions. Subsets may either specify integer indices, e.g.
+cell = c(27411:27416)
, band = -c(14:16, 19:32)
, or character vectors if
+the dimension has a dimnames attribute, e.g.
+band = c("rainfed rice", "rainfed maize")
.\
+Coordinate pairs of individual cells can be selected by providing a list or
+tibble in the form of coords = list(lon = ..., lat =...)
. Coordinate
+values need to be supplied as character vectors. The argument
+can also be called coordinates
. When coordinates are supplied as
+character vectors to subset either along the lon
or lat
dimension or to
+subset by coordinate pair, the function matches the grid cells closest to
+the supplied coordinate value.
An LPJmLData
object with dimensions resulting from the selection
+in subset
. Meta data are updated as well.
if (FALSE) {
+
+vegc <- read_io(filename = "./vegc.bin.json")
+
+# Subset cells by index
+subset(vegc, cell = seq(27410, 27415))
+# [...]
+# $data |>
+# dimnames() |>
+# .$cell "27409" "27410" "27411" "27412" "27413" "27414"
+# .$time "1901-12-31" "1902-12-31" "1903-12-31" "1904-12-31" ...
+# .$band "1"
+# [...]
+
+# Subset time by character vector
+subset(vegc, time = c("2001-12-31", "2002-12-31", "2003-12-31"))
+# [...]
+# $data |>
+# dimnames() |>
+# .$cell "0" "1" "2" "3" ... "67419"
+# .$time "2001-12-31" "2002-12-31" "2003-12-31"
+# .$band "1"
+# [...]
+}
+
+
Function to get the summary of the data array of an LPJmLData object. +See also summary.
+# S3 method for LPJmLData
+summary(object, ...)
LPJmLData object
Further arguments:
dimension
for which a summary is printed for every element
+(in style of matrix summary). Default is dimension = "band"
. Choose from
+available dimensions like "time"
or "cell"
.
subset
list of array dimension(s) as name/key and corresponding subset
+vector as value, e.g. list(cell = c(27411:27415)
. More information at
+subset.LPJmLData()
.
cutoff
(logical) If TRUE
summary for dimension elements > 16 are
+cut off.
Additional arguments to be passed on to summary.
Summary for object of class matrix (see summary) for +selected dimension(s) and if defined subset.
+Function to transform an LPJmLData
data object into another
+space or another time format. Combinations of space and time formats are also
+possible.
transform(x, to)
An LPJmLData object.
A character vector defining space and/or time format into which
+the corresponding data dimensions should be transformed. Choose from space
+formats c("cell", "lon_lat")
and time formats
+c("time","year_month_day")
.
An LPJmLData
object in the selected format.
if (FALSE) {
+
+runoff <- read_io(filename = "runoff.bin.json",
+ subset = list(year = as.character(1991:2000)))
+
+# Transform into space format "lon_lat". This assumes a "grid.bin.json" file
+# is present in the same directory as "runoff.bin.json".
+transform(runoff, to = "lon_lat")
+# [...]
+# $data |>
+# dimnames() |>
+# .$lat "-55.75" "-55.25" "-54.75" "-54.25" ... "83.75"
+# .$lon "-179.75" "-179.25" "-178.75" "-178.25" ... "179.75"
+# .$time "1991-01-31" "1991-02-28" "1991-03-31" "1991-04-30" ...
+# .$band "1"
+# [...]
+
+# Transform time format from a single time dimension into separate dimensions
+# for years, months, and days. Dimensions for time steps not present in the
+# data are omitted, i.e. no "day" dimension for monthly data.
+transform(runoff, to = "year_month_day")
+# [...]
+# $data |>
+# dimnames() |>
+# .$lat "-55.75" "-55.25" "-54.75" "-54.25" ... "83.75"
+# .$lon "-179.75" "-179.25" "-178.75" "-178.25" ... "179.75"
+# .$month "1" "2" "3" "4" ... "12"
+# .$year "1991" "1992" "1993" "1994" ... "2000"
+# .$band "1"
+# [...]
+}
+
+
Requires a tibble (modern data.frame class) in a
+specific format (see details & examples) to write the model configuration
+file "config_*.json"
. Each row in the tibble corresponds to a model run.
+The generated "config_*.json"
is based on a cjson file
+(e.g. "lpjml_config.cjson"
).
write_config(
+ x,
+ model_path,
+ sim_path = NULL,
+ output_list = c(),
+ output_list_timestep = "annual",
+ output_format = NULL,
+ cjson_filename = "lpjml_config.cjson",
+ parallel_cores = 4,
+ debug = FALSE,
+ params = NULL,
+ output_path = NULL,
+ js_filename = NULL
+)
A tibble in a defined format (see details).
Character string providing the path to LPJmL
+(equal to LPJROOT
environment variable).
Character string defining path where all simulation data
+are written. Also an output, a restart and a configuration folder are
+created in sim_path
to store respective data. If NULL
, model_path
is
+used.
Character vector containing the "id"
of outputvars.
+If defined, only these defined outputs will be written. Otherwise, all
+outputs set in cjson_filename
will be written. Defaults to NULL
.
Single character string or character vector
+defining what temporal resolution the defined outputs from output_list
+should have. Either provide a single character string for all outputs or
+a vector with the length of output_list
defining each timestep
+individually. Choose between "annual"
, "monthly"
or "daily"
.
Character string defining the format of the output.
+Defaults to NULL
(use default from cjson file). Options: "raw"
,
+"cdf"
(NetCDF) or "clm"
(file with header).
Character string providing the name of the main LPJmL
+configuration file to be parsed. Defaults to "lpjml_config.cjson"
.
Integer defining the number of available CPU cores for
+parallelization. Defaults to 4
.
logical If TRUE
, the inner parallelization is switched off
+to enable tracebacks and all types of error messages. Defaults to FALSE
.
Argument is deprecated as of version 1.0; use x +instead.
Argument is deprecated as of version 1.0; use sim_path +instead.
Argument is deprecated as of version 1.3; use +cjson_filename instead.
tibble with at least one column named "sim_name"
.
+Run parameters "order"
and "dependency"
are included if defined in
+x
. tibble in this format is required for
+submit_lpjml()
.
Supply a tibble for x
, in which each row represents
+a configuration (config) for an LPJmL simulation.
+Here a config refers to a precompiled "lpjml_config.cjson"
file (or file
+name provided as cjson_filename
argument) which already contains all the
+information from the mandatory cjson files.
+The precompilation is done internally by write_config()
.write_config()
uses the column names of param
as keys for the config
+json using the same syntax as lists, e.g. "k_temp"
from "param.js"
+can be accessed with "param$k_temp"
or "param[["k_temp"]]"
as the column
+name. (The former point-style syntax - "param.k_temp"
- is still valid but
+deprecated)
+For each run and thus each row, this value has to be specified in the
+tibble. If the original value should instead be used, insert
+NA
.
+Each run can be identified via the "sim_name"
, which is mandatory to
+specify.
my_params1 <- tibble(
+ sim_name = c("scenario1", "scenario2"),
+ random_seed = c(42, 404),
+ `pftpar[[1]]$name` = c("first_tree", NA),
+ `param$k_temp` = c(NA, 0.03),
+ new_phenology = c(TRUE, FALSE)
+)
+
+my_params1
+# A tibble: 2 x 5
+# sim_name random_seed `pftpar[[1]]$name` `param$k_temp` new_phenology
+# <chr> <dbl> <chr> <dbl> <lgl>
+# 1 scenario1 42 first_tree NA TRUE
+# 2 scenario2 404 NA 0.03 FALSE
To set up spin-up and transient runs, where transient runs are dependent on
+the spin-up(s), a parameter "dependency"
has to be defined as a column in
+the tibble that links simulations with each other using the
+"sim_name"
.
+Do not manually set "-DFROM_RESTART" when using "dependency"
. The same
+applies for LPJmL config settings "restart", "write_restart",
+"write_restart_filename", "restart_filename", which are set automatically
+by this function.
+This way multiple runs can be performed in succession and build a
+conceivably endless chain or tree.
# With dependent runs.
+my_params3 <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = c(42, 404),
+ dependency = c(NA, "scen1_spinup")
+)
+my_params3
+# A tibble: 2 x 4
+# sim_name random_seed order dependency
+# <chr> <int> <lgl> <chr>
+# 1 scen1_spinup 42 FALSE NA
+# 2 scen1_transient 404 TRUE scen1_spinup
Another feature is to define SLURM options for each simulation (row)
+separately. For example, users may want to set a lower wall clock limit
+(wtime
) for the transient run than the spin-up run to get a higher priority
+in the SLURM queue. This can be achieved by supplying this option as a
+parameter to param
.
+6 options are available, namely sclass
, ntasks
, wtime
, blocking
,
+constraint
and slurm_options
. Use as arguments for [submit_lpjml()].\cr If specified in
param, they overwrite the corresponding function arguments in [
submit_lpjml()`].
my_params4 <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = c(42, 404),
+ dependency = c(NA, "scen1_spinup"),
+ wtime = c("8:00:00", "2:00:00")
+)
+
+my_params4
+# A tibble: 2 x 5
+# sim_name random_seed order dependency wtime
+# <chr> <int> <lgl> <chr> <chr>
+# 1 scen1_spinup 42 FALSE NA 8:00:00
+# 2 scen1_transient 404 TRUE scen1_spinup 2:00:00
To set a macro (e.g. "MY_MACRO" or "CHECKPOINT") provide it as a column of
+the tibble as you would do with a flag in the shell:
+"-DMY_MACRO"
"-DCHECKPOINT"
.
+Wrap macros in backticks or tibble will raise an error, as
+starting an object definition with "-"
is not allowed in R.
write_config()
creates subdirectories within the sim_path
directory
"./configurations"
to store the config files.
"./output"
to store the output within subdirectories for each
+sim_name
.
"./restart"
to store the restart files within subdirectories for each
+sim_name
.
The list syntax (e.g. pftpar[[1]]$name
) allows to create column names and
+thus keys for accessing values in the config json.
The column "sim_name"
is mandatory (used as an identifier).
The run parameter "dependency"
is optional but enables interdependent
+consecutive runs using submit_lpjml()
.
SLURM options in param
allow to use different values per run.
If NA
is specified as cell value the original value is used.
R booleans/logical constants TRUE
and FALSE
are to be used for
+boolean parameters in the config json.
Value types need to be set correctly, e.g. no strings where numeric values +are expected.
if (FALSE) {
+library(tibble)
+
+model_path <- "./LPJmL_internal"
+sim_path <-"./my_runs"
+
+
+# Basic usage
+my_params <- tibble(
+ sim_name = c("scen1", "scen2"),
+ random_seed = c(12, 404),
+ `pftpar[[1]]$name` = c("first_tree", NA),
+ `param$k_temp` = c(NA, 0.03),
+ new_phenology = c(TRUE, FALSE)
+)
+
+config_details <- write_config(
+ x = my_params,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+config_details
+# A tibble: 2 x 1
+# sim_name
+# <chr>
+# 1 scen1
+# 2 scen2
+
+# Usage with dependency
+my_params <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = c(42, 404),
+ dependency = c(NA, "scen1_spinup")
+)
+
+config_details <- write_config(
+ x = my_params,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+config_details
+# A tibble: 2 x 3
+# sim_name order dependency
+# <chr> <dbl> <chr>
+# 1 scen1_spinup 1 NA
+# 2 scen1_transient 2 scen1_spinup
+
+
+my_params <- tibble(
+ sim_name = c("scen1_spinup", "scen1_transient"),
+ random_seed = c(42, 404),
+ dependency = c(NA, "scen1_spinup"),
+ wtime = c("8:00:00", "2:00:00")
+)
+
+config_details <- write_config(
+ x = my_params,
+ model_path = model_path,
+ sim_path = sim_path
+)
+
+config_details
+# A tibble: 2 x 4
+# sim_name order dependency wtime
+# <chr> <dbl> <chr> <chr>
+# 1 scen1_spinup 1 NA 8:00:00
+# 2 scen1_transient 2 scen1_spinup 2:00:00
+
+}
+
R/write_header.R
+ write_header.Rd
Write an LPJmL clm header to a file. The header has to be a list
+following the structure returned by read_header()
or create_header()
.
+The function will fail if the output file exists already unless overwrite
+is set to TRUE
.
write_header(filename, header, overwrite = FALSE)
Filename to write header into.
The header to be written.
Whether to overwrite an existing output file
+(default FALSE
).
Returns filename
invisibly.
create_header()
for creating headers from scratch and for a more
+detailed description of the LPJmL header format.
read_header()
for reading headers from files.
if (FALSE) {
+header <- read_header(filename = "old_filename.clm")
+write_header(
+ filename = "new_filename.clm",
+ header = header,
+ overwrite = FALSE
+)
+}
+
+