ALMaSS Vole ODDox  1.1
The vole model description following ODdox protocol
FodderGrass.cpp
Go to the documentation of this file.
1 //
2 // Fodder.cpp
3 //
4 /*
5 *******************************************************************************************************
6 Copyright (c) 2011, Christopher John Topping, University of Aarhus
7 All rights reserved.
8 
9 Redistribution and use in source and binary forms, with or without modification, are permitted provided
10 that the following conditions are met:
11 
12 Redistributions of source code must retain the above copyright notice, this list of conditions and the
13 following disclaimer.
14 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
15 the following disclaimer in the documentation and/or other materials provided with the distribution.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
20 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 ********************************************************************************************************
26 */
27 
28 //#define __EcoSol_01
29 #define _CRT_SECURE_NO_DEPRECATE
30 #include "../../BatchALMaSS/ALMaSS_Setup.h"
31 #include "../../Landscape/ls.h"
32 #include "../../Landscape/cropprogs/FodderGrass.h"
33 
34 //---------------------------------------------------------------------------
35 
36 extern CfgFloat cfg_silage_prop;
38 extern CfgInt cfg_pest_productapplic_period;
39 extern CfgFloat cfg_pest_product_1_amount;
40 
41 extern Landscape* g_landscape_p;
42 
43 using namespace std;
44 
45 bool FodderGrass::Do( Farm *a_farm, LE *a_field, FarmEvent *a_ev )
46 {
47  m_farm = a_farm;
48  m_field = a_field;
49  m_ev = a_ev;
50  long d1 = 0;
51  int noDates=2;
52  bool done = false;
53 
54  switch ( m_ev->m_todo ) {
55  case fg_start:
56 
57  FG_WATER_DATE = 0;
58  FG_CUT_DATE = 0;
59  FG_FERTI_DATE = 0;
62 
63  // Set up the date management stuff
64  m_last_date=g_date->DayInYear(30,9);
65 
66  // Start and stop dates for all events after harvest
67  m_field->SetMDates(0,0,g_date->DayInYear(27,7));
68 
69  // Determined by harvest date - used to see if at all possible
70  m_field->SetMDates(1,0,g_date->DayInYear(27,7));
71  m_field->SetMDates(0,1,g_date->DayInYear(28,7));
72  m_field->SetMDates(1,1,g_date->DayInYear(10,10));
73 
74  // Check the next crop for early start, unless it is a spring crop
75  // in which case we ASSUME that no checking is necessary!!!!
76  // So DO NOT implement a crop that runs over the year boundary
77 
78  //new if: do the check only for non-optimising farms and if year>0. (030713 - m_rotation used only in the hidden year, so I modified the condition from >7 to >0)
79  if(!(m_farm->GetType() == tof_OptimisingFarm && g_date->GetYearNumber()>0)){
80 
81  if (m_ev->m_startday>g_date->DayInYear(1,7))
82  {
83  if (m_field->GetMDates(0,0) >=m_ev->m_startday)
84  {
85  g_msg->Warn( WARN_BUG, "FodderGrass::Do(): "
86  "Harvest too late for the next crop to start!!!", "" );
87  exit( 1 );
88  }
89  // Now fix any late finishing problems
90  for (int i=0; i<noDates; i++) {
91  if (m_field->GetMDates(0,i)>=m_ev->m_startday)
92  m_field->SetMDates(0,i,m_ev->m_startday-1);
93  if (m_field->GetMDates(1,i)>=m_ev->m_startday)
94  m_field->SetMDates(1,i,m_ev->m_startday-1);
95  }
96  }
97 
98  // Now no operations can be timed after the start of the next crop.
99  if ( ! m_ev->m_first_year ) {
100  // Are we before July 1st?
101  d1 = g_date->OldDays() + g_date->DayInYear( 1,7 );
102 
103  if (g_date->Date() < d1) {
104  // Yes, too early. We assumme this is because the last crop was late
105  g_msg->Warn( WARN_BUG, "FodderGrass::Do(): "
106  "Crop start attempt between 1st Jan & 1st July", "" );
107  exit( 1 );
108 
109  } else {
110 
111  d1 = g_date->OldDays() + m_first_date+365; // Add 365 for spring crop
112  if (g_date->Date() > d1) {
113  // Yes too late - should not happen - raise an error
114  g_msg->Warn( WARN_BUG, "FodderGrass::Do(): "
115  "Crop start attempt after last possible start date",
116  "" );
117  exit( 1 );
118 
119  }
120  }
121  }
122  }//if
123 
124  // End single block date checking code. Please see next line
125  // comment as well.
126 
127  // Reinit d1 to first possible starting date.
128  d1 = g_date->OldDays()+m_first_date;;
129  if ( ! m_ev->m_first_year ) d1+=365; // Add 365 for spring crop (not 1st yr)
130  SimpleEvent( d1, fg_ferti_zero, false );
131 
132  d1 = g_date->OldDays() + g_date->DayInYear( 15, 3 );
133  if (g_date->Date() >= d1) d1 += 365;
134  SimpleEvent( d1, fg_ferti_one, false );
135 
136 #ifdef __EcoSol_01
137  // THIS CODE IS ONLY NEEDED IF WE ARE TESTING A HERBICIDE WITH THE PESTICIDE ENGINE
138  /* */
139  if ( g_landscape_p->SupplyShouldSpray() ) {
140  d1 = g_date->OldDays() + cfg_pest_productapplic_startdate.value();
141  if (g_date->Date() >= d1) d1 += 365;
142  SimpleEvent( d1, fg_productapplic_one, false );
143  }
144  /* */
145 #endif
146  break;
147 
149  if ( m_ev->m_lock || m_farm->DoIt( 100 ))
150  {
151  if (!m_farm->ProductApplication( m_field, 0.0,(cfg_pest_productapplic_startdate.value()+cfg_pest_productapplic_period.value()) - g_date->DayInYear(), cfg_pest_product_1_amount.value(), ppp_1)) {
152  // We didn't do it today, try again tomorrow.
153  SimpleEvent( g_date->Date() + 1, fg_productapplic_one, true );
154  break;
155  }
156  }
157  break;
158 
159  case fg_ferti_zero:
160  if ( m_ev->m_lock || m_farm->DoIt( 60 ))
161  {
162  if (!m_farm->FA_Slurry( m_field, 0.0,
163  g_date->DayInYear( 30, 4 ) - g_date->DayInYear())) {
164  // We didn't do it today, try again tomorrow.
165  SimpleEvent( g_date->Date() + 1, fg_ferti_zero, true );
166  break;
167  }
168  FG_FERTI_DATE = g_date->DayInYear();
169  }
170 
171  // This used to be broken, but is now outdated, as fg_ferti_one
172  // now is the main thread of execution. FN 15/5, 2003.
173  // Note: The line should have read: g_date->OldDays() + ...
174  //SimpleEvent( g_date->Date()+ g_date->DayInYear( 15,3 ),
175  break;
176 
177  case fg_ferti_one:
178  if (!m_farm->FA_NPK( m_field, 0.0,
179  g_date->DayInYear( 15, 4 ) - g_date->DayInYear())) {
180  // We didn't do it today, try again tomorrow.
181  SimpleEvent( g_date->Date() + 1, fg_ferti_one, true );
182  break;
183  }
184  FG_FERTI_DATE = g_date->DayInYear();
185 
186  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25,4 ),
187  fg_ferti_two, false );
188 
189  // Start a watering thread
190  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 15, 5 ),
191  fg_water_zero, false );
192  break;
193 
194  case fg_ferti_two:
195  if (!m_farm->FA_NPK( m_field, 0.0,
196  g_date->DayInYear( 10, 5 ) - g_date->DayInYear())) {
197  // We didn't do it today, try again tomorrow.
198  SimpleEvent( g_date->Date() + 1, fg_ferti_two, true );
199  break;
200  }
201  FG_FERTI_DATE = g_date->DayInYear();
202 
203  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25,5 ),
204  fg_cut_to_silage, false );
205  break;
206 
207  case fg_cut_to_silage:
208  if ( m_ev->m_lock || m_farm->DoIt( 100 )) {
209  // At least 7 days from last watering and 21 from
210  // last application of fertilizer.
211  if (g_date->DayInYear()<FG_FERTI_DATE+21 ||
212  g_date->DayInYear()<FG_WATER_DATE+7
213  ) {
214  SimpleEvent( g_date->Date() + 1, fg_cut_to_silage, true );
215  break;
216  }
217  if (!m_farm->CutToSilage( m_field, 0.0,
218  g_date->DayInYear( 10, 6 ) -
219  g_date->DayInYear())) {
220  // We didn't do it today, try again tomorrow.
221  SimpleEvent( g_date->Date() + 1, fg_cut_to_silage, true );
222  break;
223  }
224  FG_CUT_DATE=g_date->DayInYear();
225 
226  // Decide whether we got for cattle or a second silage cut.
227  // 75% go for the second cut.
228  if ( FG_FORCE_SECOND_CUT || m_farm->DoIt( 100 )) {
229  // 75% do Slurry fertilization before second cutting, 25% NPK.
230  if ( m_farm->DoIt( 75 )) {
231  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25, 5 ),
232  fg_ferti_three, false );
233  } else {
234  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25, 5 ),
235  fg_ferti_four, false );
236  }
237  break;
238  }
239  }
240  break; // Should never get here without setting up the next silage cut
241 
242  case fg_ferti_three:
243  // The percentage has already been taken care of during
244  // the decisions made under fg_cut_to_silage
245  if (!m_farm->FA_Slurry( m_field, 0.0,
246  ( FG_CUT_DATE+4 ) - g_date->DayInYear())) {
247  // We didn't do it today, try again tomorrow.
248  SimpleEvent( g_date->Date() + 1, fg_ferti_three, true );
249  break;
250  }
251 
252  {
253  // Three weeks later min
254  d1 = g_date->OldDays() + g_date->DayInYear( 16, 6 );
255  if ( d1 < g_date->Date() + 21 )
256  d1 = g_date->Date() + 21;
257  SimpleEvent( d1, fg_cut_to_silage2, false );
258  }
259  break;
260 
261  case fg_ferti_four:
262  // The percentage has already been taken care of during
263  // the decisions made under fg_cut_to_silage
264  if (!m_farm->FA_NPK( m_field, 0.0,
265  ( FG_CUT_DATE+4 ) - g_date->DayInYear())) {
266  // We didn't do it today, try again tomorrow.
267  SimpleEvent( g_date->Date() + 1, fg_ferti_four, true );
268  break;
269  }
270 
271  {
272  // Three weeks later min
273  d1 = g_date->OldDays() + g_date->DayInYear( 16, 6 );
274  if ( d1 < g_date->Date() + 21 )
275  d1 = g_date->Date() + 21;
276  SimpleEvent( d1, fg_cut_to_silage2, false );
277  }
278  break;
279 
280  case fg_cut_to_silage2:
281  // The percentage has already been taken care of during
282  // the decisions made under fg_cut_to_silage
283  if (!m_farm->CutToSilage( m_field, 0.0,
284  g_date->DayInYear( 6,7 ) -
285  g_date->DayInYear())) {
286  // We didn't do it today, try again tomorrow.
287  SimpleEvent( g_date->Date() + 1, fg_cut_to_silage2, true );
288  break;
289  }
290  FG_CUT_DATE = g_date->DayInYear();
291 
292  {
293  // Three weeks later min
294  d1 = g_date->OldDays() + g_date->DayInYear( 8, 7 );
295  if ( d1 < g_date->Date() + 21 )
296  d1 = g_date->Date() + 21;
297 
298  ChooseNextCrop (2);
299 
300  SimpleEvent( d1, fg_cut_to_silage3, false );
301  }
302  break;
303 
304  case fg_cut_to_silage3:
305  // The percentage has already been taken care of during
306  // the decisions made under fg_cut_to_silage2
307  if (!m_farm->CutToSilage( m_field, 0.0,
308  m_field->GetMDates(0,0) -
309  g_date->DayInYear())) {
310  // We didn't do it today, try again tomorrow.
311  SimpleEvent( g_date->Date() + 1, fg_cut_to_silage3, true );
312  break;
313  }
314  FG_CUT_DATE = g_date->DayInYear();
315  done=true;
316  break;
317 
318  case fg_water_zero:
319  if ( m_ev->m_lock || m_farm->DoIt( 40 ))
320  {
321  if ( g_date->Date() < FG_CUT_DATE + 3 ) {
322  // Too close to silage cutting, so try again tomorrow.
323  SimpleEvent( g_date->Date() + 1, fg_water_zero, true );
324  }
325 
326  if (!m_farm->Water( m_field, 0.0,
327  g_date->DayInYear( 1, 6 ) - g_date->DayInYear())) {
328  // We didn't do it today, try again tomorrow.
329  SimpleEvent( g_date->Date() + 1, fg_water_zero, true );
330  break;
331  }
332  // Success
333  FG_WATER_DATE=g_date->DayInYear();
334 
335  // Determine whether we want to do the second watering.
336  // If so, then force the second silage cutting as well.
337 
338  if ( m_farm->DoIt( 40 ) && !FG_HALT_SECOND_WATER ) {
339  // Do second watering.
341  d1 = g_date->OldDays() + g_date->DayInYear( 2,6 );
342  if ( d1 < g_date->Date() + 7 )
343  d1 = g_date->Date() + 7;
344  SimpleEvent( d1, fg_water_one, false );
345  }
346  }
347  // Didn't water so let the thread die
348  break;
349 
350  case fg_water_one:
351  if ( g_date->Date() < FG_CUT_DATE + 3 ) {
352  // Too close to silage cutting, so try again tomorrow.
353  SimpleEvent( g_date->Date() + 1, fg_water_one, true );
354  }
355 
356  if (!m_farm->Water( m_field, 0.0,
357  g_date->DayInYear( 30, 6 ) -
358  g_date->DayInYear())) {
359  // We didn't do it today, try again tomorrow.
360  SimpleEvent( g_date->Date() + 1, fg_water_one, true );
361  break;
362  }
363  FG_WATER_DATE=g_date->DayInYear();
364  break;
365  // End of watering thread
366 
367  default:
368  g_msg->Warn( WARN_BUG, "FodderGrass::Do(): "
369  "Unknown event type! ", "" );
370  exit( 1 );
371  }
372  return done;
373 }
374 //---------------------------------------------------------------------------
FG_WATER_DATE
#define FG_WATER_DATE
Definition: FodderGrass.h:32
fg_cut_to_silage3
Definition: FodderGrass.h:47
Landscape::SupplyShouldSpray
bool SupplyShouldSpray()
Definition: Landscape.h:357
fg_ferti_four
Definition: FodderGrass.h:44
FarmEvent
A struct to hold the information required to trigger a farm event.
Definition: farm.h:463
tof_OptimisingFarm
Definition: farm.h:273
fg_productapplic_one
Definition: FodderGrass.h:50
fg_water_zero
Definition: FodderGrass.h:48
fg_cut_to_silage2
Definition: FodderGrass.h:46
cfg_pest_productapplic_period
CfgInt cfg_pest_productapplic_period
cfg_pest_productapplic_startdate
CfgInt cfg_pest_productapplic_startdate
fg_ferti_two
Definition: FodderGrass.h:42
fg_water_one
Definition: FodderGrass.h:49
Landscape
The landscape class containing all environmental and topographical data.
Definition: Landscape.h:112
fg_cut_to_silage
Definition: FodderGrass.h:45
FG_CUT_DATE
#define FG_CUT_DATE
Definition: FodderGrass.h:31
g_landscape_p
Landscape * g_landscape_p
Definition: Landscape.cpp:258
FG_HALT_SECOND_WATER
#define FG_HALT_SECOND_WATER
Definition: FodderGrass.h:35
ppp_1
Definition: farm.h:422
Farm
The base class for all farm types.
Definition: farm.h:767
fg_ferti_zero
Definition: FodderGrass.h:40
fg_ferti_one
Definition: FodderGrass.h:41
cfg_pest_product_1_amount
CfgFloat cfg_pest_product_1_amount
FG_FORCE_SECOND_CUT
#define FG_FORCE_SECOND_CUT
Definition: FodderGrass.h:34
cfg_silage_prop
CfgFloat cfg_silage_prop
FG_FERTI_DATE
#define FG_FERTI_DATE
Definition: FodderGrass.h:33
FodderGrass::Do
bool Do(Farm *a_farm, LE *a_field, FarmEvent *a_ev)
Definition: FodderGrass.cpp:45
fg_start
Definition: FodderGrass.h:39
fg_ferti_three
Definition: FodderGrass.h:43