[Crop and Soil] Implement pasture crop type - #3163
Conversation
b7ae487 to
c6865f4
Compare
c6865f4 to
6d785a4
Compare
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1137 |
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1135 |
|
|
||
| actual = crop_manager.manage_harvest(harvest_op, "pasture_field", field_size, mock_time, soil_data) | ||
|
|
||
| # No yield is collected and no harvested crop is produced for feed storage. |
There was a problem hiding this comment.
I think with how lengthy the docstring is, there's no need for inline comments (applies to the other test as well).
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1135 |
There was a problem hiding this comment.
- Adds a new optional crop-configuration flag, deposit_all_residue_at_harvest (default false).
- When that flag is set, harvest operations collect no yield and deposit all cut biomass into the field as residue; no harvested crop is sent to feed storage.
This is probably my bad, but isn't quite how I think this should work. Instead, when the pasture is "harvested" by grazers:
- Some portion of the yield (the part that would normally be collected by the harvest operation) gets "fed" directly to the herd/cow. So, the yield bypasses the storage operations but becomes a feed operation.
- Then the remaining portion of the yield becomes residue and gets applied to the field (as currently occurs, but at a higher rate)
The efficiency of grazers is probably not the same as mechanical harvesting, so we should tweak the parameter(s) that control the ratio of collected yield to residue (maybe just the harvest_index unless there is a "harvest efficiency" parameter that I'm not aware of). Cattle grazers have a harvest efficiency of about 25% for season-long grazing (https://www.jstor.org/stable/40802661), meaning they consume about 25% of the above ground biomass. The efficiency for rotational grazing is about 40%.
|
@matthew7838 do you mind retagging me for review once @morrowcj's changes have been implemented? I think it's a significant enough difference where a second look from the dev side might be helpful. |
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1134 |
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1134 |
morrowcj
left a comment
There was a problem hiding this comment.
Minor change to the default grazing_harvest_efficiency value and a few other minor suggestions. Otherwise, LGTM.
| @property | ||
| def is_grazed(self) -> bool: | ||
| """ | ||
| Checks whether this crop is grazed rather than mechanically harvested. | ||
|
|
||
| Returns | ||
| ------- | ||
| bool | ||
| True if a grazing harvest efficiency is given, False otherwise. | ||
|
|
||
| """ | ||
| return self.grazing_harvest_efficiency is not None | ||
|
|
There was a problem hiding this comment.
I wonder if this type of flag should be set by the (eventual) grazing harvest operation rather than by the crop configuration. For example, what if someone wanted to graze a pasture in one year, and then let it grow un-grazed the second year and machine harvest it for hay at the end of that season?
Co-authored-by: Clay Morrow <25436787+morrowcj@users.noreply.github.com>
Co-authored-by: Clay Morrow <25436787+morrowcj@users.noreply.github.com>
fcaa917 to
4842983
Compare
4842983 to
cb3b684
Compare
cb3b684 to
3b99409
Compare
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1134 |
2 similar comments
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1134 |
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1134 |
| "name": "pasture", | ||
| "plant_category": "perennial", | ||
| "is_nitrogen_fixer": false, | ||
| "grazing_harvest_efficiency": 0.50, |
There was a problem hiding this comment.
Is this parameter redundant with CropManagement.harvest_efficiency?
|
Current Coverage: 99% Mypy errors on pasture-crop-type branch: 1138 |
ew3361zh
left a comment
There was a problem hiding this comment.
LGTM, not sure where the extra mypy errors are coming from looking at the code but probably somewhere that wasn't previously expecting a None type for HarvestedCrop.
| If heat unit scheduling is used for harvesting. | ||
| harvest_efficiency : float, default 1.0 | ||
| Efficiency of the harvest operation: the proportion of the cut biomass that is extracted from the field | ||
| (unitless; [0, 1]). |
There was a problem hiding this comment.
| (unitless; [0, 1]). | |
| (unitless; [0.0, 1.0]). |
Adds a
pasturecrop type for grazing, modeled after Tall Fescue, whose harvest deposits all cut biomass into the field as residue rather than removing it as harvested yield.Context
Issue(s) closed by this pull request: closes #3131
What
pasturecrop configuration (perennial, based on the Tall Fescue hay parameters) that is available for use in crop rotations.deposit_all_residue_at_harvest(defaultfalse).Why
A pasture crop type is needed so animals can graze. For a grazed crop, forage removal is handled by grazing rather than by the harvest operation, so a "harvest" of a pasture should leave all cut biomass in the field as residue instead of removing it as stored yield.
How
deposit_all_residue_at_harvest: bool = FalsetoCropData, to theCropConfigurationTypedDict (asNotRequired), and to the crop-configuration schema inRUFAS/input/metadata/properties/default.jsonwith"default": false(so the existing configurations auto-fill the field and are unaffected).CropManagement.manage_harvest, when the flag is set the crop is cut withcollected_fraction=0.0and_get_harvested_cropis skipped, so the method returnsNoneand all cut biomass flows to the field as residue via the existing residue-transfer path.pastureconfiguration toinput/data/crop_configurations/default_crop_configs.jsonwith the flag set totrue.manage_harvest/manage_crop_harvestreturn type toHarvestedCrop | None(the method already returnedNonefor kill-only operations) and widens the twofield.pycall-site annotations to match; this also removes a pre-existing mypy error.Test plan
Input Changes
deposit_all_residue_at_harvestboolean (defaultfalse) to each crop configuration undercrop_configuration_properties.pasturecrop configuration toinput/data/crop_configurations/default_crop_configs.json.falsefor all of them.Output Changes
Filter