-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwrite_to_file.py
More file actions
375 lines (292 loc) · 10.6 KB
/
write_to_file.py
File metadata and controls
375 lines (292 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
import numpy as np
from typing import Optional
import datetime
"""
Code for making a LAMMPS data file from arrays. By Zafer Kosar 2022.
Arrays must be 2-dimensional Numpy Arrays in the following format.
Number of Rows = Particle or Atoms Number
Number of Columns = Depends on the Atoms # {Style}
| atom-id | atom-type | mol-type | x-coor | y-coor | z-coor |
___________________________________________________________________
| 1 | 2 | 2 | 33.54612 | -34.1297 | 6.121313 |
-------------------------------------------------------------------
...
...
...
...
-------------------------------------------------------------------
| 1071 | 1 | 1 | 66.54612 | 44.21379 | 120.0987 |
-------------------------------------------------------------------
Note that this is Atoms array in the 'angles' style which requires 6 columns.
Other style may employ different numbers of columns. Check the LAMMPS manual.
_____________________________________________________________________________
Arrays can be:
1- Atoms(Must) :
-> |atom-id|atom-type|mol-type|x-coor|y-coor|z-coor|
2- Bonds :
-> |bond-id|bond-type|atom-id_1|atom-id_2|
3- Angles :
-> |angle-id|angle-type|atom-id_1|atom-id_2|atom-id_3|
4- Dihedrals :
-> |angle-id|angle-type|atom-id_1|atom-id_2|atom-id_3|atom-id_4|
...etc.,
_____________________________________________________________________________
function 'make_up_arrays' just creates sample arrays (i.e., atoms,bonds,angles)
for testing also giving an idea of the array structures.
_____________________________________________________________________________
function 'arr2str' generates a string from array in a file-writable format.
_____________________________________________________________________________
function 'describe' generates a string required in the beginning of data file.
e.g.,
-----------------------------------------
LAMMPS Data file -- Created in:2022-11-07
20000 atoms
3 atom types
20000 bonds
3 bond types
20000 angles
3 angle types
-----------------------------------------
_____________________________________________________________________________
function 'simulation_box' generates a string containing boundary information
for the data file.
e.g.,
----------------------
-60.123 60.123 xlo xhi
-60.123 60.123 ylo yhi
-60.123 60.123 zlo zhi
----------------------
_____________________________________________________________________________
function 'unite_strings' unites the strings to form a complete string to be
written to a file.
Note that the order here is important and should be in the following order.
-------------------------------------------------------------
whole_str = unite_strings(description, #from 'describe'
box_str, #from 'simulation_box'
atoms_str, #from 'arr2str'
bonds_str, #from 'arr2str'
angles_str, #from 'arr2str'
.
.
.
)
-------------------------------------------------------------
_____________________________________________________________________________
Sample use of the complete code is as follows.
--------------------------------------------------------------
if __name__ == '__main__':
#some arrays
atoms,bonds,angles = make_up_arrays(size=20000)
#initial text describing component
description = describe((atoms,'atoms'),
(bonds,'bonds'),
(angles,'angles'))
#simulation box boundaries
box_str = simulation_box(60.123,60.123,60.123,mirror=1,
xlo=55,ylo=31,zlo=15)
#strings of arrays
atoms_str = arr2str(arr=atoms,name='Atoms',style='angle')
bonds_str = arr2str(arr=bonds,name='Bonds')
angles_str = arr2str(arr=angles,name='Angles')
#arrays united --note that order is important
whole_str = unite_strings(description,
box_str,
atoms_str,
bonds_str,
angles_str)
with open('deneme.data','w') as f:
f.write(whole_str)
----------------------------------------------------------------
______________________________________________________________________________
"""
def make_up_arrays(size:int=260):
"""
Just making up some arrays for testing
Parameters
----------
size : int, optional
Number of atoms. The default is 260.
Returns
-------
atoms : np.ndarray
2D atoms Array.
bonds : np.ndarray
2D bonds Array.
angles : np.ndarray
2D angles Array.
"""
#arrays
atoms = np.random.rand(size,6).astype(np.float32)
atoms =atoms*120-60
bonds = np.ones([size,4]).astype(int)
angles = np.ones([size,5]).astype(int)
#setting their ids
atoms[:,0] = np.arange(len(atoms))+1
bonds[:,0] = np.arange(len(bonds))+1
angles[:,0] = np.arange(len(angles))+1
#setting the types
#for atoms
atoms[:,1] = 1
atoms[:100,1] = 2
atoms[-100:,1] = 3
atoms[:,2] = atoms[:,1]
#for bonds
bonds[:,1] = 1
bonds[:100,1] = 2
bonds[-100:,1] = 3
#for angles
angles[:,1] = 1
angles[:100,1] = 2
angles[-100:,1] = 3
return atoms,bonds,angles
def arr2str(arr:np.ndarray,name:str,style:Optional[str]=None)->str:
"""
Turn array into str with the LAMMPS data file format.
Parameters
----------
arr : np.ndarray
Array to be t.
name : str
Name of the array (Atoms, Angles, Bonds,...)
style : str
Style of the given array.
Returns
-------
str
String version of the array with the title of 'name # style'.
"""
name = name.capitalize() #a precaution for format req.
#initing strimng with the title
if style:
style = style.lower()#another precuation for format req.
string = f'{name} # {style}\n\n'
else:
string = f'{name}\n\n'
#browsing through every value
for row in arr:
for val in row:
#if the value is integer they are removed off their decimals
if int(val) == val:
string+= f'{int(val)} '
else:
string+= f'{val} '
#go next line after every row
string+='\n'
#leaving a gap for the next array to be written
string+='\n'
return string #final str is returned
def describe(*arr_tup:tuple)->str:
"""
Description part of the data file.
e.g.,
1234 atoms
12 atom type
...
Parameters
----------
*arr_tup : tuple
Array itself and its Name as such (arr,tuple) e.g. (atoms,'atoms')
Returns
-------
str
Description of the simulation components.
"""
date = datetime.datetime.now().date()
text = f'LAMMPS Data file -- Created in:{date}\n\n'
for tup in arr_tup:
#seperating array and its name
arr = tup[0]
name = tup[1].lower()
#forming the count line e.g., 1234 atoms
count = len(arr) #size
number_line = f'{count} {name}\n'
#forming the type number line
type_column = arr[:,1]
type_num = len(np.unique(type_column))
type_line = f'{type_num} {name[:-1]} types\n'
text+=number_line+type_line
text += '\n\n'
return text
def simulation_box(xhi:float,yhi:float,zhi:float,
mirror:bool=True,**xyz_lows)->str:
"""
Parameters
----------
xhi : float
x high boundary.
yhi : float
y high boundary.
zhi : float
z high boundary.
mirror : bool, optional
When True, mirrors the high boundaries as their negatives.
The default is True.
**xyz_lows : kwargs
xlo,ylo,zlo.
Raises
------
ValueError
if mirror==False and no xlo,ylo,zlo value given.
Returns
-------
str
Simulation box description text.
"""
text = ''
err = 'if mirror=False Keyword values of xlo,ylo,zlo must be given --> '
eg = 'e.g xlo=value1,ylo=value2,zlo=value3'
if mirror:
xline=f'{-xhi} {xhi} xlo xhi\n'
yline=f'{-yhi} {yhi} ylo yhi\n'
zline=f'{-zhi} {zhi} zlo zhi\n'
text+=xline+yline+zline
else:
if xyz_lows == dict():
raise ValueError(err+eg)
xlo = xyz_lows['xlo']
ylo = xyz_lows['ylo']
zlo = xyz_lows['zlo']
xline=f'{xlo} {xhi} xlo xhi\n'
yline=f'{ylo} {yhi} ylo yhi\n'
zline=f'{zlo} {zhi} zlo zhi\n'
text+=xline+yline+zline
text+='\n\n'
return text
def unite_strings(*strings)->str:
"""
Takes strings and unites them in input order.
Parameters
----------
*strings : str
String parts.
Returns
-------
str
United string.
"""
full_str = ''
for string in strings:
full_str+=string
return full_str
if __name__ == '__main__':
#some arrays
atoms,bonds,angles = make_up_arrays(size=20000)
#initial text describing component
description = describe((atoms,'atoms'),
(bonds,'bonds'),
(angles,'angles'))
#simulation box boundaries
box_str = simulation_box(60.123,60.123,60.123,mirror=1,
xlo=55,ylo=31,zlo=15)
#strings of arrays
atoms_str = arr2str(arr=atoms,name='Atoms',style='angle')
bonds_str = arr2str(arr=bonds,name='Bonds')
angles_str = arr2str(arr=angles,name='Angles')
#arrays united --note that order is important
whole_str = unite_strings(description,
box_str,
atoms_str,
bonds_str,
angles_str)
with open('deneme.data','w') as f:
f.write(whole_str)