OSDN Git Service

Initial Commit
[qcad/qcad.git] / calcunits / QCalcUnit.cpp
1 //---------------------------------------------------------------------------
2 //  Base Class of CalcUnit
3 //---------------------------------------------------------------------------
4 #include "QCalcUnit.h"
5 //---------------------------------------------------------------------------
6 #ifdef __USE__MPI
7 int QCalcUnit::gMdata;
8 int QCalcUnit::gNqubits;
9 int QCalcUnit::gProcMask;
10 int QCalcUnit::gProcBit;
11 int QCalcUnit::gMyID;
12 int QCalcUnit::gNumprocs;
13 #endif
14
15 //---------------------------------------------------------------------------
16 /**
17  *
18 **/
19 unsigned int
20 QCalcUnit::insert0(unsigned int i0, unsigned int BitNum) {
21     unsigned int msk = (1<<BitNum) -1;
22     return ((~msk & i0) << 1) | (msk & i0);
23 }
24 //---------------------------------------------------------------------------
25 /**
26  *
27 **/
28 unsigned int
29 QCalcUnit::insert1(unsigned int i0, unsigned int BitNum) {
30     unsigned int msk = (1<<BitNum) -1;
31     return ((~msk & i0) << 1) | (1 << BitNum) | (msk & i0);
32 }
33
34 //---------------------------------------------------------------------------
35 // for MPI calculation
36 //---------------------------------------------------------------------------
37 #ifdef __USE__MPI
38 //---------------------------------------------------------------------------
39 /**
40  * N - number of qbits
41  */
42 int
43 QCalcUnit::initmpi(int N, int myid, int numprocs) {
44     // numproc must be a power of 2.
45     int p = -1;
46     int n = numprocs;
47     while (n){
48         n = n >> 1;
49         p++;
50     }
51     gProcBit = p;
52     gNqubits = N;
53     gMdata          = 1 << (N - gProcBit);
54     gNumprocs       = numprocs;
55     gProcMask       = (gNumprocs - 1) << (N-gProcBit);
56     gMyID           = myid;
57     return gMdata;
58 }
59 //---------------------------------------------------------------------------
60 inline int
61 QCalcUnit::getOriginalID(int id){
62     return  gMyID << ((gNqubits-gProcBit))|id;
63 }
64 //----------------------------------------------------------------------------
65 inline int
66 QCalcUnit::getProcFromID(int id){
67     return (id >> (gNqubits - gProcBit));
68 }
69 //----------------------------------------------------------------------------
70 void
71 QCalcUnit::initdata(double R[], double I[]) {
72     for (int i = 0; i < gMdata; i++) {
73         R[i] = 0;
74         I[i] = 0;
75     }
76     if (0 == gMyID) {
77         R[0] = 1;
78     }
79 }
80 //----------------------------------------------------------------------------
81 /**
82  * Show Data
83  */
84 void
85 QCalcUnit::showdata(double R[], double I[]) {
86     for (int i = 0; i < gMdata; i++) {
87         printf("proc=%3d: idx = %03d:%f,%f\n",
88                gMyID, getOriginalID(i), R[i], I[i]);
89     }
90 }
91 //----------------------------------------------------------------------------
92 /**
93  *  Common procedure to prepare data
94  *  Return Value:
95  *  true:   need to store data
96  *  false:  don't need to store
97  */
98 bool
99 QCalcUnit::setup(const double R[], const double I[],
100                  const unsigned int &ix0, const unsigned int &ix1,
101                  double &r0, double &i0,
102                  double &r1, double &i1) {
103     MPI_Status  status;
104     MPI_Request req;
105     const int   TAG = 0;
106
107     unsigned int idx0 = ix0 & ((1<<(gNqubits-gProcBit))-1);
108     unsigned int idx1 = ix1 & ((1<<(gNqubits-gProcBit))-1);
109
110     int p0 = getProcFromID(ix0);
111     int p1 = getProcFromID(ix1);
112
113     //----
114     // Communication with MPI
115     //----
116     if (p0 != gMyID && p1 != gMyID) {
117         return false;
118     }
119
120     if (p0 == gMyID && p1 == gMyID) {
121         r0 = R[idx0];
122         r1 = R[idx1];
123         i0 = I[idx0];
124         i1 = I[idx1];
125     }
126
127     if (p0 == gMyID && p1 != gMyID) {
128         r0 = R[idx0];
129         MPI_Isend(&r0, 1, MPI_DOUBLE, p1, TAG,MPI_COMM_WORLD,&req);
130         MPI_Irecv(&r1, 1, MPI_DOUBLE, p1, TAG, MPI_COMM_WORLD, &req);
131         MPI_Wait(&req, &status);
132
133         i0 = I[idx0];
134         MPI_Isend(&i0, 1, MPI_DOUBLE, p1, TAG, MPI_COMM_WORLD, &req);
135         MPI_Irecv(&i1, 1, MPI_DOUBLE, p1, TAG, MPI_COMM_WORLD, &req);
136         MPI_Wait(&req, &status);
137     }
138     if (p0 != gMyID && p1 == gMyID) {
139         r1 = R[idx1];
140         MPI_Isend(&r1, 1, MPI_DOUBLE, p0, TAG, MPI_COMM_WORLD, &req);
141         MPI_Irecv(&r0, 1, MPI_DOUBLE, p0, TAG, MPI_COMM_WORLD, &req);
142         MPI_Wait(&req, &status);
143
144         i1 = I[idx1];
145         MPI_Isend(&i1, 1, MPI_DOUBLE, p0, TAG, MPI_COMM_WORLD, &req);
146         MPI_Irecv(&i0, 1, MPI_DOUBLE, p0, TAG, MPI_COMM_WORLD, &req);
147         MPI_Wait(&req, &status);
148     }
149     return true;
150 }
151 //----------------------------------------------------------------------------
152 /**
153  *  Common procedure to store data
154  */
155 void QCalcUnit::store(double R[], double I[],
156                       const unsigned int &ix0, const unsigned int &ix1,
157                       const double &r0, const double &i0,
158                       const double &r1, const double &i1) {
159     int p0 = getProcFromID(ix0);
160     int p1 = getProcFromID(ix1);
161     unsigned int idx0 = ix0 & ((1<<(gNqubits-gProcBit))-1);
162     unsigned int idx1 = ix1 & ((1<<(gNqubits-gProcBit))-1);
163
164     if (p0 == gMyID) {
165         R[idx0] = r0;
166         I[idx0] = i0;
167     }
168     if (p1 == gMyID) {
169         R[idx1] = r1;
170         I[idx1] = i1;
171     }
172 }
173 //----------------------------------------------------------------------------
174 #endif //__USE__MPI