- Timestamp:
- Sep 10, 2014, 7:10:26 PM (10 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- aa55d0
- Parents:
- 16c7dd
- git-author:
- Frederik Heber <heber@…> (09/01/14 15:57:23)
- git-committer:
- Frederik Heber <heber@…> (09/10/14 19:10:26)
- Location:
- src/Tesselation
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tesselation/boundary.cpp
r16c7dd r2528d8 767 767 }; 768 768 769 770 /** Fills the empty space around other molecules' surface of the simulation box with a filler.771 * \param *out output stream for debugging772 * \param *List list of molecules already present in box773 * \param *TesselStruct contains tesselated surface774 * \param *filler molecule which the box is to be filled with775 * \param configuration contains box dimensions776 * \param MaxDistance fills in molecules only up to this distance (set to -1 if whole of the domain)777 * \param distance[NDIM] distance between filling molecules in each direction778 * \param boundary length of boundary zone between molecule and filling mollecules779 * \param epsilon distance to surface which is not filled780 * \param RandAtomDisplacement maximum distance for random displacement per atom781 * \param RandMolDisplacement maximum distance for random displacement per filler molecule782 * \param DoRandomRotation true - do random rotiations, false - don't783 */784 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)785 {786 //Info FunctionInfo(__func__);787 molecule *Filling = World::getInstance().createMolecule();788 Vector CurrentPosition;789 int N[NDIM];790 int n[NDIM];791 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();792 RealSpaceMatrix Rotations;793 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();794 Vector AtomTranslations;795 Vector FillerTranslations;796 Vector FillerDistance;797 Vector Inserter;798 double FillIt = false;799 bond::ptr Binder;800 double phi[NDIM];801 map<molecule *, Tesselation *> TesselStruct;802 map<molecule *, LinkedCell_deprecated *> LCList;803 804 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++)805 if ((*ListRunner)->getAtomCount() > 0) {806 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");807 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);808 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 10.); // get linked cell list809 LOG(1, "Pre-creating tesselation for molecule " << *ListRunner << ".");810 TesselStruct[(*ListRunner)] = NULL;811 FindNonConvexBorder((*ListRunner), TesselStruct[(*ListRunner)], (const LinkedCell_deprecated *&)LCList[(*ListRunner)], 5., NULL);812 }813 814 // Center filler at origin815 filler->CenterEdge();816 const int FillerCount = filler->getAtomCount();817 LOG(2, "INFO: Filler molecule has the following bonds:");818 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {819 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();820 for(BondList::const_iterator BondRunner = ListOfBonds.begin();821 BondRunner != ListOfBonds.end();822 ++BondRunner) {823 if ((*BondRunner)->leftatom == *AtomRunner)824 LOG(2, " " << *(*BondRunner));825 }826 }827 828 atom * CopyAtoms[FillerCount];829 830 // calculate filler grid in [0,1]^3831 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);832 for(int i=0;i<NDIM;i++)833 N[i] = (int) ceil(1./FillerDistance[i]);834 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");835 836 // initialize seed of random number generator to current time837 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();838 const double rng_min = random.min();839 const double rng_max = random.max();840 //srand ( time(NULL) );841 842 // go over [0,1]^3 filler grid843 for (n[0] = 0; n[0] < N[0]; n[0]++)844 for (n[1] = 0; n[1] < N[1]; n[1]++)845 for (n[2] = 0; n[2] < N[2]; n[2]++) {846 // calculate position of current grid vector in untransformed box847 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);848 // create molecule random translation vector ...849 for (int i=0;i<NDIM;i++)850 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);851 LOG(2, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");852 853 // go through all atoms854 for (int i=0;i<FillerCount;i++)855 CopyAtoms[i] = NULL;856 857 // have same rotation angles for all molecule's atoms858 if (DoRandomRotation)859 for (int i=0;i<NDIM;i++)860 phi[i] = (random()/(rng_max-rng_min))*(2.*M_PI);861 862 // atom::clone is not const member function, hence we need iterator here863 for(molecule::iterator iter = filler->begin(); iter !=filler->end();++iter){864 865 // create atomic random translation vector ...866 for (int i=0;i<NDIM;i++)867 AtomTranslations[i] = RandomAtomDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);868 869 // ... and rotation matrix870 if (DoRandomRotation) {871 Rotations.set(0,0, cos(phi[0]) *cos(phi[2]) + (sin(phi[0])*sin(phi[1])*sin(phi[2])));872 Rotations.set(0,1, sin(phi[0]) *cos(phi[2]) - (cos(phi[0])*sin(phi[1])*sin(phi[2])));873 Rotations.set(0,2, cos(phi[1])*sin(phi[2]) );874 Rotations.set(1,0, -sin(phi[0])*cos(phi[1]) );875 Rotations.set(1,1, cos(phi[0])*cos(phi[1]) );876 Rotations.set(1,2, sin(phi[1]) );877 Rotations.set(2,0, -cos(phi[0]) *sin(phi[2]) + (sin(phi[0])*sin(phi[1])*cos(phi[2])));878 Rotations.set(2,1, -sin(phi[0]) *sin(phi[2]) - (cos(phi[0])*sin(phi[1])*cos(phi[2])));879 Rotations.set(2,2, cos(phi[1])*cos(phi[2]) );880 }881 882 // ... and put at new position883 Inserter = (*iter)->getPosition();884 if (DoRandomRotation)885 Inserter *= Rotations;886 Inserter += AtomTranslations + FillerTranslations + CurrentPosition;887 888 // check whether inserter is inside box889 Inserter *= MInverse;890 FillIt = true;891 for (int i=0;i<NDIM;i++)892 FillIt = FillIt && (Inserter[i] >= -MYEPSILON) && ((Inserter[i]-1.) <= MYEPSILON);893 Inserter *= M;894 895 // Check whether point is in- or outside896 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {897 // get linked cell list898 if (TesselStruct[(*ListRunner)] != NULL) {899 const double distance = (TesselStruct[(*ListRunner)]->GetDistanceToSurface(Inserter, LCList[(*ListRunner)]));900 FillIt = FillIt && (distance > boundary) && ((MaxDistance < 0) || (MaxDistance > distance));901 }902 }903 // insert into Filling904 if (FillIt) {905 LOG(1, "INFO: Position at " << Inserter << " is outer point.");906 // copy atom ...907 CopyAtoms[(*iter)->getNr()] = (*iter)->clone();908 (*CopyAtoms[(*iter)->getNr()]).setPosition(Inserter);909 Filling->AddAtom(CopyAtoms[(*iter)->getNr()]);910 LOG(1, "Filling atom " << **iter << ", translated to " << AtomTranslations << ", at final position is " << (CopyAtoms[(*iter)->getNr()]->getPosition()) << ".");911 } else {912 LOG(1, "INFO: Position at " << Inserter << " is inner point, within boundary or outside of MaxDistance.");913 CopyAtoms[(*iter)->getNr()] = NULL;914 continue;915 }916 }917 // go through all bonds and add as well918 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {919 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();920 for(BondList::const_iterator BondRunner = ListOfBonds.begin();921 BondRunner != ListOfBonds.end();922 ++BondRunner)923 if ((*BondRunner)->leftatom == *AtomRunner) {924 Binder = (*BondRunner);925 if ((CopyAtoms[Binder->leftatom->getNr()] != NULL) && (CopyAtoms[Binder->rightatom->getNr()] != NULL)) {926 LOG(3, "Adding Bond between " << *CopyAtoms[Binder->leftatom->getNr()] << " and " << *CopyAtoms[Binder->rightatom->getNr()]<< ".");927 Filling->AddBond(CopyAtoms[Binder->leftatom->getNr()], CopyAtoms[Binder->rightatom->getNr()], Binder->getDegree());928 }929 }930 }931 }932 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {933 delete LCList[*ListRunner];934 delete TesselStruct[(*ListRunner)];935 }936 };937 938 /** Rotates given molecule \a Filling and moves its atoms according to given939 * \a RandomAtomDisplacement.940 *941 * Note that for rotation to be sensible, the molecule should be centered at942 * the origin. This is not done here!943 *944 * \param &Filling molecule whose atoms to displace945 * \param RandomAtomDisplacement magnitude of random displacement946 * \param &Rotations 3D rotation matrix (or unity if no rotation desired)947 */948 void RandomizeMoleculePositions(949 molecule *&Filling,950 double RandomAtomDisplacement,951 RealSpaceMatrix &Rotations,952 RandomNumberGenerator &random953 )954 {955 const double rng_min = random.min();956 const double rng_max = random.max();957 958 Vector AtomTranslations;959 for(molecule::iterator miter = Filling->begin(); miter != Filling->end(); ++miter) {960 Vector temp = (*miter)->getPosition();961 temp *= Rotations;962 (*miter)->setPosition(temp);963 // create atomic random translation vector ...964 for (int i=0;i<NDIM;i++)965 AtomTranslations[i] = RandomAtomDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);966 (*miter)->setPosition((*miter)->getPosition() + AtomTranslations);967 }968 }969 970 /** Removes all atoms of a molecule outside.971 *972 * If the molecule is empty, it is removed as well.973 *974 * @param Filling molecule whose atoms to check, removed if eventually left975 * empty.976 * @return true - atoms had to be removed, false - no atoms have been removed977 */978 bool RemoveAtomsOutsideDomain(molecule *&Filling)979 {980 bool status = false;981 Box &Domain = World::getInstance().getDomain();982 // check if all is still inside domain983 for(molecule::iterator miter = Filling->begin(); miter != Filling->end(); ) {984 // check whether each atom is inside box985 if (!Domain.isInside((*miter)->getPosition())) {986 status = true;987 atom *Walker = *miter;988 ++miter;989 World::getInstance().destroyAtom(Walker);990 } else {991 ++miter;992 }993 }994 if (Filling->empty()) {995 LOG(0, "Removing molecule " << Filling->getName() << ", all atoms have been removed.");996 World::getInstance().destroyMolecule(Filling);997 Filling = NULL;998 }999 return status;1000 }1001 1002 /** Checks whether there are no atoms inside a sphere around \a CurrentPosition1003 * except those atoms present in \a *filler.1004 * If filler is NULL, then we just call LinkedCell_deprecated::GetPointsInsideSphere() and1005 * check whether the return list is empty.1006 * @param *filler1007 * @param boundary1008 * @param CurrentPosition1009 */1010 bool isSpaceAroundPointVoid(1011 LinkedCell_deprecated *LC,1012 molecule *filler,1013 const double boundary,1014 Vector &CurrentPosition)1015 {1016 size_t compareTo = 0;1017 TesselPointSTLList* liste = LC->GetPointsInsideSphere(boundary == 0. ? MYEPSILON : boundary, &CurrentPosition);1018 if (filler != NULL) {1019 for (TesselPointSTLList::const_iterator iter = liste->begin();1020 iter != liste->end();1021 ++iter) {1022 for (molecule::iterator miter = filler->begin();1023 miter != filler->end();1024 ++miter) {1025 if (*iter == *miter)1026 ++compareTo;1027 }1028 }1029 }1030 const bool result = (liste->size() == compareTo);1031 if (!result) {1032 LOG(0, "Skipping because of the following atoms:");1033 for (TesselPointSTLList::const_iterator iter = liste->begin();1034 iter != liste->end();1035 ++iter) {1036 LOG(0, **iter);1037 }1038 }1039 delete(liste);1040 return result;1041 }1042 1043 /** Sets given 3x3 matrix to a random rotation matrix.1044 *1045 * @param a matrix to set1046 */1047 inline void setRandomRotation(RealSpaceMatrix &a)1048 {1049 double phi[NDIM];1050 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1051 const double rng_min = random.min();1052 const double rng_max = random.max();1053 1054 for (int i=0;i<NDIM;i++) {1055 phi[i] = (random()/(rng_max-rng_min))*(2.*M_PI);1056 LOG(4, "DEBUG: Random angle is " << phi[i] << ".");1057 }1058 1059 a.setRotation(phi);1060 }1061 1062 /** Fills the empty space of the simulation box with water.1063 * \param *filler molecule which the box is to be filled with1064 * \param configuration contains box dimensions1065 * \param distance[NDIM] distance between filling molecules in each direction1066 * \param boundary length of boundary zone between molecule and filling molecules1067 * \param RandAtomDisplacement maximum distance for random displacement per atom1068 * \param RandMolDisplacement maximum distance for random displacement per filler molecule1069 * \param MinDistance minimum distance to boundary of domain and present molecules1070 * \param DoRandomRotation true - do random rotations, false - don't1071 */1072 void FillVoidWithMolecule(1073 molecule *&filler,1074 config &configuration,1075 const double distance[NDIM],1076 const double boundary,1077 const double RandomAtomDisplacement,1078 const double RandomMolDisplacement,1079 const double MinDistance,1080 const bool DoRandomRotation1081 )1082 {1083 //Info FunctionInfo(__func__);1084 molecule *Filling = NULL;1085 Vector CurrentPosition;1086 int N[NDIM];1087 int n[NDIM];1088 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();1089 RealSpaceMatrix Rotations;1090 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();1091 Vector FillerTranslations;1092 Vector FillerDistance;1093 Vector Inserter;1094 double FillIt = false;1095 Vector firstInserter;1096 bool firstInsertion = true;1097 const Box &Domain = World::getInstance().getDomain();1098 map<molecule *, LinkedCell_deprecated *> LCList;1099 std::vector<molecule *> List = World::getInstance().getAllMolecules();1100 MoleculeListClass *MolList = World::getInstance().getMolecules();1101 1102 for (std::vector<molecule *>::iterator ListRunner = List.begin(); ListRunner != List.end(); ListRunner++)1103 if ((*ListRunner)->getAtomCount() > 0) {1104 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");1105 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);1106 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 10.); // get linked cell list1107 }1108 1109 // Center filler at its center of gravity1110 const Vector gravity = filler->DetermineCenterOfGravity();1111 filler->CenterAtVector(gravity);1112 //const int FillerCount = filler->getAtomCount();1113 LOG(2, "INFO: Filler molecule has the following bonds:");1114 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {1115 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();1116 for(BondList::const_iterator BondRunner = ListOfBonds.begin();1117 BondRunner != ListOfBonds.end();1118 ++BondRunner)1119 if ((*BondRunner)->leftatom == *AtomRunner)1120 LOG(2, " " << *(*BondRunner));1121 }1122 1123 // calculate filler grid in [0,1]^31124 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);1125 for(int i=0;i<NDIM;i++)1126 N[i] = (int) ceil(1./FillerDistance[i]);1127 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");1128 1129 // initialize seed of random number generator to current time1130 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1131 const double rng_min = random.min();1132 const double rng_max = random.max();1133 //srand ( time(NULL) );1134 1135 // go over [0,1]^3 filler grid1136 for (n[0] = 0; n[0] < N[0]; n[0]++)1137 for (n[1] = 0; n[1] < N[1]; n[1]++)1138 for (n[2] = 0; n[2] < N[2]; n[2]++) {1139 // calculate position of current grid vector in untransformed box1140 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);1141 // create molecule random translation vector ...1142 for (int i=0;i<NDIM;i++) // have the random values [-1,1]*RandomMolDisplacement1143 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);1144 LOG(2, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");1145 1146 // ... and rotation matrix1147 if (DoRandomRotation)1148 setRandomRotation(Rotations);1149 else1150 Rotations.setIdentity();1151 1152 1153 // Check whether there is anything too close by and whether atom is outside of domain1154 FillIt = true;1155 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); ListRunner != LCList.end(); ++ListRunner) {1156 FillIt = FillIt && isSpaceAroundPointVoid(1157 ListRunner->second,1158 (firstInsertion ? filler : NULL),1159 boundary,1160 CurrentPosition);1161 FillIt = FillIt && (Domain.isValid(CurrentPosition))1162 && ((Domain.DistanceToBoundary(CurrentPosition) - MinDistance) > -MYEPSILON);1163 if (!FillIt)1164 break;1165 }1166 1167 // insert into Filling1168 if (FillIt) {1169 Inserter = CurrentPosition + FillerTranslations;1170 LOG(1, "INFO: Position at " << Inserter << " is void point.");1171 // fill!1172 Filling = filler->CopyMolecule();1173 RandomizeMoleculePositions(Filling, RandomAtomDisplacement, Rotations, random);1174 // translation1175 Filling->Translate(Inserter);1176 // remove out-of-bounds atoms1177 const bool status = RemoveAtomsOutsideDomain(Filling);1178 if ((firstInsertion) && (!status)) { // no atom has been removed1179 // remove copied atoms and molecule again1180 Filling->removeAtomsinMolecule();1181 World::getInstance().destroyMolecule(Filling);1182 // and mark is final filler position1183 Filling = filler;1184 firstInsertion = false;1185 firstInserter = Inserter;1186 } else {1187 // TODO: Remove when World has no MoleculeListClass anymore1188 if (Filling)1189 MolList->insert(Filling);1190 }1191 } else {1192 LOG(1, "INFO: Position at " << Inserter << " is non-void point, within boundary or outside of MaxDistance.");1193 continue;1194 }1195 }1196 1197 // have we inserted any molecules?1198 if (firstInsertion) {1199 // If not remove filler1200 for(molecule::iterator miter = filler->begin(); !filler->empty(); miter = filler->begin()) {1201 atom *Walker = *miter;1202 World::getInstance().destroyAtom(Walker);1203 }1204 World::getInstance().destroyMolecule(filler);1205 } else {1206 // otherwise translate and randomize to final position1207 if (DoRandomRotation)1208 setRandomRotation(Rotations);1209 else1210 Rotations.setIdentity();1211 RandomizeMoleculePositions(filler, RandomAtomDisplacement, Rotations, random);1212 // translation1213 filler->Translate(firstInserter);1214 // remove out-of-bounds atoms1215 RemoveAtomsOutsideDomain(filler);1216 }1217 1218 LOG(0, MolList->ListOfMolecules.size() << " molecules have been inserted.");1219 1220 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); !LCList.empty(); ListRunner = LCList.begin()) {1221 delete ListRunner->second;1222 LCList.erase(ListRunner);1223 }1224 };1225 1226 1227 /** Fills the empty space around other molecules' surface of the simulation box with a filler.1228 *1229 * Note that we use \a FindNonConvexBorder to determine the surface of the found molecules.1230 * There, we use a radius of twice the given \a boundary.1231 *1232 * \param *out output stream for debugging1233 * \param *List list of molecules already present in box1234 * \param *TesselStruct contains tesselated surface1235 * \param *filler molecule which the box is to be filled with1236 * \param configuration contains box dimensions1237 * \param MaxSurfaceDistance fills in molecules only up to this distance (set to -1 if whole of the domain)1238 * \param distance[NDIM] distance between filling molecules in each direction1239 * \param boundary length of boundary zone between molecule and filling molecules1240 * \param MinDistance distance to boundary of domain which is not filled1241 * \param RandAtomDisplacement maximum distance for random displacement per atom1242 * \param RandMolDisplacement maximum distance for random displacement per filler molecule1243 * \param DoRandomRotation true - do random rotations, false - don't1244 */1245 void FillBoxWithMolecule(1246 MoleculeListClass *MolList,1247 molecule *filler,1248 config &configuration,1249 const double MaxSurfaceDistance,1250 const double distance[NDIM],1251 const double boundary,1252 const double MinDistance,1253 const double RandomAtomDisplacement,1254 const double RandomMolDisplacement,1255 const bool DoRandomRotation)1256 {1257 //Info FunctionInfo(__func__);1258 molecule *Filling = NULL;1259 Vector CurrentPosition;1260 int N[NDIM];1261 int n[NDIM];1262 const RealSpaceMatrix &M = World::getInstance().getDomain().getM();1263 RealSpaceMatrix Rotations;1264 const RealSpaceMatrix &MInverse = World::getInstance().getDomain().getMinv();1265 Vector FillerTranslations;1266 Vector FillerDistance;1267 Vector Inserter;1268 double FillIt = false;1269 Vector firstInserter;1270 bool firstInsertion = true;1271 const Box &Domain = World::getInstance().getDomain();1272 map<molecule *, LinkedCell_deprecated *> LCList;1273 std::vector<molecule *> List = World::getInstance().getAllMolecules();1274 map<molecule *, Tesselation *> TesselStruct;1275 1276 for (MoleculeList::iterator ListRunner = MolList->ListOfMolecules.begin(); ListRunner != MolList->ListOfMolecules.end(); ListRunner++)1277 if ((*ListRunner)->getAtomCount() > 0) {1278 LOG(1, "Pre-creating linked cell lists for molecule " << *ListRunner << ".");1279 PointCloudAdaptor< molecule > cloud(*ListRunner, (*ListRunner)->name);1280 LCList[(*ListRunner)] = new LinkedCell_deprecated(cloud, 4.*boundary); // get linked cell list1281 LOG(1, "Pre-creating tesselation for molecule " << *ListRunner << ".");1282 TesselStruct[(*ListRunner)] = NULL;1283 FindNonConvexBorder((*ListRunner), TesselStruct[(*ListRunner)], (const LinkedCell_deprecated *&)LCList[(*ListRunner)], 2.*boundary, NULL);1284 }1285 1286 // Center filler at origin1287 filler->CenterEdge();1288 // const int FillerCount = filler->getAtomCount();1289 LOG(2, "INFO: Filler molecule has the following bonds:");1290 for(molecule::iterator AtomRunner = filler->begin(); AtomRunner != filler->end(); ++AtomRunner) {1291 const BondList& ListOfBonds = (*AtomRunner)->getListOfBonds();1292 for(BondList::const_iterator BondRunner = ListOfBonds.begin();1293 BondRunner != ListOfBonds.end();1294 ++BondRunner) {1295 if ((*BondRunner)->leftatom == *AtomRunner)1296 LOG(2, " " << *(*BondRunner));1297 }1298 }1299 1300 // atom * CopyAtoms[FillerCount];1301 1302 setVerbosity(4);1303 1304 // calculate filler grid in [0,1]^31305 FillerDistance = MInverse * Vector(distance[0], distance[1], distance[2]);1306 for(int i=0;i<NDIM;i++)1307 N[i] = (int) ceil(1./FillerDistance[i]);1308 LOG(1, "INFO: Grid steps are " << N[0] << ", " << N[1] << ", " << N[2] << ".");1309 1310 // initialize seed of random number generator to current time1311 RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();1312 const double rng_min = random.min();1313 const double rng_max = random.max();1314 //srand ( time(NULL) );1315 1316 // go over [0,1]^3 filler grid1317 for (n[0] = 0; n[0] < N[0]; n[0]++)1318 for (n[1] = 0; n[1] < N[1]; n[1]++)1319 for (n[2] = 0; n[2] < N[2]; n[2]++) {1320 // calculate position of current grid vector in untransformed box1321 CurrentPosition = M * Vector((double)n[0]/(double)N[0], (double)n[1]/(double)N[1], (double)n[2]/(double)N[2]);1322 // create molecule random translation vector ...1323 for (int i=0;i<NDIM;i++)1324 FillerTranslations[i] = RandomMolDisplacement*(random()/((rng_max-rng_min)/2.) - 1.);1325 LOG(1, "INFO: Current Position is " << CurrentPosition << "+" << FillerTranslations << ".");1326 1327 // ... and rotation matrix1328 if (DoRandomRotation)1329 setRandomRotation(Rotations);1330 else1331 Rotations.setIdentity();1332 1333 1334 // Check whether there is anything too close by and whether atom is outside of domain1335 FillIt = true;1336 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); ListRunner != LCList.end(); ++ListRunner) {1337 // check whether its void1338 FillIt = FillIt && isSpaceAroundPointVoid(1339 ListRunner->second,1340 (firstInsertion ? filler : NULL),1341 boundary,1342 CurrentPosition);1343 if (!FillIt) {1344 LOG(2, "REJECT: Position at " << Inserter << " is non-void.");1345 break;1346 }1347 // check whether inside domain1348 FillIt = FillIt && (Domain.isValid(CurrentPosition));1349 if (!FillIt) {1350 LOG(2, "REJECT: Position at " << CurrentPosition << " is "1351 << distance << ", hence outside of domain.");1352 break;1353 }1354 // check minimum distance to boundary1355 const double distance = (Domain.DistanceToBoundary(CurrentPosition) - MinDistance);1356 FillIt = FillIt && (distance > -MYEPSILON);1357 if (!FillIt) {1358 LOG(2, "REJECT: Position at " << CurrentPosition << " is " << distance << ", less than "1359 << MinDistance << " hence, too close to boundary.");1360 break;1361 }1362 }1363 // Check whether point is in- or outside of tesselations1364 if (FillIt) {1365 for (MoleculeList::iterator ListRunner = MolList->ListOfMolecules.begin(); ListRunner != MolList->ListOfMolecules.end(); ListRunner++) {1366 // get linked cell list1367 if (TesselStruct[(*ListRunner)] != NULL) {1368 const double distance = (TesselStruct[(*ListRunner)]->GetDistanceToSurface(Inserter, LCList[(*ListRunner)]));1369 LOG(2, "INFO: Distance to surface is " << distance << ".");1370 FillIt = FillIt && ((distance == -1.) || (distance > boundary)) && ((MaxSurfaceDistance < 0) || (MaxSurfaceDistance > distance));1371 if (!FillIt) {1372 LOG(2, "REJECT: Position at " << CurrentPosition << " is in distance of " << distance1373 << " to a surface, less than " << MaxSurfaceDistance << " hence, too close.");1374 break;1375 }1376 }1377 }1378 }1379 1380 // insert into Filling1381 if (FillIt) {1382 Inserter = CurrentPosition + FillerTranslations;1383 LOG(2, "ACCEPT: Position at " << CurrentPosition << " is void point.");1384 // fill!1385 Filling = filler->CopyMolecule();1386 RandomizeMoleculePositions(Filling, RandomAtomDisplacement, Rotations, random);1387 // translation1388 Filling->Translate(Inserter);1389 // remove out-of-bounds atoms1390 const bool status = RemoveAtomsOutsideDomain(Filling);1391 if ((firstInsertion) && (!status)) { // no atom has been removed1392 // remove copied atoms and molecule again1393 Filling->removeAtomsinMolecule();1394 World::getInstance().destroyMolecule(Filling);1395 // and mark is final filler position1396 Filling = filler;1397 firstInsertion = false;1398 firstInserter = Inserter;1399 } else {1400 // TODO: Remove when World has no MoleculeListClass anymore1401 if (Filling)1402 MolList->insert(Filling);1403 }1404 } else {1405 LOG(2, "REJECT: Position at " << CurrentPosition << " is non-void point, within boundary or outside of MaxSurfaceDistance.");1406 continue;1407 }1408 }1409 1410 // have we inserted any molecules?1411 if (firstInsertion) {1412 // If not remove filler1413 for(molecule::iterator miter = filler->begin(); !filler->empty(); miter = filler->begin()) {1414 atom *Walker = *miter;1415 World::getInstance().destroyAtom(Walker);1416 }1417 World::getInstance().destroyMolecule(filler);1418 } else {1419 // otherwise translate and randomize to final position1420 if (DoRandomRotation)1421 setRandomRotation(Rotations);1422 else1423 Rotations.setIdentity();1424 RandomizeMoleculePositions(filler, RandomAtomDisplacement, Rotations, random);1425 // translation1426 filler->Translate(firstInserter);1427 // remove out-of-bounds atoms1428 RemoveAtomsOutsideDomain(filler);1429 }1430 1431 LOG(0, MolList->ListOfMolecules.size() << " molecules have been inserted.");1432 1433 for (std::map<molecule *, LinkedCell_deprecated *>::iterator ListRunner = LCList.begin(); !LCList.empty(); ListRunner = LCList.begin()) {1434 delete ListRunner->second;1435 LCList.erase(ListRunner);1436 }1437 };1438 1439 769 /** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule. 1440 770 * \param *out output stream for debugging -
src/Tesselation/boundary.hpp
r16c7dd r2528d8 40 40 41 41 double ConvexizeNonconvexEnvelope(class Tesselation *&TesselStruct, const molecule * const mol, const char * const filename); 42 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);43 void FillVoidWithMolecule(molecule *&filler, config &configuration, const double distance[NDIM], const double boundary, const double RandomAtomDisplacement, const double RandomMolDisplacement, const double MinDistance, const bool DoRandomRotation);44 42 void FindConvexBorder(const molecule* const mol, Boundaries *BoundaryPts, Tesselation *&TesselStruct, const LinkedCell_deprecated *LCList, const char *filename); 45 43 Vector* FindEmbeddingHole(MoleculeListClass *mols, molecule *srcmol);
Note:
See TracChangeset
for help on using the changeset viewer.