-
Notifications
You must be signed in to change notification settings - Fork 25
[Crop and Soil] Enable crop and soil only simulation run #2932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
2bed6d5
e868d0d
45f5495
31a3249
81e3c96
fd33f8f
1cea3bb
c23078c
88522d4
2d74255
2be5a5c
3f81d92
f269a2c
368935a
bb4b63f
6b93d7b
e3024df
3e9212d
cffe1a5
2c11dcf
dfc46c3
114c46f
d130f10
4282c4d
27f0566
9c9f991
5915db4
ade0c02
ec65507
f5f8ff1
0391a47
3e9b2d0
a31591f
27d9be5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,7 @@ | |
| from RUFAS.data_structures.animal_to_manure_connection import ManureStream | ||
| from RUFAS.data_structures.crop_soil_to_feed_storage_connection import HarvestedCrop | ||
| from RUFAS.data_structures.feed_storage_to_animal_connection import NutrientStandard | ||
| from RUFAS.data_structures.field_manure_supplier import FieldManureSupplier | ||
| from RUFAS.data_structures.manure_to_crop_soil_connection import ManureEventNutrientRequestResults | ||
| from RUFAS.input_manager import InputManager | ||
| from RUFAS.output_manager import OutputManager | ||
|
|
@@ -36,6 +37,8 @@ class SimulationType(Enum): | |
|
|
||
| FULL_FARM = "full_farm" | ||
| FIELD_AND_FEED = "field_and_feed" | ||
| FIELD_ONLY = "field_only" | ||
| FIELD_WITH_STORAGE = "field_with_storage" | ||
|
|
||
| @property | ||
| def simulate_animals(self) -> bool: | ||
|
|
@@ -47,6 +50,8 @@ def _non_animal_simulation_types(cls) -> set["SimulationType"]: | |
| """Return the set of simulation types that do not simulate animals.""" | ||
| return { | ||
| cls.FIELD_AND_FEED, | ||
| cls.FIELD_ONLY, | ||
| cls.FIELD_WITH_STORAGE, | ||
| } | ||
|
|
||
| @classmethod | ||
|
|
@@ -110,6 +115,8 @@ def __init__(self, simulation_type: SimulationType) -> None: | |
| self._simulation_type_to_daily_simulation_function = { | ||
| SimulationType.FULL_FARM: self._execute_full_farm_daily_simulation, | ||
| SimulationType.FIELD_AND_FEED: self._execute_field_and_feed_daily_simulation, | ||
| simulation_type.FIELD_ONLY: self._execute_field_only_simulation, | ||
| simulation_type.FIELD_WITH_STORAGE: self._execute_field_with_storage_simulation, | ||
| } | ||
|
|
||
| self._initialize_simulation() | ||
|
|
@@ -211,7 +218,7 @@ def _execute_full_farm_daily_simulation(self) -> None: | |
| 7. Advance simulation date | ||
|
|
||
| """ | ||
| daily_harvested_crops = self._execute_daily_field_operations() | ||
| daily_harvested_crops = self._execute_daily_field_with_storage_operations() | ||
|
|
||
| harvest_schedule = self._build_harvest_schedule(daily_harvested_crops) | ||
| self._execute_feed_planning(harvest_schedule) | ||
|
|
@@ -226,6 +233,38 @@ def _execute_full_farm_daily_simulation(self) -> None: | |
|
|
||
| self._advance_time() | ||
|
|
||
| def _execute_field_with_storage_simulation(self) -> None: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does this differ from the
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The intent was to have an option where ration formulation was not performed, requiring no animal or nutritiion inputs
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should probably be doing this in |
||
| """ | ||
| Executes the daily simulation routines for a farm with only the field and storage modules. | ||
|
|
||
| Daily Field With Storage Simulation Process: | ||
| 1. Field operations (manure applications, harvesting) | ||
| 2. Record keeping (time, weather, purchased feeds fed emissions) | ||
| 3. Advance simulation date | ||
|
|
||
| """ | ||
| self._execute_daily_field_with_storage_operations() | ||
|
|
||
| self._report_daily_records() | ||
|
|
||
| self._advance_time() | ||
|
|
||
| def _execute_field_only_simulation(self) -> None: | ||
| """ | ||
| Executes the daily simulation routines for a field only modules. | ||
|
|
||
| Daily Field Process: | ||
| 1. Field operations without sending the crops to the feed manager | ||
| 2. Record keeping (time, weather, purchased feeds fed emissions) | ||
| 3. Advance simulation date | ||
|
|
||
| """ | ||
| self._execute_daily_field_only_operations() | ||
|
|
||
| self._report_daily_records() | ||
|
|
||
| self._advance_time() | ||
|
|
||
| def _execute_field_and_feed_daily_simulation(self) -> None: | ||
| """ | ||
| Executes the daily simulation routines for a farm with only the field and feed modules. | ||
|
|
@@ -239,7 +278,7 @@ def _execute_field_and_feed_daily_simulation(self) -> None: | |
| 5. Advance simulation date | ||
|
|
||
| """ | ||
| daily_harvested_crops = self._execute_daily_field_operations() | ||
| daily_harvested_crops = self._execute_daily_field_with_storage_operations() | ||
|
|
||
| harvest_schedule = self._build_harvest_schedule(daily_harvested_crops) | ||
| self._execute_feed_planning(harvest_schedule) | ||
|
|
@@ -250,13 +289,20 @@ def _execute_field_and_feed_daily_simulation(self) -> None: | |
|
|
||
| self._advance_time() | ||
|
|
||
| def _execute_daily_field_operations(self) -> list[HarvestedCrop]: | ||
| """Handles daily field operations including manure applications and crop harvesting/receiving.""" | ||
| def _execute_daily_field_only_operations(self) -> list[HarvestedCrop]: | ||
| """Handles daily field operations including manure applications.""" | ||
| manure_applications: list[ManureEventNutrientRequestResults] = self.generate_daily_manure_applications() | ||
|
|
||
| harvested_crops: list[HarvestedCrop] = self.field_manager.daily_update_routine( | ||
| self.weather, self.time, manure_applications | ||
| ) | ||
|
|
||
| return harvested_crops | ||
|
|
||
| def _execute_daily_field_with_storage_operations(self) -> list[HarvestedCrop]: | ||
| """Handles daily field operations including manure applications and crop harvesting/receiving.""" | ||
| harvested_crops: list[HarvestedCrop] = self._execute_daily_field_only_operations() | ||
|
|
||
| for crop in harvested_crops: | ||
| self.feed_manager.receive_crop(crop, self.time.simulation_day) | ||
|
|
||
|
|
@@ -279,9 +325,7 @@ def generate_daily_manure_applications(self) -> list[ManureEventNutrientRequestR | |
| manure_request = manure_event_request.nutrient_request | ||
| manure_request_results = None | ||
| if manure_request is not None: | ||
| manure_request_results = self.manure_manager.request_nutrients( | ||
| manure_request, self.simulate_animals, self.time | ||
| ) | ||
| manure_request_results = FieldManureSupplier.request_nutrients(manure_request) | ||
| manure_applications.append(ManureEventNutrientRequestResults(field_name, event, manure_request_results)) | ||
| return manure_applications | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "start_date": "2013:1", | ||
| "end_date": "2019:365", | ||
| "random_seed": 42, | ||
| "set_seed": true, | ||
| "simulation_type": "field_only", | ||
| "nutrient_standard": "NASEM", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we discussed, |
||
| "FIPS_county_code": 55025, | ||
| "include_detailed_values": false | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "start_date": "2013:1", | ||
| "end_date": "2019:365", | ||
| "random_seed": 42, | ||
| "set_seed": true, | ||
| "simulation_type": "field_with_storage", | ||
| "nutrient_standard": "NASEM", | ||
| "FIPS_county_code": 55025, | ||
| "include_detailed_values": false | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| { | ||
| "parallel_workers": 4, | ||
| "input_data_csv_export_path": "output/saved_input_data/.", | ||
| "input_data_csv_import_path": ".", | ||
| "export_input_data_to_csv": false, | ||
| "tasks": [ | ||
| { | ||
| "task_type": "SIMULATION_SINGLE_RUN", | ||
| "metadata_file_path": "input/metadata/example_field_only_metadata.json", | ||
| "output_prefix": "field_only", | ||
| "log_verbosity": "errors", | ||
| "random_seed": 42, | ||
| "SA_load_balancing_stop": 1, | ||
| "SA_load_balancing_start": 0, | ||
| "sampler_n": 2, | ||
| "skip_values": 0, | ||
| "sampler": "sobol", | ||
| "multi_run_counts": 4, | ||
| "maximum_memory_usage_percent": 80, | ||
| "maximum_memory_usage": 0, | ||
| "save_chunk_threshold_call_count": 0, | ||
| "chunkification": false, | ||
| "suppress_log_files": false, | ||
| "logs_directory": "output/logs/.", | ||
| "properties_file_path": "input/metadata/properties/default.json", | ||
| "comparison_properties_file_path": "input/metadata/properties/default.json", | ||
| "variable_name_style": "basic", | ||
| "exclude_info_maps": false, | ||
| "init_herd": false, | ||
| "save_animals": false, | ||
| "save_animals_directory": "output/.", | ||
| "filters_directory": "output/output_filters/.", | ||
| "csv_output_directory": "output/CSVs/.", | ||
| "json_output_directory": "output/JSONs/.", | ||
| "report_directory": "output/reports/.", | ||
| "graphics_directory": "output/graphics/.", | ||
| "cross_validation_file_paths": [] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| { | ||
| "parallel_workers": 4, | ||
| "input_data_csv_export_path": "output/saved_input_data/.", | ||
| "input_data_csv_import_path": ".", | ||
| "export_input_data_to_csv": false, | ||
| "tasks": [ | ||
| { | ||
| "task_type": "SIMULATION_SINGLE_RUN", | ||
| "metadata_file_path": "input/metadata/example_field_with_storage_metadata.json", | ||
| "output_prefix": "field_only", | ||
| "log_verbosity": "errors", | ||
| "random_seed": 42, | ||
| "SA_load_balancing_stop": 1, | ||
| "SA_load_balancing_start": 0, | ||
| "sampler_n": 2, | ||
| "skip_values": 0, | ||
| "sampler": "sobol", | ||
| "multi_run_counts": 4, | ||
| "maximum_memory_usage_percent": 80, | ||
| "maximum_memory_usage": 0, | ||
| "save_chunk_threshold_call_count": 0, | ||
| "chunkification": false, | ||
| "suppress_log_files": false, | ||
| "logs_directory": "output/logs/.", | ||
| "properties_file_path": "input/metadata/properties/default.json", | ||
| "comparison_properties_file_path": "input/metadata/properties/default.json", | ||
| "variable_name_style": "basic", | ||
| "exclude_info_maps": false, | ||
| "init_herd": false, | ||
| "save_animals": false, | ||
| "save_animals_directory": "output/.", | ||
| "filters_directory": "output/output_filters/.", | ||
| "csv_output_directory": "output/CSVs/.", | ||
| "json_output_directory": "output/JSONs/.", | ||
| "report_directory": "output/reports/.", | ||
| "graphics_directory": "output/graphics/.", | ||
| "cross_validation_file_paths": [] | ||
| } | ||
| ] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for these simulations where we're isolating single parts of the model we want to be sure they can run without any other parts of the model being initialized.
FIELD_ONLYstill depends on a Manure module. I know we'd talked about how to get manure applications out of the Manure module potentially - did you look into that at all?I'm working on something that was initially separating out feed management from ration planning but has grown into initializing only modules that should be required for the simulation being run by the user. Maybe we can take a look at it and see how it can fit together with this.