def FixedWindow_phopFromTrajectory_func(trajectory, Lx, p_threshold_low, every_recAlways): trajDuration = len(trajectory) Natoms = len(trajectory[0]) # uniqueHops=[] ## mostly used for our own curiosity, not a final feature: # p_hop_hierarchy = [ [],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[] ] N_ObseravblesRecorded = 12 ## we set the value to the flag -42 so that it is ibvious a box is empty ## when the bix has not been filled with the correct value resultsArray = np.zeros((Natoms, trajDuration, N_ObseravblesRecorded), dtype=float32) #- 42.0 Nact_atom = np.zeros((Natoms), dtype=int32) hop_number = 0 ## TODO: make this width an argument of this function, maybe ? TF = 5 for atom in range( Natoms): # Natoms , but then we will do it in batches with numpy NactiveTimes = 1 displacements = np.zeros((trajDuration, 3)) #, dtype=np.float) for t0 in range(1, trajDuration): displacements[t0] = module_PBC.applyPBC_vector_func( trajectory[t0, atom, :] - trajectory[t0 - 1, atom, :], Lx) TA = max(t0 - TF, 0) TB = min(t0 + TF, trajDuration - 1) subTraj = trajectory[TA:TB, atom] ##### core fo the algorithm: ########### phop, averageA, Prev_StdDev, Next_StdDev, average_distAB = FixedWindow_phopValue_func( subTraj, displacements[TA:TB], TA, TB, Lx) ######################################## tcLocA = t0 - TA #np.argmax(phop) p_hop_value = phop[tcLocA] tc = t0 # tcLocA+TA if p_hop_value > p_threshold_low: resultsArray[atom, tc, 0] = tc resultsArray[atom, tc, 1] = p_hop_value resultsArray[atom, tc, 2] = 1 resultsArray[atom, tc, 3] = TA resultsArray[atom, tc, 4] = TB resultsArray[atom, tc, 5] = averageA[0] resultsArray[atom, tc, 6] = averageA[1] resultsArray[atom, tc, 7] = averageA[2] resultsArray[atom, tc, 8] = Prev_StdDev resultsArray[atom, tc, 9] = Next_StdDev resultsArray[atom, tc, 10] = average_distAB # resultsArray[atom, NactiveTimes, 11] = tc NactiveTimes += 1 ## just for that atom in particular !! hop_number += 1 # ## remember the size of the "list" # resultsArray[atom, 1:NactiveTimes,11] = np.sort(resultsArray[atom,1:NactiveTimes,11]) # resultsArray[atom, 0 ,11] = NactiveTimes Nact_atom[atom] = NactiveTimes - 1 ############################################################################### return resultsArray, Nact_atom, hop_number
def unrolled_traj_func(trajectory, Lx, atom): trajDuration = len(trajectory) displacements = np.zeros((trajDuration, 3)) #, dtype=np.float) for t0 in range(1, trajDuration): displacements[t0] = module_PBC.applyPBC_vector_func( trajectory[t0, atom, :] - trajectory[t0 - 1, atom, :], Lx) previousPosition = trajectory[0, atom, :] unrolled_traj = trajectory[:, atom, :].copy() for t0 in range(1, trajDuration): unrolled_traj[t0] = unrolled_traj[t0 - 1] + displacements[t0] return unrolled_traj
def descriptor_func_allInstants(AtomTimesAll, trajectory, backArray, descriptor_family_name, descriptor_family_parameters, Lx, atomTypes): Natoms = len(trajectory[0, :, 0]) # Nexamples = len(AtomTimesAll)/2 descriptors_size_m = len(descriptor_family_parameters[:, 0]) Ntypes = int(np.max(atomTypes) + 1) all_instants_descriptors_array = np.zeros( (len(AtomTimesAll), descriptors_size_m * Ntypes)) ## choice of the cutoff: it will be assumed that the max of the 0th column of parmaeters gives a meanigful radius. descriptor_cutoff = np.max(descriptor_family_parameters[:, 0]) - 1e-6 for instant_index in range(len(AtomTimesAll)): # if instant_index % int(len(AtomTimesAll)/10) ==0: # print("1/10th done: instant is: ", int(instant_index)) # temporary array: # ## (we want extra precision because we will add many elements) ## descriptors_array = np.zeros((Ntypes, descriptors_size_m), dtype=float64) atom = AtomTimesAll[instant_index, 0] tc_index = backArray[AtomTimesAll[instant_index, 1]] allpos = trajectory[tc_index] pos = allpos[atom] for atom_b in range(Natoms): # distance between 'atom' and 'atom_b' : dist pos_neighb = allpos[atom_b] displacements = module_PBC.applyPBC_vector_func( pos - pos_neighb, Lx) dist = np.sqrt(np.sum((displacements)**2)) if dist < descriptor_cutoff: tmp = descriptor_func_singleDistance( descriptor_family_name, descriptor_family_parameters, dist) for i in range(descriptors_size_m): ## numba refuses to do my full copy :( using [:] .. it's stil faster !! :) descriptors_array[atomTypes[atom_b], i] += tmp[i] ## record the set of {G_i}'s for that instant for AtomType in range(Ntypes): all_instants_descriptors_array[instant_index, descriptors_size_m * AtomType:descriptors_size_m * (AtomType + 1)] = descriptors_array[AtomType] ## we do not need as much precision there. ## return all_instants_descriptors_array
def phopValue_func(subTraj, displacements, TA, TB, Lx): cumsumA, cumsumA_2 = cumsum_func(subTraj, displacements, Lx) cumsumB = reverse_cumsum_func(cumsumA) # not working (not reversible) cumsumB_2 = reverse_cumsum_func(cumsumA_2) # not working ## slower method: ##rev = reverse_vector(subTraj) ##cumsumB, cumsumB_2 = cumsum_func(rev , Lx) phop = np.zeros(TB - TA) for tc in range(TA, TB, 1): # indices LOCal to the arrays, for which time starts starts 0: tcLocA = tc - TA tcLocB = TB - tc - 1 ## here we don't have to sum over t1 and t2 as in the Naive code version, ## which means that we do not compute many avergages, we just computed ## the largest one once ## (+saved all intermediate results in the cumsum thingies) ## here we used that (a-b)^2 = a^2 - 2ab + b^2, with a=trajectory[t2,i] ## and b=<trajectory[tc:TB]> (see naive implementation for comparison) ## are these tmp variable really saving time?: averageA = cumsumA[tcLocA] / (tcLocA + 1.0) averageB = cumsumB[tcLocB] / (tcLocB + 1.0) d1 = sum_vector( \ cumsumA_2[tcLocA]/(tcLocA+1.0) \ - 2.0 * averageA * averageB \ + (averageB)**2 ) d2 = sum_vector( \ cumsumB_2[tcLocB]/(tcLocB+1.0) \ - 2.0 * averageB * averageA \ + (averageA )**2 ) phop[tcLocA] = (d1 * d2)**0.5 * xi_tc_T(tcLocA, TB - TA) tcLocA = np.argmax(phop) averageA = cumsumA[tcLocA] / (tcLocA + 1.0) # 3d vector Prev_StdDev = sum_vector(cumsumA_2[tcLocA] / (tcLocA + 1.0) - averageA**2.0) #scalar tcLocB = TB - TA - tcLocA - 1 # TB-(tc-TA)-TA-1 averageB = cumsumB[tcLocB] / (tcLocB + 1.0) # 3d vector Next_StdDev = sum_vector(cumsumB_2[tcLocB] / (tcLocB + 1.0) - averageB**2.0) #scalar average_distAB = (sum_vector( (module_PBC.applyPBC_vector_func(averageA - averageB, Lx))**2))**0.5 ## dist. between 2 averages: alreadt computed in phop. return phop, averageA, Prev_StdDev, Next_StdDev, average_distAB
def FixedWindow_phopValue_func(subTraj, displacements, TA, TB, Lx): ## tc-TA == TB-tc == Ttot/2 ## cumsumA, cumsumA_2 = cumsum_func(subTraj, displacements, Lx) cumsumB = reverse_cumsum_func(cumsumA) cumsumB_2 = reverse_cumsum_func(cumsumA_2) ## we compute twice as much as needed, but it's ok because we don't like this algorithm phop = np.zeros(TB - TA) tc = (TA + TB) / 2 # indices LOCal to the arrays, for which time starts starts 0: tcLocA = tc - TA tcLocB = TB - tc - 1 ## are these tmp variable really saving time?: averageA = cumsumA[tcLocA] / (tcLocA + 1.0) averageB = cumsumB[tcLocB] / (tcLocB + 1.0) d1 = sum_vector( \ cumsumA_2[tcLocA]/(tcLocA+1.0) \ - 2.0 * averageA * averageB \ + (averageB)**2 ) d2 = sum_vector( \ cumsumB_2[tcLocB]/(tcLocB+1.0) \ - 2.0 * averageB * averageA \ + (averageA )**2 ) phop[tcLocA] = ( d1 * d2 )**0.5 # * xi_tc_T(tcLocA,TB-TA) ## XXX TODO ! here I removed the xi, as they did in their papers ! Prev_StdDev = sum_vector(cumsumA_2[tcLocA] / (tcLocA + 1.0) - averageA**2.0) #scalar Next_StdDev = sum_vector(cumsumB_2[tcLocB] / (tcLocB + 1.0) - averageB**2.0) #scalar average_distAB = (sum_vector( (module_PBC.applyPBC_vector_func(averageA - averageB, Lx))**2))**0.5 ## dist. between 2 averages: alreadt computed in phop. return phop, averageA, Prev_StdDev, Next_StdDev, average_distAB
interval_end = interval_beg + every_forCPU for t0 in range(interval_beg, interval_end, every_forCPU): if t0 + Delta_t > trajDuration - 1: print "reached the end of this window's possible t_0's", t0, Ws[ win_index] break Delta_t_weight += 1 # print("interval_beg,interval_end, every_forCPU",interval_beg,interval_end, every_forCPU) ## "displacements" includes all particles selected (e.g. type 'A') # [selectedAtoms] TODO : adjsut using [selectedAtoms] displacements = np.abs(trajectory[t0 + Delta_t, :] - trajectory[t0, :]) for t1 in range(len(displacements)): displacements[t1] = module_PBC.applyPBC_vector_func( displacements[t1], Lx) if compute_Fkt == True: ################ CORE ################### Fk_Deltat += module_computeObservables.Fkt_function( NX, NY, NZ, Lx, displacements) ################ CORE ################### if compute_RMSD == True: tmp = displacements**2 RMSD_Deltat += ( tmp[:, 0] + tmp[:, 1] + tmp[:, 2])**0.5 ## XXX is there really a sqrt here ?? if Delta_t_weight > 0: if compute_Fkt == True:
def phopFromTrajectory_func(trajectory, Lx, p_threshold_low, every_recAlways): trajDuration = len(trajectory) Natoms = len(trajectory[0]) ## mostly used for our own curiosity, not a final feature: # p_hop_hierarchy = [ [],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[] ] N_ObseravblesRecorded = 11 ## we set the value to the flag -42 so that it is ibvious a box is empty ## when the bix has not been filled with the correct value resultsArray = np.zeros((Natoms, trajDuration, N_ObseravblesRecorded), dtype=float32) #- 42.0 Nact_atom = np.zeros((Natoms), dtype=int32) hop_number = 0 OldIntervals_lengthMax = int(3e7) NewIntervals = np.zeros((OldIntervals_lengthMax, 2), dtype=int32) - 42 OldIntervals = np.zeros((OldIntervals_lengthMax, 2), dtype=int32) - 42 OldIntervals_lengthUsed_max = 0 for atom in range( Natoms): # Natoms , but then we will do it in batches with numpy OldIntervals_lengthUsed = 0 OldIntervals[OldIntervals_lengthUsed, 0] = 0 OldIntervals[OldIntervals_lengthUsed, 1] = trajDuration OldIntervals_lengthUsed = 1 # OldIntervals = [[0, trajDuration]] # p_hop_hierarchy_depth=-1 NactiveTimes = 1 displacements = np.zeros((trajDuration, 3)) #, dtype=np.float) for t0 in range(1, trajDuration): displacements[t0] = module_PBC.applyPBC_vector_func( trajectory[t0, atom, :] - trajectory[t0 - 1, atom, :], Lx) while OldIntervals_lengthUsed > 0: #len(OldIntervals) > 0 : # p_hop_hierarchy_depth+=1 NewIntervals_lengthUsed = 0 #NewIntervals=[] # TA and TB are indeed indices, i.e. starting from 0 and ending at Nframes-1. # print(OldIntervals) for TATBindex in range( OldIntervals_lengthUsed): #for (TA,TB) in OldIntervals: TA = OldIntervals[TATBindex, 0] TB = OldIntervals[TATBindex, 1] ## dismiss the search when two consecutive "events" have been found: if TB - TA > 1: subTraj = trajectory[TA:TB, atom] ##### core fo the algorithm: ########### phop, averageA, Prev_StdDev, Next_StdDev, average_distAB = phopValue_func( subTraj, displacements[TA:TB], TA, TB, Lx) ######################################## tcLocA = np.argmax(phop) p_hop_value = phop[tcLocA] tc = tcLocA + TA # if p_hop_value > StdDevInternalA+StdDevInternalB: if p_hop_value > p_threshold_low: # p_hop_hierarchy[p_hop_hierarchy_depth].append(p_hop_value) resultsArray[atom, tc, 0] = tc resultsArray[atom, tc, 1] = p_hop_value resultsArray[atom, tc, 2] = 1 resultsArray[atom, tc, 3] = TA resultsArray[atom, tc, 4] = TB resultsArray[atom, tc, 5] = averageA[0] resultsArray[atom, tc, 6] = averageA[1] resultsArray[atom, tc, 7] = averageA[2] resultsArray[atom, tc, 8] = Prev_StdDev resultsArray[atom, tc, 9] = Next_StdDev resultsArray[atom, tc, 10] = average_distAB # resultsArray[atom, NactiveTimes, 11] = tc NactiveTimes += 1 ## just for that atom in particular !! ## TODO : after all events for all atoms have been recorded to this, ## optimize file length (compress) bu recording inly the list of events' properties for eaxh atom. ## the output file would then be shape (Natoms, number-of-events-of-most-active-atom) ## + the positions of full system for each active time (ooking at unique times) ## XXX however this may turn out to be useless if I'm lucky. hop_number += 1 ## uodate of the "list" of intervales to search events in ## ###NewIntervals.append([TA,tc]) ###NewIntervals.append([tc,TB]) NewIntervals[NewIntervals_lengthUsed, 0] = TA NewIntervals[NewIntervals_lengthUsed, 1] = tc NewIntervals[NewIntervals_lengthUsed + 1, 0] = tc NewIntervals[NewIntervals_lengthUsed + 1, 1] = TB NewIntervals_lengthUsed += 2 if NewIntervals_lengthUsed >= OldIntervals_lengthMax: print( 'error: increase size of NewIntervals array to avoid this error' ) return resultsArray, Nact_atom, OldIntervals_lengthUsed_max, hop_number else: ## there is no hop detected in that interval [TA,TB]: for tc in range(TA, TB): if tc % every_recAlways == 0: ## we want to record frames anyways, every some... resultsArray[atom, tc, 0] = tc resultsArray[atom, tc, 1] = -1.0 * phop[tc - TA] resultsArray[atom, tc, 2] = 0 resultsArray[atom, tc, 3] = TA resultsArray[atom, tc, 4] = TB resultsArray[atom, tc, 5] = 42 resultsArray[atom, tc, 6] = 42 resultsArray[atom, tc, 7] = 42 resultsArray[atom, tc, 8] = -1 resultsArray[atom, tc, 9] = -1 resultsArray[atom, tc, 10] = -1 ## resultsArray[atom, tc, 11] is not used because the site is not in the lsit of active times ## #### end of the for loop on all (TA,TB) pairs ### OldIntervals_lengthUsed = NewIntervals_lengthUsed OldIntervals_lengthUsed_max = max(OldIntervals_lengthUsed_max, OldIntervals_lengthUsed) OldIntervals[: OldIntervals_lengthUsed] = NewIntervals[: NewIntervals_lengthUsed] ## almost a ffull copy ! # ## remember the size of the "list" # resultsArray[atom, 1:NactiveTimes,11] = np.sort(resultsArray[atom,1:NactiveTimes,11]) # resultsArray[atom, 0 ,11] = NactiveTimes Nact_atom[atom] = NactiveTimes - 1 ############################################################################### return resultsArray, Nact_atom, OldIntervals_lengthUsed_max, hop_number
def dist_numbaFunction(positions, nOcc_array, back_table, rMax, linear_number_cells, cellsUnitLength, shift_vector): Natoms = positions.shape[0] resultArray = np.zeros((Natoms, max_neighb_number, 2)) dist_num = np.zeros(Natoms, dtype=int32) ## sweep atom once to build their index: histog = np.digitize(positions, cellsGrid) histog -= 1 ## becasue I don't like numpy's convention ### sweep atoms once to build the backwards-table of index: for atom in range(Natoms): i = histog[atom, 0] j = histog[atom, 1] k = histog[atom, 2] back_table[i, j, k, nOcc_array[i, j, k]] = atom nOcc_array[i, j, k] += 1 # ## We want to check that, here, but numba does not agree: # if nOcc_array[i,j,k] == max_occupancy : # print("Error: increase max_numberDensity so that max_occupancy is larger than "+str(max_occupancy)) # raise SystemExit limitSup = (linear_number_cells + 3**0.5 ) # # Lx/cellsUnitLength + 3**0.5 +1 indexMax = int(np.ceil((rMax / cellsUnitLength) + 1)) # print('indexMax=') # print(indexMax) # max index shift (in units of cell size) where we will look for neighbors (at distance less than rMax) NMax = 8000 linear_number_cellsStart = linear_number_cells if linear_number_cellsStart**3 * 1.2 > NMax: linear_number_cellsStart = int( (NMax / 1.2)**0.33333333333333333333333) previousRec = 0.0 ### sweep each atom once and then all of its neighbors (some of them are uselss, not many) for i in range(linear_number_cellsStart): for j in range(linear_number_cellsStart): for k in range(linear_number_cellsStart): ## now looking for neighbors of this cell ## TODO : optimization : ## loop only over shorter ranges, that may go outsuide the box, ## and then use ineighb % linear_number_cells to go back inside the box # the ranges may be sthg like : range(i, i+indexMax): #or more cost: (i-indexMax, i+indexMax) (then indexMax must not be too large) for ineighb in range(linear_number_cells): for jneighb in range(linear_number_cells): for kneighb in range(linear_number_cells): ## super-optimization: we cut the search to the enclosing sphere. ## apply PBC to the *distances* di = module_PBC.applyPBC_pair_func( i, ineighb, linear_number_cells) if shift_vector[0] > 0: di = module_PBC.applyPBC_pair_func( i, ineighb - shift_cells, linear_number_cells) # XXX dj = module_PBC.applyPBC_pair_func( j, jneighb, linear_number_cells) dk = module_PBC.applyPBC_pair_func( k, kneighb, linear_number_cells) # di = abs(i-ineighb) % linear_number_cells/2 ## rounding down is the desired behav # dj = abs(j-jneighb) % linear_number_cells/2 # dk = abs(k-kneighb) % linear_number_cells/2 if np.sqrt((di)**2 + (dj)**2 + (dk)**2) <= limitSup: ### this could be placed earlier, but here is fine too (faster): nOccLoc = nOcc_array[i, j, k] nOccNeighb = nOcc_array[ineighb, jneighb, kneighb] for nSelf in range(nOccLoc): atom = back_table[i, j, k, nSelf] pos = positions[atom] for nNeighb in range(nOccNeighb): atom_b = back_table[ineighb, jneighb, kneighb, nNeighb] pos_neighb = positions[atom_b] displacements = module_PBC.applyPBC_vector_func( pos - pos_neighb - shift_vector, Lx) dist = np.sqrt( np.sum((displacements)**2) ) ## TODO optimize this as a separate function, # knowing that dim=3 if dist < rMax: resultArray[atom, dist_num[atom], 0] = dist resultArray[atom, dist_num[atom], 1] = atom_b dist_num[atom] += 1 ##DEBUG : used to find and check the limitSup : #tmp= np.sqrt((di)**2+(dj)**2+(dk)**2) #if tmp > previousRec : # previousRec = tmp # save =((di), (dj), (dk)) #### DEBUG too: #print(previousRec, limitSup , rMax/cellsUnitLength, cellsUnitLength, rMax) #print(save) return resultArray, dist_num