int main(int argc, char* argv[]) { try { // ================= Creation of the model ======================= // User-defined main parameters unsigned int nDof = 3; // degrees of freedom for the ball double t0 = 0; // initial computation time double T = 2.0; // final computation time double h = 0.0005; // time step double position_init = 1.0; // initial position for lowest bead. double velocity_init = 0.0; // initial velocity for lowest bead. double theta = 0.5; // theta for MoreauJeanOSI integrator double R = 0.1; // Ball radius double m = 1; // Ball mass double g = 9.81; // Gravity // ------------------------- // --- Dynamical systems --- // ------------------------- cout << "====> Model loading ..." << endl << endl; // Number of Beads unsigned int nBeads = 10; double initialGap = 0.25; double alert = 0.02; SP::SiconosMatrix Mass(new SimpleMatrix(nDof, nDof)); (*Mass)(0, 0) = m; (*Mass)(1, 1) = m; (*Mass)(2, 2) = 3. / 5 * m * R * R; // -- Initial positions and velocities -- std::vector<SP::SiconosVector> q0(nBeads); std::vector<SP::SiconosVector> v0(nBeads); for (unsigned int i = 0; i < nBeads; i++) { (q0[i]).reset(new SiconosVector(nDof)); (v0[i]).reset(new SiconosVector(nDof)); (q0[i])->setValue(0, position_init + i * initialGap); (v0[i])->setValue(0, velocity_init); } // -- The dynamical system -- SP::SiconosVector weight(new SiconosVector(nDof)); (*weight)(0) = -m * g; std::vector<SP::LagrangianLinearTIDS> beads(nBeads); for (unsigned int i = 0; i < nBeads; i++) { beads[i].reset(new LagrangianLinearTIDS(q0[i], v0[i], Mass)); // -- Set external forces (weight) -- beads[i]->setFExtPtr(weight); } // -------------------- // --- Interactions --- // -------------------- // -- nslaw -- double e = 0.9; // Interaction ball-floor // SP::SimpleMatrix H(new SimpleMatrix(1, nDof)); (*H)(0, 0) = 1.0; SP::SiconosVector b(new SiconosVector(1)); (*b)(0) = -R; SP::NonSmoothLaw nslaw(new NewtonImpactNSL(e)); SP::Relation relation(new LagrangianLinearTIR(H, b)); SP::Interaction inter; // beads/beads interactions SP::SimpleMatrix HOfBeads(new SimpleMatrix(1, 2 * nDof)); (*HOfBeads)(0, 0) = -1.0; (*HOfBeads)(0, 3) = 1.0; SP::SiconosVector bOfBeads(new SiconosVector(1)); (*bOfBeads)(0) = -2 * R; // This doesn't work !!! //SP::Relation relationOfBeads(new LagrangianLinearTIR(HOfBeads)); //std::vector<SP::Interaction > interOfBeads(nBeads-1); // for (unsigned int i =0; i< nBeads-1; i++) // { // interOfBeads[i].reset(new Interaction(1, nslaw, relationOfBeads)); // } // This works !! std::vector<SP::Relation > relationOfBeads(nBeads - 1); std::vector<SP::Interaction > interOfBeads(nBeads - 1); // for (unsigned int i =0; i< nBeads-1; i++) // { // relationOfBeads[i].reset(new LagrangianLinearTIR(HOfBeads,bOfBeads)); // interOfBeads[i].reset(new Interaction(1, nslaw, relationOfBeads[i])); // } // -------------------------------------- // --- Model and simulation --- // -------------------------------------- SP::Model columnOfBeads(new Model(t0, T)); // -- (1) OneStepIntegrators -- SP::MoreauJeanOSI OSI(new MoreauJeanOSI(theta)); // add the dynamical system in the non smooth dynamical system for (unsigned int i = 0; i < nBeads; i++) { columnOfBeads->nonSmoothDynamicalSystem()->insertDynamicalSystem(beads[i]); } // // link the interaction and the dynamical system // for (unsigned int i =0; i< nBeads-1; i++) // { // columnOfBeads->nonSmoothDynamicalSystem()->link(interOfBeads[i],beads[i]); // columnOfBeads->nonSmoothDynamicalSystem()->link(interOfBeads[i],beads[i+1]); // } // -- (2) Time discretisation -- SP::TimeDiscretisation t(new TimeDiscretisation(t0, h)); // -- (3) one step non smooth problem SP::OneStepNSProblem osnspb(new LCP()); // -- (4) Simulation setup with (1) (2) (3) SP::TimeStepping s(new TimeStepping(t, OSI, osnspb)); columnOfBeads->setSimulation(s); // =========================== End of model definition =========================== // ================================= Computation ================================= // --- Simulation initialization --- cout << "====> Initialisation ..." << endl << endl; columnOfBeads->initialize(); int N = ceil((T - t0) / h); // Number of time steps // --- Get the values to be plotted --- // -> saved in a matrix dataPlot unsigned int outputSize = 1 + nBeads * 4; SimpleMatrix dataPlot(N + 1, outputSize); dataPlot(0, 0) = columnOfBeads->t0(); for (unsigned int i = 0; i < nBeads; i++) { dataPlot(0, 1 + i * 2) = (beads[i]->q())->getValue(0); dataPlot(0, 2 + i * 2) = (beads[i]->velocity())->getValue(0); // dataPlot(0,3+i*4) = (beads[i]->p(1))->getValue(0); } // for (unsigned int i =1; i< nBeads; i++) // { // dataPlot(0,4+i*4) = (interOfBeads[i-1]->lambda(1))->getValue(0); // } // --- Time loop --- cout << "====> Start computation ... " << endl << endl; // ==== Simulation loop - Writing without explicit event handling ===== int k = 1; boost::progress_display show_progress(N); boost::timer time; time.restart(); int ncontact = 0 ; bool isOSNSinitialized = false; while (s->hasNextEvent()) { // Rough contact detection for (unsigned int i = 0; i < nBeads - 1; i++) { // Between first bead and plane if (abs(((beads[i])->q())->getValue(0) - R) < alert) { if (!inter) { ncontact++; // std::cout << "Number of contact = " << ncontact << std::endl; inter.reset(new Interaction(1, nslaw, relation)); columnOfBeads->nonSmoothDynamicalSystem()->link(inter, beads[0]); s->initializeInteraction(s->nextTime(), inter); if (!isOSNSinitialized) { s->initOSNS(); isOSNSinitialized = true; } assert(inter->y(0)->getValue(0) >= 0); } } // Between two beads if (abs(((beads[i + 1])->q())->getValue(0) - ((beads[i])->q())->getValue(0) - 2 * R) < alert) { //std::cout << "Alert distance for declaring contact = "; //std::cout << abs(((beads[i])->q())->getValue(0)-((beads[i+1])->q())->getValue(0)) <<std::endl; if (!interOfBeads[i].get()) { ncontact++; // std::cout << "Number of contact = " << ncontact << std::endl; relationOfBeads[i].reset(new LagrangianLinearTIR(HOfBeads, bOfBeads)); interOfBeads[i].reset(new Interaction(1, nslaw, relationOfBeads[i])); columnOfBeads->nonSmoothDynamicalSystem()->link(interOfBeads[i], beads[i], beads[i+1]); s->initializeInteraction(s->nextTime(), interOfBeads[i]); if (!isOSNSinitialized) { s->initOSNS(); isOSNSinitialized = true; } assert(interOfBeads[i]->y(0)->getValue(0) >= 0); } } } s->computeOneStep(); // --- Get values to be plotted --- dataPlot(k, 0) = s->nextTime(); for (unsigned int i = 0; i < nBeads; i++) { dataPlot(k, 1 + i * 2) = (beads[i]->q())->getValue(0); dataPlot(k, 2 + i * 2) = (beads[i]->velocity())->getValue(0); } // for (unsigned int i =1; i< nBeads; i++) // { // dataPlot(k,4+i*4) = (interOfBeads[i-1]->lambda(1))->getValue(0); // } // for (unsigned int i =1; i< nBeads; i++) // { // std::cout << (interOfBeads[i-1]->y(0))->getValue(0) << std::endl ; // } s->nextStep(); ++show_progress; k++; } cout << endl << "End of computation - Number of iterations done: " << k - 1 << endl; cout << "Computation Time " << time.elapsed() << endl; // --- Output files --- cout << "====> Output file writing ..." << endl; dataPlot.resize(k, outputSize); ioMatrix::write("result.dat", "ascii", dataPlot, "noDim"); // Comparison with a reference file SimpleMatrix dataPlotRef(dataPlot); dataPlotRef.zero(); ioMatrix::read("result.ref", "ascii", dataPlotRef); cout << "====> Comparison with reference file ..." << endl; std::cout << "Error w.r.t. reference file : " << (dataPlot - dataPlotRef).normInf() << std::endl; if ((dataPlot - dataPlotRef).normInf() > 1e-12) { std::cout << "Warning. The result is rather different from the reference file." << std::endl; return 1; } } catch (SiconosException e) { cout << e.report() << endl; } catch (...) { cout << "Exception caught in ColumnOfBeadsTS.cpp" << endl; } }
void BulletSpaceFilter::buildInteractions(double time) { if (! _dynamicCollisionsObjectsInserted) { DynamicalSystemsGraph& dsg = *(_model->nonSmoothDynamicalSystem()->dynamicalSystems()); DynamicalSystemsGraph::VIterator dsi, dsiend; std11::tie(dsi, dsiend) = dsg.vertices(); for (; dsi != dsiend; ++dsi) { CollisionObjects& collisionObjects = *ask<ForCollisionObjects>(*dsg.bundle(*dsi)); for (CollisionObjects::iterator ico = collisionObjects.begin(); ico != collisionObjects.end(); ++ico) { _collisionWorld->addCollisionObject(const_cast<btCollisionObject*>((*ico).first)); DEBUG_PRINTF("add dynamic collision object %p\n", const_cast<btCollisionObject*>((*ico).first)); } } _dynamicCollisionsObjectsInserted = true; } if (! _staticCollisionsObjectsInserted) { for(StaticObjects::iterator ic = _staticObjects->begin(); ic != _staticObjects->end(); ++ic) { _collisionWorld->addCollisionObject(const_cast<btCollisionObject*>((*ic).first)); DEBUG_PRINTF("add static collision object %p\n", const_cast<btCollisionObject*>((*ic).first)); } _staticCollisionsObjectsInserted = true; } DEBUG_PRINT("-----start build interaction\n"); // 1. perform bullet collision detection gOrphanedInteractions.clear(); _collisionWorld->performDiscreteCollisionDetection(); // 2. collect old contact points from Siconos graph std::map<btManifoldPoint*, bool> contactPoints; std::map<Interaction*, bool> activeInteractions; SP::InteractionsGraph indexSet0 = model()->nonSmoothDynamicalSystem()->topology()->indexSet(0); InteractionsGraph::VIterator ui0, ui0end, v0next; std11::tie(ui0, ui0end) = indexSet0->vertices(); for (v0next = ui0 ; ui0 != ui0end; ui0 = v0next) { ++v0next; // trick to iterate on a dynamic bgl graph SP::Interaction inter0 = indexSet0->bundle(*ui0); if (gOrphanedInteractions.find(&*inter0) != gOrphanedInteractions.end()) { model()->nonSmoothDynamicalSystem()->removeInteraction(inter0); } else { SP::btManifoldPoint cp = ask<ForContactPoint>(*(inter0->relation())); if(cp) { DEBUG_PRINTF("Contact point in interaction : %p\n", &*cp); contactPoints[&*cp] = false; } } } unsigned int numManifolds = _collisionWorld->getDispatcher()->getNumManifolds(); DEBUG_PRINTF("number of manifolds : %d\n", numManifolds); for (unsigned int i = 0; i < numManifolds; ++i) { btPersistentManifold* contactManifold = _collisionWorld->getDispatcher()->getManifoldByIndexInternal(i); DEBUG_PRINTF("processing manifold %d : %p\n", i, contactManifold); const btCollisionObject* obA = contactManifold->getBody0(); const btCollisionObject* obB = contactManifold->getBody1(); DEBUG_PRINTF("object A : %p, object B: %p\n", obA, obB); // contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform()); unsigned int numContacts = contactManifold->getNumContacts(); if ( (obA->getUserPointer() && obA->getUserPointer() != obB->getUserPointer()) || (obB->getUserPointer() && obA->getUserPointer() != obB->getUserPointer()) ) { for (unsigned int z = 0; z < numContacts; ++z) { SP::btManifoldPoint cpoint(createSPtrbtManifoldPoint(contactManifold->getContactPoint(z))); DEBUG_PRINTF("manifold %d, contact %d, &contact %p, lifetime %d\n", i, z, &*cpoint, cpoint->getLifeTime()); // should no be mixed with something else that use UserPointer! SP::BulletDS dsa; SP::BulletDS dsb; unsigned long int gid1, gid2; if(obA->getUserPointer()) { dsa = static_cast<BulletDS*>(obA->getUserPointer())->shared_ptr(); assert(dsa->collisionObjects()->find(contactManifold->getBody0()) != dsa->collisionObjects()->end()); gid1 = boost::get<2>((*((*dsa->collisionObjects()).find(obA))).second); } else { gid1 = (*_staticObjects->find(obA)).second.second; } SP::NonSmoothLaw nslaw; if (obB->getUserPointer()) { dsb = static_cast<BulletDS*>(obB->getUserPointer())->shared_ptr(); assert(dsb->collisionObjects()->find(obB) != dsb->collisionObjects()->end()); gid2 = boost::get<2>((*((*dsb->collisionObjects()).find(obB))).second); } else { gid2 = (*_staticObjects->find(obB)).second.second; } DEBUG_PRINTF("collision between group %ld and %ld\n", gid1, gid2); nslaw = (*_nslaws)(gid1, gid2); if (!nslaw) { RuntimeException::selfThrow( (boost::format("Cannot find nslaw for collision between group %1% and %2%") % gid1 % gid2).str()); } assert(nslaw); std::map<btManifoldPoint*, bool>::iterator itc; itc = contactPoints.find(&*cpoint); DEBUG_EXPR(if (itc == contactPoints.end()) { DEBUG_PRINT("contact point not found\n"); for(std::map<btManifoldPoint*, bool>::iterator itd=contactPoints.begin(); itd != contactPoints.end(); ++itd) { DEBUG_PRINTF("-->%p != %p\n", &*cpoint, &*(*itd).first); } }); if (itc == contactPoints.end() || !cpoint->m_userPersistentData) { /* new interaction */ SP::Interaction inter; if (nslaw->size() == 3) { SP::BulletR rel(new BulletR(cpoint, createSPtrbtPersistentManifold(*contactManifold))); inter.reset(new Interaction(3, nslaw, rel, 4 * i + z)); } else { if (nslaw->size() == 1) { SP::BulletFrom1DLocalFrameR rel(new BulletFrom1DLocalFrameR(cpoint)); inter.reset(new Interaction(1, nslaw, rel, 4 * i + z)); } } if (obB->getUserPointer()) { SP::BulletDS dsb(static_cast<BulletDS*>(obB->getUserPointer())->shared_ptr()); if (dsa != dsb) { DEBUG_PRINTF("LINK obA:%p obB:%p inter:%p\n", obA, obB, &*inter); assert(inter); cpoint->m_userPersistentData = &*inter; link(inter, dsa, dsb); } /* else collision shapes belong to the same object do nothing */ } else { DEBUG_PRINTF("LINK obA:%p inter :%p\n", obA, &*inter); assert(inter); cpoint->m_userPersistentData = &*inter; link(inter, dsa); } } if (cpoint->m_userPersistentData) { activeInteractions[static_cast<Interaction *>(cpoint->m_userPersistentData)] = true; DEBUG_PRINTF("Interaction %p = true\n", static_cast<Interaction *>(cpoint->m_userPersistentData)); DEBUG_PRINTF("cpoint %p = true\n", &*cpoint); } else { assert(false); DEBUG_PRINT("cpoint->m_userPersistentData is empty\n"); } contactPoints[&*cpoint] = true; DEBUG_PRINTF("cpoint %p = true\n", &*cpoint); } } }