What you want to achieve is not impossible, but is also not trivial. First, you have to either declare a datatype that represents the whole structure type or one that holds only the forces. To construct the latter, start with three consecutive doubles at the proper displacement:
MPI_Datatype type_force;
int blen = 3;
MPI_Aint displ = offsetof(struct particle, force);
MPI_Type types = MPI_DOUBLE;
MPI_Type_create_struct(1, &blen, &displ, &types, &type_force);
The new datatype must be resized to match the extent of the C structure, so we could directly access multiple array elements:
MPI_Datatype type_force_resized;
MPI_Aint lb, extent;
MPI_Type_get_extent(type_force, &lb, &extent);
extent = sizeof(struct particle);
MPI_Type_create_resized(type_force, lb, extent, &type_force_resized);
MPI_Type_commit(&type_force_resized);
The global (all-)reduction now almost boils down to:
struct particle *particles = calloc(n, sizeof(struct particle));
MPI_Allreduce(mypart, particles, n, type_force_resized,
MPI_SUM, MPI_COMM_WORLD);
Since MPI_(All)Reduce does not allow different MPI datatypes to be used for the source and receive buffers, one has to use an array of struct particle instead of simply double[n][3]. The result will be placed in the forces[] field of each array element.
Now, the problem is that MPI_SUM does not operate on derived datatypes. The solution is to declare your own reduction operation:
void force_sum(struct particle *in, struct particle *inout,
int *len, MPI_Datatype *dptr)
{
for (int i = 0; i < *len; i++)
{
inout[i].force[0] += in[i].force[0];
inout[i].force[1] += in[i].force[1];
inout[i].force[2] += in[i].force[2];
}
}
MPI_Op force_sum_op;
MPI_Op_create(force_sum, 1, &force_sum_op);
With all the preparations outlined above, the reduction becomes:
MPI_Allreduce(mypart, particles, n, type_force_resized,
force_sum_op, MPI_COMM_WORLD);
A much simpler variant would be if you first gather all forces in a double forces[n][3] array. Then the whole reduction operation boils down to:
double forces[n][3]; // Local forces
double total_forces[n][3]; // Total forces
... transfer mypart[i].force into forces[i] ...
MPI_Allreduce(forces, total_forces, 3*n, MPI_DOUBLE,
MPI_SUM, MPI_COMM_WORLD);
// Done
But this method takes additional memory and needs memory copy operations.