6 #include "CalcInfSusc.h" 13 #include "ModelMacros.h" 19 void TravelReturnSweep(
double t)
24 if (!(P.DoAirports && P.HotelPlaceType < P.PlaceTypeNum)) ERR_CRITICAL(
"DoAirports || HotelPlaceType not set\n");
26 if (floor(1 + t + P.TimeStep) != floor(1 + t))
29 int floorOfTime = (int)floor(t);
30 l = 1 + floorOfTime % MAX_TRAVEL_TIME;
31 FILE* stderr_shared = stderr;
32 #pragma omp parallel for reduction(+:nr, ner) schedule(static, 1) default(none) \ 33 shared(P, Places, Hosts, l, stderr_shared) 34 for (
int tn = 0; tn < P.NumThreads; tn++)
36 for (
int j = tn; j < P.Nplace[P.HotelPlaceType]; j += P.NumThreads)
38 int n = Places[P.HotelPlaceType][j].n;
39 for (
int k = n - 1; k >= 0; k--)
41 int i = Places[P.HotelPlaceType][j].members[k];
42 if (Hosts[i].Travelling == l)
53 Places[P.HotelPlaceType][j].members[k] = Places[P.HotelPlaceType][j].members[n];
56 if (Hosts[i].PlaceLinks[P.HotelPlaceType] != j)
58 ner++; fprintf(stderr_shared,
"(%i %i) ", j, Hosts[i].PlaceLinks[P.HotelPlaceType]);
60 Hosts[i].PlaceLinks[P.HotelPlaceType] = -1;
61 Hosts[i].Travelling = 0;
64 Places[P.HotelPlaceType][j].n = n;
67 fprintf(stderr,
" d=%i e=%i>", nr, ner);
71 void TravelDepartSweep(
double t)
73 int d, mps, nld, nad, nsk, bm;
77 if (!(P.DoAirports && P.HotelPlaceType < P.PlaceTypeNum)) ERR_CRITICAL(
"DoAirports || HotelPlaceType not set\n");
79 if (floor(1 + t - P.TimeStep) != floor(1 + t))
81 bm = ((P.DoBlanketMoveRestr) && (t >= P.MoveRestrTimeStart) && (t < P.MoveRestrTimeStart + P.MoveRestrDuration));
82 mps = 2 * ((int)P.PlaceTypeMeanSize[P.HotelPlaceType]) - P.NumThreads - 1;
83 int floorOfTime = (int)floor(t);
84 d = floorOfTime % MAX_TRAVEL_TIME;
86 #pragma omp parallel for reduction(+:nad,nsk) schedule(static,1) default(none) \ 87 shared(t, P, Airports, Mcells, Hosts, Places, bm, mps, d) 88 for (
int tn = 0; tn < P.NumThreads; tn++)
89 for (
int i = tn; i < P.Nairports; i += P.NumThreads)
90 if ((Airports[i].total_traffic > 0) && (Airports[i].num_mcell > 0))
92 double s = Airports[i].total_traffic;
93 if ((t > P.AirportCloseTimeStart) && (t < P.AirportCloseTimeStart + P.AirportCloseTimeStartBase))
94 s *= P.AirportCloseEffectiveness;
95 int n = (s > 0) ? ((
int)ignpoi_mt((
double)s, tn)) : 0;
101 int l = Airports[i].Inv_DestMcells[(int)floor(s * 1024)];
102 while (Airports[i].DestMcells[l].prob < s) l++;
103 l = Airports[i].DestMcells[l].id;
104 int k = (int)(ranf_mt(tn) * ((double)Mcells[l].n));
105 int i2 = Mcells[l].members[k];
106 if ((abs(Hosts[i2].inf) < InfStat_InfectiousAsymptomaticNotCase) && (Hosts[i2].inf != InfStat_Case))
108 int d2 = HOST_AGE_GROUP(i2);
109 if ((P.RelativeTravelRate[d2] == 1) || (ranf_mt(tn) < P.RelativeTravelRate[d2]))
114 if (Hosts[i2].PlaceLinks[P.HotelPlaceType] == -1)
116 Hosts[i2].PlaceLinks[P.HotelPlaceType] = -2;
123 l = Airports[i].Inv_prop_traffic[(int)floor(s * 128)];
124 while (Airports[i].prop_traffic[l] < s) l++;
125 k = Airports[i].conn_airports[l];
128 if (dist2_raw(Airports[i].loc_x, Airports[i].loc_y, Airports[k].loc_x, Airports[k].loc_y) > P.MoveRestrRadius2)
130 if (ranf_mt(tn) > P.MoveRestrEffect)
136 Hosts[i2].PlaceLinks[P.HotelPlaceType] = -1;
146 int m = Airports[k].Inv_DestPlaces[(int)floor(s * 1024)];
147 while (Airports[k].DestPlaces[m].prob < s) m++;
148 l = Airports[k].DestPlaces[m].id;
152 if ((hp = Places[P.HotelPlaceType][l].n) < mps)
155 Places[P.HotelPlaceType][l].n++;
161 Places[P.HotelPlaceType][l].members[hp] = i2;
162 d2 = (d + P.InvJourneyDurationDistrib[(int)(ranf_mt(tn) * 1024.0)]) % MAX_TRAVEL_TIME;
163 Hosts[i2].PlaceLinks[P.HotelPlaceType] = l;
164 Hosts[i2].Travelling = 1 + d2;
169 }
while ((f) && (f2 < 300));
173 Hosts[i2].PlaceLinks[P.HotelPlaceType] = -1;
187 fprintf(stderr,
"<ar=%i as=%i", nad, nsk);
188 nl = ((double)P.PlaceTypeMeanSize[P.HotelPlaceType]) * P.HotelPropLocal / P.MeanLocalJourneyTime;
190 #pragma omp parallel for reduction(+:nld,nsk) schedule(static,1) default(none) \ 191 shared(P, Places, Cells, CellLookup, Hosts, Households, nl, bm, mps, d) 192 for (
int tn = 0; tn < P.NumThreads; tn++)
193 for (
int i = tn; i < P.Nplace[P.HotelPlaceType]; i += P.NumThreads)
196 int n = (int)ignpoi_mt(nl * Cells[c].tot_prob, tn);
197 if (Places[P.HotelPlaceType][i].n + n > mps)
199 nsk += (Places[P.HotelPlaceType][i].n + n - mps);
200 n = mps - Places[P.HotelPlaceType][i].n;
202 for (
int j = 0; j < n; j++)
208 double s = ranf_mt(tn);
209 int l = Cells[c].InvCDF[(int)floor(s * 1024)];
210 while (Cells[c].cum_trans[l] < s) l++;
211 Cell* ct = CellLookup[l];
212 int m = (int)(ranf_mt(tn) * ((double)ct->S0));
213 if (m < (ct->S + ct->L))
215 int i2 = ct->susceptible[m];
216 int d2 = HOST_AGE_GROUP(i2);
218 if ((Hosts[i2].Travelling == 0) && ((P.RelativeTravelRate[d2] == 1) || (ranf_mt(tn) < P.RelativeTravelRate[d2])))
221 {
if (Hosts[i2].PlaceLinks[P.HotelPlaceType] == -1) { Hosts[i2].PlaceLinks[P.HotelPlaceType] = -2; f3 = 1; }}
225 double s2 = dist2_raw(Households[Hosts[i2].hh].loc_x, Households[Hosts[i2].hh].loc_y, Places[P.HotelPlaceType][i].loc_x, Places[P.HotelPlaceType][i].loc_y);
227 if ((bm) && (s2 > P.MoveRestrRadius2))
229 if (ranf_mt(tn) >= P.MoveRestrEffect)
232 Hosts[i2].PlaceLinks[P.HotelPlaceType] = -1;
239 s = numKernel(s2) / Cells[c].max_trans[l];
240 if (ranf_mt(tn) >= s)
243 Hosts[i2].PlaceLinks[P.HotelPlaceType] = -1;
248 d2 = (d + P.InvLocalJourneyDurationDistrib[(int)(ranf_mt(tn) * 1024.0)]) % MAX_TRAVEL_TIME;
249 int hp = Places[P.HotelPlaceType][i].n;
250 Places[P.HotelPlaceType][i].n++;
251 Places[P.HotelPlaceType][i].members[hp] = i2;
252 Hosts[i2].Travelling = 1 + d2;
255 Hosts[i2].PlaceLinks[P.HotelPlaceType] = i;
267 fprintf(stderr,
" l=%i ls=%i ", nld, nsk);
271 void InfectSweep(
double t,
int run)
282 int f, f2, cq , bm, ci ;
283 double seasonality, sbeta, hbeta;
287 double s3, s3_scaled;
288 double s4, s4_scaled;
292 unsigned short int ts;
294 if (!P.DoSeasonality) seasonality = 1.0;
295 else seasonality = P.Seasonality[((int)t) % DAYS_PER_YEAR];
297 ts = (
unsigned short int) (P.TimeStepsPerDay * t);
298 fp = P.TimeStep / (1 - P.FalsePositiveRate);
299 sbeta = seasonality * fp * P.LocalBeta;
300 hbeta = (P.DoHouseholds) ? (seasonality * fp * P.HouseholdTrans) : 0;
301 bm = ((P.DoBlanketMoveRestr) && (t >= P.MoveRestrTimeStart) && (t < P.MoveRestrTimeStart + P.MoveRestrDuration));
302 FILE* stderr_shared = stderr;
303 #pragma omp parallel for private(n,f,f2,s,s2,s3,s4,s5,s6,cq,ci,s3_scaled,s4_scaled) schedule(static,1) default(none) \ 304 shared(t, P, CellLookup, Hosts, AdUnits, Households, Places, SamplingQueue, Cells, Mcells, StateT, hbeta, sbeta, seasonality, ts, fp, bm, stderr_shared) 305 for (
int tn = 0; tn < P.NumThreads; tn++)
306 for (
int b = tn; b < P.
NCP; b += P.NumThreads)
308 Cell* c = CellLookup[b];
310 for (
int j = 0; j < c->I; j++)
318 int fct = ((P.DoDigitalContactTracing) && (t >= AdUnits[Mcells[si->mcell].adunit].DigitalContactTracingTimeStart)
319 && (t < AdUnits[Mcells[si->mcell].adunit].DigitalContactTracingTimeStart + P.DigitalContactTracingPolicyDuration) && (Hosts[ci].digitalContactTracingUser == 1));
324 if ((Households[si->hh].nh > 1) && (!si->Travelling))
326 int l = Households[si->hh].FirstPerson;
327 int m = l + Households[si->hh].nh;
328 s3 = hbeta * CalcHouseInf(ci, ts);
331 for (
int i3 = l; (i3 < m) && (!f); i3++)
332 for (
int i2 = 0; (i2 < P.PlaceTypeNum) && (!f); i2++)
333 if (Hosts[i3].PlaceLinks[i2] >= 0)
334 f = ((PLACE_CLOSED(i2, Hosts[i3].PlaceLinks[i2]))&&(HOST_ABSENT(i3)));
336 if (f) { s3 *= P.PlaceCloseHouseholdRelContact; }
337 for (
int i3 = l; i3 < m; i3++)
338 if ((Hosts[i3].inf == InfStat_Susceptible) && (!Hosts[i3].Travelling))
340 s = s3 * CalcHouseSusc(i3, ts, ci, tn);
343 cq = Hosts[i3].pcell % P.NumThreads;
344 if ((StateT[tn].n_queue[cq] < P.InfQueuePeakLength))
346 if ((P.FalsePositiveRate > 0) && (ranf_mt(tn) < P.FalsePositiveRate))
347 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {-1, i3, -1};
350 Hosts[i3].infector = ci;
351 short int infect_type = 1 + INFECT_TYPE_MASK * (1 + si->infect_type / INFECT_TYPE_MASK);
352 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {ci, i3, infect_type};
362 if (!HOST_ABSENT(ci))
365 for (
int k = 0; k < P.PlaceTypeNum; k++)
367 int l = si->PlaceLinks[k];
370 s3 = fp * seasonality * CalcPlaceInf(ci, k, ts);
371 Microcell* mp = Mcells + Places[k][l].mcell;
374 if ((dist2_raw(Households[si->hh].loc_x, Households[si->hh].loc_y,
375 Places[k][l].loc_x, Places[k][l].loc_y) > P.MoveRestrRadius2))
376 s3 *= P.MoveRestrEffect;
378 else if ((mi->moverest != mp->moverest) && ((mi->moverest == 2) || (mp->moverest == 2)))
380 s3 *= P.MoveRestrEffect;
383 if ((k != P.HotelPlaceType) && (!si->Travelling))
385 int i2 = (si->PlaceGroupLinks[k]);
389 s4_scaled = s4 *P.ScalingFactorPlaceDigitalContacts;
391 if (s4_scaled > 1) s4_scaled = 1;
402 fprintf(stderr_shared,
"@@@ %lg\n", s4_scaled);
405 else if (s4_scaled >= 1)
406 n = Places[k][l].group_size[i2];
408 n = (int)ignbin_mt((int32_t)Places[k][l].group_size[i2], s4_scaled, tn);
409 if (n > 0) SampleWithoutReplacement(tn, n, Places[k][l].group_size[i2]);
410 for (
int m = 0; m < n; m++)
412 int i3 = Places[k][l].members[Places[k][l].group_start[i2] + SamplingQueue[tn][m]];
413 s = CalcPlaceSusc(i3, k, ts, ci, tn);
416 if ((fct) && (Hosts[i3].digitalContactTracingUser) && (ci != i3) && (!HOST_ABSENT(i3)))
418 s6 = P.ProportionDigitalContactsIsolate * s;
419 if ((Hosts[ci].ncontacts < P.MaxDigitalContactsToTrace) && (ranf_mt(tn) <s6))
421 Hosts[ci].ncontacts++;
422 int ad = Mcells[Hosts[i3].mcell].adunit;
423 if ((StateT[tn].ndct_queue[ad] < AdUnits[ad].n))
426 StateT[tn].dct_queue[ad][StateT[tn].ndct_queue[ad]++] = { i3,ci,ts };
430 fprintf(stderr_shared,
"No more space in queue! Thread: %i, AdUnit: %i\n", tn, ad);
435 if ((Hosts[i3].inf == InfStat_Susceptible) && (!HOST_ABSENT(i3)))
437 Microcell* mt = Mcells + Hosts[i3].mcell;
439 s *= CalcPersonSusc(i3, ts, ci, tn)*s4/s4_scaled;
443 if ((dist2_raw(Households[Hosts[i3].hh].loc_x, Households[Hosts[i3].hh].loc_y,
444 Places[k][l].loc_x, Places[k][l].loc_y) > P.MoveRestrRadius2))
445 s *= P.MoveRestrEffect;
447 else if ((mt->moverest != mp->moverest) && ((mt->moverest == 2) || (mp->moverest == 2)))
448 s *= P.MoveRestrEffect;
450 if ((s == 1) || (ranf_mt(tn) < s))
452 cq = Hosts[i3].pcell % P.NumThreads;
453 if ((StateT[tn].n_queue[cq] < P.InfQueuePeakLength))
455 if ((P.FalsePositiveRate > 0) && (ranf_mt(tn) < P.FalsePositiveRate))
456 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {-1, i3, -1};
459 short int infect_type = 2 + k + INFECT_TYPE_MASK * (1 + si->infect_type / INFECT_TYPE_MASK);
460 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {ci, i3, infect_type};
467 if ((k == P.HotelPlaceType) || (!si->Travelling))
469 s3 *= P.PlaceTypePropBetweenGroupLinks[k] * P.PlaceTypeGroupSizeParam1[k] / ((double)Places[k][l].n);
471 s3_scaled = (fct) ? (s3 * P.ScalingFactorPlaceDigitalContacts) : s3;
474 ERR_CRITICAL_FMT(
"@@@ %lg\n", s3);
476 else if (s3_scaled >= 1)
479 n = (int)ignbin_mt((int32_t)Places[k][l].n, s3_scaled, tn);
480 if (n > 0) SampleWithoutReplacement(tn, n, Places[k][l].n);
481 for (
int m = 0; m < n; m++)
483 int i3 = Places[k][l].members[SamplingQueue[tn][m]];
484 s = CalcPlaceSusc(i3, k, ts, ci, tn);
487 if ((fct) && (Hosts[i3].digitalContactTracingUser) && (ci != i3) && (!HOST_ABSENT(i3)))
489 s6 = P.ProportionDigitalContactsIsolate * s;
490 if ((Hosts[ci].ncontacts < P.MaxDigitalContactsToTrace) && (ranf_mt(tn) < s6))
492 Hosts[ci].ncontacts++;
493 int ad = Mcells[Hosts[i3].mcell].adunit;
494 if ((StateT[tn].ndct_queue[ad] < AdUnits[ad].n))
497 StateT[tn].dct_queue[ad][StateT[tn].ndct_queue[ad]++] = { i3,ci,ts };
501 fprintf(stderr_shared,
"No more space in queue! Thread: %i, AdUnit: %i\n", tn, ad);
506 if ((Hosts[i3].inf == InfStat_Susceptible) && (!HOST_ABSENT(i3)))
508 Microcell* mt = Mcells + Hosts[i3].mcell;
510 s*= CalcPersonSusc(i3, ts, ci, tn)*s3/s3_scaled;
513 if ((dist2_raw(Households[Hosts[i3].hh].loc_x, Households[Hosts[i3].hh].loc_y,
514 Places[k][l].loc_x, Places[k][l].loc_y) > P.MoveRestrRadius2))
515 s *= P.MoveRestrEffect;
517 else if ((mt->moverest != mp->moverest) && ((mt->moverest == 2) || (mp->moverest == 2)))
518 s *= P.MoveRestrEffect;
519 if ((s == 1) || (ranf_mt(tn) < s))
521 cq = Hosts[i3].pcell % P.NumThreads;
522 if ((StateT[tn].n_queue[cq] < P.InfQueuePeakLength))
524 if ((P.FalsePositiveRate > 0) && (ranf_mt(tn) < P.FalsePositiveRate))
525 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {-1, i3, -1};
528 short int infect_type = 2 + k + NUM_PLACE_TYPES + INFECT_TYPE_MASK * (1 + si->infect_type / INFECT_TYPE_MASK);
529 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = {ci, i3, infect_type};
549 s2 = CalcSpatialInf(ci, ts);
551 if (fct) s2 *= P.ScalingFactorSpatialDigitalContacts;
555 for (
int i3 = 0; (i3 < P.PlaceTypeNum) && (!f); i3++)
556 if (si->PlaceLinks[i3] >= 0)
557 f = PLACE_CLOSED(i3, si->PlaceLinks[i3]);
559 if((f) && (HOST_ABSENT(ci)))
561 s2 *= P.PlaceCloseSpatialRelContact;
564 StateT[tn].cell_inf[j] = (float)-s5;
569 StateT[tn].cell_inf[j] = (float)s5;
576 n = (int)ignpoi_mt(s5 * sbeta * ((
double)c->tot_prob), tn);
582 for (
int j = 0; j < i2 - 1; j++) StateT[tn].cell_inf[j] /= ((
float) s5);
584 StateT[tn].cell_inf[i2 - 1] = (StateT[tn].cell_inf[i2 - 1] < 0) ? -1.0f : 1.0f;
586 for (
int k = 0; k < n; k++)
600 if ((j > 0) && (fabs(StateT[tn].cell_inf[j - 1]) >= s))
605 else if ((j < i2 - 1) && (fabs(StateT[tn].cell_inf[j]) < s))
608 if (j == i2 - 1) f = 0;
613 f = (StateT[tn].cell_inf[j] < 0);
618 int fct = ((P.DoDigitalContactTracing) && (t >= AdUnits[Mcells[si->mcell].adunit].DigitalContactTracingTimeStart)
619 && (t < AdUnits[Mcells[si->mcell].adunit].DigitalContactTracingTimeStart + P.DigitalContactTracingPolicyDuration) && (Hosts[ci].digitalContactTracingUser == 1));
627 int l = c->InvCDF[(int)floor(s * 1024)];
628 while (c->cum_trans[l] < s) l++;
629 Cell* ct = CellLookup[l];
632 int m = (int)(ranf_mt(tn) * ((double)ct->S0));
633 int i3 = ct->susceptible[m];
634 s2 = dist2(Hosts + i3, Hosts + ci);
635 s = numKernel(s2) / c->max_trans[l];
637 if ((ranf_mt(tn) >= s) || (abs(Hosts[i3].inf) == InfStat_Dead))
643 if ((!Hosts[i3].Travelling) && ((c != ct) || (Hosts[i3].hh != si->hh)))
646 Microcell* mt = Mcells + Hosts[i3].mcell;
647 s = CalcSpatialSusc(i3, ts, ci, tn);
653 if (Hosts[i3].digitalContactTracingUser && (ci != i3))
655 if ((Hosts[ci].ncontacts<P.MaxDigitalContactsToTrace)&&(ranf_mt(tn) < s*P.ProportionDigitalContactsIsolate))
657 Hosts[ci].ncontacts++;
658 int ad = Mcells[Hosts[i3].mcell].adunit;
659 if ((StateT[tn].ndct_queue[ad] < AdUnits[ad].n))
662 StateT[tn].dct_queue[ad][StateT[tn].ndct_queue[ad]++] = { i3,ci,ts };
666 fprintf(stderr_shared,
"No more space in queue! Thread: %i, AdUnit: %i\n", tn, ad);
671 s /= P.ScalingFactorSpatialDigitalContacts;
675 s *= CalcPersonSusc(i3, ts, ci, tn);
678 if ((dist2_raw(Households[si->hh].loc_x, Households[si->hh].loc_y,
679 Households[Hosts[i3].hh].loc_x, Households[Hosts[i3].hh].loc_y) > P.MoveRestrRadius2))
680 s *= P.MoveRestrEffect;
682 else if ((mt->moverest != mi->moverest) && ((mt->moverest == 2) || (mi->moverest == 2)))
683 s *= P.MoveRestrEffect;
684 if ((!f)&& (HOST_ABSENT(i3)))
686 for (m = f2 = 0; (m < P.PlaceTypeNum) && (!f2); m++)
687 if (Hosts[i3].PlaceLinks[m] >= 0)
689 f2 = PLACE_CLOSED(m, Hosts[i3].PlaceLinks[m]);
691 if (f2) { s *= P.PlaceCloseSpatialRelContact; }
694 if ((s == 1) || (ranf_mt(tn) < s))
696 cq = ((int)(ct - Cells)) % P.NumThreads;
697 if ((Hosts[i3].inf == InfStat_Susceptible) && (StateT[tn].n_queue[cq] < P.InfQueuePeakLength))
699 if ((P.FalsePositiveRate > 0) && (ranf_mt(tn) < P.FalsePositiveRate))
700 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = { -1, i3, -1 };
703 short int infect_type = 2 + 2 * NUM_PLACE_TYPES + INFECT_TYPE_MASK * (1 + si->infect_type / INFECT_TYPE_MASK);
704 StateT[tn].inf_queue[cq][StateT[tn].n_queue[cq]++] = { ci, i3, infect_type };
717 #pragma omp parallel for schedule(static,1) default(none) \ 718 shared(t, run, P, StateT, Hosts, ts) 719 for (
int j = 0; j < P.NumThreads; j++)
721 for (
int k = 0; k < P.NumThreads; k++)
723 for (
int i = 0; i < StateT[k].n_queue[j]; i++)
725 int infector = StateT[k].inf_queue[j][i].infector;
726 int infectee = StateT[k].inf_queue[j][i].infectee;
727 short int infect_type = StateT[k].inf_queue[j][i].infect_type;
728 Hosts[infectee].infector = infector;
729 Hosts[infectee].infect_type = infect_type;
730 if (infect_type == -1)
731 DoFalseCase(infectee, t, ts, j);
733 DoInfect(infectee, t, j, run);
735 StateT[k].n_queue[j] = 0;
740 void IncubRecoverySweep(
double t,
int run)
743 unsigned short int ts;
744 ts = (
unsigned short int) (P.TimeStepsPerDay * t);
747 for (
int i = 0; i < P.NumHolidays; i++)
749 ht = P.HolidayStartTime[i] + P.PreControlClusterIdHolOffset;
750 if ((t + P.TimeStep >= ht) && (t < ht))
753 for (
int j = 0; j < P.PlaceTypeNum; j++)
755 #pragma omp parallel for schedule(static,1) default(none) shared(P, Places, Hosts, i, j, ht) 756 for(
int tn=0;tn<P.NumThreads;tn++)
757 for (
int k = tn; k < P.Nplace[j]; k+=P.NumThreads)
759 if ((P.HolidayEffect[j] < 1) && ((P.HolidayEffect[j] == 0) || (ranf_mt(tn) >= P.HolidayEffect[j])))
761 int l = (int)(ht * P.TimeStepsPerDay);
762 if (Places[j][k].close_start_time > l) Places[j][k].close_start_time = (
unsigned short) l;
763 int b = (int)((ht + P.HolidayDuration[i]) * P.TimeStepsPerDay);
764 if (Places[j][k].close_end_time < b) Places[j][k].close_end_time = (
unsigned short) b;
765 for (
int ci = 0; ci < Places[j][k].n; ci++)
767 if (Hosts[Places[j][k].members[ci]].absent_start_time > l) Hosts[Places[j][k].members[ci]].absent_start_time = (
unsigned short)l;
768 if (Hosts[Places[j][k].members[ci]].absent_stop_time < b) Hosts[Places[j][k].members[ci]].absent_stop_time = (
unsigned short)b;
776 #pragma omp parallel for schedule(static,1) default(none) shared(t, run, P, CellLookup, Hosts, AdUnits, Mcells, StateT, ts) 777 for (
int tn = 0; tn < P.NumThreads; tn++)
778 for (
int b = tn; b < P.
NCP; b += P.NumThreads)
780 Cell* c = CellLookup[b];
781 for (
int j = ((
int)c->L - 1); j >= 0; j--)
782 if (ts >= Hosts[c->latent[j]].latent_time)
783 DoIncub(c->latent[j], ts, tn, run);
785 for (
int j = c->I - 1; j >= 0; j--)
787 int ci = c->infected[j];
790 unsigned short int tc;
792 tc = si->latent_time + ((int)(P.LatentToSymptDelay / P.TimeStep));
793 if ((P.DoSymptoms) && (ts == tc))
794 DoCase(ci, t, ts, tn);
798 if (ts >= si->SARI_time) DoSARI(ci, tn);
799 if (ts >= si->Critical_time) DoCritical(ci, tn);
800 if (ts >= si->RecoveringFromCritical_time) DoRecoveringFromCritical(ci, tn);
801 if (ts >= si->recovery_or_death_time)
804 DoDeath_FromCriticalorSARIorILI(ci, tn);
806 DoRecover_FromSeverity(ci, tn);
811 if (ts >= si->recovery_or_death_time)
815 DoRecover(ci, tn, run);
820 if (HOST_TREATED(ci) && (ranf_mt(tn) < P.TreatDeathDrop))
821 DoRecover(ci, tn, run);
823 DoDeath(ci, tn, run);
827 if ((P.DoDigitalContactTracing) && (Hosts[ci].latent_time>= AdUnits[Mcells[Hosts[ci].mcell].adunit].DigitalContactTracingTimeStart) && (Hosts[ci].recovery_or_death_time < AdUnits[Mcells[Hosts[ci].mcell].adunit].DigitalContactTracingTimeStart + P.DigitalContactTracingPolicyDuration) && (Hosts[ci].digitalContactTracingUser == 1) && (P.OutputDigitalContactDist))
829 if (Hosts[ci].ncontacts > MAX_CONTACTS) Hosts[ci].ncontacts = MAX_CONTACTS;
831 StateT[tn].contact_dist[Hosts[ci].ncontacts]++;
839 void DigitalContactTracingSweep(
double t)
850 unsigned short int ts;
853 ts = (
unsigned short int) (P.TimeStepsPerDay * t);
855 FILE* stderr_shared = stderr;
856 #pragma omp parallel for schedule(static,1) default(none) \ 857 shared(t, P, AdUnits, StateT, Hosts, ts, stderr_shared) 858 for (
int tn = 0; tn < P.NumThreads; tn++)
860 for (
int i = tn; i < P.NumAdunits; i += P.NumThreads)
862 if (t >= AdUnits[i].DigitalContactTracingTimeStart)
864 for (
int j = 0; j < P.NumThreads; j++)
866 for (
int k = 0; k < StateT[j].ndct_queue[i];)
870 int infector = StateT[j].dct_queue[i][k].index;
871 int contact = StateT[j].dct_queue[i][k].contact;
872 unsigned short int contact_time = StateT[j].dct_queue[i][k].contact_time;
874 unsigned short int dct_start_time, dct_end_time;
880 dct_start_time = Hosts[contact].dct_trigger_time;
881 dct_end_time = dct_start_time + (
unsigned short int)(P.LengthDigitalContactIsolation * P.TimeStepsPerDay);
888 if (Hosts[infector].dct_trigger_time < (USHRT_MAX - 1))
890 if (contact_time > Hosts[infector].dct_trigger_time)
893 dct_start_time = contact_time + (
unsigned short int) (P.DigitalContactTracingDelay * P.TimeStepsPerDay);
898 dct_start_time = Hosts[infector].dct_trigger_time + (
unsigned short int) (P.DigitalContactTracingDelay * P.TimeStepsPerDay);
900 dct_end_time = dct_start_time + (
unsigned short int)(P.LengthDigitalContactIsolation * P.TimeStepsPerDay);
904 dct_start_time = USHRT_MAX - 1;
907 dct_end_time = Hosts[infector].recovery_or_death_time;
912 if (dct_start_time == ts)
915 if ((infector==-1) && (Hosts[contact].index_case_dct == 0))
917 Hosts[contact].index_case_dct = 1;
921 if (Hosts[contact].digitalContactTraced == 0)
924 if (AdUnits[i].ndct < AdUnits[i].n)
926 Hosts[contact].dct_start_time = dct_start_time;
927 Hosts[contact].dct_end_time = dct_end_time;
928 Hosts[contact].digitalContactTraced = 1;
936 if (Hosts[contact].index_case_dct == 1)
939 Hosts[contact].dct_test_time = dct_start_time + (
unsigned short int)(P.DelayToTestIndexCase * P.TimeStepsPerDay);
941 if ((Hosts[contact].dct_test_time >= Hosts[contact].latent_time) && (Hosts[contact].dct_test_time < Hosts[contact].recovery_or_death_time))
944 if ((P.SensitivityDCT == 0) || ((P.SensitivityDCT < 1) && (ranf_mt(tn) >= P.SensitivityDCT)))
946 Hosts[contact].dct_end_time = Hosts[contact].dct_test_time;
948 if (P.RemoveContactsOfNegativeIndexCase) Hosts[contact].index_case_dct = 2;
955 if ((P.SpecificityDCT == 1) || ((P.SpecificityDCT > 0) && (ranf_mt(tn) < P.SpecificityDCT)))
958 Hosts[contact].dct_end_time = Hosts[contact].dct_test_time;
959 if (P.RemoveContactsOfNegativeIndexCase) Hosts[contact].index_case_dct = 2;
963 else if (Hosts[contact].index_case_dct == 0)
966 if ((Hosts[infector].index_case_dct == 2) && (P.RemoveContactsOfNegativeIndexCase))
969 Hosts[contact].dct_end_time = Hosts[infector].dct_end_time;
974 Hosts[contact].dct_test_time = dct_start_time + (
unsigned short int)(P.DelayToTestDCTContacts * P.TimeStepsPerDay);
980 AdUnits[i].dct[AdUnits[i].ndct] = contact;
984 StateT[tn].cumDCT_adunit[i]++;
988 StateT[j].dct_queue[i][k] = StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1];
989 StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1] = { contact,infector,contact_time };
990 StateT[j].ndct_queue[i]--;
994 fprintf(stderr_shared,
"No more space in queue! AdUnit: %i, ndct=%i, max queue length: %i\n", i, AdUnits[i].ndct, AdUnits[i].n);
995 fprintf(stderr_shared,
"Error!\n");
1000 else if (Hosts[contact].digitalContactTraced == 1)
1006 if ((Hosts[contact].index_case_dct == 1) && (Hosts[contact].dct_test_time > (dct_start_time + (
unsigned short int)(P.DelayToTestIndexCase * P.TimeStepsPerDay))))
1008 Hosts[contact].dct_test_time = dct_start_time + (
unsigned short int)(P.DelayToTestIndexCase * P.TimeStepsPerDay);
1010 Hosts[contact].dct_end_time = dct_end_time;
1012 if ((Hosts[contact].dct_test_time >= Hosts[contact].latent_time) && (Hosts[contact].dct_test_time < Hosts[contact].recovery_or_death_time))
1015 if ((P.SensitivityDCT == 0) || ((P.SensitivityDCT < 1) && (ranf_mt(tn) >= P.SensitivityDCT)))
1017 Hosts[contact].dct_end_time = Hosts[contact].dct_test_time;
1019 if (P.RemoveContactsOfNegativeIndexCase) Hosts[contact].index_case_dct = 2;
1026 if ((P.SpecificityDCT == 1) || ((P.SpecificityDCT > 0) && (ranf_mt(tn) < P.SpecificityDCT)))
1029 Hosts[contact].dct_end_time = Hosts[contact].dct_test_time;
1030 if (P.RemoveContactsOfNegativeIndexCase) Hosts[contact].index_case_dct = 2;
1038 if ((!P.RemoveContactsOfNegativeIndexCase) || ((P.RemoveContactsOfNegativeIndexCase) && (Hosts[infector].index_case_dct == 1)))
1041 Hosts[contact].dct_end_time = dct_end_time;
1050 Hosts[contact].dct_end_time = dct_end_time;
1054 StateT[j].dct_queue[i][k] = StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1];
1055 StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1] = { contact,infector,contact_time };
1056 StateT[j].ndct_queue[i]--;
1060 else if ((dct_start_time == (USHRT_MAX - 1)) && (dct_end_time == ts))
1063 StateT[j].dct_queue[i][k] = StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1];
1064 StateT[j].dct_queue[i][StateT[j].ndct_queue[i] - 1] = { contact,infector,contact_time };
1065 StateT[j].ndct_queue[i]--;
1078 #pragma omp parallel for schedule(static,1) default(none) \ 1079 shared(t, P, AdUnits, Hosts, ts) 1080 for (
int tn = 0; tn < P.NumThreads; tn++)
1082 for (
int i = tn; i < P.NumAdunits; i += P.NumThreads)
1084 if (t >= AdUnits[i].DigitalContactTracingTimeStart)
1086 for (
int j = 0; j < AdUnits[i].ndct;)
1088 int contact = AdUnits[i].dct[j];
1093 if ((Hosts[contact].dct_test_time == ts) && (Hosts[contact].index_case_dct == 0))
1096 if ((abs(Hosts[contact].inf) == 2) || (Hosts[contact].inf == -1))
1099 if ((P.SensitivityDCT == 0) || ((P.SensitivityDCT < 1) && (ranf_mt(tn) >= P.SensitivityDCT)))
1101 Hosts[contact].dct_end_time = ts;
1104 else if (P.FindContactsOfDCTContacts)
1107 Hosts[contact].index_case_dct = 1;
1109 Hosts[contact].dct_trigger_time = ts + 1;
1111 if (Hosts[contact].inf == 2)
1113 DoDetectedCase(contact, t, ts, tn);
1114 Hosts[contact].detected = 1; Hosts[contact].detected_time = ts;
1122 if ((P.SpecificityDCT == 1) || ((P.SpecificityDCT > 0) && (ranf_mt(tn) < P.SpecificityDCT)))
1124 Hosts[contact].dct_end_time = ts;
1130 else if (P.FindContactsOfDCTContacts)
1133 if ((Hosts[contact].index_case_dct == 0) && ((abs(Hosts[contact].inf) == 2) || (Hosts[contact].inf == -1)))
1137 Hosts[contact].index_case_dct = 1;
1139 Hosts[contact].dct_trigger_time = ts + 1;
1141 if (Hosts[contact].inf == 2)
1143 DoDetectedCase(contact, t, ts, tn);
1144 Hosts[contact].detected = 1; Hosts[contact].detected_time = ts;
1150 if (Hosts[contact].dct_end_time == ts)
1153 Hosts[contact].digitalContactTraced = 0;
1155 if (Hosts[contact].index_case_dct)
1157 Hosts[contact].index_case_dct = 0;
1163 AdUnits[i].dct[j] = AdUnits[i].dct[AdUnits[i].ndct - 1];
1164 AdUnits[i].dct[AdUnits[i].ndct - 1] = contact;
1177 int TreatSweep(
double t)
1181 int f, f1, f2, f3, f4;
1185 unsigned short int ts;
1186 unsigned short int tstf;
1187 unsigned short int tstb;
1188 unsigned short int tsvb;
1189 unsigned short int tspf;
1190 unsigned short int tsmb;
1191 unsigned short int tsmf;
1192 unsigned short int tssdf;
1193 unsigned short int tskwpf;
1197 ts = (
unsigned short int) (P.TimeStepsPerDay * t);
1199 if (P.DoGlobalTriggers)
1201 if (P.DoPerCapitaTriggers)
1202 global_trig = (int)floor(((
double)State.trigDC) * P.GlobalIncThreshPop / ((
double)P.
PopSize));
1204 global_trig = State.trigDC;
1210 if ((P.DoPlaces) && (t >= P.TreatTimeStart) && (t < P.TreatTimeStart + P.TreatPlaceGeogDuration) && (State.cumT < P.TreatMaxCourses))
1212 tstf = (
unsigned short int) (P.TimeStepsPerDay * (t + P.TreatDelayMean + P.TreatProphCourseLength));
1214 #pragma omp parallel for private(f) reduction(+:f1) schedule(static,1) default(none) \ 1215 shared(P, StateT, Places, Hosts, ts, tstf) 1216 for (
int i = 0; i < P.NumThreads; i++)
1217 for (
int j = 0; j < P.PlaceTypeNum; j++)
1219 for (
int k = 0; k < StateT[i].np_queue[j]; k++)
1221 int l = StateT[i].p_queue[j][k];
1222 if (P.DoPlaceGroupTreat)
1224 f = StateT[i].pg_queue[j][k];
1225 for (
int m = ((
int)Places[j][l].group_start[f]); m < ((int)(Places[j][l].group_start[f] + Places[j][l].group_size[f])); m++)
1237 if ((!HOST_TO_BE_TREATED(Places[j][l].members[m])) && ((P.TreatPlaceTotalProp[j] == 1) || (ranf_mt(i) < P.TreatPlaceTotalProp[j])))
1238 DoProph(Places[j][l].members[m], ts, i);
1243 if ((Places[j][l].treat) && (!PLACE_TREATED(j, l)))
1246 Places[j][l].treat_end_time = tstf;
1247 for (
int m = 0; m < Places[j][l].n; m++)
1248 if (!HOST_TO_BE_TREATED(Places[j][l].members[m]))
1250 if ((P.TreatPlaceTotalProp[j] == 1) || (ranf_mt(i) < P.TreatPlaceTotalProp[j]))
1251 DoProph(Places[j][l].members[m], ts, i);
1254 Places[j][l].treat = 0;
1257 StateT[i].np_queue[j] = 0;
1262 if ((P.DoMassVacc) && (t >= P.VaccTimeStart))
1263 for (
int j = 0; j < 2; j++)
1265 int m = (int)P.VaccMaxCourses;
1266 if (m > State.n_mvacc) m = State.n_mvacc;
1267 #pragma omp parallel for schedule(static,1000) default(none) \ 1268 shared(State, m, ts) 1269 for (
int i = State.mvacc_cum; i < m; i++)
1270 DoVacc(State.mvacc_queue[i], ts);
1271 State.mvacc_cum = m;
1273 if ((t >= P.TreatTimeStart) || (t >= P.VaccTimeStartGeo) || (t >= P.PlaceCloseTimeStart) || (t >= P.MoveRestrTimeStart) || (t >= P.SocDistTimeStart) || (t >= P.KeyWorkerProphTimeStart))
1275 tstf = (
unsigned short int) (P.TimeStepsPerDay * (t + P.TreatProphCourseLength) - 1);
1276 tstb = (
unsigned short int) (P.TimeStepsPerDay * (t + P.TreatDelayMean));
1277 tsvb = (
unsigned short int) (P.TimeStepsPerDay * (t + P.VaccDelayMean));
1278 tspf = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + P.PlaceCloseDelayMean + P.PlaceCloseDuration));
1279 tsmf = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + P.MoveRestrDuration));
1280 tsmb = (
unsigned short int) floor(P.TimeStepsPerDay * (t + P.MoveDelayMean));
1281 tssdf = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + P.SocDistDurationCurrent));
1282 tskwpf = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + P.KeyWorkerProphRenewalDuration));
1283 nckwp = (int)ceil(P.KeyWorkerProphDuration / P.TreatProphCourseLength);
1285 #pragma omp parallel for private(f2,f3,f4,r) reduction(+:f) schedule(static,1) default(none) \ 1286 shared(t, P, Hosts, Mcells, McellLookup, AdUnits, State, global_trig, ts, tstf, tstb, tsvb, tspf, tsmf, tsmb, tssdf, tskwpf, nckwp) 1287 for (
int tn = 0; tn < P.NumThreads; tn++)
1288 for (
int bs = tn; bs < P.NMCP; bs += P.NumThreads)
1290 int b = (int)(McellLookup[bs] - Mcells);
1291 int adi = (P.DoAdUnits) ? Mcells[b].adunit : -1;
1292 int ad = (P.DoAdUnits) ? AdUnits[adi].
id : 0;
1305 if ((Mcells[b].treat == 2) && (ts >= Mcells[b].treat_end_time))
1308 Mcells[b].treat = 0;
1310 if ((Mcells[b].treat == 1) && (ts >= Mcells[b].treat_start_time))
1313 Mcells[b].treat = 2;
1314 Mcells[b].treat_trig = 0;
1315 Mcells[b].treat_end_time = tstf;
1316 for (
int i = 0; i < Mcells[b].n; i++)
1318 int l = Mcells[b].members[i];
1319 if ((!HOST_TO_BE_TREATED(l)) && ((P.TreatPropRadial == 1) || (ranf_mt(tn) < P.TreatPropRadial)))
1320 DoProphNoDelay(l, ts, tn, 1);
1323 if (P.DoGlobalTriggers)
1324 f2 = (global_trig >= P.TreatCellIncThresh);
1325 else if (P.DoAdminTriggers)
1327 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.TreatCellIncThresh)) / P.IncThreshPop)) : (
int)P.TreatCellIncThresh;
1328 f2 = (State.trigDC_adunit[adi] > trig_thresh);
1332 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.TreatCellIncThresh)) / P.IncThreshPop)) : (
int)P.TreatCellIncThresh;
1333 f2 = (Mcells[b].treat_trig >= trig_thresh);
1335 if ((t >= P.TreatTimeStart) && (Mcells[b].treat == 0) && (f2) && (P.TreatRadius2 > 0))
1338 Direction j = Right;
1344 if ((!P.TreatByAdminUnit) || (ad > 0))
1346 int ad2 = ad / P.TreatAdminUnitDivisor;
1349 if (P.is_in_bounds(min))
1351 if (P.TreatByAdminUnit)
1352 f4 = (AdUnits[Mcells[k].adunit].id / P.TreatAdminUnitDivisor == ad2);
1354 f4 = ((r = dist2_mm(Mcells + b, Mcells + k)) < P.TreatRadius2);
1358 if ((Mcells[k].n > 0) && (Mcells[k].treat == 0))
1360 Mcells[k].treat_start_time = tstb;
1361 Mcells[k].treat = 1;
1362 maxx += Mcells[k].n;
1379 k = P.get_micro_cell_index_from_position(min);
1380 }
while ((f3) && (maxx < P.TreatMaxCoursesPerCase));
1391 if ((Mcells[b].vacc == 1) && (ts >= Mcells[b].vacc_start_time))
1394 Mcells[b].vacc_trig = 0;
1397 for (
int i = 0; i < Mcells[b].n; i++)
1399 int l = Mcells[b].members[i];
1401 if (((P.VaccProp == 1) || (ranf_mt(tn) < P.VaccProp)))
1404 DoVaccNoDelay(l,ts);
1410 if (P.DoGlobalTriggers)
1411 f2 = (global_trig >= P.VaccCellIncThresh);
1412 else if (P.DoAdminTriggers)
1414 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.VaccCellIncThresh)) / P.IncThreshPop)) : (
int)P.VaccCellIncThresh;
1415 f2 = (State.trigDC_adunit[adi] > trig_thresh);
1419 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.VaccCellIncThresh)) / P.IncThreshPop)) : (
int)P.VaccCellIncThresh;
1420 f2 = (Mcells[b].treat_trig >= trig_thresh);
1422 if ((!P.DoMassVacc) && (P.VaccRadius2 > 0) && (t >= P.VaccTimeStartGeo) && (Mcells[b].vacc == 0) && (f2))
1425 Direction j = Right;
1430 if ((!P.VaccByAdminUnit) || (ad > 0))
1432 int ad2 = ad / P.VaccAdminUnitDivisor;
1435 if (P.is_in_bounds(min))
1437 if (P.VaccByAdminUnit)
1439 f4 = (AdUnits[Mcells[k].adunit].id / P.VaccAdminUnitDivisor == ad2);
1443 f4 = ((r = dist2_mm(Mcells + b, Mcells + k)) < P.VaccRadius2);
1447 if (r < P.VaccMinRadius2)
1449 else if ((Mcells[k].n > 0) && (Mcells[k].vacc == 0))
1451 Mcells[k].vacc_start_time = tsvb;
1469 k = P.get_micro_cell_index_from_position(min);
1480 if (P.DoGlobalTriggers)
1481 f2 = (global_trig < P.PlaceCloseCellIncStopThresh);
1482 else if (P.DoAdminTriggers)
1484 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.PlaceCloseCellIncStopThresh)) / P.IncThreshPop)) : P.PlaceCloseCellIncStopThresh;
1485 f2 = (State.trigDC_adunit[adi] < trig_thresh);
1489 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.PlaceCloseCellIncStopThresh)) / P.IncThreshPop)) : P.PlaceCloseCellIncStopThresh;
1490 f2 = (Mcells[b].treat_trig < trig_thresh);
1492 if ((Mcells[b].placeclose == 2) && ((f2) || (ts >= Mcells[b].place_end_time)))
1495 Mcells[b].placeclose = P.DoPlaceCloseOnceOnly;
1496 Mcells[b].place_end_time = ts;
1497 Mcells[b].place_trig = 0;
1500 for (
int j2 = 0; j2 < P.PlaceTypeNum; j2++)
1501 if (j2 != P.HotelPlaceType)
1502 for (
int i2 = 0; i2 < Mcells[b].np[j2]; i2++)
1503 DoPlaceOpen(j2, Mcells[b].places[j2][i2], ts, tn);
1508 if ((P.DoPlaces) && (t >= P.PlaceCloseTimeStart) && (Mcells[b].placeclose == 0))
1512 if (P.DoGlobalTriggers)
1514 f2 = (global_trig >= P.PlaceCloseCellIncThresh);
1516 else if (P.DoAdminTriggers)
1518 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.PlaceCloseCellIncThresh)) / P.IncThreshPop)) : P.PlaceCloseCellIncThresh;
1519 f2 = (State.trigDC_adunit[adi] > trig_thresh);
1523 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.PlaceCloseCellIncThresh)) / P.IncThreshPop)) : P.PlaceCloseCellIncThresh;
1524 f2 = (Mcells[b].treat_trig >= trig_thresh);
1526 if (((P.PlaceCloseByAdminUnit) && (AdUnits[Mcells[b].adunit].place_close_trig < USHRT_MAX - 1)
1527 && (((
double)AdUnits[Mcells[b].adunit].place_close_trig) / ((
double)AdUnits[Mcells[b].adunit].NP) > P.PlaceCloseAdunitPropThresh))
1528 || ((!P.PlaceCloseByAdminUnit) && (f2)))
1531 int interventionFlag;
1532 interventionFlag = 1;
1533 if ((P.DoInterventionDelaysByAdUnit)&&((t <= AdUnits[Mcells[b].adunit].PlaceCloseTimeStart) || (t >= (AdUnits[Mcells[b].adunit].PlaceCloseTimeStart + AdUnits[Mcells[b].adunit].PlaceCloseDuration))))
1534 interventionFlag = 0;
1536 if ((interventionFlag == 1)&&((!P.PlaceCloseByAdminUnit) || (ad > 0)))
1538 if ((Mcells[b].n > 0) && (Mcells[b].placeclose == 0))
1541 if (P.DoInterventionDelaysByAdUnit)
1542 Mcells[b].place_end_time = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + P.PlaceCloseDelayMean + AdUnits[Mcells[b].adunit].PlaceCloseDuration));
1544 Mcells[b].place_end_time = tspf;
1545 Mcells[b].place_trig = 0;
1546 Mcells[b].placeclose = 2;
1547 for (
int j2 = 0; j2 < P.PlaceTypeNum; j2++)
1548 if (j2 != P.HotelPlaceType)
1549 for (
int i2 = 0; i2 < Mcells[b].np[j2]; i2++)
1550 DoPlaceClose(j2, Mcells[b].places[j2][i2], ts, tn, 1);
1561 if ((Mcells[b].moverest == 2) && (ts >= Mcells[b].move_end_time))
1564 Mcells[b].moverest = P.DoMoveRestrOnceOnly;
1566 if ((Mcells[b].moverest == 1) && (ts >= Mcells[b].move_start_time))
1569 Mcells[b].moverest = 2;
1570 Mcells[b].move_trig = 0;
1571 Mcells[b].move_end_time = tsmf;
1573 if (P.DoGlobalTriggers)
1574 f2 = (global_trig >= P.MoveRestrCellIncThresh);
1575 else if (P.DoAdminTriggers)
1577 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.MoveRestrCellIncThresh)) / P.IncThreshPop)) : P.MoveRestrCellIncThresh;
1578 f2 = (State.trigDC_adunit[adi] > trig_thresh);
1582 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.MoveRestrCellIncThresh)) / P.IncThreshPop)) : P.MoveRestrCellIncThresh;
1583 f2 = (Mcells[b].treat_trig >= trig_thresh);
1586 if ((t >= P.MoveRestrTimeStart) && (Mcells[b].moverest == 0) && (f2))
1589 Direction j = Direction::Right;
1594 if ((!P.MoveRestrByAdminUnit) || (ad > 0))
1596 int ad2 = ad / P.MoveRestrAdminUnitDivisor;
1599 if (P.is_in_bounds(min))
1601 if (P.MoveRestrByAdminUnit)
1602 f4 = (AdUnits[Mcells[k].adunit].id / P.MoveRestrAdminUnitDivisor == ad2);
1604 f4 = ((r = dist2_mm(Mcells + b, Mcells + k)) < P.MoveRestrRadius2);
1608 if ((Mcells[k].n > 0) && (Mcells[k].moverest == 0))
1610 Mcells[k].move_start_time = tsmb;
1611 Mcells[k].moverest = 1;
1622 if (j == 1) { f3 = f2; f2 = 0; }
1624 k = P.get_micro_cell_index_from_position(min);
1634 if (P.DoGlobalTriggers)
1635 f2 = (global_trig < P.SocDistCellIncStopThresh);
1636 else if (P.DoAdminTriggers)
1638 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.SocDistCellIncStopThresh)) / P.IncThreshPop)) : P.SocDistCellIncStopThresh;
1639 f2 = (State.trigDC_adunit[adi] < trig_thresh);
1643 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.SocDistCellIncStopThresh)) / P.IncThreshPop)) : P.SocDistCellIncStopThresh;
1644 f2 = (Mcells[b].treat_trig < trig_thresh);
1648 if ((t >= P.SocDistTimeStart) && (Mcells[b].socdist == 2) && ((f2) || (ts >= Mcells[b].socdist_end_time)))
1651 Mcells[b].socdist = P.DoSocDistOnceOnly;
1652 Mcells[b].socdist_trig = 0;
1653 Mcells[b].socdist_end_time = ts;
1655 if (P.DoGlobalTriggers)
1656 f2 = (global_trig >= P.SocDistCellIncThresh);
1657 else if (P.DoAdminTriggers)
1659 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.SocDistCellIncThresh)) / P.IncThreshPop)) : P.SocDistCellIncThresh;
1660 f2 = (State.trigDC_adunit[adi] >= trig_thresh);
1664 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.SocDistCellIncThresh)) / P.IncThreshPop)) : P.SocDistCellIncThresh;
1665 f2 = (Mcells[b].treat_trig >= trig_thresh);
1667 if ((t >= P.SocDistTimeStart) && (Mcells[b].socdist == 0) && (f2))
1670 int interventionFlag;
1671 interventionFlag = 1;
1673 if (P.DoInterventionDelaysByAdUnit)
1674 if ((t <= AdUnits[Mcells[b].adunit].SocialDistanceTimeStart) ||
1675 (t >= (AdUnits[Mcells[b].adunit].SocialDistanceTimeStart + AdUnits[Mcells[b].adunit].SocialDistanceDuration)))
1676 interventionFlag = 0;
1678 if (interventionFlag == 1)
1679 if ((Mcells[b].n > 0) && (Mcells[b].socdist == 0))
1681 Mcells[b].socdist = 2;
1682 Mcells[b].socdist_trig = 0;
1683 if (P.DoInterventionDelaysByAdUnit)
1685 Mcells[b].socdist_end_time = (
unsigned short int) ceil(P.TimeStepsPerDay * (t + AdUnits[Mcells[b].adunit].SocialDistanceDuration));
1687 Mcells[b].socdist_end_time = tssdf;
1696 if ((Mcells[b].keyworkerproph == 2) && (ts >= Mcells[b].keyworkerproph_end_time))
1699 Mcells[b].keyworkerproph = P.DoKeyWorkerProphOnceOnly;
1701 if (P.DoGlobalTriggers)
1702 f2 = (global_trig >= P.KeyWorkerProphCellIncThresh);
1703 else if (P.DoAdminTriggers)
1705 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(AdUnits[adi].n * P.KeyWorkerProphCellIncThresh)) / P.IncThreshPop)) : P.KeyWorkerProphCellIncThresh;
1706 f2 = (State.trigDC_adunit[adi] > trig_thresh);
1710 int trig_thresh = (P.DoPerCapitaTriggers) ? ((
int)ceil(((
double)(Mcells[b].n * P.KeyWorkerProphCellIncThresh)) / P.IncThreshPop)) : P.KeyWorkerProphCellIncThresh;
1711 f2 = (Mcells[b].treat_trig >= trig_thresh);
1713 if ((P.DoPlaces) && (t >= P.KeyWorkerProphTimeStart) && (Mcells[b].keyworkerproph == 0) && (f2))
1716 Direction j = Right;
1723 if (P.is_in_bounds(min))
1724 if (dist2_mm(Mcells + b, Mcells + k) < P.KeyWorkerProphRadius2)
1727 if ((Mcells[k].n > 0) && (Mcells[k].keyworkerproph == 0))
1729 Mcells[k].keyworkerproph = 2;
1730 Mcells[k].keyworkerproph_trig = 0;
1731 Mcells[k].keyworkerproph_end_time = tskwpf;
1732 for (
int i2 = 0; i2 < Mcells[k].n; i2++)
1734 int j2 = Mcells[k].members[i2];
1735 if ((Hosts[j2].keyworker) && (!HOST_TO_BE_TREATED(j2)))
1736 DoProphNoDelay(j2, ts, tn, nckwp);
1753 k = P.get_micro_cell_index_from_position(min);
1758 for (
int i = 0; i < P.NumThreads; i++)
1760 State.cumT += StateT[i].cumT;
1761 State.cumTP += StateT[i].cumTP;
1762 State.cumUT += StateT[i].cumUT;
1764 StateT[i].cumT = StateT[i].cumUT = StateT[i].cumTP = 0;
The basic unit of the simulation and is associated to a geographical location.
double height_
The height.
DomainSize in_cells_
Size of spatial domain in cells.