Index: /issm/trunk-jpl/src/c/classes/FemModel.cpp
===================================================================
--- /issm/trunk-jpl/src/c/classes/FemModel.cpp	(revision 27373)
+++ /issm/trunk-jpl/src/c/classes/FemModel.cpp	(revision 27374)
@@ -1445,9 +1445,15 @@
 
 	/*Now send and receive vector for vertices on partition edge*/
-	#ifdef _HAVE_AD_
-	IssmDouble* buffer = xNew<IssmDouble>(this->vertices->Size(),"t"); //only one alloc, "t" is required by adolc
-	#else
-	IssmDouble* buffer = xNew<IssmDouble>(this->vertices->Size());
-	#endif
+	IssmDouble       **send_buffers  = xNew<IssmDouble*>(num_procs);
+	ISSM_MPI_Request  *send_requests = xNew<ISSM_MPI_Request>(num_procs);
+	for (int rank = 0;rank<num_procs;rank++){
+		#ifdef _HAVE_AD_
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size(),"t"); //only one alloc, "t" is required by adolc
+		#else
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size());
+		#endif
+		send_requests[rank] = MPI_REQUEST_NULL;
+	}
+	IssmDouble* recv_buffer = xNew<IssmDouble>(this->vertices->Size());
 	for(int rank=0;rank<num_procs;rank++){
 		if(this->vertices->common_send[rank]){
@@ -1457,7 +1463,7 @@
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(!vertex->clone);
-				buffer[i] = local_vector[vertex->lid];
-			}
-			ISSM_MPI_Send(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm());
+            send_buffers[rank][i] = local_vector[vertex->lid];
+			}
+         ISSM_MPI_Isend(send_buffers[rank],numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&send_requests[rank]);
 		}
 	}
@@ -1465,14 +1471,20 @@
 		if(this->vertices->common_recv[rank]){
 			int  numids = this->vertices->common_recv[rank];
-			ISSM_MPI_Recv(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
+         ISSM_MPI_Recv(recv_buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
 			for(int i=0;i<numids;i++){
 				int   master_lid = this->vertices->common_recv_ids[rank][i];
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(vertex->clone);
-				local_vector[vertex->lid] = buffer[i];
-			}
-		}
-	}
-	xDelete<IssmDouble>(buffer);
+            local_vector[vertex->lid] = recv_buffer[i];
+			}
+		}
+	}
+   xDelete<IssmDouble>(recv_buffer);
+   for(int rank=0;rank<num_procs;rank++){
+      ISSM_MPI_Wait(&send_requests[rank],&status);
+      xDelete<IssmDouble>(send_buffers[rank]);
+   }
+   xDelete<IssmDouble*>(send_buffers);
+   xDelete<ISSM_MPI_Request>(send_requests);
 }/*}}}*/
 void FemModel::SyncLocalVectorWithClonesVerticesAdd(IssmDouble* local_vector){/*{{{*/
@@ -1484,9 +1496,15 @@
 
 	/*Now send and receive vector for vertices on partition edge*/
-	#ifdef _HAVE_AD_
-	IssmDouble* buffer = xNew<IssmDouble>(this->vertices->Size(),"t"); //only one alloc, "t" is required by adolc
-	#else
-	IssmDouble* buffer = xNew<IssmDouble>(this->vertices->Size());
-	#endif
+	IssmDouble       **send_buffers  = xNew<IssmDouble*>(num_procs);
+	ISSM_MPI_Request  *send_requests = xNew<ISSM_MPI_Request>(num_procs);
+	for (int rank = 0;rank<num_procs;rank++){
+		#ifdef _HAVE_AD_
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size(),"t"); //only one alloc, "t" is required by adolc
+		#else
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size());
+		#endif
+		send_requests[rank] = MPI_REQUEST_NULL;
+	}
+	IssmDouble* recv_buffer = xNew<IssmDouble>(this->vertices->Size());
 
 	/*1st: add slaves to master values (reverse of what we usually do)*/
@@ -1498,7 +1516,7 @@
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(vertex->clone);
-				buffer[i] = local_vector[vertex->lid];
-			}
-			ISSM_MPI_Send(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm());
+				send_buffers[rank][i] = local_vector[vertex->lid];
+			}
+			ISSM_MPI_Isend(send_buffers[rank],numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&send_requests[rank]);
 		}
 	}
@@ -1506,13 +1524,16 @@
 		if(this->vertices->common_send[rank]){
 			int  numids = this->vertices->common_send[rank];
-			ISSM_MPI_Recv(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
+			ISSM_MPI_Recv(recv_buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
 			for(int i=0;i<numids;i++){
 				int   master_lid = this->vertices->common_send_ids[rank][i];
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(!vertex->clone);
-				local_vector[vertex->lid] += buffer[i];
-			}
-		}
-	}
+				local_vector[vertex->lid] += recv_buffer[i];
+			}
+		}
+	}
+
+	/*Wait until MPI is done*/
+	for(int rank=0;rank<num_procs;rank++) ISSM_MPI_Wait(&send_requests[rank],&status);
 
 	/*Now sync masters across partitions*/
@@ -1524,7 +1545,7 @@
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(!vertex->clone);
-				buffer[i] = local_vector[vertex->lid];
-			}
-			ISSM_MPI_Send(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm());
+				send_buffers[rank][i] = local_vector[vertex->lid];
+			}
+			ISSM_MPI_Isend(send_buffers[rank],numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&send_requests[rank]);
 		}
 	}
@@ -1532,14 +1553,21 @@
 		if(this->vertices->common_recv[rank]){
 			int  numids = this->vertices->common_recv[rank];
-			ISSM_MPI_Recv(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
+			ISSM_MPI_Recv(recv_buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
+
 			for(int i=0;i<numids;i++){
 				int   master_lid = this->vertices->common_recv_ids[rank][i];
 				Vertex* vertex=xDynamicCast<Vertex*>(this->vertices->GetObjectByOffset(master_lid));
 				_assert_(vertex->clone);
-				local_vector[vertex->lid] = buffer[i];
-			}
-		}
-	}
-	xDelete<IssmDouble>(buffer);
+				local_vector[vertex->lid] = recv_buffer[i];
+			}
+		}
+	}
+	xDelete<IssmDouble>(recv_buffer);
+	for(int rank=0;rank<num_procs;rank++){
+		ISSM_MPI_Wait(&send_requests[rank],&status);
+		xDelete<IssmDouble>(send_buffers[rank]);
+	}
+	xDelete<IssmDouble*>(send_buffers);
+	xDelete<ISSM_MPI_Request>(send_requests);
 }/*}}}*/
 void FemModel::GetLocalVectorWithClonesNodes(IssmDouble** plocal_vector,Vector<IssmDouble> *vector){/*{{{*/
@@ -1567,9 +1595,17 @@
 
 	/*Now send and receive vector for nodes on partition edge*/
-	#ifdef _HAVE_AD_
-	IssmDouble* buffer = xNew<IssmDouble>(this->nodes->Size(),"t"); //only one alloc, "t" is required by adolc
-	#else
-	IssmDouble* buffer = xNew<IssmDouble>(this->nodes->Size());
-	#endif
+	/*Now send and receive vector for vertices on partition edge*/
+	IssmDouble       **send_buffers  = xNew<IssmDouble*>(num_procs);
+	ISSM_MPI_Request  *send_requests = xNew<ISSM_MPI_Request>(num_procs);
+	for (int rank = 0;rank<num_procs;rank++){
+		#ifdef _HAVE_AD_
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size(),"t"); //only one alloc, "t" is required by adolc
+		#else
+		send_buffers[rank] = xNew<IssmDouble>(this->vertices->Size());
+		#endif
+		send_requests[rank] = MPI_REQUEST_NULL;
+	}
+	IssmDouble* recv_buffer = xNew<IssmDouble>(this->vertices->Size());
+
 	for(int rank=0;rank<num_procs;rank++){
 		if(this->nodes->common_send[rank]){
@@ -1579,7 +1615,7 @@
 				Node* vertex=xDynamicCast<Node*>(this->nodes->GetObjectByOffset(master_lid));
 				_assert_(!vertex->clone);
-				buffer[i] = local_vector[vertex->lid];
-			}
-			ISSM_MPI_Send(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm());
+				send_buffers[rank][i] = local_vector[vertex->lid];
+			}
+			ISSM_MPI_Isend(send_buffers[rank],numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&send_requests[rank]);
 		}
 	}
@@ -1587,14 +1623,21 @@
 		if(this->nodes->common_recv[rank]){
 			int  numids = this->nodes->common_recv[rank];
-			ISSM_MPI_Recv(buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
+			ISSM_MPI_Recv(recv_buffer,numids,ISSM_MPI_DOUBLE,rank,0,IssmComm::GetComm(),&status);
 			for(int i=0;i<numids;i++){
 				int   master_lid = this->nodes->common_recv_ids[rank][i];
 				Node* vertex=xDynamicCast<Node*>(this->nodes->GetObjectByOffset(master_lid));
 				_assert_(vertex->clone);
-				local_vector[vertex->lid] = buffer[i];
-			}
-		}
-	}
-	xDelete<IssmDouble>(buffer);
+				local_vector[vertex->lid] = recv_buffer[i];
+			}
+		}
+	}
+
+	xDelete<IssmDouble>(recv_buffer);
+	for(int rank=0;rank<num_procs;rank++){
+		ISSM_MPI_Wait(&send_requests[rank],&status);
+		xDelete<IssmDouble>(send_buffers[rank]);
+	}
+	xDelete<IssmDouble*>(send_buffers);
+	xDelete<ISSM_MPI_Request>(send_requests);
 
 	/*Assign output pointer*/
