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/__cycle1.py DELETED
@@ -1,880 +0,0 @@
1
- ###############################################################
2
- # Import montu modules
3
- ###############################################################
4
- from fargopy.version import *
5
-
6
- ###############################################################
7
- # Required packages
8
- ###############################################################
9
- import os
10
- import subprocess
11
- import inspect
12
- import signal
13
-
14
- # Remove zombie subprocesses
15
- signal.signal(signal.SIGCHLD, signal.SIG_IGN)
16
-
17
- ###############################################################
18
- # Module constants
19
- ###############################################################
20
- FARGOPY_CONFIGURATION = dict(
21
- VERBOSE = False,
22
- FARGO3D_CLONE_REPO_CMD = 'git clone https://bitbucket.org/fargo3d/public.git',
23
- FARGO3D_BASEDIR = './',
24
- FARGO3D_PACKDIR = 'public/',
25
- FARGO3D_FULLDIR = './public/',
26
- FARGO3D_HEADER = 'src/fargo3d.h',
27
- FARGO3D_BINARY = 'fargo3d',
28
- SYS_STDOUT = '',
29
- SYS_STDERR = '',
30
- )
31
-
32
- ###############################################################
33
- # Classes
34
- ###############################################################
35
-
36
- #/////////////////////////////////////
37
- # UTIL CLASS
38
- #/////////////////////////////////////
39
- class Util(object):
40
-
41
- QERROR = True
42
- STDERR = ''
43
- STDOUT = ''
44
-
45
- @staticmethod
46
- def get_methods(my_class):
47
- """Get a list of the methods for class my_class
48
- """
49
- return sorted([member[0] for member in inspect.getmembers(my_class) if '__' not in member[0]])
50
-
51
- @staticmethod
52
- def data_path(filename,check=False):
53
- """Get the full path of the `datafile` which is one of the datafiles provided with the package.
54
-
55
- Parameters:
56
- filename: Name of the data file, string.
57
-
58
- Return:
59
- Full path to package datafile in the python environment.
60
-
61
- """
62
- file_path = os.path.join(os.path.dirname(__file__),'data',filename)
63
- if check and (not os.path.isfile(file_path)):
64
- raise ValueError(f"File '{filename}' does not exist in data directory")
65
- return file_path
66
-
67
- @staticmethod
68
- def sysrun(cmd):
69
- if Conf.VERBOSE:
70
- print(f"::FARGOpy:: Running: {cmd}")
71
- os.system(cmd)
72
-
73
- @staticmethod
74
- def _run(cmd):
75
- p=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
76
- while True:
77
- line = p.stdout.readline().rstrip()
78
- if not line:
79
- break
80
- yield line
81
- (output,error)=p.communicate()
82
- yield p.returncode,error
83
-
84
- @staticmethod
85
- def sysrun(cmd,verbose=True):
86
- """Run a system command
87
- """
88
-
89
- if Conf.VERBOSE:
90
- print(f"::FARGOpy::sysrun::cmd = {cmd}")
91
-
92
- out=[]
93
- for path in Util._run(cmd):
94
- try:
95
- if verbose:
96
- print(path.decode('utf-8'))
97
- out += [path.decode('utf-8')]
98
- except:
99
- out += [(path[0],path[1].decode('utf-8'))]
100
-
101
- Util.STDOUT = ''
102
- if len(out)>1:
103
- Util.STDOUT = '\n'.join(out[:-1])
104
-
105
- Util.STDERR = out[-1][1]
106
- if len(Util.STDERR)>0:
107
- Util.QERROR = out[-1][0]
108
- if Util.QERROR == 0:
109
- Util.QERROR = -1
110
- else:
111
- Util.QERROR = 0
112
-
113
- if Util.QERROR and verbose:
114
- print(f"Error:\n{Util.STDERR}")
115
-
116
- if Conf.VERBOSE:
117
- error = out[-1][0]
118
- if Util.QERROR>0:
119
- print(f"::FARGOpy::sysrun::Error check Util.STDERR.")
120
- elif Util.QERROR<0:
121
- print(f"::FARGOpy::sysrun::Done. Still some issues must be check. Check Util.STDOUT and Util.STDERR for details.")
122
- elif Util.QERROR==0:
123
- print(f"::FARGOpy::sysrun::Done. You're great. Check Util.STDOUT for details.")
124
-
125
- return Util.QERROR,out
126
-
127
- #/////////////////////////////////////
128
- # CONFIGURATION CLASS
129
- #/////////////////////////////////////
130
- class Conf(object):
131
- """Configuration class.
132
- """
133
- VERBOSE = False
134
- FARGO3D_CLONE_REPO_CMD = 'git clone https://bitbucket.org/fargo3d/public.git'
135
- FARGO3D_BASEDIR = './'
136
- FARGO3D_PACKDIR = 'public/'
137
- FARGO3D_SETUPS = 'setups/'
138
- FARGO3D_FULLDIR = './public/'
139
- FARGO3D_HEADER = 'src/fargo3d.h'
140
- FARGO3D_BINARY = 'fargo3d'
141
- FARGO3D_IS_HERE = False
142
- FARGO3D_IS_COMPILING = False
143
- FARGO3D_IS_COMPILING_PARALLEL = False
144
- FARGO3D_IS_COMPILING_GPU = False
145
- FARGO3D_PARALLEL = 0
146
- FARGO3D_GPU = 0
147
- SYS_STDOUT = ''
148
- SYS_STDERR = ''
149
-
150
- def __init__(self):
151
- # Common attributes
152
- self.parallel = 0
153
- self.gpu = 0
154
-
155
- def compile_fargo3d(self,clean=True):
156
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
157
- if clean:
158
- Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} clean mrproper',verbose=False)
159
-
160
- error,out = Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} PARALLEL={self.parallel} GPU={self.gpu}',verbose=False)
161
- if error:
162
- if not Conf._check_fargo_binary(Conf.FARGO3D_FULLDIR,quiet=True):
163
- print("An error compiling the code arose. Check dependencies.")
164
- print(Util.STDERR)
165
- return False
166
-
167
- return True
168
-
169
- def list_setups(self):
170
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
171
- error,output = Util.sysrun(f"ls {Conf.FARGO3D_FULLDIR}/{Conf.FARGO3D_SETUPS}",verbose=False)
172
- if error:
173
- print("No setups found")
174
- return []
175
- else:
176
- setups = output[:-1]
177
- return setups
178
-
179
- @staticmethod
180
- def clean_fargo3d():
181
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
182
- error,out = Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} clean mrproper',verbose=False)
183
-
184
- @staticmethod
185
- def set_fargo3d(basedir=None,react='get compile parallel gpu'):
186
- """Check if FARGO3D is properly installed in the sysem
187
-
188
- Parameters:
189
- basedir: string, default = None:
190
- Set the basedir where FARGO3D installation will be looked-for.
191
- If None, it will assume the by-default value Conf.FARGO3D_BASEDIR
192
- (see constants at the beginning of this file)
193
-
194
- FARGO3D installation will be:
195
- <basedir>/public/...
196
-
197
- react: string, default = 'get compile parallel gpu'
198
- How to react upon a finding. For instance, if FARGO3D installation
199
- is not found in basedir and you set react = 'get', this method
200
- will attempt to get a copy of FARGO3D. Otherwise you may get the
201
- copy by yourself.
202
-
203
- The same for 'compile', that after testing that FARGO3D directory
204
- is present will attempto to compile a basic version of the package.
205
-
206
- 'parallel' and 'gpu' will attempt to compile parallel and GPU
207
- versions of `fargo3d`.
208
- Return:
209
- If everything is correct and the react is configured the method will
210
- end with the package downloaded to basedir, and three basic binaries
211
- `.fargo3d_`, `.fargo3d_PARALLEL-1` and `.fargo3d_GPU-1` in the installation
212
- directory.
213
-
214
- The configuration variables FARGO3D_BASEDIR, FARGO3D_PACKDIR, FARGO3D_FULLDIR
215
- will also be set with this routine.
216
-
217
- Last but not least the following configuration variables will be also set:
218
- FARGO3D_IS_HERE: indicating the package is present.
219
- FARGO3D_IS_COMPILING: indicating the package is properly compiling.
220
- FARGO3D_PARALLEL: 0/1 depending if parallel capabilities are available.
221
- FARGO3D_GPU: 0/1 depending if GPU capabilities are available.
222
- """
223
- no_basedir = False
224
- if not basedir:
225
- no_basedir = True
226
- basedir = Conf.FARGO3D_BASEDIR
227
- else:
228
- if not os.path.isdir(basedir):
229
- raise AssertionError(f"Provided basedir '{basedir}' not even exist")
230
- else:
231
- basedir = basedir[0]+basedir[1:].strip('/')+'/'
232
-
233
- # Check if FARGO3D has been downloaded
234
- print("> Checking for FARGO3D directroy:")
235
- if not Conf._check_fargo(basedir+Conf.FARGO3D_PACKDIR):
236
- if 'get' in react:
237
- print("\tGetting FARGO3D public repo...")
238
- Conf._get_fargo(basedir)
239
- Conf.FARGO3D_IS_HERE = True
240
- else:
241
- options = "" if no_basedir else f"basedir='{basedir}',"
242
- print(f"\tDownload it with `set_fargo3d({options}react='get')` or set variable Conf.configure_fargo3d('{basedir}','public').""")
243
- return
244
- else:
245
- print(f"\t✓FARGO3D source code is available in your system at '{basedir+Conf.FARGO3D_PACKDIR}'")
246
- Conf.FARGO3D_IS_HERE = True
247
- Conf.configure_fargo3d(basedir,Conf.FARGO3D_PACKDIR)
248
-
249
- # Check if FARGO3D can be compiled normally
250
- print("> Checking for FARGO3D normal binary:")
251
- options = ''
252
- if not Conf._check_fargo_binary(basedir+Conf.FARGO3D_PACKDIR,options):
253
- if 'compile' in react:
254
- print("\tCompiling FARGO3D (it may take a while)...")
255
- if Conf._compile_fargo3d(options,quiet=True):
256
- Conf.FARGO3D_IS_COMPILING = True
257
- print(f"\t✓Binary in normal mode compiling correctly")
258
- else:
259
- Conf.FARGO3D_IS_COMPILING = True
260
- print(f"\t✓Binary in normal mode compiling correctly")
261
-
262
- # Check if FARGO3D can be compiled in parallel
263
- print("> Checking for FARGO3D parallel binary:")
264
- options='PARALLEL=1'
265
- if not Conf._check_fargo_binary(basedir+Conf.FARGO3D_PACKDIR,options):
266
- if 'parallel' in react:
267
- #print("\tCompiling FARGO3D in parallel (it may take a while)...")
268
- if Conf._compile_fargo3d(options,quiet=True):
269
- Conf.FARGO3D_PARALLEL = 1
270
- Conf.FARGO3D_IS_COMPILING_PARALLEL = True
271
- print(f"\t✓Binary in parallel mode compiling correctly")
272
- else:
273
- Conf.FARGO3D_PARALLEL = 1
274
- Conf.FARGO3D_IS_COMPILING_PARALLEL = True
275
- print(f"\t✓Binary in parallel mode compiling correctly")
276
-
277
- # Check if FARGO3D can be compiled in parallel
278
- print("> Checking for FARGO3D GPU binary:")
279
- options='GPU=1'
280
- if not Conf._check_fargo_binary(basedir+Conf.FARGO3D_PACKDIR,options):
281
- if 'gpu' in react:
282
- print("\tCompiling FARGO3D with GPU (it may take a while)...")
283
- if Conf._compile_fargo3d(options,quiet=True):
284
- Conf.FARGO3D_GPU = 1
285
- Conf.FARGO3D_IS_COMPILING_GPU = True
286
- print(f"\t✓Binary in GPU mode compiling correctly")
287
- else:
288
- print(f"\tNo GPU available")
289
-
290
- else:
291
- Conf.FARGO3D_GPU = 1
292
- Conf.FARGO3D_IS_COMPILING_GPU = True
293
- print(f"\t✓Binary in GPU mode compiling correctly")
294
-
295
- @staticmethod
296
- def _check_fargo(fulldir):
297
- if not os.path.isfile(fulldir+Conf.FARGO3D_HEADER):
298
- print(f"FARGO3D source code is not available at '{fulldir}'")
299
- return False
300
-
301
- return True
302
-
303
- @staticmethod
304
- def _is_fargo_here():
305
- if not Conf.FARGO3D_IS_HERE:
306
- raise AssertionError(f"FARGO3D source code has not been checked. Run Conf.set_fargo3d().")
307
- return True
308
-
309
- @staticmethod
310
- def _check_fargo_binary(fulldir,options='',quiet=False):
311
- if not os.path.isfile(fulldir+"."+Conf.FARGO3D_BINARY+f"_{Conf._binary_name(options)}"):
312
- if not quiet:
313
- print(f"FARGO3D binary with options '{options}' not compiled at '{fulldir}'")
314
- return False
315
- return True
316
-
317
- @staticmethod
318
- def _get_fargo(basedir):
319
- error,out = Util.sysrun(f'cd {basedir};{Conf.FARGO3D_CLONE_REPO_CMD}',verbose=False)
320
- if Util.QERROR <= 0:
321
- Conf.configure_fargo3d(basedir,Conf.FARGO3D_PACKDIR)
322
- print(f"\t✓Package downloaded to '{Conf.FARGO3D_FULLDIR}'")
323
- FARGO3D_IS_HERE = True
324
- else:
325
- print("\tError downloading. Check Util.STDOUT and Util.STDERR for verifying.")
326
-
327
- @staticmethod
328
- def _compile_fargo3d(options,quiet=False,force=False):
329
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
330
-
331
- # Binary filename
332
- binary_file = f".{Conf.FARGO3D_BINARY}_{Conf._binary_name(options)}"
333
-
334
- # Clean directory
335
- Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} clean mrproper',verbose=False)
336
-
337
- # Check if binary already exist
338
- lets_compile = True
339
- if not force:
340
- if os.path.isfile(f"{Conf.FARGO3D_FULLDIR}/{binary_file}"):
341
- print(f"Binary {Conf.FARGO3D_FULLDIR}/{binary_file} already compiled.")
342
- lets_compile = False
343
-
344
- if lets_compile:
345
-
346
- if not quiet:
347
- print(f"Compiling FARGO3D with options '{options}' (it may take a while... go for a coffee)")
348
-
349
- # Compile with options
350
- error,out = Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} {options}',verbose=False)
351
-
352
- # Check result of compilation
353
- if error:
354
- if not os.path.isfile(Conf.FARGO3D_FULLDIR+Conf.FARGO3D_BINARY):
355
- if not quiet:
356
- print("An error compiling the code arose. Check dependencies.")
357
- print(Util.STDERR)
358
- return None
359
-
360
- # Create a copy of binary compiled with options
361
- Util.sysrun(f"cp -rf {Conf.FARGO3D_FULLDIR}/{Conf.FARGO3D_BINARY} {Conf.FARGO3D_FULLDIR}/{binary_file}")
362
-
363
- # Clean all results
364
- Util.sysrun(f'make -C {Conf.FARGO3D_FULLDIR} clean mrproper',verbose=False)
365
- return binary_file
366
-
367
- @staticmethod
368
- def _run_fargo3d(fargo3d_binary,
369
- logfile='/tmp/fargo.log',
370
- options='',
371
- mode='async',
372
- resume=False,
373
- verbose=True):
374
- if Conf._check_fargo(Conf.FARGO3D_FULLDIR):
375
-
376
- # Run command
377
- run_cmd = f"cd {Conf.FARGO3D_FULLDIR};nohup {fargo3d_binary} {options} &> {logfile} & echo $!"
378
-
379
- # Let's run
380
- if mode == 'sync':
381
- # Run it synchronously, showing the output while running
382
- run_cmd = f"cd {Conf.FARGO3D_FULLDIR};{fargo3d_binary} {options} |tee {logfile}"
383
- print(f"Running synchronously: {run_cmd.replace('//','/')}")
384
- Util.sysrun(run_cmd,verbose=verbose)
385
-
386
- elif mode == 'async':
387
- # Run asynchronously in the background
388
- run_cmd = f"{fargo3d_binary} {options}"
389
- print(f"Running asynchronously: {run_cmd.replace('//','/')}")
390
- logmode = 'a' if resume else 'w'
391
- logfile_handler=open(logfile,logmode)
392
- process = subprocess.Popen(run_cmd.split(),cwd=Conf.FARGO3D_FULLDIR,
393
- stdout=logfile_handler,stderr=logfile_handler)
394
- print(f"Command is running in background")
395
- return process
396
-
397
- @staticmethod
398
- def _binary_name(options):
399
- return options.replace(' ','_').replace('=','-')
400
-
401
- @staticmethod
402
- def configure_fargo3d(basedir='.',packdir='public',parallel=None,gpu=None):
403
-
404
- # Configure directories
405
- Conf.FARGO3D_BASEDIR = (basedir + "/").replace('//','/')
406
- Conf.FARGO3D_PACKDIR = (packdir + "/").replace('//','/')
407
- Conf.FARGO3D_FULLDIR = (basedir + packdir).replace('//','/')
408
-
409
- # Configure compiling options
410
- if parallel is not None:
411
- Conf.parallel = parallel
412
- if gpu is not None:
413
- Conf.gpu = gpu
414
-
415
- @staticmethod
416
- def show_fargo3d_configuration():
417
- print("Is FARGO3D installed: ",Conf.FARGO3D_IS_HERE)
418
- print("Is FARGO3D compiling: ",Conf.FARGO3D_IS_COMPILING)
419
- print("Is FARGO3D compiling in parallel: ",Conf.FARGO3D_IS_COMPILING_PARALLEL)
420
- print("Is FARGO3D compiling in GPU: ",Conf.FARGO3D_IS_COMPILING_GPU)
421
- print("FARGO3D clone repositoty command: ",Conf.FARGO3D_CLONE_REPO_CMD)
422
- print("FARGO3D directories: ")
423
- print("\tBase directory: ",Conf.FARGO3D_BASEDIR)
424
- print("\tPackage directory: ",Conf.FARGO3D_PACKDIR)
425
- print("\tBasic package header: ",Conf.FARGO3D_HEADER)
426
- print("\tSetups location: ",Conf.FARGO3D_SETUPS)
427
- print("\tSetups location: ",Conf.FARGO3D_FULLDIR)
428
- print("Compile in parallel: ",Conf.FARGO3D_PARALLEL)
429
- print("Compile in GPU: ",Conf.FARGO3D_GPU)
430
-
431
- @staticmethod
432
- def _check_setup(setup):
433
- setup_dir = f"{Conf.FARGO3D_SETUPS}/{setup}"
434
- if not os.path.isdir(f"{Conf.FARGO3D_FULLDIR}/{setup_dir}"):
435
- print(f"No setup dir '{setup_dir}'")
436
- return None
437
-
438
- parameters_file = f"{setup_dir}/{setup}.par"
439
- if not os.path.isfile(f"{Conf.FARGO3D_FULLDIR}/{parameters_file}"):
440
- print(f"No parameter files '{setup}.par' in '{setup_dir}'")
441
- return None
442
-
443
- return setup_dir,parameters_file
444
-
445
- class Dictobj(object):
446
- """Convert a dictionary to an object
447
-
448
- Examples:
449
- ob = Dictobj(a=2,b=3)
450
- print(ob.a,ob.b)
451
- ob = Dictobj(dict=dict(a=2,b=3))
452
- print(ob.a,ob.b)
453
- ob = Dictobj(dict={'a':2,'b':3})
454
- print(ob.a,ob.b)
455
- """
456
-
457
- def __init__(self, **kwargs):
458
- if 'dict' in kwargs.keys():
459
- kwargs.update(kwargs['dict'])
460
- for key, value in kwargs.items():
461
- if key == 'dict':continue
462
- setattr(self, key, value)
463
-
464
- def __str__(self):
465
- return str(self.__dict__)
466
-
467
- def __repr__(self):
468
- return self.__str__()
469
-
470
- ###############################################################
471
- # Required packages
472
- ###############################################################
473
- import subprocess
474
- import os
475
- import re
476
- import time
477
- import numpy as np
478
-
479
- ###############################################################
480
- # Module constants
481
- ###############################################################
482
-
483
- ###############################################################
484
- # Classes
485
- ###############################################################
486
- class Simulation(Conf):
487
- """Simulation class.
488
- """
489
- def __init__(self,**kwargs):
490
- super().__init__()
491
-
492
- if 'setup' in kwargs.keys():
493
- self.load_setup(setup=kwargs['setup'])
494
- else:
495
- self.setup = None
496
-
497
- # Compilation options
498
- self.parallel = Conf.FARGO3D_PARALLEL
499
- self.gpu = Conf.FARGO3D_GPU
500
-
501
- # Other options
502
- self.compile_options = None
503
- self.fargo3d_binary = None
504
- self.fargo3d_process = None
505
-
506
- def load_setup(self,setup=None):
507
- if not setup:
508
- setups = self.list_setups()
509
- print(f"You must select a setup, from a custom directory or from the list:{setups}")
510
-
511
- output = Conf._check_setup(setup)
512
- if output:
513
- self.setup = setup
514
- self.setup_directory = output[0]
515
- self.setup_parameters = output[1]
516
- self.setup_outputs = f"{self.setup_directory}/../../outputs/{self.setup}"
517
- self.logfile = f"{Conf.FARGO3D_FULLDIR}/{self.setup_directory}/{self.setup}.log"
518
-
519
- def compile(self,
520
- parallel=None,gpu=None,
521
- options='',
522
- force=False
523
- ):
524
- if not self._is_setup():
525
- return
526
-
527
- parallel = self.parallel if parallel is None else parallel
528
- gpu = self.gpu if gpu is None else gpu
529
-
530
- self.compile_options = f"SETUP={self.setup} PARALLEL={parallel} GPU={gpu} "+options
531
- self.fargo3d_binary = Conf._compile_fargo3d(options=self.compile_options,force=force)
532
-
533
- def run(self,
534
- mode='async',
535
- options='-m',
536
- mpioptions = '-np 1',
537
- resume=False
538
- ):
539
-
540
- if not self._is_setup():
541
- return
542
- if self._is_running():
543
- return
544
-
545
- if self.fargo3d_binary is None:
546
- print("You must first compile your simulation with: <simulation>.compile().")
547
- return
548
-
549
- # Mandatory options
550
- options = options + " -t"
551
- if 'run_options' not in self.__dict__.keys():
552
- self.run_options = options
553
-
554
- self.logfile = f"{Conf.FARGO3D_FULLDIR}/{self.setup_directory}/{self.setup}.log"
555
-
556
- # Select command to run
557
- precmd=''
558
- if Conf.FARGO3D_PARALLEL:
559
- precmd = f"mpirun {mpioptions} "
560
-
561
- self.fargo3d_process = Conf._run_fargo3d(f"{precmd}./{self.fargo3d_binary} {options}",
562
- logfile=self.logfile,
563
- mode=mode,
564
- resume=resume,
565
- options=self.setup_parameters)
566
-
567
- def resume(self,since=0,mpioptions = '-np 1'):
568
- """Resume a simulation from a given snapshot
569
- """
570
- if not self._is_setup():
571
- return
572
- if not self._is_resumable():
573
- return
574
- if self._is_running():
575
- return
576
-
577
- print(f"Resuming from snapshot {since}")
578
- self.run(mode='async',mpioptions=mpioptions,resume=True,options=self.run_options+f' -S {since}')
579
-
580
- def _is_resumable(self):
581
- outputs_directory = f"{Conf.FARGO3D_FULLDIR}/{self.setup_outputs}/"
582
- if not os.path.isdir(outputs_directory):
583
- print("There is no output to resume at '{outputs_directory.replace('//','/')}'.")
584
- return False
585
- return True
586
-
587
- def _get_snapshots(self):
588
- if not self._is_setup():
589
- return
590
- if not self._is_resumable():
591
- return
592
-
593
- error,output = Util.sysrun(f"grep OUTPUT {self.logfile}",verbose=False)
594
- if not error:
595
- snapshots = output[:-1]
596
- else:
597
- snapshots = []
598
- return snapshots
599
-
600
- def get_resumable_snapshot(self):
601
- error,output = Util.sysrun(f"grep OUTPUT {self.logfile}",verbose=False)
602
- if not error:
603
- find = re.findall(r'OUTPUTS\s+(\d+)',output[-2])
604
- resumable_snapshot = int(find[0])
605
- else:
606
- resumable_snapshot = 0
607
- return resumable_snapshot
608
-
609
- def _is_running(self,verbose=True):
610
- if self.fargo3d_process:
611
- poll = self.fargo3d_process.poll()
612
- if poll is None:
613
- if verbose:
614
- print(f"The process is already running with pid '{self.fargo3d_process.pid}'")
615
- return True
616
- else:
617
- return False
618
- else:
619
- return False
620
-
621
- def stop(self):
622
- """Stop the present running process
623
- """
624
- if not self._is_setup():
625
- return
626
-
627
- if not self._is_running():
628
- print("The process is stopped.")
629
- return
630
-
631
- if self.fargo3d_process:
632
- poll = self.fargo3d_process.poll()
633
- if poll is None:
634
- print(f"Stopping FARGO3D process (pid = {self.fargo3d_process.pid})")
635
- subprocess.Popen.kill(self.fargo3d_process)
636
- del self.fargo3d_process
637
- self.fargo3d_process = None
638
- else:
639
- print("The process has already finished.")
640
-
641
- def _is_setup(self):
642
- if self.setup is None:
643
- print("The simulation has not been set-up yet. Run <simulation>.load_setup('<setup>')")
644
- return False
645
- return True
646
-
647
- def status(self,
648
- mode='isrunning',
649
- verbose=True
650
- ):
651
- """Check the status of the running process
652
-
653
- Parameters:
654
- mode: string, defaul='isrunning':
655
- Available modes:
656
- 'isrunning': Just show if the process is running.
657
- 'logfile': Show the latest lines of the logfile
658
- 'outputs': Show (and return) a list of outputs
659
- 'snapshots': Show (and return) a list of snapshots
660
-
661
- """
662
- if not self._is_setup():
663
- return
664
-
665
- # Bar separating output
666
- bar = f"\n{''.join(['#']*80)}\n"
667
- # vprint
668
- vprint = print if verbose else lambda x:x
669
-
670
- if 'isrunning' in mode or mode=='all':
671
- vprint(bar+"Running status of the process:")
672
- if self.fargo3d_process:
673
- poll = self.fargo3d_process.poll()
674
-
675
- if poll is None:
676
- vprint("\tThe process is running.")
677
- else:
678
- vprint(f"\tThe process has ended with termination code {poll}.")
679
- else:
680
- vprint(f"\tThe process is stopped.")
681
-
682
- if 'logfile' in mode or mode=='all':
683
- vprint(bar+"Logfile content:")
684
- if 'logfile' in self.__dict__.keys() and os.path.isfile(self.logfile):
685
- vprint("The latest 10 lines of the logfile:\n")
686
- if verbose:
687
- os.system(f"tail -n 10 {self.logfile}")
688
- else:
689
- vprint("No log file created yet")
690
-
691
- if 'outputs' in mode or mode=='all':
692
- vprint(bar+"Output content:")
693
- error,output = Util.sysrun(f"ls {Conf.FARGO3D_FULLDIR}/{self.setup_outputs}/*.dat",verbose=False)
694
- if not error:
695
- files = [file.split('/')[-1] for file in output[:-1]]
696
- file_list = ""
697
- for i,file in enumerate(files):
698
- file_list += f"{file}, "
699
- if ((i+1)%10) == 0:
700
- file_list += "\n"
701
- file_list = file_list.strip("\n,")
702
- vprint(f"\n{len(files)} available datafiles:\n")
703
- self.output_datafiles = files
704
- vprint(file_list)
705
- else:
706
- vprint("No datafiles yet available")
707
-
708
- if 'snapshots' in mode or mode=='all':
709
- vprint(bar+"Snapshots:")
710
- self.output_snapshots = self._get_snapshots()
711
- nsnapshots = len(self.output_snapshots)
712
- self.resumable_snapshot = None
713
- if nsnapshots:
714
- vprint(f"\tNumber of available snapshots: {nsnapshots}")
715
- if nsnapshots > 1:
716
- find = re.findall(r'OUTPUTS\s+(\d+)',self.output_snapshots[-2])
717
- self.resumable_snapshot = int(find[0])
718
- vprint(f"\tLatest resumable snapshot: {self.resumable_snapshot}")
719
- else:
720
- vprint(f"\tNo resumable snapshot")
721
- else:
722
- vprint("No snapshots yet")
723
-
724
- if 'progress' in mode:
725
- self._status_progress()
726
-
727
- def _status_progress(self,minfreq =0.1):
728
- """Show a progress of the execution
729
-
730
- Parameters:
731
- minfreq: float, default = 0.1:
732
- Minimum amount of seconds between status check.
733
- """
734
- # Prepare
735
- frequency = minfreq
736
- previous_output = ''
737
- previous_resumable_snapshot = 1e100
738
- time_previous = time.time()
739
-
740
- # Infinite loop checking for output
741
- while True:
742
- if not self._is_running(verbose=False):
743
- print("The simulation is not running anymore")
744
- return
745
- error,output = Util.sysrun(f"grep OUTPUT {self.logfile} |tail -n 1",verbose=False)
746
- if not error:
747
- # Get the latest output
748
- latest_output = output[-2]
749
- if latest_output != previous_output:
750
- print(f"{latest_output} [output pace = {frequency:.1f} secs]")
751
- # Fun the number of the output
752
- find = re.findall(r'OUTPUTS\s+(\d+)',latest_output)
753
- resumable_snapshot = int(find[0])
754
- # Get the time elapsed since last status check
755
- time_now = time.time()
756
- frequency = max(time_now - time_previous,minfreq)/2
757
- if (resumable_snapshot - previous_resumable_snapshot)>1:
758
- # Reduce frequency if snapshots are accelerating
759
- frequency = frequency/2
760
- previous_resumable_snapshot = resumable_snapshot
761
- time_previous = time_now
762
-
763
- previous_output = latest_output
764
- try:
765
- time.sleep(frequency)
766
- except KeyboardInterrupt:
767
- return
768
-
769
- def clean_output(self):
770
- """
771
- Clean all outputs
772
- """
773
- if not self._is_setup():
774
- return
775
- if self._is_running():
776
- return
777
-
778
- print(f"Cleaning simulation outputs...")
779
- run_cmd = f"rm -r {Conf.FARGO3D_FULLDIR}/{self.setup_outputs}/*"
780
- error,output = Util.sysrun(run_cmd,verbose=False)
781
- if error:
782
- print("Output directory is clean already.")
783
- if not error:
784
- print("Done.")
785
-
786
- def load_domain(self):
787
-
788
- # Load
789
- self.dim = 0
790
- self.domains = []
791
-
792
- print(f"Loading domain...")
793
- print("Domain size:")
794
- output_dir = Conf.FARGO3D_FULLDIR + "/" + self.setup_outputs
795
- file_x = output_dir + "/domain_x.dat"
796
- if os.path.isfile(file_x):
797
- self.domain_x = np.genfromtxt(file_x)
798
- self.dim += 1
799
- self.domains += [self.domain_x]
800
- print(f"\tVariable 1 (periodic): {len(self.domain_x)}")
801
- file_y = output_dir + "/domain_y.dat"
802
- if os.path.isfile(file_y):
803
- self.domain_y = np.genfromtxt(file_y)[3:-3]
804
- self.dim += 1
805
- self.domains += [self.domain_y]
806
- print(f"\tVariable 2: {len(self.domain_y)}")
807
- file_z = output_dir + "/domain_z.dat"
808
- if os.path.isfile(file_z):
809
- self.domain_z = np.genfromtxt(file_z)[3:-3]
810
- self.dim += 1
811
- self.domains += [self.domain_z]
812
- print(f"\tVariable 3: {len(self.domain_z)}")
813
-
814
- print(f"Problem in {self.dim} dimensions")
815
-
816
- # Get grid
817
- print(f"Building vargrids...")
818
- self.var1_12, self.var2_12 = np.meshgrid(self.domain_x,self.domain_y)
819
- self.var1_12, self.var3_12 = np.meshgrid(self.domain_x,self.domain_z)
820
- self.var2_23, self.var3_23 = np.meshgrid(self.domain_y,self.domain_z)
821
- print(f"Done.")
822
-
823
- def load_variables(self):
824
- output_dir = Conf.FARGO3D_FULLDIR + "/" + self.setup_outputs
825
- variables = np.genfromtxt(output_dir+"/variables.par",
826
- dtype={'names': ("parameters","values"),
827
- 'formats': ("|S30","|S300")}).tolist()
828
- print(f"Loading variables")
829
- self.vars = dict()
830
- for posicion in variables:
831
- self.vars[posicion[0].decode("utf-8")] = posicion[1].decode("utf-8")
832
- self.vars = Dictobj(dict=self.vars)
833
- print(f"{len(self.vars.__dict__.keys())} variables load. See <sim>.vars")
834
-
835
- def load_field(self,fluid='gas',field='dens',snapshot=None):
836
- if 'vars' not in self.__dict__.keys():
837
- self.load_variables()
838
- if not self._is_resumable():
839
- print("Simulation has not produced any output yet.")
840
- if snapshot is None:
841
- snapshot = self._get_resumable_snapshot()
842
-
843
- output_dir = Conf.FARGO3D_FULLDIR + "/" + self.setup_outputs
844
- file_name = fluid+field+str(snapshot)+".dat"
845
- file_field = output_dir+"/"+file_name
846
- if os.path.isfile(file_field):
847
- self.dim = 3 if 'NZ' in self.vars.__dict__.keys() else 2
848
- if self.dim == 2:
849
- field = np.fromfile(file_field).reshape(int(self.vars.NY),int(self.vars.NX))
850
- else:
851
- field = np.fromfile(file_field).reshape(int(self.vars.NZ),int(self.vars.NY),int(self.vars.NX))
852
- return field
853
- else:
854
- print(f"File with field '{file_name}' not found")
855
-
856
- ###############################################################
857
- # Aliases
858
- ###############################################################
859
-
860
- ###############################################################
861
- # External modules
862
- ###############################################################
863
- import numpy as np
864
- import warnings
865
-
866
- ###############################################################
867
- # Constants
868
- ###############################################################
869
- # Numerical Constants
870
- RAD = 180/np.pi
871
- DEG = 1/RAD
872
-
873
- ###############################################################
874
- # Initialization
875
- ###############################################################
876
- # Avoid warnings
877
- warnings.filterwarnings("ignore")
878
-
879
- # Showing version
880
- print(f"Running FARGOpy version {version}")