00001
00025 #include "PhysFuelModel.h"
00026
00027 PhysFuelModel * InitPhysFuelModelEmpty() {
00028 PhysFuelModel * pfm = NULL;
00029 int i;
00030
00031 if ( (pfm = (PhysFuelModel *) malloc(sizeof(PhysFuelModel))) == NULL ) {
00032 ERR_ERROR_CONTINUE("Unable to allocate memory for PhysFuelModel. \n", ERR_ENOMEM);
00033 return pfm;
00034 }
00035
00036 pfm->brntype = EnumPhysUnBurnable;
00037 pfm->units = EnumUnknownUnits;
00038 pfm->fdepth = 0.0;
00039 pfm->num_fp = 0;
00040 pfm->fdens = pfm->fsav = pfm->pkrat = 0.0;
00041 for(i = 0; i < EnumNumSizeClasses; i++) {
00042 pfm->load[i] = pfm->sav[i] = pfm->dens[i] = 0.0;
00043 pfm->sarea[i] = pfm->effhn[i] = 0.0;
00044 pfm->awtg[i] = 0.0;
00045 pfm->larea = pfm->darea = 0.0;
00046 pfm->fm[i] = 0.0;
00047 }
00048
00049 return pfm;
00050 }
00051
00052 PhysFuelModel * InitPhysFuelModelFMDFile(FILE * fstream, int model_num) {
00053 PhysFuelModel * pfm = NULL;
00054 int c, i = 0;
00055 char * line = NULL, * token = NULL;
00056 float fmd_vals[PHYS_FM_FMD_NUM_VALUES];
00057
00058 if ( fstream == NULL ) {
00059 ERR_ERROR_CONTINUE("Stream to FMD file not open, PhysFuelModel not retrieved. \n", ERR_EIOFAIL);
00060 return pfm;
00061 }
00062
00063 if ( (pfm = InitPhysFuelModelEmpty()) == NULL ) {
00064 ERR_ERROR_CONTINUE("Unable to allocate memory for PhysFuelModel. \n", ERR_ENOMEM);
00065 return pfm;
00066 }
00067
00068 pfm->brntype = EnumPhysBurnable;
00069 pfm->units = EnumEnglishUnits;
00070
00071
00072 while ( (c = fgetc(fstream)) != EOF ) {
00073 ungetc(c, fstream);
00074
00075 if ( (line = GetLineFStreamIO(fstream)) != NULL ) {
00076
00077 if ( line[0] != *PHYS_FM_FMD_COMMENT_CHAR
00078 && (token = strtok(line, PHYS_FM_FMD_SEPARATOR_CHARS)) != NULL ) {
00079
00080 if ( strcmp(token, PHYS_FM_FMD_KEYWORD_ENGLISH) == 0) {
00081 pfm->units = EnumEnglishUnits;
00082 }
00083
00084 else if ( strcmp(token, PHYS_FM_FMD_KEYWORD_METRIC) == 0) {
00085 pfm->units = EnumMetricUnits;
00086 }
00087
00088 else if ( model_num == atoi(token) ) {
00089
00090 while ( (token = strtok(NULL, PHYS_FM_FMD_SEPARATOR_CHARS)) != NULL ) {
00091 fmd_vals[i] = atof(token);
00092 i++;
00093 }
00094 }
00095 }
00096 free(line);
00097 }
00098
00099 }
00100
00101
00102 if ( i == 0 && pfm != NULL ) {
00103 ERR_ERROR_CONTINUE("Attribute values for model num not retrieved from .FMD file. \n", ERR_ERANGE);
00104 FreePhysFuelModel(pfm);
00105 pfm = NULL;
00106 return pfm;
00107 }
00108
00109
00110 pfm->fdepth = (pfm->units == EnumEnglishUnits) ?
00111 fmd_vals[PHYS_FM_FMD_FBED_DEPTH] : UNITS_CM_TO_M(fmd_vals[PHYS_FM_FMD_FBED_DEPTH]);
00112
00113 pfm->load[EnumD1HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00114 fmd_vals[PHYS_FM_FMD_D1H_LOAD] : UNITS_MGPHA_TO_KGPMSQ(fmd_vals[PHYS_FM_FMD_D1H_LOAD]);
00115 pfm->load[EnumD10HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00116 fmd_vals[PHYS_FM_FMD_D10H_LOAD] : UNITS_MGPHA_TO_KGPMSQ(fmd_vals[PHYS_FM_FMD_D10H_LOAD]);
00117 pfm->load[EnumD100HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00118 fmd_vals[PHYS_FM_FMD_D100H_LOAD] : UNITS_MGPHA_TO_KGPMSQ(fmd_vals[PHYS_FM_FMD_D100H_LOAD]);
00119 pfm->load[EnumLHSizeClass] = (pfm->units == EnumEnglishUnits) ?
00120 fmd_vals[PHYS_FM_FMD_LH_LOAD] : UNITS_MGPHA_TO_KGPMSQ(fmd_vals[PHYS_FM_FMD_LH_LOAD]);
00121 pfm->load[EnumLWSizeClass] = (pfm->units == EnumEnglishUnits) ?
00122 fmd_vals[PHYS_FM_FMD_LW_LOAD] : UNITS_MGPHA_TO_KGPMSQ(fmd_vals[PHYS_FM_FMD_LW_LOAD]);
00123
00124 pfm->sav[EnumD1HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00125 fmd_vals[PHYS_FM_FMD_1H_SAV] : UNITS_CMSAV_TO_MSAV(fmd_vals[PHYS_FM_FMD_1H_SAV]);
00126 pfm->sav[EnumD10HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00127 PHYS_FM_D10H_STD_SAV_ENGLISH : UNITS_FTSAV_TO_MSAV(PHYS_FM_D10H_STD_SAV_ENGLISH);
00128 pfm->sav[EnumD100HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00129 PHYS_FM_D100H_STD_SAV_ENGLISH : UNITS_FTSAV_TO_MSAV(PHYS_FM_D100H_STD_SAV_ENGLISH);
00130 pfm->sav[EnumLHSizeClass] = (pfm->units == EnumEnglishUnits) ?
00131 fmd_vals[PHYS_FM_FMD_LH_SAV] : UNITS_CMSAV_TO_MSAV(fmd_vals[PHYS_FM_FMD_LH_SAV]);
00132 pfm->sav[EnumLWSizeClass] = (pfm->units == EnumEnglishUnits) ?
00133 fmd_vals[PHYS_FM_FMD_LW_SAV] : UNITS_CMSAV_TO_MSAV(fmd_vals[PHYS_FM_FMD_LW_SAV]);
00134
00135 pfm->dens[EnumD1HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00136 PHYS_FM_STD_FP_DENSITY_ENGLISH : UNITS_LBPFT3_TO_KGPM3(PHYS_FM_STD_FP_DENSITY_ENGLISH);
00137 pfm->dens[EnumD10HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00138 PHYS_FM_STD_FP_DENSITY_ENGLISH : UNITS_LBPFT3_TO_KGPM3(PHYS_FM_STD_FP_DENSITY_ENGLISH);
00139 pfm->dens[EnumD100HSizeClass] = (pfm->units == EnumEnglishUnits) ?
00140 PHYS_FM_STD_FP_DENSITY_ENGLISH : UNITS_LBPFT3_TO_KGPM3(PHYS_FM_STD_FP_DENSITY_ENGLISH);
00141 pfm->dens[EnumLHSizeClass] = (pfm->units == EnumEnglishUnits) ?
00142 PHYS_FM_STD_FP_DENSITY_ENGLISH : UNITS_LBPFT3_TO_KGPM3(PHYS_FM_STD_FP_DENSITY_ENGLISH);
00143 pfm->dens[EnumLWSizeClass] = (pfm->units == EnumEnglishUnits) ?
00144 PHYS_FM_STD_FP_DENSITY_ENGLISH : UNITS_LBPFT3_TO_KGPM3(PHYS_FM_STD_FP_DENSITY_ENGLISH);
00145
00146
00147 for(i = 0; i < EnumNumSizeClasses; i++) {
00148 if ( UNITS_FP_GT_ZERO(pfm->load[i]) ) {
00149 pfm->num_fp = pfm->num_fp + 1;
00150 }
00151 }
00152
00153
00154 if ( PhysFuelModelSetDerivedProperties(pfm) ) {
00155 ERR_ERROR_CONTINUE("Unable to initialize PhysFuelModel from .FMD file. \n", ERR_EBADFUNC);
00156 FreePhysFuelModel(pfm);
00157 pfm = NULL;
00158 return pfm;
00159 }
00160
00161 return pfm;
00162 }
00163
00164 PhysFuelModel * InitPhysFuelModelUnBurnable() {
00165 PhysFuelModel * pfm = NULL;
00166
00167 if ( (pfm = InitPhysFuelModelEmpty()) == NULL ) {
00168 ERR_ERROR_CONTINUE("Unable to allocate memory for PhysFuelModel. \n", ERR_ENOMEM);
00169 return pfm;
00170 }
00171
00172 pfm->brntype = EnumPhysUnBurnable;
00173
00174 return pfm;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 int PhysFuelModelSetDerivedProperties(PhysFuelModel * pfm) {
00192 int i;
00193 float tarea, lsav, dsav;
00194
00195 tarea = lsav = dsav = 0.0;
00196
00197
00198 if ( pfm == NULL ) {
00199 ERR_ERROR("Unable to calculate derived properties in PhysFuelModel. \n", ERR_EINVAL);
00200 }
00201
00202
00203 if ( pfm->brntype == EnumPhysUnBurnable ) {
00204 return ERR_SUCCESS;
00205 }
00206
00207
00208 for(i = 0; i < EnumNumSizeClasses; i++) {
00209
00210 if ( UNITS_FP_GT_ZERO(pfm->dens[i]) ) {
00211 pfm->sarea[i] = (pfm->load[i] * pfm->sav[i]) / pfm->dens[i];
00212 }
00213 else {
00214 pfm->sarea[i] = 0.0;
00215 }
00216
00217 if ( pfm->units == EnumEnglishUnits ) {
00218 if ( UNITS_FP_GT_ZERO(pfm->sav[i]) ) {
00219 pfm->effhn[i] = exp(-138.0 / pfm->sav[i]);
00220 }
00221 else {
00222 pfm->effhn[i] = 0.0;
00223 }
00224 }
00225 if ( pfm->units == EnumMetricUnits ) {
00226 if ( UNITS_FP_GT_ZERO(pfm->sav[i]) ) {
00227 pfm->effhn[i] = exp(-1.0 / (0.0022 * pfm->sav[i]));
00228 }
00229 else {
00230 pfm->effhn[i] = 0.0;
00231 }
00232 }
00233
00234 pfm->awtg[i] = 0.0;
00235 }
00236
00237
00238 pfm->larea = pfm->darea = 0.0;
00239 pfm->larea = pfm->sarea[EnumLHSizeClass] + pfm->sarea[EnumLWSizeClass];
00240 pfm->darea = pfm->sarea[EnumD1HSizeClass] + pfm->sarea[EnumD10HSizeClass] + pfm->sarea[EnumD100HSizeClass];
00241
00242
00243 if ( UNITS_FP_GT_ZERO(pfm->larea) ) {
00244 pfm->awtg[EnumLHSizeClass] = pfm->sarea[EnumLHSizeClass] / pfm->larea;
00245 pfm->awtg[EnumLWSizeClass] = pfm->sarea[EnumLWSizeClass] / pfm->larea;
00246 }
00247 if ( UNITS_FP_GT_ZERO(pfm->darea) ) {
00248 pfm->awtg[EnumD1HSizeClass] = pfm->sarea[EnumD1HSizeClass] / pfm->darea;
00249 pfm->awtg[EnumD10HSizeClass] = pfm->sarea[EnumD10HSizeClass] / pfm->darea;
00250 pfm->awtg[EnumD100HSizeClass] = pfm->sarea[EnumD100HSizeClass] / pfm->darea;
00251 }
00252
00253
00254 tarea = pfm->larea + pfm->darea;
00255 pfm->larea = pfm->larea / tarea;
00256 pfm->darea = pfm->darea / tarea;
00257
00258
00259 if ( UNITS_FP_GT_ZERO(pfm->fdepth) ) {
00260 pfm->fdens = (pfm->load[EnumLHSizeClass] + pfm->load[EnumLWSizeClass] + pfm->load[EnumD1HSizeClass] +
00261 pfm->load[EnumD10HSizeClass] + pfm->load[EnumD100HSizeClass]) / pfm->fdepth;
00262 }
00263
00264
00265 lsav = (pfm->awtg[EnumLHSizeClass] * pfm->sav[EnumLHSizeClass]) +
00266 (pfm->awtg[EnumLWSizeClass] * pfm->sav[EnumLWSizeClass]);
00267 dsav = (pfm->awtg[EnumD1HSizeClass] * pfm->sav[EnumD1HSizeClass]) +
00268 (pfm->awtg[EnumD10HSizeClass] * pfm->sav[EnumD10HSizeClass]) +
00269 (pfm->awtg[EnumD100HSizeClass] * pfm->sav[EnumD100HSizeClass]);
00270 pfm->fsav = (pfm->larea * lsav) + (pfm->darea * dsav);
00271
00272
00273 pfm->pkrat = 0.0;
00274 for(i = 0; i < EnumNumSizeClasses; i++) {
00275 if ( UNITS_FP_GT_ZERO(pfm->dens[i]) ) {
00276 pfm->pkrat += pfm->load[i] / pfm->dens[i];
00277 }
00278 }
00279 if ( UNITS_FP_GT_ZERO(pfm->fdepth) ) {
00280 pfm->pkrat /= pfm->fdepth;
00281 }
00282
00283 return ERR_SUCCESS;
00284 }
00285
00286 int PhysFuelModelMetricToEnglish(PhysFuelModel * pfm) {
00287 int i;
00288
00289 if ( pfm == NULL ) {
00290 ERR_ERROR("PhysFuelModel values not initialized, conversion failed. \n", ERR_EINVAL);
00291 }
00292 else if ( pfm->brntype == EnumPhysUnBurnable ) {
00293 ERR_ERROR("PhysFuelModel designated unburnable, conversion failed. \n", ERR_EINVAL);
00294 }
00295 else if ( pfm->units == EnumUnknownUnits ) {
00296 ERR_ERROR("PhysFuelModel units are unknown, unable to convert to ENGLISH. \n", ERR_EINVAL);
00297 }
00298 else if ( pfm->units == EnumEnglishUnits ) {
00299 ERR_ERROR("PhysFuelModel values already ENGLISH, no conversion necessary. \n", ERR_WARNING);
00300 }
00301
00302 pfm->units = EnumEnglishUnits;
00303
00304
00305 for(i = 0; i < EnumNumSizeClasses; i++) {
00306 if ( UNITS_FP_GT_ZERO(pfm->load[i]) ) {
00307 pfm->load[i] = UNITS_KGPMSQ_TO_LBPFTSQ(pfm->load[i]);
00308 }
00309 if ( UNITS_FP_GT_ZERO(pfm->sav[i]) ) {
00310 pfm->sav[i] = UNITS_MSAV_TO_FTSAV(pfm->sav[i]);
00311 }
00312 if ( UNITS_FP_GT_ZERO(pfm->dens[i]) ) {
00313 pfm->dens[i] = UNITS_KGPM3_TO_LBPFT3(pfm->dens[i]);
00314 }
00315 }
00316
00317
00318 if ( UNITS_FP_GT_ZERO(pfm->fdepth) ) {
00319 pfm->fdepth = UNITS_M_TO_FT(pfm->fdepth);
00320 }
00321 if ( UNITS_FP_GT_ZERO(pfm->fdens) ) {
00322 pfm->fdens = UNITS_KGPM3_TO_LBPFT3(pfm->fdens);
00323 }
00324 if ( UNITS_FP_GT_ZERO(pfm->fsav) ) {
00325 pfm->fsav = UNITS_MSAV_TO_FTSAV(pfm->fsav);
00326 }
00327
00328
00329 if ( PhysFuelModelSetDerivedProperties(pfm) ) {
00330 ERR_ERROR("Calculation of derived properties failed during unit conversion. \n", ERR_EBADFUNC);
00331 }
00332
00333 return ERR_SUCCESS;
00334 }
00335
00336 int PhysFuelModelEnglishToMetric(PhysFuelModel * pfm) {
00337 int i;
00338
00339 if ( pfm == NULL ) {
00340 ERR_ERROR("PhysFuelModel values not initialized, conversion failed. \n", ERR_EINVAL);
00341 }
00342 else if ( pfm->brntype == EnumPhysUnBurnable ) {
00343 ERR_ERROR("PhysFuelModel designated unburnable, conversion failed. \n", ERR_EINVAL);
00344 }
00345 else if ( pfm->units == EnumUnknownUnits ) {
00346 ERR_ERROR("PhysFuelModel units are unknown, unable to convert to METRIC. \n", ERR_EINVAL);
00347 }
00348 else if ( pfm->units == EnumMetricUnits ) {
00349 ERR_ERROR("PhysFuelModel values already METRIC, no conversion necessary. \n", ERR_WARNING);
00350 }
00351
00352 pfm->units = EnumMetricUnits;
00353
00354
00355 for(i = 0; i < EnumNumSizeClasses; i++) {
00356 if ( UNITS_FP_GT_ZERO(pfm->load[i]) ) {
00357 pfm->load[i] = UNITS_LBPFTSQ_TO_KGPMSQ(pfm->load[i]);
00358 }
00359 if ( UNITS_FP_GT_ZERO(pfm->sav[i]) ) {
00360 pfm->sav[i] = UNITS_FTSAV_TO_MSAV(pfm->sav[i]);
00361 }
00362 if ( UNITS_FP_GT_ZERO(pfm->dens[i]) ) {
00363 pfm->dens[i] = UNITS_LBPFT3_TO_KGPM3(pfm->dens[i]);
00364 }
00365 }
00366
00367
00368 if ( UNITS_FP_GT_ZERO(pfm->fdepth) ) {
00369 pfm->fdepth = UNITS_FT_TO_M(pfm->fdepth);
00370 }
00371 if ( UNITS_FP_GT_ZERO(pfm->fdens) ) {
00372 pfm->fdens = UNITS_LBPFT3_TO_KGPM3(pfm->fdens);
00373 }
00374 if ( UNITS_FP_GT_ZERO(pfm->fsav) ) {
00375 pfm->fsav = UNITS_FTSAV_TO_MSAV(pfm->fsav);
00376 }
00377
00378
00379 if ( PhysFuelModelSetDerivedProperties(pfm) ) {
00380 ERR_ERROR("Calculation of derived properties failed during unit conversion. \n", ERR_EBADFUNC);
00381 }
00382
00383 return ERR_SUCCESS;
00384 }
00385
00386 void PhysFuelModelDumpToStream(PhysFuelModel * pfm, FILE * fstream) {
00387 if ( pfm == NULL || fstream == NULL ) {
00388 ERR_ERROR_CONTINUE("Unable to dump PhysFuelModel attributes. \n", ERR_EINVAL);
00389 return;
00390 }
00391
00392 switch(pfm->units) {
00393 case EnumUnknownUnits:
00394 fprintf(fstream, "UNITS: UNKNOWN \n");
00395 break;
00396 case EnumEnglishUnits:
00397 fprintf(fstream, "UNITS: ENGLISH \n");
00398 break;
00399 case EnumMetricUnits:
00400 fprintf(fstream, "UNITS: METRIC \n");
00401 break;
00402 default:
00403 fprintf(fstream, "UNITS: <WARNING! NOT RECOGNIZED> \n");
00404 break;
00405 }
00406 fprintf(fstream, "FUEL BED PROPERTIES \n");
00407 fprintf(fstream, "DEPTH: \t\t %f \n", pfm->fdepth);
00408 fprintf(fstream, "NUM FP: \t %d \n", pfm->num_fp);
00409 fprintf(fstream, "FUEL BED CHARACTERISTIC PROPERTIES \n");
00410 fprintf(fstream, "FDENS: \t\t %f \n", pfm->fdens);
00411 fprintf(fstream, "FSAV: \t\t %f \n", pfm->fsav);
00412 fprintf(fstream, "PACKR: \t\t %f \n", pfm->pkrat);
00413 fprintf(fstream, "FUEL PARTICLE PROPERTIES \n");
00414 fprintf(fstream, "SIZE: \t D1H \t\t D10H \t\t D100H \t\t LH \t\t LW \n");
00415 fprintf(fstream, "LOAD: \t %.4f \t %.4f \t %.4f \t %.4f \t %.4f \n",
00416 pfm->load[EnumD1HSizeClass], pfm->load[EnumD10HSizeClass], pfm->load[EnumD100HSizeClass],
00417 pfm->load[EnumLHSizeClass], pfm->load[EnumLWSizeClass] );
00418 fprintf(fstream, "SAV: \t %.4f \t %.4f \t %.4f \t %.4f \t %.4f \n",
00419 pfm->sav[EnumD1HSizeClass], pfm->sav[EnumD10HSizeClass], pfm->sav[EnumD100HSizeClass],
00420 pfm->sav[EnumLHSizeClass], pfm->sav[EnumLWSizeClass] );
00421 fprintf(fstream, "DENS: \t %.4f \t %.4f \t %.4f \t %.4f \t %.4f \n",
00422 pfm->dens[EnumD1HSizeClass], pfm->dens[EnumD10HSizeClass], pfm->dens[EnumD100HSizeClass],
00423 pfm->dens[EnumLHSizeClass], pfm->dens[EnumLWSizeClass] );
00424 fprintf(fstream, "FUEL PARTICLE DERIVED PROPERTIES \n");
00425 fprintf(fstream, "SAREA: \t %f \t %f \t %f \t %f \t %f \n",
00426 pfm->sarea[EnumD1HSizeClass], pfm->sarea[EnumD10HSizeClass], pfm->sarea[EnumD100HSizeClass],
00427 pfm->sarea[EnumLHSizeClass], pfm->sarea[EnumLWSizeClass] );
00428 fprintf(fstream, "EFFHN: \t %f \t %f \t %f \t %f \t %f \n",
00429 pfm->effhn[EnumD1HSizeClass], pfm->effhn[EnumD10HSizeClass], pfm->effhn[EnumD100HSizeClass],
00430 pfm->effhn[EnumLHSizeClass], pfm->effhn[EnumLWSizeClass] );
00431 fprintf(fstream, "FUEL BED WEIGHTING PROPERTIES \n");
00432 fprintf(fstream, "AWTG: \t %f \t %f \t %f \t %f \t %f \n",
00433 pfm->awtg[EnumD1HSizeClass], pfm->awtg[EnumD10HSizeClass], pfm->awtg[EnumD100HSizeClass],
00434 pfm->awtg[EnumLHSizeClass], pfm->awtg[EnumLWSizeClass] );
00435 fprintf(fstream, "LDWTG: \t %f \t %f \t %f \t %f \t %f \n",
00436 pfm->darea, pfm->darea, pfm->darea, pfm->larea, pfm->larea );
00437 fprintf(fstream, "FUEL PARTICLE ENVIRONMENTAL PROPERTIES \n");
00438 fprintf(fstream, "FM: \t %f \t %f \t %f \t %f \t %f \n",
00439 pfm->fm[EnumD1HSizeClass], pfm->fm[EnumD10HSizeClass], pfm->fm[EnumD100HSizeClass],
00440 pfm->fm[EnumLHSizeClass], pfm->fm[EnumLWSizeClass] );
00441 fprintf(fstream, "NOTE: some attributes not user-configurable, assigned default values \n");
00442
00443 return;
00444 }
00445
00446 void FreePhysFuelModel(void * vptr) {
00447 PhysFuelModel * pfm = NULL;
00448 if ( vptr != NULL ) {
00449 pfm = (PhysFuelModel *) vptr;
00450 if ( pfm != NULL ) {
00451 free(pfm);
00452 }
00453 }
00454 pfm = NULL;
00455 return;
00456 }
00457
00458