Changeset 0c83d8 for utils/boxmaker.py
- Timestamp:
- Nov 7, 2011, 4:12:24 PM (13 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:
- 32bc47
- Parents:
- 5735ba
- git-author:
- Gregor Bollerhey <bollerhe@…> (10/17/11 11:03:12)
- git-committer:
- Frederik Heber <heber@…> (11/07/11 16:12:24)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
utils/boxmaker.py
r5735ba r0c83d8 1 1 import re, os, os.path, sys, operator 2 2 3 def ReadSettings(): 3 class c_opt(): 4 basename = None 5 tremofiledir = './' 6 potentialsfiledir = './' 7 outfilename = 'out' 8 9 source = None 10 molarmass = None 11 density = None 12 temp = None 13 14 number = '1000' 15 16 cubicdomain = 'on' 17 cubiccell = 'off' 18 autorotate = 'off' # Not implemented yet 19 autodim = 'on' 20 21 def update(self, name, value): 22 if name in dir(self): 23 exec('self.%s = "%s"' % (name, value)) 24 else: 25 print 'Warning: Unknown option:', name 26 27 28 def ReadSettings(opt): 29 # Obtain basename 4 30 if len(sys.argv) >= 2: 5 global opt_basename 6 opt_basename = sys.argv[1] 7 else: 8 print 'usage: boxmaker.py <basename>' 31 opt.basename = sys.argv[1] 32 else: 33 print 'Usage: boxmaker.py <basename> [options]' 9 34 exit() 10 11 with open('boxmaker.'+opt_basename) as f: 35 36 # Read settings file 37 with open('boxmaker.' + opt.basename) as f: 12 38 for line in f: 13 39 if len(line) > 0 and line[0] != '#': 14 40 L, S, R = line.partition('=') 15 varname = 'opt_' + L.strip() 16 17 exec('global %s\n%s="%s"' % (varname, varname, R.strip())) 18 19 # IT'S A HACK 20 global opt_number 21 22 if len(sys.argv) == 3: 23 opt_number = sys.argv[2] 24 25 26 def ReadUnits(): 27 lines = [] 28 with open(opt_tremofiledir+opt_basename+'.tremolo') as f: 41 opt.update(L.strip(), R.strip()) 42 43 # Parse parameters 44 i = 2 45 while i < len(sys.argv): 46 L = sys.argv[i] 47 48 if L[0] in '+-': 49 LN = L[1:] 50 51 if L[0] == '+': 52 R = 'on' 53 else: 54 R = 'off' 55 else: 56 LN = L 57 i += 1 58 R = sys.argv[i] 59 60 opt.update(LN, R) 61 i += 1 62 63 64 def ReadUnits(opt): 65 lines = [] # The file needs to be processed twice, so we save the lines in the first run 66 67 with open(opt.tremofiledir + opt.basename + '.tremolo') as f: 29 68 for line in f: 30 69 if len(line) > 0 and line[0] != '#': 31 70 line = line.strip() 32 lines.append(line .strip())33 71 lines.append(line) 72 34 73 if 'systemofunits' in line: 35 74 L, S, SOU = line.partition('=') 36 SOU = SOU.strip()[:-1] 37 75 SOU = SOU.strip()[:-1] # Remove semicolon 76 38 77 if SOU == 'custom': 39 78 units = {} 40 79 quantities = ['length', 'mass'] 41 80 42 81 for quantity in quantities: 43 units[quantity] = [None, None] # scaling factor and unit.44 82 units[quantity] = [None, None] # Init with scaling factor and unit 'None'. 83 45 84 for line in lines: 46 85 for quantity in quantities: 47 86 if quantity in line: 48 87 L, S, R = line.partition('=') 49 R = R.strip()[:-1] # remove semicolon50 88 R = R.strip()[:-1] # Remove semicolon 89 51 90 if 'scalingfactor' in line: 52 91 units[quantity][0] = R 53 92 else: 54 93 units[quantity][1] = R 55 94 56 95 elif SOU == 'kcalpermole': 57 96 units = {'length': ['1', 'angstrom'], 'mass': ['1', 'u']} 58 97 59 98 elif SOU == 'evolt': 60 99 units = {'length': ['1', 'angstrom'], 'mass': ['1', 'u']} 61 100 62 101 else: # SI 63 102 units = {'length': ['1', 'm'], 'mass': ['1', 'kg']} 64 103 65 104 return units 66 67 105 106 68 107 def ConvertUnits(have, want): 69 # redo with pipes?108 # Redo with pipes? 70 109 ret = os.system("units '%s' '%s' > temp_units_output" % (have, want)) 71 110 72 111 if ret == 0: 73 112 with open('temp_units_output') as f: 74 113 line = f.readline() 114 115 os.system('rm temp_units_output') 116 117 return float(line[3:-1]) 118 else: 119 raise NameError('UnitError') 120 121 122 def UpdateSettings(opt): 123 # Map boolean values 124 for name in ['cubicdomain', 'cubiccell', 'autorotate', 'autodim']: 125 value = eval('opt.' + name) 126 127 if value == 'on': 128 value = True 129 elif value == 'off': 130 value = False 131 else: 132 print 'Not a boolean value:', value 133 exit() 75 134 76 os.system('rm temp_units_output') 77 78 return float(line[3:-1]) 79 else: 80 raise NameError('UnitError') 81 82 83 def UpdateSettings(): 84 global opt_molarmass, opt_density, opt_number 85 86 units = ReadUnits() 87 88 have = opt_molarmass 89 want = '%s*%s / mol' % tuple(units['mass']) 90 opt_molarmass = ConvertUnits(have, want) 91 92 have = opt_density 93 want = '(%s*%s) ' % tuple(units['mass']) + '/ (%s*%s)**3' % tuple(units['length']) 94 opt_density = ConvertUnits(have, want) 95 96 nvec = opt_number.split() 135 exec('opt.' + name + '= value') 136 137 # Convert dimensions 138 if opt.autodim: 139 units = ReadUnits(opt) 140 141 have = opt.molarmass 142 want = '%s*%s / mol' % tuple(units['mass']) 143 opt.molarmass = ConvertUnits(have, want) 144 145 have = opt.density 146 want = '(%s*%s) ' % tuple(units['mass']) + '/ (%s*%s)**3' % tuple(units['length']) 147 opt.density = ConvertUnits(have, want) 148 else: 149 opt.molarmass = float(opt.molarmass) 150 opt.density = float(opt.density) 151 152 # Number might be an integer or a 3-vector 153 nvec = opt.number.split() 97 154 if len(nvec) == 3: 98 opt _number = [0]*399 155 opt.number = [0]*3 156 100 157 for i in range(3): 101 opt_number[i] = int(nvec[i]) 102 else: 103 opt_number = int(opt_number) 104 105 106 def FindNearestCube(n): 107 global opt_number 108 109 newroot = round(opt_number**(1./3)) 110 111 opt_number = int(newroot**3) 112 print 'warning: number changed to %d' % opt_number 113 114 return [int(newroot)] * 3 115 116 117 def FindBestCuboid(n): 118 # prime factors of n 119 # taken from http://www.hsg-kl.de/faecher/inf/python/listen/index.php, "Beispiel 2" 120 121 F = [] 122 123 while n%2 == 0: 124 F.append(2) 125 n = n/2 126 while n%3 == 0: 127 F.append(3) 128 n = n/3 129 158 opt.number[i] = int(nvec[i]) 159 else: 160 opt.number = int(opt.number) 161 162 163 def FindBestCube(opt): 164 newroot = int( round(opt.number**(1./3)) ) 165 newnumber = newroot**3 166 167 if newnumber != opt.number: 168 print 'Warning: Number changed to %d.' % newnumber 169 170 return [newroot] * 3 171 172 173 def FindBestCuboid(opt): 174 n = opt.number 175 176 # Prime factors of n 177 factors = [] 178 179 for i in [2, 3]: 180 while n % i == 0: 181 factors.append(i) 182 n /= 2 183 130 184 t = 5 131 185 diff = 2 132 186 133 187 while t*t <= n: 134 while n%t == 0: 135 F.append(t) 136 n = n/t 188 while n % t == 0: 189 factors.append(t) 190 n /= t 191 137 192 t = t + diff 138 193 diff = 6 - diff 194 139 195 if n > 1: 140 F.append(n)141 142 # even distribution of current biggest prime to each vector -> similar sizes143 if len( F) < 3:144 print ' warning: not enough prime factors - falling back to cubic placement'145 return Find NearestCube(n, mlen)146 147 F.sort()196 factors.append(n) 197 198 # Even distribution of current biggest prime to each vector -> similar sizes 199 if len(factors) < 3: 200 print 'Warning: Not enough prime factors - falling back to cubic placement' 201 return FindBestCube(opt) 202 203 factors.sort() 148 204 distri = [[],[],[]] 149 205 current = 0 150 151 for primfaktor in F:152 distri[current].append( primfaktor)206 207 for factor in factors: 208 distri[current].append(factor) 153 209 current += 1 154 210 if current == 3: 155 211 current = 0 156 157 result = [ ]158 159 print ' box used:',160 212 213 result = [0]*3 214 215 print '======== CUBOID USED:', 216 161 217 for i in range(3): 162 a = reduce(operator.mul, distri[i]) 163 print a, 164 result.append(int(a)) 165 166 print 218 result[i] = int( reduce(operator.mul, distri[i]) ) 219 220 print result 167 221 return result 168 169 170 def GetSourceBBabs( ):222 223 224 def GetSourceBBabs(opt): 171 225 bbmax = [0.0]*3 172 bbmin = [ 0.0]*3173 174 s_name_ext = os.path.basename(opt _source).rsplit('.',1)226 bbmin = [float('inf')]*3 227 228 s_name_ext = os.path.basename(opt.source).rsplit('.', 1) 175 229 s_namepart = s_name_ext[0] 176 177 if len(s_name_ext [0])> 1:230 231 if len(s_name_ext) > 1: 178 232 s_ext = s_name_ext[1] 179 233 else: 180 234 s_ext = '' 181 182 # convert from any format to xyz 183 os.system('molecuilder -o xyz --parse-tremolo-potentials %s -i temp_source.xyz -l %s' % (opt_potentialsfiledir+opt_basename+'.potentials', opt_source)) 184 235 236 # Convert from any format to xyz 237 os.system('molecuilder -o xyz --parse-tremolo-potentials %s -i temp_source.xyz -l %s' % (opt.potentialsfiledir+opt.basename+'.potentials', opt.source)) 238 239 # Calculate bounding box from xyz-file 185 240 with open('temp_source.xyz') as f: 186 241 N = int(f.readline()) 187 242 comment = f.readline() 188 243 189 244 for i in xrange(N): 190 245 buf = f.readline() 191 246 xyz = buf.split()[1:] 192 247 193 248 for i in range(3): 194 249 bbmax[i] = max(bbmax[i], float(xyz[i])) … … 196 251 197 252 bb = [0.0]*3 198 253 199 254 for i in range(3): 200 bb[i] = bbmax[i] - bbmin[i] 201 202 255 bb[i] = abs(bbmax[i] - bbmin[i]) 256 203 257 os.system('rm temp_source.*') 204 258 return bb 205 259 206 207 ReadSettings() 208 UpdateSettings() 209 210 211 if type(opt_number) == type([]): 212 nbox = opt_number 260 # Global options with sensible default parameters 261 opt = c_opt() 262 263 ReadSettings(opt) 264 UpdateSettings(opt) 265 266 if type(opt.number) == type([]): 267 # Number is a vector - use it without any modification 268 nbox = opt.number 213 269 else: 214 if opt _constraint == 'cube':215 nbox = Find NearestCube(opt_number)216 else: 217 nbox = FindBestCuboid(opt _number)270 if opt.cubicdomain: 271 nbox = FindBestCube(opt) 272 else: 273 nbox = FindBestCuboid(opt) 218 274 219 275 avogadro = 6.022143e23 220 VolumePerMolecule = opt_molarmass / (avogadro * opt_density) 221 222 try: 223 bb = GetSourceBBabs() 224 print '======== BBOX:', bb 225 s = (VolumePerMolecule / (bb[0]*bb[1]*bb[2])) ** (1./3) 226 227 if s < 0: 228 print 'warning: molecular cells will overlap' 229 230 for i in range(3): 231 bb[i] = bb[i]*s 276 VolumePerMolecule = opt.molarmass / (avogadro * opt.density) 277 cell = [VolumePerMolecule**(1./3)] * 3 278 279 if not opt.cubiccell: 280 try: 281 bb = GetSourceBBabs(opt) 282 print '======== BBOX:', bb 283 # Scaling factor - the molecules bounding box is scaled to fit the volume suiting the density 284 s = (VolumePerMolecule / (bb[0]*bb[1]*bb[2])) ** (1./3) 285 286 if s < 1: 287 print 'Warning: Molecular cells will overlap.' 288 289 for i in range(3): 290 cell[i] = bb[i]*s 291 except ZeroDivisionError: 292 print 'Warning: Singularity in bounding box, falling back to cubic cell.' 232 293 233 cell = bb 234 except ZeroDivisionError: 235 print 'warning: singularity in bounding box, using cubic cell' 236 cell = [VolumePerMolecule**(1./3)] * 3 237 294 238 295 print '======== CELL: ', cell 239 296 … … 241 298 242 299 mol.CommandVerbose('0') 243 mol.ParserParseTremoloPotentials(opt _potentialsfiledir+opt_basename+'.potentials')244 mol.WorldInput(opt _source)300 mol.ParserParseTremoloPotentials(opt.potentialsfiledir + opt.basename + '.potentials') 301 mol.WorldInput(opt.source) 245 302 mol.WorldCenterInBox('%f 0 0 %f 0 %f' % tuple(cell)) 246 303 mol.WorldRepeatBox('%d %d %d' % tuple(nbox)) 247 mol.WorldOutput( 'out.data')248 mol.WorldOutput( 'out.xyz')304 mol.WorldOutput(opt.outfilename + '.data') 305 mol.WorldOutput(opt.outfilename + '.xyz') 249 306 250 307 domain = [0.0]*3 … … 252 309 for i in range(3): 253 310 domain[i] = cell[i]*nbox[i] 254 311 255 312 print '======== DOMAIN: ', domain
Note:
See TracChangeset
for help on using the changeset viewer.