aboutsummaryrefslogtreecommitdiff
path: root/src/PostReceiveGA.c
blob: 3a7864b82e739c92a83e14ac4c0013066674122d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 /*@@
   @file      PostReceiveGA.c
   @date      Wed Feb 2 11:28:06 1997
   @author    Gabrielle Allen
   @desc 
   Routines which post all the IRecv commands for a GA. These
   allow the asyncronous model proposed in, for example,
   @seeroutine SyncGA to go!
   @enddesc 
   @version $Header$
 @@*/

#include <stdio.h>

#include "pugh.h"

static char *rcsid = "$Header$";

CCTK_FILEVERSION(CactusPUGH_PUGH_PostReceiveGA_c)

/*#define DEBUG_PUGH*/


 /*@@
   @routine   PostReceiveGA
   @date      Thu Apr  3 12:10:46 1997
   @author    Paul Walker
   @desc 
   This routine posts a recieve (MPI_Irecv) of the buffer
   we want to get the send from another processor, which
   will be sent by @seeroutine pGA_PostSend and then
   finalized by @seeroutoine pGA_FinishRecv. 
   <p>
   Aside from a silly calculation to get a unique tag
   based on neigbors and processors, this is a very
   straightforward routine.
   @enddesc 
   @history
   @hdate Nov 4 1998 @hauthor Gabrielle Allen
   @hdesc Allow for forced synchronization of all GAs with storage
   @endhistory
 @@*/

void PostReceiveGA(pGH *GH, pGA *GA, int dir)
{
#ifdef CCTK_MPI
  int rtag;
  MPI_Datatype mpi_type;
  MPI_Datatype *recv_dt;

  if (!(GA->storage)) 
  {
    CCTK_VWarn(2, __LINE__, __FILE__, CCTK_THORNSTRING,
               "Trying to synchronize variable '%s' with no storage", GA->name);
    return;
  }

  /* Return if communication not required and no forced synchronisation */
  if (!(GH->forceSync || GA->docomm[dir])) 
  {
    return;
  }

  if (GA->connectivity->neighbours[GH->myproc][dir] < 0) 
  {
    return;
  }

  switch (GA->vtype) 
  {
    case CCTK_VARIABLE_CHAR:
      mpi_type = PUGH_MPI_CHAR;
      recv_dt = GH->recv_char_dt [GA->stagger];
      break;

    case CCTK_VARIABLE_INT:
      mpi_type = PUGH_MPI_INT;
      recv_dt = GH->recv_int_dt [GA->stagger];
      break;

    case CCTK_VARIABLE_REAL:
      mpi_type = PUGH_MPI_REAL;
      recv_dt = GH->recv_real_dt [GA->stagger];
      break;

    case CCTK_VARIABLE_COMPLEX:
      mpi_type = GH->PUGH_mpi_complex;
      recv_dt = GH->recv_complex_dt [GA->stagger];
      break;

    default:
      CCTK_WARN (1, "Unknown variable type in PostReceiveGA");
      return;
  }

  rtag = 1000 + dir + 2 * (GH->myproc + GH->nprocs * GA->id);
  /* mod the tag to force MPI compliance */
  rtag = rtag % 32768;
#ifdef DEBUG_PUGH
  printf ("RECV GA %s Side %d Proc %d rtag %d size %d from proc %d\n",
          GA->name,
          dir,
          GH->myproc,
          rtag,
          GA->buffer_sz[dir],
          GA->connectivity->neighbours[GH->myproc][dir]);
#endif
  if (GH->commmodel == PUGH_ALLOCATEDBUFFERS)
  {
    CACTUS_MPI_ERROR (MPI_Irecv (GA->recv_buffer [dir],
                      GA->buffer_sz [dir], mpi_type,
                      GA->connectivity->neighbours [GH->myproc][dir], rtag,
                      GH->PUGH_COMM_WORLD, &(GA->rreq [dir])));
  }
  if (GH->commmodel == PUGH_DERIVEDTYPES)
  {
    CACTUS_MPI_ERROR (MPI_Irecv (GA->data,
                      1, recv_dt [dir],
                      GA->connectivity->neighbours [GH->myproc][dir], rtag,
                      GH->PUGH_COMM_WORLD, &(GA->rreq [dir])));
  }
#endif
}