Changes in src/Tesselation/boundary.cpp [052c10:2b7375]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tesselation/boundary.cpp
r052c10 r2b7375 183 183 LineMap LinesOnBoundary; 184 184 TriangleMap TrianglesOnBoundary; 185 Vector *MolCenter = mol->DetermineCenterOfAll();185 Vector MolCenter = mol->DetermineCenterOfAll(); 186 186 Vector helper; 187 187 BoundariesTestPair BoundaryTestPair; … … 207 207 // Boundaries stores non-const TesselPoint ref, hence we need iterator here 208 208 for (molecule::iterator iter = mol->begin(); iter != mol->end(); ++iter) { 209 ProjectedVector = (*iter)->getPosition() - ( *MolCenter);209 ProjectedVector = (*iter)->getPosition() - (MolCenter); 210 210 ProjectedVector.ProjectOntoPlane(AxisVector); 211 211 … … 233 233 LOG(2, "Keeping new vector due to larger projected distance " << ProjectedVectorNorm << "."); 234 234 } else if (fabs(ProjectedVectorNorm - BoundaryTestPair.first->second.first) < MYEPSILON) { 235 helper = (*iter)->getPosition() - ( *MolCenter);235 helper = (*iter)->getPosition() - (MolCenter); 236 236 const double oldhelperNorm = helper.NormSquared(); 237 helper = BoundaryTestPair.first->second.second->getPosition() - ( *MolCenter);237 helper = BoundaryTestPair.first->second.second->getPosition() - (MolCenter); 238 238 if (helper.NormSquared() < oldhelperNorm) { 239 239 BoundaryTestPair.first->second.second = (*iter); … … 289 289 { 290 290 Vector SideA, SideB, SideC, SideH; 291 SideA = left->second.second->getPosition() - ( *MolCenter);291 SideA = left->second.second->getPosition() - (MolCenter); 292 292 SideA.ProjectOntoPlane(AxisVector); 293 293 // LOG(1, "SideA: " << SideA); 294 294 295 SideB = right->second.second->getPosition() -( *MolCenter);295 SideB = right->second.second->getPosition() -(MolCenter); 296 296 SideB.ProjectOntoPlane(AxisVector); 297 297 // LOG(1, "SideB: " << SideB); … … 301 301 // LOG(1, "SideC: " << SideC); 302 302 303 SideH = runner->second.second->getPosition() -( *MolCenter);303 SideH = runner->second.second->getPosition() -(MolCenter); 304 304 SideH.ProjectOntoPlane(AxisVector); 305 305 // LOG(1, "SideH: " << SideH); … … 329 329 } while (flag); 330 330 } 331 delete(MolCenter);332 331 return BoundaryPoints; 333 332 }; … … 655 654 }; 656 655 657 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density.658 * We get cluster volume by Tesselation::getVolumeOfConvexEnvelope() and its diameters by GetDiametersOfCluster()659 * TODO: Here, we need a VolumeOfGeneralEnvelope (i.e. non-convex one)660 * \param *out output stream for debugging661 * \param *configuration needed for path to store convex envelope file662 * \param *mol molecule structure representing the cluster663 * \param *&TesselStruct Tesselation structure with triangles on return664 * \param ClusterVolume guesstimated cluster volume, if equal 0 we used Tesselation::getVolumeOfConvexEnvelope() instead.665 * \param celldensity desired average density in final cell666 */667 void PrepareClustersinWater(config *configuration, molecule *mol, double ClusterVolume, double celldensity)668 {669 //Info FunctionInfo(__func__);670 bool IsAngstroem = true;671 double *GreatestDiameter = NULL;672 Boundaries *BoundaryPoints = NULL;673 class Tesselation *TesselStruct = NULL;674 Vector BoxLengths;675 int repetition[NDIM] = { 1, 1, 1 };676 int TotalNoClusters = 1;677 double totalmass = 0.;678 double clustervolume = 0.;679 double cellvolume = 0.;680 681 // transform to PAS by Action682 Vector MainAxis(0.,0.,1.);683 mol->RotateToPrincipalAxisSystem(MainAxis);684 685 IsAngstroem = configuration->GetIsAngstroem();686 BoundaryPoints = GetBoundaryPoints(mol, TesselStruct);687 GreatestDiameter = GetDiametersOfCluster(BoundaryPoints, mol, TesselStruct, IsAngstroem);688 PointCloudAdaptor< molecule > cloud(mol, mol->name);689 LinkedCell_deprecated *LCList = new LinkedCell_deprecated(cloud, 10.);690 FindConvexBorder(mol, BoundaryPoints, TesselStruct, (const LinkedCell_deprecated *&)LCList, NULL);691 delete (LCList);692 delete[] BoundaryPoints;693 694 695 // some preparations beforehand696 if (ClusterVolume == 0)697 clustervolume = TesselStruct->getVolumeOfConvexEnvelope(configuration->GetIsAngstroem());698 else699 clustervolume = ClusterVolume;700 701 delete TesselStruct;702 703 for (int i = 0; i < NDIM; i++)704 TotalNoClusters *= repetition[i];705 706 // sum up the atomic masses707 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {708 totalmass += (*iter)->getType()->getMass();709 }710 LOG(0, "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit.");711 LOG(0, "RESULT: The average density is " << setprecision(10) << totalmass / clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3.");712 713 // solve cubic polynomial714 LOG(1, "Solving equidistant suspension in water problem ...");715 if (IsAngstroem)716 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass / clustervolume)) / (celldensity - 1);717 else718 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass / clustervolume)) / (celldensity - 1);719 LOG(1, "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3.");720 721 double minimumvolume = TotalNoClusters * (GreatestDiameter[0] * GreatestDiameter[1] * GreatestDiameter[2]);722 LOG(1, "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3.");723 if (minimumvolume > cellvolume) {724 ELOG(1, "the containing box already has a greater volume than the envisaged cell volume!");725 LOG(0, "Setting Box dimensions to minimum possible, the greatest diameters.");726 for (int i = 0; i < NDIM; i++)727 BoxLengths[i] = GreatestDiameter[i];728 mol->CenterEdge(&BoxLengths);729 } else {730 BoxLengths[0] = (repetition[0] * GreatestDiameter[0] + repetition[1] * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);731 BoxLengths[1] = (repetition[0] * repetition[1] * GreatestDiameter[0] * GreatestDiameter[1] + repetition[0] * repetition[2] * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1] * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);732 BoxLengths[2] = minimumvolume - cellvolume;733 double x0 = 0.;734 double x1 = 0.;735 double x2 = 0.;736 if (gsl_poly_solve_cubic(BoxLengths[0], BoxLengths[1], BoxLengths[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return737 LOG(0, "RESULT: The resulting spacing is: " << x0 << " .");738 else {739 LOG(0, "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " .");740 x0 = x2; // sorted in ascending order741 }742 743 cellvolume = 1.;744 for (int i = 0; i < NDIM; i++) {745 BoxLengths[i] = repetition[i] * (x0 + GreatestDiameter[i]);746 cellvolume *= BoxLengths[i];747 }748 749 // set new box dimensions750 LOG(0, "Translating to box with these boundaries.");751 mol->SetBoxDimension(&BoxLengths);752 mol->CenterInBox();753 }754 delete[] GreatestDiameter;755 // update Box of atoms by boundary756 mol->SetBoxDimension(&BoxLengths);757 LOG(0, "RESULT: The resulting cell dimensions are: " << BoxLengths[0] << " and " << BoxLengths[1] << " and " << BoxLengths[2] << " with total volume of " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3.");758 };759 760 761 /** Fills the empty space around other molecules' surface of the simulation box with a filler.762 * \param *out output stream for debugging763 * \param *List list of molecules already present in box764 * \param *TesselStruct contains tesselated surface765 * \param *filler molecule which the box is to be filled with766 * \param configuration contains box dimensions767 * \param MaxDistance fills in molecules only up to this distance (set to -1 if whole of the domain)768 * \param distance[NDIM] distance between filling molecules in each direction769 * \param boundary length of boundary zone between molecule and filling mollecules770 * \param epsilon distance to surface which is not filled771 * \param RandAtomDisplacement maximum distance for random displacement per atom772 * \param RandMolDisplacement maximum distance for random displacement per filler molecule773 * \param DoRandomRotation true - do random rotiations, false - don't774 */775 void FillBoxWithMolecule(MoleculeListClass *List, molecule *filler, config &configuration, const double MaxDistance, const double distance[NDIM], const double boundary, const double RandomAtomDisplacement, const double RandomMolDisplacement, const bool DoRandomRotation)776 {777 //Info FunctionInfo(__func__);778 molecule *Filling = World::getInstance().createMolecule();779 Vector CurrentPosition;780 int N[NDIM];781 int n[NDIM];782 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();783 RealSpaceMatrix Rotations;784 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();785 Vector AtomTranslations;786 Vector FillerTranslations;787 Vector FillerDistance;788 Vector Inserter;789 double FillIt = false;790 bond::ptr Binder;791 double phi[NDIM];792 map<molecule *, Tesselation *> TesselStruct;793 map<molecule *, LinkedCell_deprecated *> LCList;794 795 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++)796 if ((*ListRunner)->getAtomCount() > 0) {797 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");798 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);799 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 10.); // get linked cell list800 LOG(1, "Pre-creating tesselation for molecule " << *ListRunner << ".");801 TesselStruct[(*ListRunner)] = NULL;802 FindNonConvexBorder((*ListRunner), TesselStruct[(*ListRunner)], (const LinkedCell_deprecated *&)LCList[(*ListRunner)], 5., NULL);803 }804 805 // Center filler at origin806 filler->CenterEdge(&Inserter);807 const int FillerCount = filler->getAtomCount();808 LOG(2, "INFO: Filler molecule has the following bonds:");809 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {810 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();811 for(BondList::const_iterator BondRunner = ListOfBonds.begin();812 BondRunner != ListOfBonds.end();813 ++BondRunner) {814 if ((*BondRunner)->leftatom == *AtomRunner)815 LOG(2, " " << *(*BondRunner));816 }817 }818 819 atom * CopyAtoms[FillerCount];820 821 // calculate filler grid in [0,1]^3822 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);823 for(int i=0;i<NDIM;i++)824 N[i] = (int) ceil(1./FillerDistance[i]);825 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");826 827 // initialize seed of random number generator to current time828 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();829 const double rng_min = random.min();830 const double rng_max = random.max();831 //srand ( time(NULL) );832 833 // go over [0,1]^3 filler grid834 for (n[0] = 0; n[0] < N[0]; n[0]++)835 for (n[1] = 0; n[1] < N[1]; n[1]++)836 for (n[2] = 0; n[2] < N[2]; n[2]++) {837 // calculate position of current grid vector in untransformed box838 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);839 // create molecule random translation vector ...840 for (int i=0;i<NDIM;i++)841 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);842 LOG(2, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");843 844 // go through all atoms845 for (int i=0;i<FillerCount;i++)846 CopyAtoms[i] = NULL;847 848 // have same rotation angles for all molecule's atoms849 if (DoRandomRotation)850 for (int i=0;i<NDIM;i++)851 phi[i] = (random()/(rng_max-rng_min))*(2.*M_PI);852 853 // atom::clone is not const member function, hence we need iterator here854 for(molecule::iterator iter = filler->begin(); iter !=filler->end();++iter){855 856 // create atomic random translation vector ...857 for (int i=0;i<NDIM;i++)858 AtomTranslations[i] = RandomAtomDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);859 860 // ... and rotation matrix861 if (DoRandomRotation) {862 Rotations.set(0,0, cos(phi[0]) *cos(phi[2]) + (sin(phi[0])*sin(phi[1])*sin(phi[2])));863 Rotations.set(0,1, sin(phi[0]) *cos(phi[2]) - (cos(phi[0])*sin(phi[1])*sin(phi[2])));864 Rotations.set(0,2, cos(phi[1])*sin(phi[2]) );865 Rotations.set(1,0, -sin(phi[0])*cos(phi[1]) );866 Rotations.set(1,1, cos(phi[0])*cos(phi[1]) );867 Rotations.set(1,2, sin(phi[1]) );868 Rotations.set(2,0, -cos(phi[0]) *sin(phi[2]) + (sin(phi[0])*sin(phi[1])*cos(phi[2])));869 Rotations.set(2,1, -sin(phi[0]) *sin(phi[2]) - (cos(phi[0])*sin(phi[1])*cos(phi[2])));870 Rotations.set(2,2, cos(phi[1])*cos(phi[2]) );871 }872 873 // ... and put at new position874 Inserter = (*iter)->getPosition();875 if (DoRandomRotation)876 Inserter *= Rotations;877 Inserter += AtomTranslations + FillerTranslations + CurrentPosition;878 879 // check whether inserter is inside box880 Inserter *= MInverse;881 FillIt = true;882 for (int i=0;i<NDIM;i++)883 FillIt = FillIt && (Inserter[i] >= -MYEPSILON) && ((Inserter[i]-1.) <= MYEPSILON);884 Inserter *= M;885 886 // Check whether point is in- or outside887 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {888 // get linked cell list889 if (TesselStruct[(*ListRunner)] != NULL) {890 const double distance = (TesselStruct[(*ListRunner)]->GetDistanceToSurface(Inserter, LCList[(*ListRunner)]));891 FillIt = FillIt && (distance > boundary) && ((MaxDistance < 0) || (MaxDistance > distance));892 }893 }894 // insert into Filling895 if (FillIt) {896 LOG(1, "INFO: Position at " << Inserter << " is outer point.");897 // copy atom ...898 CopyAtoms[(*iter)->getNr()] = (*iter)->clone();899 (*CopyAtoms[(*iter)->getNr()]).setPosition(Inserter);900 Filling->AddAtom(CopyAtoms[(*iter)->getNr()]);901 LOG(1, "Filling atom " << **iter << ", translated to " << AtomTranslations << ", at final position is " << (CopyAtoms[(*iter)->getNr()]->getPosition()) << ".");902 } else {903 LOG(1, "INFO: Position at " << Inserter << " is inner point, within boundary or outside of MaxDistance.");904 CopyAtoms[(*iter)->getNr()] = NULL;905 continue;906 }907 }908 // go through all bonds and add as well909 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {910 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();911 for(BondList::const_iterator BondRunner = ListOfBonds.begin();912 BondRunner != ListOfBonds.end();913 ++BondRunner)914 if ((*BondRunner)->leftatom == *AtomRunner) {915 Binder = (*BondRunner);916 if ((CopyAtoms[Binder->leftatom->getNr()] != NULL) && (CopyAtoms[Binder->rightatom->getNr()] != NULL)) {917 LOG(3, "Adding Bond between " << *CopyAtoms[Binder->leftatom->getNr()] << " and " << *CopyAtoms[Binder->rightatom->getNr()]<< ".");918 Filling->AddBond(CopyAtoms[Binder->leftatom->getNr()], CopyAtoms[Binder->rightatom->getNr()], Binder->getDegree());919 }920 }921 }922 }923 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {924 delete LCList[*ListRunner];925 delete TesselStruct[(*ListRunner)];926 }927 };928 929 /** Rotates given molecule \a Filling and moves its atoms according to given930 * \a RandomAtomDisplacement.931 *932 * Note that for rotation to be sensible, the molecule should be centered at933 * the origin. This is not done here!934 *935 * \param &Filling molecule whose atoms to displace936 * \param RandomAtomDisplacement magnitude of random displacement937 * \param &Rotations 3D rotation matrix (or unity if no rotation desired)938 */939 void RandomizeMoleculePositions(940 molecule *&Filling,941 double RandomAtomDisplacement,942 RealSpaceMatrix &Rotations,943 RandomNumberGenerator &random944 )945 {946 const double rng_min = random.min();947 const double rng_max = random.max();948 949 Vector AtomTranslations;950 for(molecule::iterator miter = Filling->begin(); miter != Filling->end(); ++miter) {951 Vector temp = (*miter)->getPosition();952 temp *= Rotations;953 (*miter)->setPosition(temp);954 // create atomic random translation vector ...955 for (int i=0;i<NDIM;i++)956 AtomTranslations[i] = RandomAtomDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);957 (*miter)->setPosition((*miter)->getPosition() + AtomTranslations);958 }959 }960 961 /** Removes all atoms of a molecule outside.962 *963 * If the molecule is empty, it is removed as well.964 *965 * @param Filling molecule whose atoms to check, removed if eventually left966 * empty.967 * @return true - atoms had to be removed, false - no atoms have been removed968 */969 bool RemoveAtomsOutsideDomain(molecule *&Filling)970 {971 bool status = false;972 Box &Domain = World::getInstance().getDomain();973 // check if all is still inside domain974 for(molecule::iterator miter = Filling->begin(); miter != Filling->end(); ) {975 // check whether each atom is inside box976 if (!Domain.isInside((*miter)->getPosition())) {977 status = true;978 atom *Walker = *miter;979 ++miter;980 World::getInstance().destroyAtom(Walker);981 } else {982 ++miter;983 }984 }985 if (Filling->empty()) {986 LOG(0, "Removing molecule " << Filling->getName() << ", all atoms have been removed.");987 World::getInstance().destroyMolecule(Filling);988 Filling = NULL;989 }990 return status;991 }992 993 /** Checks whether there are no atoms inside a sphere around \a CurrentPosition994 * except those atoms present in \a *filler.995 * If filler is NULL, then we just call LinkedCell_deprecated::GetPointsInsideSphere() and996 * check whether the return list is empty.997 * @param *filler998 * @param boundary999 * @param CurrentPosition1000 */1001 bool isSpaceAroundPointVoid(1002 LinkedCell_deprecated *LC,1003 molecule *filler,1004 const double boundary,1005 Vector &CurrentPosition)1006 {1007 size_t compareTo = 0;1008 TesselPointSTLList* liste = LC->GetPointsInsideSphere(boundary == 0. ? MYEPSILON : boundary, &CurrentPosition);1009 if (filler != NULL) {1010 for (TesselPointSTLList::const_iterator iter = liste->begin();1011 iter != liste->end();1012 ++iter) {1013 for (molecule::iterator miter = filler->begin();1014 miter != filler->end();1015 ++miter) {1016 if (*iter == *miter)1017 ++compareTo;1018 }1019 }1020 }1021 const bool result = (liste->size() == compareTo);1022 if (!result) {1023 LOG(0, "Skipping because of the following atoms:");1024 for (TesselPointSTLList::const_iterator iter = liste->begin();1025 iter != liste->end();1026 ++iter) {1027 LOG(0, **iter);1028 }1029 }1030 delete liste;1031 return result;1032 }1033 1034 /** Sets given 3x3 matrix to a random rotation matrix.1035 *1036 * @param a matrix to set1037 */1038 inline void setRandomRotation(RealSpaceMatrix &a)1039 {1040 double phi[NDIM];1041 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1042 const double rng_min = random.min();1043 const double rng_max = random.max();1044 1045 for (int i=0;i<NDIM;i++) {1046 phi[i] = (random()/(rng_max-rng_min))*(2.*M_PI);1047 LOG(4, "DEBUG: Random angle is " << phi[i] << ".");1048 }1049 1050 a.setRotation(phi);1051 }1052 1053 /** Fills the empty space of the simulation box with water.1054 * \param *filler molecule which the box is to be filled with1055 * \param configuration contains box dimensions1056 * \param distance[NDIM] distance between filling molecules in each direction1057 * \param boundary length of boundary zone between molecule and filling molecules1058 * \param RandAtomDisplacement maximum distance for random displacement per atom1059 * \param RandMolDisplacement maximum distance for random displacement per filler molecule1060 * \param MinDistance minimum distance to boundary of domain and present molecules1061 * \param DoRandomRotation true - do random rotations, false - don't1062 */1063 void FillVoidWithMolecule(1064 molecule *&filler,1065 config &configuration,1066 const double distance[NDIM],1067 const double boundary,1068 const double RandomAtomDisplacement,1069 const double RandomMolDisplacement,1070 const double MinDistance,1071 const bool DoRandomRotation1072 )1073 {1074 //Info FunctionInfo(__func__);1075 molecule *Filling = NULL;1076 Vector CurrentPosition;1077 int N[NDIM];1078 int n[NDIM];1079 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();1080 RealSpaceMatrix Rotations;1081 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();1082 Vector FillerTranslations;1083 Vector FillerDistance;1084 Vector Inserter;1085 double FillIt = false;1086 Vector firstInserter;1087 bool firstInsertion = true;1088 const Box &Domain = World::getInstance().getDomain();1089 map<molecule *, LinkedCell_deprecated *> LCList;1090 std::vector<molecule *> List = World::getInstance().getAllMolecules();1091 MoleculeListClass *MolList = World::getInstance().getMolecules();1092 1093 for (std::vector<molecule *>::iterator ListRunner = List.begin(); ListRunner != List.end(); ListRunner++)1094 if ((*ListRunner)->getAtomCount() > 0) {1095 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");1096 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);1097 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 10.); // get linked cell list1098 }1099 1100 // Center filler at its center of gravity1101 Vector *gravity = filler->DetermineCenterOfGravity();1102 filler->CenterAtVector(gravity);1103 delete gravity;1104 //const int FillerCount = filler->getAtomCount();1105 LOG(2, "INFO: Filler molecule has the following bonds:");1106 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {1107 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();1108 for(BondList::const_iterator BondRunner = ListOfBonds.begin();1109 BondRunner != ListOfBonds.end();1110 ++BondRunner)1111 if ((*BondRunner)->leftatom == *AtomRunner)1112 LOG(2, " " << *(*BondRunner));1113 }1114 1115 // calculate filler grid in [0,1]^31116 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);1117 for(int i=0;i<NDIM;i++)1118 N[i] = (int) ceil(1./FillerDistance[i]);1119 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");1120 1121 // initialize seed of random number generator to current time1122 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1123 const double rng_min = random.min();1124 const double rng_max = random.max();1125 //srand ( time(NULL) );1126 1127 // go over [0,1]^3 filler grid1128 for (n[0] = 0; n[0] < N[0]; n[0]++)1129 for (n[1] = 0; n[1] < N[1]; n[1]++)1130 for (n[2] = 0; n[2] < N[2]; n[2]++) {1131 // calculate position of current grid vector in untransformed box1132 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);1133 // create molecule random translation vector ...1134 for (int i=0;i<NDIM;i++) // have the random values [-1,1]*RandomMolDisplacement1135 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);1136 LOG(2, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");1137 1138 // ... and rotation matrix1139 if (DoRandomRotation)1140 setRandomRotation(Rotations);1141 else1142 Rotations.setIdentity();1143 1144 1145 // Check whether there is anything too close by and whether atom is outside of domain1146 FillIt = true;1147 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); ListRunner != LCList.end(); ++ListRunner) {1148 FillIt = FillIt && isSpaceAroundPointVoid(1149 ListRunner->second,1150 (firstInsertion ? filler : NULL),1151 boundary,1152 CurrentPosition);1153 FillIt = FillIt && (Domain.isValid(CurrentPosition))1154 && ((Domain.DistanceToBoundary(CurrentPosition) - MinDistance) > -MYEPSILON);1155 if (!FillIt)1156 break;1157 }1158 1159 // insert into Filling1160 if (FillIt) {1161 Inserter = CurrentPosition + FillerTranslations;1162 LOG(1, "INFO: Position at " << Inserter << " is void point.");1163 // fill!1164 Filling = filler->CopyMolecule();1165 RandomizeMoleculePositions(Filling, RandomAtomDisplacement, Rotations, random);1166 // translation1167 Filling->Translate(&Inserter);1168 // remove out-of-bounds atoms1169 const bool status = RemoveAtomsOutsideDomain(Filling);1170 if ((firstInsertion) && (!status)) { // no atom has been removed1171 // remove copied atoms and molecule again1172 Filling->removeAtomsinMolecule();1173 World::getInstance().destroyMolecule(Filling);1174 // and mark is final filler position1175 Filling = filler;1176 firstInsertion = false;1177 firstInserter = Inserter;1178 } else {1179 // TODO: Remove when World has no MoleculeListClass anymore1180 if (Filling)1181 MolList->insert(Filling);1182 }1183 } else {1184 LOG(1, "INFO: Position at " << Inserter << " is non-void point, within boundary or outside of MaxDistance.");1185 continue;1186 }1187 }1188 1189 // have we inserted any molecules?1190 if (firstInsertion) {1191 // If not remove filler1192 for(molecule::iterator miter = filler->begin(); !filler->empty(); miter = filler->begin()) {1193 atom *Walker = *miter;1194 World::getInstance().destroyAtom(Walker);1195 }1196 World::getInstance().destroyMolecule(filler);1197 } else {1198 // otherwise translate and randomize to final position1199 if (DoRandomRotation)1200 setRandomRotation(Rotations);1201 else1202 Rotations.setIdentity();1203 RandomizeMoleculePositions(filler, RandomAtomDisplacement, Rotations, random);1204 // translation1205 filler->Translate(&firstInserter);1206 // remove out-of-bounds atoms1207 RemoveAtomsOutsideDomain(filler);1208 }1209 1210 LOG(0, MolList->ListOfMolecules.size() << " molecules have been inserted.");1211 1212 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); !LCList.empty(); ListRunner = LCList.begin()) {1213 delete ListRunner->second;1214 LCList.erase(ListRunner);1215 }1216 };1217 1218 1219 /** Fills the empty space around other molecules' surface of the simulation box with a filler.1220 *1221 * Note that we use \a FindNonConvexBorder to determine the surface of the found molecules.1222 * There, we use a radius of twice the given \a boundary.1223 *1224 * \param *out output stream for debugging1225 * \param *List list of molecules already present in box1226 * \param *TesselStruct contains tesselated surface1227 * \param *filler molecule which the box is to be filled with1228 * \param configuration contains box dimensions1229 * \param MaxSurfaceDistance fills in molecules only up to this distance (set to -1 if whole of the domain)1230 * \param distance[NDIM] distance between filling molecules in each direction1231 * \param boundary length of boundary zone between molecule and filling molecules1232 * \param MinDistance distance to boundary of domain which is not filled1233 * \param RandAtomDisplacement maximum distance for random displacement per atom1234 * \param RandMolDisplacement maximum distance for random displacement per filler molecule1235 * \param DoRandomRotation true - do random rotations, false - don't1236 */1237 void FillBoxWithMolecule(1238 MoleculeListClass *MolList,1239 molecule *filler,1240 config &configuration,1241 const double MaxSurfaceDistance,1242 const double distance[NDIM],1243 const double boundary,1244 const double MinDistance,1245 const double RandomAtomDisplacement,1246 const double RandomMolDisplacement,1247 const bool DoRandomRotation)1248 {1249 //Info FunctionInfo(__func__);1250 molecule *Filling = NULL;1251 Vector CurrentPosition;1252 int N[NDIM];1253 int n[NDIM];1254 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();1255 RealSpaceMatrix Rotations;1256 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();1257 Vector FillerTranslations;1258 Vector FillerDistance;1259 Vector Inserter;1260 double FillIt = false;1261 Vector firstInserter;1262 bool firstInsertion = true;1263 const Box &Domain = World::getInstance().getDomain();1264 map<molecule *, LinkedCell_deprecated *> LCList;1265 std::vector<molecule *> List = World::getInstance().getAllMolecules();1266 map<molecule *, Tesselation *> TesselStruct;1267 1268 for (MoleculeList::iterator ListRunner = MolList->ListOfMolecules.begin(); ListRunner != MolList->ListOfMolecules.end(); ListRunner++)1269 if ((*ListRunner)->getAtomCount() > 0) {1270 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");1271 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);1272 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 4.*boundary); // get linked cell list1273 LOG(1, "Pre-creating tesselation for molecule " << *ListRunner << ".");1274 TesselStruct[(*ListRunner)] = NULL;1275 FindNonConvexBorder((*ListRunner), TesselStruct[(*ListRunner)], (const LinkedCell_deprecated *&)LCList[(*ListRunner)], 2.*boundary, NULL);1276 }1277 1278 // Center filler at origin1279 filler->CenterEdge(&Inserter);1280 // const int FillerCount = filler->getAtomCount();1281 LOG(2, "INFO: Filler molecule has the following bonds:");1282 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {1283 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();1284 for(BondList::const_iterator BondRunner = ListOfBonds.begin();1285 BondRunner != ListOfBonds.end();1286 ++BondRunner) {1287 if ((*BondRunner)->leftatom == *AtomRunner)1288 LOG(2, " " << *(*BondRunner));1289 }1290 }1291 1292 // atom * CopyAtoms[FillerCount];1293 1294 setVerbosity(4);1295 1296 // calculate filler grid in [0,1]^31297 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);1298 for(int i=0;i<NDIM;i++)1299 N[i] = (int) ceil(1./FillerDistance[i]);1300 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");1301 1302 // initialize seed of random number generator to current time1303 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1304 const double rng_min = random.min();1305 const double rng_max = random.max();1306 //srand ( time(NULL) );1307 1308 // go over [0,1]^3 filler grid1309 for (n[0] = 0; n[0] < N[0]; n[0]++)1310 for (n[1] = 0; n[1] < N[1]; n[1]++)1311 for (n[2] = 0; n[2] < N[2]; n[2]++) {1312 // calculate position of current grid vector in untransformed box1313 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);1314 // create molecule random translation vector ...1315 for (int i=0;i<NDIM;i++)1316 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);1317 LOG(1, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");1318 1319 // ... and rotation matrix1320 if (DoRandomRotation)1321 setRandomRotation(Rotations);1322 else1323 Rotations.setIdentity();1324 1325 1326 // Check whether there is anything too close by and whether atom is outside of domain1327 FillIt = true;1328 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); ListRunner != LCList.end(); ++ListRunner) {1329 // check whether its void1330 FillIt = FillIt && isSpaceAroundPointVoid(1331 ListRunner->second,1332 (firstInsertion ? filler : NULL),1333 boundary,1334 CurrentPosition);1335 if (!FillIt) {1336 LOG(2, "REJECT: Position at " << Inserter << " is non-void.");1337 break;1338 }1339 // check whether inside domain1340 FillIt = FillIt && (Domain.isValid(CurrentPosition));1341 if (!FillIt) {1342 LOG(2, "REJECT: Position at " << CurrentPosition << " is "1343 << distance << ", hence outside of domain.");1344 break;1345 }1346 // check minimum distance to boundary1347 const double distance = (Domain.DistanceToBoundary(CurrentPosition) - MinDistance);1348 FillIt = FillIt && (distance > -MYEPSILON);1349 if (!FillIt) {1350 LOG(2, "REJECT: Position at " << CurrentPosition << " is " << distance << ", less than "1351 << MinDistance << " hence, too close to boundary.");1352 break;1353 }1354 }1355 // Check whether point is in- or outside of tesselations1356 if (FillIt) {1357 for (MoleculeList::iterator ListRunner = MolList->ListOfMolecules.begin(); ListRunner != MolList->ListOfMolecules.end(); ListRunner++) {1358 // get linked cell list1359 if (TesselStruct[(*ListRunner)] != NULL) {1360 const double distance = (TesselStruct[(*ListRunner)]->GetDistanceToSurface(Inserter, LCList[(*ListRunner)]));1361 LOG(2, "INFO: Distance to surface is " << distance << ".");1362 FillIt = FillIt && ((distance == -1.) || (distance > boundary)) && ((MaxSurfaceDistance < 0) || (MaxSurfaceDistance > distance));1363 if (!FillIt) {1364 LOG(2, "REJECT: Position at " << CurrentPosition << " is in distance of " << distance1365 << " to a surface, less than " << MaxSurfaceDistance << " hence, too close.");1366 break;1367 }1368 }1369 }1370 }1371 1372 // insert into Filling1373 if (FillIt) {1374 Inserter = CurrentPosition + FillerTranslations;1375 LOG(2, "ACCEPT: Position at " << CurrentPosition << " is void point.");1376 // fill!1377 Filling = filler->CopyMolecule();1378 RandomizeMoleculePositions(Filling, RandomAtomDisplacement, Rotations, random);1379 // translation1380 Filling->Translate(&Inserter);1381 // remove out-of-bounds atoms1382 const bool status = RemoveAtomsOutsideDomain(Filling);1383 if ((firstInsertion) && (!status)) { // no atom has been removed1384 // remove copied atoms and molecule again1385 Filling->removeAtomsinMolecule();1386 World::getInstance().destroyMolecule(Filling);1387 // and mark is final filler position1388 Filling = filler;1389 firstInsertion = false;1390 firstInserter = Inserter;1391 } else {1392 // TODO: Remove when World has no MoleculeListClass anymore1393 if (Filling)1394 MolList->insert(Filling);1395 }1396 } else {1397 LOG(2, "REJECT: Position at " << CurrentPosition << " is non-void point, within boundary or outside of MaxSurfaceDistance.");1398 continue;1399 }1400 }1401 1402 // have we inserted any molecules?1403 if (firstInsertion) {1404 // If not remove filler1405 for(molecule::iterator miter = filler->begin(); !filler->empty(); miter = filler->begin()) {1406 atom *Walker = *miter;1407 World::getInstance().destroyAtom(Walker);1408 }1409 World::getInstance().destroyMolecule(filler);1410 } else {1411 // otherwise translate and randomize to final position1412 if (DoRandomRotation)1413 setRandomRotation(Rotations);1414 else1415 Rotations.setIdentity();1416 RandomizeMoleculePositions(filler, RandomAtomDisplacement, Rotations, random);1417 // translation1418 filler->Translate(&firstInserter);1419 // remove out-of-bounds atoms1420 RemoveAtomsOutsideDomain(filler);1421 }1422 1423 LOG(0, MolList->ListOfMolecules.size() << " molecules have been inserted.");1424 1425 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); !LCList.empty(); ListRunner = LCList.begin()) {1426 delete ListRunner->second;1427 LCList.erase(ListRunner);1428 }1429 };1430 1431 656 /** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule. 1432 657 * \param *out output stream for debugging
Note:
See TracChangeset
for help on using the changeset viewer.