00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <cassert>
00013 #include "ParticleLayoutFromGrid.h"
00014
00015 void ParticleLayoutFromGrid::update(ParticleBase< ParticleLayoutFromGrid >& particles) {
00016 unsigned num_procs = Ippl::getNodes();
00017 unsigned my_id = Ippl::myNode();
00018 size_t num_my_particles = particles.getLocalNum();
00019
00020
00021 size_t num_destroyed_particles = particles.getDestroyNum();
00022 particles.performDestroy();
00023 num_my_particles -= num_destroyed_particles;
00024
00025
00026 particles.setLocalNum(num_my_particles);
00027
00028
00029
00030
00031
00032
00033 unsigned num_active_procs = grid_->give_number_of_active_processes();
00034 if (num_active_procs > 1)
00035 num_my_particles = redistribute_particles(particles);
00036
00037
00038 size_t num_total_particles;
00039 reduce(num_my_particles, num_total_particles, OpAddAssign());
00040 particles.setTotalNum(num_total_particles);
00041 }
00042
00043 void ParticleLayoutFromGrid::apply_bconds(ParticlePos_t& R)
00044 {
00045 Inform msg("update");
00046 size_t num_my_particles = R.size();
00047
00048 for (size_t ip = 0; ip < num_my_particles; ++ ip) {
00049 D3vector pos(R[ip](0), R[ip](1), R[ip](2));
00050 if (!geom_domain_->point_in_domain(pos)) {
00051 msg << "Particle " << ip << " moved outside domain." << endl;
00052 }
00053 }
00054 }
00055
00056 size_t ParticleLayoutFromGrid::redistribute_particles(ParticleBase< ParticleLayoutFromGrid >& particles)
00057 {
00058 unsigned num_procs = Ippl::getNodes();
00059 unsigned my_id = Ippl::myNode();
00060 size_t num_my_particles = particles.getLocalNum();
00061
00062
00063
00064 unsigned num_active_procs = grid_->give_number_of_active_processes();
00065
00066
00067 if (my_id >= num_active_procs)
00068 return num_my_particles;
00069
00070 std::vector<D3vector> bb_min;
00071 std::vector<D3vector> bb_max;
00072 for (int p = 0; p < num_active_procs; ++ p) {
00073 double xmin[3], xmax[3];
00074 grid_->localbox(xmin, xmax, p);
00075 bb_min.push_back(D3vector(xmin[0], xmin[1], xmin[2]));
00076 bb_max.push_back(D3vector(xmax[0], xmax[1], xmax[2]));
00077 }
00078
00079
00080
00081
00082 std::vector<Message> messages(num_active_procs);
00083
00084 std::vector<size_t>* put_list = new std::vector<size_t>[num_active_procs];
00085
00086 for (size_t ip = 0; ip < num_my_particles; ++ ip) {
00087 D3vector pos(particles.R[ip][0], particles.R[ip][1], particles.R[ip][2]);
00088
00089 if (!is_local_pos(pos))
00090 {
00091
00092
00093
00094 unsigned target_id = num_active_procs;
00095 for (unsigned p = 0; p < num_active_procs; ++ p) {
00096 if (is_inside_box(bb_min[p], bb_max[p], pos)) {
00097 target_id = p;
00098 break;
00099 }
00100 }
00101 assert(target_id != num_active_procs && target_id != my_id);
00102 put_list[target_id].push_back(ip);
00103
00104
00105 particles.destroy(1, ip);
00106 }
00107 }
00108
00109
00110 int tag = Ippl::Comm->next_tag(P_SPATIAL_TRANSFER_TAG, P_LAYOUT_CYCLE);
00111 for (int p = 0; p < num_active_procs; ++ p) {
00112 if (p != my_id) {
00113
00114 particles.putMessage(messages[p], put_list[p]);
00115 particles.putMessage(messages[p], (size_t) 0, (size_t) 0);
00116
00117
00118 Ippl::Comm->send(&messages[p], p, tag, false);
00119 }
00120 put_list[p].clear();
00121 }
00122
00123
00124 num_my_particles -= particles.getDestroyNum();
00125 particles.performDestroy();
00126
00127
00128 particles.setLocalNum(num_my_particles);
00129
00130
00131 unsigned sendnum = num_active_procs - 1;
00132 while (sendnum-- > 0) {
00133 int node = Communicate::COMM_ANY_NODE;
00134 Message *recmsg = Ippl::Comm->receive_block(node, tag);
00135 size_t recvd;
00136 size_t total_recvd = 0;
00137 while ((recvd = particles.getMessage(*recmsg)) > 0)
00138 total_recvd += recvd;
00139 num_my_particles += total_recvd;
00140 delete recmsg;
00141 }
00142
00143
00144 particles.setLocalNum(num_my_particles);
00145
00146 delete[] put_list;
00147 return num_my_particles;
00148 }