Methods |
Corresponding author: Christopher John Topping ( cjt@ecos.au.dk ) Academic editor: Leonardo Candela
© 2024 Christopher John Topping, Xiaodong Duan.
This is an open access article distributed under the terms of the Creative Commons Attribution License (CC BY 4.0), which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited.
Citation:
Topping CJ, Duan X (2024) ALMaSS Landscape and Farming Simulation: software classes and methods. Food and Ecological Systems Modelling Journal 5: e121215. https://doi.org/10.3897/fmj.5.121215
|
This article describes the landscape model for the Animal Landscape and Man Simulation System (ALMaSS). The article itself provides an overall description of the software classes and functions, with examples of use. In addition, there are links for code access, executable directory and code documentation for the model. These provide access to model details.
The descriptions cover the landscape class, its internal data, and the class hierarchy primarily associated with the landscape simulation. They also cover the timing and scheduling of actions and provide an overview of the landscape class interface. The Farm and Farm Manager classes responsible for simulating farming activities are presented together with descriptions of crop classes for crop management and weather and calendar classes.
ALMaSS, OOP, Vegetation Growth Modelling
The Animal Landscape and Man Simulation System (ALMaSS) (
In ALMaSS, the Landscape class essentially provides the environment into which other models can be run. It can, however, be used as a model in its own right, for example, to generate pesticide use maps. As a consequence of its role, the landscape must be able to supply all information needed by any other model in space and time. Other models thus define the role of the landscape class, but equally, this means that the full range of detailed data and mechanisms is beyond the scope of a single paper.
There are two parts of the landscape model where two approaches can be taken. These areas are the implementation of pesticide use and its fate and the implementation of farm management. In these cases, the functionality described here is the basic functionality normally used when neither the pesticides nor the farm management are the objects of study, i.e. typical ALMaSS use. Specific cases of detailed pesticide implementation and use (e.g.
In this paper, we describe the steps in linking external data to the internal representation in ALMaSS, the class structure implemented, and the processes covered by the core components of the ALMaSS landscape model.
ALMaSS needs to simulate landscapes of areas up to 50 × 50 km, with a typical size of 10 × 10 km, and at 1 m2 resolution. The ALMaSS system and the landscape simulation part should support multiple models running simultaneously, and the modelled entities can be in the order of 50 million concurrent agents. Hence, computational efficiency in both memory and CPU speed is critical. However, at the same time, the system must be flexible to support the needs of models ranging from simple insects to human decision-making. To achieve efficiency and flexibility, ALMaSS uses a strong object-oriented paradigm (OOP) in developing the code and relies on C++ development using relatively low-level programming code for efficient coding of algorithms and data structures. The OOP paradigm also confers an important additional benefit: facilitating the management of a huge code structure. OOP in C++ relies on the definition of classes to describe the behaviour of entities in the code. From these classes, descendent classes can be created, inheriting the functionality of the parents. This compartmentalises the code and allows modification of the classes without interfering with the functioning of the wider program. Classes interact with other entities through defined interfaces; thus, this is the only part of the class that needs to be cleanly integrated with the rest of the program. This approach also means new classes can be added without needing a major rewrite, either by extension of previous classes or modification of the interfaces of related components to allow their integration. In the following description, we refer to this class hierarchy to describe the major parts of the landscape simulation.
The Landscape Class is a fundamental component of ALMaSS, providing the interface for all environmental information required to run agent-based and subpopulation models. It effectively separates external data inputs from the implementation and internal Landscape interface.
The Landscape Class is initialised at the start of any ALMaSS simulation. This initialisation process sets up the primary data structures and classes used by the simulation, playing a crucial role in the ALMaSS simulation system. The key aspects of this initialisation process include:
The Landscape Class is the backbone of the ALMaSS simulation environment, ensuring that all agents and subpopulations can access the necessary environmental information and interact realistically within the simulated landscape.
The method used to represent the data as a map inside ALMaSS uses the flyweight design pattern (
The map structure is created based on the information passed from the PolyRef and .lsb files resulting from the external data handling procedure.
The .lsb file is a landscape binary format file that lists the size and location of the landscape map and holds the reference number to the polygon that covers the majority of the cell for every 1 m2 cell. This number is linked to the PolyRef file. The .lsb file, therefore, provides the topographic map of the landscape and is read into ALMaSS to create the flyweight data structure described above.
The format of the PolyRef file is to list one row for each polygon in the landscape and for the area covered by these to have 100% coverage for the rectangle describing the landscape. An example of the top of a PolyRef file is shown in Table
Example of a polygon reference (PolyRef) file input from a Danish landscape denoted by DK in the first row which is followed by the location (Latitude and Longitude) of the NE corner of the landscape that this file refers to. The second row is the number of polygons defined in the file. Polytype is a standard ALMaSS code for this polygon type. PolyRefNum is a unique identifier for the polygon in this map. Area is the area in m2. FarmRef is a reference to the farm that owns the polygon, if any (or -1 if there is not farm associated with it). Unsprayed Margin Ref indicates the PolyRef for the associated unsprayed margin, if any (or -1). Soiltype is the soil type under the polygon as the most common type, or -1 if not known. Centroid X and Centroid Y are the coordinates of the centroid of the polygon. Openness, Elevation, Slope and Aspect are not used in this example but can be included if needed.
DK Latitude 57.3801 Longitude 9.83159 | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
41058 | |||||||||||
PolyType | PolyRefNum | Area | Farm Ref | UnSprayed Margin Ref | SoilType | Openness | CentroidX | CentroidY | Elevation | Slope | Aspect |
123 | 0 | 165 | -1 | -1 | -1 | 0 | 260 | 17 | 0 | 0 | 0 |
130 | 1 | 311 | -1 | -1 | 3 | 0 | 366 | 44 | 0 | 0 | 0 |
130 | 2 | 195 | -1 | -1 | -1 | 0 | 421 | 23 | 0 | 0 | 0 |
13 | 3 | 1805 | -1 | -1 | 3 | 0 | 442 | 647 | 0 | 0 | 0 |
13 | 4 | 25 | -1 | -1 | -1 | 0 | 430 | 9 | 0 | 0 | 0 |
210 | 5 | 289 | -1 | -1 | -1 | 0 | 438 | 14 | 0 | 0 | 0 |
210 | 6 | 313 | -1 | -1 | -1 | 0 | 536 | 31 | 0 | 0 | 0 |
98 | 7 | 224 | -1 | -1 | -1 | 0 | 656 | 11 | 0 | 0 | 0 |
207 | 8 | 55 | -1 | -1 | -1 | 0 | 654 | 13 | 0 | 0 | 0 |
210 | 9 | 8606 | -1 | -1 | 3 | 0 | 731 | 23 | 0 | 0 | 0 |
110 | 10 | 1172 | -1 | -1 | 3 | 0 | 874 | 13 | 0 | 0 | 0 |
ALMaSS soil types as referenced inside ALMaSS code with their FAO classification, agricultural usage and class for management of crop management.
Agricultural Usage | ALMaSS Code SoilType | FAO Texture Code | Description | Crop management types |
---|---|---|---|---|
None | 0 | - | Water | - |
None | 1 | S | Sand (unspecified) | Light (sandy type) |
Poor | 2 | LS | Loamy swand | Light (sandy type) |
Poor | 3 | SL | Sandy loam | Light (sandy type) |
Average | 4 | SCL | Sandy clay loam | Light (sandy type) |
Average | 5 | SiL | Silt loam | Average (silty loam type) |
Good | 6 | SiCL | Silty clay loam | Average (silty loam type) |
Good | 7 | CL | Clay loam | Heavy (clay & loam type) |
Good | 8 | L | Loam | Heavy (clay & loam type) |
Good | 9 | Si | Silt | Average (silty loam type) |
Good | 10 | SC | Sandy clay | Heavy (clay & loam type) |
Good | 11 | SiC | Silty clay | Heavy (clay & loam type) |
Good | 12 | C | Clay | Heavy (clay & loam type) |
Good | 13 | HC | Heavy Clay | Heavy (clay & loam type) |
Good | 14 | O | Organic & peat | Organic & peat |
The basic timestep for landscape operations is one day. This means that several operations must be carried out at the start of each simulation day. These collectively update the landscape simulation so the other ALMaSS models can access the data specific to that day on completion. These operations fall into four main types, 1) updating the calendar, 2) updating the weather, 3) updating the farming, and 4) updating the polygon internal behaviour (through updating all LE objects). Each of these four areas are detailed below. Date and weather are controlled by the Calendar and Weather classes, respectively, and are described in their respective sections. Farming is a complex subject area of the landscape simulation and is detailed below (See Farm, FarmManager and Crop classes), however, the landscape is responsible for calling the FarmManager class daily and asking it to update all the farms. The Landscape controls the link between updating the polygons and the Landscape class by calling the ‘Tick’ function for each polygon. The Tick function can be implemented differently for different base TOLE types within the LE class hierarchy but is executed correctly by OOP polymorphism.
The Landscape Class has an extensive interface function set, which provides the rest of the simulation with access to landscape data or data from LE instances or Farms. Using this interface rather than direct access to the data simplifies the maintenance of the code by allowing the implementation within the Landscape and associated classes to be altered without affecting the rest of the simulation models.
The LE class (Landscape Element) is the base class for describing polygons in the landscape. Descendent classes implement specific behaviour for different TOLE types. This hierarchy (Fig.
The landscape element class hierarchy based on the LE base class. All types of landscape element are classified as being in one of these classes. Those with specific behaviour are placed in the lowest tier whilst those represented by generic types only differing in attribute values are placed in the NonVegElement and VegElement class.
The problem of multiple types is avoided by adding classificatory attributes and the relatively short class hierarchy in Fig.
Flexibility is further increased through ‘user-defined’ attributes that individual models can use to create specific combinations of TOLE and TOVs. For efficiency, these attributes are defined at run-time and written into the attributes of polygons on creation of the Landscape instance. The LE and descendent classes have a wide range of functionality. For example, the road classes can represent the traffic loads at any given point in time.
A major part of the LE functionality is modelling vegetation growth (see below). Other LE functionality is targeted at supporting specific other models. There is a sub-model for general insect biomass, others for decay rates of spilled grain and good forage resources, digestibility of vegetation, and a new set of functionality under development for supporting pollinator resource modelling. The design here relies on the sensible inclusion of only those functionalities actually in use for any given simulation, following the concept of avoiding false inclusions but also false exclusions (
As mentioned above, some LE descendent classes have special behaviours. These are largely related to management activities, such as mowing roadside verges or cutting grass. Of these, the Field class has a specific role in providing functionality related to rotational crops. This functionality includes recording the current, past and planned next crop and some special behaviour simulating the creation of tramlines when the tractor drives into the field and their subsequent closure as vegetation grows.
One key part of implementing the external data in the simulation is the simulation of vegetation growth. Any class with VegElement as the base class will simulate vegetation development on a daily basis. The underlying method is described by (
Further flexibility is obtained by creation of different growth phases, describing different periods of the plant growth or responses to external influences. Five phases are currently implemented, and can be used when defining a growth curve as needed. These are 1) From January 1st; 2) From Sowing; 3) From March 1st; 4) After Harvest/cut; 5) After Second Harvest/cut. Complex patterns can be simulated by combining the growth curve phases differently. For example, an autumn sown wheat crop might have: From sowing in September, followed by January to March, followed by From March, followed by After Harvest. Each TOV type has to have an associated plant growth curve, but this curve may be used by multiple TOVs (e.g., most variants of barley have the same growth curve). During the simulation, major management events such as harvest or cutting events will trigger an immediate jump to a different growth phase. In this way the flexible timing of the crop management can be taken into account.
LAI is converted to cover through application of Beer’s Law to calculate vegetation cover. The equation using Beer’s law to calculate the cover (C) C = 1−exp(−k*LAI) where k is the light extinction coefficient and is assumed for cover to be 0.6, and LAI is the total LAI. This value is towards the high end of the range for winter wheat (Soleymani 2016) and was chosen as a reasonable estimate for most vegetation. Change in biomass is implemented as described by (
Agricultural simulation is a large part of the Landscape functionality. This is achieved by defining a hierarchy of interacting objects starting with a FarmManager class which controls all the lists of farms and their scheduling, the Farm class which represents instances of individual farms, and the Crop class which defines the management of each crop grown on farm fields.
This class is an administrative class controlling the list of farms and is involved in scheduling farming actions. This is called once per day from the Landscape as part of the daily updating of the landscape simulation. The FarmManager is created with the Landscape class from the FarmRefs.txt file generated during the external data handling process. This file contains a list of all farms together with a reference for their farm type, e.g., conventional arable farm, and is used by the FarmManager to create and populate the list of farm objects in the simulation. After the creation of the farms the FarmManager creates a centre point for each farm (centroid) which can be used by other objects in the simulation. The FarmManager class itself has no further functionality but acts as an interface to farm information, providing lists and data as necessary to support simulation elsewhere in ALMaSS, often using the farm reference number from the FarmRefs.txt as an index to the farm of interest.
The Farm Class is the organising class for each individual farm and its data. The Farm object is created, and its management is initialised by the FarmManager on start-up. Each farm consists primarily of a list of fields for which it is the owner/manager. Some of these fields may be designated as permanent crops (e.g. pasture or trees such as orchards), and others will be fields in a crop rotation. Depending on the level of information present in the external data sources, permanent crops may be identified individually and exist as separate TOLEs in the map or may be represented by a proportion of the farm area. In the latter case, the allocation of permanent crops is made to the farm fields to best match the proportion of area under those crops reported to the CAP subsidy scheme used to create the underlying data. On construction, the farm object will be linked to all its fields via a list of pointers. The farm will also be allocated a Farmer object, but this class is not needed to run the standard ALMaSS landscape simulation.
After the management’s initialisation, the Farm object will allocate a crop to each field. Permanent crops have a fixed vegetation type, but rotational crops must be chosen. In the rotational case, each field will be randomly allocated one crop from the crop rotation for the farm (which is a function of the farm type). This rotation is typically 100 crops long and represents the area covered by each crop type in one-percentage blocks. The crop rotation needs to be specified by the user and associated with the farm type. This is not an automatic process but uses external data as the basis for developing a ‘.rot’ file, i.e., the list of crops in the rotation. Before a simulation can be run a .rot file must exist and be associated with each farm type present in the landscape.
Each crop type (at TOV) has a specific management that is defined by a crop management code file. This management causes the execution of farm activities such as ploughing. These farm activities (called FarmToDo in ALMaSS) are a property of the Farm class. Each FarmToDo has the following basic behaviour when called:
Storing the last FarmToDo as an easily accessible ‘last event’ and a traced history provides maximum flexibility for other models to access management history.
Crop classes hold the information necessary to manage a farmed crop. This may be an arable crop in rotation or a permanent crop, including grazed grassland. The basis for the development of a crop class is a table of events and a resulting flow diagram which describes farming operations with conditions for implementation (e.g., related to weather or crop growth) and periods during which they are implemented. The diagram follows 100% of farmers starting from any post-harvest operations from the previous crop until the end of harvest or any post-harvest operations for this crop. At each decision branch, a certain proportion of farmers will be allocated to each possible path. If this allocation is based on probability, the overall consistency over time is maintained, meaning that if 100% of farmers start, 100% will also reach the end of the plan.
There is only one instance of each crop class. This is done to encapsulate the field polygon information in the LE class instance (i.e., the field where the crop is grown). In this way, duplicate data is avoided, and it is clear that any cropping information needed is accessed via the LE class interface. All functions of the crop class are contained in the single instance of that class, which means that all necessary data to run each crop on each field must be passed to this crop object each time it is called. This data is passed using an event queue containing pointers to the farm owner object and the field through which the data can be accessed. When a crop is started on a field, an initiation event is sent to the queue; this is a timed event that may be for the next time step or months or more. When this event is triggered, the crop management code starts. The farm management to be carried out then generates new events placed on the stack in the same way; they can also fork multiple events from a single point. The management plan is thus very flexible and runs as a multi-threaded program. Only one thread (designated the main thread) reaches the end of the plan’s execution, returning a ‘Done’ signal on completion, which then triggers choosing the next crop in the rotation for that field and sending a new initiation event to the queue. The other threads may end or re-join the main thread (Fig.
The range of conditions related to branching in the crop is large. These may link to the farm type as in the example in Fig.
There is an interplay between the vegetation growth curves and management plans. Some events, such as harvest, will trigger a change in the vegetation growth phase, thus altering crop growth.
ALMaSS does not simulate weather, but instead, it’s an input. Weather data consists of hourly mean temperature, precipitation, wind speed, wind direction, soil temperature, snow depth, humidity, and radiation. Weather is based on a historical record for an area and is part of the external data procedure needed for ALMaSS. Because it is a historical record, it is usually looped for long simulations. Consequently, models in the system can request weather information for periods during the simulation, even for the future. For example, a crop code may trigger a farm management event requiring five days without rain before execution.
The Weather Class interface provides access to all weather data as immediate weather data (at the point in time the function is called), at a date, particular hour, day, or over a specific period. Thus, the weather class can be viewed as a non-dynamic data supplier.
The Calendar class performs timekeeping for ALMaSS. Depending on the time step used (typically 1 day to 10 minutes for animals), the Calendar class will provide the current time, as well as general functionality related to the number of days per month and indexing for time-dependent function calls (e.g., supplying rain over a period of time). The calendar class is a critical part of the crop management functionality since it supplies Julian days and the simulation date, both used in the Crop Class codes.
The Calendar class has a detailed set of functions for calculating the sunrise and sunset time. This calculation is done automatically from the latitude and longitude supplied during the landscape generation process. This position is used to calculate the time at which the sun drops below or comes above the horizon based on an angle (90° for official and 108° for astronomical).
ALMaSS landscape simulation attempts to find a balance between the inclusion of necessary detail to support the other system models, flexibility to change or include more, and efficiency at run-time. A further consideration is that ALMaSS was designed for ecologists, not software engineers, and the majority of contributors to the models are not professional programmers. Consequently, code should be written as simply as possible to maximise understanding.
Using the approach described above allows ALMaSS to simulate a landscape in considerable detail. A 10 × 10 km landscape in Denmark typically has upwards of 40,000 polygons and 150–200 farms represented. Simulation run-time for the landscape with no animals is fast, approximately one year per second on an average PC. During this year, all farm operations are carried out daily, and all vegetated elements model their vegetation biomass, LAI, and height daily, as well as digestibility, insect biomass, and other sub-models daily. RAM is a limiting factor, with landscapes of 50 × 50 km requiring a computer with 64GM RAM to run animal simulations. At 50 × 50 km, the raster map alone requires 20GB of memory. However, there is linear scaling between area and run-time for the landscape simulation.
The main aim of the landscape is to serve other simulation components with data requirements. Communication is done via interface functions such as SupplyVegPhase(int a_poly), which returns the current vegetation growth phase for an LE. Direct polygon calls are the fastest way to access the data with the index to the polygon data array being provided as a_poly. However, direct calls are not always possible, and access has to be via the x,y coordinate system to determine the polygon index. Efficiency here is lower since a_poly must be reached via the raster map using x+(yW), where W is the width of the landscape in m. The need for range checks at run-time for these calls typically results in this being the low-level time-sensitive operation when running an animal model. Despite these problems, ALMaSS can cope with millions of concurrent agents and, for some simulations, up to 50 million.
A key feature of the landscape simulation, as carried out using this modular software process, is the ability to upgrade any component as necessary without compromising the model’s integrity. This design allows for the continued testing and development of the code to be possible.
Functionally, the design facilitates the evaluation of complex questions such as spatially differentiated management (e.g., by application through farm type) or complex systems dynamics operating through long-chain interactions, resulting in emergent properties. For example, in
The ALMaSS landscape model is a highly detailed landscape simulator that is specifically designed to support ALMaSS model simulations of species and people. As such it does not have a direct analogue in the scientific literature. ALMaSS is designed to represent actual landscape areas, but could be used in conjunction with landscape generators (
In terms of supporting ALMaSS species and human models, the ALMaSS landscape simulation has been robust, flexible, and reliable for over 20 years. However, many aspects could be improved. Some of these are related to the fact that ALMaSS has grown beyond its initial design parameters, i.e., representing Danish landscapes (
A similar issue is connected to the use of the TOLE and TOV types to represent landscape elements and vegetation types. The increasing size of the enumerations for TOLE and TOV types makes using these as control structures less and less efficient. The use of attributes described above goes some way to rectify this, but it is not an easily managed solution. Hence, in future versions, the aim is to create a hierarchical classification system for TOLE and TOV types. Such a classification will facilitate much faster conditional statement execution by limiting the number of queries to the lowest common denominator. However, for this to work, the underlying classification algorithm must map well to the conditional tests that ALMaSS models need. This will refer to function rather than topographical classification, see for example (
In the most recent version of the ALMaSS Population_Manager class (
The ALMaSS landscape has been designed to service the needs of ALMaSS species models, but since it is written in a modular form as a set of linked C++ classes, it could be used as a library to be added to other model systems. However, the easiest way to use it for new models would be to add new models to the ALMaSS framework. Expanding the models available within the system would provide more building blocks for future modellers.
Expansion also has another benefit. The ALMaSS system is designed to answer complex questions about landscape, management, and wildlife. These questions are multi-faceted, often requiring the integration of multiple modules. For example, determining the impact of wildlife management options requires integration of landscape and cropping modules with wildlife management options and multiple species (
The ALMaSS landscape simulation model has had significant impacts (over 80 published papers and reports), being successfully utilised in three European H2020 projects: PoshBee, B-GOOD, and EcoStack, and currently supporting the population modelling framework in the Horizon Europe project PollinERA (
In all three cases, the scenarios evaluated were driven by changes in the configuration of the ALMaSS landscape model.
ALMaSS is intended for use by researchers to develop their own simulations. It is not an out-of-the-box simulation program. The code for the landscape model can be accessed through a GitLab project ALMaSS_Methodology (https://gitlab.com/ALMaSS/almass_methodology). This is a complete implementation of the landscape model. But, please note that this is only a running example, as it includes only one artificial farm type and uses only two crops in its crop rotation file (UserDefinedFarm27.rot). The source codes for two Danish crops, spring barley and winter wheat, are included as examples. Procedures to compile the code for Linux are provided in the GitLab project.
The project also includes a run directory, which contains an executable version of the code for Linux and the required input files for ALMaSS simulations. If you choose to compile the code yourself, you need to copy the executable to the run directory. By default, it will run a 1-year simulation for the landscape model. In the “Image” subdirectory under the run directory, you can find several images stored from the simulation showing biomass, vegetation type, landscape element type, soil type, and farm ownership for the fifteenth day of each month, after the simulation is run. Different colours represent either different types or different amounts, such as biomass. As shown in Fig.
The vegetation types in January and September are displayed in Fig.
The ALMaSS landscape simulation is flexible. Different scenarios can be set by changing parameters in the “TIALMaSSConfig.cfg” file. For example, removing the # symbols for the lines below the “TIALMaSSConfig.cfg” will create a monocrop scenario. In this scenario, all the farms will only grow winter wheat as shown in Fig.
#FARM_FIXED_CROP_ENABLE (bool) = true
#FARM_FIXED_CROP_TYPE (int) = 1026
Another important aspect is the use of the ALMaSS simulation as a dynamic context for species simulations. The same GitLab project currently provides three artificial species models and a Skylark model, which users can run as examples. Details about these model types can be found in
Suppl. material
Suppl. material
Many people have contributed to the ALMaSS landscape model over the years. Martin Rehder and Frank Nikolaisen were instrumental in the early design of the model. Geoff Groom, Luna Kondrup Marcussen and Elżbieta Ziółkowska all have made important contributions to aspects of the model as it is today. This work was partially supported by DeiC National HPC (UCloud, GenomeDK, LUMI) (g.a. DeiC-AU-N1-000025, DeiC-AU-L5-0011 and DeiC-AU-N2-2023015) and by the EcoStack project funded by the European Union’s Horizon 2020 research and innovation programme under Grant Agreement no. 773554.
The authors have declared that no competing interests exist.
No ethical statement was reported.
This work was partially supported by DeiC National HPC (UCloud, GenomeDK, LUMI) (g.a. DeiC-AU-N1-000025, DeiC-AU-L5-0011 and DeiC-AU-N2-2023015) and by the EcoStack project funded by the European Union's Horizon 2020 research and innovation programme under Grant Agreement no. 773554.
Conceptualization: CJT. Methodology: XD. Software: XD, CJT. Writing - original draft: CJT. Writing - review and editing: XD, CJT.
Christopher John Topping https://orcid.org/0000-0003-0874-7603
Xiaodong Duan https://orcid.org/0000-0003-2345-4155
All of the data that support the findings of this study are available in the main text or Supplementary Information.
The code documentation for the ALMaSS Landscape Model
Data type: pdf
Explanation note: Landscape and associated class documentation generated by doxygen (www.doxy.org).
Vegetation growth simulation in ALMaSS
Data type: pdf
Explanation note: Vegetation growth model (