kip-hart / microstructpy Goto Github PK
View Code? Open in Web Editor NEWMicrostructure modeling, mesh generation, analysis, and visualization.
Home Page: https://docs.microstructpy.org
License: MIT License
Microstructure modeling, mesh generation, analysis, and visualization.
Home Page: https://docs.microstructpy.org
License: MIT License
Is your feature request related to a problem? Please describe.
The vtk writer for PolyMesh
was actually a facets writer
instead of cell wrtier
. It also doesn't include the attributes such as volume, phase number and seed numbers.
I have wrote a vtk writer for polymesh. Now you can do following analyze:
This is a example of checking node ind and cell ind for any particular polyhedron. It will be very useful for debuging purpose.
Describe the solution you'd like
The working code is attached, please feel free to integrate it into the MicroStructPy.
seed_basename = 'seeds.vtk'
seed_filename = os.path.join(directory, seed_basename)
#seeds2VTK(seed_filename,seeds)
seeds.write(seed_filename)
poly_basename = 'polymesh.vtk'
poly_filename = os.path.join(directory, poly_basename)
#polymesh2VTK(poly_filename,pmesh)
pmesh.write(poly_filename)
import vtk
import vtk.util.numpy_support as vtk_np
def seeds2VTK(fname, seeds):
numPts=len(seeds)
geom_name = type(seeds.seeds[0].geometry).__name__.lower().strip()
centers=np.array([s.position for s in seeds.seeds])
if(centers.shape[1]==2):#extend to 3D pts
temp = np.zeros((numPts,3))
temp[:,:-1] = centers
centers=temp
vtkPoly=vtk.vtkPolyData()
if(geom_name in ['circle','sphere']):
verts = vtk.vtkPoints()
cells = vtk.vtkCellArray()
verts.SetNumberOfPoints(numPts)
verts.SetData(vtk_np.numpy_to_vtk(centers))
vtkPoly.SetPoints(verts)
cells_npy = np.vstack([np.ones(numPts,dtype=np.int64),
np.arange(numPts,dtype=np.int64)]).T.flatten()
cells.SetCells(numPts,vtk_np.numpy_to_vtkIdTypeArray(cells_npy))
vtkPoly.SetVerts(cells)
diameters=np.array([s.geometry.diameter for s in seeds.seeds])
#print(diameters)
diameters = vtk_np.numpy_to_vtk(diameters)
diameters.SetName("Diameters")
vtkPoly.GetCellData().SetScalars(diameters)
MaterialID=np.array([s.phase for s in seeds.seeds])
MaterialID = vtk_np.numpy_to_vtk(MaterialID)
MaterialID.SetName("MaterialID")
vtkPoly.GetCellData().AddArray(MaterialID)
writer = vtk.vtkPolyDataWriter()
writer.SetFileName(fname)
writer.SetInputData(vtkPoly)
writer.SetFileTypeToASCII() #We can switch to binary for large dataset
writer.Write()
else:
print('Other shape is not supported to write to VTK yet!')
def polymesh2VTK(fname,pmesh):
ugrid = vtk.vtkUnstructuredGrid()
# Create real polyhedron
points = vtk.vtkPoints()
points.SetNumberOfPoints(len(pmesh.points))
pmesh.points=np.array(pmesh.points)
for i in range(len(pmesh.points)):
points.SetPoint(i, pmesh.points[i,0],pmesh.points[i,1],pmesh.points[i,2])
ugrid.SetPoints(points)
# List of pointIds that make up the face
for cell in pmesh.regions:
faceId = vtk.vtkIdList()
faceId.InsertNextId(len(cell)) # Number faces that make up the cell.
for face in cell:
face_pts=pmesh.facets[face]
faceId.InsertNextId(len(face_pts)) # Number of points in face
[faceId.InsertNextId(i) for i in face_pts] # Insert the pointIds for the face
ugrid.InsertNextCell(vtk.VTK_POLYHEDRON, faceId)
MaterialID = vtk_np.numpy_to_vtk(num_array=np.array(pmesh.phase_numbers))
MaterialID.SetName("MaterialID")
ugrid.GetCellData().SetScalars(MaterialID)
SeedsID = vtk_np.numpy_to_vtk(num_array=np.array(pmesh.seed_numbers))
SeedsID.SetName("SeedsID")
ugrid.GetCellData().AddArray(SeedsID)
Vol=vtk_np.numpy_to_vtk(num_array=np.array(pmesh.volumes))
Vol.SetName("Volume")
ugrid.GetCellData().AddArray(Vol)
#writer = vtk.vtkXMLUnstructuredGridWriter()
writer = vtk.vtkUnstructuredGridWriter()
writer.SetInputData(ugrid)
writer.SetFileName(fname)
writer.SetFileTypeToASCII()
writer.Write()
Describe the bug
I have exported a triangular mesh with the abaqus format. When trying to import the file using meshio, I got
ValueError: invalid literal for int() with base 10: ' 3294.0'
The error seems to be caused by the element section in the .inp file, which starts by
*Element, type=C3D4 1, 3294.0, 2393.0, 2976.0, 4753.0 2, 56.0, 57.0, 2333.0, 2077.0 3, 2072.0, 2393.0, 3294.0, 4753.0
I suppose the values should be ints? Of course, this could also be a bug in the meshio read function.
To Reproduce
Steps to reproduce the behavior:
import microstructpy as msp
import scipy.stats
# Create Materials
m1 = {
'name': 'm1',
'volume': scipy.stats.lognorm(scale=0.5, s=0.95),
'size': 1,
'shape': 'sphere',
'fraction': 9
}
m2 = {
'name': 'm2',
'volume': scipy.stats.lognorm(scale=1, s=0.95),
'size': 0.2,
'shape': 'sphere',
'fraction': 1
}
materials = [m1,m2]
# Create Domain
domain = msp.geometry.Cube(side_length=7, corner=(0, 0, 0))
# Create List of Un-Positioned Seeds
seed_area = domain.volume
rng_seeds = {'size': 1}
seeds = msp.seeding.SeedList.from_info(materials,
seed_area,
rng_seeds)
# Position Seeds in Domain
seeds.position(domain)
# Create Polygonal Mesh
pmesh = msp.meshing.PolyMesh.from_seeds(seeds, domain)
# Create Triangular Mesh
tmesh = msp.meshing.TriMesh.from_polymesh(pmesh,materials, mesher='gmsh')
tmesh.write( 'trimesh.inp',format = "abaqus",polymesh=pmesh)
import meshio
mesh = meshio.read("trimesh.inp")
Expected behavior
Meshio imports .inp
Desktop (please complete the following information):
Linux 4.11.0-1-amd64 #1 SMP Debian 4.11.6-1 (2017-06-19) x86_64 GNU/Linux
in Jupyter notebook
Describe the bug
There is an error when saving the generated trimesh as abaqus file. The error is:
File "C:\Users\XXX\Desktop\foam.py", line 89, in main
tmesh.write('foam_mesh.inp', format='abaqus')
File "C:\Users\XXX\Anaconda3\envs\microstrucutpy\Lib\site-packages\microstructpy\meshing\trimesh.py", line 377, in write
poly_neighbors = np.array(polymesh.facet_neighbors)
AttributeError: 'NoneType' object has no attribute 'facet_neighbors'
To Reproduce
Steps to reproduce the behavior:
version
microstructpy 1.5.9
Howdy,
I have pip installed microstructpy with no error. But when running the python -c 'import microstructpy' command, I got an TypeError like this:
C:\Users\quanz>python -c "import microstructpy"
Traceback (most recent call last):
File "", line 1, in
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\microstructpy_init_.py", line 1, in
import microstructpy.cli
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\microstructpy\cli.py", line 31, in
from microstructpy.meshing import PolyMesh
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\microstructpy\meshing_init_.py", line 2, in
from microstructpy.meshing.trimesh import RasterMesh
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\microstructpy\meshing\trimesh.py", line 19, in
import pygmsh as pg
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pygmsh_init_.py", line 1, in
from . import geo, occ
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pygmsh\geo_init_.py", line 1, in
from .geometry import Geometry
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\pygmsh\geo\geometry.py", line 5, in
import gmsh
File "C:\Users\quanz\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\gmsh.py", line 53, in
lib = CDLL(libpath)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.752.0_x64__qbz5n2kfra8p0\lib\ctypes_init_.py", line 364, in init
if '/' in name or '\' in name:
TypeError: argument of type 'NoneType' is not iterable
Any help would be highly appreciated.
Regards,
Quan
Describe the bug
Troubleshooting "Missing library for pygmsh on Linux" doesn't work.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
When Step.4.
[sudo] password for iwahori:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'libglu1-mesa' instead of 'libglu1'
libglu1-mesa is already the newest version (9.0.2-1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Selected 'libglu1-mesa' instead of 'libglu1' is possible cause...
Desktop (please complete the following information):
Smartphone (please complete the following information):
Additional context
I'm not able to work with 2D ply meshes in any of the tools I've tried (paraview, meshio, trimesh).
3D ply meshes appear to work fine.
I don't know the ply standard very well, but by digging through some of the meshio module source code, it appears that ply may need to have 3 dimensions. I'd suspect setting all of the z values to 0 may make it work. Also the last half of the ply file looks to have what I suspect are supposed to be faces that appear to be only 2 points making them lines rather than faces.
The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.
Hi Kip,
I have to simplify my problem to be two main phases (matrix and inclusions), and I am able to import the file into Abaqus after doing this. After that, I found out that the mesh is an orphan mesh, which can't be changed, and I can't define the material properties to conduct FE simulations.
So, could you kindly inform me what I need to do or where I can read about it?
Regards,
Kip
Very nice work!
We try to use your package MicroStructPy in our research group to built polycristalline electrolytes for impedance simulation. We usually use numpy arrays in which each grain is represented by several array entries (very similar to voxels, or images in 2D). The grains are distinguishable by different integer values in the matrix. In this way it's easy to modify the structure and use it for several different purposes (as an example for our simulations).
Example for a 2D structure consisting of 2 grains:
1111112222
1111112222
1111222222
1112222222
I think it would be very nice if you could implement a function which can transform the 2d and 3d polygon mesh into numpy arrays.
Looking forward to your reply!
Hi, sorry for the odd question, but what are the future plans for this package? i.e. will it receive continuous TLC, or is/was it linked to a Ph.D. project or a fixed-term post-doc study?
I have used "pip install" the module and run the example but the export all txt file.
the document show let the ‘format=“abaqus”
’ and i do this in the installed file that the path“Lib\site-packages\microstructpy\meshing\trimesh.py
”. After that i re-run the example there haven't export abaqus file,whats the problem? i need your advice. Or i should change the compiled file of the trimesh.py?
Really thanks~
Looking forward to your reply!
Describe the bug
I'm receiving an AssertionError
when I try to generate a simple PolyMesh from a SeedList:
Traceback (most recent call last):
File "simple_microstructpy.py", line 15, in <module>
polymesh = microstructpy.meshing.PolyMesh.from_seeds(seed_list, domain, verbose=True)
File "(...)lib/python3.8/site-packages/microstructpy/meshing/polymesh.py", line 639, in from_seeds
assert not missing_seeds, str(missing_seeds)
AssertionError: {0, 1, 2, 3, 4}
To Reproduce
I am using the below script to reproduce this behaviour:
import microstructpy
position_array = [[-0.37342, -0.289708, 0.5128352],
[0.204211, 0.41113, 0.4889689],
[-0.453932, -0.178443, 0.4169717],
[-0.112715, 0.434528, 0.4959116],
[-0.12776, -0.0181222, 0.4907776]]
seed_list = microstructpy.seeding.SeedList()
for position in position_array:
new_seed = microstructpy.seeding.Seed.factory(seed_type="sphere", position=position)
seed_list.append(new_seed)
domain = microstructpy.geometry.Cube(side_length=1.2)
polymesh = microstructpy.meshing.PolyMesh.from_seeds(seed_list, domain, verbose=True)
Expected behavior
I'd expect a mesh to be generated here. I suspect the problem is with voro++ under the hood?
Is your feature request related to a problem? Please describe.
Gmsh mesh generator is support by many open-source simulation code. It will be nice to add a Gmsh meshing interface.
meshio
library support Gmsh
very well. Once we have gmsh file, we can use meshio
to convert the mesh into any mesh format, such asAbaqus, ANSYS msh, AVS-UCD, CGNS, DOLFIN XML, Exodus, FLAC3D, H5M, Kratos/MDPA, Medit, MED/Salome, Nastran (bulk data), Neuroglancer precomputed format, Gmsh (format versions 2.2, 4.0, and 4.1), OBJ, OFF, PERMAS, PLY, STL, Tecplot .dat, TetGen .node/.ele, SVG (2D only, output only), UGRID, VTK, VTU (not raw binary data), WKT (TIN), XDMF.
Describe the solution you'd like
The working code is attached, please feel free to integrate it into the MicroStructPy. It support to mesh any polymesh.region we want.
Noted that Gmsh is intefaced by generating its built-in script file *.geo
. We need to use Gmsh to load the geo file and generate mesh.
pmesh = msp.meshing.PolyMesh.from_seeds(seeds, domain)
tri_basename = 'polymesh_gmsh.geo'
tri_filename = os.path.join(directory, tri_basename)
Material_number=0
MaterialIDs=[i for i,p in enumerate(pmesh.phase_numbers) if p==Material_number]
#Current function usage
#geo=pgm.Mesh.mspPolymesh2geo(pmesh,regionIDs=MaterialIDs,max_edge_size=0.3)
#with open(tri_filename, 'w') as f:
# f.write(geo)
#Expected msp usage
tmesh = msp.meshing.TriMesh.from_polymesh(pmesh, phases, max_edge_length=0.3)
tmesh.write(tri_filename, "geo", seeds, pmesh)
def mspPolymesh2geo(polymesh,regionIDs=[],max_edge_size=-1):
"""Convert MicroStructPy polymesh to gmsh geo script
Method
--------
Chose the regionID you want to output
Author: Bin Wang([email protected])
Date: April. 2020
"""
NumRegions=len(polymesh.regions)
if(len(regionIDs)==0): regionIDs=[n for n in range(NumRegions)] #All region
#Collect Pts,facets and volumes for requested material
facets_out=[]
regionIDs_out=[]
for ri,region in enumerate(polymesh.regions):
for mID in regionIDs:
if(ri==mID):
facets_out+=region
regionIDs_out+=[ri]
pts_out=list(set([pi for fi in facets_out for pi in polymesh.facets[fi]]))
string=''
string += '/* -------Genetrated by PyGeoMesh------- */\n\n'
string += 'SetFactory("Built-in");\n' #This is not working well for fixing orientation
string +='\n'
#* 1. -----------Collect Points------------
string += '/* --Model_Points-- */\n'
for pi, pts in enumerate(polymesh.points):#Loop over regions
if(pi not in pts_out): continue
string += "p%d = newp; Point(p%d) = {%.20f,%.20f,%.20f};\n" % (pi,pi, pts[0], pts[1], pts[2])
string +='\n'
#* 2. -----------Collect Polyhedron Facet Edges------------
Line_id=0
string += '/* --Polyhedron Edges/Facets-- */\n'
for fi,facet in enumerate(polymesh.facets):
if(fi not in facets_out): continue
NumPts=len(facet)
temp ="clp%d = newll; Curve Loop(clp%d) = {" % (fi,fi)
for pi in range(NumPts):
id0,id1 = facet[pi],facet[(pi+1)%NumPts] #round end connect pair
string += "lp%d = newl; Line(lp%d) = {p%d,p%d};\n" % (Line_id, Line_id, id0, id1)
temp += "lp%d," % (Line_id)
Line_id = Line_id + 1
temp=temp[:-1] + "};\n"
#handle boundary inward normal vector
temp += "sp%d = news; Plane Surface(sp%d) = {clp%d};\n" % (fi,fi,fi)
string += temp + '\n'
string += '\n'
#* 3. -----------Collect Polyhedron------------
string += '/* --Polyhedron Cells-- */\n'
for ri,region in enumerate(polymesh.regions):
if(ri not in regionIDs_out): continue
string+='vlp%d = newsl; Surface Loop(vlp%d)={' %(ri,ri)
for fi in region:
facet_neigh=polymesh.facet_neighbors[fi]
if(facet_neigh[1]==ri): string+='-sp%d,'%(fi) #Backside of the facet
else: string+='sp%d,'%(fi)
string=string[:-1]+'};\n'
string+='vp%d = newv; Volume(vp%d)={vlp%d};\n' %(ri,ri,ri)
string +='\n'
string += '/* --Combine Duplicated Entites, Polyhedron Edges here-- */\n'
string+='Coherence;\n'
#* 4. ------------Reverse boundary facet orientation-----------
inward_facet=[]
regionIDs_wall=list( set(range(len(polymesh.regions))) - set(regionIDs_out) )
id2tagName={-1:'X-',-2:'X+',-3:'Y-',-4:'Y+',-5:'Z-',-6:'Z+'}
boundary_facets={'X-':[],'X+':[],'Y-':[],'Y+':[],'Z-':[],'Z+':[],'Wall':[]}
for fi,facet in enumerate(polymesh.facets):
if(fi not in facets_out): continue
facet_neigh=np.array(polymesh.facet_neighbors[fi])
check1=facet_neigh[0]<0 or facet_neigh[1]<0 #boundary facet X-,X+...
check2=facet_neigh[0] in regionIDs_wall or facet_neigh[1] in regionIDs_wall #material interface wall
#print('facet',fi,'neigh',facet_neigh,check1,check2)
if(check1 or check2):#This is a boundary facet
if(facet_neigh[1] in regionIDs_out):#Normal always point toward facet_neigh[1] cell
inward_facet+=[fi]
if(check1):
boundary_id=facet_neigh[facet_neigh<0][0]
boundary_name=id2tagName[boundary_id]
boundary_facets[boundary_name].append(fi)
if(check2):
boundary_facets['Wall'].append(fi)
string +='\n'
#print(inward_facet,regionIDs_wall)
string += '/* --Fix boundary surface orientation-- */\n'
string += 'ReverseMesh Surface{%s};\n' % ','.join('sp'+str(x) for x in inward_facet)
string +='\n'
string += '/* --Physical Tags-- */\n'
print('boundary facets Tag=',boundary_facets)
for name,facet_list in boundary_facets.items():
if(len(facet_list)>0):
string+='Physical Surface("%s") = {%s};\n' %(name,','.join('sp'+str(f) for f in facet_list))
for ri,region_geo in enumerate(polymesh.regions):
if(ri not in regionIDs_out): continue
string+='Physical Volume("Material%d") = {vp%d};\n' %(ri,ri)
string+='\n'
string += '/* --Mesh Size Setup-- */\n'
if(max_edge_size==-1):#Auto mesh size
max_edge_size=np.sum(polymesh.volumes)**(1/3.0)/8.0
string +='//Mesh.CharacteristicLengthMin = %s;\n' %(max_edge_size)
string +='Mesh.CharacteristicLengthMax = %s;\n' %(max_edge_size)
return string
When I try to install the microstuctpy I found that there is a problem when matplotlib content is installing within the whole installation of microstructpy.
Before that I have installed scipy and numpy in this new-build conda environment. necessary c++ development enviro have been installed
When I try to solve this I found that all discussion only talk about several special version matplotlib installation. For this case there is no discussion.
How can I solve that?
Thanks for your nice Python code for such microstructure modeling.
Is your feature request related to a problem? Please describe.
CLI interface can plot very nice seeds, polymesh and trimesh. But I need write very long code to reproduce the figure, here is an examples
def getPhaseColor(i,phases):
return phases[i].get('color', 'C' + str(i % 10))
# Create Figure
k = 1
off = 1
len_x = domain.length + 2 * off
len_y = domain.width + 2 * off
plt.figure(figsize=(k * len_x, k * len_y))
# Plot Seeds
seed_colors=[getPhaseColor(s.phase, phases) for s in seeds]
seeds.plot(color=seed_colors, alpha=0.8, edgecolor='k', linewidth=0.3)
domain.plot(facecolor='none', edgecolor='k', linewidth=0.5)
# Add legend
legend_patchs=[]
for ph in phases:
legend_patchs.append( mpatches.Patch(color=ph["color"], ec='k',label=ph["name"]) )
plt.legend(handles=legend_patchs)
plt.axis('image')
plt.show()
Describe the solution you'd like
# Create Figure
plt.figure(figsize=(5, 5))
seeds.plot(material_name=['Matrix','Void'],color=['C0','C1'], alpha=0.8, edgecolor='k', linewidth=0.3)
domain.plot(facecolor='none', edgecolor='k', linewidth=0.5)
plt.axis('image')
plt.show()
Hi,
My name is Mostafa Mohamed and am a graduate student at Arizona State University.
I am reporting this bug as follows: the error appears:
"TypeError: FigureBase.gca() got an unexpected keyword argument 'projection'"
Thanks in advance for any help!
Regards,
Mostafa
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.