-
Notifications
You must be signed in to change notification settings - Fork 16
/
SS_readdata_330.tpl
5082 lines (4803 loc) · 183 KB
/
SS_readdata_330.tpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// SS_Label_file #3. **SS_readdata.tpl**
// SS_Label_file # * read *data_file* named in starter.ss
// SS_Label_file # * create arrays for data with dimensioning defined dynamically
// SS_Label_file # * creates link from each data element to area/time/fleet that datum occur, and other arrays with specification of which data types occur in each area/time
// SS_Label_file # * uses function found in SS_global: <u>get_data_timing()</u>
// SS_Label_file # * read *forecast.ss*
// SS_Label_file # * note that this extends the time dimension of some arrays, so is read before readcontrol
// SS_Label_Flow read data file named in starter.ss file
// SS_Label_Info_2.0 #READ DATA FILE
// SS_Label_Info_2.1 #Read comments and dimension info
// SS_Label_Info_2.1.1 #Read and save comments at top of data file
number fif // end of file marker
LOCAL_CALCS
// clang-format on
//
ad_comm::change_datafile_name(datfilename);
if (finish_starter == 999)
{
warnstream << "finish_starter=999, so probably used a 3.24 starter.ss; please update";
write_message(WARN, 0);
finish_starter = 3.30;
}
cout << " reading from data file" << endl;
ifstream Data_Stream(datfilename); // even if the global_datafile name is used, there still is a different logical device created
k = 0;
N_DC = 0;
while (k == 0)
{
Data_Stream >> readline; // reads the line from input stream
if (length(readline) > 2)
{
checkchar = readline(1);
k = strcmp(checkchar, "#");
checkchar = readline(1, 2);
j = strcmp(checkchar, "#C");
if (j == 0)
{
N_DC++;
Data_Comments += readline;
}
}
}
// clang-format off
END_CALCS
!!// SS_Label_Info_2.1.2 #Read model time dimensions
int read_seas_mo; // 1=read integer season; 2=read real months
LOCAL_CALCS
// clang-format on
read_seas_mo = 2;
// clang-format off
END_CALCS
int N_subseas; // number of subseasons within season; must be even number to get one to be mid_season
ivector timing_constants(1,6);
LOCAL_CALCS
// clang-format on
*(ad_comm::global_datafile) >> styr; //start year of the model
echoinput << styr << " start year " << endl;
*(ad_comm::global_datafile) >> endyr; // end year of the model
echoinput << endyr << " end year " << endl;
*(ad_comm::global_datafile) >> nseas; // number of seasons
echoinput << nseas << " N seasons " << endl;
// clang-format off
END_CALCS
init_vector seasdur(1,nseas); // season duration; enter in units of months, fractions OK; will be rescaled to sum to 1.0 if total is greater than 11.9
LOCAL_CALCS
// clang-format on
echoinput << seasdur << " months/seas (fractions OK) " << endl;
*(ad_comm::global_datafile) >> N_subseas;
echoinput << N_subseas << " Number of subseasons (even number only; min 2) for calculation of ALK " << endl;
mid_subseas = N_subseas / 2 + 1;
timing_constants(1) = read_seas_mo;
timing_constants(2) = nseas;
timing_constants(3) = N_subseas;
timing_constants(4) = mid_subseas;
timing_constants(5) = styr;
timing_constants(6) = endyr;
// clang-format off
END_CALCS
int TimeMax;
int TimeMax_Fcast_std;
int ALK_time_max;
int eq_yr;
int bio_yr;
number sumseas;
// SS_Label_Info_2.1.3 #Set up seasons
vector seasdur_half(1,nseas); // half a season
matrix subseasdur(1,nseas,1,N_subseas); // cumulative time, within season, for each subseas
vector subseasdur_delta(1,nseas); // length of each subseason
vector azero_seas(1,nseas); // cumulative time, within year, up until begin of this season
LOCAL_CALCS
// clang-format on
sumseas = sum(seasdur);
if (sumseas >= 11.9)
{
seasdur /= sumseas;
seas_as_year = 0;
sumseas = 12.0; // to be sure it is exactly 12.
}
else
{
seasdur /= 12.;
seas_as_year = 1;
// sumseas will now be used as the duration of the pseudo-year, rather than assuming year has 12 months;
if (nseas > 1)
{
warnstream << "Error. Can only have 1 season when during seasons as psuedo-years.";
write_message (FATAL, 0);
}
}
seasdur_half = seasdur * 0.5; // half a season
subseasdur_delta = seasdur / double(N_subseas);
TimeMax = styr + (endyr + 50 - styr) * nseas + nseas - 1;
retro_yr = endyr + retro_yr;
ALK_time_max = (endyr - styr + 51) * nseas * N_subseas; // sets maximum size for data array indexing 50 years into forecast
// ALK_time_max will be redefined after reading forecast's YrMax to accomodate forecasts longer than the 50 year data limit
azero_seas(1) = 0.;
if (nseas > 1)
{
for (s = 2; s <= nseas; s++) /* SS_loop: calculate azero_seas from cumulative sum of seasdur(s) */
{
azero_seas(s) = sum(seasdur(1, s - 1));
}
}
subseasdur.initialize();
for (s = 1; s <= nseas; s++) /* SS_loop: for each season */
{
for (subseas = 2; subseas <= N_subseas; subseas++) /* SS_loop: calculate cumulative time within season to start of each subseas */
{
subseasdur(s, subseas) = subseasdur(s, subseas - 1) + seasdur(s) / double(N_subseas);
}
}
echoinput << seasdur << " processed season duration (frac. of year) " << endl;
echoinput << subseasdur_delta << " processed subseason duration (frac. of year) " << endl;
echoinput << " processed subseason cumulative annual time within season " << endl
<< subseasdur << endl;
if (seas_as_year == 1)
{
warnstream << "Season durations sum to <11.9, so SS3 assumes you are doing years as pseudo-seasons." << endl
<< "There can be only 1 season in this timestep and SS3 will ignore month input and assume all observation occur at middle of this pseudo-year" << endl
<< "mortality, growth and movement rates are per annum, so will get multiplied by the duration of this timestep as they are used." << endl
<< "What gets reported as age is now age in timesteps; and input of age-specific M or K requires one entry per timestep" << endl
<< "Similarly, output of age-specific quantities is in terms of number of timesteps, not real years" << endl
<< "spawn_month and settlement_month in control file are best set to 1.0 when doing years as pseudo-seasons" << endl;
write_message(WARN, 1);
}
// clang-format off
END_CALCS
// SPAWN-RECR: define spawning season
init_number spawn_rd;
number spawn_month; // month that spawning occurs
int spawn_seas; // spawning occurs in this season
int spawn_subseas; //
number spawn_time_seas; // real time within season for mortality calculation
LOCAL_CALCS
// clang-format on
if (read_seas_mo == 1) // so reading values of integer season
{
spawn_seas = spawn_rd;
spawn_month = 1.0 + azero_seas(spawn_seas) / sumseas;
spawn_subseas = 1;
spawn_time_seas = 0.0;
}
else // reading values of month
{
spawn_month = spawn_rd;
temp1 = (spawn_month - 1.0) / sumseas; // spawn_month as fraction of year
if (spawn_month >= 13.0)
{
warnstream << "Fatal error. spawn_month must be <13.0, end of year is 12.99, value read is: " << spawn_month;
write_message (FATAL, 0);
}
spawn_seas = 1; // earlist possible spawn_seas;
spawn_subseas = 1; // earliest possible subseas in spawn_seas
temp = azero_seas(spawn_seas) + subseasdur_delta(spawn_seas); // starting value
while (temp <= temp1 + 1.0e-9)
{
if (spawn_subseas == N_subseas)
{
spawn_seas++;
spawn_subseas = 1;
}
else
{
spawn_subseas++;
}
temp += subseasdur_delta(spawn_seas);
}
// spawn_time_seas = (temp1 - azero_seas(spawn_seas)) / seasdur(spawn_seas); // incorrect: remaining fraction of year converted to fraction of season
spawn_time_seas = (temp1 - azero_seas(spawn_seas)); // timing in units of fraction of year such that exp(-Z*spawn_time_seas) will be correct
}
echoinput << "SPAWN month: " << spawn_month << "; seas: " << spawn_seas << "; subseas_for_ALK: " << spawn_subseas << "; spawntiming as frac. of year: " << spawn_time_seas << endl;
if (spawn_seas > nseas)
{
warnstream << " spawn_seas index must be <= nseas ";
write_message(WARN, 0);
}
// clang-format off
END_CALCS
int pop; // number of areas
int gender_rd;
int gender; // number of sexes
int nages; // maxage as accumulator
int nages2; // doubled vector to store males after females = gender*nages+gender-1
int Nsurvey;
int Nfleet;
int Nfleet1; // used with 3.24 for number of fishing fleets
LOCAL_CALCS
// clang-format on
{
*(ad_comm::global_datafile) >> gender_rd;
gender = abs(gender_rd);
if (gender_rd < 0)
echoinput << "gender read is negative, so total spawnbiomass will be multiplied by frac_female parameter" << endl;
*(ad_comm::global_datafile) >> nages;
echoinput << gender << " N sexes " << endl
<< "Accumulator age " << nages << endl;
*(ad_comm::global_datafile) >> pop;
echoinput << pop << " N_areas " << endl;
*(ad_comm::global_datafile) >> Nfleet;
Nfleet1 = 0;
Nsurvey = 0;
nages2 = gender * nages + gender - 1;
echoinput << Nfleet << " total number of fishing fleets and surveys " << endl;
// define some useful labels
MGtype_Lbl += "natmort";
MGtype_Lbl += "growth";
MGtype_Lbl += "wtlen";
MGtype_Lbl += "recr_dist";
MGtype_Lbl += "migration";
MGtype_Lbl += "ageerror";
MGtype_Lbl += "catchmult";
MGtype_Lbl += "hermaphro";
MGtype_Lbl += "null9";
MGtype_Lbl += "selectivity";
MGtype_Lbl += "rel_F";
MGtype_Lbl += "recruitment";
echoinput << "MGtype labels: "<< MGtype_Lbl << endl;
}
// clang-format off
END_CALCS
// SS_Label_Info_2.1.5 #Define fleets, surveys, predators and areas
imatrix pfleetname(1,Nfleet,1,2);
ivector fleet_type(1,Nfleet); // 1=fleet with catch; 2=discard only fleet with F; 3=survey(ignore catch); 4=M2=predator
int N_bycatch; // number of bycatch only fleets
int N_pred; // number of predator fleets
ivector N_catchfleets(0,pop); // number of bycatch plus landed catch fleets by area
imatrix fish_fleet_area(0,pop,0,Nfleet); // list of catch_fleets that are type 1 or 2, so have a F
ivector predator(1,Nfleet); // list of "fleets" that are type 4
ivector predator_rev(1,Nfleet); // predator ID given f
imatrix predator_area(0,pop,0,Nfleet); // list of predators by area
ivector need_catch_mult(1,Nfleet); // 0=no, 1=need catch_multiplier parameter
vector surveytime(1,Nfleet); // (-1, 1) code for fisheries to indicate use of season-wide observations, or specifically timed observations
ivector fleet_area(1,Nfleet); // areas in which each fleet/survey/predator operates
vector catchunits1(1,Nfleet); // 1=biomass; 2=numbers
// vector catch_se_rd1(1,Nfleet) // units are se of log(catch); use -1 to ignore input catch values for discard only fleets
vector catchunits(1,Nfleet);
// vector catch_se_rd(1,Nfleet)
matrix catch_se(styr-nseas,TimeMax,1,Nfleet);
matrix fleet_setup(1,Nfleet,1,5); // type, timing, area, units, need_catch_mult
matrix bycatch_setup(1,Nfleet,1,6);
// 1: fleet number; must match fleet definitions"<<endl;
// 2: 1=include dead bycatch in total dead catch for F0.1 and MSY optimizations and forecast ABC; 2=omit from total catch for these purposes (but still include the mortality)"<<endl;
// 3: 1=Fmult scales with other fleets; 2=bycatch F constant at input value; 3=mean bycatch F from range of years"<<endl;
// 4: F or first year of range"<<endl;
// 5: last year of range"<<endl;
// 6: not used"<<endl;
ivector YPR_mask(1,Nfleet);
ivector retParmLoc(1,1);
int N_retParm;
LOCAL_CALCS
// clang-format on
bycatch_setup.initialize();
YPR_mask.initialize();
catch_se = 0.01; // initialize to a small value
{
N_bycatch = 0;
N_catchfleets.initialize();
fish_fleet_area.initialize();
predator_area.initialize();
N_pred = 0;
predator.initialize();
echoinput << "rows are fleets; columns are: Fleet_#, fleet_type, timing, area, units, need_catch_mult" << endl;
for (f = 1; f <= Nfleet; f++)
{
*(ad_comm::global_datafile) >> fleet_setup(f)(1, 5);
*(ad_comm::global_datafile) >> anystring;
fleetname += anystring;
fleet_type(f) = int(fleet_setup(f, 1));
if (fleet_type(f) == 2)
N_bycatch++;
surveytime(f) = fleet_setup(f, 2) / fabs(fleet_setup(f, 2));
fleet_setup(f, 2) = surveytime(f);
p = int(fleet_setup(f, 3)); //area
fleet_area(f) = p;
catchunits(f) = int(fleet_setup(f, 4));
need_catch_mult(f) = int(fleet_setup(f, 5));
if (fleet_type(f) <= 2)
{
N_catchfleets(0)++; // overall N
N_catchfleets(p)++; // count by area
fish_fleet_area(0, N_catchfleets(0)) = f; // to find the "f" index for a catchfleet when not within an area loop
fish_fleet_area(p, N_catchfleets(p)) = f; // to find the index when in an area loop
YPR_mask(f) = 1;
if (surveytime(f) != -1.)
{
warnstream << "fishing fleet: " << f << " surveytime read as: " << surveytime(f) << " normally is -1 for fishing fleet; can override for indiv. obs. using 1000+month";
write_message(WARN, 0);
}
}
else if (fleet_type(f) == 3)
{
if (surveytime(f) == -1.)
{
warnstream << "survey fleet: " << f << " surveytime read as: " << surveytime(f) << " SS3 resets to 1 for all survey fleets, and always overridden by indiv. obs. month";
write_message (FATAL, 0);
surveytime(f) = 1.;
}
}
else if (fleet_type(f) == 4) // predator, e.g. red tide
{
N_pred++;
predator(N_pred) = f;
predator_rev(f) = N_pred;
predator_area(0, N_pred) = f; // to find the "f" index for a predator when not within an area loop
predator_area(p, N_pred) = f; // to find the index when in an area loop
surveytime(f) = -1.;
}
if (fleet_type(f) > 1 && need_catch_mult(f) > 0)
{
warnstream << "Need_catch_mult can be used only for fleet_type=1 fleet= " << f;
write_message (FATAL, 0);
}
echoinput << f << " # " << fleet_setup(f) << " # " << fleetname(f) << endl;
if (f > 1) { // check for duplicate fleet names, which will break r4ss
for (int f1 = 1; f1 < f; f1++)
{
if (fleetname(f1) == fleetname(f))
{
warnstream << "duplicate fleet names for fleets: " << f1 << " and " << f << "; " << fleetname(f) << "; SS3 will exit";
write_message (FATAL, 0);
}
}
}
}
if (N_bycatch > 0)
{
echoinput << "Now read bycatch fleet characteristics for " << N_bycatch << " fleets" << endl;
echoinput << "1: fleet number; must match fleet definitions" << endl;
echoinput << "2: 1=include dead bycatch in total dead catch for F0.1 and MSY optimizations and forecast ABC; 2=omit from total catch for these purposes (but still include the mortality)" << endl;
echoinput << "3: 1=Fmult scales with other fleets; 2=bycatch F constant at input value; 3=mean bycatch F from range of years" << endl;
echoinput << "4: F or first year of range" << endl;
echoinput << "5: last year of range" << endl;
echoinput << "6: not used" << endl;
for (j = 1; j <= N_bycatch; j++)
{
*(ad_comm::global_datafile) >> f;
bycatch_setup(f, 1) = f;
*(ad_comm::global_datafile) >> bycatch_setup(f)(2, 6);
if (fleet_type(f) == 2)
{
echoinput << f << " " << fleetname(f) << " bycatch_setup: " << bycatch_setup(f) << endl;
if (bycatch_setup(f, 2) == 2) // omit bycatch fleet catch from YPR optimize
{
YPR_mask(f) = 0;
}
if (bycatch_setup(f, 3) == 3) // check year range
{
if (bycatch_setup(f, 4) < styr)
bycatch_setup(f, 4) = styr;
if (bycatch_setup(f, 5) > retro_yr)
bycatch_setup(f, 5) = retro_yr;
}
}
else
{
warnstream << "fleet " << f << " is in bycatch list but not designated as bycatch fleet";
write_message (FATAL, 0);
}
}
}
echoinput << "YPR_optimize_mask: " << YPR_mask << endl;
Nfleet1 = N_catchfleets(0);
N_retParm = 0;
}
// clang-format off
END_CALCS
// ProgLabel_2.1.5 define genders and max age
ivector age_vector(0,nages);
vector r_ages(0,nages);
vector frac_ages(0,nages);
ivector years(styr,endyr); // vector of the years of the model
vector r_years(styr,endyr);
ivector ALK_subseas_update(1,nseas*N_subseas); // 0 means ALK is OK for this subseas, 1 means that recalc is needed
ivector F_reporting_ages(1,2);
LOCAL_CALCS
// clang-format on
for (a = 0; a <= nages; a++) // SS_loop: fill ivector age vector
age_vector(a) = a;
for (a = 0; a <= nages; a++) // SS_loop: fill real vector r_ages
r_ages(a) = double(a);
frac_ages = r_ages / r_ages(nages);
for (y = styr; y <= endyr; y++)
{ //year vector
years(y) = y;
r_years(y) = y;
}
if (F_reporting == 4 || F_reporting == 5)
{
F_reporting_ages = F_reporting_ages_R;
if (F_reporting_ages(1) > (nages - 2) || F_reporting_ages(1) < 0)
{
warnstream << "reset lower end of F_reporting_ages to be nages-2 ";
write_message(ADJUST, 0);
F_reporting_ages(1) = nages - 2;
}
if (F_reporting_ages(2) > (nages - 2) || F_reporting_ages(2) < 0)
{
warnstream << "reset upper end of F_reporting_ages to be nages-2 ";
write_message(ADJUST, 0);
F_reporting_ages(2) = nages - 2;
}
}
else
{
F_reporting_ages(1) = nages / 2;
F_reporting_ages(2) = F_reporting_ages(1);
}
// clang-format off
END_CALCS
// SS_Label_Info_2.1.6 #Indexes for data timing. "have_data" and "data_time" hold pointers for data occurrence, timing, and ALK need
int data_type;
number data_timing;
4iarray have_data(1,ALK_time_max,0,Nfleet,0,9,0,150);
imatrix have_data_yr(styr,endyr+50,0,Nfleet);
// have_data stores the data index of each datum occurring at time ALK_time, for fleet f of observation type k. Up to 150 data are allowed due to CAAL data
// have_data(ALK_idx,0,0,0) is overall indicator that some datum requires ALK update in this ALK_time
// have_data() 3rd element: 0=any; 1=survey/CPUE/effort; 2=discard; 3=mnwt; 4=length; 5=age; 6=SizeFreq; 7=sizeage; 8=morphcomp; 9=tags
// have_data() 4th element; zero'th element contains N obs for this subseas; allows for 150 observations per datatype per fleet per subseason
3darray data_time(1,ALK_time_max,1,Nfleet,1,3);
// data_time(): first value will hold real month; 2nd is timing within season; 3rd is year.fraction
// for a given fleet x subseas, all observations must have the same specific timing (month.fraction)
// a warning will be given if subsequent observations have a different month.fraction
// an observation's real_month is used to assign it to a season and a subseas within that seas, and it is used to calculate the data_timing within the season for mortality
// where ALK_idx=(y-styr)*nseas*N_subseas+(s-1)*N_subseas+subseas This is index to subseas and used to indicate which ALK is being referenced
// ProgLabel_2.2 Read CATCH amount by fleet
matrix obs_equ_catch(1,nseas,1,Nfleet); // initial, equilibrium catch. now seasonal
LOCAL_CALCS
// clang-format on
have_data.initialize();
have_data_yr.initialize();
obs_equ_catch.initialize();
for (y = 1; y <= ALK_time_max; y++)
for (f = 1; f <= Nfleet; f++)
{
data_time(y, f, 1) = -1.0; // set to illegal value since 0.0 is valid
}
// clang-format off
END_CALCS
!!// SS_Label_Info_2.2 #Read CATCH amount by fleet
int N_ReadCatch;
// int Catch_read;
vector tempvec(1,6); // vector used for temporary reads
LOCAL_CALCS
// clang-format on
ender = 0;
do
{
dvector tempvec(1, 5);
*(ad_comm::global_datafile) >> tempvec(1, 5);
if (tempvec(1) == -9999.)
ender = 1;
catch_read.push_back(tempvec(1, 5));
} while (ender == 0);
N_ReadCatch = catch_read.size() - 1;
echoinput << N_ReadCatch << " records" << endl;
// clang-format off
END_CALCS
matrix catch_ret_obs(1,Nfleet,styr-nseas,TimeMax+nseas);
imatrix catch_record_count(1,Nfleet,styr-nseas,TimeMax+nseas);
3iarray catch_seas_area(styr,TimeMax,1,pop,0,Nfleet);
matrix totcatch_byarea(styr,TimeMax,1,pop);
vector totcat(styr-1,endyr); // by year, not by t
int first_catch_yr;
vector catch_by_fleet(1,Nfleet);
ivector disc_fleet_list(1,Nfleet);
int N_retain_fleets;
int catch_warn;
LOCAL_CALCS
// clang-format on
catch_ret_obs.initialize();
catch_record_count.initialize();
catch_warn = 0;
tempvec.initialize();
for (k = 0; k <= N_ReadCatch - 1; k++)
{
// do read in list format y, s, f, catch, catch_se
tempvec(1, 5) = catch_read[k];
g = tempvec(1);
s = tempvec(2);
f = tempvec(3);
if (g == -999)
{ // designates initial equilibrium
y = styr - 1;
}
else
{
y = g;
}
if (k == 0)
echoinput << "first catch record: " << tempvec(1, 5) << endl;
if (k == (N_ReadCatch - 1))
echoinput << "last catch record: " << tempvec(1, 5) << endl;
if (y >= (styr - 1) && y <= endyr && (g == -999 || g >= styr)) // observation is in date range
{
if (s > nseas)
{
catch_warn++;
s = nseas;
// allows for collapsing multiple season catch data down into fewer seasons
// typically to collapse to annual because accumulation will all be in the index "nseas"
}
if (s > 0)
{
t = styr + (y - styr) * nseas + s - 1;
{
catch_ret_obs(f, t) += tempvec(4);
catch_record_count(f, t)++;
catch_se(t, f) = tempvec(5);
}
}
else // distribute catch equally across seasons
{
for (s = 1; s <= nseas; s++)
{
t = styr + (y - styr) * nseas + s - 1;
{
catch_ret_obs(f, t) += tempvec(4) / nseas;
catch_record_count(f, t)++;
}
}
}
}
}
if (catch_warn > 0) {
if (catch_warn > 1)
warnstream << catch_warn << " catch records have ";
else
warnstream << "one catch record has ";
warnstream << "seas>nseas; perhaps erroneous entry of month rather than season; changed to nseas";
write_message(ADJUST, 0);
}
// warn on duplicate catch records
for (y = styr - 1; y <= endyr; y++)
for (s = 1; s <= nseas; s++)
for (f = 1; f <= Nfleet; f++) {
t = styr + (y - styr) * nseas + s - 1;
if (catch_record_count(f, t) > 1)
{
warnstream << catch_record_count(f, t) << " catch records have been accumulated into year, seas, fleet " << y << " " << s << " " << f << "; total catch= " << catch_ret_obs(f, t);
write_message(WARN, 0);
}
}
obs_equ_catch.initialize();
for (s = 1; s <= nseas; s++)
{
for (f = 1; f <= Nfleet; f++)
if (fleet_type(f) <= 2)
{
obs_equ_catch(s, f) = catch_ret_obs(f, styr - nseas - 1 + s);
}
echoinput << " equ, seas: -1 " << s << " catches: " << obs_equ_catch(s) << endl;
}
for (y = styr; y <= endyr; y++)
for (s = 1; s <= nseas; s++)
{
t = styr + (y - styr) * nseas + s - 1;
echoinput << "year, seas: " << y << " " << s << " catches: " << trans(catch_ret_obs)(t) << endl;
}
// calc total catch by year so can calculate the first year with catch and to omit zero catch years from sdreport
totcat.initialize();
catch_seas_area.initialize();
totcatch_byarea.initialize();
totcat(styr - 1) = sum(obs_equ_catch); // sums over all seasons and fleets
first_catch_yr = 0;
if (totcat(styr - 1) > 0.0)
first_catch_yr = styr - 1;
for (y = styr; y <= endyr; y++)
{
for (s = 1; s <= nseas; s++)
{
t = styr + (y - styr) * nseas + s - 1;
for (p = 1; p <= pop; p++)
for (f = 1; f <= Nfleet; f++)
if (fleet_area(f) == p && catch_ret_obs(f, t) > 0.0 && fleet_type(f) <= 2) // excludes survey and predator fleets
{
catch_seas_area(t, p, f) = 1;
catch_seas_area(t, p, 0) = 1;
if (fleet_type(f) == 1)
totcat(y) += catch_ret_obs(f, t);
if (fleet_type(f) == 1)
totcatch_byarea(t, p) += catch_ret_obs(f, t);
}
}
if (totcat(y) > 0.0 && first_catch_yr == 0)
first_catch_yr = y;
if (y == endyr && totcat(y) == 0.0)
{
warnstream << "catch is 0.0 in endyr; this can cause problem in the benchmark and forecast calculations. ";
write_message(WARN, 0);
}
}
echoinput << endl
<< "#_show_total_catch_by_fleet" << endl;
catch_by_fleet = rowsum(catch_ret_obs);
for (f = 1; f <= Nfleet; f++)
{
echoinput << f << " type: " << fleet_type(f) << " " << fleetname(f) << " catch: " << catch_by_fleet(f);
if (fleet_type(f) == 3 && catch_by_fleet(f) > 0.0)
{
warnstream << " Catch by survey fleet will be ignored " << fleet_type(f);
write_message(WARN, 1);
}
echoinput << endl;
}
// clang-format off
END_CALCS
// SS_Label_Info_2.3 #Read fishery CPUE, effort, and Survey index or abundance
!!echoinput<<endl<<"#_ now read survey characteristics: fleet_#, svyunits, svyerrtype for each fleet "<<endl;
int Svy_N_rd;
int Svy_N;
init_imatrix Svy_units_rd(1,Nfleet,1,4);
ivector Svy_units(1,Nfleet); // 0=num; 1=bio; 2=F; >=30 for special patterns
ivector Svy_errtype(1,Nfleet); // -2=gamma(Cole); -1=normal; 0=lognormal ; 1=lognormal w/ biascorr; >1=T-dist
ivector Svy_sdreport(1,Nfleet); // 0=no sdreport; 1=enable sdreport
int Svy_N_sdreport;
LOCAL_CALCS
// clang-format on
data_type = 1; // for surveys
echoinput << "Units: 0=numbers; 1=biomass; 2=F; >=30 for special patterns" << endl;
echoinput << "Errtype: -2=gamma(future); -1=normal; 0=lognormal ; 1=lognormal w/ biascorr; >1=T-dist with DF=XXX" << endl;
echoinput << "SD_Report: 0=no sdreport; 1=enable sdreport" << endl;
echoinput << "Fleet Units Err_Type SD_Report" << endl;
echoinput << Svy_units_rd << endl;
Svy_units = column(Svy_units_rd, 2);
Svy_errtype = column(Svy_units_rd, 3);
Svy_sdreport = column(Svy_units_rd, 4);
for (f = 1; f<=Nfleet; f++)
{
if (Svy_units(f) >= 35 && Svy_errtype(f) >= 0)
{
warnstream << " survey error type must not be lognormal for surveys of deviations for fleet: " << f << fleetname(f) << endl;
write_message(FATAL, 1);
}
if (Svy_errtype(f) < -2 )
{
warnstream << " survey error type = " << Svy_errtype(f) << " is illegal for fleet: " << f << fleetname(f) << endl;
write_message(FATAL, 1);
}
}
// read survey data
ender = 0;
do
{
dvector tempvec(1, 5);
*(ad_comm::global_datafile) >> tempvec(1, 5);
if (tempvec(1) == -9999.)
ender = 1;
Svy_data.push_back(tempvec(1, 5));
} while (ender == 0);
Svy_N_rd = Svy_data.size() - 1;
echoinput << Svy_N_rd << " nobs_survey " << endl;
// clang-format off
END_CALCS
// init_matrix Svy_data(1,Svy_N_rd,1,5)
// !!if(Svy_N_rd>0) echoinput<<" Svy_data "<<endl<<Svy_data<<endl;
ivector Svy_N_fleet(1,Nfleet); // total N
ivector Svy_N_fleet_use(1,Nfleet); // N in likelihood
int in_superperiod;
ivector Svy_super_N(1,Nfleet); // N super_yrs per fleet
LOCAL_CALCS
// clang-format on
// count the number of observations, exclude those outside the specified year range, count the number of superperiods
Svy_N = 0;
Svy_N_fleet = 0;
Svy_N_fleet_use = 0;
Svy_super_N = 0;
if (Svy_N_rd > 0)
{
for (i = 0; i <= Svy_N_rd - 1; i++)
{
echoinput << Svy_data[i] << endl;
y = Svy_data[i](1);
if (y >= styr)
{
f = abs(Svy_data[i](3)); // negative f turns off observation
Svy_N_fleet(f)++;
if (Svy_data[i](5) < 0)
{
warnstream << "cannot use negative se to indicate superperiods in survey data";
write_message (FATAL, 0);
}
if (Svy_data[i](2) < 0)
Svy_super_N(f)++; // count the super-periods if seas<0
}
}
Svy_N = sum(Svy_N_fleet);
for (f = 1; f <= Nfleet; f++)
if (Svy_super_N(f) > 0)
{
j = Svy_super_N(f) / 2; // because we counted the begin and end
if (2 * j != Svy_super_N(f))
{
warnstream << "unequal number of starts and ends of survey superperiods ";
write_message (FATAL, 0);
}
else
{
Svy_super_N(f) = j;
}
}
}
// check if there are observations for the index before enabling sdreport
for (f = 1; f <= Nfleet; ++f)
{
if (Svy_N_fleet(f) == 0) Svy_sdreport(f) = 0;
}
// clang-format off
END_CALCS
imatrix Svy_time_t(1,Nfleet,1,Svy_N_fleet); // stores the continuous season index (t) for each obs
imatrix Svy_ALK_time(1,Nfleet,1,Svy_N_fleet); // stores the continuous subseas index (ALK_time) for each obs
imatrix Svy_use(1,Nfleet,1,Svy_N_fleet);
matrix Svy_obs(1,Nfleet,1,Svy_N_fleet);
matrix Svy_obs_log(1,Nfleet,1,Svy_N_fleet);
matrix Svy_se_rd(1,Nfleet,1,Svy_N_fleet);
matrix Svy_se(1,Nfleet,1,Svy_N_fleet);
// arrays for Super-years
imatrix Svy_super(1,Nfleet,1,Svy_N_fleet); // indicator used to display start/stop in reports
imatrix Svy_super_start(1,Nfleet,1,Svy_super_N); // where Svy_super_N is a vector
imatrix Svy_super_end(1,Nfleet,1,Svy_super_N);
matrix Svy_super_weight(1,Nfleet,1,Svy_N_fleet);
ivector Svy_styr(1,Nfleet);
ivector Svy_endyr(1,Nfleet);
imatrix Svy_yr(1,Nfleet,1,Svy_N_fleet);
number real_month;
vector timing_input(1,3);
vector timing_r_result(1,3);
vector Svy_minval(1,Nfleet);
vector Svy_maxval(1,Nfleet);
ivector timing_i_result(1,6);
// r_result(1,3) will contain: real_month, data_timing_seas, data_timing_yr,
// i_result(1,6) will contain y, t, s, f, ALK_time, use_midseas
LOCAL_CALCS
// clang-format on
// SS_Label_Info_2.3.1 #Process survey observations, move info into working arrays,create super-periods as needed
Svy_super_N.initialize();
Svy_N_fleet.initialize();
Svy_styr.initialize();
Svy_endyr.initialize();
Svy_yr.initialize();
Svy_minval.initialize();
Svy_minval = 999999999.;
Svy_maxval.initialize();
Svy_maxval = -999999999.;
in_superperiod = 0;
if (Svy_N > 0)
{
for (i = 0; i <= Svy_N_rd - 1; i++) // loop all, including those out of yr range
{
y = Svy_data[i](1);
if (y > endyr + 50)
{
warnstream << "forecast observations cannot be beyond endyr +50";
write_message (FATAL, 0);
}
if (y >= styr)
{
// call a global function to calculate data timing and create various indexes
// function will return: data_timing, ALK_time, real_month, use_midseas
timing_input(1, 3) = Svy_data[i](1, 3);
get_data_timing(timing_input, timing_constants, timing_i_result, timing_r_result, seasdur, subseasdur_delta, azero_seas, surveytime);
f = abs(Svy_data[i](3));
if (y > retro_yr)
Svy_data[i](3) = -f;
Svy_N_fleet(f)++; // count obs by fleet again
j = Svy_N_fleet(f); // index of observation as stored in working array
t = timing_i_result(2);
ALK_time = timing_i_result(5);
// some fleet specific indexes and working versions of the data and se
Svy_time_t(f, j) = t;
Svy_ALK_time(f, j) = ALK_time; // continuous subseas counter in which jth obs from fleet f occurs
Svy_se_rd(f, j) = Svy_data[i](5); // later adjust with varadjust, copy to se_cr_use, then adjust with extra se parameter
if (Svy_data[i](3) < 0)
{
Svy_use(f, j) = -1;
}
else
{
Svy_use(f, j) = 1;
Svy_N_fleet_use(f)++;
}
Svy_obs(f, j) = Svy_data[i](4);
Svy_yr(f, j) = y;
if (Svy_styr(f) == 0 || (y >= styr && y < Svy_styr(f)))
Svy_styr(f) = y; // for dimensioning survey q devs
if (Svy_endyr(f) == 0 || (y <= endyr && y > Svy_endyr(f)))
Svy_endyr(f) = y; // for dimensioning survey q devs
// Svy_styr and Svy_endyr for recruitment surveys will be checked against recdev start and end in readcontrol
if (y >= styr && Svy_data[i](3) > 0)
{
Svy_minval(f) = min(Svy_minval(f), Svy_obs(f, j));
Svy_maxval(f) = max(Svy_maxval(f), Svy_obs(f, j));
}
// some all fleet indexes
if (data_time(ALK_time, f, 1) < 0.0) // so first occurrence of data at ALK_time,f
{ // real_month,fraction of season, year.fraction
data_time(ALK_time, f)(1, 3) = timing_r_result(1, 3);
}
else if (timing_r_result(1) == data_time(ALK_time, f, 1))
{
warnstream << "SURVEY: duplicate survey obs for this time-fleet: y,s,f: " << y << " " << s << " " << f << " SS3 will exit ";
write_message (FATAL, 0);
}
have_data(ALK_time, 0, 0, 0) = 1;
have_data(ALK_time, f, 0, 0) = 1; // so have data of some type in this subseas, for this fleet
have_data(ALK_time, f, data_type, 0)++; // count the number of observations in this subseas
p = have_data(ALK_time, f, data_type, 0); // current number of observations
have_data(ALK_time, f, data_type, p) = j; // store data index for the p'th observation in this subseas
have_data_yr(y, f) = 1; // survey or comp data exist this year
have_data_yr(y, 0) = 1;
// create super_year indexes
if (Svy_data[i](2) < 0) // start or stop a super-period; ALL observations must be continguous in the file
{
Svy_super(f, j) = -1;
if (in_superperiod == 0) // start superperiod
{
Svy_super_N(f)++;
Svy_super_start(f, Svy_super_N(f)) = j;
in_superperiod = 1;
}
else
{
if (in_superperiod == 1) // end superperiod
{
Svy_super_end(f, Svy_super_N(f)) = j;
in_superperiod = 0;
}
else
{
}
}
}
else
{
Svy_super(f, j) = 1;
}
}
}
echoinput << "Successful read of survey data; total N: " << Svy_N << endl;
echoinput << "Index Survey_name N Super_Per Min_val max_val // Observations:" << endl;
for (f = 1; f <= Nfleet; f++)
{
if (Svy_N_fleet(f) > 0)
{
echoinput << f << " " << fleetname(f) << " " << Svy_N_fleet(f) << " " << Svy_super_N(f) << " " << Svy_minval(f) << " " << Svy_maxval(f) << " // " << Svy_obs(f) << endl;
if (Svy_errtype(f) >= 0 && Svy_minval(f) <= 0.)
{
warnstream << "error, SS3 has exited. A fleet uses lognormal error and has an observation <=0.0; fleet: " << f;
write_message (FATAL, 0);
}
}
}
}
Svy_N_sdreport = 0;
for (f = 1; f <= Nfleet; ++f)
{
if (Svy_sdreport(f) > 0)
{
Svy_N_sdreport += Svy_N_fleet(f);
}
}
if (Svy_N_sdreport < 0)
Svy_N_sdreport = 0;
echoinput << "Number of sdreport index values: " << Svy_N_sdreport << endl;
// clang-format off
END_CALCS
init_int Ndisc_fleets;
int nobs_disc; // number of discard records kept in active array
int disc_N_read; // number of records read
ivector disc_N_fleet(1,Nfleet); // kept obs per fleet
ivector disc_N_fleet_use(1,Nfleet); // kept obs per fleet
ivector N_suprper_disc(1,Nfleet); // N super_yrs per obs
LOCAL_CALCS
// clang-format on
// SS_Label_Info_2.4 #read Discard data
echoinput << " note order of discard read is now: N fleets with disc, then if Ndisc_fleets>0 read: fleet, disc_units, disc_error(for 1,Ndisc_fleets), then read obs " << endl;
echoinput << Ndisc_fleets << " N fleets with discard " << endl;
if (Ndisc_fleets > 0)
{
j = Nfleet;
}
else
{
j = 0;
}
data_type = 2; // for discard
// clang-format off
END_CALCS
init_imatrix disc_units_rd(1,Ndisc_fleets,1,3);
ivector disc_units(1,j); // formerly scalar disc_type
ivector disc_errtype(1,j); // formerly scalar DF_disc
vector disc_errtype_r(1,j); // real version for T-dist
vector disc_minval(1,j);
vector disc_maxval(1,j);
LOCAL_CALCS
// clang-format on
disc_units.initialize();
disc_errtype.initialize();
disc_minval.initialize();
disc_minval = 999999999.;
disc_maxval.initialize();
disc_maxval = -999999999.;
nobs_disc = 0;
disc_N_fleet = 0;
disc_N_fleet_use = 0;
N_suprper_disc = 0;
if (Ndisc_fleets > 0)
{
echoinput << "#_discard_units (1=same_as_catchunits(bio/num);2=fraction; 3=numbers)" << endl;
echoinput << "#_discard_error: >0 for DF of T-dist(read CV below); 0 for normal with CV; -1 for normal with se; -2 for lognormal; -3 for trunc normal with CV" << endl;
echoinput << "#_fleet units errtype" << endl;
echoinput << disc_units_rd << endl;
for (j = 1; j <= Ndisc_fleets; j++)
{
f = disc_units_rd(j, 1);
disc_units(f) = disc_units_rd(j, 2);
disc_errtype(f) = disc_units_rd(j, 3);
disc_errtype_r(f) = float(disc_errtype(f));
}
ender = 0;
do
{
dvector tempvec(1, 5);
*(ad_comm::global_datafile) >> tempvec(1, 5);