Version 1.5.3
API improvements
- Added
append_simulationmethod
append_simulation method can be used to append simulations to the current ApsimModel instance. Unlike
clone_simulation, this method supports transferring simulations from external ApsimModel objects in addition to duplicating
simulations already present within the current model instance.
Advantages:
- Reuse simulations across APSIM models without manual copying.
- Build complex scenario collections from multiple source models with minimal effort.
- Quickly create simulation variants by duplicating existing simulations.
- Avoid naming conflicts through optional simulation renaming.
- By allowing multiple simulations to be managed within a single APSIM model instance, the overhead associated with repeatedly loading and initializing
Models.exeis reduced. - Rapidly generate multiple simulation scenarios using the
payloadargument, enabling efficient exploration of management, soil, weather, or cultivar variations and their impacts on model outputs. - Simplify what-if analysis by automatically creating simulation variants from different input configurations, reducing the effort required to evaluate alternative strategies and outcomes.
Basic example:
Append a simulation from another APSIM model
from apsimNGpy import ApsimModel
base_model = ApsimModel("Maize")
# Get the first simulation from another model
other_simulation = ApsimModel("Soybean")[0]
base_model.append_simulation(
simulation=other_simulation,
rename="Simulation2",
)Duplicate an existing simulation
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
model.append_simulation(
simulation=model[0],
rename="Simulation_copy",
)Edit the appended simulation on the fly
The payload argument allows simulations to be modified during the append operation, making it easy to generate multiple scenario variants without additional editing steps.
from apsimNGpy import ApsimModel
with ApsimModel("Maize") as model:
model.append_simulation(
simulation=model[0],
rename="pop12",
payload=dict(
model_type="Models.Manager",
model_name="Sow using a variable rule",
Population=12,
),
)This feature is particularly useful for rapidly generating scenario ensembles, sensitivity analysis experiments, and optimization studies where multiple simulations differ only in a small number of parameter values.
Note
append_simulation()should not be used withExperimentManagerobjects, even thoughExperimentManagerinherits fromApsimModel. Experiment managers are designed around a single base simulation and appending simulations directly may result in unexpected behavior.In many cases, appended simulations should be modified to distinguish them from their source simulations. The
payloadargument provides a convenient way to apply edits during the append operation.payloadmay be either a dictionary or a list of dictionaries containing arguments accepted byedit_model().
model.append_simulation(
simulation=model[0],
rename="clone1",
payload=dict(
model_type="Models.Manager",
model_name="Sow using a variable rule",
Population=12,
),
)For more examples and implementation details:
help(model.append_simulation)Added add_node_from()
A new add_node_from() method has been introduced to simplify transferring APSIM nodes between models and simulations while providing greater control over node placement and replacement behavior.
Advantages
- Transfer nodes from external or internal APSIM models into a specified target location.
- Improve workflow automation for model customization, scenario generation, and programmatic model construction.
- Reduce errors by enforcing keyword-only arguments, improving readability and preventing parameter mis-ordering.
- Support safe replacement of existing nodes through the
del_if_existsoption. - Allow inserted nodes to be renamed during transfer to avoid naming conflicts.
- Identify source nodes using either node names or full APSIM paths.
- Improve handling of multiple nodes of the same type, such as Manager scripts serving different roles within a simulation.
Example
target_model.add_node_from(
source=source_model,
source_node="Fertiliser",
target="Simulation.Field",
rename="HighN",
del_if_exists=True,
)This addition provides a more robust and flexible approach for building, modifying, and extending APSIM models programmatically, particularly in workflows involving large-scale scenario generation, experimentation, and model templating.
Added clone_simulation()
A new clone_simulation() method has been introduced to simplify the creation of simulation variants within the same APSIM model.
Advantages
- Rapidly generate alternative management, cultivar, or environmental scenarios while preserving the original simulation.
- Simplify comparative analysis by maintaining multiple simulation variants within a single APSIM model.
- Reduce the effort required to create and manage large scenario ensembles.
- Enable efficient sensitivity analysis, optimization, and what-if experimentation workflows.
Example
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
population = 10
simulation_name = f"sim_{population}"
model.clone_simulation(
rename=simulation_name,
base_simulation=0,
)
model.edit_model(
model_type="Models.Manager",
model_name="Sow using a variable rule",
simulations=simulation_name,
Population=population,
)Added has_node()
A new has_node() method has been added to simplify node discovery and validation within APSIM models.
Advantages
- Verify the existence of nodes before performing modifications.
- Support node lookup using either node names or full APSIM paths.
- Improve robustness of automation workflows by reducing node-resolution errors.
- Facilitate model inspection, validation, and dynamic editing operations.
Example
from apsimNGpy import ApsimModel
with ApsimModel("Maize") as model:
model.has_node(
"Sow using a variable rule",
"Models.Manager",
)
model.has_node(
".Simulations.Simulation.Field.Sow using a variable rule",
"Models.Manager",
)Added switch_wm_to_swim3()
A new switch_wm_to_swim3() method has been introduced to simplify the replacement of APSIM's default soil water model with the physically based SWIM3 module.
Advantages
- Accelerate conversion of existing models to SWIM3.
- Automatically configure subsurface tile drainage systems.
- Support custom SWIM3 parameter overrides.
- Validate drainage configuration inputs before model execution.
- Simplify hydrological scenario analysis and drainage-management studies.
Examples
Automatic drainage configuration:
model.switch_wm_to_swim3(
ss_tile_drainage="auto"
)Custom drainage configuration:
model.switch_wm_to_swim3(
ss_tile_drainage={
"DrainDepth": 1200,
"DrainSpacing": 30000,
"ImpermDepth": 2500,
}
)Cultivar Editing Interface
Introduced a dedicated CultivarEditor implementation based on a composition-oriented design.
Advantages
- Provides a clearer and more maintainable API for cultivar editing.
- Simplifies the creation and management of derived cultivars.
- Improves compatibility with APSIM cultivar editing limitations.
- Enables cultivar modifications without directly altering replacement nodes.
Added add_new_model()
A new add_new_model() method has been introduced for dynamically constructing and inserting APSIM model nodes directly from Python dictionaries.
Advantages
- Build APSIM models programmatically without manual JSON manipulation.
- Create APSIM nodes directly from Python-native data structures.
- Support both APSIM-standard
"$type"and Python-friendly"type"declarations. - Automatically resolve and instantiate APSIM CLR model types.
- Insert nodes into arbitrary locations within an APSIM model.
- Support replacement and renaming during insertion.
- Automatically parse APSIM date fields and manager parameter definitions.
- Simplify automated model generation, templating, and scenario construction workflows.
Example
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
model.add_new_model(
parent_identifier="Simulation",
parent_type="Simulation",
source={
"$type": "Models.Clock, Models",
"Start": "2000-01-01",
"End": "2020-12-31",
},
)Bug Fixes and Improvements
Fixed add_replacement() Duplication Issue
Resolved an issue where repeated calls to add_replacement() could create duplicate replacement nodes. The method now detects existing replacements and prevents unintended duplication, improving model consistency and reducing replacement management errors.
Improved inspect_model_parameters()
inspect_model_parameters() now returns a dictionary consistently across supported APSIM model types.
Advantages
- Provides a uniform and predictable API across APSIM model types.
- Simplifies programmatic inspection, calibration, and model-editing workflows.
- Preserves both scalar and layered parameter values in a single structure.
- Eliminates model-type-specific return handling.
- Improves compatibility with calibration, sensitivity analysis, optimization, and automated model generation workflows.
Additional Improvements
- When matching nodes are found across multiple simulations, the returned structure is nested and keyed by simulation name, making it easy to compare equivalent nodes between simulations.
- Each dict returned contains the complete node payload, including metadata such as
FullPath, parent node references, and model-specific properties. - For
Models.Managernodes, both theParametersdictionary and the underlyingCodeArrayare returned. - The exact contents of the returned dictionary depend on the APSIM model type being inspected. For example, Weather nodes expose meteorological metadata and climate properties, whereas Manager nodes expose script parameters, source code, and execution settings.
- Despite these model-specific differences, all information is exposed through a single, consistent API.
Examples
Inspecting a Weather node:
from apsimNGpy import ApsimModel
model = ApsimModel("Maize")
weather = model.inspect_model_parameters(
model_type="Models.Climate.Weather",
model_name="Weather",
)
print(weather)Output (truncated):
{
"Simulation": {
"Name": "Weather",
"FullPath": ".Simulations.Simulation.Weather",
"FileName": "%root%/Examples/WeatherFiles/AU_Dalby.met",
"Latitude": -27.18,
"Longitude": 151.26,
"Tav": 19.09,
"Amp": 0.0,
"Parent": <Models.Core.IModel>,
...
}
}Inspecting a Manager script:
manager = model.inspect_model_parameters(
model_type="Models.Manager",
model_name="Sow using a variable rule",
)
print(manager["Simulation"]["Parameters"])Output:
{
"Crop": "Maize",
"StartDate": "1-nov",
"EndDate": "10-jan",
"MinESW": "100.0",
"MinRain": "25.0",
"RainDays": "7",
"CultivarName": "Dekalb_XL82",
"SowingDepth": "30.0",
"RowSpacing": "750.0",
"Population": "6.0",
}Accessing the underlying Manager script source:
manager["Simulation"]["CodeArray"]Example with multiple simulations:
{
"Simulation": {
"Parameters": {
"Population": "6.0",
},
"FullPath": ".Simulations.Simulation.Field.Sow using a variable rule",
},
"sim_10": {
"Parameters": {
"Population": "10.0",
},
"FullPath": ".Simulations.sim_10.Field.Sow using a variable rule",
},
}This enhancement provides a single inspection interface capable of exposing rich, model-specific details while maintaining a consistent and predictable return structure across APSIM component types.
Improved inspect_model()
inspect_model() now returns an empty list ([]) when the requested model type is not found in the simulation tree, providing more predictable behavior and simplifying downstream validation and automation workflows.
Removed Default Execution Timeout in run method
The fixed 800-second execution timeout has been removed and replaced with unlimited runtime by default. This prevents premature termination of computationally intensive workflows, including large-scale sensitivity analyses, optimization studies, and long-running simulation ensembles.