/** * Attaches the relevant prevalence chart to each herd structure. * * @param self the model. * @param herds the herd list. */ void attach_prevalence_charts (struct naadsm_model_t_ *self, HRD_herd_list_t *herds) { local_data_t *local_data; HRD_herd_t *herd; unsigned int nherds; unsigned int i; #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER attach_prevalence_charts (%s)", MODEL_NAME); #endif local_data = (local_data_t *) (self->model_data); nherds = HRD_herd_list_length (herds); for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); if (local_data->production_type[herd->production_type] == TRUE) herd->prevalence_curve = local_data->prevalence; } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT attach_prevalence_charts (%s)", MODEL_NAME); #endif return; }
int callback (int id, void *arg) { callback_t *callback_data; HRD_herd_list_t *herds; HRD_herd_t *herd2; callback_data = (callback_t *) arg; herds = callback_data->herds; /* Because herd indices start at 0, and R-Tree rectangle IDs start at 1. */ herd2 = HRD_herd_list_get (herds, id - 1); check_and_infect (callback_data->self, herds, callback_data->herd1, herd2, callback_data->event, callback_data->rng, callback_data->queue); /* A return value of 0 would mean that the spatial search should stop early * (before all herds in the search rectangle were visited). We don't want * that, so return 1. */ return 1; }
/** * Responds to a new day event by updating the reporting variables. * * @param self the model. * @param herds a list of herds. * @param zones a list of zones. * @param event a new day event. */ void handle_new_day_event (struct ergadm_model_t_ *self, HRD_herd_list_t * herds, ZON_zone_list_t * zones, EVT_new_day_event_t * event) { local_data_t *local_data; gboolean shape_due, area_due, num_areas_due, num_units_due; int i; ZON_zone_t *zone, *next_smaller_zone; GString *s; double area; unsigned int nherds; HRD_herd_t *herd; char *drill_down_list[3] = { NULL, NULL, NULL }; #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER handle_new_day_event (%s)", MODEL_NAME); #endif local_data = (local_data_t *) (self->model_data); shape_due = RPT_reporting_due (local_data->shape, event->day); area_due = RPT_reporting_due (local_data->area, event->day); num_areas_due = RPT_reporting_due (local_data->num_separate_areas, event->day); num_units_due = RPT_reporting_due (local_data->num_units, event->day); for (i = 0; i < local_data->nzones; i++) { zone = ZON_zone_list_get (zones, i); if (shape_due) { s = polygon_to_wkt (zone->poly); RPT_reporting_set_text1 (local_data->shape, s->str, zone->name); /* The string was copied so it can be freed. */ g_string_free (s, TRUE); } if (area_due) { area = ZON_update_area (zone); RPT_reporting_set_real1 (local_data->area, area, zone->name); } if (num_areas_due) RPT_reporting_set_integer1 (local_data->num_separate_areas, zone->poly->num_contours, zone->name); } /* In the loop above, the area of each zone polygon was computed. But since * zones are nested inside of each other, that's not exactly what we want: * we want the area displayed for an "outer" zone to exclude the area of the * smaller "inner" zones. So we do that computation here. */ if (area_due) { /* Start with the next-to-last zone, because the last one is the * "background" zone. */ for (i = local_data->nzones - 2; i > 0; i--) { zone = ZON_zone_list_get (zones, i); next_smaller_zone = ZON_zone_list_get (zones, i - 1); zone->area -= next_smaller_zone->area; RPT_reporting_set_real1 (local_data->area, zone->area, zone->name); if (NULL != guilib_record_zone_area) guilib_record_zone_area (zone->level, zone->area); } /* Don't forget to report the smallest zone to the GUI! */ if (NULL != guilib_record_zone_area) { zone = ZON_zone_list_get (zones, 0); guilib_record_zone_area (zone->level, zone->area); } } if (local_data->num_animal_days_by_prodtype->frequency != RPT_never || num_units_due) { nherds = zones->membership_length; for (i = 0; i < local_data->nzones; i++) { zone = ZON_zone_list_get (zones, i); RPT_reporting_set_integer1 (local_data->num_units, 0, zone->name); } for (i = 0; i < nherds; i++) { zone = zones->membership[i]->parent; RPT_reporting_add_integer1 (local_data->num_units, 1, zone->name); herd = HRD_herd_list_get (herds, i); if (herd->status != Destroyed) { drill_down_list[0] = herd->production_type_name; drill_down_list[1] = zone->name; RPT_reporting_add_integer (local_data->num_animal_days_by_prodtype, herd->size, drill_down_list); } } } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT handle_new_day_event (%s)", MODEL_NAME); #endif }
/** * Responds to a new day event by updating the reporting variables. * * @param self the model. * @param herds a list of herds. * @param zones a list of zones. * @param event a new day event. */ void handle_new_day_event (struct naadsm_model_t_ *self, HRD_herd_list_t * herds, ZON_zone_list_t * zones, EVT_new_day_event_t * event) { local_data_t *local_data = (local_data_t *) (self->model_data); #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER handle_new_day_event (%s)", MODEL_NAME); #endif /* Zero the daily counts. */ /* RPT_reporting_zero (local_data->total_cost); RPT_reporting_zero (local_data->appraisal_cost); RPT_reporting_zero (local_data->euthanasia_cost); RPT_reporting_zero (local_data->indemnification_cost); RPT_reporting_zero (local_data->carcass_disposal_cost); RPT_reporting_zero (local_data->cleaning_disinfecting_cost); RPT_reporting_zero (local_data->vaccination_cost); RPT_reporting_zero (local_data->surveillance_cost); */ /* This is an expensive cost calculation, so only do it if the user * will see any benefit from it. */ if ((local_data->surveillance_cost_param) && (/*(local_data->surveillance_cost->frequency != RPT_never ) || (local_data->total_cost->frequency != RPT_never) ||*/ (local_data->cumul_surveillance_cost->frequency != RPT_never ) || (local_data->cumul_total_cost->frequency != RPT_never))) { double **surveillance_cost_param = local_data->surveillance_cost_param; unsigned int nherds = zones->membership_length; unsigned int i; double cost = 0; for (i = 0; i < nherds; i++) { ZON_zone_t *zone = zones->membership[i]->parent; unsigned int zone_index = zone->level - 1; HRD_herd_t *herd = HRD_herd_list_get (herds, i); if (surveillance_cost_param[zone_index] && /* TODO. This should probably be the authority's view * of whether the herd has been destroyed or not. */ (herd->status != Destroyed)) { cost = surveillance_cost_param[zone_index][herd->production_type] * (double) (herd->size); /* RPT_reporting_add_real (local_data->surveillance_cost, cost, NULL); RPT_reporting_add_real (local_data->total_cost, cost, NULL); */ RPT_reporting_add_real (local_data->cumul_surveillance_cost, cost, NULL); RPT_reporting_add_real (local_data->cumul_total_cost, cost, NULL); } } } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT handle_new_day_event (%s)", MODEL_NAME); #endif }
int main (int argc, char *argv[]) { int verbosity = 0; const char *herd_file = NULL; unsigned int nherds; HRD_herd_t *herd; int i; /* loop counter */ char *summary; GError *option_error = NULL; GOptionContext *context; GOptionEntry options[] = { { "herd-file", 'h', 0, G_OPTION_ARG_FILENAME, &herd_file, "SpreadModel 3.0 herd file", NULL }, { "verbosity", 'V', 0, G_OPTION_ARG_INT, &verbosity, "Message verbosity level (0 = simulation output only, 1 = all debugging output)", NULL }, { NULL } }; context = g_option_context_new (""); g_option_context_add_main_entries (context, options, /* translation = */ NULL); if (!g_option_context_parse (context, &argc, &argv, &option_error)) { g_error ("option parsing failed: %s\n", option_error->message); } g_option_context_free (context); /* Set the verbosity level. */ if (verbosity < 1) { g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, silent_log_handler, NULL); g_log_set_handler ("herd", G_LOG_LEVEL_DEBUG, silent_log_handler, NULL); } /* Get the list of herds. */ herds = HRD_new_herd_list (); if (herd_file) yyin = fopen (herd_file, "r"); else if (yyin == NULL) yyin = stdin; while (!feof (yyin)) yyparse (); if (yyin != stdin) fclose (yyin); nherds = HRD_herd_list_length (herds); #if DEBUG g_debug ("%i herds read", nherds); summary = HRD_herd_list_to_string (herds); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "\n%s", summary); free (summary); #endif printf ("<herds>\n"); for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); printf (" <herd>\n"); printf (" <id>%s</id>\n", herd->official_id); printf (" <production-type>%u</production-type>\n", herd->production_type); printf (" <size>%u</size>\n", herd->size); printf (" <location>\n"); printf (" <latitude>%g</latitude>\n", herd->y); printf (" <longitude>%g</longitude>\n", herd->x); printf (" </location>\n"); printf (" <status>%s</status>\n", HRD_status_name[herd->status]); printf (" </herd>\n"); } printf ("</herds>\n"); /* Clean up. */ HRD_free_herd_list (herds); return EXIT_SUCCESS; }
/** * Responds to a new day event by releasing any pending infections and * stochastically generating infections. * * @param self the model. * @param herds a list of herds. * @param event a new day event. * @param rng a random number generator. * @param queue for any new events the model creates. */ void handle_new_day_event (struct ergadm_model_t_ *self, HRD_herd_list_t * herds, EVT_new_day_event_t * event, RAN_gen_t * rng, EVT_event_queue_t * queue) { local_data_t *local_data; HRD_herd_t *herd1; unsigned int nherds; /* number of herds */ unsigned int herd1_index, herd2_index; gboolean herd1_can_be_source; double distance; GQueue *q; EVT_event_t *pending_event; struct Rect search_rect; /* for narrowing down radius searches using the R-tree (spatial index) */ double mult; /* to account for latitude */ callback_t callback_data; #if DEBUG GString *s; #endif #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER handle_new_day_event (%s)", MODEL_NAME); #endif local_data = (local_data_t *) (self->model_data); /* Release any pending (due to airborne transport delays) events. */ local_data->rotating_index = (local_data->rotating_index + 1) % local_data->pending_infections->len; q = (GQueue *) g_ptr_array_index (local_data->pending_infections, local_data->rotating_index); while (!g_queue_is_empty (q)) { /* Remove the event from this model's internal queue and place it in the * simulation's event queue. */ pending_event = (EVT_event_t *) g_queue_pop_head (q); EVT_event_enqueue (queue, pending_event); local_data->npending_infections--; } if ( #if defined(USE_RTREE) && USE_RTREE == 1 /* For debugging purposes, you can #define USE_RTREE to 0 to never use * the spatial index, or 1 to always use it. */ TRUE || #endif local_data->use_rtree_index) { /* Initialize a data structure used by the callback function. */ callback_data.self = self; callback_data.herds = herds; callback_data.event = event; callback_data.rng = rng; callback_data.queue = queue; } nherds = HRD_herd_list_length (herds); for (herd1_index = 0; herd1_index < nherds; herd1_index++) { herd1 = HRD_herd_list_get (herds, herd1_index); /* Can this herd be the source of an exposure? */ #if DEBUG s = g_string_new (NULL); g_string_sprintf (s, "unit \"%s\" is %s, state is %s: ", herd1->official_id, herd1->production_type_name, HRD_status_name[herd1->status]); #endif herd1_can_be_source = local_data->param_block[herd1->production_type] != NULL && (herd1->status == InfectiousSubclinical || herd1->status == InfectiousClinical); #if DEBUG g_string_sprintfa (s, "%s be source", herd1_can_be_source ? "can" : "cannot"); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", s->str); g_string_free (s, TRUE); #endif if (!herd1_can_be_source) continue; if (local_data->use_rtree_index[herd1->production_type]) { distance = local_data->max_spread[herd1->production_type] / GIS_DEGREE_DISTANCE; mult = 1.0 / MIN (cos (DEG2RAD * (herd1->lat + distance)), cos(DEG2RAD * (herd1->lat - distance))); search_rect.boundary[0] = herd1->lon - (distance * mult) - EPSILON; search_rect.boundary[1] = herd1->lat - distance - EPSILON; search_rect.boundary[2] = herd1->lon + (distance * mult) + EPSILON; search_rect.boundary[3] = herd1->lat + distance + EPSILON; callback_data.herd1 = herd1; RTreeSearch (herds->spatial_index, &search_rect, callback, &callback_data); } else for (herd2_index = 0; herd2_index < nherds; herd2_index++) check_and_infect (self, herds, herd1, HRD_herd_list_get (herds, herd2_index), event, rng, queue); } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT handle_new_day_event (%s)", MODEL_NAME); #endif return; }
/** * Computes the size factor for each herd. * * @param herds a list of herds. * @return an array containing the size factor for each herd. */ double * build_size_factor_list (HRD_herd_list_t * herds) { HRD_herd_t *herd; unsigned int nherds; /* number of herds */ unsigned int max_size = 0; /* size of largest herd */ gsl_histogram *histogram; PDF_dist_t *herd_size_dist; double *size_factor; unsigned int i; /* loop counter */ #if DEBUG char *s; #endif #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- ENTER build_size_factor_list"); #endif nherds = HRD_herd_list_length (herds); size_factor = g_new (double, nherds); /* Find the largest herd. */ for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); if (herd->size > max_size) max_size = herd->size; } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "largest herd = %u", max_size); #endif /* Build a histogram with one bin for each herd size. */ histogram = gsl_histogram_alloc (max_size); g_assert (histogram != NULL); gsl_histogram_set_ranges_uniform (histogram, 0.5, (double) max_size + 0.5); for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); gsl_histogram_increment (histogram, (double) (herd->size)); } herd_size_dist = PDF_new_histogram_dist (histogram); g_assert (herd_size_dist != NULL); #if DEBUG s = PDF_dist_to_string (herd_size_dist); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "herd size distribution =\n%s", s); free (s); #endif /* Compute the herd size factors. */ for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); size_factor[i] = PDF_cdf (herd->size, herd_size_dist) * 2; } #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "herd size factors"); for (i = 0; i < nherds; i++) { herd = HRD_herd_list_get (herds, i); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "herd #%u (size %u) = %g", i, herd->size, size_factor[i]); } #endif /* The following line also frees the histogram. */ PDF_free_dist (herd_size_dist); #if DEBUG g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "----- EXIT build_size_factor_list"); #endif return size_factor; }