void Robot::move() { Pos p = posAfterMove(); if (world_->canMoveTo(p)) pos_ = p; }
bool recruit(int s, int dpxx, int dpxy, int dpxz, int cs, int axis, int turns, int dx, int dy, int dz){ /* By introducing seemingly redundant parameter dpxx, dpxy and dpxz (which is simply the position difference between molecule s and cs), we could be sure that the position difference would always have a change between -1 and 1, thus avoiding the unphysical rotation near the surface due to periodic boundary conditions. note: do not use static variables in this function unless required, because the function is recursive. */ ppos dpx(dpxx, dpxy, dpxz), n_dir; mol[s].status = 2; cluster_series[cluster_size++] = s; // use cluster_series instead of checking molecule status in loops to improve efficiency if (turns){ switch (axis){ case 0: n_dir.set(1, 0, 0); break; case 1: n_dir.set(0, 1, 0); break; case 2: n_dir.set(0, 0, 1); } } else{ n_dir.set(dx, dy, dz); } mol[s].cluster_eff_rad_diff2 = (double)mod2(dpx.crossproduct(n_dir.x, n_dir.y, n_dir.z)) / mod2(n_dir); int i, j, k; int s1; int oOrnt, nOrnt; double E0, Ef, Er; double pf, pr; ppos px_cnt = mol[s].px, px_fwd = posAfterMove(dpxx, dpxy, dpxz, cs, axis, turns, dx, dy, dz), px_rev = posAfterMove(dpxx, dpxy, dpxz, cs, axis, turns ? (4 - turns) : 0, -dx, -dy, -dz), npx; px_fwd.adjust(); px_rev.adjust(); mol[s].px_cnt_backup = px_cnt; mol[s].px_fwd_dest = px_fwd; mol[s].ornt_cnt_backup = oOrnt = mol[s].ornt; mol[s].ornt_fwd_dest = nOrnt = orntRot[mol[s].ornt][axis][turns]; bool accept = true; double judge_value; if (s == 210){ i = 100; } for (i = -1; i <= 1; i++){ for (j = -1; j <= 1; j++){ for (k = -1; k <= 1; k++){ npx = mol[s].px.plus(i, j, k); npx.adjust(); if ((i || j || k) && stage[npx.x][npx.y][npx.z] >= 0){ // propose a link s1 = stage[npx.x][npx.y][npx.z]; if (px_fwd == npx){ // forward move cause overlap switch (mol[s1].status){ case 0: // recruit and accept (temp) if (mol[s].links >= 8){ cout << "Warning: too many links for particle " << s << endl; break; } mol[s].link_with[mol[s].links] = s1; if (px_rev == npx)mol[s].link_with_pRatio[mol[s].links] = 1; // reverse also overlap else{ // reverse not overlap E0 = interactEnergy(s, s1); mol[s].put(px_rev.x, px_rev.y, px_rev.z, orntRot[oOrnt][axis][turns ? (4 - turns) : 0]); Er = interactEnergy(s, s1); mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt); pr = (Er > E0) ? (1 - exp(-(Er - E0) / k_B / T)) : 0; mol[s].link_with_pRatio[mol[s].links] = pr / 1.0; } mol[s].links++; accept = recruit(s1, dpxx + i, dpxy + j, dpxz + k, cs, axis, turns, dx, dy, dz) && accept; // "accept" must be put after "&&" break; case 1: // unrecruit and deny accept = false; break; case 2: ;// do nothing because already recruited } } else{ // forward move do not cause overlap switch (mol[s1].status){ case 0: // try to recruit E0 = interactEnergy(s, s1); mol[s].put(px_fwd.x, px_fwd.y, px_fwd.z, nOrnt); Ef = interactEnergy(s, s1); mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt); pf = (Ef > E0) ? (1 - exp(-(Ef - E0) / k_B / T)) : 0; judge_value = judge(gen); if (judge_value < pf){ // link formed (where pf must be over 0.0) if (mol[s].links >= 8){ cout << "Warning: too many links for particle " << s << endl; break; } mol[s].link_with[mol[s].links] = s1; if (px_rev == npx)mol[s].link_with_pRatio[mol[s].links] = 1; // reverse overlap else{ // reverse not overlap mol[s].put(px_rev.x, px_rev.y, px_rev.z, orntRot[oOrnt][axis][turns ? (4 - turns) : 0]); Er = interactEnergy(s, s1); mol[s].put(px_cnt.x, px_cnt.y, px_cnt.z, oOrnt); pr = (Er > E0) ? (1 - exp(-(Er - E0) / k_B / T)) : 0; mol[s].link_with_pRatio[mol[s].links] = pr / pf; } mol[s].links++; accept = recruit(s1, dpxx + i, dpxy + j, dpxz + k, cs, axis, turns, dx, dy, dz) && accept; // "accept" must be put after "&&" } break; case 1: case 2: ;// do nothing } } //calculate energy } } } } // do not prevent far away collisions return accept; }