ALMaSS Vole ODDox  1.1
The vole model description following ODdox protocol
CloverGrassGrazed1.cpp
Go to the documentation of this file.
1 /*
2 *******************************************************************************************************
3 Copyright (c) 2011, Christopher John Topping, University of Aarhus
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided
7 that the following conditions are met:
8 
9 Redistributions of source code must retain the above copyright notice, this list of conditions and the
10 following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
12 the following disclaimer in the documentation and/or other materials provided with the distribution.
13 
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
17 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
19 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 ********************************************************************************************************
23 */
24 
25 //#define __EcoSol_01
26 #define _CRT_SECURE_NO_DEPRECATE
27 //#include "ALMaSS_Setup.h"
28 #include "../../Landscape/ls.h"
29 #include "../../Landscape/cropprogs/CloverGrassGrazed1.h"
30 
31 //---------------------------------------------------------------------------
32 
33 extern CfgFloat cfg_silage_prop;
35 extern CfgInt cfg_pest_productapplic_period;
36 extern CfgFloat cfg_pest_product_1_amount;
37 
38 extern Landscape* g_landscape_p;
39 
40 using namespace std;
41 
42 bool CloverGrassGrazed1::Do( Farm *a_farm, LE *a_field, FarmEvent *a_ev )
43 {
44  m_farm = a_farm;
45  m_field = a_field;
46  m_ev = a_ev;
47  long d1 = 0;
48  int noDates=2;
49  bool done = false;
50 
51  switch ( m_ev->m_todo ) {
52  case cgg1_start:
53 
54  CGG1_WATER_DATE = 0;
55  CGG1_CUT_DATE = 0;
56  CGG1_FERTI_DATE = 0;
59 
60  // Set up the date management stuff
61  m_last_date=g_date->DayInYear(30,9);
62 
63  // Start and stop dates for all events after harvest
64  m_field->SetMDates(0,0,g_date->DayInYear(27,7));
65 
66  // Determined by harvest date - used to see if at all possible
67  m_field->SetMDates(1,0,g_date->DayInYear(27,7));
68  m_field->SetMDates(0,1,g_date->DayInYear(28,7));
69  m_field->SetMDates(1,1,g_date->DayInYear(10,10));
70 
71  // Check the next crop for early start, unless it is a spring crop
72  // in which case we ASSUME that no checking is necessary!!!!
73  // So DO NOT implement a crop that runs over the year boundary
74 
75  //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)
76  if(!(m_farm->GetType() == tof_OptimisingFarm && g_date->GetYearNumber()>0)){
77 
78  if (m_ev->m_startday>g_date->DayInYear(1,7))
79  {
80  if (m_field->GetMDates(0,0) >=m_ev->m_startday)
81  {
82  g_msg->Warn( WARN_BUG, "CloverGrassGrazed1::Do(): "
83  "Harvest too late for the next crop to start!!!", "" );
84  exit( 1 );
85  }
86  // Now fix any late finishing problems
87  for (int i=0; i<noDates; i++) {
88  if(m_field->GetMDates(0,i)>=m_ev->m_startday) {
89  m_field->SetMDates(0,i,m_ev->m_startday-1); //move the starting date
90  }
91  if(m_field->GetMDates(1,i)>=m_ev->m_startday){
92  m_field->SetMConstants(i,0);
93  m_field->SetMDates(1,i,m_ev->m_startday-1); //move the finishing date
94  }
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, "CloverGrassGrazed1::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, "CloverGrassGrazed1::Do(): "
115  "Crop start attempt after last possible start date",
116  "" );
117  exit( 1 );
118 
119  }
120  }
121  }
122  }//if
123  // End single block date checking code. Please see next line
124  // comment as well.
125 
126  // Reinit d1 to first possible starting date.
127  d1 = g_date->OldDays()+m_first_date;;
128  if ( ! m_ev->m_first_year ) d1+=365; // Add 365 for spring crop (not 1st yr)
129  SimpleEvent( d1, cgg1_ferti_zero, false );
130  d1 = g_date->OldDays() + g_date->DayInYear(15, 3);
131  if (!m_ev->m_first_year) d1 += 365; // Add 365 for spring crop (not 1st yr)
132  SimpleEvent(d1, cgg1_ferti_one, false);
133 
134 #ifdef __EcoSol_01
135  // THIS CODE IS ONLY NEEDED IF WE ARE TESTING A HERBICIDE WITH THE PESTICIDE ENGINE
136  /* */
137  if ( g_landscape_p->SupplyShouldSpray() ) {
138  d1 = g_date->OldDays() + cfg_pest_productapplic_startdate.value();
139  if (g_date->Date() >= d1) d1 += 365;
140  SimpleEvent( d1, cgg1_productapplic_one, false );
141  }
142  /* */
143 #endif
144  break;
145 
147  if ( m_ev->m_lock || m_farm->DoIt( 100 ))
148  {
149  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)) {
150  // We didn't do it today, try again tomorrow.
151  SimpleEvent( g_date->Date() + 1, cgg1_productapplic_one, true );
152  break;
153  }
154  }
155  break;
156 
157  case cgg1_ferti_zero:
158  if ( m_ev->m_lock || m_farm->DoIt( 60 ))
159  {
160  if (!m_farm->FA_Slurry( m_field, 0.0, g_date->DayInYear( 30, 4 ) - g_date->DayInYear())) {
161  // We didn't do it today, try again tomorrow.
162  SimpleEvent( g_date->Date() + 1, cgg1_ferti_zero, true );
163  break;
164  }
165  CGG1_FERTI_DATE = g_date->DayInYear();
166  }
167  break; // End of thread
168 
169  case cgg1_ferti_one:
170  m_ev->m_field->SetLastSownVeg(tov_CloverGrassGrazed1); //Force last sown, needed for goose habitat classification
171  m_ev->m_field->SetStubble(false);
172  if (!m_farm->FA_NPK( m_field, 0.0,
173  g_date->DayInYear( 15, 4 ) - g_date->DayInYear())) {
174  // We didn't do it today, try again tomorrow.
175  SimpleEvent( g_date->Date() + 1, cgg1_ferti_one, true );
176  break;
177  }
178  CGG1_FERTI_DATE = g_date->DayInYear();
179 
180 
181  ChooseNextCrop (2);
182 
183  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25,4 ),
184  cgg1_ferti_two, false );
185 
186  // Start a watering thread
187  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 15, 5 ),
188  cgg1_water_zero, false );
189  break;
190 
191  case cgg1_ferti_two:
192  if (!m_farm->FA_NPK( m_field, 0.0,
193  g_date->DayInYear( 10, 5 ) - g_date->DayInYear())) {
194  // We didn't do it today, try again tomorrow.
195  SimpleEvent( g_date->Date() + 1, cgg1_ferti_two, true );
196  break;
197  }
198  CGG1_FERTI_DATE = g_date->DayInYear();
199 
200  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25,5 ),
201  cgg1_cut_to_silage, false );
202  break;
203 
204  case cgg1_cut_to_silage:
205  if ( m_ev->m_lock || m_farm->DoIt(int( cfg_silage_prop.value()* 100 ))) {
206  // At least 7 days from last watering and 21 from
207  // last application of fertilizer.
208  if (g_date->DayInYear()<CGG1_FERTI_DATE+21 ||
209  g_date->DayInYear()<CGG1_WATER_DATE+7
210  ) {
211  SimpleEvent( g_date->Date() + 1, cgg1_cut_to_silage, true );
212  break;
213  }
214  if (!m_farm->CutToSilage( m_field, 0.0,
215  g_date->DayInYear( 10, 6 ) -
216  g_date->DayInYear())) {
217  // We didn't do it today, try again tomorrow.
218  SimpleEvent( g_date->Date() + 1, cgg1_cut_to_silage, true );
219  break;
220  }
221  CGG1_CUT_DATE=g_date->DayInYear();
222 
223  // Decide whether we got for cattle or a second silage cut.
224  // 75% go for the second cut.
225  if ( CGG1_FORCE_SECOND_CUT || m_farm->DoIt( int( cfg_silage_prop.value()*100 ))) { //22.02.2013 - force the cut to have comparable conditions for different years; 75 changed to 100
226  // 75% do Slurry fertilization before second cutting, 25% NPK.
227  if ( m_farm->DoIt( 75 )) {
228  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25, 5 ),
229  cgg1_ferti_three, false );
230  } else {
231  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 25, 5 ),
232  cgg1_ferti_four, false );
233  }
234  break;
235  }
236  }
237 
238  // No second or third silage cut, so go for the cattle.
239  // Prevent the second watering from taking place (if it hasn't
240  // already).
241 
243  SimpleEvent( g_date->OldDays() + g_date->DayInYear( 16, 6 ),
244  cgg1_cattle_out, false );
245  break;
246 
247  case cgg1_cattle_out:
248  if (g_date->DayInYear()<CGG1_CUT_DATE+21) {
249  // Too close to last silage cutting, so try again tomorrow.
250  SimpleEvent( g_date->Date() + 1, cgg1_cattle_out, true );
251  break;
252  }
253  if (m_field->GetMConstants(1)==0) {
254  if (!m_farm->CattleOut( m_field, 0.0, -1)) { //raise an error
255  g_msg->Warn( WARN_BUG, "CloverGrassGrazed1::Do(): failure in 'CattleOut' execution", "" );
256  exit( 1 );
257  }
258  }
259  else {
260  if (!m_farm->CattleOut( m_field, 0.0, m_field->GetMDates(1,1) - g_date->DayInYear())) {
261  SimpleEvent( g_date->Date() + 1, cgg1_cattle_out, true );
262  break;
263  }
264  }
265  // Success
266  // Keep them out there
267  SimpleEvent( g_date->Date()+ m_field->GetMConstants(1), cgg1_cattle_is_out, false );
268  break;
269 
270  case cgg1_cattle_is_out: // Keep the cattle out there
271  // CattleIsOut() returns false if it is not time to stop grazing
272 
273  if (m_field->GetMConstants(1)==0) {
274  if (!m_farm->CattleIsOut( m_field, 0.0, -1, m_field->GetMDates(1,1))) {
275  //added 27.08 - issue a warning only if we fail on the last day that this can be done, i.e. MDate
276  if(g_date->Date() == m_field->GetMDates(1,1)){
277  g_msg->Warn( WARN_BUG, "CloverGrassGrazed1::Do(): failure in 'CattleIsOut' execution", "" );
278  exit( 1 );
279  }
280  SimpleEvent( g_date->Date()+1, cgg1_cattle_is_out, false );
281  break;
282  }
283  }
284  else {
285  if (!m_farm->CattleIsOut( m_field, 0.0, m_field->GetMDates(1,1) - g_date->DayInYear(), m_field->GetMDates(1,1))) {
286  SimpleEvent( g_date->Date()+1, cgg1_cattle_is_out, false );
287  break;
288  }
289  }
290 
291 
292 
293 
294  done=true;
295  break;
296 
297  case cgg1_ferti_three:
298  // The percentage has already been taken care of during
299  // the decisions made under cgg1_cut_to_silage
300  if (!m_farm->FA_Slurry( m_field, 0.0,
301  ( CGG1_CUT_DATE+4 ) - g_date->DayInYear())) {
302  // We didn't do it today, try again tomorrow.
303  SimpleEvent( g_date->Date() + 1, cgg1_ferti_three, true );
304  break;
305  }
306 
307  {
308  // Three weeks later min
309  d1 = g_date->OldDays() + g_date->DayInYear( 16, 6 );
310  if ( d1 < g_date->Date() + 21 )
311  d1 = g_date->Date() + 21;
312  SimpleEvent( d1, cgg1_cut_to_silage2, false );
313  }
314  break;
315 
316  case cgg1_ferti_four:
317  // The percentage has already been taken care of during
318  // the decisions made under cgg1_cut_to_silage
319  if (!m_farm->FA_NPK( m_field, 0.0,
320  ( CGG1_CUT_DATE+4 ) - g_date->DayInYear())) {
321  // We didn't do it today, try again tomorrow.
322  SimpleEvent( g_date->Date() + 1, cgg1_ferti_four, true );
323  break;
324  }
325 
326  {
327  // Three weeks later min
328  d1 = g_date->OldDays() + g_date->DayInYear( 16, 6 );
329  if ( d1 < g_date->Date() + 21 )
330  d1 = g_date->Date() + 21;
331  SimpleEvent( d1, cgg1_cut_to_silage2, false );
332  }
333  break;
334 
335  case cgg1_cut_to_silage2:
336  // The percentage has already been taken care of during
337  // the decisions made under cgg1_cut_to_silage
338  if (!m_farm->CutToSilage( m_field, 0.0,
339  g_date->DayInYear( 6,7 ) -
340  g_date->DayInYear())) {
341  // We didn't do it today, try again tomorrow.
342  SimpleEvent( g_date->Date() + 1, cgg1_cut_to_silage2, true );
343  break;
344  }
345  CGG1_CUT_DATE = g_date->DayInYear();
346 
347  {
348  // Three weeks later min
349  d1 = g_date->OldDays() + g_date->DayInYear( 8, 7 );
350  if ( d1 < g_date->Date() + 21 )
351  d1 = g_date->Date() + 21;
352 
353  if ( m_farm->DoIt(int( cfg_silage_prop.value()* 50 ))) {
354  SimpleEvent( d1, cgg1_cut_to_silage3, false );
355  } else {
356  SimpleEvent( d1, cgg1_cattle_out, false );
357  }
358  }
359  break;
360 
361  case cgg1_cut_to_silage3:
362  // The percentage has already been taken care of during
363  // the decisions made under cgg1_cut_to_silage2
364  if (m_field->GetMConstants(0)==0) {
365  if (!m_farm->CutToSilage( m_field, 0.0, -1)) { //raise an error
366  g_msg->Warn( WARN_BUG, "CloverGrassGrazed1::Do(): failure in 'CutToSilage' execution", "" );
367  exit( 1 );
368  }
369  }
370  else {
371  if (!m_farm->CutToSilage( m_field, 0.0, m_field->GetMDates(0,0) - g_date->DayInYear())) {
372  // We didn't do it today, try again tomorrow.
373  SimpleEvent( g_date->Date() + 1, cgg1_cut_to_silage3, true );
374  break;
375  }
376  }
377  CGG1_CUT_DATE = g_date->DayInYear();
378 
379  {
380  // Three weeks later min
381  d1 = g_date->OldDays() + g_date->DayInYear( 28, 7 );
382  if ( d1 < g_date->Date() + 21 )
383  d1 = g_date->Date() + 21;
384  if ( d1 < m_field->GetMDates(0,1))
385  d1 = m_field->GetMDates(0,1);
386  SimpleEvent( d1, cgg1_cattle_out, false );
387  }
388  break;
389 
390  case cgg1_water_zero:
391  if ( m_ev->m_lock || m_farm->DoIt( 40 ))
392  {
393  if ( g_date->Date() < CGG1_CUT_DATE + 3 ) {
394  // Too close to silage cutting, so try again tomorrow.
395  SimpleEvent( g_date->Date() + 1, cgg1_water_zero, true );
396  }
397 
398  if (!m_farm->Water( m_field, 0.0,
399  g_date->DayInYear( 1, 6 ) - g_date->DayInYear())) {
400  // We didn't do it today, try again tomorrow.
401  SimpleEvent( g_date->Date() + 1, cgg1_water_zero, true );
402  break;
403  }
404  // Success
405  CGG1_WATER_DATE=g_date->DayInYear();
406 
407  // Determine whether we want to do the second watering.
408  // If so, then force the second silage cutting as well.
409 
410  if ( m_farm->DoIt( 40 ) && !CGG1_HALT_SECOND_WATER ) {
411  // Do second watering.
413  d1 = g_date->OldDays() + g_date->DayInYear( 2,6 );
414  if ( d1 < g_date->Date() + 7 )
415  d1 = g_date->Date() + 7;
416  SimpleEvent( d1, cgg1_water_one, false );
417  }
418  }
419  // Didn't water so let the thread die
420  break;
421 
422  case cgg1_water_one:
423  if ( g_date->Date() < CGG1_CUT_DATE + 3 ) {
424  // Too close to silage cutting, so try again tomorrow.
425  SimpleEvent( g_date->Date() + 1, cgg1_water_one, true );
426  }
427 
428  if (!m_farm->Water( m_field, 0.0,
429  g_date->DayInYear( 30, 6 ) -
430  g_date->DayInYear())) {
431  // We didn't do it today, try again tomorrow.
432  SimpleEvent( g_date->Date() + 1, cgg1_water_one, true );
433  break;
434  }
435  CGG1_WATER_DATE=g_date->DayInYear();
436  break;
437  // End of watering thread
438 
439  default:
440  g_msg->Warn( WARN_BUG, "CloverGrassGrazed1::Do(): "
441  "Unknown event type! ", "" );
442  exit( 1 );
443  }
444  return done;
445 }
446 //---------------------------------------------------------------------------
cgg1_ferti_three
Definition: CloverGrassGrazed1.h:40
cgg1_water_zero
Definition: CloverGrassGrazed1.h:45
cfg_pest_productapplic_startdate
CfgInt cfg_pest_productapplic_startdate
CGG1_FORCE_SECOND_CUT
#define CGG1_FORCE_SECOND_CUT
Definition: CloverGrassGrazed1.h:31
Landscape::SupplyShouldSpray
bool SupplyShouldSpray()
Definition: Landscape.h:357
FarmEvent
A struct to hold the information required to trigger a farm event.
Definition: farm.h:463
cgg1_cattle_out
Definition: CloverGrassGrazed1.h:47
tof_OptimisingFarm
Definition: farm.h:273
cgg1_ferti_two
Definition: CloverGrassGrazed1.h:39
cgg1_start
Definition: CloverGrassGrazed1.h:36
CGG1_HALT_SECOND_WATER
#define CGG1_HALT_SECOND_WATER
Definition: CloverGrassGrazed1.h:32
cgg1_ferti_one
Definition: CloverGrassGrazed1.h:38
Landscape
The landscape class containing all environmental and topographical data.
Definition: Landscape.h:112
CloverGrassGrazed1::Do
bool Do(Farm *a_farm, LE *a_field, FarmEvent *a_ev)
Definition: CloverGrassGrazed1.cpp:42
g_landscape_p
Landscape * g_landscape_p
Definition: Landscape.cpp:258
cfg_pest_product_1_amount
CfgFloat cfg_pest_product_1_amount
cgg1_ferti_four
Definition: CloverGrassGrazed1.h:41
cgg1_cut_to_silage
Definition: CloverGrassGrazed1.h:42
cgg1_cattle_is_out
Definition: CloverGrassGrazed1.h:48
CGG1_CUT_DATE
#define CGG1_CUT_DATE
Definition: CloverGrassGrazed1.h:28
ppp_1
Definition: farm.h:422
cgg1_water_one
Definition: CloverGrassGrazed1.h:46
cgg1_cut_to_silage2
Definition: CloverGrassGrazed1.h:43
cfg_pest_productapplic_period
CfgInt cfg_pest_productapplic_period
cgg1_productapplic_one
Definition: CloverGrassGrazed1.h:49
CGG1_WATER_DATE
#define CGG1_WATER_DATE
Definition: CloverGrassGrazed1.h:29
Farm
The base class for all farm types.
Definition: farm.h:767
CGG1_FERTI_DATE
#define CGG1_FERTI_DATE
Definition: CloverGrassGrazed1.h:30
tov_CloverGrassGrazed1
Definition: tov_declaration.h:32
cgg1_cut_to_silage3
Definition: CloverGrassGrazed1.h:44
cfg_silage_prop
CfgFloat cfg_silage_prop
cgg1_ferti_zero
Definition: CloverGrassGrazed1.h:37