ALMaSS Rabbit ODdox  1.00
The rabbit model description following ODdox protocol
pesticide.cpp
Go to the documentation of this file.
1 //
2 // pesticide.cpp
3 //
4 /*
5 *******************************************************************************************************
6 Copyright (c) 2003, Christopher John Topping, EcoSol
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 _CRT_SECURE_NO_DEPRECATE
29 //#define __WithinOrchardPesticideSim__
30 
31 #include <vector>
32 #include <cstdio> // Only needed for debugging purposes.
33 #include <math.h>
34 #include <iostream>
35 #include <fstream>
36 #include "ls.h"
37 
38 using namespace std;
39 
40 CfgBool l_pest_enable_pesticide_engine( "PEST_ENABLE_PESTICIDE_ENGINE",CFG_CUSTOM, false );
41 static CfgFloat l_pest_ai_half_life("PEST_AI_HALF_LIFE", CFG_CUSTOM, 10.0);
42 static CfgFloat l_pest_ai_half_life_Soil("PEST_AI_HALF_LIFE_SOIL", CFG_CUSTOM, 10.0);
43 static CfgFloat l_pest_ai_half_life_Veg("PEST_AI_HALF_LIFE_VEG", CFG_CUSTOM, 10.0);
44 static CfgFloat l_pest_diffusion_slope("PEST_DRIFT_SLOPE", CFG_CUSTOM, -0.6122);
45 static CfgInt l_pest_diffusion_grid_count("PEST_DIFFUSION_GRID_COUNT",CFG_CUSTOM, 1 );
46 static CfgFloat l_pest_zero_threshold("PEST_ZERO_THRESHOLD",CFG_CUSTOM, 0.00001 );
47 CfgFloat l_pest_insecticide_amount("PEST_INSECTICIDE_AMOUNT",CFG_CUSTOM, 0.00 );
48 CfgFloat l_pest_product_0_amount("PEST_PRODUCT_ZERO_AMOUNT",CFG_CUSTOM, 0.004145 );
49 CfgFloat l_pest_product_1_amount("PEST_PRODUCT_ONE_AMOUNT", CFG_CUSTOM, 0.004145);
50 CfgBool l_pest_use_application_rate("PEST_USE_APPLICATIONRATE", CFG_CUSTOM, false);
51 CfgFloat l_pest_daily_mort( "PEST_DAILY_MORTALITY", CFG_CUSTOM, 0.25 );
52 CfgFloat l_pest_daily_mort2( "PEST_DAILY_MORTALITY_TWO", CFG_CUSTOM, 0.25 );
55 CfgFloat l_pest_trigger_threshold1( "PEST_TRIGGER_THRESHOLD_ONE", CFG_CUSTOM, 1.0 );
56 CfgFloat l_pest_trigger_threshold2( "PEST_TRIGGER_THRESHOLD_TWO", CFG_CUSTOM, 1.0 );
57 
58 CfgInt cfg_pest_productapplic_startdate("PEST_PRODUCTAPPLIC_STARTDATE", CFG_CUSTOM, -1);
59 CfgInt cfg_pest_productapplic_startdate2("PEST_PRODUCTAPPLIC_STARTDATE_TWO",CFG_CUSTOM,-1);
60 CfgInt cfg_pest_productapplic_startdate3("PEST_PRODUCTAPPLIC_STARTDATE_THREE",CFG_CUSTOM,-1);
61 CfgInt cfg_pest_productapplic_period("PEST_PRODUCTAPPLIC_PERIOD",CFG_CUSTOM,1);
62 
63 CfgBool cfg_pest_residue_or_rate("PEST_RESIDUE_OR_RATE",CFG_CUSTOM,true);
64 
65 CfgBool cfg_pest_springbarley_on("PEST_SPRINGBARLEY_ON", CFG_CUSTOM, false);
66 CfgBool cfg_pest_winterwheat_on("PEST_WINTERWHEAT_ON", CFG_CUSTOM, false);
67 CfgBool cfg_pest_winterrape_on("PEST_WINTERRAPE_ON", CFG_CUSTOM, false);
68 CfgBool cfg_pest_SBS_ERA("PEST_SBS_ERA", CFG_CUSTOM, false);
69 
71 extern Landscape *g_land;
72 
73 
74 
75 void Pesticide::Tick( void )
76 {
77  // Get todays rainfall
78  m_rainfallcategory = (unsigned) floor(g_land->SupplyRain() * 100 + 0.5);
79  if (m_rainfallcategory >= 100) m_rainfallcategory = 99;
80  // Now make it an index to the 100x100 array.
81  m_rainfallcategory *= 100;
83  {
85  return;
86  }
87  MainMapDecay();
90 }
91 //-----------------------------------------------------------------------------------------------------------------------------
92 
94 {
98  for ( unsigned int i=0; i<m_daily_spray_queue.size(); i++ ) {
99  delete m_daily_spray_queue[i];
100  }
101  m_daily_spray_queue.resize( 0 );
102 }
103 //-----------------------------------------------------------------------------------------------------------------------------
104 
105 void Pesticide::DailyQueueAdd( LE* a_element_sprayed, double a_amount )
106 {
107  PesticideEvent *l_event = new PesticideEvent( a_element_sprayed, a_amount );
108 
109  m_daily_spray_queue.resize( m_daily_spray_queue.size() + 1 );
111  l_event;
112 }
113 //-----------------------------------------------------------------------------------------------------------------------------
114 
116 {
123  if (0 == m_daily_spray_queue.size())
124  // Event queue empty, nobody sprayed anything today.
125  return;
126 
127  // Spraying at least one field. Force the main pesticide map
128  // decay method to run tomorrow.
129  m_something_to_decay = true;
130 
131  for ( unsigned int i=0; i<m_daily_spray_queue.size(); i++ )
132  {
133  m_wind = g_land->SupplyWindDirection();
134  int minx=m_daily_spray_queue[i]->m_sprayed_elem->GetMinX();
135  int maxx=m_daily_spray_queue[i]->m_sprayed_elem->GetMaxX();
136  int miny=m_daily_spray_queue[i]->m_sprayed_elem->GetMinY();
137  int maxy=m_daily_spray_queue[i]->m_sprayed_elem->GetMaxY();
138  // For cover we use the crop, and save this for later
139  double cover = m_daily_spray_queue[i]->m_sprayed_elem->GetVegCover();
140  TwinMapClear(minx, miny, maxx, maxy);
141  // Add the amount in m_amount to the twin map (all squares covered with the polygon get m_amount added.
142  TwinMapSpray( m_daily_spray_queue[i]->m_sprayed_elem, m_daily_spray_queue[i]->m_amount, minx, miny, maxx, maxy);
143  // This adds it to the main map and if necessary sorts out the allocation between veg and soil.
144  TwinMapDiffusion(minx, miny, maxx, maxy, cover);
145  }
146 }
147 //-----------------------------------------------------------------------------------------------------------------------------
148 
149 void Pesticide::TwinMapClear( int a_minx, int a_miny, int a_maxx, int a_maxy )
150 {
151  for ( int y=a_miny; y<=a_maxy; y++ )
152  {
153  int t = y * m_pest_map_width;
154  for ( int x=a_minx; x<=a_maxx; x++ )
155  {
156  m_pest_map_twin[t + x] = 0.0;
157  }
158  }
159 }
160 //-----------------------------------------------------------------------------------------------------------------------------
161 
162 void Pesticide::TwinMapSpray( LE* a_element_sprayed, double a_amount, int a_minx, int a_miny, int a_maxx, int a_maxy )
163 {
173  /* Replaced with more detailed fate code for EFSA June 2014
174  if (l_pest_use_application_rate.value()) {
175  // We are applying a field rate. The actual residue needs to be calculated here
176  double biomass = a_element_sprayed->GetVegBiomass();
177  double cover = a_element_sprayed->GetVegCover();
178  // rate is in mg/m and needs to be converted to mg/kg
179  double residue = (a_amount/(biomass*0.001)) * 0.435855; // g to kg veg // 0.435855 is a specific calculation to obtain the same residue that Joe Crocker used for the scale of use study
180  a_amount = residue * cover;
181  }
182  */
183  double l_fractional_amount = a_amount * m_prop; // m_prop is a constant related to the grid area (i.e. how many squares are in one grid square).
184  int l_large_map_index = a_element_sprayed->GetMapIndex();
185  /*
186  * Going through the whole landscape is very slow and unnecessary for small polygons.
187  * Since our polygons do not extend beyond the edge of the map
188  * ie do not wrap round, then we only need a measure of minx, maxx, miny, maxy.
189  * This is set up at the start of the simulation.
190  */
191  for ( int y=a_miny; y<=a_maxy; y++ ) {
192  for ( int x=a_minx; x<=a_maxx; x++ ) {
193  if ( m_land->Get( x, y ) == l_large_map_index )
194  {
195  // This adds the l_fractional_amount to the twin map
196  TwinMapSprayPixel( x, y, l_fractional_amount );
197  }
198  }
199  }
201 }
202 //-----------------------------------------------------------------------------------------------------------------------------
203 
205 {
206  if ( m_x_excess ) {
207  for ( unsigned int i=0; i<m_pest_map_width-1; i++ ) {
208  m_pest_map_twin[ i * m_pest_map_width + m_pest_map_height-1 ] *= m_corr_x;
209  }
210  }
211 
212  if ( m_y_excess ) {
213  unsigned int l_additive = (m_pest_map_height-1)*m_pest_map_width;
214  for ( unsigned int i=0; i<m_pest_map_height-1; i++ ) {
215  m_pest_map_twin[ i + l_additive ] *= m_corr_y;
216  }
217  }
218 
219  if ( m_x_excess && m_y_excess ) {
220  m_pest_map_twin[ m_pest_map_size-1 ] *= (((double)(PEST_GRIDAREA)) / ((double)(m_x_excess*m_y_excess)));
221  }
222 }
223 //-----------------------------------------------------------------------------------------------------------------------------
224 
225 /*
226 void Pesticide::TwinMapCopyToMask( int a_minx, int a_miny, int a_maxx, int a_maxy )
227 {
228  // Copy the newly calculated pesticide amounts over to the mask map
229  for ( int y=a_miny; y<=a_maxy; y++ )
230  {
231  int t = y * m_pest_map_width;
232  for ( int x=a_minx; x<=a_maxx; x++ )
233  {
234  m_pest_map_mask[t + x] = m_pest_map_twin[t + x];
235  }
236  }
237 }
238 */
239 //-----------------------------------------------------------------------------------------------------------------------------
240 
241 /*
242 void Pesticide::TwinMapAddToMain( void )
243 {
244  for ( unsigned int i=0; i<m_pest_map_size; i++ ) {
245  m_pest_map_main[i] += m_pest_map_twin[i];
246  }
247 }
248 //-----------------------------------------------------------------------------------------------------------------------------
249 */
250 void Pesticide::TwinMapDiffusion( int a_minx, int a_miny, int a_maxx, int a_maxy, double a_cover )
251 {
252  for ( int y=a_miny; y<a_maxy; y++ )
253  {
254  int t = y*m_pest_map_width;
255  for ( int x=a_minx; x<a_maxx; x++ )
256  {
257  if ( m_pest_map_twin[ t + x ] > 0.0 )
258  {
259  double l_amount = m_pest_map_twin[ t + x ];
260  for ( unsigned int i=0; i<m_diffusion_mask[m_wind].size(); i++ )
261  {
262  // This adds the pesticide to the main map - simply adds the calculated amount.
263  DiffusionSprayPixel( x + m_diffusion_mask[m_wind][i]->Getdx(),m_pest_map_width,y + m_diffusion_mask[m_wind][i]->Getdy(),
264  m_pest_map_height,m_diffusion_mask[m_wind][i]->GetFraction() *l_amount, a_cover);
265  }
266  }
267  }
268  }
269 }
270 //-----------------------------------------------------------------------------------------------------------------------------
271 
272 inline void Pesticide::DiffusionSprayPixel(int a_x, int a_limit_x, int a_y, int a_limit_y, double a_amount, double a_cover)
273 {
281  // First we have to do the typical out of bounds checks - if these fail do nothing, the pesticide fell off the world
282  if (a_x < 0 || a_x >= a_limit_x || a_y < 0 || a_y >= a_limit_y) return;
283  // Now calculate the coordinate entry in the array and store this as l_coord
284  int l_coord = a_y * a_limit_x + a_x;
285 #ifdef __DETAILED_PESTICIDE_FATE
286  // Here we need to calculate the partition of pesticide into two compartments.
287  m_pest_map_vegcanopy[l_coord] += a_amount * a_cover;
288  m_pest_map_soil[l_coord] += a_amount - m_pest_map_vegcanopy[l_coord];
289 #else
290  m_pest_map_main[l_coord] += a_amount;
291 #endif
292 }
293 //-----------------------------------------------------------------------------------------------------------------------------
294 
296 {
304  int l_grid = l_pest_diffusion_grid_count.value();
305  const int l_side_length = l_grid * 2 + 1;
306  double* l_diff;
307  l_diff = new double[l_side_length];
308  int cells = 1;
309  double sum = 1.0;
310  l_diff[0] = 1.0;
311  for (int l=1; l<l_side_length; l++)
312  {
313  l_diff[l] = DiffusionFunction(l);
314  sum += l_diff[l];
315  }
316  for (int l=0; l<l_side_length; l++)
317  {
318  l_diff[l] /= sum;
319  l_diff[l] /= cells;
320  cells += 2; // 2 more cells per row away from centre square
321  }
322  // Calculated for 4 wind directions
323  for (int wind=0; wind < 4; wind ++)
324  {
325  m_diffusion_mask[wind].resize( l_side_length * l_side_length );
326  for ( int x = 0; x< l_side_length; x++ )
327  {
328  for ( int y= 0; y< l_side_length; y++ )
329  {
330  m_diffusion_mask[wind][x + y * l_side_length] = new Diffusor( x, y, 0); // first zero all values
331  }
332  }
333  }
334  int strtx = l_grid;
335  int strty = l_grid;
336  int fin = 1;
337  // North
338  for (int step = 0; step <= l_grid; step++)
339  {
340  for (int cc=0; cc<fin; cc++)
341  {
342  m_diffusion_mask[0][ strtx + (cc-step) + ((strty-step)*l_side_length)]->SetFraction(l_diff[step]);
343  }
344  fin += 2;
345  }
346  // South
347  fin = 1;
348  for (int step = 0; step <= l_grid; step++)
349  {
350  for (int cc=0; cc<fin; cc++)
351  {
352  m_diffusion_mask[2][ strtx + (cc-step) + ((strty+step)*l_side_length)]->SetFraction(l_diff[step]);
353  }
354  fin += 2;
355  }
356  // East
357  fin = 1;
358  for (int step = 0; step <= l_grid; step++)
359  {
360  for (int cc=0; cc<fin; cc++)
361  {
362  m_diffusion_mask[3][ (strtx + step) + ((strty+(cc-step))*l_side_length)]->SetFraction(l_diff[step]);
363  }
364  fin += 2;
365  }
366  // West
367  fin = 1;
368  for (int step = 0; step <= l_grid; step++)
369  {
370  for (int cc=0; cc<fin; cc++)
371  {
372  m_diffusion_mask[1][ (strtx - step) + ((strty+(cc-step))*l_side_length)]->SetFraction(l_diff[step]);
373  }
374  fin += 2;
375  }
376 
377  delete[] l_diff;
378 }
379 //-----------------------------------------------------------------------------------------------------------------------------
380 
381 
382 
383 /*
384 void Pesticide::DiffusionMaskInit( void )
385 {
386  int l_grid = l_pest_diffusion_grid_count.value();
387  int l_side_length = l_grid * 2 + 1;
388 
389  m_diffusion_mask.resize( l_side_length * l_side_length );
390 
391  unsigned int i = 0;
392  //double l_diff_zero = DiffusionFunction( 0.0 );
393  double l_diff_sum = 0.0;
394  for ( int x = -l_grid; x < l_grid + 1; x++ ) {
395  for ( int y = -l_grid; y < l_grid + 1; y++ ) {
396  double l_dist = sqrt( (double) x*x + y*y ); // ***CJT*** added 28/8/2009
397  // m_diffusion_mask has the square to drift spray to with the proportions relative to the amount received in the centre square
398  // but the total may be greater than one, so we need the adjustment provided by the second loop
399  double l_diff = DiffusionFunction(l_dist);
400  l_diff_sum += l_diff;
401  m_diffusion_mask[i] = new Diffusor( x, y, l_diff); // ***CJT*** changed 28/8/2009 l_diff_zero
402  i++;
403  }
404  }
405  for ( unsigned x = 0; x < i; x++) {
406  m_diffusion_mask[x]->m_fraction /= l_diff_sum;
407  }
408 }
409 
410 */
411 
412 double Pesticide::DiffusionFunction( double a_dist_meters )
413 {
414  double pp;
419 // y=(2.753767)*(x+(1.86976))**(-2.121563)
420 #ifdef __WithinOrchardPesticideSim__
421  if (a_dist_meters==0) pp=0.7784;
422  else pp=0.0277;
423 #else
424 // pp=2.753767 * pow(( a_dist_meters+1.86976 ), -2.121563);
425  pp= exp( l_pest_diffusion_slope.value() * a_dist_meters );
426  //pp=pow(( a_dist_meters+1 ), l_pest_diffusion_slope.value() );
427  //pp = (2.7593 * pow(a_dist_meters,-0.9778)) * 0.001;
428  if (pp<(l_pest_zero_threshold.value()/10)) pp=0; // Don't bother with the little ones
429 #endif
430  return pp;
431 }
432 //-----------------------------------------------------------------------------------------------------------------------------
433 
435 {
436  if ( ! m_something_to_decay ) return;
441  double l_zero = l_pest_zero_threshold.value();
442  m_something_to_decay = false;
443  for ( unsigned int i=0; i<m_pest_map_size; i++ )
444  {
445 #ifdef __DETAILED_PESTICIDE_FATE
446  if ((m_pest_map_vegcanopy[i] > l_zero) )
447  {
448  //Calculate wash-off m_pest_map_width * m_pest_map_height y * m_pest_map_width + x
449  int x = ( i % m_pest_map_width ) << PEST_GRIDSIZE_POW2;
450  int y = ( i / m_pest_map_width ) << PEST_GRIDSIZE_POW2;
451  double cover = g_landscape_p->SupplyVegCover(x,y);
452  unsigned cov = 100 * cover; // Cover is steps of zero to 99, may need to check for bounds here (may get cover of 1.0 ?)
453  double Rwp = m_pest_map_vegcanopy[i] *= m_RainWashoffFactor[m_rainfallcategory+cov]; // m_RainWashoffFactor is the index to the array
454  m_pest_map_soil[i] = (m_pest_map_soil[i] + Rwp) * m_pest_daily_decay_frac_Soil;
455  m_pest_map_vegcanopy[i] -= Rwp;
456  m_pest_map_vegcanopy[i] *= m_pest_daily_decay_frac_Veg;
457  m_something_to_decay = true;
458  }
459  else
460  {
461  if (m_pest_map_soil[i] > l_zero)
462  {
463  m_pest_map_soil[i] = m_pest_map_soil[i] * m_pest_daily_decay_frac_Soil;
464  m_something_to_decay = true;
465  }
466  else
467  {
468  m_pest_map_vegcanopy[i] = 0.0;
469  m_pest_map_soil[i] = 0.0;
470  }
471 #else
472  if (m_pest_map_main[i] > l_zero)
473  {
479  m_something_to_decay = true;
480  }
481  else
482  {
483  m_pest_map_main[i] = 0.0;
484  }
485 #endif
486  }
487 }
488 //-----------------------------------------------------------------------------------------------------------------------------
489 
491 {
493  {
494  m_map = a_map;
495  m_land = a_land;
496  m_something_to_decay = false;
497 
498  // Figure out critical border coordinates,
499  // proportional fractions etc.
500  m_prop = 1.0 / ((double)(PEST_GRIDAREA));
502  if ( m_x_excess ) {
503  m_corr_x = (double)PEST_GRIDSIZE /(double)m_x_excess;
504  }
506  if ( m_y_excess ) {
507  m_corr_y = (double)PEST_GRIDSIZE / (double)m_y_excess;
508  }
509 
511  if ( m_land->MapWidth() & (PEST_GRIDSIZE-1))
513 
515  if ( m_land->MapHeight() & (PEST_GRIDSIZE-1))
517 
518  m_pest_map_size = m_pest_map_width * m_pest_map_height;
519 
520  m_pest_map_twin = (double*)malloc(sizeof(double)* m_pest_map_size);
521 
522 #ifdef __DETAILED_PESTICIDE_FATE
523  m_pest_map_vegcanopy = (double*)malloc(sizeof(double)* m_pest_map_size);
524  m_pest_map_soil = (double*)malloc(sizeof(double)* m_pest_map_size);
525  if (l_pest_enable_pesticide_engine.value() && ((m_pest_map_twin == NULL) || (m_pest_map_vegcanopy == NULL) || (m_pest_map_soil == NULL)))
526  {
527  g_msg->Warn(WARN_FATAL,"Pesticide::Pesticide(): Out of memory.", "" );
528  exit(1);
529  }
530 #else
531  m_pest_map_main = (double*)malloc(sizeof(double)* m_pest_map_size);
532  if (l_pest_enable_pesticide_engine.value() && ((m_pest_map_twin == NULL) || (m_pest_map_main == NULL)))
533  {
534  g_msg->Warn(WARN_FATAL,"Pesticide::Pesticide(): Out of memory.", "" );
535  exit(1);
536  }
537 #endif
538  for ( unsigned int i=0; i<m_pest_map_size; i++ ) {
539 #ifdef __DETAILED_PESTICIDE_FATE
540  m_pest_map_vegcanopy[i] = 0.0;
541  m_pest_map_soil[i] = 0.0;;
542 #else
543  m_pest_map_main[i] = 0.0;
544 #endif
545  m_pest_map_twin[i] = 0.0;
546  }
547 
548  m_pest_daily_decay_frac = pow(10.0, log10(0.5) / l_pest_ai_half_life.value());
550 #ifdef __BORLANDC__
552 #else
553  m_pest_daily_decay_frac_Veg = log(2.0)/l_pest_ai_half_life_Veg.value();
554 #endif
555 
556  m_pest_daily_decay_frac_Soil = pow(10.0, log10(0.5) / l_pest_ai_half_life_Soil.value());
557  // This calculates
561  }
562 }
563 //-----------------------------------------------------------------------------------------------------------------------------
564 
566 {
570  double rainsteps = 0.1; // mm, multiply rainfall by 100 to get this, save result as integer
571  double coversteps = 1.0; // %, multiply cover by 100 to get this, save result as integer
572  for (int i = 0; i < 100; i++)
573  {
574  double SC = i * coversteps;
575  double LAI = log(0 - (1 - SC))*1.666666667; // This is the inverse of Beer's Law
576  for (int r = 0; r < 100; r++)
577  {
578  double P = r * rainsteps;
579  double Pi = LAI*(1 - (1 / ((1 + SC * P) / LAI)));
580  double Rw = 0.25*(SC * P - Pi); // Rw is a proportion of canopy pesticide washed off.
581  m_RainWashoffFactor[r * 100 + i] = Rw;
582  }
583  }
584 }
585 //-----------------------------------------------------------------------------------------------------------------------------
586 
588 {
589 #ifdef __DETAILED_PESTICIDE_FATE
591  free( m_pest_map_soil );
592  free(m_pest_map_vegcanopy);
593  }
594 #else
596  free( m_pest_map_main );
597  }
598 #endif
600  free( m_pest_map_twin );
601  //free( m_pest_map_mask );
602  }
603 
604  for (int w=0; w<4; w++)
605  {
606  for ( unsigned int i=0; i<m_diffusion_mask[w].size(); i++ )
607  {
608  delete m_diffusion_mask[w][i];
609  }
610  m_diffusion_mask[w].resize(0);
611  }
612  DailyQueueClear();
613 }
614 //-----------------------------------------------------------------------------------------------------------------------------
615 
616 #ifdef PEST_DEBUG
617 
619 {
620  int l_grid = l_pest_diffusion_grid_count.value();
621  const int l_side_length = l_grid * 2 + 1;
622 
623  // Need a debug test, output all diffusion masks to file
624  ofstream ofile("diffusionmask.txt",ios::out);
625  for (int i=0; i<4; i++)
626  {
627  for ( int x = 0; x< l_side_length; x++ )
628  {
629  for ( int y= 0; y< l_side_length; y++ )
630  {
631  ofile << m_diffusion_mask[i][x+(y*l_side_length)]->GetFraction() << '\t';
632  }
633  ofile << endl;
634  }
635  ofile << endl;
636  ofile << endl;
637  }
638  ofile.close();
639  }
640 //-----------------------------------------------------------------------------------------------------------------------------
641 
642 // For file saving and loading.
643 #define CFG_CHANNEL_BITS 8
644 #define CFG_CHANNEL_MAXVAL (2^CFG_CHANNEL_BITS-1)
645 
646 #define SV_UINT32 unsigned int
647 #define SV_INT32 int
648 #define SV_UINT8 unsigned char
649 #define SV_INT8 char
650 
651 bool Pesticide::SavePPM( double *a_map,
652  int a_beginx, int a_width,
653  int a_beginy, int a_height,
654  char* a_filename )
655 {
656  a_beginx = 0;
657  a_width = m_pest_map_width;
658  a_beginy = 0;
659  a_height = m_pest_map_height;
660 
661  SV_UINT32 linesize = a_width*3;
662  SV_UINT8* linebuffer = (SV_UINT8*)malloc(sizeof(SV_UINT8)* linesize);
663 
664  if ( linebuffer == NULL ) {
666  "Pesticide::SavePPM(): Out of memory!", "" );
667  exit(1);
668  }
669 
670  FILE* l_file;
671  l_file=fopen(a_filename, "w" );
672  if ( !l_file ) {
673  printf("PesticideTest::SavePPM(): "
674  "Unable to open file for writing: %s\n",
675  a_filename );
676  exit(1);
677  }
678 
679  fprintf( l_file, "P6\n%d %d %d\n",
680  a_width,
681  a_height,
682  255 );
683 
684  for ( int line=a_beginy; line< a_beginy + a_height; line++ ) {
685  int i = 0;
686  for ( int column=a_beginx; column < a_beginx + a_width; column++ ) {
687  int localcolor = (int)( a_map[ line * m_pest_map_width + column ]
688  * 255.0);
689  if ( localcolor <= 255 ) {
690  linebuffer [ i++ ] = char (localcolor & 0xff);
691  linebuffer [ i++ ] = 0;
692  linebuffer [ i++ ] = 0;
693  } else {
694  linebuffer [ i++ ] = 255;
695  localcolor -= 255;
696  if ( localcolor <= 255 ) {
697  linebuffer [ i++ ] = char (localcolor);
698  linebuffer [ i++ ] = 0;
699  } else {
700  linebuffer [ i++ ] = 255;
701  localcolor -= 255;
702  if ( localcolor <= 255 ) {
703  linebuffer [ i++ ] = char (localcolor);
704  } else {
705  linebuffer [ i++ ] = 255;
706  }
707  }
708  }
709  }
710  fwrite( linebuffer, sizeof(SV_UINT8), linesize, l_file );
711  }
712 
713  fclose( l_file );
714  free( linebuffer );
715  return true;
716 }
717 //-----------------------------------------------------------------------------------------------------------------------------
718 
719 /*
720 void Pesticide::Test( Landscape *a_map )
721 {
722  for ( int i=0; i<730; i++) {
723 
724  if ( random(100) < 10 ) {
725  int l_sprays = random(5)+1;
726  for ( int j=0; j<l_sprays; j++ ) {
727  int l_x = random(1500);
728  int l_y = random(1500);
729  DailyQueueAdd( a_map->
730  SupplyLEPointer( a_map->SupplyPolyRef( l_x, l_y )),
731  1.0 );
732  }
733  char l_filename[20];
734  sprintf( l_filename, "ppms/p%04d.ppm", i );
735  SavePPM( m_pest_map_main,
736  0, 0, 0, 0,
737  l_filename );
738  }
739 
740  Tick();
741  }
742 }
743 //-----------------------------------------------------------------------------------------------------------------------------
744 */
745 #endif // PEST_DEBUG
static CfgFloat l_pest_ai_half_life_Soil("PEST_AI_HALF_LIFE_SOIL", CFG_CUSTOM, 10.0)
void TwinMapClear(int a_minx, int a_miny, int a_maxx, int a_maxy)
Definition: pesticide.cpp:149
#define SV_UINT8
Definition: pesticide.cpp:648
CfgBool cfg_pest_winterwheat_on("PEST_WINTERWHEAT_ON", CFG_CUSTOM, false)
CfgBool l_pest_enable_pesticide_engine("PEST_ENABLE_PESTICIDE_ENGINE", CFG_CUSTOM, false)
The landscape class containing all environmental and topographical data.
Definition: landscape.h:109
void DailyQueueClear(void)
Definition: pesticide.cpp:93
int MapWidth(void)
Definition: rastermap.h:57
int GetMapIndex(void)
Definition: elements.h:190
unsigned int m_pest_map_width
Definition: pesticide.h:178
CfgFloat l_pest_daily_mort2("PEST_DAILY_MORTALITY_TWO", CFG_CUSTOM, 0.25)
double m_pest_daily_decay_frac_Soil
Definition: pesticide.h:160
void TwinMapDiffusion(int a_minx, int a_miny, int a_maxx, int a_maxy, double a_cover)
Definition: pesticide.cpp:250
double m_RainWashoffFactor[10000]
a structure to hold pre-calculated pesticide rain wash off factor (Rw)
Definition: pesticide.h:182
void DiffusionMaskInit(void)
Definition: pesticide.cpp:295
int MapHeight(void)
Definition: rastermap.h:58
RasterMap * m_land
Definition: pesticide.h:163
int SupplyWindDirection(void)
Definition: landscape.h:1349
Integer configurator entry class.
Definition: configurator.h:85
void DailyQueueAdd(LE *a_element_sprayed, double a_amount)
Definition: pesticide.cpp:105
int m_x_excess
Definition: pesticide.h:149
CfgBool cfg_pest_residue_or_rate("PEST_RESIDUE_OR_RATE", CFG_CUSTOM, true)
#define PEST_GRIDSIZE_POW2
Turns on code for detailed pesticide fate handling.
Definition: pesticide.h:42
double m_prop
Definition: pesticide.h:151
double * m_pest_map_twin
Definition: pesticide.h:176
static CfgFloat l_pest_ai_half_life("PEST_AI_HALF_LIFE", CFG_CUSTOM, 10.0)
double value(void)
Definition: configurator.h:107
Definition: elements.h:81
int Get(int a_x, int a_y)
Definition: rastermap.h:86
void CalcRainWashOffFactors()
Pre-calculates the constants required for rain wash off with increasing rainfall and stores this in m...
Definition: pesticide.cpp:565
double m_pest_daily_decay_frac_Veg
Definition: pesticide.h:159
class Pesticide * g_pest
Definition: pesticide.cpp:70
int m_wind
Definition: pesticide.h:154
#define SV_UINT32
Definition: pesticide.cpp:646
Diffusion_mask m_diffusion_mask[4]
Pre-calculated square diffusion map, assuming wind directions (4) Used after spraying an element in...
Definition: pesticide.h:188
CfgFloat l_pest_daily_mort("PEST_DAILY_MORTALITY", CFG_CUSTOM, 0.25)
void TwinMapSprayCorrectBorders(void)
Definition: pesticide.cpp:204
class MapErrorMsg * g_msg
Definition: maperrormsg.cpp:38
bool value(void)
Definition: configurator.h:123
CfgFloat l_pest_insecticide_amount("PEST_INSECTICIDE_AMOUNT", CFG_CUSTOM, 0.00)
vector< PesticideEvent * > m_daily_spray_queue
Definition: pesticide.h:191
unsigned m_rainfallcategory
Daily rainfall saved here * 100 to use as an indext to the Pesticide::m_RainWashoffFactor array - an ...
Definition: pesticide.h:184
static CfgFloat l_pest_diffusion_slope("PEST_DRIFT_SLOPE", CFG_CUSTOM,-0.6122)
double SupplyRain(void)
Definition: landscape.h:1291
CfgInt cfg_pest_productapplic_startdate2("PEST_PRODUCTAPPLIC_STARTDATE_TWO", CFG_CUSTOM,-1)
virtual ~Pesticide(void)
Definition: pesticide.cpp:587
double DiffusionFunction(double a_dist_meters)
Definition: pesticide.cpp:412
void Tick(void)
Definition: pesticide.cpp:75
void DiffusionMaskInitTest(void)
Definition: pesticide.cpp:618
void DailyQueueProcess(void)
Definition: pesticide.cpp:115
int m_y_excess
Definition: pesticide.h:150
#define PEST_GRIDSIZE
Definition: pesticide.h:43
Pesticide(RasterMap *a_land, Landscape *a_map)
Definition: pesticide.cpp:490
Bool configurator entry class.
Definition: configurator.h:116
CfgFloat l_pest_product_0_amount("PEST_PRODUCT_ZERO_AMOUNT", CFG_CUSTOM, 0.004145)
double m_corr_x
Definition: pesticide.h:152
static CfgFloat l_pest_ai_half_life_Veg("PEST_AI_HALF_LIFE_VEG", CFG_CUSTOM, 10.0)
Landscape * g_land
void TwinMapSprayPixel(int a_large_map_x, int a_large_map_y, double a_fractional_amount)
Definition: pesticide.h:348
double SupplyVegCover(int a_polyref)
Definition: landscape.h:969
void TwinMapSpray(LE *a_element_spryaed, double a_amount, int a_minx, int a_miny, int a_maxx, int a_maxy)
Definition: pesticide.cpp:162
unsigned int m_pest_map_size
Definition: pesticide.h:177
bool SavePPM(double *a_map, int a_beginx, int a_width, int a_beginy, int a_height, char *a_filename)
Definition: pesticide.cpp:651
bool m_something_to_decay
Definition: pesticide.h:144
CfgFloat l_pest_product_1_amount("PEST_PRODUCT_ONE_AMOUNT", CFG_CUSTOM, 0.004145)
int value(void)
Definition: configurator.h:92
void MainMapDecay(void)
Definition: pesticide.cpp:434
CfgBool l_pest_use_application_rate("PEST_USE_APPLICATIONRATE", CFG_CUSTOM, false)
unsigned int m_pest_map_height
Definition: pesticide.h:179
void Warn(MapErrorState a_level, std::string a_msg1, std::string a_msg2)
Definition: maperrormsg.cpp:56
CfgFloat l_pest_trigger_threshold2("PEST_TRIGGER_THRESHOLD_TWO", CFG_CUSTOM, 1.0)
Landscape * m_map
Definition: pesticide.h:166
CfgBool cfg_pest_winterrape_on("PEST_WINTERRAPE_ON", CFG_CUSTOM, false)
double m_pest_daily_decay_frac
Definition: pesticide.h:158
CfgFloat l_pest_trigger_threshold1("PEST_TRIGGER_THRESHOLD_ONE", CFG_CUSTOM, 1.0)
This is a trigger values that can be used to trigger pesticides effects. Currently only used by the B...
static CfgInt l_pest_diffusion_grid_count("PEST_DIFFUSION_GRID_COUNT", CFG_CUSTOM, 1)
CfgBool cfg_pest_SBS_ERA("PEST_SBS_ERA", CFG_CUSTOM, false)
Double configurator entry class.
Definition: configurator.h:100
CfgInt cfg_pest_productapplic_period("PEST_PRODUCTAPPLIC_PERIOD", CFG_CUSTOM, 1)
Definition: elements.cpp:113
double * m_pest_map_main
Definition: pesticide.h:174
static CfgFloat l_pest_zero_threshold("PEST_ZERO_THRESHOLD", CFG_CUSTOM, 0.00001)
CfgInt cfg_pest_productapplic_startdate("PEST_PRODUCTAPPLIC_STARTDATE", CFG_CUSTOM,-1)
Definition: elements.cpp:110
CfgBool cfg_pest_springbarley_on("PEST_SPRINGBARLEY_ON", CFG_CUSTOM, false)
double m_corr_y
Definition: pesticide.h:153
#define PEST_GRIDAREA
Definition: pesticide.h:44
class Landscape * g_landscape_p
Definition: Landscape.cpp:238
void DiffusionSprayPixel(int a_x, int a_limit_x, int a_y, int a_limit_y, double a_amount, double a_cover)
Definition: pesticide.cpp:272
CfgInt cfg_pest_productapplic_startdate3("PEST_PRODUCTAPPLIC_STARTDATE_THREE", CFG_CUSTOM,-1)