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
Esempio n. 3
0
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(); }

}
Esempio n. 4
0
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);
	}
}