/*!\file Patch.c * \brief: implementation of the Patch object */ /*Include files */ #ifdef HAVE_CONFIG_H #include #else #error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!" #endif #include #include #include #include "./classes.h" #include "../shared/shared.h" /*Object constructors and destructors:*/ /*FUNCTION Patch::Patch() default constructor {{{*/ Patch::Patch(){ this->numrows = 0; this->numcols = 0; this->maxvertices = 0; this->maxnodes = 0; this->values = NULL; } /*}}}*/ /*FUNCTION Patch::Patch(int numrows, int maxvertices, int maxnodes){{{*/ Patch::Patch(int in_numrows, int in_maxvertices, int in_maxnodes){ this->numrows=in_numrows; this->maxvertices=in_maxvertices; this->maxnodes=in_maxnodes; this->numcols=1 //enum_type +1 //step +1 //time +1 //element id +1 //interpolation type +maxvertices //vertices +maxnodes; //nodes //Allocate values and fill with NaN: if (this->numcols*this->numrows==0){ this->values=NULL; } else{ this->values=xNew(this->numcols*this->numrows); for(int i=0;inumrows;i++){ for(int j=0;jnumcols;j++){ this->values[i*this->numcols+j]=NAN; } } } } /*}}}*/ /*FUNCTION Patch::~Patch(){{{*/ Patch::~Patch(){ xDelete(values); } /*}}}*/ /*Object methods*/ /*FUNCTION Patch::fillelementinfo{{{*/ void Patch::fillelementinfo(int count, int element_id, int* vertices_ids, int num_vertices){ int i; IssmDouble* row=NULL; /*point to the start of the row: */ row=this->values+count*this->numcols; /*Let's remember what is on a row: enum_type step time element_id interpolation vertices_ids nodal_values */ row[3]=element_id; for(i=0;ivalues+count*this->numcols; /*Let's remember what is on a row: enum_type step time element_id interpolation vertices_ids nodal_values */ row[0]=enum_type; row[1]=(IssmDouble)step; row[2]=time; row[4]=interpolation; for(i=0;imaxvertices+i]=nodal_values[i]; } } /*}}}*/ /*FUNCTION Patch::Gather{{{*/ void Patch::Gather(void){ int count; int my_rank; int num_procs; int total_numrows; int node_numrows; IssmDouble *total_values = NULL; ISSM_MPI_Status status; /*recover my_rank:*/ my_rank=IssmComm::GetRank(); num_procs=IssmComm::GetSize(); /*First, figure out total number of rows combining all the cpus: */ ISSM_MPI_Reduce(&this->numrows,&total_numrows,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,IssmComm::GetComm() ); ISSM_MPI_Bcast(&total_numrows,1,ISSM_MPI_INT,0,IssmComm::GetComm()); /*return if patch empty*/ if(total_numrows==0) return; /*Now, allocate buffer to holds all the values, on node 0: */ if(my_rank==0)total_values=xNew(this->numcols*total_numrows); /*Start by copying node 0 values onto total_values: */ if(my_rank==0){ count=0; xMemCpy(total_values+count,this->values,this->numcols*this->numrows); count+=this->numrows*this->numcols; } /*Now, ask other nodes to send their values: */ for(int i=1;inumrows,1,ISSM_MPI_INT,0,1,IssmComm::GetComm()); if (this->numrows)ISSM_MPI_Send(this->values,this->numrows*this->numcols,ISSM_MPI_DOUBLE,0,1,IssmComm::GetComm()); } if (my_rank==0){ ISSM_MPI_Recv(&node_numrows,1,ISSM_MPI_INT,i,1,IssmComm::GetComm(),&status); if (node_numrows)ISSM_MPI_Recv(total_values+count,node_numrows*this->numcols,ISSM_MPI_DOUBLE,i,1,IssmComm::GetComm(),&status); count+=node_numrows*this->numcols; } } /*Now, node 0 has total_values, of size total_numrows*this->numcols. Update the fields in the patch, to reflect this new * reality. For other cpus, no point in keeping their data anymore: */ if(my_rank==0){ this->numrows=total_numrows; xDelete(this->values); this->values=total_values; } else{ this->numrows=0; xDelete(this->values); } }/*}}}*/