"""
Tessellation module
===================
:synopsis: Periodic domain weighted tessellation.
.. moduleauthor:: Pavel Ferkl <pavel.ferkl@gmail.com>
.. moduleauthor:: Mohammad Marvi-Mashhadi <mohammad.marvi@imdea.org>
"""
import os
import subprocess as sp
import shlex as sx
import pandas as pd
from .geo_tools import read_geo, extract_data
from . import vtk_tools
[docs]def tessellate(fname, visualize, clean):
"""Use Laguerre tessellation to create dry foam.
Uses `Neper <http://neper.sourceforge.net/>`_ for tessellation.
``*Packing.csv`` must exists.
Args:
fname (str): base filename
visualize (bool): create picture of tessellation if True
clean (bool): delete redundant files if True
"""
number_of_cells = prep(fname)
neper_tessellation(fname, number_of_cells)
periodic_box(fname, 1, False)
save_gnuplot(fname)
if visualize:
neper_visualize(fname)
if clean:
clean_files()
[docs]def prep(fname):
"""Prepare input files for Neper.
Creates ``centers.txt`` and ``rads.txt`` files.
Args:
fname (str): base filename
Returns:
int: number of cells
"""
dtf = pd.read_csv(fname + 'Packing.csv')
dtf['r'] = dtf['d'] / 2
dtf[['x', 'y', 'z']].to_csv('centers.txt', sep='\t', header=None,
index=None)
dtf[['r']].to_csv('rads.txt', sep='\t', header=None, index=None)
return len(dtf)
[docs]def neper_tessellation(fname, number_of_cells, rve_size=1):
"""Run Neper tessellation module.
Neper regularization is not available for periodic tessellations. Requires
``centers.txt`` and ``rads.txt`` files.
Args:
fname (str): base filename
number_of_cells (int): number of cells
rve_size (float, optional): domain size
"""
command = "neper -T \
-n {0:d} \
-domain 'cube({1:d},{1:d},{1:d})' \
-periodicity x,y,z \
-morpho voronoi \
-morphooptiini 'coo:file(centers.txt),weight:file(rads.txt)' \
-o {2}Tessellation -format tess,geo \
-statcell vol -statedge length -statface area \
-statver x".format(number_of_cells, rve_size, fname)
sp.Popen(sx.split(command)).wait()
[docs]def neper_visualize(fname):
"""Run Neper visualization module.
Requires POV-Ray package. Requires ``*Tessellation.tess`` and ``rads.txt``
files.
Args:
fname (str): base filename
"""
command = "neper -V {0}Tessellation.tess -datacellcol ori \
-datacelltrs 0.5 -showseed all -dataseedrad @rads.txt \
-dataseedtrs 1.0 -print {0}Tessellation".format(fname)
sp.Popen(sx.split(command))
[docs]def save_gnuplot(fname):
"""Save tessellation in gnuplot format.
Requires ``*Tessellation.tess`` file. Creates ``*Tessellation.gnu`` file.
Args:
fname (str): base filename
"""
sdat = read_geo(fname + "Tessellation.geo")
edat = extract_data(sdat)
point = edat["point"]
line = edat["line"]
with open('{0}Tessellation.gnu'.format(fname), 'w') as flp:
for pidx in line.values():
flp.write('{0} {1} {2}\n'.format(
point[pidx[0]][0], point[pidx[0]][1], point[pidx[0]][2]))
flp.write('{0} {1} {2}\n\n\n'.format(
point[pidx[1]][0], point[pidx[1]][1], point[pidx[1]][2]))
[docs]def periodic_box(fname, dsize, render):
"""Uses gmsh and vtk to move closed foam to periodic box.
Requires ``*Tessellation.geo`` file. Creates ``*TessellationBox.stl`` file.
Args:
fname (str): base filename
dsize (float): box size
render (bool): render scene if True
"""
geo_to_stl(fname + "Tessellation.geo")
vtk_tools.stl_to_periodic_box(
fname + "Tessellation.stl", fname + "TessellationBox.stl", [0, 0, 0],
[dsize, dsize, dsize], render
)
[docs]def geo_to_stl(fin):
"""Convert ``*.geo`` file to ``*.stl`` file
Uses ``gmsh``.
Args:
fin (str): input filename
"""
print("Converting .geo to .stl")
cmd = sx.split("gmsh -n -2 -v 3 -format stl " + fin)
sp.Popen(cmd).wait()
[docs]def clean_files():
"""Delete unnecessary files."""
flist = [
'centers.txt',
'rads.txt',
'generation.conf',
'packing_init.xyzd',
'packing.nfo',
'packing_prev.xyzd',
'packing.xyzd',
]
for fil in flist:
if os.path.exists(fil):
os.remove(fil)