centralized facilities for differential operations
note the need to reverse the grid shape in data from the ASCII table. If x is fastest, z is slowest we require x to be the rightmost index
This commit is contained in:
parent
80b50f460e
commit
3e65d44e07
|
@ -2,6 +2,7 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
from io import StringIO
|
||||
from optparse import OptionParser
|
||||
|
||||
import numpy as np
|
||||
|
@ -12,47 +13,6 @@ import damask
|
|||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
||||
scriptID = ' '.join([scriptName,damask.version])
|
||||
|
||||
def merge_dicts(*dict_args):
|
||||
"""Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts."""
|
||||
result = {}
|
||||
for dictionary in dict_args:
|
||||
result.update(dictionary)
|
||||
return result
|
||||
|
||||
def curlFFT(geomdim,field):
|
||||
"""Calculate curl of a vector or tensor field by transforming into Fourier space."""
|
||||
shapeFFT = np.array(np.shape(field))[0:3]
|
||||
grid = np.array(np.shape(field)[2::-1])
|
||||
N = grid.prod() # field size
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT)
|
||||
|
||||
# differentiation in Fourier space
|
||||
TWOPIIMG = 2.0j*np.pi
|
||||
einsums = {
|
||||
3:'slm,ijkl,ijkm->ijks', # vector, 3 -> 3
|
||||
9:'slm,ijkl,ijknm->ijksn', # tensor, 3x3 -> 3x3
|
||||
}
|
||||
k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0]
|
||||
if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1]
|
||||
if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_si = np.arange(grid[0]//2+1)/geomdim[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
|
||||
e = np.zeros((3, 3, 3))
|
||||
e[0, 1, 2] = e[1, 2, 0] = e[2, 0, 1] = 1.0 # Levi-Civita symbols
|
||||
e[0, 2, 1] = e[2, 1, 0] = e[1, 0, 2] = -1.0
|
||||
|
||||
curl_fourier = np.einsum(einsums[n],e,k_s,field_fourier)*TWOPIIMG
|
||||
|
||||
return np.fft.irfftn(curl_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,n])
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# MAIN
|
||||
|
@ -60,8 +20,7 @@ def curlFFT(geomdim,field):
|
|||
|
||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """
|
||||
Add column(s) containing curl of requested column(s).
|
||||
Operates on periodic ordered three-dimensional data sets
|
||||
of vector and tensor fields.
|
||||
Operates on periodic ordered three-dimensional data sets of vector and tensor fields.
|
||||
""", version = scriptID)
|
||||
|
||||
parser.add_option('-p','--pos','--periodiccellcenter',
|
||||
|
@ -69,93 +28,30 @@ parser.add_option('-p','--pos','--periodiccellcenter',
|
|||
type = 'string', metavar = 'string',
|
||||
help = 'label of coordinates [%default]')
|
||||
parser.add_option('-l','--label',
|
||||
dest = 'data',
|
||||
dest = 'labels',
|
||||
action = 'extend', metavar = '<string LIST>',
|
||||
help = 'label(s) of field values')
|
||||
|
||||
parser.set_defaults(pos = 'pos',
|
||||
)
|
||||
|
||||
|
||||
(options,filenames) = parser.parse_args()
|
||||
|
||||
if options.data is None: parser.error('no data column specified.')
|
||||
|
||||
# --- define possible data types -------------------------------------------------------------------
|
||||
|
||||
datatypes = {
|
||||
3: {'name': 'vector',
|
||||
'shape': [3],
|
||||
},
|
||||
9: {'name': 'tensor',
|
||||
'shape': [3,3],
|
||||
},
|
||||
}
|
||||
|
||||
# --- loop over input files ------------------------------------------------------------------------
|
||||
|
||||
if filenames == []: filenames = [None]
|
||||
|
||||
if options.labels is None: parser.error('no data column specified.')
|
||||
|
||||
for name in filenames:
|
||||
try: table = damask.ASCIItable(name = name,buffered = False)
|
||||
except: continue
|
||||
damask.util.report(scriptName,name)
|
||||
damask.util.report(scriptName,name)
|
||||
|
||||
# --- interpret header ----------------------------------------------------------------------------
|
||||
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
||||
grid,size = damask.util.coordGridAndSize(table.get_array(options.pos))
|
||||
|
||||
table.head_read()
|
||||
|
||||
remarks = []
|
||||
errors = []
|
||||
active = []
|
||||
|
||||
coordDim = table.label_dimension(options.pos)
|
||||
if coordDim != 3:
|
||||
errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos))
|
||||
else: coordCol = table.label_index(options.pos)
|
||||
|
||||
for me in options.data:
|
||||
dim = table.label_dimension(me)
|
||||
if dim in datatypes:
|
||||
active.append(merge_dicts({'label':me},datatypes[dim]))
|
||||
remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me))
|
||||
else:
|
||||
remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \
|
||||
'"{}" not found...'.format(me) )
|
||||
|
||||
if remarks != []: damask.util.croak(remarks)
|
||||
if errors != []:
|
||||
damask.util.croak(errors)
|
||||
table.close(dismiss = True)
|
||||
continue
|
||||
|
||||
# ------------------------------------------ assemble header --------------------------------------
|
||||
|
||||
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
|
||||
for data in active:
|
||||
table.labels_append(['{}_curlFFT({})'.format(i+1,data['label'])
|
||||
for i in range(np.prod(np.array(data['shape'])))]) # extend ASCII header with new labels
|
||||
table.head_write()
|
||||
|
||||
# --------------- figure out size and grid ---------------------------------------------------------
|
||||
|
||||
table.data_readArray()
|
||||
grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)])
|
||||
|
||||
# ------------------------------------------ process value field -----------------------------------
|
||||
|
||||
stack = [table.data]
|
||||
for data in active:
|
||||
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
|
||||
stack.append(curlFFT(size[::-1],
|
||||
table.data[:,table.label_indexrange(data['label'])].
|
||||
reshape(grid[::-1].tolist()+data['shape'])))
|
||||
|
||||
# ------------------------------------------ output result -----------------------------------------
|
||||
|
||||
if len(stack) > 1: table.data = np.hstack(tuple(stack))
|
||||
table.data_writeArray('%.12g')
|
||||
|
||||
# ------------------------------------------ output finalization -----------------------------------
|
||||
|
||||
table.close() # close input ASCII table (works for stdin)
|
||||
for label in options.labels:
|
||||
field = table.get_array(label)
|
||||
shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor
|
||||
field = table.get_array(label).reshape(np.append(grid[::-1],shape))
|
||||
table.add_array('curlFFT({})'.format(label),
|
||||
damask.grid_filters.curl(size[::-1],field).reshape((-1,np.prod(shape))),
|
||||
scriptID+' '+' '.join(sys.argv[1:]))
|
||||
|
||||
table.to_ASCII(sys.stdout if name is None else name)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
from io import StringIO
|
||||
from optparse import OptionParser
|
||||
|
||||
import numpy as np
|
||||
|
@ -12,52 +13,14 @@ import damask
|
|||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
||||
scriptID = ' '.join([scriptName,damask.version])
|
||||
|
||||
def merge_dicts(*dict_args):
|
||||
"""Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts."""
|
||||
result = {}
|
||||
for dictionary in dict_args:
|
||||
result.update(dictionary)
|
||||
return result
|
||||
|
||||
def divFFT(geomdim,field):
|
||||
"""Calculate divergence of a vector or tensor field by transforming into Fourier space."""
|
||||
shapeFFT = np.array(np.shape(field))[0:3]
|
||||
grid = np.array(np.shape(field)[2::-1])
|
||||
N = grid.prod() # field size
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT)
|
||||
|
||||
# differentiation in Fourier space
|
||||
TWOPIIMG = 2.0j*np.pi
|
||||
einsums = {
|
||||
3:'ijkl,ijkl->ijk', # vector, 3 -> 1
|
||||
9:'ijkm,ijklm->ijkl', # tensor, 3x3 -> 3
|
||||
}
|
||||
k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0]
|
||||
if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1]
|
||||
if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_si = np.arange(grid[0]//2+1)/geomdim[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
|
||||
div_fourier = np.einsum(einsums[n],k_s,field_fourier)*TWOPIIMG
|
||||
|
||||
return np.fft.irfftn(div_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,n//3])
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog option(s) [ASCIItable(s)]', description = """
|
||||
Add column(s) containing curl of requested column(s).
|
||||
Operates on periodic ordered three-dimensional data sets
|
||||
of vector and tensor fields.
|
||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """
|
||||
Add column(s) containing divergence of requested column(s).
|
||||
Operates on periodic ordered three-dimensional data sets of vector and tensor fields.
|
||||
""", version = scriptID)
|
||||
|
||||
parser.add_option('-p','--pos','--periodiccellcenter',
|
||||
|
@ -65,95 +28,30 @@ parser.add_option('-p','--pos','--periodiccellcenter',
|
|||
type = 'string', metavar = 'string',
|
||||
help = 'label of coordinates [%default]')
|
||||
parser.add_option('-l','--label',
|
||||
dest = 'data',
|
||||
dest = 'labels',
|
||||
action = 'extend', metavar = '<string LIST>',
|
||||
help = 'label(s) of field values')
|
||||
|
||||
parser.set_defaults(pos = 'pos',
|
||||
)
|
||||
|
||||
|
||||
(options,filenames) = parser.parse_args()
|
||||
|
||||
if options.data is None: parser.error('no data column specified.')
|
||||
|
||||
# --- define possible data types -------------------------------------------------------------------
|
||||
|
||||
datatypes = {
|
||||
3: {'name': 'vector',
|
||||
'shape': [3],
|
||||
},
|
||||
9: {'name': 'tensor',
|
||||
'shape': [3,3],
|
||||
},
|
||||
}
|
||||
|
||||
# --- loop over input files ------------------------------------------------------------------------
|
||||
|
||||
if filenames == []: filenames = [None]
|
||||
|
||||
if options.labels is None: parser.error('no data column specified.')
|
||||
|
||||
for name in filenames:
|
||||
try: table = damask.ASCIItable(name = name,buffered = False)
|
||||
except: continue
|
||||
damask.util.report(scriptName,name)
|
||||
damask.util.report(scriptName,name)
|
||||
|
||||
# --- interpret header ----------------------------------------------------------------------------
|
||||
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
||||
grid,size = damask.util.coordGridAndSize(table.get_array(options.pos))
|
||||
|
||||
table.head_read()
|
||||
|
||||
remarks = []
|
||||
errors = []
|
||||
active = []
|
||||
|
||||
coordDim = table.label_dimension(options.pos)
|
||||
if coordDim != 3:
|
||||
errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos))
|
||||
else: coordCol = table.label_index(options.pos)
|
||||
|
||||
for me in options.data:
|
||||
dim = table.label_dimension(me)
|
||||
if dim in datatypes:
|
||||
active.append(merge_dicts({'label':me},datatypes[dim]))
|
||||
remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me))
|
||||
else:
|
||||
remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \
|
||||
'"{}" not found...'.format(me) )
|
||||
|
||||
if remarks != []: damask.util.croak(remarks)
|
||||
if errors != []:
|
||||
damask.util.croak(errors)
|
||||
table.close(dismiss = True)
|
||||
continue
|
||||
|
||||
# ------------------------------------------ assemble header --------------------------------------
|
||||
|
||||
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
|
||||
for data in active:
|
||||
table.labels_append(['divFFT({})'.format(data['label']) if data['shape'] == [3] \
|
||||
else '{}_divFFT({})'.format(i+1,data['label'])
|
||||
for i in range(np.prod(np.array(data['shape']))//3)]) # extend ASCII header with new labels
|
||||
table.head_write()
|
||||
|
||||
# --------------- figure out size and grid ---------------------------------------------------------
|
||||
|
||||
table.data_readArray()
|
||||
|
||||
grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)])
|
||||
|
||||
# ------------------------------------------ process value field -----------------------------------
|
||||
|
||||
stack = [table.data]
|
||||
for data in active:
|
||||
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
|
||||
stack.append(divFFT(size[::-1],
|
||||
table.data[:,table.label_indexrange(data['label'])].
|
||||
reshape(grid[::-1].tolist()+data['shape'])))
|
||||
|
||||
# ------------------------------------------ output result -----------------------------------------
|
||||
|
||||
if len(stack) > 1: table.data = np.hstack(tuple(stack))
|
||||
table.data_writeArray('%.12g')
|
||||
|
||||
# ------------------------------------------ output finalization -----------------------------------
|
||||
|
||||
table.close() # close input ASCII table (works for stdin)
|
||||
for label in options.labels:
|
||||
field = table.get_array(label)
|
||||
shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor
|
||||
field = table.get_array(label).reshape(np.append(grid[::-1],shape))
|
||||
table.add_array('divFFT({})'.format(label),
|
||||
damask.grid_filters.divergence(size[::-1],field).reshape((-1,np.prod(shape)//3)),
|
||||
scriptID+' '+' '.join(sys.argv[1:]))
|
||||
|
||||
table.to_ASCII(sys.stdout if name is None else name)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
from io import StringIO
|
||||
from optparse import OptionParser
|
||||
|
||||
import numpy as np
|
||||
|
@ -12,43 +13,6 @@ import damask
|
|||
scriptName = os.path.splitext(os.path.basename(__file__))[0]
|
||||
scriptID = ' '.join([scriptName,damask.version])
|
||||
|
||||
def merge_dicts(*dict_args):
|
||||
"""Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts."""
|
||||
result = {}
|
||||
for dictionary in dict_args:
|
||||
result.update(dictionary)
|
||||
return result
|
||||
|
||||
def gradFFT(geomdim,field):
|
||||
"""Calculate gradient of a vector or scalar field by transforming into Fourier space."""
|
||||
shapeFFT = np.array(np.shape(field))[0:3]
|
||||
grid = np.array(np.shape(field)[2::-1])
|
||||
N = grid.prod() # field size
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT)
|
||||
|
||||
# differentiation in Fourier space
|
||||
TWOPIIMG = 2.0j*np.pi
|
||||
einsums = {
|
||||
1:'ijkl,ijkm->ijkm', # scalar, 1 -> 3
|
||||
3:'ijkl,ijkm->ijklm', # vector, 3 -> 3x3
|
||||
}
|
||||
|
||||
k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0]
|
||||
if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1]
|
||||
if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_si = np.arange(grid[0]//2+1)/geomdim[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
grad_fourier = np.einsum(einsums[n],field_fourier,k_s)*TWOPIIMG
|
||||
|
||||
return np.fft.irfftn(grad_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,3*n])
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# MAIN
|
||||
|
@ -56,9 +20,7 @@ def gradFFT(geomdim,field):
|
|||
|
||||
parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """
|
||||
Add column(s) containing gradient of requested column(s).
|
||||
Operates on periodic ordered three-dimensional data sets
|
||||
of vector and scalar fields.
|
||||
|
||||
Operates on periodic ordered three-dimensional data sets of scalar and vector fields.
|
||||
""", version = scriptID)
|
||||
|
||||
parser.add_option('-p','--pos','--periodiccellcenter',
|
||||
|
@ -66,7 +28,7 @@ parser.add_option('-p','--pos','--periodiccellcenter',
|
|||
type = 'string', metavar = 'string',
|
||||
help = 'label of coordinates [%default]')
|
||||
parser.add_option('-l','--label',
|
||||
dest = 'data',
|
||||
dest = 'labels',
|
||||
action = 'extend', metavar = '<string LIST>',
|
||||
help = 'label(s) of field values')
|
||||
|
||||
|
@ -74,85 +36,22 @@ parser.set_defaults(pos = 'pos',
|
|||
)
|
||||
|
||||
(options,filenames) = parser.parse_args()
|
||||
|
||||
if options.data is None: parser.error('no data column specified.')
|
||||
|
||||
# --- define possible data types -------------------------------------------------------------------
|
||||
|
||||
datatypes = {
|
||||
1: {'name': 'scalar',
|
||||
'shape': [1],
|
||||
},
|
||||
3: {'name': 'vector',
|
||||
'shape': [3],
|
||||
},
|
||||
}
|
||||
|
||||
# --- loop over input files ------------------------------------------------------------------------
|
||||
|
||||
if filenames == []: filenames = [None]
|
||||
|
||||
if options.labels is None: parser.error('no data column specified.')
|
||||
|
||||
for name in filenames:
|
||||
try: table = damask.ASCIItable(name = name,buffered = False)
|
||||
except: continue
|
||||
damask.util.report(scriptName,name)
|
||||
damask.util.report(scriptName,name)
|
||||
|
||||
# --- interpret header ----------------------------------------------------------------------------
|
||||
table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name)
|
||||
grid,size = damask.util.coordGridAndSize(table.get_array(options.pos))
|
||||
|
||||
table.head_read()
|
||||
|
||||
remarks = []
|
||||
errors = []
|
||||
active = []
|
||||
|
||||
coordDim = table.label_dimension(options.pos)
|
||||
if coordDim != 3:
|
||||
errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos))
|
||||
else: coordCol = table.label_index(options.pos)
|
||||
|
||||
for me in options.data:
|
||||
dim = table.label_dimension(me)
|
||||
if dim in datatypes:
|
||||
active.append(merge_dicts({'label':me},datatypes[dim]))
|
||||
remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me))
|
||||
else:
|
||||
remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \
|
||||
'"{}" not found...'.format(me) )
|
||||
|
||||
if remarks != []: damask.util.croak(remarks)
|
||||
if errors != []:
|
||||
damask.util.croak(errors)
|
||||
table.close(dismiss = True)
|
||||
continue
|
||||
|
||||
# ------------------------------------------ assemble header --------------------------------------
|
||||
|
||||
table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:]))
|
||||
for data in active:
|
||||
table.labels_append(['{}_gradFFT({})'.format(i+1,data['label'])
|
||||
for i in range(coordDim*np.prod(np.array(data['shape'])))]) # extend ASCII header with new labels
|
||||
table.head_write()
|
||||
|
||||
# --------------- figure out size and grid ---------------------------------------------------------
|
||||
|
||||
table.data_readArray()
|
||||
|
||||
grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)])
|
||||
|
||||
# ------------------------------------------ process value field -----------------------------------
|
||||
|
||||
stack = [table.data]
|
||||
for data in active:
|
||||
# we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation
|
||||
stack.append(gradFFT(size[::-1],
|
||||
table.data[:,table.label_indexrange(data['label'])].
|
||||
reshape(grid[::-1].tolist()+data['shape'])))
|
||||
|
||||
# ------------------------------------------ output result -----------------------------------------
|
||||
|
||||
if len(stack) > 1: table.data = np.hstack(tuple(stack))
|
||||
table.data_writeArray('%.12g')
|
||||
|
||||
# ------------------------------------------ output finalization -----------------------------------
|
||||
|
||||
table.close() # close input ASCII table (works for stdin)
|
||||
for label in options.labels:
|
||||
field = table.get_array(label)
|
||||
shape = (1,) if np.prod(field.shape)//np.prod(grid) == 1 else (3,) # scalar or vector
|
||||
field = table.get_array(label).reshape(np.append(grid[::-1],shape))
|
||||
table.add_array('gradFFT({})'.format(label),
|
||||
damask.grid_filters.gradient(size[::-1],field).reshape((-1,np.prod(shape)*3)),
|
||||
scriptID+' '+' '.join(sys.argv[1:]))
|
||||
|
||||
table.to_ASCII(sys.stdout if name is None else name)
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import numpy as np
|
||||
|
||||
|
||||
def curl(size,field):
|
||||
"""Calculate curl of a vector or tensor field in Fourier space."""
|
||||
def __ks(size,field):
|
||||
"""Get differential operator."""
|
||||
grid = np.array(np.shape(field)[0:3])
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2))
|
||||
|
||||
k_sk = np.where(np.arange(grid[0])>grid[0]//2,np.arange(grid[0])-grid[0],np.arange(grid[0]))/size[0]
|
||||
if grid[0]%2 == 0: k_sk[grid[0]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
@ -17,64 +13,47 @@ def curl(size,field):
|
|||
k_si = np.arange(grid[2]//2+1)/size[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
return np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3)
|
||||
|
||||
|
||||
def curl(size,field):
|
||||
"""Calculate curl of a vector or tensor field in Fourier space."""
|
||||
n = np.prod(field.shape[3:])
|
||||
k_s = __ks(size,field)
|
||||
|
||||
e = np.zeros((3, 3, 3))
|
||||
e[0, 1, 2] = e[1, 2, 0] = e[2, 0, 1] = +1.0 # Levi-Civita symbol
|
||||
e[0, 2, 1] = e[2, 1, 0] = e[1, 0, 2] = -1.0
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2))
|
||||
curl = (np.einsum('slm,ijkl,ijkm ->ijks', e,k_s,field_fourier)*2.0j*np.pi if n == 3 else # vector, 3 -> 3
|
||||
np.einsum('slm,ijkl,ijknm->ijksn',e,k_s,field_fourier)*2.0j*np.pi) # tensor, 3x3 -> 3x3
|
||||
|
||||
return np.fft.irfftn(curl,axes=(0,1,2))
|
||||
return np.fft.irfftn(curl,axes=(0,1,2),s=field.shape[0:3])
|
||||
|
||||
|
||||
def divergence(size,field):
|
||||
"""Calculate divergence of a vector or tensor field in Fourier space."""
|
||||
grid = np.array(np.shape(field)[0:3])
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
n = np.prod(field.shape[3:])
|
||||
k_s = __ks(size,field)
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=grid)
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2))
|
||||
divergence = (np.einsum('ijkl,ijkl ->ijk', k_s,field_fourier)*2.0j*np.pi if n == 3 else # vector, 3 -> 1
|
||||
np.einsum('ijkm,ijklm->ijkl',k_s,field_fourier)*2.0j*np.pi) # tensor, 3x3 -> 3
|
||||
|
||||
k_sk = np.where(np.arange(grid[0])>grid[0]//2,np.arange(grid[0])-grid[0],np.arange(grid[0]))/size[0]
|
||||
if grid[0]%2 == 0: k_sk[grid[0]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/size[1]
|
||||
if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_si = np.arange(grid[2]//2+1)/size[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
|
||||
divergence = (np.einsum('ijkl,ijkl ->ijk', k_s,field_fourier)*2.0j*np.pi if n == 3 else # vector, 3 -> 1
|
||||
np.einsum('ijkm,ijklm->ijkl',k_s,field_fourier)*2.0j*np.pi) # tensor, 3x3 -> 3
|
||||
|
||||
return np.fft.irfftn(div_fourier,axes=(0,1,2),s=grid)
|
||||
return np.fft.irfftn(divergence,axes=(0,1,2),s=field.shape[0:3])
|
||||
|
||||
|
||||
def gradient(size,field):
|
||||
"""Calculate gradient of a vector or scalar field in Fourier space."""
|
||||
grid = np.array(np.shape(field)[2::-1])
|
||||
n = np.array(np.shape(field)[3:]).prod() # data size
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=grid)
|
||||
|
||||
k_sk = np.where(np.arange(grid[0])>grid[0]//2,np.arange(grid[0])-grid[0],np.arange(grid[0]))/size[0]
|
||||
if grid[0]%2 == 0: k_sk[grid[0]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/size[1]
|
||||
if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011)
|
||||
|
||||
k_si = np.arange(grid[2]//2+1)/size[2]
|
||||
|
||||
kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij')
|
||||
k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16')
|
||||
n = np.prod(field.shape[3:])
|
||||
k_s = __ks(size,field)
|
||||
|
||||
field_fourier = np.fft.rfftn(field,axes=(0,1,2))
|
||||
gradient = (np.einsum('ijkl,ijkm->ijkm', field_fourier,k_s)*2.0j*np.pi if n == 1 else # scalar, 1 -> 3
|
||||
np.einsum('ijkl,ijkm->ijklm',field_fourier,k_s)*2.0j*np.pi) # vector, 3 -> 3x3
|
||||
|
||||
return np.fft.irfftn(grad_fourier,axes=(0,1,2),s=grid)
|
||||
return np.fft.irfftn(gradient,axes=(0,1,2),s=field.shape[0:3])
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue