"""
Tools for gmsh/getdp control and input/output.
"""
import meshio
import os
import subprocess
import numpy as np
import shutil
from pyonelab import gmsh, getdp
def make_var_str(varname, varvalue):
s = varname + " = " + str(varvalue) + ";"
return s
def append_inputs(str_to_append, data_file):
f = open(data_file, "a")
f.write("\n")
f.write(str_to_append)
f.close()
def make_inputs(data_dict):
S = ""
for key in data_dict:
s = "\n" + make_var_str(key, data_dict[key])
S += s
return S
def write_inputs(string, data_file, close=True):
f = open(data_file, "w")
f.write(string)
if close:
f.close()
return f
def get_content(filename):
with open(filename) as f:
conts = f.read()
f.close()
return conts
def maketmp(content, filename, dirname="", mode="w"):
path = os.path.join(dirname, filename)
with open(path, mode) as f:
f.write(content)
f.close()
return path
[docs]def mesh_model(
path_mesh, path_geo, mesh_format="msh2", dim=None, verbose=0, other_option=""
):
"""Mesh the model using Gmsh_
.. _Gmsh:
http://gmsh.info/
"""
dim = dim or [1, 2]
list_dim = ["-{}".format(d) for d in dim]
command = [gmsh, "-v", str(verbose), "-format", mesh_format, path_geo]
command += list_dim + other_option.split() + ["-o", path_mesh]
subprocess.call(command)
def solve_problem(resolution, path_pro, path_mesh, path_pos=None, verbose=0, argstr=""):
command = [
getdp,
"-v",
str(verbose),
path_pro,
"-pre",
resolution,
"-msh",
path_mesh,
]
if path_pos:
command += ["-gmshread"] + path_pos.split()
command += ["-cal", "-v2"] + argstr.split()
subprocess.call(command)
def make_content_mesh_pos(nodes, els, dom, celltype):
nodes_ID, nodes_coords = nodes
els_ID, _, els_nodes_ID, geom_ID_dom = els
s = "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"
nnodes = len(nodes_ID)
s += "$Nodes\n"
s += str(nnodes) + "\n"
for i in range(nnodes):
x, y, z = nodes_coords[i]
s += str(nodes_ID[i]) + " " + str(x) + " " + str(y) + " " + str(z) + "\n"
s += "$EndNodes\n"
nels = len(els_ID)
s += "$Elements\n"
s += str(nels) + "\n"
for i in range(nels):
if celltype is "triangle":
s1 = str(2)
elif celltype is "quad":
s1 = str(3)
elif celltype is "tetra":
s1 = str(4)
s += (
str(els_ID[i])
+ " "
+ s1
+ " 2 "
+ str(dom)
+ " "
+ str(geom_ID_dom[i])
+ " "
)
for j in els_nodes_ID[i]:
s += str(j) + " "
s += "\n"
s += "$EndElements\n"
return s
def get_nodes(path_mesh, physical_ID, celltype):
mesh = meshio.read(path_mesh)
phys_ID = mesh.cell_data[celltype]["gmsh:physical"]
domain = phys_ID == physical_ID
cell = mesh.cells[celltype]
els_nodes_ID = cell[domain]
nodes_ID_domain = np.unique(els_nodes_ID.flatten())
nodes_coords_domain = mesh.points[nodes_ID_domain]
return nodes_ID_domain + 1, nodes_coords_domain
def get_elements(path_mesh, physical_ID, celltype):
mesh = meshio.read(path_mesh)
phys_ID = mesh.cell_data[celltype]["gmsh:physical"]
domain = phys_ID == physical_ID
n = 1
for k in mesh.cell_data.keys():
if k is celltype:
n += 0
else:
n += len(mesh.cell_data[k]["gmsh:physical"])
el_ID = np.arange(0, len(domain))[domain] + n
cell = mesh.cells[celltype]
els_nodes_ID = cell[domain]
el_center = np.mean(mesh.points[els_nodes_ID], axis=1)
return el_ID, el_center, els_nodes_ID + 1, None
def make_pos(ID, data, content_mesh, viewname, celltype="nodes", mesh_format=2):
s = content_mesh
if not s:
if mesh_format == 2:
meshversion = "2.2 0 8"
else:
meshversion = "4.1 0 8"
s = "$MeshFormat\n{}\n$EndMeshFormat\n".format(meshversion)
N = len(ID)
if celltype is "nodes":
str_start, str_end = "$NodeData\n", "$EndNodeData\n"
elif celltype is "elements":
str_start, str_end = "$ElementData\n", "$EndElementData\n"
elif celltype is "elements_nodes":
str_start, str_end = "$ElementNodeData\n", "$EndElementNodeData\n"
else:
raise TypeError("Wrong celltype specified: choose between nodes and elements")
for dat, name in zip([data.real, data.imag], ["_real", "_imag"]):
s += str_start
s += '1\n"' + viewname + name + '"\n1\n0\n3\n0\n1\n' + str(N) + "\n"
for idf, value in zip(ID, dat):
if celltype is "elements_nodes":
s += str(int(idf)) + " 3 " + (str(value.real) + " ") * 3 + "\n"
else:
s += str(int(idf)) + " " + str(value.real) + "\n"
s += str_end
return s
def open_gmsh(path_mesh, path_geo, pos_list=None, verbose=2):
pos_list = pos_list or []
command = [gmsh, path_geo, path_mesh] + pos_list + ["-v", str(verbose), "&"]
# subprocess.call(command, shell=True)
subprocess.call(" ".join(command), shell=True)
# os.system(" ".join(command))
[docs]def postpro_commands(postop, path_pro, path_mesh, path_pos=None, verbose=0):
"""Generate a command list for postprocessing by GetDP (see main.pro
file in ./base folder for default available postprocessings, or to add
your own)
Args:
postop (str): The name of the postoperation to perform.
path_pro (str): Path to the .pro file
path_mesh (str): Path to the .msh file
path_pos (str , optional): Path to a file to be read by ``gmshread``.
verbose (int): verbosity level
Defaults to None.
Returns:
list : The list of strings to be oscommanded.
"""
path_res = path_pro[:-4] + ".res"
s = (
getdp
+ " -v "
+ str(verbose)
+ " "
+ path_pro
+ " -res "
+ path_res
+ " -msh "
+ path_mesh
)
if path_pos:
s += " -gmshread " + path_pos
s += " -pos " + postop + " -v2"
return s.split()
def load_node_table(filename):
nodenumber = np.loadtxt(filename, usecols=[0], skiprows=1)
values = np.loadtxt(filename, usecols=[1], skiprows=1) + 1j * np.loadtxt(
filename, usecols=[2], skiprows=1
)
return nodenumber, values
def load_table(filename):
return np.loadtxt(filename, usecols=[3]) + 1j * np.loadtxt(filename, usecols=[4])
# def load_node_table_vect(filename):
# nodenumber = np.loadtxt(filename, usecols=[0], skiprows=1)
# values = np.loadtxt(filename, usecols=[1], skiprows=1) + 1j * np.loadtxt(
# filename, usecols=[2], skiprows=1
# )
# return nodenumber, values
def load_table_vect(filename):
vect = []
for i in range(3):
comp = 0
for j in range(2):
comp += np.loadtxt(filename, usecols=[3 + i + j * 3]) * np.exp(
j * 1j * np.pi / 2
)
vect.append(comp)
return vect
def load_node_table_vect(filename):
nodenumber = np.loadtxt(filename, usecols=[0], skiprows=1)
vect = []
for i in range(3):
comp = 0
for j in range(2):
comp += np.loadtxt(filename, usecols=[1 + i + j * 3], skiprows=1) * np.exp(
j * 1j * np.pi / 2
)
vect.append(comp)
return nodenumber, vect
def load_element_table_vect(filename):
# nodenumber = np.loadtxt(filename, usecols=[0], skiprows=1)
vect = []
for i in range(3):
comp = 0
for j in range(2):
comp += np.loadtxt(filename, usecols=[1 + i + j * 3], skiprows=1) * np.exp(
j * 1j * np.pi / 2
)
vect.append(comp)
# return nodenumber, vect
return vect
def load_timetable(filename):
return np.loadtxt(filename, usecols=[5]) + 1j * np.loadtxt(filename, usecols=[6])
def load_ev_timetable(filename):
return np.loadtxt(filename, usecols=[1]) + 1j * np.loadtxt(filename, usecols=[5])
def points2geo(points, lc_incl, output_path="./tmp.geo", startpoint=1000):
x, y = points
fout = open(output_path, "w")
# lc_name = "%s_lc" % filename[0:3]
# Format
# Point(1) = {0, 0, 0, lc};
# fout.write("%s = 0.005;\n" % lc_name)
j = startpoint
n_lines = len(x)
for i in range(n_lines):
outputline = "Point(%i) = { %8.8f, %8.8f, %8.8f, %s};\n " % (
j,
x[i],
y[i],
0,
lc_incl,
)
j = j + 1
fout.write(outputline)
# gmsh bspline format
# Write out splinefit line
fout.write(
"BSpline(%i) = {%i:%i};\n" % (startpoint, startpoint, startpoint + n_lines - 1)
)
fout.close()