В функции update каждая задача должна обменять конечные точки
(граничные значения) с ее левым и правым соседями до обновления ее амплитуд вдоль волны.
Каждая задача указывает на npoints точек на волне. Атрибуты для
этих точек запоминаются от values[1] до values[npoints],
где values есть действительный массив двойной точности.
Величины values[0] и values[npoints+1] будут содержать
граничные значения из соседних задач.
Итак, задача, обменивающая конечные точки с ее левым соседом отправляет ее значение
values[1] крайней левой точки и получает некое граничное значение в
values[0]. Первое указывает индекс первой точки,
управляемой этой задачей в полной (нераспределенной) волне. Задача, которая владеет
точкой 1 на волне не имеет левого соседа и не будет призводить
этот обмен.
if (first != 1)
{
MPI_Isend(&values[1], 1, MPI_DOUBLE, left, E_RtoL, MPI_COMM_WORLD,
&Prequest[0]);
MPI_Irecv(&values[0], 1, MPI_DOUBLE, left, E_LtoR, MPI_COMM_WORLD,
&Prequest[1]);
}
Теги сообщения E_RtoL и E_LtoR предлагают
направление, в котором сообщение передается (справа-налево или слева-направо).
Коммуникатор MPI_COMM_WORLD. Так как этот коммуникатор является неблокирующим, то
возвращается запрос Prequest[n], который будет использован для проверки статуса коммуникации.
Обмен с левым соседом сопровождается обменом с правым соседом
Задача, которая владеет абсолютно последней точкой (индекс
tpoints) на волне не имеет правого соседа и не будет делать
этот обмен.
if (first + npoints -1 != tpoints)
{
MPI_Isend(&values[npoints], 1, MPI_DOUBLE, right, E_LtoR,
MPI_COMM_WORLD, &Prequest[2]);
MPI_Irecv(&values[npoints+1], 1, MPI_DOUBLE, right, E_RtoL,
MPI_COMM_WORLD, &Prequest[3]);
}
Связи затем блокируют, поскольку последующие вычисления требуют конечных точек, которые передаются:
MPI_Waitall(4, Prequest, Pstatus);