Changeset 27268
- Timestamp:
- 09/07/22 19:46:13 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/branches/trunk-larour-SLPS2022/src/c/modules/QmuStatisticsx/QmuStatisticsx.cpp
r27267 r27268 6 6 #include "../OutputResultsx/OutputResultsx.h" 7 7 8 int readdata(IssmDouble** pdoublemat, int* pdoublematsize, IssmDouble* pdouble, FILE* fid,char* field,int step){ /*{{{*/9 10 int length;11 char fieldname[1000];12 int fieldname_size;13 IssmDouble rtime;14 int rstep;15 int M,N;16 17 //fields that we retrive:18 IssmDouble dfield;19 char* sfield = NULL;20 IssmDouble* dmatfield = NULL;21 int* imatfield = NULL;22 23 //type of the returned field:24 int type;25 int found=0;26 27 while(1){28 29 size_t ret_code = fread(&fieldname_size, sizeof(int), 1, fid);30 if(ret_code != 1) break; //we are done.31 32 fread(fieldname, sizeof(char), fieldname_size, fid);33 //_printf0_("fieldname: " << fieldname << "\n");34 35 fread(&rtime, sizeof(IssmDouble), 1, fid);36 fread(&rstep, sizeof(int), 1, fid);37 38 //check on field:39 if ((step==rstep) && (strcmp(field,fieldname)==0)){40 41 //ok, go read the result really:42 fread(&type,sizeof(int),1,fid);43 fread(&M,sizeof(int),1,fid);44 if (type==1){45 fread(&dfield,sizeof(IssmDouble),1,fid);46 }47 else if (type==2){48 fread(&M,sizeof(int),1,fid);49 sfield=xNew<char>(M);50 fread(sfield,sizeof(char),M,fid);51 }52 else if (type==3){53 fread(&N,sizeof(int),1,fid);54 dmatfield=xNew<IssmDouble>(M*N);55 fread(dmatfield,sizeof(IssmDouble),M*N,fid);56 }57 else if (type==4){58 fread(&N,sizeof(int),1,fid);59 imatfield=xNew<int>(M*N);60 fread(imatfield,sizeof(int),M*N,fid);61 }62 else _error_("cannot read data of type " << type << "\n");63 found=1;64 break;65 }66 else{67 //just skim to next results.68 fread(&type,sizeof(int),1,fid);69 fread(&M,sizeof(int),1,fid);70 if (type==1){71 fseek(fid,sizeof(IssmDouble),SEEK_CUR);72 }73 else if(type==2){74 fseek(fid,M*sizeof(char),SEEK_CUR);75 }76 else if(type==3){77 fread(&N,sizeof(int),1,fid);78 fseek(fid,M*N*sizeof(IssmDouble),SEEK_CUR);79 }80 else if(type==4){81 fread(&N,sizeof(int),1,fid);82 fseek(fid,M*N*sizeof(int),SEEK_CUR);83 }84 else _error_("cannot read data of type " << type << "\n");85 }86 }87 if(found==0)_error_("cound not find " << field << " at step " << step << "\n");88 89 /*assign output pointers:*/90 *pdoublemat=dmatfield;91 *pdoublematsize=M*N;92 *pdouble=dfield;93 94 /*return:*/95 return type;96 97 }98 /*}}}*/99 int ComputeHistogram(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/100 101 int nsamples;102 char* directory=NULL;103 char* model=NULL;104 char** fields=NULL;105 int* steps=NULL;106 int nsteps;107 int nfields;108 int nbins;109 int range,lower_row,upper_row;110 int nfilesperdirectory;111 112 /*intermediary:*/113 IssmDouble* doublemat=NULL;114 int doublematsize;115 IssmDouble scalar;116 117 /*computation of average and variance itself:*/118 IssmDouble** maxxs = NULL;119 IssmDouble** minxs = NULL;120 int* xtype=NULL;121 int* xsize=NULL;122 123 IssmDouble** maxmeans=NULL;124 IssmDouble** minmeans=NULL;125 int* meanxtype=NULL;126 int* meanxsize=NULL;127 128 /*only work on the statistical communicator: */129 if (color==MPI_UNDEFINED)return 0;130 131 /*Retrieve parameters:*/132 parameters->FindParam(&nfilesperdirectory,QmuNfilesPerDirectoryEnum);133 parameters->FindParam(&nsamples,QmuNsampleEnum);134 parameters->FindParam(&directory,DirectoryNameEnum);135 parameters->FindParam(&model,InputFileNameEnum);136 parameters->FindParam(&fields,&nfields,FieldsEnum);137 parameters->FindParam(&steps,&nsteps,StepsEnum);138 parameters->FindParam(&nbins,NbinsEnum);139 140 /*Get rank from the stat comm communicator:*/141 IssmComm::SetComm(statcomm);142 int my_rank=IssmComm::GetRank();143 144 /*Open files and read them complelety, in a distributed way:*/145 range=DetermineLocalSize(nsamples,IssmComm::GetComm());146 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm());147 148 /*Initialize arrays:*/149 maxmeans=xNew<IssmDouble*>(nfields);150 minmeans=xNew<IssmDouble*>(nfields);151 meanxtype=xNew<int>(nfields);152 meanxsize=xNew<int>(nfields);153 154 maxxs=xNew<IssmDouble*>(nfields*nsteps);155 minxs=xNew<IssmDouble*>(nfields*nsteps);156 xtype=xNew<int>(nfields*nsteps);157 xsize=xNew<int>(nfields*nsteps);158 159 /*Start opening files:*/160 for(int i=(lower_row+1);i<=upper_row;i++){161 _printf0_("reading file #: " << i << "\n");162 char file[1000];163 long int length;164 char* buffer=NULL;165 166 /*string:*/167 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i);168 169 /*open file: */170 _printf0_(" opening file: " << file << "\n");171 FILE* fid=fopen(file,"rb");172 if(fid==NULL)_error_("cound not open file: " << file << "\n");173 174 /*figure out size of file, and read the whole thing:*/175 _printf0_(" reading file:\n");176 fseek(fid, 0, SEEK_END);177 length = ftell (fid);178 fseek(fid, 0, SEEK_SET);179 buffer = xNew<char>(length);180 fread(buffer, sizeof(char), length, fid);181 182 /*close file:*/183 fclose(fid);184 185 /*create a memory stream with this buffer:*/186 _printf0_(" processing file:\n");187 fid=fmemopen(buffer, length, "rb");188 189 /*start reading data from the buffer directly:*/190 for (int f=0;f<nfields;f++){191 char* field=fields[f];192 fseek(fid,0,SEEK_SET);193 for (int j=0;j<nsteps;j++){194 int counter=f*nsteps+j;195 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);196 if(i==(lower_row+1)){197 if(xtype[counter]==1){198 maxxs[counter]=xNew<IssmDouble>(1);199 minxs[counter]=xNew<IssmDouble>(1);200 *maxxs[counter]=scalar;201 *minxs[counter]=scalar;202 xsize[counter]=1;203 }204 else if (xtype[counter]==3){205 maxxs[counter]=xNew<IssmDouble>(doublematsize);206 xMemCpy<IssmDouble>(maxxs[counter],doublemat,doublematsize);207 minxs[counter]=xNew<IssmDouble>(doublematsize);208 xMemCpy<IssmDouble>(minxs[counter],doublemat,doublematsize);209 xsize[counter]=doublematsize;210 xDelete<IssmDouble>(doublemat);211 }212 else _error_("cannot carry out statistics on type " << xtype[counter]);213 }214 else{215 if(xtype[counter]==1){216 *maxxs[counter]=max(*maxxs[counter],scalar);217 *minxs[counter]=min(*minxs[counter],scalar);218 }219 else if (xtype[counter]==3){220 IssmDouble* newmax=maxxs[counter];221 IssmDouble* newmin=minxs[counter];222 for(int k=0;k<doublematsize;k++){223 if(doublemat[k]>newmax[k])newmax[k]=doublemat[k];224 if(doublemat[k]<newmin[k])newmin[k]=doublemat[k];225 }226 xDelete<IssmDouble>(doublemat);227 }228 else _error_("cannot carry out statistics on type " << xtype[counter]);229 }230 }231 }232 _printf0_(" average in time:\n");233 234 /*Deal with average in time: */235 for (int f=0;f<nfields;f++){236 fseek(fid,0,SEEK_SET);237 char* field=fields[f];238 meanxtype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]);239 240 if(meanxtype[f]==1){241 meanxsize[f]=1;242 IssmDouble timemean=0;243 fseek(fid,0,SEEK_SET);244 for (int j=0;j<nsteps;j++){245 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);246 timemean+=scalar/nsteps;247 }248 249 /*Figure out max and min of time means: */250 if(i==(lower_row+1)){251 maxmeans[f]=xNewZeroInit<IssmDouble>(1);252 minmeans[f]=xNewZeroInit<IssmDouble>(1);253 *maxmeans[f]=timemean;254 *minmeans[f]=timemean;255 }256 else{257 *maxmeans[f]=max(*maxmeans[f],timemean);258 *minmeans[f]=min(*minmeans[f],timemean);259 }260 }261 else{262 meanxsize[f]=doublematsize;263 fseek(fid,0,SEEK_SET);264 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize);265 for (int j=0;j<nsteps;j++){266 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);267 for (int k=0;k<doublematsize;k++){268 timemean[k]+=doublemat[k]/nsteps;269 }270 xDelete<IssmDouble>(doublemat);271 }272 273 if(i==(lower_row+1)){274 maxmeans[f]=xNew<IssmDouble>(doublematsize);275 xMemCpy<IssmDouble>(maxmeans[f],timemean,doublematsize);276 minmeans[f]=xNew<IssmDouble>(doublematsize);277 xMemCpy<IssmDouble>(minmeans[f],timemean,doublematsize);278 }279 else{280 IssmDouble* maxx=maxmeans[f];281 IssmDouble* minx=minmeans[f];282 283 for(int k=0;k<doublematsize;k++){284 maxx[k]=max(maxx[k],timemean[k]);285 minx[k]=min(minx[k],timemean[k]);286 }287 maxmeans[f]=maxx;288 minmeans[f]=minx;289 }290 }291 }292 fclose(fid);293 294 /*delete buffer:*/295 xDelete<char>(buffer);296 }297 ISSM_MPI_Barrier(IssmComm::GetComm());298 _printf0_("Done reading files, now computing min and max.\n");299 300 /*We have agregated minx and max across the cluster, now gather across the cluster onto301 *cpu0 and then compute statistics:*/302 for (int f=0;f<nfields;f++){303 int counter0=f*nsteps+0;304 if (xtype[counter0]==1){ /*deal with scalars {{{*/305 for (int j=0;j<nsteps;j++){306 int counter=f*nsteps+j;307 308 /*we are broadcasting doubles:*/309 IssmDouble maxscalar=*maxxs[counter];310 IssmDouble minscalar=*minxs[counter];311 IssmDouble allmaxscalar;312 IssmDouble allminscalar;313 IssmDouble sumscalar_alltimes=0;314 315 ISSM_MPI_Allreduce(&maxscalar,&allmaxscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm());316 ISSM_MPI_Allreduce(&minscalar,&allminscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm());317 318 /*Store broadcasted value for later computation of histograms:*/319 *maxxs[counter]=allmaxscalar;320 *minxs[counter]=allminscalar;321 322 }323 } /*}}}*/324 else{ /*deal with arrays:{{{*/325 326 int size=xsize[counter0];327 for (int j=0;j<nsteps;j++){328 int counter=f*nsteps+j;329 330 /*we are broadcasting double arrays:*/331 IssmDouble* maxx=maxxs[counter];332 IssmDouble* minx=minxs[counter];333 334 IssmDouble* allmax=xNew<IssmDouble>(size);335 IssmDouble* allmin=xNew<IssmDouble>(size);336 337 ISSM_MPI_Allreduce(maxx,allmax,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm());338 ISSM_MPI_Allreduce(minx,allmin,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm());339 340 /*Store broadcasted value for later computation of histograms:*/341 maxxs[counter]=allmax;342 minxs[counter]=allmin;343 }344 } /*}}}*/345 }346 347 /*Now do the same for the time mean fields:*/348 for (int f=0;f<nfields;f++){349 if (meanxtype[f]==1){ /*deal with scalars {{{*/350 351 /*we are broadcasting doubles:*/352 IssmDouble maxscalar=*maxmeans[f];353 IssmDouble minscalar=*minmeans[f];354 IssmDouble allmaxscalar;355 IssmDouble allminscalar;356 357 ISSM_MPI_Allreduce(&maxscalar,&allmaxscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm());358 ISSM_MPI_Allreduce(&minscalar,&allminscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm());359 360 /*Store for later use in histogram computation:*/361 *maxmeans[f]=allmaxscalar;362 *minmeans[f]=allminscalar;363 364 } /*}}}*/365 else{ /*deal with arrays:{{{*/366 367 int size=meanxsize[f];368 369 /*we are broadcasting double arrays:*/370 IssmDouble* maxx=maxmeans[f];371 IssmDouble* minx=minmeans[f];372 373 IssmDouble* allmax=xNew<IssmDouble>(size);374 IssmDouble* allmin=xNew<IssmDouble>(size);375 376 ISSM_MPI_Allreduce(maxx,allmax,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm());377 ISSM_MPI_Allreduce(minx,allmin,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm());378 379 /*Store for later use in histogram computation:*/380 maxmeans[f]=allmax;381 minmeans[f]=allmin;382 383 } /*}}}*/384 }385 386 /*Now that we have the min and max, we can start binning. First allocate387 * histograms, then start filling them:*/388 IssmDouble** histogram=xNew<IssmDouble*>(nfields*nsteps);389 IssmDouble** timehistogram=xNew<IssmDouble*>(nfields);390 391 _printf0_("Start reading files again, this time binning values in the histogram:\n");392 /*Start opening files:*/393 for (int i=(lower_row+1);i<=upper_row;i++){394 _printf0_("reading file #: " << i << "\n");395 char file[1000];396 long int length;397 char* buffer=NULL;398 399 /*string:*/400 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i);401 402 /*open file: */403 _printf0_(" opening file:\n");404 FILE* fid=fopen(file,"rb");405 if(fid==NULL)_error_("cound not open file: " << file << "\n");406 407 /*figure out size of file, and read the whole thing:*/408 _printf0_(" reading file:\n");409 fseek (fid, 0, SEEK_END);410 length = ftell (fid);411 fseek (fid, 0, SEEK_SET);412 buffer = xNew<char>(length);413 fread (buffer, sizeof(char), length, fid);414 415 /*close file:*/416 fclose (fid);417 418 /*create a memory stream with this buffer:*/419 _printf0_(" processing file:\n");420 fid=fmemopen(buffer, length, "rb");421 422 /*start reading data from the buffer directly:*/423 for (int f=0;f<nfields;f++){424 char* field=fields[f];425 fseek(fid,0,SEEK_SET);426 for (int j=0;j<nsteps;j++){427 int counter=f*nsteps+j;428 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);429 if(i==(lower_row+1)){430 if(xtype[counter]==1){431 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(nbins);432 IssmDouble ma=*maxxs[counter];433 IssmDouble mi=*minxs[counter];434 int index=(scalar-mi)/(ma-mi)*nbins; if (index==nbins)index--;435 if(ma==mi)index=0;436 //_printf_( index << "|" << scalar << "|" << mi << "|" << ma << "|" << nbins << "\n");437 localhistogram[index]++;438 histogram[counter]=localhistogram;439 }440 else if (xtype[counter]==3){441 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(doublematsize*nbins);442 IssmDouble* ma=maxxs[counter];443 IssmDouble* mi=minxs[counter];444 for (int k=0;k<doublematsize;k++){445 IssmDouble scalar=doublemat[k];446 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index--;447 if (mi[k]==ma[k])index=0;448 _assert_(scalar<=ma[k]); _assert_(scalar>=mi[k]); _assert_(index<nbins);449 localhistogram[k*nbins+index]++;450 }451 histogram[counter]=localhistogram;452 xDelete<IssmDouble>(doublemat);453 }454 else _error_("cannot carry out statistics on type " << xtype[counter]);455 }456 else{457 if(xtype[counter]==1){458 IssmDouble* localhistogram=histogram[counter];459 IssmDouble ma=*maxxs[counter];460 IssmDouble mi=*minxs[counter];461 int index=(scalar-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1;462 if(ma==mi)index=0;463 localhistogram[index]++;464 }465 else if (xtype[counter]==3){466 IssmDouble* localhistogram=histogram[counter];467 IssmDouble* ma=maxxs[counter];468 IssmDouble* mi=minxs[counter];469 for (int k=0;k<doublematsize;k++){470 IssmDouble scalar=doublemat[k];471 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1;472 if (mi[k]==ma[k])index=0;473 474 localhistogram[k*nbins+index]++;475 }476 xDelete<IssmDouble>(doublemat);477 }478 else _error_("cannot carry out statistics on type " << xtype[counter]);479 }480 }481 }482 _printf0_(" average in time:\n");483 484 /*Deal with average in time: */485 for (int f=0;f<nfields;f++){486 fseek(fid,0,SEEK_SET);487 char* field=fields[f];488 meanxtype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]);489 490 if(meanxtype[f]==1){491 IssmDouble timemean=0;492 fseek(fid,0,SEEK_SET);493 for (int j=0;j<nsteps;j++){494 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);495 timemean+=scalar/nsteps;496 }497 498 /*Figure out max and min of time means: */499 if(i==(lower_row+1)){500 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(nbins);501 IssmDouble ma=*maxmeans[f];502 IssmDouble mi=*minmeans[f];503 int index=(timemean-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1;504 if(ma==mi)index=0;505 localhistogram[index]++;506 timehistogram[f]=localhistogram;507 }508 else{509 IssmDouble* localhistogram=timehistogram[f];510 IssmDouble ma=*maxmeans[f];511 IssmDouble mi=*minmeans[f];512 int index=(timemean-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1;513 if(ma==mi)index=0;514 localhistogram[index]++;515 }516 }517 else{518 fseek(fid,0,SEEK_SET);519 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize);520 for (int j=0;j<nsteps;j++){521 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);522 for (int k=0;k<doublematsize;k++){523 timemean[k]+=doublemat[k]/nsteps;524 }525 xDelete<IssmDouble>(doublemat);526 }527 528 if(i==(lower_row+1)){529 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(doublematsize*nbins);530 IssmDouble* ma=maxmeans[f];531 IssmDouble* mi=minmeans[f];532 533 for (int k=0;k<doublematsize;k++){534 IssmDouble scalar=timemean[k];535 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1;536 if (mi[k]==ma[k])index=0;537 localhistogram[k*nbins+index]++;538 }539 timehistogram[f]=localhistogram;540 }541 else{542 543 IssmDouble* localhistogram=timehistogram[f];544 IssmDouble* ma=maxmeans[f];545 IssmDouble* mi=minmeans[f];546 547 for (int k=0;k<doublematsize;k++){548 IssmDouble scalar=timemean[k];549 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1;550 if (mi[k]==ma[k])index=0;551 552 localhistogram[k*nbins+index]++;553 }554 }555 }556 }557 fclose(fid);558 559 /*delete buffer:*/560 xDelete<char>(buffer);561 }562 _printf0_("Start aggregating histogram:\n");563 564 /*We have agregated histograms across the cluster, now gather them across the cluster onto565 *cpu0: */566 for (int f=0;f<nfields;f++){567 int counter0=f*nsteps+0;568 if (xtype[counter0]==1){ /*deal with scalars {{{*/569 for (int j=0;j<nsteps;j++){570 int counter=f*nsteps+j;571 572 /*we are broadcasting doubles:*/573 IssmDouble* histo=histogram[counter]; //size nbins574 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(nbins);575 576 ISSM_MPI_Allreduce(histo,allhisto,nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm());577 578 /*add to results:*/579 if(my_rank==0){580 char fieldname[1000];581 582 sprintf(fieldname,"%s%s",fields[f],"Histogram");583 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,1,nbins,j+1,0));584 585 sprintf(fieldname,"%s%s",fields[f],"Max");586 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*maxxs[counter],j+1,0));587 sprintf(fieldname,"%s%s",fields[f],"Min");588 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*minxs[counter],j+1,0));589 }590 }591 } /*}}}*/592 else{ /*deal with arrays:{{{*/593 594 int size=xsize[counter0];595 for (int j=0;j<nsteps;j++){596 int counter=f*nsteps+j;597 598 /*we are broadcasting double arrays:*/599 IssmDouble* histo=histogram[counter];600 IssmDouble* allhisto=xNew<IssmDouble>(size*nbins);601 602 ISSM_MPI_Allreduce(histo,allhisto,size*nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm());603 xDelete<IssmDouble>(histo);604 605 /*add to results:*/606 if(my_rank==0){607 char fieldname[1000];608 609 sprintf(fieldname,"%s%s",fields[f],"Histogram");610 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,size,nbins,j+1,0));611 612 sprintf(fieldname,"%s%s",fields[f],"Max");613 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,maxxs[counter],size,1,j+1,0));614 sprintf(fieldname,"%s%s",fields[f],"Min");615 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,minxs[counter],size,1,j+1,0));616 }617 }618 } /*}}}*/619 }620 _printf0_("Start aggregating time mean histogram:\n");621 622 /*Now do the same for the time mean fields:*/623 for (int f=0;f<nfields;f++){624 if (meanxtype[f]==1){ /*deal with scalars {{{*/625 626 /*we are broadcasting doubles:*/627 IssmDouble* histo=timehistogram[f];628 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(nbins);629 630 ISSM_MPI_Allreduce(histo,allhisto,nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm());631 632 /*add to results at time step 1:*/633 if(my_rank==0){634 char fieldname[1000];635 636 sprintf(fieldname,"%s%s",fields[f],"TimeMeanHistogram");637 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,1,nbins,steps[0],0));638 639 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMax");640 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*maxmeans[f],steps[0],0));641 sprintf(fieldname,"%s%s",fields[f],"TimeMeaMin");642 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*minmeans[f],steps[0],0));643 }644 } /*}}}*/645 else{ /*deal with arrays:{{{*/646 647 int size=meanxsize[f];648 649 /*we are broadcasting double arrays:*/650 IssmDouble* histo=timehistogram[f];651 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(size*nbins);652 653 ISSM_MPI_Allreduce(histo,allhisto,size*nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm());654 xDelete<IssmDouble>(histo);655 /*add to results at step 1:*/656 if(my_rank==0){657 char fieldname[1000];658 659 sprintf(fieldname,"%s%s",fields[f],"TimeMeanHistogram");660 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,size,nbins,steps[0],0));661 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMax");662 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,maxmeans[f],size,1,steps[0],0));663 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMin");664 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,minmeans[f],size,1,steps[0],0));665 }666 } /*}}}*/667 }668 _printf0_("Done aggregating time mean histogram:\n");669 IssmComm::SetComm(ISSM_MPI_COMM_WORLD);670 671 return 1;672 }673 /*}}}*/674 int ComputeMeanVariance(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/675 676 int nsamples;677 char* directory=NULL;678 char* model=NULL;679 char** fields=NULL;680 int* steps=NULL;681 int nsteps;682 int nfields;683 int range,lower_row,upper_row;684 int nfilesperdirectory;685 686 /*intermediary:*/687 IssmDouble* doublemat=NULL;688 int doublematsize;689 IssmDouble scalar;690 691 /*computation of average and variance itself:*/692 IssmDouble* x = NULL;693 IssmDouble* x2 = NULL;694 IssmDouble** xs = NULL;695 IssmDouble** xs2 = NULL;696 int* xtype=NULL;697 int* xsize=NULL;698 699 IssmDouble** meanx=NULL;700 IssmDouble** meanx2=NULL;701 int* meantype=NULL;702 int* meansize=NULL;703 704 /*only work on the statistical communicator: */705 if (color==MPI_UNDEFINED)return 0;706 707 /*Retrieve parameters:*/708 parameters->FindParam(&nfilesperdirectory,QmuNfilesPerDirectoryEnum);709 parameters->FindParam(&nsamples,QmuNsampleEnum);710 parameters->FindParam(&directory,DirectoryNameEnum);711 parameters->FindParam(&model,InputFileNameEnum);712 parameters->FindParam(&fields,&nfields,FieldsEnum);713 parameters->FindParam(&steps,&nsteps,StepsEnum);714 715 /*Get rank from the stat comm communicator:*/716 IssmComm::SetComm(statcomm);717 int my_rank=IssmComm::GetRank();718 719 /*Open files and read them complelety, in a distributed way:*/720 range=DetermineLocalSize(nsamples,IssmComm::GetComm());721 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm());722 723 /*Initialize arrays:*/724 xs=xNew<IssmDouble*>(nfields*nsteps);725 xs2=xNew<IssmDouble*>(nfields*nsteps);726 xtype=xNew<int>(nfields*nsteps);727 xsize=xNew<int>(nfields*nsteps);728 729 meantype=xNew<int>(nfields);730 meansize=xNew<int>(nfields);731 meanx=xNew<IssmDouble*>(nfields);732 meanx2=xNew<IssmDouble*>(nfields);733 734 /*Start opening files:*/735 for (int i=(lower_row+1);i<=upper_row;i++){736 _printf0_("reading file #: " << i << "\n");737 char file[1000];738 long int length;739 char* buffer=NULL;740 741 /*string:*/742 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i);743 744 /*open file: */745 _printf0_(" opening file: " << file << "\n");746 FILE* fid=fopen(file,"rb");747 if(fid==NULL) _error_(" could not open file: " << file << "\n");748 749 /*figure out size of file, and read the whole thing:*/750 _printf0_(" reading file:\n");751 fseek (fid, 0, SEEK_END);752 length = ftell (fid);753 fseek (fid, 0, SEEK_SET);754 buffer = xNew<char>(length);755 fread (buffer, sizeof(char), length, fid);756 757 /*close file:*/758 fclose (fid);759 760 /*create a memory stream with this buffer:*/761 _printf0_(" processing file:\n");762 fid=fmemopen(buffer, length, "rb");763 764 /*start reading data from the buffer directly:*/765 for (int f=0;f<nfields;f++){766 char* field=fields[f];767 fseek(fid,0,SEEK_SET);768 for (int j=0;j<nsteps;j++){769 int counter=f*nsteps+j;770 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);771 if(i==(lower_row+1)){772 if(xtype[counter]==1){773 xs[counter]=xNew<IssmDouble>(1);774 xs2[counter]=xNew<IssmDouble>(1);775 *xs[counter]=scalar;776 *xs2[counter]=pow(scalar,2.0);777 xsize[counter]=1;778 }779 else if (xtype[counter]==3){780 IssmDouble* doublemat2=xNew<IssmDouble>(doublematsize);781 for(int k=0;k<doublematsize;k++)doublemat2[k]=pow(doublemat[k],2.0);782 xs[counter]=doublemat;783 xs2[counter]=doublemat2;784 xsize[counter]=doublematsize;785 }786 else _error_("cannot carry out statistics on type " << xtype[counter]);787 }788 else{789 if(xtype[counter]==1){790 *xs[counter]+=scalar;791 *xs2[counter]+=pow(scalar,2.0);792 }793 else if (xtype[counter]==3){794 IssmDouble* newdoublemat=xs[counter];795 IssmDouble* newdoublemat2=xs2[counter];796 for(int k=0;k<doublematsize;k++){797 newdoublemat[k]+=doublemat[k];798 newdoublemat2[k]+=pow(doublemat[k],2.0);799 }800 xs[counter]=newdoublemat;801 xs2[counter]=newdoublemat2;802 }803 else _error_("cannot carry out statistics on type " << xtype[counter]);804 }805 }806 }807 808 /*Deal with time mean: */809 for (int f=0;f<nfields;f++){810 char* field=fields[f];811 fseek(fid,0,SEEK_SET);812 meantype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]);813 if(i==(lower_row+1)){814 if(meantype[f]==1){815 meanx[f]=xNewZeroInit<IssmDouble>(1);816 meanx2[f]=xNewZeroInit<IssmDouble>(1);817 meansize[f]=1;818 }819 else{820 meanx[f]=xNewZeroInit<IssmDouble>(doublematsize);821 meanx2[f]=xNewZeroInit<IssmDouble>(doublematsize);822 meansize[f]=doublematsize;823 }824 }825 fseek(fid,0,SEEK_SET);826 if(meantype[f]==1){827 IssmDouble sc=0;828 IssmDouble sc2=0;829 for(int j=0;j<nsteps;j++){830 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);831 sc+=scalar/nsteps;832 }833 sc2+=pow(sc,2.0);834 *meanx[f]+=sc;835 *meanx2[f]+=sc2;836 }837 else{838 IssmDouble* sc=meanx[f];839 IssmDouble* sc2=meanx2[f];840 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize);841 IssmDouble* timemean2=xNewZeroInit<IssmDouble>(doublematsize);842 843 for(int j=0;j<nsteps;j++){844 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);845 for (int k=0;k<doublematsize;k++){846 timemean[k]+=doublemat[k]/nsteps;847 }848 }849 for (int k=0;k<doublematsize;k++){850 timemean2[k]=pow(timemean[k],2.0);851 }852 for (int k=0;k<doublematsize;k++){853 sc[k]+=timemean[k];854 sc2[k]+=timemean2[k];855 }856 857 }858 859 }860 fclose(fid);861 862 /*delete buffer:*/863 xDelete<char>(buffer);864 }865 ISSM_MPI_Barrier(IssmComm::GetComm());866 _printf0_("Done reading files, now computing mean and variance.\n");867 868 /*We have agregated x and x^2 across the cluster, now gather across the cluster onto869 *cpu0 and then compute statistics:*/870 for (int f=0;f<nfields;f++){871 int counter0=f*nsteps+0;872 if (xtype[counter0]==1){ /*deal with scalars {{{*/873 IssmDouble mean,stddev;874 for (int j=0;j<nsteps;j++){875 int counter=f*nsteps+j;876 877 /*we are broadcasting doubles:*/878 IssmDouble scalar=*xs[counter];879 IssmDouble scalar2=*xs2[counter];880 IssmDouble sumscalar;881 IssmDouble sumscalar2;882 883 ISSM_MPI_Reduce(&scalar,&sumscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());884 ISSM_MPI_Reduce(&scalar2,&sumscalar2,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());885 /*Build average and standard deviation. For standard deviation, use the886 *following formula: sigma^2=E(x^2)-mu^2:*/887 mean=sumscalar/nsamples;888 stddev=sqrt(sumscalar2/nsamples-pow(mean,2.0));889 890 /*add to results:*/891 if(my_rank==0){892 char fieldname[1000];893 894 sprintf(fieldname,"%s%s",fields[f],"Mean");895 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,mean,j+1,0));896 sprintf(fieldname,"%s%s",fields[f],"Stddev");897 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,stddev,j+1,0));898 }899 900 }901 } /*}}}*/902 else{ /*deal with arrays:{{{*/903 904 int size=xsize[counter0];905 906 IssmDouble* mean=xNew<IssmDouble>(size);907 IssmDouble* stddev=xNew<IssmDouble>(size);908 909 for (int j=0;j<nsteps;j++){910 int counter=f*nsteps+j;911 912 /*we are broadcasting double arrays:*/913 x=xs[counter];914 x2=xs2[counter];915 916 IssmDouble* sumx=xNew<IssmDouble>(size);917 IssmDouble* sumx2=xNew<IssmDouble>(size);918 919 ISSM_MPI_Reduce(x,sumx,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());920 ISSM_MPI_Reduce(x2,sumx2,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());921 922 /*Build average and standard deviation. For standard deviation, use the923 *following formula: sigma^2=E(x^2)-mu^2:*/924 for (int k=0;k<size;k++){925 mean[k]=sumx[k]/nsamples;926 stddev[k]=sqrt(sumx2[k]/nsamples-pow(mean[k],2.0));927 }928 929 /*add to results:*/930 if(my_rank==0){931 char fieldname[1000];932 933 sprintf(fieldname,"%s%s",fields[f],"Mean");934 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,mean,size,1,j+1,0));935 sprintf(fieldname,"%s%s",fields[f],"Stddev");936 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,stddev,size,1,j+1,0));937 }938 }939 } /*}}}*/940 }941 /*Do the same but for the time mean:*/942 for (int f=0;f<nfields;f++){943 if (meantype[f]==1){ /*deal with scalars {{{*/944 IssmDouble mean,stddev;945 946 /*we are broadcasting doubles:*/947 IssmDouble scalar=*meanx[f];948 IssmDouble scalar2=*meanx2[f];949 IssmDouble sumscalar;950 IssmDouble sumscalar2;951 952 ISSM_MPI_Reduce(&scalar,&sumscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());953 ISSM_MPI_Reduce(&scalar2,&sumscalar2,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());954 /*Build average and standard deviation. For standard deviation, use the955 *following formula: sigma^2=E(x^2)-mu^2:*/956 mean=sumscalar/nsamples;957 stddev=sqrt(sumscalar2/nsamples-pow(mean,2.0));958 959 /*add to results:*/960 if(my_rank==0){961 char fieldname[1000];962 963 sprintf(fieldname,"%s%s",fields[f],"TimeMean");964 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,mean,steps[0],0));965 sprintf(fieldname,"%s%s",fields[f],"TimeStddev");966 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,stddev,steps[0],0));967 }968 } /*}}}*/969 else{ /*deal with arrays:{{{*/970 971 int size=meansize[f];972 IssmDouble* mean=xNew<IssmDouble>(size);973 IssmDouble* stddev=xNew<IssmDouble>(size);974 975 /*we are broadcasting double arrays:*/976 x=meanx[f];977 x2=meanx2[f];978 979 IssmDouble* sumx=xNew<IssmDouble>(size);980 IssmDouble* sumx2=xNew<IssmDouble>(size);981 982 ISSM_MPI_Reduce(x,sumx,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());983 ISSM_MPI_Reduce(x2,sumx2,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm());984 985 /*Build average and standard deviation. For standard deviation, use the986 *following formula: sigma^2=E(x^2)-mu^2:*/987 for (int k=0;k<size;k++){988 mean[k]=sumx[k]/nsamples;989 stddev[k]=sqrt(sumx2[k]/nsamples-pow(mean[k],2.0));990 }991 992 /*add to results:*/993 if(my_rank==0){994 char fieldname[1000];995 996 sprintf(fieldname,"%s%s",fields[f],"TimeMean");997 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,mean,size,1,steps[0],0));998 sprintf(fieldname,"%s%s",fields[f],"TimeStddev");999 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,stddev,size,1,steps[0],0));1000 }1001 } /*}}}*/1002 }1003 1004 _printf0_("Done with MeanVariance:\n");1005 IssmComm::SetComm(ISSM_MPI_COMM_WORLD);1006 1007 return 1;1008 } /*}}}*/1009 int ComputeSampleSeries(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/1010 1011 int nsamples;1012 char* directory=NULL;1013 char* model=NULL;1014 char** fields=NULL;1015 int* steps=NULL;1016 int nsteps;1017 int nfields;1018 int range,lower_row,upper_row;1019 int nfilesperdirectory;1020 int* indices=NULL;1021 int nindices;1022 1023 /*intermediary:*/1024 IssmDouble* doublemat=NULL;1025 int doublematsize;1026 IssmDouble scalar;1027 1028 /*computation of average and variance itself:*/1029 IssmDouble* x = NULL;1030 IssmDouble* allx=NULL;1031 IssmDouble** xs = NULL;1032 int* xtype=NULL;1033 int* xsize=NULL;1034 1035 /*only work on the statistical communicator: */1036 if (color==MPI_UNDEFINED)return 0;1037 1038 /*Retrieve parameters:*/1039 parameters->FindParam(&nsamples,QmuNsampleEnum);1040 parameters->FindParam(&directory,DirectoryNameEnum);1041 parameters->FindParam(&model,InputFileNameEnum);1042 parameters->FindParam(&fields,&nfields,FieldsEnum);1043 parameters->FindParam(&steps,&nsteps,StepsEnum);1044 parameters->FindParam(&indices,&nindices,IndicesEnum);1045 1046 /*Get rank from the stat comm communicator:*/1047 IssmComm::SetComm(statcomm);1048 int my_rank=IssmComm::GetRank();1049 1050 /*Open files and read them complelety, in a distributed way:*/1051 range=DetermineLocalSize(nsamples,IssmComm::GetComm());1052 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm());1053 1054 /*Initialize arrays:*/1055 xs=xNew<IssmDouble*>(nfields*nsteps);1056 xtype=xNew<int>(nfields*nsteps);1057 xsize=xNew<int>(nfields*nsteps);1058 1059 /*Start opening files:*/1060 for (int i=(lower_row+1);i<=upper_row;i++){1061 _printf0_("reading file #: " << i << "\n");1062 char file[1000];1063 long int length;1064 char* buffer=NULL;1065 1066 /*string:*/1067 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i);1068 1069 /*open file: */1070 _printf0_(" opening file:\n");1071 FILE* fid=fopen(file,"rb");1072 1073 /*figure out size of file, and read the whole thing:*/1074 _printf0_(" reading file:\n");1075 fseek (fid, 0, SEEK_END);1076 length = ftell (fid);1077 fseek (fid, 0, SEEK_SET);1078 buffer = xNew<char>(length);1079 fread (buffer, sizeof(char), length, fid);1080 1081 /*close file:*/1082 fclose (fid);1083 1084 /*create a memory stream with this buffer:*/1085 _printf0_(" processing file:\n");1086 fid=fmemopen(buffer, length, "rb");1087 1088 /*start reading data from the buffer directly:*/1089 for (int f=0;f<nfields;f++){1090 fseek(fid,0,SEEK_SET);1091 char* field=fields[f];1092 for (int j=0;j<nsteps;j++){1093 int counter=f*nsteps+j;1094 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]);1095 if(i==(lower_row+1)){1096 if(xtype[counter]==1){1097 x=xNew<IssmDouble>(range);1098 x[0]=scalar;1099 xs[counter]=x;1100 xsize[counter]=range;1101 }1102 else if (xtype[counter]==3){1103 x=xNew<IssmDouble>(nindices*range);1104 for(int k=0;k<nindices;k++)x[(i-(lower_row+1))*nindices+k]=doublemat[indices[k]-1];1105 xs[counter]=x;1106 xsize[counter]=range*nindices;1107 }1108 else _error_("cannot carry out statistics on type " << xtype[counter]);1109 }1110 else{1111 if(xtype[counter]==1){1112 x=xs[counter];1113 x[i-(lower_row+1)]=scalar;1114 xs[counter]=x;1115 }1116 else if (xtype[counter]==3){1117 x=xs[counter];1118 for(int k=0;k<nindices;k++)x[(i-(lower_row+1))*nindices+k]=doublemat[indices[k]-1];1119 xs[counter]=x;1120 }1121 else _error_("cannot carry out statistics on type " << xtype[counter]);1122 }1123 }1124 }1125 fclose(fid);1126 1127 /*delete buffer:*/1128 xDelete<char>(buffer);1129 }1130 ISSM_MPI_Barrier(IssmComm::GetComm());1131 _printf0_("Done reading files, now assembling time series.\n");1132 1133 for (int f=0;f<nfields;f++){1134 for (int j=0;j<nsteps;j++){1135 int counter=f*nsteps+j;1136 if (xtype[counter]==1){1137 /*we are broadcasting range times doubles:*/1138 x=xs[counter];1139 allx=xNew<IssmDouble>(nsamples);1140 MPI_Gather(x, range, ISSM_MPI_PDOUBLE,allx, range, ISSM_MPI_PDOUBLE, 0, IssmComm::GetComm());1141 /*add to results:*/1142 if(my_rank==0){1143 char fieldname[1000];1144 1145 sprintf(fieldname,"%s%s",fields[f],"Samples");1146 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allx,nsamples,1,j+1,0));1147 }1148 }1149 else{1150 /*we are broadcasting double arrays:*/1151 x=xs[counter];1152 allx=xNew<IssmDouble>(nsamples*nindices);1153 1154 MPI_Gather(x, range*nindices, ISSM_MPI_PDOUBLE,allx, range*nindices, ISSM_MPI_PDOUBLE, 0, IssmComm::GetComm());1155 1156 /*add to results:*/1157 if(my_rank==0){1158 char fieldname[1000];1159 sprintf(fieldname,"%s%s",fields[f],"Samples");1160 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allx,nsamples,nindices,j+1,0));1161 }1162 }1163 }1164 }1165 _printf0_("Done with SampleSeries:\n");1166 IssmComm::SetComm(ISSM_MPI_COMM_WORLD);1167 1168 return 1;1169 } /*}}}*/1170 int OutputStatistics(Parameters* parameters,Results* results,int color,ISSM_MPI_Comm statcomm){ /*{{{*/1171 1172 char outputfilename[1000];1173 char* directory=NULL;1174 char* model=NULL;1175 char* method=NULL;1176 int nsamples;1177 int* steps=NULL;1178 int nsteps;1179 1180 /*only work on the statistical communicator: */1181 if (color==MPI_UNDEFINED)return 0;1182 1183 FemModel* femmodel=new FemModel();1184 1185 /*Some parameters that will allow us to use the OutputResultsx module:*/1186 parameters->AddObject(new BoolParam(QmuIsdakotaEnum,false));1187 parameters->AddObject(new BoolParam(SettingsIoGatherEnum,true));1188 1189 parameters->FindParam(&directory,DirectoryNameEnum);1190 parameters->FindParam(&model,InputFileNameEnum);1191 parameters->FindParam(&nsamples,QmuNsampleEnum);1192 parameters->FindParam(&steps,&nsteps,StepsEnum);1193 1194 sprintf(outputfilename,"%s/%s.stats",directory,model);1195 parameters->AddObject(new StringParam(OutputFileNameEnum,outputfilename));1196 1197 /*Call OutputResults module:*/1198 femmodel->parameters=parameters;1199 femmodel->results=results;1200 1201 OutputResultsx(femmodel);1202 1203 return 1;1204 } /*}}}*/1205 bool DakotaDirStructure(int argc,char** argv){ /*{{{*/1206 1207 char* input_file;1208 FILE* fid;1209 IoModel* iomodel=NULL;1210 int check;1211 1212 //qmu statistics1213 bool statistics = false;1214 int numdirectories = 0;1215 1216 /*First things first, set the communicator as a global variable: */1217 IssmComm::SetComm(MPI_COMM_WORLD);1218 1219 /*Barrier:*/1220 ISSM_MPI_Barrier(IssmComm::GetComm());1221 _printf0_("Preparing directory structure for model outputs:" << "\n");1222 1223 //open model input file for reading1224 input_file=xNew<char>((strlen(argv[2])+strlen(argv[3])+strlen(".bin")+2));1225 sprintf(input_file,"%s/%s%s",argv[2],argv[3],".bin");1226 fid=fopen(input_file,"rb");1227 if (fid==NULL) Cerr << "dirstructure error message: could not open model " << input_file << " to retrieve qmu statistics parameters" << std::endl;1228 1229 //initialize IoModel, but light version, we just need it to fetch one constant:1230 iomodel=new IoModel();1231 iomodel->fid=fid;1232 iomodel->FetchConstants();1233 1234 //early return if statistics not requested:1235 iomodel->FindConstant(&statistics,"md.qmu.statistics");1236 if(!statistics){1237 delete iomodel;1238 xDelete<char>(input_file);1239 fclose(fid);1240 return false; //important return value!1241 }1242 1243 iomodel->FindConstant(&numdirectories,"md.qmu.statistics.ndirectories");1244 1245 /*Ok, we have everything we need to create the directory structure:*/1246 if(IssmComm::GetRank()==0){1247 for (int i=0;i<numdirectories;i++){1248 char directory[1000];1249 sprintf(directory,"./%i",i+1);1250 1251 check = mkdir(directory,ACCESSPERMS);1252 if (check) _error_("dirstructure error message: could not create directory " << directory << "\n");1253 }1254 }1255 1256 /*Delete resources:*/1257 delete iomodel;1258 xDelete<char>(input_file);1259 1260 //close model file:1261 fclose(fid);1262 1263 //return value:1264 return true; //statistics computation on!1265 } /*}}}*/1266 8 int DakotaStatistics(int argc,char** argv){ /*{{{*/ 1267 9 10 /*Variables:{{{*/ 1268 11 char* input_file; 1269 12 FILE* fid; … … 1293 36 Parameters* parameters=NULL; 1294 37 int color; 1295 1296 / *First things first, set the communicator as a global variable: */38 /*}}}*/ 39 //First things first, set the communicator as a global variable and be sure we are all here: {{{ 1297 40 IssmComm::SetComm(MPI_COMM_WORLD); 1298 41 my_rank=IssmComm::GetRank(); … … 1301 44 ISSM_MPI_Barrier(IssmComm::GetComm()); 1302 45 _printf0_("Dakota Statistic Computation" << "\n"); 1303 1304 // open model input file for reading46 /*}}}*/ 47 //Open model input file for reading {{{ 1305 48 input_file=xNew<char>((strlen(argv[2])+strlen(argv[3])+strlen(".bin")+2)); 1306 49 sprintf(input_file,"%s/%s%s",argv[2],argv[3],".bin"); 1307 50 fid=fopen(input_file,"rb"); 1308 51 if (fid==NULL) Cerr << "issm_dakota_statistics error message: could not open model " << input_file << " to retrieve qmu statistics parameters" << std::endl; 1309 1310 // initialize IoModel, but light version, we'll need it to fetch constants:52 //}}} 53 //Initialize IoModel, but light version, we'll need it to fetch constants: {{{ 1311 54 iomodel=new IoModel(); 1312 55 iomodel->fid=fid; 1313 56 iomodel->FetchConstants(); 1314 1315 // early return if statistics not requested:57 /*}}}*/ 58 //Early return if statistics not requested: {{{ 1316 59 iomodel->FindConstant(&statistics,"md.qmu.statistics"); 1317 60 if(!statistics){ … … 1320 63 fclose(fid); 1321 64 return 0; 1322 }else{ 1323 //create parameters datasets with al the qmu statistics settings we need: 1324 1325 /*Initialize parameters and results:*/ 1326 results = new Results(); 1327 parameters=new Parameters(); 1328 1329 //solution type: 1330 parameters->AddObject(new IntParam(SolutionTypeEnum,StatisticsSolutionEnum)); 1331 1332 //root directory 1333 directory=xNew<char>(strlen(argv[2])+1); 1334 xMemCpy<char>(directory,argv[2],strlen(argv[2])+1); 1335 parameters->AddObject(new StringParam(DirectoryNameEnum,directory)); 1336 1337 //model name 1338 model=xNew<char>(strlen(argv[3])+1); 1339 xMemCpy<char>(model,argv[3],strlen(argv[3])+1); 1340 parameters->AddObject(new StringParam(InputFileNameEnum,model)); 1341 1342 //nsamples 1343 iomodel->FindConstant(&nsamples,"md.qmu.method.params.samples"); 1344 parameters->AddObject(new IntParam(QmuNsampleEnum,nsamples)); 1345 1346 //ndirectories 1347 iomodel->FindConstant(&numdirectories,"md.qmu.statistics.ndirectories"); 1348 parameters->AddObject(new IntParam(QmuNdirectoriesEnum,numdirectories)); 1349 1350 //nfiles per directory 1351 iomodel->FindConstant(&nfilesperdirectory,"md.qmu.statistics.nfiles_per_directory"); 1352 parameters->AddObject(new IntParam(QmuNfilesPerDirectoryEnum,nfilesperdirectory)); 1353 1354 //At this point, we don't want to go forward any longer, we want to create an MPI 1355 //communicator on which to carry out the computations: 1356 if ((my_rank+1)*nfilesperdirectory>nsamples)color=MPI_UNDEFINED; 1357 else color=0; 1358 ISSM_MPI_Comm_split(ISSM_MPI_COMM_WORLD,color, my_rank, &statcomm); 1359 1360 iomodel->FindConstant(&numstatistics,"md.qmu.statistics.numstatistics"); 1361 for (int i=1;i<=numstatistics;i++){ 1362 1363 char* directory=NULL; 1364 char* model=NULL; 1365 int nsamples; 1366 _printf0_("Dealing with qmu statistical computation #" << i << "\n"); 1367 1368 sprintf(string,"md.qmu.statistics.method(%i).name",i); 1369 iomodel->FindConstant(&name,string); 1370 1371 sprintf(string,"md.qmu.statistics.method(%i).fields",i); 1372 iomodel->FindConstant(&fields,&nfields,string); 1373 parameters->AddObject(new StringArrayParam(FieldsEnum,fields,nfields)); 1374 1375 sprintf(string,"md.qmu.statistics.method(%i).steps",i); 1376 iomodel->FetchData(&steps,&dummy,&nsteps,string); 1377 parameters->AddObject(new IntVecParam(StepsEnum,steps,nsteps)); 1378 1379 if (strcmp(name,"Histogram")==0){ 1380 /*fetch nbins: */ 1381 sprintf(string,"md.qmu.statistics.method(%i).nbins",i); 1382 iomodel->FindConstant(&nbins,string); 1383 parameters->AddObject(new IntParam(NbinsEnum,nbins)); 1384 ComputeHistogram(parameters,results,color,statcomm); 1385 } 1386 else if (strcmp(name,"SampleSeries")==0){ 1387 /*fetch indices: */ 1388 sprintf(string,"md.qmu.statistics.method(%i).indices",i); 1389 iomodel->FetchData(&indices,&dummy,&nindices,string); 1390 parameters->AddObject(new IntVecParam(IndicesEnum,indices,nindices)); 1391 1392 ComputeSampleSeries(parameters,results,color,statcomm); 1393 } 1394 else if (strcmp(name,"MeanVariance")==0){ 1395 ComputeMeanVariance(parameters,results,color,statcomm); 1396 } 1397 else _error_(" error creating qmu statistics methods parameters: unsupported method " << name); 65 } 66 /*}}}*/ 67 //Create parameters datasets with al the qmu statistics settings we need: {{{ 68 69 /*Initialize parameters and results:*/ 70 results = new Results(); 71 parameters=new Parameters(); 72 73 //solution type: 74 parameters->AddObject(new IntParam(SolutionTypeEnum,StatisticsSolutionEnum)); 75 76 //root directory 77 directory=xNew<char>(strlen(argv[2])+1); 78 xMemCpy<char>(directory,argv[2],strlen(argv[2])+1); 79 parameters->AddObject(new StringParam(DirectoryNameEnum,directory)); 80 81 //model name 82 model=xNew<char>(strlen(argv[3])+1); 83 xMemCpy<char>(model,argv[3],strlen(argv[3])+1); 84 parameters->AddObject(new StringParam(InputFileNameEnum,model)); 85 86 //nsamples 87 iomodel->FindConstant(&nsamples,"md.qmu.method.params.samples"); 88 parameters->AddObject(new IntParam(QmuNsampleEnum,nsamples)); 89 90 //ndirectories 91 iomodel->FindConstant(&numdirectories,"md.qmu.statistics.ndirectories"); 92 parameters->AddObject(new IntParam(QmuNdirectoriesEnum,numdirectories)); 93 94 //nfiles per directory 95 iomodel->FindConstant(&nfilesperdirectory,"md.qmu.statistics.nfiles_per_directory"); 96 parameters->AddObject(new IntParam(QmuNfilesPerDirectoryEnum,nfilesperdirectory)); 97 /*}}}*/ 98 /*Create MPI world: {{{*/ 99 //At this point, we don't want to go forward any longer, we want to create an MPI 100 //communicator on which to carry out the computations: 101 if ((my_rank+1)*nfilesperdirectory>nsamples)color=MPI_UNDEFINED; 102 else color=0; 103 ISSM_MPI_Comm_split(ISSM_MPI_COMM_WORLD,color, my_rank, &statcomm); 104 /*}}}*/ 105 106 iomodel->FindConstant(&numstatistics,"md.qmu.statistics.numstatistics"); 107 for (int i=1;i<=numstatistics;i++){ 108 109 char* directory=NULL; 110 char* model=NULL; 111 int nsamples; 112 _printf0_("Dealing with qmu statistical computation #" << i << "\n"); 113 114 sprintf(string,"md.qmu.statistics.method(%i).name",i); 115 iomodel->FindConstant(&name,string); 116 117 sprintf(string,"md.qmu.statistics.method(%i).fields",i); 118 iomodel->FindConstant(&fields,&nfields,string); 119 parameters->AddObject(new StringArrayParam(FieldsEnum,fields,nfields)); 120 121 sprintf(string,"md.qmu.statistics.method(%i).steps",i); 122 iomodel->FetchData(&steps,&dummy,&nsteps,string); 123 parameters->AddObject(new IntVecParam(StepsEnum,steps,nsteps)); 124 125 if (strcmp(name,"Histogram")==0){ 126 /*fetch nbins: */ 127 sprintf(string,"md.qmu.statistics.method(%i).nbins",i); 128 iomodel->FindConstant(&nbins,string); 129 parameters->AddObject(new IntParam(NbinsEnum,nbins)); 130 ComputeHistogram(parameters,results,color,statcomm); 1398 131 } 1399 1400 /*Delete resources:*/ 1401 xDelete<char>(input_file); 1402 delete iomodel; 1403 } 132 else if (strcmp(name,"SampleSeries")==0){ 133 /*fetch indices: */ 134 sprintf(string,"md.qmu.statistics.method(%i).indices",i); 135 iomodel->FetchData(&indices,&dummy,&nindices,string); 136 parameters->AddObject(new IntVecParam(IndicesEnum,indices,nindices)); 137 138 ComputeSampleSeries(parameters,results,color,statcomm); 139 } 140 else if (strcmp(name,"MeanVariance")==0){ 141 ComputeMeanVariance(parameters,results,color,statcomm); 142 } 143 else _error_(" error creating qmu statistics methods parameters: unsupported method " << name); 144 } 145 146 /*Delete resources:*/ 147 xDelete<char>(input_file); 148 delete iomodel; 1404 149 1405 150 //close model file: … … 1418 163 return 1; 1419 164 } /*}}}*/ 165 int ComputeHistogram(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/ 166 167 int nsamples; 168 char* directory=NULL; 169 char* model=NULL; 170 char** fields=NULL; 171 int* steps=NULL; 172 int nsteps; 173 int nfields; 174 int nbins; 175 int range,lower_row,upper_row; 176 int nfilesperdirectory; 177 178 /*intermediary:*/ 179 IssmDouble* doublemat=NULL; 180 int doublematsize; 181 IssmDouble scalar; 182 183 /*computation of average and variance itself:*/ 184 IssmDouble** maxxs = NULL; 185 IssmDouble** minxs = NULL; 186 int* xtype=NULL; 187 int* xsize=NULL; 188 189 IssmDouble** maxmeans=NULL; 190 IssmDouble** minmeans=NULL; 191 int* meanxtype=NULL; 192 int* meanxsize=NULL; 193 194 /*only work on the statistical communicator: */ 195 if (color==MPI_UNDEFINED)return 0; 196 197 /*Retrieve parameters:*/ 198 parameters->FindParam(&nfilesperdirectory,QmuNfilesPerDirectoryEnum); 199 parameters->FindParam(&nsamples,QmuNsampleEnum); 200 parameters->FindParam(&directory,DirectoryNameEnum); 201 parameters->FindParam(&model,InputFileNameEnum); 202 parameters->FindParam(&fields,&nfields,FieldsEnum); 203 parameters->FindParam(&steps,&nsteps,StepsEnum); 204 parameters->FindParam(&nbins,NbinsEnum); 205 206 /*Get rank from the stat comm communicator:*/ 207 IssmComm::SetComm(statcomm); 208 int my_rank=IssmComm::GetRank(); 209 210 /*Open files and read them complelety, in a distributed way:*/ 211 range=DetermineLocalSize(nsamples,IssmComm::GetComm()); 212 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm()); 213 214 /*Initialize arrays:*/ 215 maxmeans=xNew<IssmDouble*>(nfields); 216 minmeans=xNew<IssmDouble*>(nfields); 217 meanxtype=xNew<int>(nfields); 218 meanxsize=xNew<int>(nfields); 219 220 maxxs=xNew<IssmDouble*>(nfields*nsteps); 221 minxs=xNew<IssmDouble*>(nfields*nsteps); 222 xtype=xNew<int>(nfields*nsteps); 223 xsize=xNew<int>(nfields*nsteps); 224 225 /*Start opening files:*/ 226 for(int i=(lower_row+1);i<=upper_row;i++){ 227 _printf0_("reading file #: " << i << "\n"); 228 /*First read file to figure out size of it in order to create memory buffer mapping into the file. {{{ 229 *This makes it much more efficient to read files without lag.:*/ 230 char file[1000]; 231 long int length; 232 char* buffer=NULL; 233 234 /*string:*/ 235 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i); 236 237 /*open file: */ 238 _printf0_(" opening file: " << file << "\n"); 239 FILE* fid=fopen(file,"rb"); 240 if(fid==NULL)_error_("cound not open file: " << file << "\n"); 241 242 /*figure out size of file, and read the whole thing:*/ 243 _printf0_(" reading file:\n"); 244 fseek(fid, 0, SEEK_END); 245 length = ftell (fid); 246 fseek(fid, 0, SEEK_SET); 247 buffer = xNew<char>(length); 248 fread(buffer, sizeof(char), length, fid); 249 250 /*close file:*/ 251 fclose(fid); 252 253 /*create a memory stream with this buffer which will be use to read the files:*/ 254 _printf0_(" processing file:\n"); 255 fid=fmemopen(buffer, length, "rb"); 256 /*}}}*/ 257 /*Figure out for each field, each time step, arrays on each cpu holwing min anx max values:{{{*/ 258 for (int f=0;f<nfields;f++){ 259 char* field=fields[f]; 260 fseek(fid,0,SEEK_SET); 261 for (int j=0;j<nsteps;j++){ 262 int counter=f*nsteps+j; 263 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 264 if(i==(lower_row+1)){ 265 if(xtype[counter]==1){ 266 maxxs[counter]=xNew<IssmDouble>(1); 267 minxs[counter]=xNew<IssmDouble>(1); 268 *maxxs[counter]=scalar; 269 *minxs[counter]=scalar; 270 xsize[counter]=1; 271 } 272 else if (xtype[counter]==3){ 273 maxxs[counter]=xNew<IssmDouble>(doublematsize); 274 xMemCpy<IssmDouble>(maxxs[counter],doublemat,doublematsize); 275 minxs[counter]=xNew<IssmDouble>(doublematsize); 276 xMemCpy<IssmDouble>(minxs[counter],doublemat,doublematsize); 277 xsize[counter]=doublematsize; 278 xDelete<IssmDouble>(doublemat); 279 } 280 else _error_("cannot carry out statistics on type " << xtype[counter]); 281 } 282 else{ 283 if(xtype[counter]==1){ 284 *maxxs[counter]=max(*maxxs[counter],scalar); 285 *minxs[counter]=min(*minxs[counter],scalar); 286 } 287 else if (xtype[counter]==3){ 288 IssmDouble* newmax=maxxs[counter]; 289 IssmDouble* newmin=minxs[counter]; 290 for(int k=0;k<doublematsize;k++){ 291 if(doublemat[k]>newmax[k])newmax[k]=doublemat[k]; 292 if(doublemat[k]<newmin[k])newmin[k]=doublemat[k]; 293 } 294 xDelete<IssmDouble>(doublemat); 295 } 296 else _error_("cannot carry out statistics on type " << xtype[counter]); 297 } 298 } 299 } 300 /*}}}*/ 301 /*Same thing for average in time:{{{*/ 302 _printf0_(" average in time:\n"); 303 304 /*Deal with average in time: */ 305 for (int f=0;f<nfields;f++){ 306 fseek(fid,0,SEEK_SET); 307 char* field=fields[f]; 308 meanxtype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]); 309 310 if(meanxtype[f]==1){ 311 meanxsize[f]=1; 312 IssmDouble timemean=0; 313 fseek(fid,0,SEEK_SET); 314 for (int j=0;j<nsteps;j++){ 315 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 316 timemean+=scalar/nsteps; 317 } 318 319 /*Figure out max and min of time means: */ 320 if(i==(lower_row+1)){ 321 maxmeans[f]=xNewZeroInit<IssmDouble>(1); 322 minmeans[f]=xNewZeroInit<IssmDouble>(1); 323 *maxmeans[f]=timemean; 324 *minmeans[f]=timemean; 325 } 326 else{ 327 *maxmeans[f]=max(*maxmeans[f],timemean); 328 *minmeans[f]=min(*minmeans[f],timemean); 329 } 330 } 331 else{ 332 meanxsize[f]=doublematsize; 333 fseek(fid,0,SEEK_SET); 334 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize); 335 for (int j=0;j<nsteps;j++){ 336 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 337 for (int k=0;k<doublematsize;k++){ 338 timemean[k]+=doublemat[k]/nsteps; 339 } 340 xDelete<IssmDouble>(doublemat); 341 } 342 343 if(i==(lower_row+1)){ 344 maxmeans[f]=xNew<IssmDouble>(doublematsize); 345 xMemCpy<IssmDouble>(maxmeans[f],timemean,doublematsize); 346 minmeans[f]=xNew<IssmDouble>(doublematsize); 347 xMemCpy<IssmDouble>(minmeans[f],timemean,doublematsize); 348 } 349 else{ 350 IssmDouble* maxx=maxmeans[f]; 351 IssmDouble* minx=minmeans[f]; 352 353 for(int k=0;k<doublematsize;k++){ 354 maxx[k]=max(maxx[k],timemean[k]); 355 minx[k]=min(minx[k],timemean[k]); 356 } 357 maxmeans[f]=maxx; 358 minmeans[f]=minx; 359 } 360 } 361 } 362 /*}}}*/ 363 /*Done reading files, close buffer and free memory:{{{*/ 364 fclose(fid); 365 xDelete<char>(buffer); 366 /*}}}*/ 367 } 368 ISSM_MPI_Barrier(IssmComm::GetComm()); 369 _printf0_("Done reading files, now computing min and max.\n"); 370 371 /*We have collected minx and max across the cluster, now gather across the cluster onto 372 *cpu0 and then compute statistics:*/ 373 for (int f=0;f<nfields;f++){ 374 int counter0=f*nsteps+0; 375 if (xtype[counter0]==1){ /*deal with scalars {{{*/ 376 for (int j=0;j<nsteps;j++){ 377 int counter=f*nsteps+j; 378 379 /*we are broadcasting doubles:*/ 380 IssmDouble maxscalar=*maxxs[counter]; 381 IssmDouble minscalar=*minxs[counter]; 382 IssmDouble allmaxscalar; 383 IssmDouble allminscalar; 384 IssmDouble sumscalar_alltimes=0; 385 386 ISSM_MPI_Allreduce(&maxscalar,&allmaxscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm()); 387 ISSM_MPI_Allreduce(&minscalar,&allminscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm()); 388 389 /*Store broadcasted value for later computation of histograms:*/ 390 *maxxs[counter]=allmaxscalar; 391 *minxs[counter]=allminscalar; 392 393 } 394 } /*}}}*/ 395 else{ /*deal with arrays:{{{*/ 396 397 int size=xsize[counter0]; 398 for (int j=0;j<nsteps;j++){ 399 int counter=f*nsteps+j; 400 401 /*we are broadcasting double arrays:*/ 402 IssmDouble* maxx=maxxs[counter]; 403 IssmDouble* minx=minxs[counter]; 404 405 IssmDouble* allmax=xNew<IssmDouble>(size); 406 IssmDouble* allmin=xNew<IssmDouble>(size); 407 408 ISSM_MPI_Allreduce(maxx,allmax,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm()); 409 ISSM_MPI_Allreduce(minx,allmin,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm()); 410 411 /*Store broadcasted value for later computation of histograms:*/ 412 maxxs[counter]=allmax; 413 minxs[counter]=allmin; 414 } 415 } /*}}}*/ 416 } 417 418 /*Now do the same for the time mean fields:*/ 419 for (int f=0;f<nfields;f++){ 420 if (meanxtype[f]==1){ /*deal with scalars {{{*/ 421 422 /*we are broadcasting doubles:*/ 423 IssmDouble maxscalar=*maxmeans[f]; 424 IssmDouble minscalar=*minmeans[f]; 425 IssmDouble allmaxscalar; 426 IssmDouble allminscalar; 427 428 ISSM_MPI_Allreduce(&maxscalar,&allmaxscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm()); 429 ISSM_MPI_Allreduce(&minscalar,&allminscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm()); 430 431 /*Store for later use in histogram computation:*/ 432 *maxmeans[f]=allmaxscalar; 433 *minmeans[f]=allminscalar; 434 435 } /*}}}*/ 436 else{ /*deal with arrays:{{{*/ 437 438 int size=meanxsize[f]; 439 440 /*we are broadcasting double arrays:*/ 441 IssmDouble* maxx=maxmeans[f]; 442 IssmDouble* minx=minmeans[f]; 443 444 IssmDouble* allmax=xNew<IssmDouble>(size); 445 IssmDouble* allmin=xNew<IssmDouble>(size); 446 447 ISSM_MPI_Allreduce(maxx,allmax,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm()); 448 ISSM_MPI_Allreduce(minx,allmin,size,ISSM_MPI_PDOUBLE,ISSM_MPI_MIN,IssmComm::GetComm()); 449 450 /*Store for later use in histogram computation:*/ 451 maxmeans[f]=allmax; 452 minmeans[f]=allmin; 453 454 } /*}}}*/ 455 } 456 457 /*Now that we have the min and max, we can start binning. First allocate 458 * histograms, then start filling them:*/ 459 IssmDouble** histogram=xNew<IssmDouble*>(nfields*nsteps); 460 IssmDouble** timehistogram=xNew<IssmDouble*>(nfields); 461 _printf0_("Start reading files again, this time binning values in the histogram:\n"); 462 /*Start opening files:*/ 463 for (int i=(lower_row+1);i<=upper_row;i++){ 464 _printf0_("reading file #: " << i << "\n"); 465 /*read file and make a buffer:{{{*/ 466 char file[1000]; 467 long int length; 468 char* buffer=NULL; 469 470 /*string:*/ 471 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i); 472 473 /*open file: */ 474 _printf0_(" opening file:\n"); 475 FILE* fid=fopen(file,"rb"); 476 if(fid==NULL)_error_("cound not open file: " << file << "\n"); 477 478 /*figure out size of file, and read the whole thing:*/ 479 _printf0_(" reading file:\n"); 480 fseek (fid, 0, SEEK_END); 481 length = ftell (fid); 482 fseek (fid, 0, SEEK_SET); 483 buffer = xNew<char>(length); 484 fread (buffer, sizeof(char), length, fid); 485 486 /*close file:*/ 487 fclose (fid); 488 489 /*create a memory stream with this buffer:*/ 490 _printf0_(" processing file:\n"); 491 fid=fmemopen(buffer, length, "rb"); 492 /*}}}*/ 493 /*read data and fill up the histogram using the min and max values from before:{{{*/ 494 for (int f=0;f<nfields;f++){ 495 char* field=fields[f]; 496 fseek(fid,0,SEEK_SET); 497 for (int j=0;j<nsteps;j++){ 498 int counter=f*nsteps+j; 499 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 500 if(i==(lower_row+1)){ 501 if(xtype[counter]==1){ 502 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(nbins); 503 IssmDouble ma=*maxxs[counter]; 504 IssmDouble mi=*minxs[counter]; 505 int index=(scalar-mi)/(ma-mi)*nbins; if (index==nbins)index--; 506 if(ma==mi)index=0; 507 //_printf_( index << "|" << scalar << "|" << mi << "|" << ma << "|" << nbins << "\n"); 508 localhistogram[index]++; 509 histogram[counter]=localhistogram; 510 } 511 else if (xtype[counter]==3){ 512 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(doublematsize*nbins); 513 IssmDouble* ma=maxxs[counter]; 514 IssmDouble* mi=minxs[counter]; 515 for (int k=0;k<doublematsize;k++){ 516 IssmDouble scalar=doublemat[k]; 517 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index--; 518 if (mi[k]==ma[k])index=0; 519 _assert_(scalar<=ma[k]); _assert_(scalar>=mi[k]); _assert_(index<nbins); 520 localhistogram[k*nbins+index]++; 521 } 522 histogram[counter]=localhistogram; 523 xDelete<IssmDouble>(doublemat); 524 } 525 else _error_("cannot carry out statistics on type " << xtype[counter]); 526 } 527 else{ 528 if(xtype[counter]==1){ 529 IssmDouble* localhistogram=histogram[counter]; 530 IssmDouble ma=*maxxs[counter]; 531 IssmDouble mi=*minxs[counter]; 532 int index=(scalar-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1; 533 if(ma==mi)index=0; 534 localhistogram[index]++; 535 } 536 else if (xtype[counter]==3){ 537 IssmDouble* localhistogram=histogram[counter]; 538 IssmDouble* ma=maxxs[counter]; 539 IssmDouble* mi=minxs[counter]; 540 for (int k=0;k<doublematsize;k++){ 541 IssmDouble scalar=doublemat[k]; 542 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1; 543 if (mi[k]==ma[k])index=0; 544 545 localhistogram[k*nbins+index]++; 546 } 547 xDelete<IssmDouble>(doublemat); 548 } 549 else _error_("cannot carry out statistics on type " << xtype[counter]); 550 } 551 } 552 } 553 /*}}}*/ 554 /*Deal with average in time: {{{*/ 555 _printf0_(" average in time:\n"); 556 for (int f=0;f<nfields;f++){ 557 fseek(fid,0,SEEK_SET); 558 char* field=fields[f]; 559 meanxtype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]); 560 561 if(meanxtype[f]==1){ 562 IssmDouble timemean=0; 563 fseek(fid,0,SEEK_SET); 564 for (int j=0;j<nsteps;j++){ 565 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 566 timemean+=scalar/nsteps; 567 } 568 569 /*Figure out max and min of time means: */ 570 if(i==(lower_row+1)){ 571 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(nbins); 572 IssmDouble ma=*maxmeans[f]; 573 IssmDouble mi=*minmeans[f]; 574 int index=(timemean-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1; 575 if(ma==mi)index=0; 576 localhistogram[index]++; 577 timehistogram[f]=localhistogram; 578 } 579 else{ 580 IssmDouble* localhistogram=timehistogram[f]; 581 IssmDouble ma=*maxmeans[f]; 582 IssmDouble mi=*minmeans[f]; 583 int index=(timemean-mi)/(ma-mi)*nbins; if (index==nbins)index=nbins-1; 584 if(ma==mi)index=0; 585 localhistogram[index]++; 586 } 587 } 588 else{ 589 fseek(fid,0,SEEK_SET); 590 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize); 591 for (int j=0;j<nsteps;j++){ 592 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 593 for (int k=0;k<doublematsize;k++){ 594 timemean[k]+=doublemat[k]/nsteps; 595 } 596 xDelete<IssmDouble>(doublemat); 597 } 598 599 if(i==(lower_row+1)){ 600 IssmDouble* localhistogram=xNewZeroInit<IssmDouble>(doublematsize*nbins); 601 IssmDouble* ma=maxmeans[f]; 602 IssmDouble* mi=minmeans[f]; 603 604 for (int k=0;k<doublematsize;k++){ 605 IssmDouble scalar=timemean[k]; 606 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1; 607 if (mi[k]==ma[k])index=0; 608 localhistogram[k*nbins+index]++; 609 } 610 timehistogram[f]=localhistogram; 611 } 612 else{ 613 614 IssmDouble* localhistogram=timehistogram[f]; 615 IssmDouble* ma=maxmeans[f]; 616 IssmDouble* mi=minmeans[f]; 617 618 for (int k=0;k<doublematsize;k++){ 619 IssmDouble scalar=timemean[k]; 620 int index=(scalar-mi[k])/(ma[k]-mi[k])*nbins; if (index==nbins)index=nbins-1; 621 if (mi[k]==ma[k])index=0; 622 623 localhistogram[k*nbins+index]++; 624 } 625 } 626 } 627 } 628 /*}}}*/ 629 /*close file and delete allocation:{{{*/ 630 fclose(fid); 631 xDelete<char>(buffer); 632 /*}}}*/ 633 } 634 635 636 /*We have agregated histograms across the cluster, now gather them across the cluster onto 637 *cpu0: */ 638 _printf0_("Collect histograms on cpu 0 and save to results:\n"); 639 for (int f=0;f<nfields;f++){ 640 int counter0=f*nsteps+0; 641 if (xtype[counter0]==1){ /*deal with scalars {{{*/ 642 for (int j=0;j<nsteps;j++){ 643 int counter=f*nsteps+j; 644 645 /*we are broadcasting doubles:*/ 646 IssmDouble* histo=histogram[counter]; //size nbins 647 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(nbins); 648 649 ISSM_MPI_Allreduce(histo,allhisto,nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm()); 650 xDelete<IssmDouble>(histo); 651 652 /*add to results while deallocating as much as possible:*/ 653 char fieldname[1000]; 654 if(my_rank==0){ 655 sprintf(fieldname,"%s%s",fields[f],"Histogram"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,1,nbins,j+1,0)); 656 } 657 xDelete<IssmDouble>(allhisto); 658 if(my_rank==0){ 659 sprintf(fieldname,"%s%s",fields[f],"Max"); results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*maxxs[counter],j+1,0)); 660 sprintf(fieldname,"%s%s",fields[f],"Min"); results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*minxs[counter],j+1,0)); 661 } 662 xDelete<IssmDouble>(maxxs[counter]); 663 xDelete<IssmDouble>(minxs[counter]); 664 } 665 } /*}}}*/ 666 else{ /*deal with arrays:{{{*/ 667 668 int size=xsize[counter0]; 669 for (int j=0;j<nsteps;j++){ 670 int counter=f*nsteps+j; 671 672 /*we are broadcasting double arrays:*/ 673 IssmDouble* histo=histogram[counter]; 674 IssmDouble* allhisto=xNew<IssmDouble>(size*nbins); 675 676 ISSM_MPI_Allreduce(histo,allhisto,size*nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm()); 677 xDelete<IssmDouble>(histo); 678 679 /*add to results:*/ 680 char fieldname[1000]; 681 if(my_rank==0){ 682 sprintf(fieldname,"%s%s",fields[f],"Histogram"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,size,nbins,j+1,0)); 683 } 684 xDelete<IssmDouble>(allhisto); 685 if(my_rank==0){ 686 sprintf(fieldname,"%s%s",fields[f],"Max"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,maxxs[counter],size,1,j+1,0)); 687 sprintf(fieldname,"%s%s",fields[f],"Min"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,minxs[counter],size,1,j+1,0)); 688 } 689 xDelete<IssmDouble>(maxxs[counter]); 690 xDelete<IssmDouble>(minxs[counter]); 691 } 692 } /*}}}*/ 693 } 694 /*Now do the same for the time mean fields:*/ 695 _printf0_("Collect time mean histograms on cpu 0 and save to results:\n"); 696 for (int f=0;f<nfields;f++){ 697 if (meanxtype[f]==1){ /*deal with scalars {{{*/ 698 699 /*we are broadcasting doubles:*/ 700 IssmDouble* histo=timehistogram[f]; 701 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(nbins); 702 703 ISSM_MPI_Allreduce(histo,allhisto,nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_MAX,IssmComm::GetComm()); 704 xDelete<IssmDouble>(histo); 705 706 /*add to results at time step 1:*/ 707 char fieldname[1000]; 708 if(my_rank==0){ 709 sprintf(fieldname,"%s%s",fields[f],"TimeMeanHistogram"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,1,nbins,steps[0],0)); 710 } 711 xDelete<IssmDouble>(allhisto); 712 if(my_rank==0){ 713 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMax"); results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*maxmeans[f],steps[0],0)); 714 sprintf(fieldname,"%s%s",fields[f],"TimeMeaMin"); results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,*minmeans[f],steps[0],0)); 715 } 716 xDelete<IssmDouble>(maxmeans[f]); 717 xDelete<IssmDouble>(minmeans[f]); 718 } /*}}}*/ 719 else{ /*deal with arrays:{{{*/ 720 721 int size=meanxsize[f]; 722 723 /*we are broadcasting double arrays:*/ 724 IssmDouble* histo=timehistogram[f]; 725 IssmDouble* allhisto=xNewZeroInit<IssmDouble>(size*nbins); 726 727 ISSM_MPI_Allreduce(histo,allhisto,size*nbins,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,IssmComm::GetComm()); 728 xDelete<IssmDouble>(histo); 729 730 /*add to results at step 1:*/ 731 char fieldname[1000]; 732 if(my_rank==0){ 733 sprintf(fieldname,"%s%s",fields[f],"TimeMeanHistogram"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allhisto,size,nbins,steps[0],0)); 734 } 735 xDelete<IssmDouble>(allhisto); 736 if(my_rank==0){ 737 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMax"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,maxmeans[f],size,1,steps[0],0)); 738 sprintf(fieldname,"%s%s",fields[f],"TimeMeanMin"); results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,minmeans[f],size,1,steps[0],0)); 739 } 740 xDelete<IssmDouble>(maxmeans[f]); 741 xDelete<IssmDouble>(minmeans[f]); 742 } /*}}}*/ 743 } 744 _printf0_("Done aggregating time mean histogram:\n"); 745 IssmComm::SetComm(ISSM_MPI_COMM_WORLD); 746 747 /*Free allocations:*/ 748 xDelete<char>(directory); 749 xDelete<char>(model); 750 for (int i=0;i<nfields;i++)xDelete<char>(fields[i]); 751 xDelete<char*>(fields); 752 xDelete<int>(steps); 753 xDelete<IssmDouble*>(maxxs); 754 xDelete<IssmDouble*>(minxs); 755 xDelete<IssmDouble*>(maxmeans); 756 xDelete<IssmDouble*>(minmeans); 757 xDelete<int>(xtype); 758 xDelete<int>(xsize); 759 760 return 1; 761 } 762 /*}}}*/ 763 int ComputeMeanVariance(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/ 764 765 int nsamples; 766 char* directory=NULL; 767 char* model=NULL; 768 char** fields=NULL; 769 int* steps=NULL; 770 int nsteps; 771 int nfields; 772 int range,lower_row,upper_row; 773 int nfilesperdirectory; 774 775 /*intermediary:*/ 776 IssmDouble* doublemat=NULL; 777 int doublematsize; 778 IssmDouble scalar; 779 780 /*computation of average and variance itself:*/ 781 IssmDouble* x = NULL; 782 IssmDouble* x2 = NULL; 783 IssmDouble** xs = NULL; 784 IssmDouble** xs2 = NULL; 785 int* xtype=NULL; 786 int* xsize=NULL; 787 788 IssmDouble** meanx=NULL; 789 IssmDouble** meanx2=NULL; 790 int* meantype=NULL; 791 int* meansize=NULL; 792 793 /*only work on the statistical communicator: */ 794 if (color==MPI_UNDEFINED)return 0; 795 796 /*Retrieve parameters:*/ 797 parameters->FindParam(&nfilesperdirectory,QmuNfilesPerDirectoryEnum); 798 parameters->FindParam(&nsamples,QmuNsampleEnum); 799 parameters->FindParam(&directory,DirectoryNameEnum); 800 parameters->FindParam(&model,InputFileNameEnum); 801 parameters->FindParam(&fields,&nfields,FieldsEnum); 802 parameters->FindParam(&steps,&nsteps,StepsEnum); 803 804 /*Get rank from the stat comm communicator:*/ 805 IssmComm::SetComm(statcomm); 806 int my_rank=IssmComm::GetRank(); 807 808 /*Open files and read them complelety, in a distributed way:*/ 809 range=DetermineLocalSize(nsamples,IssmComm::GetComm()); 810 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm()); 811 812 /*Initialize arrays:*/ 813 xs=xNew<IssmDouble*>(nfields*nsteps); 814 xs2=xNew<IssmDouble*>(nfields*nsteps); 815 xtype=xNew<int>(nfields*nsteps); 816 xsize=xNew<int>(nfields*nsteps); 817 818 meantype=xNew<int>(nfields); 819 meansize=xNew<int>(nfields); 820 meanx=xNew<IssmDouble*>(nfields); 821 meanx2=xNew<IssmDouble*>(nfields); 822 823 /*Start opening files:*/ 824 for (int i=(lower_row+1);i<=upper_row;i++){ 825 _printf0_("reading file #: " << i << "\n"); 826 char file[1000]; 827 long int length; 828 char* buffer=NULL; 829 830 /*string:*/ 831 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i); 832 833 /*open file: */ 834 _printf0_(" opening file: " << file << "\n"); 835 FILE* fid=fopen(file,"rb"); 836 if(fid==NULL) _error_(" could not open file: " << file << "\n"); 837 838 /*figure out size of file, and read the whole thing:*/ 839 _printf0_(" reading file:\n"); 840 fseek (fid, 0, SEEK_END); 841 length = ftell (fid); 842 fseek (fid, 0, SEEK_SET); 843 buffer = xNew<char>(length); 844 fread (buffer, sizeof(char), length, fid); 845 846 /*close file:*/ 847 fclose (fid); 848 849 /*create a memory stream with this buffer:*/ 850 _printf0_(" processing file:\n"); 851 fid=fmemopen(buffer, length, "rb"); 852 853 /*start reading data from the buffer directly:*/ 854 for (int f=0;f<nfields;f++){ 855 char* field=fields[f]; 856 fseek(fid,0,SEEK_SET); 857 for (int j=0;j<nsteps;j++){ 858 int counter=f*nsteps+j; 859 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 860 if(i==(lower_row+1)){ 861 if(xtype[counter]==1){ 862 xs[counter]=xNew<IssmDouble>(1); 863 xs2[counter]=xNew<IssmDouble>(1); 864 *xs[counter]=scalar; 865 *xs2[counter]=pow(scalar,2.0); 866 xsize[counter]=1; 867 } 868 else if (xtype[counter]==3){ 869 IssmDouble* doublemat2=xNew<IssmDouble>(doublematsize); 870 for(int k=0;k<doublematsize;k++)doublemat2[k]=pow(doublemat[k],2.0); 871 xs[counter]=doublemat; 872 xs2[counter]=doublemat2; 873 xsize[counter]=doublematsize; 874 } 875 else _error_("cannot carry out statistics on type " << xtype[counter]); 876 } 877 else{ 878 if(xtype[counter]==1){ 879 *xs[counter]+=scalar; 880 *xs2[counter]+=pow(scalar,2.0); 881 } 882 else if (xtype[counter]==3){ 883 IssmDouble* newdoublemat=xs[counter]; 884 IssmDouble* newdoublemat2=xs2[counter]; 885 for(int k=0;k<doublematsize;k++){ 886 newdoublemat[k]+=doublemat[k]; 887 newdoublemat2[k]+=pow(doublemat[k],2.0); 888 } 889 xs[counter]=newdoublemat; 890 xs2[counter]=newdoublemat2; 891 } 892 else _error_("cannot carry out statistics on type " << xtype[counter]); 893 } 894 } 895 } 896 897 /*Deal with time mean: */ 898 for (int f=0;f<nfields;f++){ 899 char* field=fields[f]; 900 fseek(fid,0,SEEK_SET); 901 meantype[f]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[0]); 902 if(i==(lower_row+1)){ 903 if(meantype[f]==1){ 904 meanx[f]=xNewZeroInit<IssmDouble>(1); 905 meanx2[f]=xNewZeroInit<IssmDouble>(1); 906 meansize[f]=1; 907 } 908 else{ 909 meanx[f]=xNewZeroInit<IssmDouble>(doublematsize); 910 meanx2[f]=xNewZeroInit<IssmDouble>(doublematsize); 911 meansize[f]=doublematsize; 912 } 913 } 914 fseek(fid,0,SEEK_SET); 915 if(meantype[f]==1){ 916 IssmDouble sc=0; 917 IssmDouble sc2=0; 918 for(int j=0;j<nsteps;j++){ 919 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 920 sc+=scalar/nsteps; 921 } 922 sc2+=pow(sc,2.0); 923 *meanx[f]+=sc; 924 *meanx2[f]+=sc2; 925 } 926 else{ 927 IssmDouble* sc=meanx[f]; 928 IssmDouble* sc2=meanx2[f]; 929 IssmDouble* timemean=xNewZeroInit<IssmDouble>(doublematsize); 930 IssmDouble* timemean2=xNewZeroInit<IssmDouble>(doublematsize); 931 932 for(int j=0;j<nsteps;j++){ 933 readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 934 for (int k=0;k<doublematsize;k++){ 935 timemean[k]+=doublemat[k]/nsteps; 936 } 937 } 938 for (int k=0;k<doublematsize;k++){ 939 timemean2[k]=pow(timemean[k],2.0); 940 } 941 for (int k=0;k<doublematsize;k++){ 942 sc[k]+=timemean[k]; 943 sc2[k]+=timemean2[k]; 944 } 945 946 } 947 948 } 949 fclose(fid); 950 951 /*delete buffer:*/ 952 xDelete<char>(buffer); 953 } 954 ISSM_MPI_Barrier(IssmComm::GetComm()); 955 _printf0_("Done reading files, now computing mean and variance.\n"); 956 957 /*We have agregated x and x^2 across the cluster, now gather across the cluster onto 958 *cpu0 and then compute statistics:*/ 959 for (int f=0;f<nfields;f++){ 960 int counter0=f*nsteps+0; 961 if (xtype[counter0]==1){ /*deal with scalars {{{*/ 962 IssmDouble mean,stddev; 963 for (int j=0;j<nsteps;j++){ 964 int counter=f*nsteps+j; 965 966 /*we are broadcasting doubles:*/ 967 IssmDouble scalar=*xs[counter]; 968 IssmDouble scalar2=*xs2[counter]; 969 IssmDouble sumscalar; 970 IssmDouble sumscalar2; 971 972 ISSM_MPI_Reduce(&scalar,&sumscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 973 ISSM_MPI_Reduce(&scalar2,&sumscalar2,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 974 /*Build average and standard deviation. For standard deviation, use the 975 *following formula: sigma^2=E(x^2)-mu^2:*/ 976 mean=sumscalar/nsamples; 977 stddev=sqrt(sumscalar2/nsamples-pow(mean,2.0)); 978 979 /*add to results:*/ 980 if(my_rank==0){ 981 char fieldname[1000]; 982 983 sprintf(fieldname,"%s%s",fields[f],"Mean"); 984 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,mean,j+1,0)); 985 sprintf(fieldname,"%s%s",fields[f],"Stddev"); 986 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,stddev,j+1,0)); 987 } 988 989 } 990 } /*}}}*/ 991 else{ /*deal with arrays:{{{*/ 992 993 int size=xsize[counter0]; 994 995 IssmDouble* mean=xNew<IssmDouble>(size); 996 IssmDouble* stddev=xNew<IssmDouble>(size); 997 998 for (int j=0;j<nsteps;j++){ 999 int counter=f*nsteps+j; 1000 1001 /*we are broadcasting double arrays:*/ 1002 x=xs[counter]; 1003 x2=xs2[counter]; 1004 1005 IssmDouble* sumx=xNew<IssmDouble>(size); 1006 IssmDouble* sumx2=xNew<IssmDouble>(size); 1007 1008 ISSM_MPI_Reduce(x,sumx,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1009 ISSM_MPI_Reduce(x2,sumx2,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1010 1011 /*Build average and standard deviation. For standard deviation, use the 1012 *following formula: sigma^2=E(x^2)-mu^2:*/ 1013 for (int k=0;k<size;k++){ 1014 mean[k]=sumx[k]/nsamples; 1015 stddev[k]=sqrt(sumx2[k]/nsamples-pow(mean[k],2.0)); 1016 } 1017 1018 /*add to results:*/ 1019 if(my_rank==0){ 1020 char fieldname[1000]; 1021 1022 sprintf(fieldname,"%s%s",fields[f],"Mean"); 1023 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,mean,size,1,j+1,0)); 1024 sprintf(fieldname,"%s%s",fields[f],"Stddev"); 1025 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,stddev,size,1,j+1,0)); 1026 } 1027 } 1028 } /*}}}*/ 1029 } 1030 /*Do the same but for the time mean:*/ 1031 for (int f=0;f<nfields;f++){ 1032 if (meantype[f]==1){ /*deal with scalars {{{*/ 1033 IssmDouble mean,stddev; 1034 1035 /*we are broadcasting doubles:*/ 1036 IssmDouble scalar=*meanx[f]; 1037 IssmDouble scalar2=*meanx2[f]; 1038 IssmDouble sumscalar; 1039 IssmDouble sumscalar2; 1040 1041 ISSM_MPI_Reduce(&scalar,&sumscalar,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1042 ISSM_MPI_Reduce(&scalar2,&sumscalar2,1,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1043 /*Build average and standard deviation. For standard deviation, use the 1044 *following formula: sigma^2=E(x^2)-mu^2:*/ 1045 mean=sumscalar/nsamples; 1046 stddev=sqrt(sumscalar2/nsamples-pow(mean,2.0)); 1047 1048 /*add to results:*/ 1049 if(my_rank==0){ 1050 char fieldname[1000]; 1051 1052 sprintf(fieldname,"%s%s",fields[f],"TimeMean"); 1053 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,mean,steps[0],0)); 1054 sprintf(fieldname,"%s%s",fields[f],"TimeStddev"); 1055 results->AddResult(new GenericExternalResult<IssmDouble>(results->Size()+1,fieldname,stddev,steps[0],0)); 1056 } 1057 } /*}}}*/ 1058 else{ /*deal with arrays:{{{*/ 1059 1060 int size=meansize[f]; 1061 IssmDouble* mean=xNew<IssmDouble>(size); 1062 IssmDouble* stddev=xNew<IssmDouble>(size); 1063 1064 /*we are broadcasting double arrays:*/ 1065 x=meanx[f]; 1066 x2=meanx2[f]; 1067 1068 IssmDouble* sumx=xNew<IssmDouble>(size); 1069 IssmDouble* sumx2=xNew<IssmDouble>(size); 1070 1071 ISSM_MPI_Reduce(x,sumx,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1072 ISSM_MPI_Reduce(x2,sumx2,size,ISSM_MPI_PDOUBLE,ISSM_MPI_SUM,0,IssmComm::GetComm()); 1073 1074 /*Build average and standard deviation. For standard deviation, use the 1075 *following formula: sigma^2=E(x^2)-mu^2:*/ 1076 for (int k=0;k<size;k++){ 1077 mean[k]=sumx[k]/nsamples; 1078 stddev[k]=sqrt(sumx2[k]/nsamples-pow(mean[k],2.0)); 1079 } 1080 1081 /*add to results:*/ 1082 if(my_rank==0){ 1083 char fieldname[1000]; 1084 1085 sprintf(fieldname,"%s%s",fields[f],"TimeMean"); 1086 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,mean,size,1,steps[0],0)); 1087 sprintf(fieldname,"%s%s",fields[f],"TimeStddev"); 1088 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,stddev,size,1,steps[0],0)); 1089 } 1090 } /*}}}*/ 1091 } 1092 1093 _printf0_("Done with MeanVariance:\n"); 1094 IssmComm::SetComm(ISSM_MPI_COMM_WORLD); 1095 1096 return 1; 1097 } /*}}}*/ 1098 int ComputeSampleSeries(Parameters* parameters,Results* results,int color, ISSM_MPI_Comm statcomm){ /*{{{*/ 1099 1100 int nsamples; 1101 char* directory=NULL; 1102 char* model=NULL; 1103 char** fields=NULL; 1104 int* steps=NULL; 1105 int nsteps; 1106 int nfields; 1107 int range,lower_row,upper_row; 1108 int nfilesperdirectory; 1109 int* indices=NULL; 1110 int nindices; 1111 1112 /*intermediary:*/ 1113 IssmDouble* doublemat=NULL; 1114 int doublematsize; 1115 IssmDouble scalar; 1116 1117 /*computation of average and variance itself:*/ 1118 IssmDouble* x = NULL; 1119 IssmDouble* allx=NULL; 1120 IssmDouble** xs = NULL; 1121 int* xtype=NULL; 1122 int* xsize=NULL; 1123 1124 /*only work on the statistical communicator: */ 1125 if (color==MPI_UNDEFINED)return 0; 1126 1127 /*Retrieve parameters:*/ 1128 parameters->FindParam(&nsamples,QmuNsampleEnum); 1129 parameters->FindParam(&directory,DirectoryNameEnum); 1130 parameters->FindParam(&model,InputFileNameEnum); 1131 parameters->FindParam(&fields,&nfields,FieldsEnum); 1132 parameters->FindParam(&steps,&nsteps,StepsEnum); 1133 parameters->FindParam(&indices,&nindices,IndicesEnum); 1134 1135 /*Get rank from the stat comm communicator:*/ 1136 IssmComm::SetComm(statcomm); 1137 int my_rank=IssmComm::GetRank(); 1138 1139 /*Open files and read them complelety, in a distributed way:*/ 1140 range=DetermineLocalSize(nsamples,IssmComm::GetComm()); 1141 GetOwnershipBoundariesFromRange(&lower_row,&upper_row,range,IssmComm::GetComm()); 1142 1143 /*Initialize arrays:*/ 1144 xs=xNew<IssmDouble*>(nfields*nsteps); 1145 xtype=xNew<int>(nfields*nsteps); 1146 xsize=xNew<int>(nfields*nsteps); 1147 1148 /*Start opening files:*/ 1149 for (int i=(lower_row+1);i<=upper_row;i++){ 1150 _printf0_("reading file #: " << i << "\n"); 1151 char file[1000]; 1152 long int length; 1153 char* buffer=NULL; 1154 1155 /*string:*/ 1156 sprintf(file,"%s/%i/%s.outbin.%i",directory,my_rank+1,model,i); 1157 1158 /*open file: */ 1159 _printf0_(" opening file:\n"); 1160 FILE* fid=fopen(file,"rb"); 1161 1162 /*figure out size of file, and read the whole thing:*/ 1163 _printf0_(" reading file:\n"); 1164 fseek (fid, 0, SEEK_END); 1165 length = ftell (fid); 1166 fseek (fid, 0, SEEK_SET); 1167 buffer = xNew<char>(length); 1168 fread (buffer, sizeof(char), length, fid); 1169 1170 /*close file:*/ 1171 fclose (fid); 1172 1173 /*create a memory stream with this buffer:*/ 1174 _printf0_(" processing file:\n"); 1175 fid=fmemopen(buffer, length, "rb"); 1176 1177 /*start reading data from the buffer directly:*/ 1178 for (int f=0;f<nfields;f++){ 1179 fseek(fid,0,SEEK_SET); 1180 char* field=fields[f]; 1181 for (int j=0;j<nsteps;j++){ 1182 int counter=f*nsteps+j; 1183 xtype[counter]=readdata(&doublemat, &doublematsize, &scalar, fid,field,steps[j]); 1184 if(i==(lower_row+1)){ 1185 if(xtype[counter]==1){ 1186 x=xNew<IssmDouble>(range); 1187 x[0]=scalar; 1188 xs[counter]=x; 1189 xsize[counter]=range; 1190 } 1191 else if (xtype[counter]==3){ 1192 x=xNew<IssmDouble>(nindices*range); 1193 for(int k=0;k<nindices;k++)x[(i-(lower_row+1))*nindices+k]=doublemat[indices[k]-1]; 1194 xs[counter]=x; 1195 xsize[counter]=range*nindices; 1196 } 1197 else _error_("cannot carry out statistics on type " << xtype[counter]); 1198 } 1199 else{ 1200 if(xtype[counter]==1){ 1201 x=xs[counter]; 1202 x[i-(lower_row+1)]=scalar; 1203 xs[counter]=x; 1204 } 1205 else if (xtype[counter]==3){ 1206 x=xs[counter]; 1207 for(int k=0;k<nindices;k++)x[(i-(lower_row+1))*nindices+k]=doublemat[indices[k]-1]; 1208 xs[counter]=x; 1209 } 1210 else _error_("cannot carry out statistics on type " << xtype[counter]); 1211 } 1212 } 1213 } 1214 fclose(fid); 1215 1216 /*delete buffer:*/ 1217 xDelete<char>(buffer); 1218 } 1219 ISSM_MPI_Barrier(IssmComm::GetComm()); 1220 _printf0_("Done reading files, now assembling time series.\n"); 1221 1222 for (int f=0;f<nfields;f++){ 1223 for (int j=0;j<nsteps;j++){ 1224 int counter=f*nsteps+j; 1225 if (xtype[counter]==1){ 1226 /*we are broadcasting range times doubles:*/ 1227 x=xs[counter]; 1228 allx=xNew<IssmDouble>(nsamples); 1229 MPI_Gather(x, range, ISSM_MPI_PDOUBLE,allx, range, ISSM_MPI_PDOUBLE, 0, IssmComm::GetComm()); 1230 /*add to results:*/ 1231 if(my_rank==0){ 1232 char fieldname[1000]; 1233 1234 sprintf(fieldname,"%s%s",fields[f],"Samples"); 1235 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allx,nsamples,1,j+1,0)); 1236 } 1237 } 1238 else{ 1239 /*we are broadcasting double arrays:*/ 1240 x=xs[counter]; 1241 allx=xNew<IssmDouble>(nsamples*nindices); 1242 1243 MPI_Gather(x, range*nindices, ISSM_MPI_PDOUBLE,allx, range*nindices, ISSM_MPI_PDOUBLE, 0, IssmComm::GetComm()); 1244 1245 /*add to results:*/ 1246 if(my_rank==0){ 1247 char fieldname[1000]; 1248 sprintf(fieldname,"%s%s",fields[f],"Samples"); 1249 results->AddResult(new GenericExternalResult<IssmPDouble*>(results->Size()+1,fieldname,allx,nsamples,nindices,j+1,0)); 1250 } 1251 } 1252 } 1253 } 1254 _printf0_("Done with SampleSeries:\n"); 1255 IssmComm::SetComm(ISSM_MPI_COMM_WORLD); 1256 1257 return 1; 1258 } /*}}}*/ 1259 int OutputStatistics(Parameters* parameters,Results* results,int color,ISSM_MPI_Comm statcomm){ /*{{{*/ 1260 1261 char outputfilename[1000]; 1262 char* directory=NULL; 1263 char* model=NULL; 1264 char* method=NULL; 1265 int nsamples; 1266 int* steps=NULL; 1267 int nsteps; 1268 1269 /*only work on the statistical communicator: */ 1270 if (color==MPI_UNDEFINED)return 0; 1271 1272 FemModel* femmodel=new FemModel(); 1273 1274 /*Some parameters that will allow us to use the OutputResultsx module:*/ 1275 parameters->AddObject(new BoolParam(QmuIsdakotaEnum,false)); 1276 parameters->AddObject(new BoolParam(SettingsIoGatherEnum,true)); 1277 1278 parameters->FindParam(&directory,DirectoryNameEnum); 1279 parameters->FindParam(&model,InputFileNameEnum); 1280 parameters->FindParam(&nsamples,QmuNsampleEnum); 1281 parameters->FindParam(&steps,&nsteps,StepsEnum); 1282 1283 sprintf(outputfilename,"%s/%s.stats",directory,model); 1284 parameters->AddObject(new StringParam(OutputFileNameEnum,outputfilename)); 1285 1286 /*Call OutputResults module:*/ 1287 femmodel->parameters=parameters; 1288 femmodel->results=results; 1289 1290 OutputResultsx(femmodel); 1291 1292 return 1; 1293 } /*}}}*/ 1294 int readdata(IssmDouble** pdoublemat, int* pdoublematsize, IssmDouble* pdouble, FILE* fid,char* field,int step){ /*{{{*/ 1295 1296 int length; 1297 char fieldname[1000]; 1298 int fieldname_size; 1299 IssmDouble rtime; 1300 int rstep; 1301 int M,N; 1302 1303 //fields that we retrive: 1304 IssmDouble dfield; 1305 char* sfield = NULL; 1306 IssmDouble* dmatfield = NULL; 1307 int* imatfield = NULL; 1308 1309 //type of the returned field: 1310 int type; 1311 int found=0; 1312 1313 while(1){ 1314 1315 size_t ret_code = fread(&fieldname_size, sizeof(int), 1, fid); 1316 if(ret_code != 1) break; //we are done. 1317 1318 fread(fieldname, sizeof(char), fieldname_size, fid); 1319 //_printf0_("fieldname: " << fieldname << "\n"); 1320 1321 fread(&rtime, sizeof(IssmDouble), 1, fid); 1322 fread(&rstep, sizeof(int), 1, fid); 1323 1324 //check on field: 1325 if ((step==rstep) && (strcmp(field,fieldname)==0)){ 1326 1327 //ok, go read the result really: 1328 fread(&type,sizeof(int),1,fid); 1329 fread(&M,sizeof(int),1,fid); 1330 if (type==1){ 1331 fread(&dfield,sizeof(IssmDouble),1,fid); 1332 } 1333 else if (type==2){ 1334 fread(&M,sizeof(int),1,fid); 1335 sfield=xNew<char>(M); 1336 fread(sfield,sizeof(char),M,fid); 1337 } 1338 else if (type==3){ 1339 fread(&N,sizeof(int),1,fid); 1340 dmatfield=xNew<IssmDouble>(M*N); 1341 fread(dmatfield,sizeof(IssmDouble),M*N,fid); 1342 } 1343 else if (type==4){ 1344 fread(&N,sizeof(int),1,fid); 1345 imatfield=xNew<int>(M*N); 1346 fread(imatfield,sizeof(int),M*N,fid); 1347 } 1348 else _error_("cannot read data of type " << type << "\n"); 1349 found=1; 1350 break; 1351 } 1352 else{ 1353 //just skim to next results. 1354 fread(&type,sizeof(int),1,fid); 1355 fread(&M,sizeof(int),1,fid); 1356 if (type==1){ 1357 fseek(fid,sizeof(IssmDouble),SEEK_CUR); 1358 } 1359 else if(type==2){ 1360 fseek(fid,M*sizeof(char),SEEK_CUR); 1361 } 1362 else if(type==3){ 1363 fread(&N,sizeof(int),1,fid); 1364 fseek(fid,M*N*sizeof(IssmDouble),SEEK_CUR); 1365 } 1366 else if(type==4){ 1367 fread(&N,sizeof(int),1,fid); 1368 fseek(fid,M*N*sizeof(int),SEEK_CUR); 1369 } 1370 else _error_("cannot read data of type " << type << "\n"); 1371 } 1372 } 1373 if(found==0)_error_("cound not find " << field << " at step " << step << "\n"); 1374 1375 /*assign output pointers:*/ 1376 *pdoublemat=dmatfield; 1377 *pdoublematsize=M*N; 1378 *pdouble=dfield; 1379 1380 /*return:*/ 1381 return type; 1382 1383 } 1384 /*}}}*/ 1385 bool DakotaDirStructure(int argc,char** argv){ /*{{{*/ 1386 1387 char* input_file; 1388 FILE* fid; 1389 IoModel* iomodel=NULL; 1390 int check; 1391 1392 //qmu statistics 1393 bool statistics = false; 1394 int numdirectories = 0; 1395 1396 /*First things first, set the communicator as a global variable: */ 1397 IssmComm::SetComm(MPI_COMM_WORLD); 1398 1399 /*Barrier:*/ 1400 ISSM_MPI_Barrier(IssmComm::GetComm()); 1401 _printf0_("Preparing directory structure for model outputs:" << "\n"); 1402 1403 //open model input file for reading 1404 input_file=xNew<char>((strlen(argv[2])+strlen(argv[3])+strlen(".bin")+2)); 1405 sprintf(input_file,"%s/%s%s",argv[2],argv[3],".bin"); 1406 fid=fopen(input_file,"rb"); 1407 if (fid==NULL) Cerr << "dirstructure error message: could not open model " << input_file << " to retrieve qmu statistics parameters" << std::endl; 1408 1409 //initialize IoModel, but light version, we just need it to fetch one constant: 1410 iomodel=new IoModel(); 1411 iomodel->fid=fid; 1412 iomodel->FetchConstants(); 1413 1414 //early return if statistics not requested: 1415 iomodel->FindConstant(&statistics,"md.qmu.statistics"); 1416 if(!statistics){ 1417 delete iomodel; 1418 xDelete<char>(input_file); 1419 fclose(fid); 1420 return false; //important return value! 1421 } 1422 1423 iomodel->FindConstant(&numdirectories,"md.qmu.statistics.ndirectories"); 1424 1425 /*Ok, we have everything we need to create the directory structure:*/ 1426 if(IssmComm::GetRank()==0){ 1427 for (int i=0;i<numdirectories;i++){ 1428 char directory[1000]; 1429 sprintf(directory,"./%i",i+1); 1430 1431 check = mkdir(directory,ACCESSPERMS); 1432 if (check) _error_("dirstructure error message: could not create directory " << directory << "\n"); 1433 } 1434 } 1435 1436 /*Delete resources:*/ 1437 delete iomodel; 1438 xDelete<char>(input_file); 1439 1440 //close model file: 1441 fclose(fid); 1442 1443 //return value: 1444 return true; //statistics computation on! 1445 } /*}}}*/
Note:
See TracChangeset
for help on using the changeset viewer.