示例#1
0
void ChEmitterAsset::Update(ChPhysicsItem* updater, const ChCoordsys<>& coords) {

    ChSystem* msys = updater->GetSystem();
    
    if (!msys) 
        return;

    double mt = msys->GetChTime();

    if (mt < this->last_t)
        last_t = mt;
    
    double dt = mt - last_t;
    last_t = mt;

    if (dt == 0)
        return;
    //***TODO*** a better way to deduce dt, ex. by using flags in Update(),
    // to know if Update really follows a t+dt update, etc. 

    // Create the particles!

    ChFrameMoving<> mframe(coords);

    // special case: the owner is a body? so use also speed info
    if(ChBody* mbody = dynamic_cast<ChBody*>(updater)) {

        ChFrameMoving<> bodyframe = mbody->GetFrame_REF_to_abs();
        ChFrameMoving<> relcoords;
        bodyframe.TransformParentToLocal(mframe, relcoords);
        relcoords.SetCoord_dt(CSYSNULL);
        relcoords.SetCoord_dtdt(CSYSNULL);
        bodyframe.TransformLocalToParent(relcoords, mframe);
    }

    this->memitter.EmitParticles(*msys, dt, mframe);
}
示例#2
0
int main(int argc, char* argv[])
{
  ChSystem system;

  // Disable gravity
  system.Set_G_acc(ChVector<>(0, 0, 0));

  // Set the half-length of the two shafts
  double hl = 2;

  // Set the bend angle between the two shafts (positive rotation about the
  // global X axis)
  double angle = CH_C_PI / 6;
  double cosa = std::cos(angle);
  double sina = std::sin(angle);
  ChQuaternion<> rot = Q_from_AngX(angle);

  // Create the ground (fixed) body
  // ------------------------------

  ChSharedPtr<ChBody> ground(new ChBody);
  system.AddBody(ground);
  ground->SetIdentifier(-1);
  ground->SetBodyFixed(true);
  ground->SetCollide(false);

  // attach visualization assets to represent the revolute and cylindrical
  // joints that connect the two shafts to ground
  {
    ChSharedPtr<ChCylinderShape> cyl_1(new ChCylinderShape);
    cyl_1->GetCylinderGeometry().p1 = ChVector<>(0, 0, -hl - 0.2);
    cyl_1->GetCylinderGeometry().p2 = ChVector<>(0, 0, -hl + 0.2);
    cyl_1->GetCylinderGeometry().rad = 0.3;
    ground->AddAsset(cyl_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(0, -(hl - 0.2) * sina, (hl - 0.2) * cosa);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0, -(hl + 0.2) * sina, (hl + 0.2) * cosa);
    cyl_2->GetCylinderGeometry().rad = 0.3;
    ground->AddAsset(cyl_2);
  }

  // Create the first shaft body
  // ---------------------------

  ChSharedPtr<ChBody> shaft_1(new ChBody);
  system.AddBody(shaft_1);
  shaft_1->SetIdentifier(1);
  shaft_1->SetBodyFixed(false);
  shaft_1->SetCollide(false);
  shaft_1->SetMass(1);
  shaft_1->SetInertiaXX(ChVector<>(1, 1, 0.2));
  shaft_1->SetPos(ChVector<>(0, 0, -hl));
  shaft_1->SetRot(ChQuaternion<>(1, 0, 0, 0));

  // Add visualization assets to represent the shaft (a box) and the arm of the
  // universal joint's cross associated with this shaft (a cylinder)
  {
    ChSharedPtr<ChBoxShape> box_1(new ChBoxShape);
    box_1->GetBoxGeometry().Size = ChVector<>(0.15, 0.15, 0.9 * hl);
    shaft_1->AddAsset(box_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(-0.2, 0, hl);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0.2, 0, hl);
    cyl_2->GetCylinderGeometry().rad = 0.05;
    shaft_1->AddAsset(cyl_2);

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0.6f, 0, 0));
    shaft_1->AddAsset(col);
  }


  // Create the second shaft body
  // ----------------------------

  // The second shaft is identical to the first one, but initialized at an angle
  // equal to the specified bend angle.

  ChSharedPtr<ChBody> shaft_2(new ChBody);
  system.AddBody(shaft_2);
  shaft_2->SetIdentifier(1);
  shaft_2->SetBodyFixed(false);
  shaft_2->SetCollide(false);
  shaft_2->SetMass(1);
  shaft_2->SetInertiaXX(ChVector<>(1, 1, 0.2));
  shaft_2->SetPos(ChVector<>(0, -hl * sina, hl * cosa));
  shaft_2->SetRot(rot);

  // Add visualization assets to represent the shaft (a box) and the arm of the
  // universal joint's cross associated with this shaft (a cylinder)
  {
    ChSharedPtr<ChBoxShape> box_1(new ChBoxShape);
    box_1->GetBoxGeometry().Size = ChVector<>(0.15, 0.15, 0.9 * hl);
    shaft_2->AddAsset(box_1);

    ChSharedPtr<ChCylinderShape> cyl_2(new ChCylinderShape);
    cyl_2->GetCylinderGeometry().p1 = ChVector<>(0, -0.2, -hl);
    cyl_2->GetCylinderGeometry().p2 = ChVector<>(0, 0.2, -hl);
    cyl_2->GetCylinderGeometry().rad = 0.05;
    shaft_2->AddAsset(cyl_2);

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0, 0, 0.6f));
    shaft_2->AddAsset(col);
  }

  // Connect the first shaft to ground
  // ---------------------------------

  // Use a ChLinkEngine to impose both the revolute joint constraints, as well
  // as constant angular velocity.  The joint is located at the origin of the
  // first shaft.

  ChSharedPtr<ChLinkEngine> motor(new ChLinkEngine);
  system.AddLink(motor);
  motor->Initialize(ground, shaft_1, ChCoordsys<>(ChVector<>(0, 0, -hl), ChQuaternion<>(1, 0, 0, 0)));
  motor->Set_eng_mode(ChLinkEngine::ENG_MODE_ROTATION);
  motor->Set_rot_funct(ChSharedPtr<ChFunction>(new ChFunction_Ramp(0, 1)));

  // Connect the second shaft to ground through a cylindrical joint
  // --------------------------------------------------------------

  // Use a cylindrical joint so that we do not have redundant constraints
  // (note that, technically Chrono could deal with a revolute joint here).
  // the joint is located at the origin of the second shaft.

  ChSharedPtr<ChLinkLockCylindrical> cyljoint(new ChLinkLockCylindrical);
  system.AddLink(cyljoint);
  cyljoint->Initialize(ground, shaft_2, ChCoordsys<>(ChVector<>(0, -hl * sina, hl * cosa), rot));

  // Connect the two shafts through a universal joint
  // ------------------------------------------------

  // The joint is located at the global origin.  Its kinematic constraints will
  // enforce orthogonality of the associated cross.

  ChSharedPtr<ChLinkUniversal> ujoint(new ChLinkUniversal);
  system.AddLink(ujoint);
  ujoint->Initialize(shaft_1, shaft_2, ChFrame<>(ChVector<>(0, 0, 0), rot));

  // Create the Irrlicht application
  // -------------------------------

  ChIrrApp application(&system, L"ChBodyAuxRef demo", core::dimension2d<u32>(800, 600), false, true);
  application.AddTypicalLogo();
  application.AddTypicalSky();
  application.AddTypicalLights();
  application.AddTypicalCamera(core::vector3df(3, 1, -1.5));

  application.AssetBindAll();
  application.AssetUpdateAll();

  // Simulation loop
  application.SetTimestep(0.001);

  int frame = 0;

  while (application.GetDevice()->run())
  {
    application.BeginScene();
    application.DrawAll();
    application.DoStep();
    application.EndScene();
    frame++;

    if (frame % 20 == 0) {
      // Output the shaft angular velocities at the current time
      double omega_1 = shaft_1->GetWvel_loc().z;
      double omega_2 = shaft_2->GetWvel_loc().z;
      GetLog() << system.GetChTime() << "   " << omega_1 << "   " << omega_2 << "\n";
    }
  }

  return 0;
}
示例#3
0
int main(int argc, char* argv[])
{

	// In CHRONO engine, The DLL_CreateGlobals() - DLL_DeleteGlobals(); pair is needed if
	// global functions are needed.
	DLL_CreateGlobals();

	// Create a ChronoENGINE physical system
	ChSystem mphysicalSystem;

	// Create the Irrlicht visualization (open the Irrlicht device, 
	// bind a simple user interface, etc. etc.)
	ChIrrAppInterface application(&mphysicalSystem, L"Benchmark application",core::dimension2d<u32>(800,600),false);

 
	// Easy shortcuts to add logo, camera, lights and sky in Irrlicht scene:
	ChIrrWizard::add_typical_Lights(application.GetDevice());
	ChIrrWizard::add_typical_Camera(application.GetDevice(), core::vector3df(0,14,-40));



 	// 
	// CREATE THE MECHANICAL SYSTEM OF CHRONO...
	// 

 
	application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
	application.GetVideoDriver()->endScene(); 
	GetLog() << "  ** PLEASE WAIT FOR INITIALIZATION! \n  ** This may take seconds or minutes..\n\n";

    
	// Prepare the physical system for the simulation
 
	mphysicalSystem.SetIntegrationType(ChSystem::INT_ANITESCU); 
	//mphysicalSystem.SetIntegrationType(ChSystem::INT_TASORA); 

	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SYMMSOR); // here would be the better choiche since the wall is build ground up.
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_JACOBI); 
	//mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR_MULTITHREAD); 
	//mphysicalSystem.SetParallelThreadNumber(4);

	mphysicalSystem.SetMaxPenetrationRecoverySpeed(1.6); // used by Anitescu stepper only
	mphysicalSystem.SetIterLCPmaxItersSpeed(20);
	mphysicalSystem.SetIterLCPmaxItersStab(10); // unuseful for Anitescu, only Tasora uses this
	//mphysicalSystem.SetIterLCPwarmStarting(true);


	// Test convergence for varying omega 
	//
	// (solver:SOR)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_SOR_Niter.dat");
		ChStreamOutAsciiFile data_dgamma_SOR_Niter("data_dgamma_SOR_Niter.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double momega = 0.2; (momega <= 1.401 && application.GetDevice()->run()); momega +=0.2)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetIterLCPomega(momega);
					mphysicalSystem.SetIterLCPsharpnessLambda(0.7);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_SOR_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}


				

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_SOR_Niter << "\n";
			data_dgamma_SOR_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test convergence for varying omega 
	//
	// (solver:JACOBI)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_JACOBI_Niter("data_err_JACOBI_Niter_L10_at500_ok.dat");
		ChStreamOutAsciiFile data_dgamma_JACOBI_Niter("data_dgamma_JACOBI_Niter_L10_at500_ok.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPomega(0.8);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double momega = 0.1; (momega <= 0.71 && application.GetDevice()->run()); momega +=0.1)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPmaxItersSpeed(80);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_JACOBI);
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					msolver->SetRecordViolation(true);
					mphysicalSystem.SetIterLCPomega(momega);
					mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_JACOBI_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_JACOBI_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_JACOBI_Niter << "\n";
			data_dgamma_JACOBI_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test lambda effect
	//
	// Velocity error  vs.  Num. velocity iterations  vs. Lambda
	// (solver:SOR)
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_SOR_Niter_om1.dat");
		ChStreamOutAsciiFile data_dgamma_SOR_Niter("data_dgamma_SOR_Niter_om1.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(80);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double mlambda = 0.2; (mlambda <= 1.01 && application.GetDevice()->run()); mlambda +=0.2)
		{
			ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			mphysicalSystem.SetIterLCPomega(0.8);
			mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
			mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);

				// create spheres and walls, and insert into that scene node
			ChSetRandomSeed(123);
			create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

			int totframes = 0;
										// ------- begin simulation loop -----
			while(application.GetDevice()->run())
			{
				totframes++;

				application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
				application.DrawAll();

				if (totframes==plotframe)
				{
					mphysicalSystem.SetIterLCPomega(1.0);
					mphysicalSystem.SetIterLCPsharpnessLambda(mlambda);
					mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
				}

				// integrate
				mphysicalSystem.DoStepDynamics(0.01);

				application.GetVideoDriver()->endScene(); 

				//***PLOT***
				if (totframes==plotframe)
				{
					GetLog()<< "Saving data\n";
					ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
					for (int k=0; k< msolver->GetViolationHistory().size(); k++)
					{
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[k] << " ";
					}
					for (int j=0; j< msolver->GetDeltalambdaHistory().size(); j++)
					{
						data_dgamma_SOR_Niter <<  msolver->GetDeltalambdaHistory()[j] << " ";
					}
				}


				

				if(totframes>plotframe) break;

			}							// ------- end of simulation loop -----

			GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
			
			data_err_SOR_Niter << "\n";
			data_dgamma_SOR_Niter << "\n";

			// remove the root scene node (contains walls & spheres but no camera no lights)
			// to reset and prepare for new scene at next for() loop.
			parent->remove();

			// Now the system should already have no bodies, because of full removal from Irrlicht scene.
			// Then, the following clearing should be unuseful...(do it anyway..)
			mphysicalSystem.Clear(); 
		}

	} // end test



	// Test stack aspect ratio
	//
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_SOR_Niter("data_err_aspectratio3.dat");
		int plotframe = 500;
		int ntestspheres = 220;

		mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
		mphysicalSystem.SetIterLCPmaxItersSpeed(30);
		mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 

		ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
		msolver->SetRecordViolation(true);

		for (double mspheres=10; (mspheres <= 330 && application.GetDevice()->run()); mspheres +=40)
		{
			for (int nviters = 20; (nviters <= 101 && application.GetDevice()->run()); nviters +=20)
			{
				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mphysicalSystem.SetIterLCPomega(0.9);
				mphysicalSystem.SetIterLCPsharpnessLambda(1.0);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0);
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, mspheres, 1.6, 10,20.1); 

				int totframes = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					if (totframes==plotframe)
					{
						mphysicalSystem.SetIterLCPomega(0.9);
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0);
					}

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// integrate
					mphysicalSystem.DoStepDynamics(0.01);

					application.GetVideoDriver()->endScene(); 

					//***PLOT***
					if (totframes==plotframe)
					{
						GetLog()<< "Saving data\n";
						ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
						data_err_SOR_Niter <<  msolver->GetViolationHistory()[msolver->GetViolationHistory().size()-1] << " ";
					}

					if(totframes>plotframe) break;

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_SOR_Niter << "\n";
		}

	} // end test




	// Test pos error
	//
	//
	if (false)
	{
		ChStreamOutAsciiFile data_err_pos("data_err_pos.dat");
		int plotframe = 500;
		int ntestspheres = 120;
		double mystep= 0;

		for (double mdt=0.01; (mdt>0.00015 && application.GetDevice()->run()); mdt*=0.5)
		{
			GetLog() << "\n\nDT = " << mdt << "\n";

			for (int nviters = 20; (nviters <= 81 && application.GetDevice()->run()); nviters +=20)
			{
				GetLog() << "  nviters = " << nviters << "\n";

				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mystep = 0.01;
				mphysicalSystem.SetChTime(0.0);
				mphysicalSystem.SetIterLCPsharpnessLambda(0.8);
				mphysicalSystem.SetIterLCPomega(0.8);
				mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(2.0); 
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

				int totframes = 0;
				int averagecnt = 0;
				double average = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// start mode
					if (mphysicalSystem.GetChTime()>2.4)
					{	
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mystep=mdt;
					}

					//start average
					if (mphysicalSystem.GetChTime()>2.6)
					{	

						class _label_reporter_class : public chrono::ChReportContactCallback 
						{
						public:
							virtual bool ReportContactCallback (
											const chrono::ChVector<>& pA,				
											const chrono::ChVector<>& pB,				
											const chrono::ChMatrix33<>& plane_coord,	
											const double& distance,				
											const float& mfriction,			  	
											const chrono::ChVector<>& react_forces,		
											const chrono::ChVector<>& react_torques,	
											chrono::collision::ChCollisionModel* modA,	
											chrono::collision::ChCollisionModel* modB) 
							{
								if (distance<maxpen)
									maxpen = distance;
								return true; // to continue scanning contacts
							}
							// Data 
							double maxpen;
						};

						_label_reporter_class my_label_rep;

						my_label_rep.maxpen = 0;

						// scan all contacts
						mphysicalSystem.GetContactContainer()->ReportAllContacts(&my_label_rep);
						//GetLog() << "        p: " << my_label_rep.maxpen << "\n";
						averagecnt++;
						average += my_label_rep.maxpen;
					}

					// stop average & loop
					if(mphysicalSystem.GetChTime()>2.8)
					{
						average /= (double)averagecnt;
						GetLog() << "     avg.err: " << average << "\n";
						data_err_pos <<  average << " ";
						break;
					}

					// integrate
					mphysicalSystem.DoStepDynamics(mystep);

					application.GetVideoDriver()->endScene(); 

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_pos << "\n";
		}

	} // end test



	// Test pos error with Tasora stabilization
	//
	//
	if (true)
	{
		ChStreamOutAsciiFile data_err_pos("data_err_tasora.dat");
		int ntestspheres = 120;

		for (int npiters = 20; (npiters <= 81 && application.GetDevice()->run()); npiters +=20)
		{
			GetLog() << "  npiters = " << npiters << "\n";

			for (int nviters = 20; (nviters <= 81 && application.GetDevice()->run()); nviters +=20)
			{
				GetLog() << "  nviters = " << nviters << "\n";

				ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

				mphysicalSystem.SetChTime(0.0);
				mphysicalSystem.SetIterLCPsharpnessLambda(0.8);
				mphysicalSystem.SetIterLCPomega(0.8);
				mphysicalSystem.SetLcpSolverType(ChSystem::LCP_ITERATIVE_SOR);
				mphysicalSystem.SetIntegrationType(ChSystem::INT_TASORA);
				mphysicalSystem.SetIterLCPmaxItersSpeed(30);
				mphysicalSystem.SetIterLCPmaxItersStab(30);
				mphysicalSystem.SetMaxPenetrationRecoverySpeed(0.0); 
				
					// create spheres and walls, and insert into that scene node
				ChSetRandomSeed(13);
				create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, ntestspheres, 1.6, 10); 

				int totframes = 0;
				int averagecnt = 0;
				double average = 0;
											// ------- begin simulation loop -----
				while(application.GetDevice()->run())
				{
					totframes++;

					application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
					application.DrawAll();

					// start mode
					if (mphysicalSystem.GetChTime()>3)
					{	
						mphysicalSystem.SetIterLCPmaxItersSpeed(nviters);
						mphysicalSystem.SetIterLCPmaxItersStab(npiters);
					}

					//start average
					if (mphysicalSystem.GetChTime()>4.2)
					{	

						class _label_reporter_class : public chrono::ChReportContactCallback 
						{
						public:
							virtual bool ReportContactCallback (
											const chrono::ChVector<>& pA,				
											const chrono::ChVector<>& pB,				
											const chrono::ChMatrix33<>& plane_coord,	
											const double& distance,				
											const float& mfriction,			  	
											const chrono::ChVector<>& react_forces,		
											const chrono::ChVector<>& react_torques,	
											chrono::collision::ChCollisionModel* modA,	
											chrono::collision::ChCollisionModel* modB) 
							{
								if (distance<maxpen)
									maxpen = distance;
								return true; // to continue scanning contacts
							}
							// Data 
							double maxpen;
						};

						_label_reporter_class my_label_rep;

						my_label_rep.maxpen = 0;

						// scan all contacts
						mphysicalSystem.GetContactContainer()->ReportAllContacts(&my_label_rep);
						averagecnt++;
						average += my_label_rep.maxpen;
					}

					// stop average & loop
					if(mphysicalSystem.GetChTime()>4.5)
					{
						average /= (double)averagecnt;
						GetLog() << "     avg.err: " << average << "\n";
						data_err_pos <<  average << " ";
						break;
					}

					// integrate
					mphysicalSystem.DoStepDynamics(0.01);

					application.GetVideoDriver()->endScene(); 

				}							// ------- end of simulation loop -----

				
				// remove the root scene node (contains walls & spheres but no camera no lights)
				// to reset and prepare for new scene at next for() loop.
				parent->remove();

				// Now the system should already have no bodies, because of full removal from Irrlicht scene.
				// Then, the following clearing should be unuseful...(do it anyway..)
				mphysicalSystem.Clear(); 
			}

			data_err_pos << "\n";
		}

	} // end test



	getchar();



	//
	// loop of tests:each time test more spheres!
	// 
	ChStreamOutAsciiFile data_spheres_times("data_spheres_times.dat");
	ChStreamOutAsciiFile data_contacts_times("data_contact_times.dat");
	ChStreamOutAsciiFile data_ncontacts("data_ncontacts.dat");
	ChStreamOutAsciiFile data_timexconstr("data_timexconstr.dat");

	for (int nspheres = 1; (nspheres <= 1 && application.GetDevice()->run()); nspheres +=1)
	{

		ChStreamOutAsciiFile data_timing("data_timing1k.dat");
		

		// 
		// Create all the  rigid bodies!!!! 
		//

			// the root scene node containing all dynamic objects
		ISceneNode* parent = application.GetSceneManager()->addEmptySceneNode();

			// create spheres and walls, and insert into that scene node
		create_some_falling_items(mphysicalSystem, application.GetSceneManager(), application.GetVideoDriver(), parent, SPHERE_NUM,SPHERE_RAD,SPHERE_MASS); 

		// 
		// THE SOFT-REAL-TIME CYCLE
		// 

		int mdelay=0;
		int lastFPS = -1;

		ChTimer<double>mtimer; 

		ChRealtimeStepTimer m_realtime_timer;

		//ChStreamOutAsciiFile data_deltares("data_pNviolation_i80.dat");


		int totframes = 0;
		while(application.GetDevice()->run())
		{
			totframes++;

			if (totframes == 400) mtimer.start();

			// Irrlicht must prepare frame to draw
			application.GetVideoDriver()->beginScene(true, true, SColor(255,140,161,192));
		
			// Irrlicht draws all 3D objects and all GUI items
			application.DrawAll();


			// HERE CHRONO INTEGRATION IS PERFORMED: THE  
			// TIME OF THE SIMULATION ADVANCES FOR A SINGLE
			// STEP:
			mphysicalSystem.DoStepDynamics(0.01);


			application.GetVideoDriver()->endScene(); 

			

			if (totframes > 600)
			data_timing << mphysicalSystem.GetChTime()-3.0 << " " \
						<< mphysicalSystem.GetTimerStep() << " " \
						<< mphysicalSystem.GetTimerLcp()+mphysicalSystem.GetTimerCollisionBroad() << " " \
						<< mphysicalSystem.GetTimerLcp() << "\n";


			/*
			//***PLOT*** plot max constr.normal violation
			if ((totframes<600)&&(totframes>300))
			{
				ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverStab();
				if (msolver->GetViolationHistory().size()>1)
					data_deltares <<  msolver->GetViolationHistory()[msolver->GetViolationHistory().size()-1] << "\n";
			}

			//***PLOT*** plot deltalambda corrections for varying omega
			if (totframes==999)
			{
				ChLcpIterativeSymmSOR* msolver = (ChLcpIterativeSymmSOR*)mphysicalSystem.GetLcpSolverSpeed();
				msolver->SetOmega(1.0);
			}
			if (totframes==1000)
			{
				GetLog()<< "Saving plot data\n";
				ChLcpIterativeSolver* msolver = (ChLcpIterativeSolver*)mphysicalSystem.GetLcpSolverSpeed();
				ChStreamOutAsciiFile data_deltalambda("data_deltalambda_om80.dat");
				for (int k=0; k< msolver->GetDeltalambdaHistory().size(); k++)
				{
					data_deltalambda <<  msolver->GetDeltalambdaHistory()[k] << "\n";
				}
			}
			*/

			if ((totframes>200)&&(totframes<=500))
			{
				//data_timexconstr << mphysicalSystem.GetTimerLcp()/(double)mphysicalSystem.GetNcontacts() << "\n";
				//GetLog()<< "  avg time/contacts " << mphysicalSystem.GetTimerLcp()/(double)mphysicalSystem.GetNcontacts() << "\n";
				//GetLog()<< "  ncontacts " << (double)mphysicalSystem.GetNcontacts() << "\n";
			}

			if(totframes>500) break;


		}  // ------- end of simulation loop -----



		mtimer.stop();
		GetLog()<< "Time used for simulating/viewing first 500 steps: " << mtimer() << "\n";
		GetLog()<< "  num contacts " << mphysicalSystem.GetNcontacts() << "\n";
		GetLog()<< "  avg time/contacts " << mtimer()/(double)mphysicalSystem.GetNcontacts() << "\n";
		data_spheres_times << nspheres << "  " << mtimer() << "\n";
		data_contacts_times << mphysicalSystem.GetNcontacts() << "  " << mtimer() << "\n";
		

		// remove the root scene node (contains walls & spheres but no camera no lights)
		// to reset and prepare for new scene at next for() loop.
		parent->remove();

		// Now the system should already have no bodies, because of full removal from Irrlicht scene.
		// Then, the following clearing should be unuseful...(do it anyway..)
		mphysicalSystem.Clear(); 
	}



	// Remember this at the end of the program, if you started
	// with DLL_CreateGlobals();
	DLL_DeleteGlobals();

	getchar();

	return 0;
}