aboutsummaryrefslogtreecommitdiff
path: root/CarpetDev/CarpetIOF5/src/distribute.hh
blob: 96eaf66333ddf81bc8a8468462b8f4111c469506 (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
#ifndef DISTRIBUTE_HH
#define DISTRIBUTE_HH

#include <cctk.h>

#include <defs.hh>
#include <vect.hh>

#include <list>

#include <mpi.h>



namespace CarpetIOF5 {
  
  using namespace std;
  
  
  
  // Fragment descriptor
  struct fragdesc_t {
    // only integer entries
    int varindex;
    static int const mglevel = 0;
    int reflevel, map, src_component, timelevel;
    ivect imin, imax;           // upper bound is inclusive
    
    // destination
    int component, process;
    int tag;
    
    // meta-messages
    enum state_t { state_normal, state_sent_all, state_all_sent_all };
    int state;
    
    fragdesc_t(): state(state_normal) {}
    
    int num_ints() const { return sizeof(fragdesc_t) / sizeof(int); }
    int npoints() const;
    int vartypesize() const;
    MPI_Datatype datatype() const;
  };
  
  
  
  // Scatter (distribute) Cactus variables
  class scatter_t {
    
    cGH const *const cctkGH;
    
    static int const max_concurrent_sends = 100;
    enum tags_t {
      tag_desc,
      tag_data_min,
      tag_data_max = tag_data_min + max_concurrent_sends
    };
    
    class busy_tags_t {
      vector<bool> tags;
    public:
      busy_tags_t();
      ~busy_tags_t();
      int allocate_tag();
      void free_tag(int tag);
    };
    vector<busy_tags_t> busy_tags;
    
    struct transmission_t {
      fragdesc_t fragdesc;
      vector<char> data;
      MPI_Request request;
      transmission_t(): request(MPI_REQUEST_NULL) {}
      ~transmission_t() { assert(request==MPI_REQUEST_NULL); }
    };
    
    // Desired number of public receives to keep posted at all times
    static int const num_public_recvs = 10;
    list<transmission_t*> public_recvs, recvs, sends;
    int num_received, num_sent;
    ptrdiff_t bytes_allocated;
    
    bool did_send_all;
    int did_receive_sent_all;
    bool did_receive_all_sent_all;
    fragdesc_t to_parent, to_children;
    
  public:
    scatter_t(cGH const *cctkGH_);
    ~scatter_t();
    
    void send(fragdesc_t const& fd, void const *data);
    
  private:
    void post_public_recvs();
    void do_some_work(bool do_wait = false);
    
    void maybe_send_did_send();
    void send_all_did_send();
    void set_did_send_all();
    void set_did_receive_sent_all();
    void set_did_receive_all_sent_all();
    void handle_state_transition(fragdesc_t const& fd);
    
    list<transmission_t*> split_for_sending(fragdesc_t const& fd,
                                            void const *data);
    void write_data(transmission_t *const tm);
  };
  
} // namespace CarpetIOF5

#endif  // #ifndef DISTRIBUTE_HH