void propagate_nuclear(double dt,Nuclear* mol,Electronic* el,Hamiltonian* ham,Thermostat* therm, int opt){ /** \brief One step of Velocity verlet algorithm coupled to nuclear Thermostat - for NVT calculations !!! IMPORTANT: Presently, this is only a template - the thermostat part is only outlined - need to test this first !!! \param[in] Integration time step \param[in,out] mol Describes the nuclear DOF. Changes during the integration. \param[in] el Describes electronic DOF. Does not change during the integration. \param[in,out] ham Is the Hamiltonian object that works as a functor (takes care of all calculations of given type) -its internal variables are changed during the compuations \param[in] therm The pointer to a Thermostat object, which contains the information about thermal bath state \param[in] opt Option for selecting the way to describe the electron-nuclear interaction: = 0 - Ehrenfest (mean-field, MF), =1 - (fewest switched surface hopping, FSSH) */ int i; // Propagate momenta and positions of all nuclei // mol->P[i] *= exp(-therm->gamma*0.25*dt); // mol->P[i] += therm->ksi() * 0.5*dt; // mol->P[i] *= exp(-therm->gamma*0.25*dt); // exp(iL_q*dt)*exp(iL_p*dt/2) mol->propagate_p(0.5*dt); mol->propagate_q(dt); // Update Hamiltonian ham->set_q(mol->q); ham->compute(); // Update forces and potential energy compute_potential_energy(mol, el, ham, opt); compute_forces(mol, el, ham, opt); // Propagate momenta of all nucleii // operator exp(iL_p*dt/2) mol->propagate_p(0.5*dt); // Propagate momenta and positions of all nuclei // mol->P[i] *= exp(-therm->gamma*0.25*dt); // mol->P[i] += therm->ksi() * 0.5*dt; // mol->P[i] *= exp(-therm->gamma*0.25*dt); }// propagate_nuclear
void propagate_nuclear(double dt,Nuclear* mol,Electronic* el,Hamiltonian* ham,int opt){ /** \brief One step of Velocity verlet algorithm for nuclear DOF \param[in] Integration time step \param[in,out] mol Describes the nuclear DOF. Changes during the integration. \param[in] el Describes electronic DOF. Does not change during the integration. \param[in,out] ham Is the Hamiltonian object that works as a functor (takes care of all calculations of given type) -its internal variables are changed during the compuations \param[in] opt Option for selecting the way to describe the electron-nuclear interaction: = 0 - Ehrenfest (mean-field, MF), =1 - (fewest switched surface hopping, FSSH) */ int i; vector<double> v_(mol->nnucl); // Propagate momenta and positions of all nuclei // exp(iL_q*dt)*exp(iL_p*dt/2) mol->propagate_p(0.5*dt); mol->propagate_q(dt); // Update Hamiltonian ham->set_q(mol->q); for(i=0;i<mol->nnucl;i++){ v_[i] = mol->p[i]/mol->mass[i]; } ham->set_v(v_); ham->compute(); // Update forces and potential energy compute_potential_energy(mol, el, ham, opt); compute_forces(mol, el, ham, opt); // Propagate momenta of all nucleii // operator exp(iL_p*dt/2) mol->propagate_p(0.5*dt); // ham->set_q(mol->q); for(i=0;i<mol->nnucl;i++){ v_[i] = mol->p[i]/mol->mass[i]; } ham->set_v(v_); // ham->compute(); }// propagate_nuclear
void State::init_md(Nuclear& mol, Electronic& el, Hamiltonian& ham, Random& rnd){ //----- Checking type of ensemble and the existence of required variables ------ int is_thermostat, is_barostat, is_system; is_system = (syst!=NULL); is_thermostat = (thermostat!=NULL); is_barostat = (barostat!=NULL); cout<<"is_system = "<<is_system<<endl; cout<<"is_thermostat = "<<is_thermostat<<endl; cout<<"is_barostat = "<<is_barostat<<endl; int Nf_b = 0; if(!is_system){ std::cout<<"Fatal error: No system defined - nothing to simulate\n Exiting now...\n"; exit(1); } if(md->ensemble=="NVT"||md->ensemble=="NPT"){ if(!is_thermostat){ std::cout<<"Error: No Thermostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);} } if(md->ensemble=="NPT"||md->ensemble=="NPH"){ Nf_b = 1; if(!is_barostat){std::cout<<"Error: No Barostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);} } if(md->ensemble=="NPT_FLEX"||md->ensemble=="NPH_FLEX"){ Nf_b = 9; if(!is_barostat){std::cout<<"Error: No Barostat object were set up. Can not run simulations in "<<md->ensemble<<" ensemble\n"; exit(1);} } // if(md->ensemble=="NVE"){is_thermostat = 0; is_barostat = 0; } //---------------- Checking combinations ----------------------------------- if(is_barostat&&is_thermostat){ if(thermostat->thermostat_type!="Nose-Hoover" && md->ensemble=="NPT"){ std::cout<<"Error: Can not use thermostat other than Nose-Hoover for simulations in NPT ensemble\n Exiting now...\n"; exit(1); } } //------ Initialize thermostat and/or barostat if they exist ---------------- if(is_thermostat){ thermostat->set_Nf_t(syst->Nf_t); thermostat->set_Nf_r(syst->Nf_r); if(is_barostat){ thermostat->set_Nf_b(Nf_b); } thermostat->init_nhc(); syst->init_fragment_velocities(thermostat->Temperature, rnd); } if(is_barostat){ barostat->set_Nf_t(syst->Nf_t); barostat->set_Nf_r(syst->Nf_r); barostat->set_Nf_b(Nf_b); if(is_thermostat){ barostat->init(thermostat->Temperature); } } //---------------- Initialize system -------------------- E_kin = 0.0; for(int i=0;i<syst->Number_of_fragments;i++){ RigidBody& top = syst->Fragments[i].Group_RB; E_kin += (top.ekin_tr() + top.ekin_rot()); } syst->zero_forces_and_torques(); //!!!!!!!!!! E_pot = system->energy(); !!!!!!!!!!!!!!!!! syst->extract_atomic_q(mol.q); // syst -> mol E_pot = compute_potential_energy(mol, el, ham, 1); // # 1 - FSSH forces compute_forces(mol, el, ham, 1); syst->set_atomic_f(mol.f); // mol -> syst syst->update_fragment_forces_and_torques(); E_tot = E_pot + E_kin; H0 = E_tot; H_NP = 0.0; if(is_thermostat){ H0 += thermostat->energy(); } if(md->integrator=="Terec"||md->integrator=="qTerec"){ for(int i=0;i<syst->Number_of_fragments;i++){ syst->Fragments[i].Group_RB.initialize_terec(md->terec_exp_size); } } is_md_initialized = 1; if(is_thermostat){ thermostat->show_info(); } if(is_barostat){ barostat->show_info(); } }
void SimpleSkeletonGrower::grow_potential(int no_branch) { //overview: maintain a volume to represent the potential energy at each step, //then find the min_element_index and the min_rotate that require the minimum potential energy if(!_surface.is_loaded() || !_root) { printf("SimpleSkeletonGrower::surface error\n"); return; } //find the dimensions of the volume float v_height = -1.0f; osg::Vec3 origin(0.0f, 0.0f, 0.0f); for(unsigned int i=0; i<_surface._surface_pts.size(); i++) { float cur = (_surface._surface_pts[i] - origin).length2(); if(v_height == -1.0f || cur > v_height) v_height = cur; } if(v_height == -1.0f) { printf("SimpleSkeletonGrower::grow_potential():v_height(-1.0f) error\n"); return; } //v_height = sqrt(v_height) * 1.5f; //old v_height = sqrt(v_height) * 2.0f; //new float v_step = v_height / 100.0f; osg::Vec3 corner(-v_height/2.0f, -v_height/2.0f, 0.0f); SimpleVolumeFloat space(v_height, v_height, v_height, v_step, v_step, v_step); float energy_effect = v_step * 18; //negative charges on initial skeleton //bfs std::queue <BDLSkeletonNode *> Queue; Queue.push(_root); while(!Queue.empty()) { BDLSkeletonNode *front = Queue.front(); Queue.pop(); osg::Vec3 cur = Transformer::toVec3(front) - corner; space.add_potential(cur.x(), cur.y(), cur.z(), -3, energy_effect); for(unsigned int i=0; i<front->_children.size(); i++) Queue.push(front->_children[i]); } //positive charges on volume surface for(unsigned int i=0; i<_surface._surface_pts.size(); i++) { osg::Vec3 cur = _surface._surface_pts[i] - corner; space.add_potential(cur.x(), cur.y(), cur.z(), 1, energy_effect*1.5f); } std::vector <LibraryElement> elements = _library._library_element; for(int i=0; i<no_branch; i++) { //pick a tail first //not by minimum generation, but by farest position from surface point BDLSkeletonNode *tail = pick_branch(true); if(!tail) { printf("SimpleSkeletonGrower::grow():converged at %d-th step.\n", i+1); break; } //compute the node-->id dict std::map <BDLSkeletonNode *, int> dict; int id = 0; //bfs on source std::queue <BDLSkeletonNode *> Queue; Queue.push(_root); while(!Queue.empty()) { BDLSkeletonNode *front = Queue.front(); Queue.pop(); dict[front] = id; for(unsigned int j=0; j<front->_children.size(); j++) Queue.push(front->_children[j]); id++; } int tail_id = dict[tail]; //####trial starts#### int min_element_index = -1; int min_rotate = -1; float min_energy = -1.0f; for(unsigned int e=0; e<elements.size(); e++) for(int r=0; r<360; r+=30) { LibraryElement element_trial = elements[e]; if(false) { //copy the original(_root) tree and find the corresponding tail BDLSkeletonNode *copy_root = BDLSkeletonNode::copy_tree(_root); BDLSkeletonNode *copy_tail = NULL; //bfs on target, Queue is now empty at this point id = 0; Queue.push(copy_root); while(!Queue.empty()) { BDLSkeletonNode *front = Queue.front(); Queue.pop(); if(id == tail_id) copy_tail = front; for(unsigned int j=0; j<front->_children.size(); j++) Queue.push(front->_children[j]); id++; } //branch replacement std::vector <BDLSkeletonNode *> subtree_trial = replace_branch(copy_tail, element_trial, r); std::vector <BDLSkeletonNode *> non_pruned_nodes = after_pruned(subtree_trial); //but logically //prune(subtree_trial); //no need to do it actually } std::vector <BDLSkeletonNode *> subtree_trial = replace_branch_unchanged(tail, element_trial, r); std::vector <BDLSkeletonNode *> non_pruned_nodes = after_pruned(subtree_trial); //but logically //compute the potential energy //float energy = non_pruned_nodes.empty() ? 23418715 : compute_potential_energy(subtree_trial, space); float energy = compute_potential_energy(non_pruned_nodes, space); if(energy == 23418715.0f) //to let it grow a little bit randomly even it's completely outside the segmentation { min_element_index = rand()%elements.size(); min_rotate = rand()%360; min_energy = 0.0f; } else if(min_energy == -1.0f || energy > min_energy) //the max in value is the min potential energy for negative charge { min_element_index = e; min_rotate = r; min_energy = energy; } //delete the copied tree //BDLSkeletonNode::delete_this(copy_root); for(unsigned int j=0; j<subtree_trial.size(); j++) delete subtree_trial[j]; } //####trial ends#### //actual replacement if(min_energy != -1.0f) { //printf("tail(%p) min_energy(%f) min_element_index(%d) min_rotate(%d)\n", tail, min_energy, min_element_index, min_rotate); std::vector <BDLSkeletonNode *> subtree = replace_branch(tail, elements[min_element_index], min_rotate); std::vector <BDLSkeletonNode *> update_nodes = after_pruned(subtree); prune(subtree); //prune leniently //update space for(unsigned int j=0; j<update_nodes.size(); j++) { osg::Vec3 cur = Transformer::toVec3(update_nodes[j]) - corner; space.add_potential(cur.x(), cur.y(), cur.z(), -3, energy_effect); //negative charge } } //if(i > no_branch * 0.5f && i < no_branch * 0.75f) if(i > no_branch * 0.75f) { if(!_approaching_done) _close_threshold /= 2.0f; _approaching_done = true; } else if(i >= no_branch * 0.90f) _approaching_done = false; } //aftermath: should be shared for different grow methods //prune strictly on entire tree prune_strictly(_root); if(true) { //printf("backward_grow()\n"); backward_grow(); prune_strictly(_root); } }