Skip to content

Commit

Permalink
Merge pull request #10 from boutproject/pylib_merge
Browse files Browse the repository at this point in the history
Merge changes from BOUT-dev
  • Loading branch information
johnomotani authored Oct 31, 2020
2 parents c0cdb17 + f599a57 commit 073ff33
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 101 deletions.
12 changes: 5 additions & 7 deletions boututils/analyse_equil_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from past.utils import old_div

import numpy
from bunch import Bunch
from . import local_min_max
from scipy.interpolate import RectBivariateSpline
from matplotlib.pyplot import contour, gradient, annotate, plot, draw
Expand All @@ -35,8 +34,8 @@ def analyse_equil(F, R, Z):
Returns
-------
bunch
A structure of critical points containing:
object
An object of critical points containing:
n_opoint, n_xpoint - Number of O- and X-points
primary_opt - Index of plasma centre O-point
Expand Down Expand Up @@ -169,8 +168,7 @@ def analyse_equil(F, R, Z):
print("Number of O-points: "+str(n_opoint))

if n_opoint == 0 :
print("No O-points! Giving up on this equilibrium")
return Bunch(n_opoint=0, n_xpoint=0, primary_opt=-1)
raise RuntimeError("No O-points! Giving up on this equilibrium")


#;;;;;;;;;;;;;; Find plasma centre ;;;;;;;;;;;;;;;;;;;
Expand Down Expand Up @@ -259,8 +257,8 @@ def analyse_equil(F, R, Z):



#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
# Put results into a structure
#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
# Put results into a structure

result = Bunch(n_opoint=n_opoint, n_xpoint=n_xpoint, # Number of O- and X-points
primary_opt=primary_opt, # Which O-point is the plasma centre
Expand Down
6 changes: 6 additions & 0 deletions boututils/bunch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# what we need from bunch

class Bunch:
def __init__(self, **dict):
for k in dict:
setattr(self, k, dict[k])
11 changes: 5 additions & 6 deletions boututils/check_scaling.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ def check_order(error_list, expected_order, tolerance=2.e-1, spacing=None):
if len(error_list) < 2:
raise RuntimeError("Expected at least 2 data points to calculate error")

success=True
success = True

for i in range(len(error_list)-1):
if spacing is None:
actual_order = log(errors[i] / errors[i+1]) / log(2)
else:
actual_order = log(errors[i] / errors[i+1]) / log(grid_spacing[i] / grid_spacing[i+1])
grid_spacing = 2 if spacing is None else spacing[i] / spacing[i+1]
actual_order = log(error_list[i] / error_list[i+1]) / log(grid_spacing)

if not isclose(actual_order, expected_order, atol=tolerance, rtol=0):
success=False
success = False
return success


Expand Down
7 changes: 4 additions & 3 deletions boututils/datafile.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,11 +729,12 @@ def read(self, name, ranges=None, asBoutArray=True):
if var is None:
return None

if asBoutArray:
attributes = self.attributes(n)
attributes = self.attributes(n) if asBoutArray else {}

time_dependent = attributes.get("bout_type", "none").endswith("_t")

ndims = len(var.shape)
if ndims == 1 and var.shape[0] == 1:
if ndims == 1 and var.shape[0] == 1 and not time_dependent:
data = var
if asBoutArray:
data = BoutArray(data, attributes=attributes)
Expand Down
2 changes: 1 addition & 1 deletion boututils/efit_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from builtins import range
from past.utils import old_div
import numpy as np
from bunch import Bunch
from boututils.bunch import Bunch
from .radial_grid import radial_grid
from .analyse_equil_2 import analyse_equil
from pylab import (cm, clabel, contour, draw, legend, plot, setp, show,
Expand Down
2 changes: 1 addition & 1 deletion boututils/geqdsk.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3

from __future__ import print_function
from __future__ import division
Expand Down
16 changes: 5 additions & 11 deletions boututils/moment_xyzt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
from builtins import range
from past.utils import old_div
import numpy as np
from bunch import Bunch

from boututils.bunch import Bunch

def RMSvalue( vec1d):
#;
Expand All @@ -16,9 +15,9 @@ def RMSvalue( vec1d):
valrms=np.sqrt(old_div(np.sum((vec1d-valav)**2),nel))
acvec=vec1d-valav


return Bunch(valrms=valrms, valav=valav, acvec=acvec)

return Bunch(valrms=valrms,
valav=valav,
acvec=acvec)



Expand All @@ -30,8 +29,6 @@ def moment_xyzt( sig_xyzt, *args):#rms=None, dc=None, ac=None):
#; -AC (DC subtracted out), i.e., a function of (x,y,z,t)
#;-------------------------------------------------------------------

try: # return to caller

d = np.shape(sig_xyzt)
if np.size(d) != 4 :
print("Error: Variable must be 4D (x,y,z,t)")
Expand Down Expand Up @@ -73,8 +70,5 @@ def moment_xyzt( sig_xyzt, *args):#rms=None, dc=None, ac=None):
res.ac = ac

if 'RMS' not in args and 'DC' not in args and 'AC' not in args :
print('Wrong argument')
raise RuntimeError('Wrong argument')
return res
except:
print('moment_xyz failed')
return
6 changes: 2 additions & 4 deletions boututils/read_geqdsk.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import print_function
from builtins import range
import numpy
from bunch import Bunch
from geqdsk import Geqdsk
from boututils.bunch import Bunch

def read_geqdsk (file):

Expand Down Expand Up @@ -67,8 +67,6 @@ def read_geqdsk (file):
for j in range(0,nyefit):
r[i,j] = rgrid1 + xdim*i/(nxefit-1)
z[i,j] = (zmid-0.5*zdim) + zdim*j/(nyefit-1)



f=f.T

Expand All @@ -89,4 +87,4 @@ def read_geqdsk (file):
pres=pres, # Plasma pressure in nt/m^2 on uniform flux grid
qpsi=qpsi, # q values on uniform flux grid
nbdry=nbdry, rbdry=rbdry, zbdry=zbdry, # Plasma boundary
nlim=nlim, xlim=xlim, ylim=ylim) # Wall boundary
nlim=nlim, xlim=xlim, ylim=ylim) # Wall boundary
117 changes: 85 additions & 32 deletions boututils/run_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@

from builtins import str
import os
import pathlib
import re
import subprocess
from subprocess import call, Popen, STDOUT, PIPE

try:
# Python 2.4 onwards
from subprocess import call, Popen, STDOUT, PIPE
lib = "call"
except ImportError:
# FIXME: drop support for python < 2.4!
# Use os.system (depreciated)
from os import popen4, system
lib = "system"

if os.name == "nt":
# Default on Windows
DEFAULT_MPIRUN = "mpiexec.exe -n"
else:
DEFAULT_MPIRUN = "mpirun -np"

def getmpirun(default="mpirun -np"):

def getmpirun(default=DEFAULT_MPIRUN):
"""Return environment variable named MPIRUN, if it exists else return
a default mpirun command
Expand Down Expand Up @@ -53,27 +52,20 @@ def shell(command, pipe=False):
"""
output = None
status = 0
if lib == "system":
if pipe:
handle = popen4(command)
output = handle[1].read()
else:
status = system(command)
if pipe:
child = Popen(command, stderr=STDOUT, stdout=PIPE, shell=True)
# This returns a b'string' which is casted to string in
# python 2. However, as we want to use f.write() in our
# runtest, we cast this to utf-8 here
output = child.stdout.read().decode("utf-8", "ignore")
# Wait for the process to finish. Note that child.wait()
# would have deadlocked the system as stdout is PIPEd, we
# therefore use communicate, which in the end also waits for
# the process to finish
child.communicate()
status = child.returncode
else:
if pipe:
child = Popen(command, stderr=STDOUT, stdout=PIPE, shell=True)
# This returns a b'string' which is casted to string in
# python 2. However, as we want to use f.write() in our
# runtest, we cast this to utf-8 here
output = child.stdout.read().decode("utf-8", "ignore")
# Wait for the process to finish. Note that child.wait()
# would have deadlocked the system as stdout is PIPEd, we
# therefore use communicate, which in the end also waits for
# the process to finish
child.communicate()
status = child.returncode
else:
status = call(command, shell=True)
status = call(command, shell=True)

return status, output

Expand All @@ -93,6 +85,18 @@ def determineNumberOfCPUs():
The number of CPUs
"""

# cpuset
# cpuset may restrict the number of *available* processors
try:
m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$',
open('/proc/self/status').read())
if m:
res = bin(int(m.group(1).replace(',', ''), 16)).count('1')
if res > 0:
return res
except IOError:
pass

# Python 2.6+
try:
import multiprocessing
Expand Down Expand Up @@ -228,8 +232,12 @@ def launch(command, runcmd=None, nproc=None, mthread=None,
cmd = cmd + " > "+output

if mthread is not None:
cmd = "OMP_NUM_THREADS={j} ".format(j=mthread)+cmd

if os.name == "nt":
# We're on windows, so we have to do it a little different
cmd = 'cmd /C "set OMP_NUM_THREADS={} && {}"'.format(mthread, cmd)
else:
cmd = "OMP_NUM_THREADS={} {}".format(mthread, cmd)

if verbose == True:
print(cmd)

Expand Down Expand Up @@ -277,3 +285,48 @@ def launch_safe(command, *args, **kwargs):
"Output was\n\n%s"%
(s,command,out))
return s, out


def build_and_log(test):
"""Run make and redirect the output to a log file. Prints input
On Windows, does nothing because executable should have already
been built
"""

if os.name == "nt":
return

print("Making {}".format(test))

if os.path.exists("makefile") or os.path.exists("Makefile"):
return shell_safe("make > make.log")

ctest_filename = "CTestTestfile.cmake"
if not os.path.exists(ctest_filename):
raise RuntimeError("Could not build: no makefile and no CMake files detected")

# We're using CMake, but we need to know the target name. If
# bout_add_integrated_test was used (which it should have been!),
# then the test name is the same as the target name
with open(ctest_filename, "r") as f:
contents = f.read()
match = re.search("add_test.(.*) ", contents)
if match is None:
raise RuntimeError("Using CMake, but could not determine test name")
test_name = match.group(1)

# Now we need to find the build directory. It'll be the first
# parent containing CMakeCache.txt
here = pathlib.Path(".").absolute()
for parent in here.parents:
if (parent / "CMakeCache.txt").exists():
return shell_safe(
"cmake --build {} --target {} > make.log".format(parent, test_name)
)

# We've just looked up the entire directory structure and not
# found the build directory, this could happen if CMakeCache was
# deleted, in which case we can't build anyway
raise RuntimeError("Using CMake, but could not find build directory")
Loading

0 comments on commit 073ff33

Please sign in to comment.