avoid detour via shell

This commit is contained in:
Martin Diehl 2020-03-29 19:12:23 +02:00
parent f1b4d81fb4
commit e61c1a027b
2 changed files with 109 additions and 9 deletions

View File

@ -1,11 +1,15 @@
import sys import sys
from io import StringIO from io import StringIO
import multiprocessing
from functools import partial
import numpy as np import numpy as np
from scipy import ndimage from scipy import ndimage,spatial
from . import VTK from . import VTK
from . import util from . import util
from . import Environment
from . import grid_filters
class Geom: class Geom:
@ -50,7 +54,7 @@ class Geom:
def update(self,microstructure=None,size=None,origin=None,rescale=False): def update(self,microstructure=None,size=None,origin=None,rescale=False):
""" """
Updates microstructure and size. Update microstructure and size.
Parameters Parameters
---------- ----------
@ -113,7 +117,7 @@ class Geom:
def set_comments(self,comments): def set_comments(self,comments):
""" """
Replaces all existing comments. Replace all existing comments.
Parameters Parameters
---------- ----------
@ -127,7 +131,7 @@ class Geom:
def add_comments(self,comments): def add_comments(self,comments):
""" """
Appends comments to existing comments. Append comments to existing comments.
Parameters Parameters
---------- ----------
@ -140,7 +144,7 @@ class Geom:
def set_microstructure(self,microstructure): def set_microstructure(self,microstructure):
""" """
Replaces the existing microstructure representation. Replace the existing microstructure representation.
Parameters Parameters
---------- ----------
@ -159,7 +163,7 @@ class Geom:
def set_size(self,size): def set_size(self,size):
""" """
Replaces the existing size information. Replace the existing size information.
Parameters Parameters
---------- ----------
@ -179,7 +183,7 @@ class Geom:
def set_origin(self,origin): def set_origin(self,origin):
""" """
Replaces the existing origin information. Replace the existing origin information.
Parameters Parameters
---------- ----------
@ -196,7 +200,7 @@ class Geom:
def set_homogenization(self,homogenization): def set_homogenization(self,homogenization):
""" """
Replaces the existing homogenization index. Replace the existing homogenization index.
Parameters Parameters
---------- ----------
@ -264,7 +268,7 @@ class Geom:
@staticmethod @staticmethod
def from_file(fname): def from_file(fname):
""" """
Reads a geom file. Read a geom file.
Parameters Parameters
---------- ----------
@ -325,6 +329,81 @@ class Geom:
return Geom(microstructure.reshape(grid),size,origin,homogenization,comments) return Geom(microstructure.reshape(grid),size,origin,homogenization,comments)
@staticmethod
def _find_closest_seed(seeds, weights, point):
return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights)
@staticmethod
def from_Laguerre_tessellation(grid,size,seeds,weights,periodic=True):
"""
Generate geometry from Laguerre tessellation.
Parameters
----------
grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction.
size : list or numpy.ndarray of shape (3)
physical size of the microstructure in meter.
seeds : numpy.ndarray of shape (:,3)
position of the seed points in meter. All points need to lay within the box.
weights : numpy.ndarray of shape (seeds.shape[0])
weights of the seeds. Setting all weights to 1.0 gives a standard Voronoi tessellation.
periodic : Boolean, optional
perform a periodic tessellation. Defaults to True.
"""
if periodic:
weights_p = np.tile(weights,27).flatten(order='F') # Laguerre weights (1,2,3,1,2,3,...,1,2,3)
seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.])))
seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.])))
seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]])))
coords = grid_filters.cell_coord0(grid*3,size*3,-size).reshape(-1,3,order='F')
else:
weights_p = weights.flatten()
seeds_p = seeds
coords = grid_filters.cell_coord0(grid,size).reshape(-1,3,order='F')
pool = multiprocessing.Pool(processes = int(Environment().options['DAMASK_NUM_THREADS']))
result = pool.map_async(partial(Geom._find_closest_seed,seeds_p,weights_p), [coord for coord in coords])
pool.close()
pool.join()
microstructure = np.array(result.get())
if periodic:
microstructure = microstructure.reshape(grid[0]*3,grid[1]*3,grid[2]*3)
microstructure = microstructure[grid[0]:grid[0]*2,grid[1]:grid[1]*2,grid[2]:grid[2]*2]%seeds.shape[0]
else:
microstructure = microstructure.reshape(grid)
#comments = 'geom.py:from_Laguerre_tessellation v{}'.format(version)
return Geom(microstructure+1,size,homogenization=1)
@staticmethod
def from_Voronoi_tessellation(grid,size,seeds,periodic=True):
"""
Generate geometry from Voronoi tessellation.
Parameters
----------
grid : numpy.ndarray of shape (3)
number of grid points in x,y,z direction.
size : list or numpy.ndarray of shape (3)
physical size of the microstructure in meter.
seeds : numpy.ndarray of shape (:,3)
position of the seed points in meter. All points need to lay within the box.
periodic : Boolean, optional
perform a periodic tessellation. Defaults to True.
"""
coords = grid_filters.cell_coord0(grid,size).reshape(-1,3,order='F')
KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds)
devNull,microstructure = KDTree.query(coords)
#comments = 'geom.py:from_Voronoi_tessellation v{}'.format(version)
return Geom(microstructure.reshape(grid)+1,size,homogenization=1)
def to_file(self,fname,pack=None): def to_file(self,fname,pack=None):
""" """
Writes a geom file. Writes a geom file.

View File

@ -97,3 +97,24 @@ class TestGeom:
reference = os.path.join(reference_dir,'scale_{}.geom'.format(tag)) reference = os.path.join(reference_dir,'scale_{}.geom'.format(tag))
if update: modified.to_file(reference) if update: modified.to_file(reference)
assert geom_equal(modified,Geom.from_file(reference)) assert geom_equal(modified,Geom.from_file(reference))
@pytest.mark.parametrize('periodic',[(True),(False)])
def test_tessellation(self,periodic):
grid = np.random.randint(10,20,3)
size = np.random.random(3) + 1.0
N_seeds= np.random.randint(10,30)
seeds = np.random.rand(N_seeds,3) * np.broadcast_to(size,(N_seeds,3))
Voronoi = Geom.from_Voronoi_tessellation( grid,size,seeds, periodic)
Laguerre = Geom.from_Laguerre_tessellation(grid,size,seeds,np.ones(N_seeds),periodic)
assert geom_equal(Laguerre,Voronoi)
def test_Laguerre(self):
grid = np.random.randint(10,20,3)
size = np.random.random(3) + 1.0
N_seeds= np.random.randint(10,30)
seeds = np.random.rand(N_seeds,3) * np.broadcast_to(size,(N_seeds,3))
weights= np.full((N_seeds),-np.inf)
ms = np.random.randint(1, N_seeds+1)
weights[ms-1] = np.random.random()
Laguerre = Geom.from_Laguerre_tessellation(grid,size,seeds,weights,np.random.random()>0.5)
assert np.all(Laguerre.microstructure == ms)