fargopy 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fargopy/conf.py DELETED
@@ -1,20 +0,0 @@
1
- ###############################################################
2
- # FARGOpy interdependencies
3
- ###############################################################
4
- import fargopy
5
-
6
- ###############################################################
7
- # Required packages
8
- ###############################################################
9
-
10
- ###############################################################
11
- # Classes
12
- ###############################################################
13
-
14
- #/////////////////////////////////////
15
- # CONFIGURATION CLASS
16
- #/////////////////////////////////////
17
- class Conf(object):
18
- """Configuration class.
19
- """
20
-
fargopy/fargo3d.py DELETED
@@ -1,505 +0,0 @@
1
- ###############################################################
2
- # FARGOpy interdependencies
3
- ###############################################################
4
- import fargopy
5
-
6
- ###############################################################
7
- # Required packages
8
- ###############################################################
9
- import os
10
- import numpy as np
11
- import re
12
-
13
- ###############################################################
14
- # Constants
15
- ###############################################################
16
- KB = 1.380650424e-16 # Boltzmann constant: erg/K, erg = g cm^2 / s^2
17
- MP = 1.672623099e-24 # Mass of the proton, g
18
- GCONST = 6.67259e-8 # Gravitational constant, cm^3/g/s^2
19
- RGAS = 8.314472e7 # Gas constant, erg /K/mol
20
- MSUN = 1.9891e33 # g
21
- AU = 1.49598e13 # cm
22
- YEAR = 31557600.0 # s
23
-
24
- # Map of coordinates into FARGO3D coordinates
25
- COORDS_MAP = dict(
26
- cartesian = dict(x='x',y='y',z='z'),
27
- cylindrical = dict(phi='x',r='y',z='z'),
28
- spherical = dict(phi='x',r='y',theta='z'),
29
- )
30
-
31
- ###############################################################
32
- # Classes
33
- ###############################################################
34
- class Fargobj(object):
35
- def __init__(self):
36
- self.fobject = True
37
-
38
- def has(self,key):
39
- if key in self.__dict__.keys():
40
- return True
41
- else:
42
- return False
43
-
44
- class Fargo3d(Fargobj):
45
-
46
- def __init__(self):
47
- super().__init__()
48
-
49
- def compile_fargo3d(self,clean=True):
50
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
51
- if clean:
52
- Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} clean mrproper',verbose=False)
53
-
54
- error,out = Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} PARALLEL={self.parallel} GPU={self.gpu}',verbose=False)
55
- if error:
56
- if not Conf._check_fargo_binary(Conf.FARGO3D_FULLDIR,quiet=True):
57
- print("An error compiling the code arose. Check dependencies.")
58
- print(Util.STDERR)
59
- return False
60
-
61
- return True
62
-
63
- class Field(Fargobj):
64
- """Fields:
65
-
66
- Attributes:
67
- coordinates: type of coordinates (cartesian, cylindrical, spherical)
68
- data: numpy arrays with data of the field
69
-
70
- Methods:
71
- slice: get an slice of a field along a given spatial direction.
72
- Examples:
73
- density.slice(r=0.5) # Take the closest slice to r = 0.5
74
- density.slice(ir=20) # Take the slice through the 20 shell
75
- density.slice(phi=30*RAD,interp='nearest') # Take a slice interpolating to the nearest
76
- """
77
-
78
- def __init__(self,data=None,coordinates='cartesian',domains=None):
79
- self.data = data
80
- self.coordinates = coordinates
81
- self.domains = domains
82
-
83
- def meshslice(self,slice='x,y,z',output='cartesian:x,y,z'):
84
- """Perform a slice on a field and produce as an output the
85
- corresponding field slice and the associated matrices of
86
- coordinates for plotting.
87
-
88
- Examples:
89
- # Don't do nothing, but r, phi, z are matrices with the same dimensions of gasdens
90
- r,phi,z,gasdens = gasdens.meshslice(slice='r,phi,z', output='cylindrical:r,phi,z')
91
-
92
- # Make a z=0 slice and return the r and phi matrices for plotting the field.
93
- r,phi,gasdens_rp = gasdens.meshslice(slice='r,phi,z=0', output='spherica:r,phi')
94
- plt.pcolormesh(r,phi,gasdens_rp)
95
- plt.pcolormesh(phi,r,gasdens_rp.T)
96
-
97
- # Make a z=0, iphi = 0 slice and return r
98
- r, gasdens_r = gasdens.meshslice(slice='r,iphi=0,z=0', output='cylindrical:r')
99
- plt.plot(r,gasdens_r)
100
-
101
- # Make a z = 0 slice and express the result in cartesian coordinates
102
- x,y,gasdens_xy = gasdens.meshslice(slice='r,phi,z=0', output='cartesian:x,y')
103
- plt.pcolormesh(x,y,gasdens_xy)
104
-
105
- # Make a phi = 0 slice and express the result in cartesian coordinates
106
- y,z,gasdens_yz = gasdens.meshslice(slice='r,phi=0,z', output='cartesian:y,z')
107
- plt.pcolormesh(y,z,gasdens_yz)
108
- """
109
- # Analysis of the slice
110
-
111
- # Perform the slice
112
- slice_cmd = f"self.slice({slice},pattern=True)"
113
- slice,pattern = eval(slice_cmd)
114
-
115
- # Create the mesh
116
- if self.coordinates == 'cartesian':
117
- z,y,x = np.meshgrid(self.domains.z,self.domains.y,self.domains.x,indexing='ij')
118
- x,y,z = r*np.cos(phi),r*np.sin(phi),z
119
-
120
- x = eval(f"x[{pattern}]")
121
- y = eval(f"y[{pattern}]")
122
- z = eval(f"z[{pattern}]")
123
-
124
- mesh = fargopy.Dictobj(dict=dict(x=x,y=y,z=z))
125
-
126
- if self.coordinates == 'cylindrical':
127
- z,r,phi = np.meshgrid(self.domains.z,self.domains.r,self.domains.phi,indexing='ij')
128
- x,y,z = r*np.cos(phi),r*np.sin(phi),z
129
-
130
- x = eval(f"x[{pattern}]")
131
- y = eval(f"y[{pattern}]")
132
- z = eval(f"z[{pattern}]")
133
- r = eval(f"r[{pattern}]")
134
- phi = eval(f"phi[{pattern}]")
135
-
136
- mesh = fargopy.Dictobj(dict=dict(r=r,phi=phi,x=x,y=y,z=z))
137
-
138
- if self.coordinates == 'spherical':
139
- theta,r,phi = np.meshgrid(self.domains.theta,self.domains.r,self.domains.phi,indexing='ij')
140
- x,y,z = r*np.sin(theta)*np.cos(phi),r*np.sin(theta)*np.sin(phi),r*np.cos(theta)
141
-
142
- x = eval(f"x[{pattern}]")
143
- y = eval(f"y[{pattern}]")
144
- z = eval(f"z[{pattern}]")
145
- r = eval(f"r[{pattern}]")
146
- phi = eval(f"phi[{pattern}]")
147
- theta = eval(f"theta[{pattern}]")
148
-
149
- mesh = fargopy.Dictobj(dict=dict(r=r,phi=phi,theta=theta,x=x,y=y,z=z))
150
-
151
- return slice,mesh
152
-
153
- def slice(self,quiet=True,pattern=False,**kwargs):
154
- """Extract an slice of a 3-dimensional FARGO3D field
155
-
156
- Parameters:
157
- quiet: boolean, default = False:
158
- If True extract the slice quietly.
159
- Else, print some control messages.
160
-
161
- ir, iphi, itheta, ix, iy, iz: string or integer:
162
- Index or range of indexes of the corresponding coordinate.
163
-
164
- r, phi, theta, x, y, z: float:
165
- Value for slicing. The slicing search for the closest
166
- value in the domain.
167
-
168
- Returns:
169
- slice: sliced field.
170
-
171
- Examples:
172
- # 0D: Get the value of the field in iphi = 0, itheta = -1 and close to r = 0.82
173
- gasvz.slice(iphi=0,itheta=-1,r=0.82)
174
-
175
- # 1D: Get all values of the field in radial direction at iphi = 0, itheta = -1
176
- gasvz.slice(iphi=0,itheta=-1)
177
-
178
- # 2D: Get all values of the field for values close to phi = 0
179
- gasvz.slice(phi=0)
180
- """
181
- # By default slice
182
- ivar = dict(x=':',y=':',z=':')
183
-
184
- if len(kwargs.keys()) == 0:
185
- pattern_str = f"{ivar['z']},{ivar['y']},{ivar['x']}"
186
- if pattern:
187
- return self.data, pattern_str
188
- return self.data
189
-
190
- # Check all conditions
191
- for key,item in kwargs.items():
192
- match = re.match('^i(.+)',key)
193
- if match:
194
- index = item
195
- coord = match.group(1)
196
- if not quiet:
197
- print(f"Index condition {index} for coordinate {coord}")
198
- ivar[COORDS_MAP[self.coordinates][coord]] = index
199
- else:
200
- if not quiet:
201
- print(f"Numeric condition found for coordinate {key}")
202
- if key in self.domains.keys():
203
- # Check if value provided is in range
204
- domain = self.domains.item(key)
205
- extrema = self.domains.extrema[key]
206
- min, max = extrema[0][1], extrema[1][1]
207
- if (item<min) or (item>max):
208
- raise ValueError(f"You are attempting to get a slice in {key} = {item}, but the valid range for this variable is [{min},{max}]")
209
- find = abs(self.domains.item(key) - item)
210
- ivar[COORDS_MAP[self.coordinates][key]] = find.argmin()
211
-
212
- pattern_str = f"{ivar['z']},{ivar['y']},{ivar['x']}"
213
- slice_cmd = f"self.data[{pattern_str}]"
214
- if not quiet:
215
- print(f"Slice: {slice_cmd}")
216
- slice = eval(slice_cmd)
217
-
218
- if pattern:
219
- return slice,pattern_str
220
- return slice
221
-
222
- def get_size(self):
223
- return self.data.nbytes
224
-
225
- def __str__(self):
226
- return str(self.data)
227
-
228
- def __repr__(self):
229
- return str(self.data)
230
-
231
- class Simulation(Fargo3d):
232
-
233
- def __init__(self):
234
- super().__init__()
235
- self.output_dir = None
236
- self.set_units(UL=AU,UM=MSUN)
237
-
238
- def set_output_dir(self,dir):
239
- if not os.path.isdir(dir):
240
- print(f"Directory '{dir}' does not exist.")
241
- else:
242
- print(f"Now you are connected with output directory '{dir}'")
243
- self.output_dir = dir
244
-
245
- def list_outputs(self,quiet=False):
246
- if self.output_dir is None:
247
- print(f"You have to set forst the outputs directory with <sim>.set_outputs('<directory>')")
248
- else:
249
- error,output = fargopy.Sys.run(f"ls {self.output_dir}")
250
- if error == 0:
251
- files = output[:-1]
252
- print(f"{len(files)} files in output directory")
253
- if not quiet:
254
- file_list = ""
255
- for i,file in enumerate(files):
256
- file_list += f"{file}, "
257
- if ((i+1)%10) == 0:
258
- file_list += "\n"
259
- print(file_list)
260
- return files
261
-
262
- def load_properties(self,quiet=False,
263
- varfile='variables.par',
264
- domain_prefix='domain_',
265
- dimsfile='dims.dat'
266
- ):
267
- if self.output_dir is None:
268
- print(f"You have to set forst the outputs directory with <sim>.set_outputs('<directory>')")
269
-
270
- # Read variables
271
- vars = self._load_variables(varfile)
272
- print(f"Simulation in {vars.DIM} dimensions")
273
-
274
- # Read domains
275
- domains = self._load_domains(vars,domain_prefix)
276
-
277
- # Store the variables in the object
278
- self.vars = vars
279
- self.domains = domains
280
-
281
- # Optionally read dims
282
- dims = self._load_dims(dimsfile)
283
- if len(dims):
284
- self.dims = dims
285
-
286
- print("Configuration variables and domains load into the object. See e.g. <sim>.vars")
287
- return vars, domains
288
-
289
- def _load_dims(self,dimsfile):
290
- """Parse the dim directory
291
- """
292
- dimsfile = f"{self.output_dir}/{dimsfile}".replace('//','/')
293
- if not os.path.isfile(dimsfile):
294
- #print(f"No file with dimensions '{dimsfile}' found.")
295
- return []
296
- dims = np.loadtxt(dimsfile)
297
- return dims
298
-
299
- def _load_variables(self,varfile):
300
- """Parse the file with the variables
301
- """
302
-
303
- varfile = f"{self.output_dir}/{varfile}".replace('//','/')
304
- if not os.path.isfile(varfile):
305
- print(f"No file with variables named '{varfile}' found.")
306
- return
307
-
308
- print(f"Loading variables")
309
- variables = np.genfromtxt(
310
- varfile,dtype={'names': ("parameters","values"),
311
- 'formats': ("|S30","|S300")}
312
- ).tolist()
313
-
314
- vars = dict()
315
- for posicion in variables:
316
- str_value = posicion[1].decode("utf-8")
317
- try:
318
- value = int(str_value)
319
- except:
320
- try:
321
- value = float(str_value)
322
- except:
323
- value = str_value
324
- vars[posicion[0].decode("utf-8")] = value
325
-
326
- vars = fargopy.Dictobj(dict=vars)
327
- print(f"{len(vars.__dict__.keys())} variables loaded")
328
-
329
- # Create additional variables
330
- variables = ['x', 'y', 'z']
331
- if vars.COORDINATES == 'cylindrical':
332
- variables = ['phi', 'r', 'z']
333
- elif vars.COORDINATES == 'spherical':
334
- variables = ['phi', 'r', 'theta']
335
- vars.VARIABLES = variables
336
-
337
- vars.__dict__[f'N{variables[0].upper()}'] = vars.NX
338
- vars.__dict__[f'N{variables[1].upper()}'] = vars.NY
339
- vars.__dict__[f'N{variables[2].upper()}'] = vars.NZ
340
-
341
- # Dimension of the domain
342
- vars.DIM = 2 if vars.NZ == 1 else 3
343
-
344
- return vars
345
-
346
- def _load_domains(self,vars,domain_prefix,
347
- borders=[[],[3,-3],[3,-3]],
348
- middle=True):
349
-
350
- # Coordinates
351
- variable_suffixes = ['x', 'y', 'z']
352
- print(f"Loading domain in {vars.COORDINATES} coordinates:")
353
-
354
- # Correct dims in case of 2D
355
- if vars.DIM == 2:
356
- borders[-1] = []
357
-
358
- # Load domains
359
- domains = dict()
360
- domains['extrema'] = dict()
361
-
362
- for i,variable_suffix in enumerate(variable_suffixes):
363
- domain_file = f"{self.output_dir}/{domain_prefix}{variable_suffix}.dat".replace('//','/')
364
- if os.path.isfile(domain_file):
365
-
366
- # Load data from file
367
- domains[vars.VARIABLES[i]] = np.genfromtxt(domain_file)
368
-
369
- if len(borders[i]) > 0:
370
- # Drop the border of the domain
371
- domains[vars.VARIABLES[i]] = domains[vars.VARIABLES[i]][borders[i][0]:borders[i][1]]
372
-
373
- if middle:
374
- # Average between domain cell coordinates
375
- domains[vars.VARIABLES[i]] = 0.5*(domains[vars.VARIABLES[i]][:-1]+domains[vars.VARIABLES[i]][1:])
376
-
377
- # Show indices and value map
378
- domains['extrema'][vars.VARIABLES[i]] = [[0,domains[vars.VARIABLES[i]][0]],[-1,domains[vars.VARIABLES[i]][-1]]]
379
-
380
- print(f"\tVariable {vars.VARIABLES[i]}: {len(domains[vars.VARIABLES[i]])} {domains['extrema'][vars.VARIABLES[i]]}")
381
- else:
382
- print(f"\tDomain file {domain_file} not found.")
383
- domains = fargopy.Dictobj(dict=domains)
384
-
385
- return domains
386
-
387
- def load_field(self,field,snapshot=None,type='scalar'):
388
-
389
- if not self.has('vars'):
390
- # If the simulation has not loaded the variables
391
- dims, vars, domains = sim.load_properties()
392
-
393
- # In case no snapshot has been provided use 0
394
- snapshot = 0 if snapshot is None else snapshot
395
-
396
- field_data = []
397
- if type == 'scalar':
398
- file_name = f"{field}{str(snapshot)}.dat"
399
- file_field = f"{self.output_dir}/{file_name}".replace('//','/')
400
- field_data = self._load_field_scalar(file_field)
401
- elif type == 'vector':
402
- field_data = []
403
- variables = ['x','y']
404
- if self.vars.DIM == 3:
405
- variables += ['z']
406
- for i,variable in enumerate(variables):
407
- file_name = f"{field}{variable}{str(snapshot)}.dat"
408
- file_field = f"{self.output_dir}/{file_name}".replace('//','/')
409
- field_data += [self._load_field_scalar(file_field)]
410
- else:
411
- raise ValueError(f"Field type '{type}' not recognized.")
412
-
413
- field = Field(data=np.array(field_data), coordinates=self.vars.COORDINATES, domains=self.domains)
414
- return field
415
-
416
- def _load_field_scalar(self,file):
417
- """Load scalar field from file a file.
418
- """
419
- if os.path.isfile(file):
420
- field_data = np.fromfile(file).reshape(int(self.vars.NZ),int(self.vars.NY),int(self.vars.NX))
421
- """
422
- if self.vars.NZ > 1:
423
- # 3D field
424
- field_data = np.fromfile(file).reshape(int(self.vars.NZ),int(self.vars.NY),int(self.vars.NX))
425
- else:
426
- # 2D field
427
- field_data = np.fromfile(file).reshape(int(self.vars.NY),int(self.vars.NX))
428
- """
429
- return field_data
430
- else:
431
- raise AssertionError(f"File with field '{file}' not found")
432
-
433
- def load_allfields(self,fluid,snapshot=None):
434
- """Load all fields in the output
435
- """
436
- qall = False
437
- if snapshot is None:
438
- qall = True
439
- fields = fargopy.Dictobj()
440
- else:
441
- fields = fargopy.Dictobj()
442
-
443
- # Search for field files
444
- pattern = f"{self.output_dir}/{fluid}*.dat"
445
- error,output = fargopy.Sys.run(f"ls {pattern}")
446
-
447
- if not error:
448
- size = 0
449
- for file_field in output[:-1]:
450
- comps = Simulation._parse_file_field(file_field)
451
- if comps:
452
- if qall:
453
- # Store all snapshots
454
- field_name = comps[0]
455
- field_snap = int(comps[1])
456
- field_data = self._load_field_scalar(file_field)
457
- if str(field_snap) not in fields.keys():
458
- fields.__dict__[str(field_snap)] = fargopy.Dictobj()
459
- size += field_data.nbytes
460
- (fields.__dict__[str(field_snap)]).__dict__[f"{field_name}"] = Field(data=field_data, coordinates=self.vars.COORDINATES, domains=self.domains)
461
- else:
462
- # Store a specific snapshot
463
- if int(comps[1]) == snapshot:
464
- field_name = comps[0]
465
- field_data = self._load_field_scalar(file_field)
466
- size += field_data.nbytes
467
- fields.__dict__[f"{field_name}"] = Field(data=field_data, coordinates=self.vars.COORDINATES, domains=self.domains)
468
-
469
- else:
470
- raise ValueError(f"No field found with pattern '{pattern}'. Change the fluid")
471
-
472
- if qall:
473
- fields.snapshots = sorted([int(s) for s in fields.keys() if s != 'size'])
474
- fields.size = size/1024**2
475
- return fields
476
-
477
- @staticmethod
478
- def _parse_file_field(file_field):
479
- basename = os.path.basename(file_field)
480
- comps = None
481
- match = re.match('([a-zA-Z]+)(\d+).dat',basename)
482
- if match is not None:
483
- comps = [match.group(i) for i in range(1,match.lastindex+1)]
484
- return comps
485
-
486
- def set_units(self,UM=MSUN,UL=AU,G=1,mu=2.35):
487
- """Set units of simulation
488
- """
489
- # Basic
490
- self.UM = UM
491
- self.UL = UL
492
- self.G = G
493
- self.UT = (G*self.UL**3/(GCONST*self.UM))**0.5 # In seconds
494
-
495
- # Thermodynamics
496
- self.UTEMP = (GCONST*MP*mu/KB)*self.UM/self.UL # In K
497
-
498
- # Derivative
499
- self.USIGMA = self.UM/self.UL**2 # In g/cm^2
500
- self.URHO = self.UM/self.UL**3 # In kg/m^3
501
- self.UEPS = self.UM/(self.UL*self.UT**2) # In J/m^3
502
- self.UV = self.UL/self.UT
503
-
504
-
505
-