diff --git a/atlantis/PreRules.am b/atlantis/PreRules.am index 573262a..cee4489 100755 --- a/atlantis/PreRules.am +++ b/atlantis/PreRules.am @@ -100,27 +100,26 @@ endif # AM_CFLAGS += -D SS3_LINK_ENABLED -I$(top_srcdir)/atSS3Link/include #endif -if RASSESS_LINK_ENABLED - AM_CFLAGS += -D RASSESS_LINK_ENABLED -# NOTE: nested if statments # For the R links # A working R installation is required. # R must have been built with the '--enable-R-shlib' option enabled to provide the R shared library # Ensure the R_HOME environment variable is set appropriately # # R_HOME = $(shell R RHOME) -# on Ubuntu Linux + if OS_LINUX - R_HOME = /usr/lib/R - R_BASE = /usr/lib/R +R_BASE = /usr/lib/R +R_HOME = /usr/lib/R endif -# on OS X + if OS_MACOS - R_BASE = /Library/Frameworks/R.framework/Resources - R_HOME = /Library/Frameworks/R.framework/Resources +R_BASE = /Library/Frameworks/R.framework/Resources +R_HOME = /Library/Frameworks/R.framework/Resources endif - AM_CFLAGS += -I$(R_BASE)/include -I/usr/share/R/include - LIBS += -L$(R_BASE)/lib -lR -endif +if RASSESS_LINK_ENABLED +AM_CFLAGS += -D RASSESS_LINK_ENABLED +AM_CFLAGS += -I$(R_BASE)/include -I/usr/share/R/include +LIBS += -L$(R_BASE)/lib -lR +endif \ No newline at end of file diff --git a/atlantis/atecology/atprocess.c b/atlantis/atecology/atprocess.c index f347481..024b5e5 100755 --- a/atlantis/atecology/atprocess.c +++ b/atlantis/atecology/atprocess.c @@ -1941,6 +1941,7 @@ void Calculate_Catch(MSEBoxModel *bm, BoxLayerValues *boxLayerInfo, FILE *llogfp if (FunctGroupArray[guild].isVertebrate == TRUE) { FunctGroupArray[guild].SizeNumCaught[cohort][nf][bm->current_box] += bm->FishingResults[nf][CatchAtAge_result_id]; FunctGroupArray[guild].SizeNumDiscard[cohort][nf][bm->current_box] += bm->FishingResults[nf][DiscardsAtAge_result_id]; + FunctGroupArray[guild].SizeCaught[cohort][nf][bm->current_box] += bm->FishingResults[nf][Catch_result_id]; } } else { bm->RecCatch[bm->current_box][guild][nf] += bm->FishingResults[nf][Catch_result_id]; diff --git a/atlantis/atlantisUtil/atUtilGroupIO.c b/atlantis/atlantisUtil/atUtilGroupIO.c index 8e860bb..ab9e3f5 100755 --- a/atlantis/atlantisUtil/atUtilGroupIO.c +++ b/atlantis/atlantisUtil/atUtilGroupIO.c @@ -840,7 +840,8 @@ int Util_Read_Functional_Group_XML(MSEBoxModel *bm, char *fileName, FILE *llogfp FunctGroupArray[i].X_RS = Util_Alloc_Init_1D_Double(FunctGroupArray[i].numCohortsXnumGenes, 0.0); FunctGroupArray[i].RAssessSpringSurvey = Util_Alloc_Init_2D_Double(bm->nbox, FunctGroupArray[i].numCohortsXnumGenes, 0.0); FunctGroupArray[i].RAssessAutumnSurvey = Util_Alloc_Init_2D_Double(bm->nbox, FunctGroupArray[i].numCohortsXnumGenes, 0.0); - + FunctGroupArray[i].RAssessSpringSurveySize = Util_Alloc_Init_2D_Double(bm->nbox, FunctGroupArray[i].numCohortsXnumGenes, 0.0); + FunctGroupArray[i].RAssessAutumnSurveySize = Util_Alloc_Init_2D_Double(bm->nbox, FunctGroupArray[i].numCohortsXnumGenes, 0.0); FunctGroupArray[i].min_wgt = Util_Alloc_Init_1D_Double(FunctGroupArray[i].numCohortsXnumGenes, 0.0); FunctGroupArray[i].max_wgt = Util_Alloc_Init_1D_Double(FunctGroupArray[i].numCohortsXnumGenes, 0.0); FunctGroupArray[i].rolling_wgt = Util_Alloc_Init_2D_Double(bm->K_rolling_cap_num + 1, FunctGroupArray[i].numCohortsXnumGenes, 0.0); @@ -1289,6 +1290,8 @@ void Free_Functional_Group_Memory(MSEBoxModel *bm) { free4d(FunctGroupArray[i].boxPopRatio); free2d(FunctGroupArray[i].RAssessSpringSurvey); free2d(FunctGroupArray[i].RAssessAutumnSurvey); + free2d(FunctGroupArray[i].RAssessSpringSurveySize); + free2d(FunctGroupArray[i].RAssessAutumnSurveySize); free1d(FunctGroupArray[i].min_wgt); free1d(FunctGroupArray[i].max_wgt); free2d(FunctGroupArray[i].rolling_wgt); diff --git a/atlantis/atlantisUtil/include/atFunctGroup.h b/atlantis/atlantisUtil/include/atFunctGroup.h index 818d720..c176cee 100644 --- a/atlantis/atlantisUtil/include/atFunctGroup.h +++ b/atlantis/atlantisUtil/include/atFunctGroup.h @@ -285,6 +285,9 @@ typedef struct { double ***SizeCaught; /**< Sampled catch - size in catch */ double **RAssessSpringSurvey; /**< Spring survey abundance - for RAssess */ double **RAssessAutumnSurvey; /**< Autumn survey abundance - for RAssess */ + double **RAssessSpringSurveySize; /**< Spring survey size - for RAssess */ + double **RAssessAutumnSurveySize; /**< Autumn survey size - for RAssess */ + /* Used in tracking informaiton for calcualting system cap in fisheries */ double *min_wgt; diff --git a/atlantis/atmanage/atRlinkRAssess.c b/atlantis/atmanage/atRlinkRAssess.c index 3532046..291ddb6 100644 --- a/atlantis/atmanage/atRlinkRAssess.c +++ b/atlantis/atmanage/atRlinkRAssess.c @@ -45,7 +45,7 @@ void Do_RAssess(MSEBoxModel *bm, int species, int year, FILE *llogfp) { } // Reuse SS data generation code - GenData(bm, species, year); + //GenData(bm, species, year); // Not working for RAssess parameterization // Create and Popuate RAssessFile if(!bm->RAssess_initiated[species]) { @@ -89,95 +89,98 @@ FILE * Init_RAssess_File(MSEBoxModel *bm, int species) { } /* Write RAssess input file */ -void Populate_RAssessFile(FILE *fp, MSEBoxModel *bm, int groupIndex){ - int cohort, istock, isex, r, b, nf, this_age; - int iyr = (int)(bm->dayt/365.0); - int Nregions = (int)(bm->RBCestimation.RBCspeciesParam[groupIndex][NumRegions_id]); - int this_year = (int)(bm->dayt/365.0) + bm->RAssessRefYear - 1; // Assumes that as happens on Day 365 it would count first year as RefYear + 1 so need to -1 to get it to RefYear - double catchnum, discardnum, totlandings, catchsize, catchlen, counter1, counter2, this_size, this_length, - numspring, numautumn, calcM; - - for (cohort = 0; cohort < FunctGroupArray[groupIndex].numCohortsXnumGenes; cohort++) { - this_age = cohort * FunctGroupArray[groupIndex].ageClassSize; - fprintf(fp,"%d%s", this_year, bm->RassessColDelimiter); // calendar year - could be model year if needed - fprintf(fp,"%d%s", this_age, bm->RassessColDelimiter); // age – in years - - // TODO: Talk to RAssess about implications of cohort being multipe years - - catchnum = 0.0; - discardnum = 0.0; - totlandings = 0.0; - catchsize = 0.0; - counter1 = 0.0; - counter2 = 0.0; - this_size = 0.0; - this_length = 0.0; - - for (istock = 0; istock < FunctGroupArray[groupIndex].numStocks; istock++){ - for (isex = 0; isex < bm->K_num_sexes; isex++){ - this_size += bm->RBCestimation.RBCspeciesArray[groupIndex].MeanWtAge[istock][isex][cohort][iyr] * 1000.0; // convert weight to g from kg - this_length += bm->RBCestimation.RBCspeciesArray[groupIndex].MeanLenAge[istock][isex][cohort]; - counter1 += 1.0; - } - } - this_size /= counter1; - this_length /= counter1; - - for (nf = 0; nf < bm->K_num_fisheries; nf++) { - for (r = 0; r < Nregions; r++) { - totlandings += bm->RBCestimation.RBCspeciesArray[groupIndex].CatchData[nf][r][iyr] / 1000.0; // As going kg to tonnes - } - for (b = 0; b < bm->nbox; b++) { - catchnum += FunctGroupArray[groupIndex].SizeNumCaught[cohort][nf][b]; // - discardnum += FunctGroupArray[groupIndex].SizeNumDiscard[cohort][nf][b]; - catchsize += FunctGroupArray[groupIndex].SizeCaught[cohort][nf][b]; - counter2 += 1.0; - } - } - catchsize /= counter2; - catchlen = Get_Length(bm, catchsize, groupIndex); - - numspring = 0.0; - numautumn = 0.0; - for (b = 0; b < bm->nbox; b++) { - numspring += FunctGroupArray[groupIndex].RAssessSpringSurvey[cohort][b]; - numautumn += FunctGroupArray[groupIndex].RAssessAutumnSurvey[cohort][b]; - } - - fprintf(fp,"%f%s", catchnum + discardnum, bm->RassessColDelimiter); // total catch (in numbers at age) - fprintf(fp,"%f%s", catchlen, bm->RassessColDelimiter); // mean length at age in the catch in cm - fprintf(fp,"%f%s", catchsize, bm->RassessColDelimiter); // mean weight at age in the catch in grams - fprintf(fp,"%f%s", numspring, bm->RassessColDelimiter); // area swept abundance by age - fprintf(fp,"%f%s", this_size, bm->RassessColDelimiter); // weight at age, in grams - fprintf(fp,"%f%s", this_length, bm->RassessColDelimiter); // length at age in cm - fprintf(fp,"%f%s", FunctGroupArray[groupIndex].scaled_FSPB[cohort], bm->RassessColDelimiter); // proportion mature by age - fprintf(fp,"%f%s", numautumn, bm->RassessColDelimiter); // area swept abundance by age - - if(bm->RAssessFixedM) { - // If a parameter setting - fprintf(fp,"%f%s", FunctGroupArray[groupIndex].speciesParams[assess_nat_mort_id], bm->RassessColDelimiter); - } else { - // If using dynamic value - calcM = 0.0; - for (istock = 0; istock < FunctGroupArray[groupIndex].numStocks; istock++){ - calcM += (bm->calcTrackedMort[groupIndex][cohort][istock][finalM1_id] + bm->calcTrackedMort[groupIndex][cohort][istock][finalM2_id]); - } - fprintf(fp,"%f%s", calcM, bm->RassessColDelimiter); - } - - fprintf(fp,"%f", totlandings); // In tonnes - fprintf(fp,"\n"); +void Populate_RAssessFile(FILE *fp, MSEBoxModel *bm, int species){ + int cohort, this_age, b, nf; + int this_year = (int)(bm->dayt/365.0) + bm->RAssessRefYear - 1; + double catchnum, discardnum, catchsize, catchlen, counter1, this_size, this_length, numspring, numautumn, calcM; + + + for (cohort = 0; cohort < FunctGroupArray[species].numCohortsXnumGenes; cohort++) { + + this_age = cohort * FunctGroupArray[species].ageClassSize; + fprintf(fp,"%d%s", this_year, bm->RassessColDelimiter); // calendar year - could be model year if needed + fprintf(fp,"%d%s", this_age, bm->RassessColDelimiter); // age – in years + + // TODO: Talk to RAssess about implications of cohort being multipe years + + catchnum = 0.0; + discardnum = 0.0; + catchsize = 0.0; + catchlen = 0.0; + counter1 = 0.0; + this_size = 0.0; + this_length = 0.0; + + + for (nf = 0; nf < bm->K_num_fisheries; nf++) { + for (b = 0; b < bm->nbox; b++) { + catchnum += FunctGroupArray[species].SizeNumCaught[cohort][nf][b]; //Numbers caught + discardnum += FunctGroupArray[species].SizeNumDiscard[cohort][nf][b]; //Numbers discarded + catchsize += FunctGroupArray[species].SizeCaught[cohort][nf][b]; //Biomass caught + } + } + if (catchnum > 0.0) { + catchsize /= catchnum; + } else { + catchsize = 0.0; } - fflush(fp); - return; + catchlen = Ecology_Get_Size(bm, species, catchsize, cohort); + catchsize = catchsize * bm->X_CN * mg_2_g; //mg_2_g (0.02) includes wet weight + + numspring = 0.0; + numautumn = 0.0; + for (b = 0; b < bm->nbox; b++) { + numspring += FunctGroupArray[species].RAssessSpringSurvey[cohort][b]; + numautumn += FunctGroupArray[species].RAssessAutumnSurvey[cohort][b]; + + if (FunctGroupArray[species].RAssessSpringSurveySize[cohort][b] > 0.0) { + this_size += FunctGroupArray[species].RAssessSpringSurveySize[cohort][b]; + counter1 += 1.0; + } + } + + if (counter1 > 0.0) { + this_size /= counter1; + } else { + this_size = 0.0; + } + + this_length = Ecology_Get_Size(bm, species, this_size, cohort); + this_size = this_size * bm->X_CN * mg_2_g; + + fprintf(fp,"%f%s", catchnum + discardnum, bm->RassessColDelimiter); // total catch (in numbers at age) + fprintf(fp,"%f%s", catchlen, bm->RassessColDelimiter); // mean length at age in the catch in cm + fprintf(fp,"%f%s", catchsize, bm->RassessColDelimiter); // mean weight at age in the catch in grams + fprintf(fp,"%f%s", numspring, bm->RassessColDelimiter); // area swept abundance by age + fprintf(fp,"%f%s", this_size, bm->RassessColDelimiter); // weight at age, in grams + fprintf(fp,"%f%s", this_length, bm->RassessColDelimiter); // length at age in cm + fprintf(fp,"%f%s", FunctGroupArray[species].scaled_FSPB[cohort], bm->RassessColDelimiter); // proportion mature by age + fprintf(fp,"%f%s", numautumn, bm->RassessColDelimiter); // area swept abundance by age + + if(bm->RAssessFixedM) { + // If a parameter setting + fprintf(fp,"%f%s", FunctGroupArray[species].speciesParams[assess_nat_mort_id], bm->RassessColDelimiter); + } else { + // If using dynamic value + calcM = 0.0; + fprintf(fp,"%f%s", calcM, bm->RassessColDelimiter); + } + + fprintf(fp,"%f", catchsize*catchnum/1e+6); // Landings in tonnes + fprintf(fp,"\n"); + } + fflush(fp); + + return; } + /* Do survey data collection for purposes of RAssess estimate */ void RAssessSurvey(MSEBoxModel *bm, FILE *llogfp) { int springSurvey = 0; int sp, cohort, bb, b, den, sn, rn, k; - double sample_num, survey_num, q, avail, swept_area, rawwgt, rawlngth, rawn, this_wgt; + double sample_num, survey_num, q, avail, rawwgt, rawlngth, rawn; int fishery_id = bm->RAssessFisheryID; if (bm->TofY == bm->RAssessSpringSurveyDay) { @@ -188,7 +191,8 @@ void RAssessSurvey(MSEBoxModel *bm, FILE *llogfp) { for (sp = 0; sp < bm->K_num_tot_sp; sp++) { if (FunctGroupArray[sp].isTAC > 1) { - printf("Doing RAssess Survey for %s\n", FunctGroupArray[sp].groupCode); + fprintf(bm->logFile, "Doing RAssess survey (springSurvey = %d) for %s\n",springSurvey, FunctGroupArray[sp].groupCode); + fflush(bm->logFile); for (cohort = 0; cohort < FunctGroupArray[sp].numCohortsXnumGenes; cohort++) { for (bb = 0; bb < bm->nsbox; bb++) { @@ -198,27 +202,33 @@ void RAssessSurvey(MSEBoxModel *bm, FILE *llogfp) { sn = FunctGroupArray[sp].structNTracers[cohort]; rn = FunctGroupArray[sp].resNTracers[cohort]; - // Just use max size as do mixing in movement so undless sedentary then all same size anyways - for (k = 0; k < bm->boxes[b].nz; k++){ - this_wgt = (bm->boxes[b].tr[k][sn] + bm->boxes[b].tr[k][rn]); - if (this_wgt > rawwgt) { - rawwgt = this_wgt; - } + // Just use max size as do mixing in movement so unless sedentary then all same size anyways + rawwgt = 0.0; + rawn = 0.0; + for (k=0; k < bm->boxes[b].nz; k++) { + rawn += bm->boxes[b].tr[k][den]; + if ((bm->boxes[b].tr[k][sn] + bm->boxes[b].tr[k][rn]) > rawwgt) { + rawwgt = bm->boxes[b].tr[k][sn] + bm->boxes[b].tr[k][rn]; + } } - - rawlngth = Get_Length(bm, rawwgt, sp); + + // This sampling method needs checking, i.e adding error to weight + rawlngth = Ecology_Get_Size(bm, sp, rawwgt, cohort); avail = bm->SP_FISHERYprms[sp][fishery_id][avail_id]; q = Selectivity(bm, rawlngth, fishery_id, avail, 0, bm->logFile); // Also accounts for availability - swept_area = bm->FISHERYprms[fishery_id][swept_area_id] / (bm->boxes[b].area * bm->boxes[b].botz); - rawn = bm->boxes[b].tr[k][den]; sample_num = Assess_Add_Error(bm, flagcount, rawn, k_avgcount, k_varcount); - survey_num = sample_num * q * swept_area; + survey_num = sample_num * q; if (springSurvey) { FunctGroupArray[sp].RAssessSpringSurvey[cohort][b] = survey_num; + FunctGroupArray[sp].RAssessSpringSurveySize[cohort][b] = rawwgt; } else { FunctGroupArray[sp].RAssessAutumnSurvey[cohort][b] = survey_num; + FunctGroupArray[sp].RAssessAutumnSurveySize[cohort][b] = rawwgt; } + + fprintf(bm->logFile, "RAssess Survey: survey_num = %e, rawwgt = %e for ageclass = %d in box = %d\n", survey_num, rawwgt, cohort, b); + fflush(bm->logFile); } } } @@ -227,74 +237,208 @@ void RAssessSurvey(MSEBoxModel *bm, FILE *llogfp) { return; } -/** Reading in the file defining the TAC. Has an assumed format of +/** Reading in the file defining the TAC or Effort. + +The TAC file should have the following format + + fishery_id TAC + ID XX + + where ID is the index of fisheries as in fishery.csv file + and XX is the value of the TAC e.g. + + fishery_id TAC + 0 2e+07 + 1 0e+00 + 2 0e+00 + 3 0e+00 - TAC - XX + The Effort file should have the following format matching the parameters needed for effortmodel = 3 + meff and effort are the same value for each box per fishery - where XX is the value of the TAC e.g. + box fishery_id Effort_hdistrib1 Effort_hdistrib2 Effort_hdistrib3 Effort_hdistrib4 meff1 meff2 meff3 meff4 effort + 0 1 0 0 0 0 1 1 0 1.3 20000 + 1 1 0.2 0.2 0.2 0.2 1 1 0 1.3 20000 + 2 1 0.3 0.3 0.3 0.3 1 1 0 1.3 20000 + 0 3 0 0 0 0 1 1 0 2 5000 + 1 3 0.2 0.2 0.2 0.2 1 1 0 2 5000 + 2 3 0.3 0.3 0.3 0.3 1 1 0 2 5000 - TAC - 10000 */ + void Read_RAssess_output(MSEBoxModel *bm, int species, int year, FILE *llogfp) { - char outname[STRLEN]; - char ch; - FILE *fp; - char *valueStr; - char buffer[STRLEN]; - char seps[] = " ,\t"; - int size = 100; // TODO: Set this to sensible value - int buflen = 200; - double *values = (double *) malloc((size_t)size * sizeof(double)); - char *line_buf = NULL; - size_t line_buf_size = 0; - size_t line_size; - - if(verbose) { - printf("Read_RAssess_output: reading results back in for %s\n", FunctGroupArray[species].groupCode); + char outname[STRLEN]; + FILE *fp; + char buffer[STRLEN]; + + + sprintf(outname, "%s_%s", + FunctGroupArray[species].groupCode, + bm->RAssessRoutName); + + if ((fp = Open_Input_File(bm->destFolder, outname, "rt")) == NULL) { + quit("Cannot open R generated TAC output file %s\n", outname); + } + + /* Read header line */ + if (fgets(buffer, sizeof(buffer), fp) == NULL) { + fprintf(llogfp, + "ERROR-RAssess: Empty R generated TAC output file %s\n", + outname); + fflush(llogfp); + fclose(fp); + quit("Error: empty R generated TAC output file %s\n", outname); + } + + + + /* If header includes "TAC" the TAC values are read in */ + if (strstr(buffer, "TAC") != NULL) { + int fishery_id; + double tac_val; + double total_tac = 0.0; + + fprintf(llogfp, + "RAssess: TAC format detected in %s for species %s\n", + outname, + FunctGroupArray[species].groupCode); + + + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + if (buffer[0] == '\n' || buffer[0] == '\0') { + continue; } - - /** Create filename - was _Rassess.out**/ - sprintf(outname,"%s_%s",FunctGroupArray[species].groupCode, bm->RAssessRoutName); - if ((fp = Open_Input_File(bm->destFolder,outname, "rt")) == NULL) { - quit("Cannot open R generated output file %s\n", outname); + /* Checking format and input of the output file */ + if (sscanf(buffer, "%d%lf", &fishery_id, &tac_val) != 2) { + fprintf(llogfp, + "WARNING-RAssess: Skipping malformed TAC line in %s: %s\n", outname, buffer); + fflush(llogfp); + continue; } - // Get the first line of the file - line_size = getline(&line_buf, &line_buf_size, fp); - /* - if(line_size > 2) { - quit("Error in %s - expected header row not present\n", outname); + if (fishery_id < 0 || fishery_id >= bm->K_num_fisheries) { + fprintf(llogfp, + "WARNING-RAssess: Fishery index %d out of range in %s (valid range 0-%d)\n", + fishery_id, outname, bm->K_num_fisheries - 1); + fflush(llogfp); + continue; } - */ - // Read in data lines - /* Loop for all lines */ - fseek(fp, 0L, 0); - while (fgets(buffer, buflen, fp) != NULL) { - ch = buffer[0]; - - if (ch == '\n') - continue; - - if (strcmp(buffer, "TAC") == 0){ - // Do nothing as header row - } else { - valueStr = strtok(buffer, seps); - if(strlen(valueStr) != 0) { - bm->RBCestimation.RBCspeciesParam[species][RBCest_id] = atof(valueStr); - } - } + if (tac_val < 0.0) { + fprintf(llogfp, + "WARNING-RAssess: Negative TAC value %.3f for species %s, fishery %d in %s\n", + tac_val, + FunctGroupArray[species].groupCode, + fishery_id, + outname); } - fprintf(bm->logFile, "%s RAssessTAC set to %e\n", FunctGroupArray[species].groupCode, bm->RBCestimation.RBCspeciesParam[species][RBCest_id]); - fflush(bm->logFile); + /* Read TAC into array that is used to scale mFC and Effort */ + bm->TACamt[species][fishery_id][now_id] = tac_val; + total_tac += tac_val; - free1d(values); - fclose(fp); - - return; + fprintf(llogfp, + "RAssess: Updated TAC for species %s, fishery %d to %.3f for year %d\n", + FunctGroupArray[species].groupCode, fishery_id, tac_val, year); + } + + /* Store total TAC across fisheries for this species */ + bm->RBCestimation.RBCspeciesParam[species][RBCest_id] = total_tac; + + fprintf(llogfp, + "RAssess: %s total TAC across fisheries set to %.3f\n", + FunctGroupArray[species].groupCode, total_tac); + + } else if (strstr(buffer, "Effort") != NULL || strstr(buffer, "effort") != NULL) { + + int b, fishery_id; + double Effort_hdistrib1, Effort_hdistrib2; + double Effort_hdistrib3, Effort_hdistrib4; + double meff1, meff2, meff3, meff4; + double effort; + + fprintf(llogfp, + "RAssess: Effort format detected in %s for species %s\n", + outname, + FunctGroupArray[species].groupCode); + + while (fgets(buffer, sizeof(buffer), fp) != NULL) { + if (buffer[0] == '\n' || buffer[0] == '\0') { + continue; + } + + if (sscanf(buffer, "%d%d%lf%lf%lf%lf%lf%lf%lf%lf%lf", + &b, &fishery_id, + &Effort_hdistrib1, &Effort_hdistrib2, + &Effort_hdistrib3, &Effort_hdistrib4, + &meff1, &meff2, &meff3, &meff4, + &effort) != 11) { + + fprintf(llogfp, + "WARNING-RAssess: Skipping malformed effort line in %s: %s", + outname, buffer); + fflush(llogfp); + continue; + } + + if (b < 0 || b >= bm->nbox) { + fprintf(llogfp, + "WARNING-RAssess: Box index %d out of range in %s " + "(valid range 0-%d)\n", + b, outname, bm->nbox - 1); + fflush(llogfp); + continue; + } + + if (fishery_id < 0 || fishery_id >= bm->K_num_fisheries) { + fprintf(llogfp, + "WARNING-RAssess: Fishery index %d out of range in %s " + "(valid range 0-%d)\n", + fishery_id, outname, bm->K_num_fisheries - 1); + fflush(llogfp); + continue; + } + + bm->Effort_hdistrib[b][fishery_id][0] = Effort_hdistrib1; + bm->Effort_hdistrib[b][fishery_id][1] = Effort_hdistrib2; + bm->Effort_hdistrib[b][fishery_id][2] = Effort_hdistrib3; + bm->Effort_hdistrib[b][fishery_id][3] = Effort_hdistrib4; + + mEff[fishery_id][0] = meff1; + mEff[fishery_id][1] = meff2; + mEff[fishery_id][2] = meff3; + mEff[fishery_id][3] = meff4; + + bm->FISHERYprms[fishery_id][EffortLevel_id] = effort; + + fprintf(llogfp, + "RAssess: Updated effort for box %d, fishery %d: " + "hdistrib for seasons 1-4 = (%.3f %.3f %.3f %.3f) " + "meff for seasons 1-4 = (%.3f %.3f %.3f %.3f) effort = %.3f\n", + b, + fishery_id, + Effort_hdistrib1, + Effort_hdistrib2, + Effort_hdistrib3, + Effort_hdistrib4, + meff1, + meff2, + meff3, + meff4, + effort); + } + } else { + fprintf(llogfp, + "RAssess: No TAC or Effort found in header of %s for species %s. " + "No values were read.\n", + outname, + FunctGroupArray[species].groupCode); + } + + fflush(llogfp); + fclose(fp); + + return; }