Skip to content

Commit

Permalink
updated ci script and added to python tools
Browse files Browse the repository at this point in the history
  • Loading branch information
smiet committed Feb 28, 2020
1 parent 0335442 commit bd7692a
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 32 deletions.
8 changes: 5 additions & 3 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ build:centos7:

case1:
stage: test
image: garrettwrong/spec_centos-7
image: csmiet/testspec
script:
- source source.sh
- cd ci/G1V03L2Fi
- ../../xspec G1V03L2Fi.001.sp
#- comparison
- xspec G1V03L2Fi.001.sp
- python3 -m py_spec.ci.test G1V03L2Fi.001.sp.h5 comparison.h5
#comparison python3 -m py_spec.ci.testspec f1 f2
artifacts:
when: always
paths:
Expand Down
2 changes: 2 additions & 0 deletions Utilities/pythontools/py_spec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
from .proc_spec import *
from . import plot
from . import math
from . import external
from . import ci


3 changes: 3 additions & 0 deletions Utilities/pythontools/py_spec/ci/__init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# import the test script

import test
57 changes: 57 additions & 0 deletions Utilities/pythontools/py_spec/ci/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: Caoxiang Zhu ([email protected])
For any help, type ./compare_spec.py -h
"""
import numpy as np
from py_spec import SPEC
import argparse

# parse command line arguments
parser = argparse.ArgumentParser(description="Compare two SPEC HDF5 outputs")
parser.add_argument("filename", type=str, help="file name to be compared")
parser.add_argument("reference", type=str, help="reference data")
parser.add_argument("-t", "--tol", type=float, default=1E-12, help="difference tolerance")

args = parser.parse_args()
print('Compare SPEC outputs in {:s} and {:s} with tolerance {:12.5E}'.format(
args.filename, args.reference, args.tol))
data_A = SPEC(args.filename)
data_B = SPEC(args.reference)
tol = args.tol
match = True


def compare(data, reference):
global match
for key, value in vars(data).items():
if isinstance(value, SPEC): # recurse data
print('------------------')
print('Elements in '+key)
compare(value, reference.__dict__[key])
else:
if key in ['filename', 'version']: # not compare filename and version
continue
elif key == 'iterations': # skip iteration data (might be revised)
continue
else:
# print(key)
diff = np.linalg.norm(np.abs(np.array(value) - np.array(reference.__dict__[key])))
unmatch = diff > tol
if unmatch:
match = False
print('UNMATCHED: '+key, ', diff={:12.5E}'.format(diff))
else :
print('ok: '+key)
return

compare(data_A, data_B)
print('===================')
if match :
print('All the terms are within tolerance.')
else :
print('Differences in some elements are larger than the tolerence.')

exit

2 changes: 1 addition & 1 deletion Utilities/pythontools/py_spec/math/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# import the math functions

from .fourier_surface import *
from .fourier_surface import fourier_surface
from .interface_current import *
15 changes: 1 addition & 14 deletions Utilities/pythontools/py_spec/math/fourier_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
# coded by @zhucaoxiang ([email protected])
# adapted by @smiet ([email protected])
#

import numpy as np

class fourier_surface(object):
import numpy as np
'''
toroidal surface in Fourier representation
R = \sum RBC cos(mu-nv) + RBS sin(mu-nv)
Z = \sum ZBC cos(mu-nv) + ZBS sin(mu-nv)
'''
def __init__(self, xm=[], xn=[], rbc=[], zbs=[], rbs=[], zbc=[]):
import numpy as np
"""Initialization with Fourier harmonics.
Parameters:
Expand Down Expand Up @@ -45,7 +43,6 @@ def read_spec_output(cls, spec_out, ns=-1):
Returns:
fourier_surface class
"""
import numpy as np
# check if spec_out is in correct format
#if not isinstance(spec_out, SPEC):
# raise TypeError("Invalid type of input data, should be SPEC type.")
Expand Down Expand Up @@ -74,7 +71,6 @@ def read_vmec_output(cls, woutfile, ns=-1):
Returns:
fourier_surface class
"""
import numpy as np
import xarray as ncdata # read netcdf file
vmec = ncdata.open_dataset(woutfile)
xm = vmec['xm'].values
Expand Down Expand Up @@ -108,7 +104,6 @@ def read_focus_input(cls, filename, Mpol=9999, Ntor=9999):
Returns:
fourier_surface class
"""
import numpy as np
with open(filename, 'r') as f:
line = f.readline() #skip one line
line = f.readline()
Expand Down Expand Up @@ -152,7 +147,6 @@ def read_winding_surfce(cls, filename, Mpol=9999, Ntor=9999):
Returns:
fourier_surface class
"""
import numpy as np
with open(filename, 'r') as f:
line = ''
while "phip_edge" not in line:
Expand Down Expand Up @@ -205,7 +199,6 @@ def rz(self, theta, zeta, normal=False):
r, z -- float array_like
r, z, [rt, zt], [rz, zz] -- if normal
"""
import numpy as np
assert len(np.atleast_1d(theta)) == len(np.atleast_1d(zeta)), "theta, zeta should be equal size"
# mt - nz (in matrix)
_mtnz = np.matmul( np.reshape(self.xm, (-1,1)), np.reshape(theta, (1,-1)) ) \
Expand Down Expand Up @@ -243,7 +236,6 @@ def xyz(self, theta, zeta, normal=False):
x, y, z -- float array_like
x, y, z, [nx, ny, nz] -- if normal
"""
import numpy as np
data = self.rz(theta, zeta, normal)
r = data[0]
z = data[1]
Expand Down Expand Up @@ -277,7 +269,6 @@ def areaVolume(self, theta0=0.0, theta1=2*np.pi, zeta0=0.0, zeta1=2*np.pi, \
area -- surface area
volume -- surface volume
"""
import numpy as np
# get mesh data
_theta = np.linspace(theta0, theta1, npol, endpoint=False)
_zeta = np.linspace(zeta0, zeta1, ntor, endpoint=False)
Expand All @@ -299,7 +290,6 @@ def get_area(self):
Returns:
area
"""
import numpy as np
self.area, _volume = self._areaVolume()
return self.area

Expand All @@ -325,7 +315,6 @@ def plot(self, zeta=0.0, npoints=360, **kwargs):
line class in matplotlib.pyplot
"""
import matplotlib.pyplot as plt
import numpy as np
# get figure and ax data
if plt.get_fignums():
fig = plt.gcf()
Expand Down Expand Up @@ -363,7 +352,6 @@ def plot3d(self, engine='pyplot', theta0=0.0, theta1=2*np.pi, zeta0=0.0, zeta1=2
Returns:
xsurf, ysurf, zsurf -- arrays of x,y,z coordinates on the surface
"""
import numpy as np
# get mesh data
_theta = np.linspace(theta0, theta1, npol)
_zeta = np.linspace(zeta0, zeta1, ntor)
Expand Down Expand Up @@ -405,7 +393,6 @@ def tovtk(self, vtkname, npol=360, ntor=360, **kwargs):
Returns:
"""
import numpy as np
from pyevtk.hl import gridToVTK # save to binary vtk
_xx, _yy, _zz = self.plot3d('noplot', zeta0=0.0, zeta1=2*np.pi,
theta0=0.0, theta1=2*np.pi, npol=npol, ntor=ntor)
Expand Down
8 changes: 5 additions & 3 deletions Utilities/pythontools/py_spec/math/interface_current.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

def interface_current(SPEC, interface_number):
"""
returns the ruccent on the interface given by interface_number.
returns the current on the interface given by interface_number.
Not working yet
We are calculating a loop integral over the difference in magnetic field on the surface.
Expand All @@ -21,13 +21,15 @@ def interface_current(SPEC, interface_number):
outer_volume = SPEC.output.Btemn[0:Ntor, 0, interface_number]
inner_volume = SPEC.output.Btemn[0:Ntor, 1, interface_number-1]

current = np.sum(outer_volume-inner_volume)* np.pi * 2 # check if idl's pi2 is pi squared or just two pi
current = np.sum(outer_volume-inner_volume) * np.pi * 2 # check if idl's pi2 is pi squared or just two pi

return current


def interface_current_total(SPEC):
"""
returns the ruccent on the interface given by interface_number.
NOT TESTED!
returns the current on the interface given by interface_number.
Not working yet
We are calculating a loop integral over the difference in magnetic field on the surface.
Expand Down
2 changes: 1 addition & 1 deletion Utilities/pythontools/py_spec/plot/plot_kam_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def plot_kam_surface(SPEC, ns=None, zeta=0.0, **kwargs):
kwargs.update({'label': 'SPEC_KAM'}) # default label
# plot all the surfaces
for i in ns:
_surf = math.fourier_surface.read_spec_output(SPEC, i) #look into which spec fourier_surface needs.
_surf = math.fourier_surface.read_spec_output(SPEC, i) # look into which spec fourier_surface needs.
if i == 0:
# plot axis as a curve
_r, _z = _surf.rz(0.0, zeta)
Expand Down
20 changes: 10 additions & 10 deletions Utilities/pythontools/py_spec/plot/plot_poincare.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,33 @@ def plot_poincare(SPEC, toroidalIdx=0, prange='full', **kwargs):
import matplotlib.pyplot as plt
import matplotlib.lines as mlines
# extract slice corresponding to the given toroidal cutplane
rr = SPEC.poincare.R[:,:,toroidalIdx]
zz = SPEC.poincare.Z[:,:,toroidalIdx]
rr = SPEC.poincare.R[:, :, toroidalIdx]
zz = SPEC.poincare.Z[:, :, toroidalIdx]
# get current figure or build new one;
if plt.get_fignums():
fig = plt.gcf()
ax = plt.gca()
else :
else:
fig, ax = plt.subplots()
# set default plotting parameters
# use dots
if kwargs.get('marker') == None:
if kwargs.get('marker') is None:
kwargs.update({'marker': '.'})
# use gray color
if kwargs.get('c') == None:
if kwargs.get('c') is None:
kwargs.update({'c': 'gray'})
# make plot depending on the 'range'
if prange == 'full':
dots = ax.scatter(rr, zz, **kwargs)
elif prange == 'upper':
dots = ax.scatter(rr[zz>=0], zz[zz>=0], **kwargs)
dots = ax.scatter(rr[zz >= 0], zz[zz >= 0], **kwargs)
elif prange == 'lower':
dots = ax.scatter(rr[zz<=0], zz[zz<=0], **kwargs)
else :
dots = ax.scatter(rr[zz <= 0], zz[zz <= 0], **kwargs)
else:
raise ValueError("prange should be one of ['full'(default), 'upper', 'lower'].")
# adjust figure properties
plt.xlabel('R [m]',fontsize=20)
plt.ylabel('Z [m]',fontsize=20)
plt.xlabel('R [m]', fontsize=20)
plt.ylabel('Z [m]', fontsize=20)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.axis('equal')
Expand Down
2 changes: 2 additions & 0 deletions ci/Dockerfile.centos7
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ RUN yum -y install epel-release
RUN yum install gcc-gfortran openmpi openmpi-devel hdf5 hdf5-devel -y
RUN yum install fftw3 fftw3-devel openblas openblas-devel -y
RUN yum install blas blas-devel lapack lapack-devel -y
RUN yum install -y python3 python3-devel
RUN pip3 install h5py matplotlib

# direct the existing makefile to the system install location
ENV FFTW_HOME=/usr
Expand Down
Binary file added ci/G1V03L2Fi/compare.h5
Binary file not shown.
20 changes: 20 additions & 0 deletions source.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
# source.sh
# This file sets the PATH to the current directory, which
# is the directory where the xspec file is located.
#
# It also updates the $PYTHONPATH variable so that the
# regression testing can be executed.
#

# Test if this is the folder where xspec lives then export paths or exit with error
if ( [ -e ./xspec ] && \
[ -e ./xspech.f90 ] ); then
export PATH=${PATH}:$PWD
export PYTHONPATH=${PYTHONPATH}:$PWD/Utilities/pythontools
else
echo "xspec executable does not exist, will not modify your path"
exit 1
fi


0 comments on commit bd7692a

Please sign in to comment.