Index: /issm/trunk-jpl/src/c/classes/objects/Bucket.h
===================================================================
--- /issm/trunk-jpl/src/c/classes/objects/Bucket.h	(revision 14874)
+++ /issm/trunk-jpl/src/c/classes/objects/Bucket.h	(revision 14875)
@@ -151,23 +151,4 @@
 		};
 		/*}}}*/
-		void SetLocalMatrixValues(double* local_matrix,int lower_row,int global_N){ /*{{{*/
-
-			int i,j;
-			for(i=0;i<m;i++){
-				for(j=0;j<n;j++){
-					*(local_matrix+global_N*(idxm[i]-lower_row)+idxn[j])=*(values+n*i+j);
-				}
-			}
-
-		};
-		/*}}}*/
-		void SetLocalVectorValues(double* local_vector,int lower_row){ /*{{{*/
-
-			int i;
-			for(i=0;i<m;i++){
-				local_vector[idxm[i]-lower_row]=values[i];
-			}
-		};
-		/*}}}*/
 		int BucketType(void){ /*{{{*/
 
@@ -205,8 +186,8 @@
 
 			/*increment buffer for next Bucket who will marshall his data: */
-			row_indices_forcpu+=m*n;
-			col_indices_forcpu+=m*n;
-			values_forcpu+=m*n;
-			modes_forcpu+=m*n;
+			row_indices_forcpu+=(m*n);
+			col_indices_forcpu+=(m*n);
+			values_forcpu+=(m*n);
+			modes_forcpu+=(m*n);
 
 			/*output modified buffers: */
@@ -221,5 +202,4 @@
 			/*intermediary: */
 			int         i;
-			int         j;
 
 			/*buffers: */
@@ -262,64 +242,4 @@
 		};
 		/*}}}*/
-#ifdef _HAVE_MPI_
-			void Isend(int receiver_rank,MPI_Request* requests,int* pcount,MPI_Comm comm){ /*{{{*/
-			int count=0;
-			int int_mode;
-
-			/*Recover pointer: */
-			count=*pcount;
-
-			/*Send all the information required: */
-			MPI_Isend(&type,1,MPI_INT,receiver_rank,2,comm,requests+count); count++;
-			MPI_Isend(&m,1,MPI_INT,receiver_rank,3,comm,requests+count); count++;
-			if(m){ MPI_Isend(idxm,m,MPI_INT,receiver_rank,4,comm,requests+count); count++; }
-			if(type==MATRIX_BUCKET){
-				MPI_Isend(&n,1,MPI_INT,receiver_rank,5,comm,requests+count); count++;
-				if(n){ MPI_Isend(idxn,n,MPI_INT,receiver_rank,6,comm,requests+count); count++; }
-				if(m*n){ MPI_Isend(values,m*n,MPI_DOUBLE,receiver_rank,7,comm,requests+count); count++; }
-			}
-			else{
-				if(m){ MPI_Isend(values,m,MPI_DOUBLE,receiver_rank,7,comm,requests+count); count++; }
-			}
-			int_mode=(int)mode;
-			MPI_Isend(&int_mode,1,MPI_INT,receiver_rank,8,comm,requests+count); count++;
-
-			/*Allocate pointers: */
-			*pcount=count;
-
-		} /*}}}*/
-		void Recv(int sender_rank, MPI_Comm comm){ /*{{{*/
-
-			MPI_Status status;
-			int int_mode;
-
-			MPI_Recv(&type,1, MPI_INT,sender_rank,2, comm, &status);
-			MPI_Recv(&m,1, MPI_INT,sender_rank,3, comm, &status);
-			if(m){
-				idxm=new int[m];
-				MPI_Recv(idxm,m, MPI_INT,sender_rank,4, comm, &status);
-			}
-			if(type==MATRIX_BUCKET){
-				MPI_Recv(&n,1, MPI_INT,sender_rank,5, comm, &status);
-				if(n){
-					idxn=new int[n];
-					MPI_Recv(idxn,n, MPI_INT,sender_rank,6, comm, &status);
-				}
-				if(m*n){
-					values=new doubletype[m*n];
-					MPI_Recv(values,m*n, MPI_DOUBLE,sender_rank,7, comm, &status);
-				}
-			}
-			else{
-				if(m){
-					values=new doubletype[m];
-					MPI_Recv(values,m, MPI_DOUBLE,sender_rank,7, comm, &status);
-				}
-			} 
-			MPI_Recv(&int_mode,1, MPI_INT,sender_rank,8, comm, &status);
-			mode=(InsMode)int_mode;
-
-		} /*}}}*/
-#endif
 };
 
Index: /issm/trunk-jpl/src/c/toolkits/issm/IssmDenseMat.h
===================================================================
--- /issm/trunk-jpl/src/c/toolkits/issm/IssmDenseMat.h	(revision 14874)
+++ /issm/trunk-jpl/src/c/toolkits/issm/IssmDenseMat.h	(revision 14875)
@@ -151,4 +151,15 @@
 					return norm;
 					break; 
+				case NORM_FROBENIUS:
+					norm=0;
+					for(i=0;i<this->M;i++){
+						for(j=0;j<this->N;j++){
+							norm+=pow(this->matrix[N*i+j],2);
+						}
+					}
+					return sqrt(norm);
+					break; 
+
+
 				default:
 					_error_("unknown norm !");
Index: /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiDenseMat.h
===================================================================
--- /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiDenseMat.h	(revision 14874)
+++ /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiDenseMat.h	(revision 14875)
@@ -162,122 +162,4 @@
 		}
 		/*}}}*/
-		/*FUNCTION Assemble2{{{*/
-		void Assemble2(){
-
-			int           i;
-			int           j;
-			int           k;
-			int           my_rank;
-			int           num_procs;
-			int          *RowRank             = NULL;
-
-			DataSet     **bucketspercpu       = NULL;
-			int          *bucketspercpu_sizes = NULL;
-			MPI_Request  *requests            = NULL;
-			MPI_Status   *statuses            = NULL;
-			MPI_Status    status;
-			int           num_requests        = 0;
-			DataSet      *mybuckets           = NULL;
-			int           lower_row;
-			int           upper_row;
-			int           count               = 0;
-
-			int           size;
-
-			/*some communicator info: */
-			num_procs=IssmComm::GetSize();
-			my_rank=IssmComm::GetRank();
-			MPI_Comm comm=IssmComm::GetComm();
-
-			/*First, make a vector of size M, which for each row between 0 and M-1, tells which cpu this row belongs to: */
-			RowRank=DetermineRowRankFromLocalSize(M,m,comm);
-
-			/*Now, sort out our dataset of buckets according to cpu ownership of rows: */
-			bucketspercpu=xNew<DataSet*>(num_procs);
-			bucketspercpu_sizes=xNew<int>(num_procs);
-
-			for(i=0;i<num_procs;i++){
-				DataSet* bucketsofcpu_i=new DataSet();
-				for (j=0;j<buckets->Size();j++){
-					Bucket<doubletype>* bucket=(Bucket<doubletype>*)buckets->GetObjectByOffset(j);
-					bucket->SpawnBucketsPerCpu(bucketsofcpu_i,i,RowRank);
-				}
-				bucketspercpu[i]=bucketsofcpu_i;
-				bucketspercpu_sizes[i]=bucketsofcpu_i->Size();
-			}
-
-			/*Recap, each cpu has num_procs datasets of buckets. For a certain cpu j, for a given dataset i, the buckets this 
-			 * dataset owns correspond to rows that are owned by cpu i, not j!:*/
-
-			/*First, figure out how many requests are going to be sent by MPI_Isend. Do this a little bit better? */
-			for(i=0;i<num_procs;i++){
-				if(i!=my_rank){
-					num_requests+=bucketspercpu[i]->Size()*MATRIXBUCKETSIZEOFREQUESTS; //this is to take into account all the MPI_ISend calls in each bucket.
-					num_requests++; //this is to take into account on MPI_ISend in BucketsSend.
-				}
-			}
-
-			/*Initialize array to track requests and statuses: */
-			requests=new MPI_Request[num_requests];
-			statuses=new MPI_Status[num_requests];
-
-			/*Now, go through all our bucketspercpu datasets, and send them to the corresponding cpus. Do not send our own buckets though!: */
-			count=0; //count requests
-			for(i=0;i<num_procs;i++){
-				if(my_rank==i){
-					for(j=0;j<num_procs;j++){
-						if(j!=i){//only send the buckets that this cpu does not own.
-
-							/*Go through the buckets belonging to cpu j, and send them accordingly. */
-							DataSet* buckets=bucketspercpu[j];
-							MPI_Isend(bucketspercpu_sizes+j,1,MPI_INT,j,1,comm,requests+count); count++; //we use bucketspercpu_sizes because we need a permanent buffer for an asynchronous send
-							for(k=0;k<buckets->Size();k++){
-								Bucket<doubletype>* bucket=(Bucket<doubletype>*)buckets->GetObjectByOffset(k);
-								bucket->Isend(j,requests,&count,comm);
-							}
-						}
-					}
-				}
-				else{
-
-					/*Receive buckets from cpu i, and add them to my own my_rank bucket list: */
-					/*First, are we receiving anything from sender_rank? :*/
-					MPI_Recv(&size,1, MPI_INT,i,1, comm, &status);
-
-					/*If so, started receiving extra buckets and plug them into out buckets: */
-					if(size){
-						for(j=0;j<size;j++){
-							Bucket<doubletype>* bucket=new Bucket<doubletype>();
-							bucket->Recv(i,comm);
-							bucketspercpu[my_rank]->AddObject(bucket);
-						}
-					}
-				}
-			}
-			/*Wait for all requests to complete: */
-			MPI_Waitall(num_requests,requests,statuses);
-
-			/*Every cpu now has a dataset of buckets  in bucketspercpu[my_rank], which holds all the values 
-			 *local to this cpu that should be added to the global matrix. Just do that: */
-			GetOwnershipBoundariesFromRange(&lower_row,&upper_row,m,comm);
-			mybuckets=bucketspercpu[my_rank];
-
-			for(i=0;i<mybuckets->Size();i++){
-				Bucket<doubletype>* bucket=(Bucket<doubletype>*)mybuckets->GetObjectByOffset(i);
-				bucket->SetLocalMatrixValues(this->matrix,lower_row,N);
-			}
-
-			/*Free ressources:{{{*/
-			xDelete<int>(RowRank);
-			for(i=0;i<num_procs;i++){
-				DataSet* buckets=bucketspercpu[i];
-				delete buckets;
-			}
-			xDelete<DataSet*>(bucketspercpu);
-			xDelete<int>(bucketspercpu_sizes);
-			xDelete<MPI_Request>(requests);
-			/*}}}*/
-		}
-		/*}}}*/
 		/*FUNCTION Assemble{{{*/
 		void Assemble(){
@@ -447,5 +329,5 @@
 				case NORM_INF:
 					local_norm=0;
-					for(i=0;i<this->M;i++){
+					for(i=0;i<this->m;i++){
 						absolute=0;
 						for(j=0;j<this->N;j++){
@@ -458,4 +340,17 @@
 					return norm;
 					break; 
+				case NORM_FROBENIUS:
+					local_norm=0;
+					for(i=0;i<this->m;i++){
+						for(j=0;j<this->N;j++){
+							local_norm+=pow(this->matrix[N*i+j],2);
+						}
+					}
+					MPI_Reduce(&local_norm, &norm, 1, MPI_DOUBLE, MPI_SUM, 0, IssmComm::GetComm());
+					MPI_Bcast(&norm,1,MPI_DOUBLE,0,IssmComm::GetComm());
+					return sqrt(norm);
+					break; 
+
+
 				default:
 					_error_("unknown norm !");
Index: /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiVec.h
===================================================================
--- /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiVec.h	(revision 14874)
+++ /issm/trunk-jpl/src/c/toolkits/issm/IssmMpiVec.h	(revision 14875)
@@ -295,122 +295,4 @@
 		}
 		/*}}}*/
-		/*FUNCTION Assemble2{{{*/
-		void Assemble2(){
-
-			int           i;
-			int           j;
-			int           k;
-			int           my_rank;
-			int           num_procs;
-			int          *RowRank             = NULL;
-
-			DataSet     **bucketspercpu       = NULL;
-			int          *bucketspercpu_sizes = NULL;
-			MPI_Request  *requests            = NULL;
-			MPI_Status   *statuses            = NULL;
-			MPI_Status    status;
-			int           num_requests        = 0;
-			DataSet      *mybuckets           = NULL;
-			int           lower_row;
-			int           upper_row;
-			int           count               = 0;
-
-			int           size;
-
-			/*some communicator info: */
-			num_procs=IssmComm::GetSize();
-			my_rank=IssmComm::GetRank();
-			MPI_Comm comm=IssmComm::GetComm();
-
-			/*First, make a vector of size M, which for each row between 0 and M-1, tells which cpu this row belongs to: */
-			RowRank=DetermineRowRankFromLocalSize(M,m,comm);
-
-			/*Now, sort out our dataset of buckets according to cpu ownership of rows: */
-			bucketspercpu=xNew<DataSet*>(num_procs);
-			bucketspercpu_sizes=xNew<int>(num_procs);
-
-			for(i=0;i<num_procs;i++){
-				DataSet* bucketsofcpu_i=new DataSet();
-				for (j=0;j<buckets->Size();j++){
-					Bucket<doubletype>* bucket=(Bucket<doubletype>*)buckets->GetObjectByOffset(j);
-					bucket->SpawnBucketsPerCpu(bucketsofcpu_i,i,RowRank);
-				}
-				bucketspercpu[i]=bucketsofcpu_i;
-				bucketspercpu_sizes[i]=bucketsofcpu_i->Size();
-			}
-
-			/*Recap, each cpu has num_procs datasets of buckets. For a certain cpu j, for a given dataset i, the buckets this 
-			 * dataset owns correspond to rows that are owned by cpu i, not j!:*/
-
-			/*First, figure out how many requests are going to be sent by MPI_Isend. Do this a little bit better? */
-			for(i=0;i<num_procs;i++){
-				if(i!=my_rank){
-					num_requests+=bucketspercpu[i]->Size()*VECTORBUCKETSIZEOFREQUESTS; //this is to take into account all the MPI_ISend calls in each bucket.
-					num_requests++; //this is to take into account on MPI_ISend in BucketsSend.
-				}
-			}
-
-			/*Initialize array to track requests and statuses: */
-			requests=new MPI_Request[num_requests];
-			statuses=new MPI_Status[num_requests];
-
-			/*Now, go through all our bucketspercpu datasets, and send them to the corresponding cpus. Do not send our own buckets though!: */
-			count=0; //count requests
-			for(i=0;i<num_procs;i++){
-				if(my_rank==i){
-					for(j=0;j<num_procs;j++){
-						if(j!=i){//only send the buckets that this cpu does not own.
-
-							/*Go through the buckets belonging to cpu j, and send them accordingly. */
-							DataSet* buckets=bucketspercpu[j];
-							MPI_Isend(bucketspercpu_sizes+j,1,MPI_INT,j,1,comm,requests+count); count++; //we use bucketspercpu_sizes because we need a permanent buffer for an asynchronous send
-							for(k=0;k<buckets->Size();k++){
-								Bucket<doubletype>* bucket=(Bucket<doubletype>*)buckets->GetObjectByOffset(k);
-								bucket->Isend(j,requests,&count,comm);
-							}
-						}
-					}
-				}
-				else{
-
-					/*Receive buckets from cpu i, and add them to my own my_rank bucket list: */
-					/*First, are we receiving anything from sender_rank? :*/
-					MPI_Recv(&size,1, MPI_INT,i,1, comm, &status);
-
-					/*If so, started receiving extra buckets and plug them into out buckets: */
-					if(size){
-						for(j=0;j<size;j++){
-							Bucket<doubletype>* bucket=new Bucket<doubletype>();
-							bucket->Recv(i,comm);
-							bucketspercpu[my_rank]->AddObject(bucket);
-						}
-					}
-				}
-			}
-			/*Wait for all requests to complete: */
-			MPI_Waitall(num_requests,requests,statuses);
-
-			/*Every cpu now has a dataset of buckets  in bucketspercpu[my_rank], which holds all the values 
-			 *local to this cpu that should be added to the global matrix. Just do that: */
-			GetOwnershipBoundariesFromRange(&lower_row,&upper_row,m,comm);
-			mybuckets=bucketspercpu[my_rank];
-
-			for(i=0;i<mybuckets->Size();i++){
-				Bucket<doubletype>* bucket=(Bucket<doubletype>*)mybuckets->GetObjectByOffset(i);
-				bucket->SetLocalVectorValues(this->vector,lower_row);
-			}
-
-			/*Free ressources:{{{*/
-			xDelete<int>(RowRank);
-			for(i=0;i<num_procs;i++){
-				DataSet* buckets=bucketspercpu[i];
-				delete buckets;
-			}
-			xDelete<DataSet*>(bucketspercpu);
-			xDelete<int>(bucketspercpu_sizes);
-			xDelete<MPI_Request>(requests);
-			/*}}}*/
-		}
-		/*}}}*/
 		/*FUNCTION SetValues{{{*/
 		void SetValues(int ssize, int* list, doubletype* values, InsMode mode){
@@ -571,4 +453,5 @@
 					local_norm=0; for(i=0;i<this->m;i++)local_norm=max(local_norm,this->vector[i]);
 					MPI_Reduce(&local_norm, &norm, 1, MPI_DOUBLE, MPI_MAX, 0, IssmComm::GetComm());
+					MPI_Bcast(&norm,1,MPI_DOUBLE,0,IssmComm::GetComm());
 					return norm;
 					break;
@@ -577,4 +460,5 @@
 					for(i=0;i<this->m;i++)local_norm+=pow(this->vector[i],2);
 					MPI_Reduce(&local_norm, &norm, 1, MPI_DOUBLE, MPI_SUM, 0, IssmComm::GetComm());
+					MPI_Bcast(&norm,1,MPI_DOUBLE,0,IssmComm::GetComm());
 					return sqrt(norm);
 					break;
Index: /issm/trunk-jpl/src/c/toolkits/toolkitsenums.h
===================================================================
--- /issm/trunk-jpl/src/c/toolkits/toolkitsenums.h	(revision 14874)
+++ /issm/trunk-jpl/src/c/toolkits/toolkitsenums.h	(revision 14875)
@@ -13,5 +13,5 @@
 
 typedef enum {INS_VAL, ADD_VAL} InsMode;
-typedef enum {NORM_INF,NORM_TWO} NormMode;
+typedef enum {NORM_INF,NORM_TWO,NORM_FROBENIUS} NormMode;
 typedef enum {DENSE_SEQUENTIAL,SPARSE_SEQUENTIAL} MatrixType;
 
