// This file is part of the brownmove simulation package // // (C) 2003 - 2009 Tihamer Geyer // tihamer.geyer@bioinformatik.uni-saarland.de // // Project Homepage http://service.bioinformatik.uni-saarland.de/brownmove #include "wall.h" #include "molecule.h" namespace brown{ Wall::Wall(string name, long int num) :InteractingBody(name, num) { myWallType = REFLECTIVE_WALL; // most basic type doublevec_set(myNormal, 1.0, 0.0, 0.0); // normal off the y-z-plane doublevec_set(myYAxis, 0.0, 1.0, 0.0); doublevec_set(myZAxis, 0.0, 0.0, 1.0); doublevec_set(periodicDX, 0.0); myCup = NULL; myAcceptor = NULL; myInjector = NULL; } Wall::Wall(const Wall &other) :InteractingBody(other) { // set ID, use same index number (currently okay for walls, // they can be discerend by their constant position in the Cup's vector) id.mclass = other.id.mclass; id.mnumber = other.id.mnumber; myWallType = other.myWallType; myCup = other.myCup; doublevec_set(myNormal, other.myNormal); doublevec_set(myYAxis, other.myYAxis); doublevec_set(myZAxis, other.myZAxis); doublevec_set(periodicDX, other.periodicDX); // create a new copy of these, too myAcceptor = NULL; myInjector = NULL; if(other.myAcceptor) { myAcceptor = new MoleculeAcceptor(*(other.myAcceptor)); setAcceptor(myAcceptor); } if(other.myInjector) { myInjector = new MoleculeInjector(*(other.myInjector)); setInjector(myInjector); } // now move to the same position as the template fullPosition p; doublevec_set(p.pos, other.getPosition()); rotation_set(p.rot, other.getRotation()); teleport(p); // teleport notofies all enclosed shapes } // As walls are usually not deleted during a simulation, we leave all the // garbage behind for the operating system to clean up Wall::~Wall() { } //! teleport sets the wall to a given place. void Wall::teleport(const fullPosition &p) { InteractingBody::teleport(p); // handles all Gestalten // rotate wall normal (also used by injector and acceptor) doublevec_set(myNormal, 1.0, 0.0, 0.0); doublevec_rotate(myNormal, p.rot); doublevec_set(myYAxis, 0.0, 1.0, 0.0); doublevec_rotate(myYAxis, p.rot); doublevec_set(myZAxis, 0.0, 0.0, 1.0); doublevec_rotate(myZAxis, p.rot); } // Checks for and handles the collision/interaction between molecules and walls // Returns true if molecule was accepted by the Acceptor bool Wall::talkToMolecule(Molecule *m, bool isPeriodic[3], const doublevec &cellSize) { position dr; double height; position theCM; Gestalt *gst; std::vector *gstV; std::vector::iterator it1; // std::cerr << "Wall::talkToMolecule: begin" << std::endl; // position of the CM relative to the wall doublevec_set(theCM, m->getCenterOfMass()); doublevec_sub(theCM, getPosition()); height = doublevec_scalprod(theCM, getNormal()); // if there is an acceptor, let it check if(myAcceptor && (height < 0.0)) { if(myAcceptor->accept(m, theCM)) { // accept determines the projections in the y- and z-directions of the wall return(true); } } // Not accepted (wrong type or outside mask) => check for interactions // If there is at least one Gestalt on the wall, check for Gestalten on the protein and let them interact gstV = m->getGestalten(); // we need the gestalt vector of the molecule in any of the following cases // Question: what will happen when the molecule does not have any Gestalt? if(size() > 0) { // For each gestalt of the molecule... for(it1 = gstV->begin(); it1 != gstV->end(); it1++) { fullForce myDummyForce; // will be discarded in the end, as wall cannot move for(std::vector::iterator myIt = getGestalten()->begin(); myIt != getGestalten()->end(); myIt++) { doublevec_set(myDummyForce.f, 0.0); doublevec_set(myDummyForce.t, 0.0); it1->calculateImpact(myDummyForce, &(*myIt), false, isPeriodic, cellSize); } } } // Default if everything else fails: // Reflective wall => NEW: bounce complete molecule back into the simulation // (was: handle each shape independently => acceptor did not get CM behind wall) // But before that, check: // Periodic wall => displace complete molecule by given vector (check theCM) else { position shift_pos; rotation shift_rot; // std::cerr << "Wall::talkToMolecule: reflective oder periodic" << std::endl; rotation_set(shift_rot, 0.0, 1.0, 0.0, 0.0); // keep orientation as is if(height < 0.0) { // tell each gestalt how far to go // periodic walls if(getWallType() == PERIODIC_WALL) { doublevec_set(shift_pos, periodicDX); // periodicDX is a vector!!! } // last resort: reflecting wall as the most basic wall type else // i.e., WallType == REFLECTIVE_WALL { doublevec_set(shift_pos, getNormal()); doublevec_mult(shift_pos, -2.0*height); } for(it1 = gstV->begin(); it1 != gstV->end(); it1++) { it1->move(shift_pos, shift_rot); } } } // std::cerr << "Wall::talkToMolecule: done" << std::endl; return(false); // molecule was not accepted } void Wall::insertNewMolecules() { if(myInjector) { myInjector->insert(); } } }