1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Commands for users.
21 """
22
23 from .cmdutil import Command
24
25 -class mpi(Command):
26 """
27 Utilities for MPI.
28 """
29
30 min_args = 0
31
33 from optparse import OptionGroup
34 super(mpi, self).__init__(env)
35 op = self.op
36 opg = OptionGroup(op, 'MPI')
37 opg.add_option('--node-env', action='store',
38 dest='node_env', default='PBS_NODEFILE',
39 help='Environment variable of the host file.',
40 )
41 opg.add_option('--compress-nodelist', action='store_true',
42 dest='compress_nodelist', default=False,
43 help='To compress nodelist on the head node.',
44 )
45 opg.add_option('--head-last', action='store_true',
46 dest='head_last', default=False,
47 help='Make the head node to be last in the host file.',
48 )
49 op.add_option_group(opg)
50 self.opg_arrangement = opg
51
53 import os, sys
54 ops, args = self.opargs
55 f = open(os.environ[ops.node_env])
56 nodes = [node.strip() for node in f.readlines()]
57 f.close()
58 if ops.compress_nodelist:
59 newnodes = []
60 for node in nodes:
61 if not newnodes or newnodes[-1] != node:
62 newnodes.append(node)
63 nodes = newnodes
64 if ops.head_last:
65 first = nodes[0]
66 ind = 1
67 while ind < len(nodes):
68 if nodes[ind] != first:
69 break
70 ind += 1
71 nodes = nodes[ind:] + nodes[:ind]
72 if len(args) > 0:
73 f = open(args[0], 'w')
74 f.write('\n'.join([node.strip() for node in nodes]))
75 f.close()
76 else:
77 sys.stdout.write('\n'.join([node.strip() for node in nodes]))
78
80 """
81 Mesh manipulation.
82 """
83
84 min_args = 1
85
87 from optparse import OptionGroup
88 super(mesh, self).__init__(env)
89 op = self.op
90
91 opg = OptionGroup(op, 'Mesh')
92 opg.add_option('--ascii', action='store_false',
93 dest='binary', default=True,
94 help='Use ASCII in VTK (default is binary).',
95 )
96 opg.add_option('--encoding', action='store', type='string',
97 dest='encoding', default='raw',
98 help='The encoding used in VTK XML binary data (raw/base64). '
99 'Must be base64 for inline binary data.',
100 )
101 opg.add_option('--inline', action='store_false',
102 dest='appended', default=True,
103 help='Inline binary data in VTK XML file.',
104 )
105 opg.add_option('--fpdtype', action='store', type='string',
106 dest='fpdtype', default='float64',
107 help='dtype for floating-point (default is float64).',
108 )
109 opg.add_option('--formats', action='store', type='string',
110 dest='formats', default='',
111 help='Assign the I/O formats as InputIO,OutputIO.',
112 )
113 opg.add_option('--compressor', action='store', type='string',
114 dest='compressor', default='',
115 help='Empty string (no compression), gz or bz2.',
116 )
117 opg.add_option('--split', action='store', type='int',
118 dest='split', default=None,
119 help='Split the loaded block into given number of parts.',
120 )
121 opg.add_option('--bc-reject', action='store', type='string',
122 dest='bc_reject', default='',
123 help='The BC (name) to be rejected in conversion.',
124 )
125 opg.add_option('--no-print-block', action='store_false',
126 dest='print_block', default=True,
127 help='Prevent printing block information.',
128 )
129 opg.add_option('--no-print-bcs', action='store_false',
130 dest='print_bc', default=True,
131 help='Prevent printing BC objects information.',
132 )
133 op.add_option_group(opg)
134 self.opg_arrangement = opg
135
136 @staticmethod
146 @staticmethod
147 - def _save_domain(ops, blk, dirname):
148 import os
149 from time import time
150 from .domain import Collective
151 from .io.domain import DomainIO
152 from .helper import info
153 info('Create domain ... ')
154 timer = time()
155 dom = Collective(blk)
156 info('done. (%gs)\n' % (time()-timer))
157 info('Partition graph into %d parts ... ' % ops.split)
158 timer = time()
159 dom.partition(ops.split)
160 info('done. (%gs)\n' % (time()-timer))
161 info('Split step 1/5: distribute into sub-domains ... ')
162 timer = time()
163 dom.distribute()
164 info('done. (%gs)\n' % (time()-timer))
165 info('Split step 2/5: compute neighbor block ... ')
166 timer = time()
167 clmap = dom.compute_neighbor_block()
168 info('done. (%gs)\n' % (time()-timer))
169 info('Split step 3/5: reindex entities ... ')
170 timer = time()
171 dom.reindex(clmap)
172 info('done. (%gs)\n' % (time()-timer))
173 info('Split step 4/5: build interface ... ')
174 timer = time()
175 dom.build_interface()
176 info('done. (%gs)\n' % (time()-timer))
177 info('Split step 5/5: supplement ... ')
178 timer = time()
179 dom.supplement()
180 info('done. (%gs)\n' % (time()-timer))
181 dio = DomainIO(dom=dom, compressor=ops.compressor)
182 if not os.path.exists(dirname):
183 os.makedirs(dirname)
184 info('Save to directory %s/ ... ' % dirname)
185 timer = time()
186 dio.save(dirname=dirname)
187 info('done. (%gs)\n' % (time()-timer))
188 @staticmethod
199 @staticmethod
200 - def _save_vtkxml(ops, blk, vtkfn, appended, binary, encoding, compressor,
201 fpdtype):
216 @staticmethod
259 import os
260 from time import time
261 from .helper import info
262 ops, args = self.opargs
263
264 iio, oio = self._determine_formats(ops, args)
265
266 info('Load %s (%s) ... ' % (args[0], type(iio).__name__))
267 timer = time()
268 blk = iio.load(stream=args[0])
269 info('done. (%gs)\n' % (time()-timer))
270
271 if ops.print_block:
272 info('Block information:')
273 info('\n %s\n' % str(blk))
274 if ops.print_bc:
275 for bc in blk.bclist:
276 info(' %s\n' % str(bc))
277 info(' Cell groups:\n')
278 for igrp in range(len(blk.grpnames)):
279 grpname = blk.grpnames[igrp]
280 info(' grp#%d: %s\n' % (igrp, grpname))
281 info(' Cell volume (min, max, all): %g, %g, %g.\n' % (
282 blk.clvol.min(), blk.clvol.max(), blk.clvol.sum()))
283
284 if oio is not None:
285 path = args[1]
286 if oio == 'BlockIO':
287 self._save_block(ops, blk, path)
288 elif oio == 'DomainIO':
289 if ops.split is None:
290 info('No saving: split must be specified.\n')
291 return
292 self._save_domain(ops, blk, path)
293 elif oio == 'VtkLegacy':
294 self._save_vtklegacy(ops, blk, path, ops.binary, ops.fpdtype)
295 elif oio == 'VtkXml':
296 self._save_vtkxml(ops, blk, path, ops.appended, ops.binary,
297 ops.encoding, ops.compressor, ops.fpdtype)
298
300 """
301 Actions related Solver log.
302 """
303
305 from optparse import OptionGroup
306 super(SolverLog, self).__init__(env)
307 op = self.op
308
309 opg = OptionGroup(op, 'Solver Log')
310 opg.add_option('-f', action='store',
311 dest='filename', default=None,
312 help='Save plot to a file with specified name.',
313 )
314 opg.add_option('--backend', action='store',
315 dest='backend', default='TkAgg',
316 help='The backend for matplotlib. Default is TkAgg.',
317 )
318 op.add_option_group(opg)
319 self.opg_arrangement = opg
320
322 import os, glob
323 ops, args = self.opargs
324 fn = args[0]
325 fns = list()
326 if os.path.isdir(fn):
327 if ops.filename != None:
328 main, ext = os.path.splitext(ops.filename)
329 dsttmpl = main+'%d'+ext
330 else:
331 dsttmpl = None
332 nfn = len(glob.glob(os.path.join(fn, 'solvcon.solver*.log')))
333 for idx in range(nfn):
334 src = os.path.join(fn, 'solvcon.solver%d.log'%idx)
335 if dsttmpl != None:
336 dst = dsttmpl%idx
337 else:
338 dst = None
339 lines = open(src).readlines()
340 fns.append((lines, src, dst))
341 else:
342 lines = open(fn).readlines()
343 fns.append((lines, fn, ops.filename))
344 return fns
345
347 """
348 Show output from RuntimeStatAnchor.
349 """
350
351 min_args = 1
352 PLOTS = ['cpu', 'loadavg', 'mem']
353
355 from optparse import OptionGroup
356 super(log_runtime, self).__init__(env)
357 op = self.op
358
359 opg = OptionGroup(op, 'Show Runtime')
360 opg.add_option('-c', action='store_true',
361 dest='cpu', default=False,
362 help='Plot CPU usage.',
363 )
364 opg.add_option('-l', action='store_true',
365 dest='loadavg', default=False,
366 help='Plot load average.',
367 )
368 opg.add_option('-m', action='store_true',
369 dest='mem', default=False,
370 help='Plot memory usage.',
371 )
372 opg.add_option('-t', action='store_true',
373 dest='xtime', default=False,
374 help='Use time as x-axis.',
375 )
376 opg.add_option('--lloc', action='store',
377 dest='lloc', default=None,
378 help='Legend location. Default is None (by plot).',
379 )
380 opg.add_option('--scale', action='store', type=int,
381 dest='scale', default=0.6,
382 help='The scale when having more than one subplot.'
383 ' Default is 0.6.',
384 )
385 op.add_option_group(opg)
386 self.opg_arrangement = opg
387
389 import matplotlib
390 ops, args = self.opargs
391 figsize = matplotlib.rcParams['figure.figsize']
392 top = matplotlib.rcParams['figure.subplot.top']
393 bottom = matplotlib.rcParams['figure.subplot.bottom']
394 if nplot > 1:
395 upscale = nplot*ops.scale
396 top = 1.0 - (1.0-top)*(1.0-top)/((1.0-top)*upscale)
397 bottom = bottom*bottom/(bottom*upscale)
398 figsize = figsize[0], figsize[1]*upscale
399 matplotlib.rcParams.update({
400 'backend': ops.backend,
401 'figure.figsize': figsize,
402 'figure.subplot.top': top,
403 'figure.subplot.bottom': bottom,
404 })
405 matplotlib.use(ops.backend)
406
408 import os, sys
409 from .anchor import RuntimeStatAnchor
410 ops, args = self.opargs
411
412 nplot = 0
413 for key in self.PLOTS:
414 if getattr(ops, key):
415 nplot += 1
416 self._init_mpl(nplot)
417 from matplotlib import pyplot as plt
418
419 datas = self._get_datas()
420
421 for lines, src, dst in datas:
422 if nplot:
423 fig = plt.figure()
424 iplot = 1
425 for key in self.PLOTS:
426 if getattr(ops, key):
427 ax = fig.add_subplot(nplot, 1, iplot)
428 kws = {
429 'xtime': ops.xtime,
430 'showx': iplot==nplot,
431 }
432 if ops.lloc != None:
433 kws['lloc'] = ops.lloc
434 getattr(RuntimeStatAnchor, 'plot_'+key)(lines, ax, **kws)
435 iplot += 1
436 if nplot:
437 sys.stdout.write('%s processed' % src)
438 if dst != None:
439 plt.savefig(dst)
440 sys.stdout.write(' and written to %s.' % dst)
441 sys.stdout.write('\n')
442
443 if nplot and ops.filename == None:
444 plt.show()
445
447 """
448 Show output from MarchStatAnchor.
449 """
450
451 min_args = 1
452
454 from optparse import OptionGroup
455 super(log_march, self).__init__(env)
456 op = self.op
457
458 opg = OptionGroup(op, 'Show March')
459 opg.add_option('-k', action='store',
460 dest='plotkeys', default='',
461 help='Keys to plot.',
462 )
463 opg.add_option('--lloc', action='store',
464 dest='lloc', default=None,
465 help='Legend location. Default is None (by plot).',
466 )
467 opg.add_option('--scale', action='store', type=int,
468 dest='scale', default=0.6,
469 help='The scale when having more than one subplot.'
470 ' Default is 0.6.',
471 )
472 op.add_option_group(opg)
473 self.opg_arrangement = opg
474
476 import matplotlib
477 ops, args = self.opargs
478 matplotlib.rcParams.update({
479 'backend': ops.backend,
480 })
481 matplotlib.use(ops.backend)
482
484 import os, sys
485 from .anchor import MarchStatAnchor
486 ops, args = self.opargs
487
488 plotkeys = ops.plotkeys.split(',')
489 nplot = len(plotkeys)
490 self._init_mpl(nplot)
491 from matplotlib import pyplot as plt
492
493 datas = self._get_datas()
494
495 if nplot == 0:
496 return
497 for lines, src, dst in datas:
498 fig = plt.figure()
499 ax = fig.add_subplot(1, 1, 1)
500 kws = dict()
501 if ops.lloc != None:
502 kws['lloc'] = ops.lloc
503 MarchStatAnchor.plot(plotkeys, lines, ax, **kws)
504 sys.stdout.write('%s processed' % src)
505 if dst != None:
506 plt.savefig(dst)
507 sys.stdout.write(' and written to %s.' % dst)
508 sys.stdout.write('\n')
509
510 if ops.filename == None:
511 plt.show()
512
514 """
515 Show output from TpoolStatAnchor.
516 """
517
518 min_args = 1
519
521 from optparse import OptionGroup
522 super(log_tpool, self).__init__(env)
523 op = self.op
524
525 opg = OptionGroup(op, 'Show Tpool')
526 opg.add_option('-k', action='store',
527 dest='plotkeys', default='',
528 help='Keys to plot.',
529 )
530 opg.add_option('--lloc', action='store',
531 dest='lloc', default=None,
532 help='Legend location. Default is None (by plot).',
533 )
534 opg.add_option('--scale', action='store', type=int,
535 dest='scale', default=0.6,
536 help='The scale when having more than one subplot.'
537 ' Default is 0.6.',
538 )
539 op.add_option_group(opg)
540 self.opg_arrangement = opg
541
543 import matplotlib
544 ops, args = self.opargs
545 figsize = matplotlib.rcParams['figure.figsize']
546 top = matplotlib.rcParams['figure.subplot.top']
547 bottom = matplotlib.rcParams['figure.subplot.bottom']
548 if nplot > 1:
549 upscale = nplot*ops.scale
550 top = 1.0 - (1.0-top)*(1.0-top)/((1.0-top)*upscale)
551 bottom = bottom*bottom/(bottom*upscale)
552 figsize = figsize[0], figsize[1]*upscale
553 matplotlib.rcParams.update({
554 'backend': ops.backend,
555 'figure.figsize': figsize,
556 'figure.subplot.top': top,
557 'figure.subplot.bottom': bottom,
558 })
559 matplotlib.use(ops.backend)
560
562 import os, sys
563 from .anchor import TpoolStatAnchor
564 ops, args = self.opargs
565
566 plotkeys = ops.plotkeys.split(',')
567 nplot = len(plotkeys)
568 self._init_mpl(nplot)
569 from matplotlib import pyplot as plt
570
571 datas = self._get_datas()
572
573 for lines, src, dst in datas:
574 if nplot:
575 fig = plt.figure()
576 iplot = 1
577 for key in plotkeys:
578 ax = fig.add_subplot(nplot, 1, iplot)
579 kws = {
580 'showx': iplot==nplot,
581 }
582 if ops.lloc != None:
583 kws['lloc'] = ops.lloc
584 TpoolStatAnchor.plot(key, lines, ax, **kws)
585 iplot += 1
586 if nplot:
587 sys.stdout.write('%s processed' % src)
588 if dst != None:
589 plt.savefig(dst)
590 sys.stdout.write(' and written to %s.' % dst)
591 sys.stdout.write('\n')
592
593 if nplot and ops.filename == None:
594 plt.show()
595
597 """
598 @ivar opg_arrangement: group for options for arrangement.
599 @itype opg_arrangement: optparse.OptionGroup
600 """
601
603 from optparse import OptionGroup
604 super(ArrangementCommand, self).__init__(env)
605 op = self.op
606
607 opg = OptionGroup(op, 'Arrangement')
608 opg.add_option('--runlevel', action='store', type=int,
609 dest='runlevel', default=0,
610 help='0: fresh run, 1: restart, 2: init only.',
611 )
612 opg.add_option('--solver-output', action='store_true',
613 dest='solver_output', default=False,
614 help='Turn on the output device in the solver object(s).',
615 )
616 opg.add_option('--npart', action='store', type=int,
617 dest='npart', default=None,
618 help='The number of partitions.',
619 )
620 opg.add_option('--compress-nodelist', action='store_true',
621 dest='compress_nodelist', default=False,
622 help='To compress nodelist on the head node.',
623 )
624 opg.add_option('-e', '--envar', action='store',
625 dest='envar', default=None,
626 help='Additional environmental variable to remote solvers.',
627 )
628 opg.add_option('-b', '--batch', action='store',
629 dest='batch', default='Batch',
630 help='The name of batch system.',
631 )
632 opg.add_option('--use-profiler', action='store_true',
633 dest='use_profiler', default=False,
634 help='Flag to use profiler in running or not.',
635 )
636 opg.add_option('--profiler-sort', action='store', type='string',
637 dest='profiler_sort', default='cum,time',
638 help='Fields for sorting stats in profiler; comma separated.',
639 )
640 opg.add_option('--profiler-dat', action='store', type='string',
641 dest='profiler_dat', default='profiler.dat',
642 help='File name for raw profiler output.',
643 )
644 opg.add_option('--profiler-log', action='store', type='string',
645 dest='profiler_log', default='profiler.log',
646 help='File name for human-readable profiler output.',
647 )
648 opg.add_option('--basedir', action='store',
649 dest='basedir', default='',
650 help='Suggested basedir (may or may not used by arrangement).',
651 )
652 opg.add_option('--test', action='store_true',
653 dest='test', default=False,
654 help='General flags for test run.',
655 )
656 op.add_option_group(opg)
657 self.opg_arrangement = opg
658
659 @property
661 ops, args = self.opargs
662 dct = dict()
663 if ops.envar:
664 for ent in ops.envar.split(','):
665 key, val = [it.strip() for it in ent.split('=')]
666 dct[key] = val
667 return dct
668
669 -class run(ArrangementCommand):
670 """
671 Run arrangement.
672 """
673
674 min_args = 0
675
677 import os
678 import cProfile
679 import pstats
680 from socket import gethostname
681 from .helper import info
682 from .conf import use_application, env
683 from . import domain
684 from .batch import batregy
685 from .case import arrangements
686 from .rpc import Worker, DEFAULT_AUTHKEY
687 ops, args = self.opargs
688 if len(args) == 0:
689 names = [os.path.basename(os.getcwd())]
690 else:
691 names = args
692
693 batch = batregy[ops.batch]
694
695 npart = ops.npart
696 if npart != None:
697 if batch == batregy.Batch:
698 domaintype = domain.Collective
699 else:
700 domaintype = domain.Distributed
701 else:
702 domaintype = domain.Domain
703
704 funckw = {
705 'envar': self.envar,
706 'runlevel': ops.runlevel,
707 'solver_output': ops.solver_output,
708 'batch': batch,
709 'npart': npart, 'domaintype': domaintype,
710 }
711 for name in names:
712 func = arrangements[name]
713 if env.mpi and env.mpi.rank != 0:
714 pdata = (
715 ops.profiler_dat,
716 ops.profiler_log,
717 ops.profiler_sort,
718 ) if ops.use_profiler else None
719 wkr = Worker(None, profiler_data=pdata)
720 wkr.run(('0.0.0.0', 0), DEFAULT_AUTHKEY)
721 else:
722 if ops.use_profiler:
723 cProfile.runctx('func(submit=False, **funckw)',
724 globals(), locals(), ops.profiler_dat)
725 plog = open(ops.profiler_log, 'w')
726 p = pstats.Stats(ops.profiler_dat, stream=plog)
727 p.sort_stats(*ops.profiler_sort.split(','))
728 p.dump_stats(ops.profiler_dat)
729 p.print_stats()
730 plog.close()
731 info('*** Profiled information saved in '
732 '%s (raw) and %s (text).\n' % (
733 ops.profiler_dat, ops.profiler_log))
734 else:
735 func(submit=False, **funckw)
736
737 -class submit(ArrangementCommand):
738 """
739 Submit arrangement to batch system.
740 """
741
742 min_args = 1
743
745 from optparse import OptionGroup
746 super(submit, self).__init__(env)
747 op = self.op
748
749 opg = OptionGroup(op, 'Batching')
750 opg.add_option('-l', '--resources', action='store',
751 dest='resources', default='',
752 help='Resource list with "," as delimiter.',
753 )
754 opg.add_option('--use-mpi', action='store_true',
755 dest='use_mpi', default=False,
756 help='Indicate to use MPI as transport layer.',
757 )
758 opg.add_option('--postpone', action='store_true',
759 dest='postpone', default=False,
760 help='Postpone feeding into batch system.',
761 )
762 op.add_option_group(opg)
763 self.opg_batch = opg
764
766 import os
767 from .conf import use_application
768 from .batch import batregy
769 from .case import arrangements
770 ops, args = self.opargs
771 if len(args) > 0:
772 name = args[0]
773 else:
774 name = os.path.basename(os.getcwd())
775
776 for modname in self.env.modnames:
777 use_application(modname)
778
779 resources = dict([(line, None) for line in ops.resources.split(',')])
780
781 batch = batregy[ops.batch]
782
783 arrangements[name](submit=True,
784 use_mpi=ops.use_mpi, postpone=ops.postpone,
785 envar=self.envar,
786 runlevel=ops.runlevel,
787 resources=resources, batch=batch, npart=ops.npart,
788 )
789
790 -class help(Command):
791 """
792 Print general help.
793 """
794
796 ops, args = self.opargs
797 self.op.print_help()
798
799 @property
802