Ejemplo n.º 1
0
void DContact::ResolveCollisions(const float2& Ncoll, float t, float fCoF, float fCoR,
					  const float2& C0, const float2& P0, float2& V0, float& w0, float m0, float i0, 
					  const float2& C1, const float2& P1, float2& V1, float& w1, float m1, float i1)
{
	// pre-computations
	float tcoll = t > 0.0f ? t : 0.0f;

	float2 Q0 = P0 + V0 * tcoll;
	float2 Q1 = P1 + V1 * tcoll;
	float2 R0 = C0 - Q0;
	float2 R1 = C1 - Q1;
	float2 T0(-R0.y, R0.x);
	float2 T1(-R1.y, R1.x);
	float2 VP0 = V0 - T0 * w0;
	float2 VP1 = V1 - T1 * w1;

	// impact velocity
	float2 Vcoll = VP0 - VP1;
	float  vn	 = Vcoll.dot(Ncoll);
	float2 Vn	 = Ncoll * vn;
	float2 Vt	 = Vcoll - Vn;
	if(vn > 0.0f) { return; }
	float vt = Vt.magnitude();
	Vt = Vt.normalize();

	// compute impulse (friction and restitution)
	float2 J, Jt(0.0f, 0.0f), Jn(0.0f, 0.0f);
	float t0 = (R0 ^ Ncoll) * (R0 ^ Ncoll) * i0;
	float t1 = (R1 ^ Ncoll) * (R1 ^ Ncoll) * i1;
	float m  = m0 + m1;
	float denom = m + t0 + t1;
	float jn = vn / denom;
	Jn = Ncoll * (-(1.0f + fCoR) * jn); // restitution
	Jt = Vt.normalize() * (fCoF * jn); // friction
	J = Jn + Jt;

	// changes in momentum
	float2 dV0 = J * m0;
	float2 dV1 = -J * m1;
	float dw0 =-(R0 ^ J) * i0; 
	float dw1 = (R1 ^ J) * i1;

	if(m0 > 0.0f) { V0 += dV0; w0 += dw0; }; // apply changes in momentum
	if(m1 > 0.0f) { V1 += dV1; w1 += dw1; }; // apply changes in momentum

	// Check for static frcition
	if (vn < 0.0f && fCoF > 0.0f)
	{
		float cone = -vt / vn;
		if (cone < fCoF)
		{
			float2 Nfriction = -Vt.normalize();
			float fCoS = cmat.coStaticFriction;

			ResolveCollisions(Nfriction, 0.0f, 0.0f, fCoS,
							 C0, P0, V0, w0, m0, i0, 
							 C1, P1, V1, w1, m1, i1);
		}
	}
};
Ejemplo n.º 2
0
//========================================================================
//========================================================================
//
//	NAME:	complex<double> bessel_1_complex(int n, complex<double> arg)
//
//	DESC:	Calculates the Bessel function of the first kind (Jn) for
//		complex arguments.
//
//	INPUT:
//		int n:: Order of Bessel function
//		complex<double> arg: Bessel function argument
//	
//	OUTPUT:
//		Jn:: Bessel function of the first kind of order n
//		
//	NOTES:	1) The Bessel function of the first kind is defined as:
//			Jn(x) = ((x/2.0)^n)*sum{m=0, m=inf}[(((-x^2)/4.0)^m)/(m!*(n+m)!)
//
//		2) J-n = ((-1)^n)*Jn
//
//		3) The infinite series representing the Bessel function
//		converges for all arguments given that enough terms are taken:
//		k >> |arg| 
//
//========================================================================
//========================================================================
complex<double> bessel_1_complex(int n, complex<double> arg)
{

  complex<double> Jn(0.0, 0.0);
  complex<double> Jn_series(0.0, 0.0);
  complex<double> Jn_seriesm1(0.0, 0.0);

  double tolerance = 100.0*depsilon();

  // Make sure that we calculate the positive order Bessel function
  int m = abs(n);

  // !!! I don't know if this will be large enough
  int k_max_r, k_max_im; 
  k_max_r = static_cast<int>(real(arg));
  k_max_im = static_cast<int>(imag(arg));

/*
  int k_max = 10*imax(k_max_r, k_max_im);

  for(int k = 0; k <= k_max; k++)
  {
    Jn_series = Jn_series + pow((0.0 - arg*arg/4.0), k)/(dfactorial(k)*dfactorial(k+m));
  }
*/

  // !!! my concern with this do loop is that if a certain term contributes 0 then the 
  // loop may inappropriately exit
  int k_max2 = static_cast<int>(2.0*static_cast<double>(imax(k_max_r, k_max_im))) + 1;

  int k = 0;

  do
  {
    Jn_seriesm1 = Jn_series;

    Jn_series = Jn_series + pow((0.0 - arg*arg/4.0), k)/(dfactorial(k)*dfactorial(k+m));

    k = k + 1;

  } while ((sqrt(real(Jn_series*conj(Jn_series) - Jn_seriesm1*conj(Jn_seriesm1))) > tolerance)   || (k < k_max2));


  Jn = pow((arg/2.0), m)*Jn_series;


  // NOW WE WILL MAKE USE OF THE BESSEL FUNCTION RELATION FOR NEGATIVE n:
  // J(n-1) = (-1)^n*Jn
  if(n < 0)
  {
    Jn = pow((0.0 - 1.0), m)*Jn;
  }


  return Jn;

}
Ejemplo n.º 3
0
////////////////////////////////////////////////////////////////
// ResolveCollision
////////////////////////////////////////////////////////////////
// calculates the change in angular and linear velocity of two
// colliding objects
////////////////////////////////////////////////////////////////
// parameters :
// ------------
// Ncoll : normal of collision
// t : time of collision, (if negative, it's a penetration depth)
// fCoF : coefficient of friction
// fCoR : coefficient of restitution
// C0 : point of contact on object 0
// P0 : centre of gravity (position) of object 0
// V0 : linear Velocity of object 0
// w0 : angular velocity of object 0
// m0 : inverse mass of object 0
// i0 : inverse inertia of object 0
// C1 : point of contact on object 1
// P1 : centre of gravity (position) of object 1
// V1 : linear Velocity of object 1
// w1 : angular velocity of object 1
// m1 : inverse mass of object 1
// i1 : inverse inertia of object 1
//
// return values : V0, w0, V1, w1 will change upon a collision
// -------------
///////////////////////////////////////////////////////////////
void ResolveCollision(const glm::vec2& Ncoll, float t, float fCoF, float fCoR,
					  const glm::vec2& C0, const glm::vec2& P0, glm::vec2& V0, float& w0, float m0, float i0,
					  const glm::vec2& C1, const glm::vec2& P1, glm::vec2& V1, float& w1, float m1, float i1)
{
	//------------------------------------------------------------------------------------------------------
	// pre-computations
	//------------------------------------------------------------------------------------------------------
	float tcoll = (t > 0.0f)? t : 0.0f;

	glm::vec2 Q0    = P0 + V0 * tcoll;
	glm::vec2 Q1    = P1 + V1 * tcoll;
	glm::vec2 R0    = C0 - Q0;
	glm::vec2 R1    = C1 - Q1;
	glm::vec2 T0    = glm::vec2(-R0.y, R0.x);
	glm::vec2 T1    = glm::vec2(-R1.y, R1.x);
	glm::vec2 VP0   = V0 - T0 * w0; // point velocity (SIGN IS WRONG)
	glm::vec2 VP1   = V1 - T1 * w1; // point velocity (SIGN IS WRONG)

	//------------------------------------------------------------------------------------------------------
	// impact velocity
	//------------------------------------------------------------------------------------------------------
	glm::vec2 Vcoll = VP0 - VP1;
	float  vn	 = glm::dot(Vcoll, Ncoll);
	glm::vec2 Vn	 = vn    * Ncoll;
	glm::vec2 Vt	 = Vcoll - Vn;

	// separation
	if (vn > 0.0f)
		return;

	float  vt = glm::length(Vt);


	//------------------------------------------------------------------------------------------------------
	// compute impulse (frction and restitution).
	// ------------------------------------------
	//
	//									-(1+Cor)(Vel.norm)
	//			j =  ------------------------------------------------------------
	//			     [1/Ma + 1/Mb] + [Ia' * (ra x norm)²] + [Ib' * (rb x norm)²]
	//------------------------------------------------------------------------------------------------------
	glm::vec2 J;
	glm::vec2 Jt(0.0f, 0.0f);
	glm::vec2 Jn(0.0f, 0.0f);

	float t0 = cross(R0, Ncoll) * cross(R0, Ncoll) * i0;
	float t1 = cross(R1, Ncoll) * cross(R1, Ncoll) * i1;
	float m  = m0 + m1;

	float denom = m + t0 + t1;

	float jn = vn / denom;

	Jn = (-(1.0f + fCoR) * jn) * Ncoll;

	if (dbg_UseFriction)
	{
		Jt = (fCoF * jn) * glm::normalize(Vt);
	}

	J = Jn + Jt;

	//------------------------------------------------------------------------------------------------------
	// changes in momentum
	//------------------------------------------------------------------------------------------------------
	glm::vec2 dV0 = J * m0;
	glm::vec2 dV1 =-J * m1;

	float dw0 =-cross(R0, J) * i0; // (SIGN IS WRONG)
	float dw1 = cross(R1, J) * i1; // (SIGN IS WRONG)

	//------------------------------------------------------------------------------------------------------
	// apply changes in momentum
	//------------------------------------------------------------------------------------------------------
	if (m0 > 0.0f) V0 += dV0;
	if (m1 > 0.0f) V1 += dV1;
	if (m0 > 0.0f) w0 += dw0;
	if (m1 > 0.0f) w1 += dw1;

	//------------------------------------------------------------------------------------------------------
	// Check for static frcition
	//------------------------------------------------------------------------------------------------------
	if (vn < 0.0f && fCoF > 0.0f)
	{
		float cone = -vt / vn;

		if (cone < fCoF)
		{
			// treat static friciton as a collision at the contact point
			glm::vec2 Nfriction = glm::normalize(-Vt);
			float fCoS = GetStaticFriction;

			ResolveCollision(Nfriction, 0.0f, 0.0f, fCoS,
							 C0, P0, V0, w0, m0, i0,
							 C1, P1, V1, w1, m1, i1);
		}
	}
}
Ejemplo n.º 4
0
 /**
  * @return \e J<sub>n</sub> the dynamical form factors of the ellipsoid.
  *
  * If \e n = 2 (the default), this is the value of <i>J</i><sub>2</sub>
  * used in the constructor.  Otherwise it is the zonal coefficient of the
  * Legendre harmonic sum of the normal gravitational potential.  Note that
  * \e J<sub>n</sub> = 0 if \e n is odd.  In most gravity applications,
  * fully normalized Legendre functions are used and the corresponding
  * coefficient is <i>C</i><sub><i>n</i>0</sub> = &minus;\e J<sub>n</sub> /
  * sqrt(2 \e n + 1).
  **********************************************************************/
 Math::real DynamicalFormFactor(int n = 2) const throw()
 { return Init() ? ( n == 2 ? _J2 : Jn(n)) : Math::NaN<real>(); }
int main()
{
  typedef viennagrid::line_1d_mesh                                    MeshType;
  typedef viennashe::device<MeshType>                                 DeviceType;
  typedef viennagrid::result_of::const_cell_range<MeshType>::type     CellContainer;

  std::cout << viennashe::preamble() << std::endl;

  std::cout << "* main(): Initializing device..." << std::endl;
  DeviceType device;

  //
  //  Generate device geometry using built-in device generator
  //
  {
    viennashe::util::device_generation_config generator_params;
    generator_params.add_segment(0.0,  1e-6, 51);  //start at x=0, length 1e-6, 51 points
    device.generate_mesh(generator_params);
  }

  //
  // Set up and initialize device
  //

  init_device(device, 0.1);

  CellContainer cells(device.mesh());

  //
  // Use a drift-diffusion simulation for obtaining an initial guess of the potential:
  //
  std::cout << "* main(): Creating DD simulator..." << std::endl;
  viennashe::config dd_cfg;
  dd_cfg.linear_solver().set(viennashe::solvers::linear_solver_ids::dense_linear_solver);
  dd_cfg.nonlinear_solver().max_iters(50);
  dd_cfg.nonlinear_solver().damping(0.5);
  //dd_cfg.nonlinear_solver().set(viennashe::solvers::nonlinear_solver_ids::newton_nonlinear_solver);  //uncomment this to use Newton (might require stronger damping)

  viennashe::simulator<DeviceType> dd_simulator(device, dd_cfg);

  std::cout << "* main(): Launching simulator..." << std::endl;
  dd_simulator.run();

  //
  // A single SHE postprocessing step (fixed field)
  //
  std::cout << "* main(): Setting up SHE..." << std::endl;

  viennashe::config config;

  config.set_electron_equation(viennashe::EQUATION_SHE);
  config.with_electrons(true);

  config.with_holes(false);
  config.set_hole_equation(viennashe::EQUATION_CONTINUITY);

  config.nonlinear_solver().max_iters(10);
  config.nonlinear_solver().damping(0.3);

  config.max_expansion_order(1);
  config.energy_spacing(0.0155 * viennashe::physics::constants::q);
  config.min_kinetic_energy_range(1.0 * viennashe::physics::constants::q);

  // configure scattering mechanisms. We use phonon scattering only for now.
  config.scattering().acoustic_phonon().enabled(true);
  config.scattering().optical_phonon().enabled(true);
  config.scattering().ionized_impurity().enabled(false);
  config.scattering().impact_ionization().enabled(false);
  config.scattering().electron_electron(false);

  //config.dispersion_relation(viennashe::she::dispersion_relation_ids::ext_vecchi_dispersion);    //uncomment this to use the extended Vecchi model

  std::cout << "* main(): Computing SHE (electrons only) without ionized impurity and Modena model ..." << std::endl;
  viennashe::simulator<DeviceType> she_simulator(device, config);

  she_simulator.set_initial_guess(viennashe::quantity::potential(),        dd_simulator.potential());
  she_simulator.set_initial_guess(viennashe::quantity::electron_density(), dd_simulator.electron_density());
  she_simulator.set_initial_guess(viennashe::quantity::hole_density(),     dd_simulator.hole_density());

  she_simulator.run();

  std::cout << "* main(): Writing SHE result..." << std::endl;
  viennashe::io::gnuplot_edf_writer edfwriter;

  double n_mid_without  = 0;
  double Jn_mid_without = 0;

  {
    viennashe::io::she_vtk_writer<DeviceType>()(device,
                                                she_simulator.config(),
                                                she_simulator.quantities().electron_distribution_function(),
                                                "simple_impurity_scattering_edf1");

    edfwriter(device, viennashe::util::any_filter(), she_simulator.edf(viennashe::ELECTRON_TYPE_ID), "simple_impurity_scattering_edf1.dat");

    typedef viennashe::simulator<DeviceType>::she_quantity_type she_quan_type;
    viennashe::she::current_density_wrapper<DeviceType, she_quan_type> Jn(device,
                  she_simulator.config(),
                  she_simulator.quantities().electron_distribution_function());

    viennashe::she::carrier_density_wrapper<she_quan_type> n(
                    she_simulator.config(),
                    she_simulator.quantities().electron_distribution_function());

    viennashe::io::write_cell_quantity_for_gnuplot(Jn, device, "simple_impurity_scattering_Jn1.dat");

    n_mid_without  = n(cells[25]);
    Jn_mid_without = Jn(cells[25])[0];
  }
  // ####################################################################################################################################

  config.scattering().ionized_impurity().enabled(true); // enable ionized impurity scattering

  std::cout << "* main(): Computing SHE (electrons only) WITH ionized impurity and Modena model ..." << std::endl;
  viennashe::simulator<DeviceType> she_simulator_with(device, config);

  she_simulator_with.set_initial_guess(viennashe::quantity::potential(),        dd_simulator.potential());
  she_simulator_with.set_initial_guess(viennashe::quantity::electron_density(), dd_simulator.electron_density());
  she_simulator_with.set_initial_guess(viennashe::quantity::hole_density(),     dd_simulator.hole_density());

  she_simulator_with.run();

  std::cout << "* main(): Writing SHE result..." << std::endl;

  viennashe::io::she_vtk_writer<DeviceType>()(device,
                                              she_simulator_with.config(),
                                              she_simulator_with.quantities().electron_distribution_function(),
                                              "simple_impurity_scattering_edf2");

  //viennashe::io::gnuplot_edf_writer edfwriter;
  edfwriter(device, viennashe::util::any_filter(), she_simulator_with.edf(viennashe::ELECTRON_TYPE_ID), "simple_impurity_scattering_edf2.dat");

  typedef viennashe::simulator<DeviceType>::she_quantity_type she_quan_type;
  viennashe::she::current_density_wrapper<DeviceType, she_quan_type> Jn(device,
                config,
                she_simulator_with.quantities().electron_distribution_function());

    viennashe::she::carrier_density_wrapper<she_quan_type> n(
                    config,
                    she_simulator_with.quantities().electron_distribution_function());

  viennashe::io::write_cell_quantity_for_gnuplot(Jn, device, "simple_impurity_scattering_Jn2.dat");

  double n_mid_with  = n(cells[25]);
  double Jn_mid_with = Jn(cells[25])[0];

  if(!viennashe::testing::fuzzy_equal(n_mid_without, n_mid_with))
  {
    std::cerr << "ERROR: Ionized impurity scattering should NOT change the electron density in a resistor!" << std::endl;
    std::cerr << "       The densities are not equal." << std::endl;
    std::cerr << n_mid_without << " != " << n_mid_with << std::endl;
    return EXIT_FAILURE;
  }

  if(viennashe::testing::fuzzy_equal(Jn_mid_without, Jn_mid_with, 1e-5))
  {
    std::cerr << "ERROR: Ionized impurity scattering should change the electron CURRENT density in a resistor!" << std::endl;
    std::cerr << "       It failed to do so." << std::endl;
    std::cerr << Jn_mid_without << " == " << Jn_mid_with << std::endl;
    return EXIT_FAILURE;
  }
  else
  {
    std::cerr << "BUT: This is ok!" << std::endl;
  }

  if(Jn_mid_without < Jn_mid_with)
  {
    std::cerr << "ERROR: Ionized impurity scattering should DECREASE the electron CURRENT density in a resistor!" << std::endl;
    std::cerr << "       It failed to do so." << std::endl;
    return EXIT_FAILURE;
  }


  std::cout << std::endl;
  std::cout << "*********************************************************" << std::endl;
  std::cout << "*           ViennaSHE finished successfully             *" << std::endl;
  std::cout << "*********************************************************" << std::endl;

  return EXIT_SUCCESS;
}
Ejemplo n.º 6
0
    void Contact::ResolveCollision()
    {
        if (!m_pxBodies[0] || !m_pxBodies[1])
            return;

        //------------------------------------------------------------------------------------------------------
        // parameters
        //------------------------------------------------------------------------------------------------------
        Point2f C0    = m_xContacts[0];
        Point2f C1    = m_xContacts[1];
        Point2f Ncoll = C1 - C0;
        // assert(Ncoll.x != 0 || Ncoll.y != 0);
        Ncoll.Normalize();

        float m0 = m_pxBodies[0]->getInvMass();
        float m1 = m_pxBodies[1]->getInvMass();
        float i0 = m_pxBodies[0]->getInvInertia();
        float i1 = m_pxBodies[1]->getInvInertia();

        const Point2f& P0   = m_pxBodies[0]->getPosition();
        const Point2f& P1   = m_pxBodies[1]->getPosition();
        const Point2f& V0   = m_pxBodies[0]->getVelocity();
        const Point2f& V1   = m_pxBodies[1]->getVelocity();
        float  w0   = m_pxBodies[0]->getAngVelocity();
        float  w1   = m_pxBodies[1]->getAngVelocity();

        //------------------------------------------------------------------------------------------------------
        // pre-computations
        //------------------------------------------------------------------------------------------------------
        Point2f R0    = C0 - P0;
        Point2f R1    = C1 - P1;
        Point2f T0    = Point2f(-R0.y, R0.x);
        Point2f T1    = Point2f(-R1.y, R1.x);
        Point2f VP0   = V0 + T0 * w0; // point velocity
        Point2f VP1   = V1 + T1 * w1; // point velocity

        //------------------------------------------------------------------------------------------------------
        // impact velocity
        //------------------------------------------------------------------------------------------------------
        Point2f Vcoll = VP0 - VP1;
        float  vn	 = Vcoll * Ncoll;
        Point2f Vn	 = Ncoll * vn;
        Point2f Vt	 = Vcoll - Vn;

        if (vn > 0.0f) // separation
            return;

        if (Vt * Vt < 0.0001f)
            Vt = Point2f(0.0f, 0.0f);

        // float  vt = Vt.Length();
        Vt.Normalize();


        //------------------------------------------------------------------------------------------------------
        // compute impulse (frction and restitution).
        // ------------------------------------------
        //
        //									-(1+Cor)(Vel.norm)
        //			j =  ------------------------------------------------------------
        //			     [1/Ma + 1/Mb] + [Ia' * (ra x norm)²] + [Ib' * (rb x norm)²]
        //------------------------------------------------------------------------------------------------------
        Point2f J;
        Point2f Jt(0.0f, 0.0f);
        Point2f Jn(0.0f, 0.0f);

        float fCoR  = s_xContactMaterial.GetRestitution();
        float fCoF  = s_xContactMaterial.GetFriction();

        float t0 = (R0 ^ Ncoll) * (R0 ^ Ncoll) * i0;
        float t1 = (R1 ^ Ncoll) * (R1 ^ Ncoll) * i1;
        float m  = m0 + m1;

        float denom = m + t0 + t1;

        float jn = vn / denom;

        Jn = Ncoll * (-(1.0f + fCoR) * jn);

        //if (dbg_UseFriction)
        Jt = Vt * (fCoF * jn);

        J = Jn + Jt;

        //------------------------------------------------------------------------------------------------------
        // changes in momentum
        //------------------------------------------------------------------------------------------------------
        Point2f dV0 = J * m0;
        Point2f dV1 =-J * m1;

        float dw0 = (R0 ^ J) * i0;
        float dw1 =-(R1 ^ J) * i1;

        //------------------------------------------------------------------------------------------------------
        // apply changes in momentum
        //------------------------------------------------------------------------------------------------------
        if (!m_pxBodies[0]->isStaticBody())
        {
            if (m0 > 0.0f)
            {
                m_pxBodies[0]->setVelocity(V0 + dV0);
            }
            if (m0 > 0.0f)
            {
                m_pxBodies[0]->setAngVelocity(w0 + dw0);
            }
        }
        if (!m_pxBodies[1]->isStaticBody())
        {
            if (m1 > 0.0f)
            {
                m_pxBodies[1]->setVelocity(V1 + dV1);
            }
            if (m1 > 0.0f)
            {
                m_pxBodies[1]->setAngVelocity(w1 + dw1);
            }
        }
        //	Render();
        return;
/*
        //------------------------------------------------------------------------------------------------------
        // Check for static frcition
        //------------------------------------------------------------------------------------------------------
        float fRestingContactVelocity = 1.0f;

        if (-vn < fRestingContactVelocity)
        {
            if (vt < fRestingContactVelocity * fCoF)
            {
                //------------------------------------------------------------------------------------------------------
                // Cancel tangential velocity on the two bodies, so they stick
                //------------------------------------------------------------------------------------------------------
                Point2f dV = V1 - V0;
                dV -= Ncoll * (dV * Ncoll);
                if (m0 > 0.0f) V0 += dV * (m0 / m + 0.01f);
                if (m1 > 0.0f) V1 -= dV * (m1 / m + 0.01f);
            }
        }
        */
    }