def readPolyhedronOFF(filename): f = open(filename, "r") line = f.readline() assert line[:3].lower() == "off" while line[0] == "#": line = f.readline() stuff = line.split() assert len(stuff) == 3 nv, nf, ne = int(stuff[0]), int(stuff[1]), int(stuff[2]) # Read the vertex positions. verts = vector_of_Vector() for i in xrange(nv): line = f.readline() stuff = line.split() assert len(stuff) == 3 verts.append(Vector(float(stuff[0]), float(stuff[1]), float(stuff[2]))) # Read the face vertex indices. facets = vector_of_vector_of_unsigned() for i in xrange(nf): line = f.readline() stuff = line.split() assert len(stuff) >= 4 n = int(stuff[0]) facets.push_back(vector_of_unsigned(n)) for j in xrange(n): k = int(stuff[j+1]) assert k < nv facets[-1][j] = k # Build the polyhedron and we're done. poly = Polyhedron(verts, facets) return poly
def readPolyhedronOBJ(filename): f = open(filename, "r") verts = vector_of_Vector() facets = vector_of_vector_of_unsigned() for line in f: stuff = line.split() if stuff: if stuff[0] == "v": assert len(stuff) == 4 verts.append(Vector(float(stuff[1]), float(stuff[2]), float(stuff[3]))) elif stuff[0] == "f": assert len(stuff) >= 4 facets.append(vector_of_unsigned()) for x in stuff[1:]: facets[-1].append(int(x.split("/")[0]) - 1) f.close() nverts = len(verts) for i in xrange(len(facets)): for j in xrange(len(facets[i])): assert facets[i][j] < nverts poly = Polyhedron(verts, facets) return poly
def __init__(self, n, rho, rmin, rmax, gradrho = None, maxIterations = 100, centroidFrac = 1.0, fracTol = 1.0e-3, tessellationBaseDir = ".", tessellationFileName = None, nNodePerh = 2.01, offset = (0.0, 0.0, 0.0), rejecter = None, randomseed = 492739149274, maxNodesPerDomain = 1000, seedPositions = None, enforceConstantMassPoints = False, cacheFileName = None): from Spheral3d import vector_of_Vector, Vector from GenerateNodeDistribution3d import GenerateIcosahedronMatchingProfile3d SphericallyConformalMap = GenerateIcosahedronMatchingProfile3d(n=n, densityProfileMethod=rho, rmin=rmin, rmax=rmax, nNodePerh=nNodePerh, offset=offset, rejecter=rejecter) n = len(SphericallyConformalMap.positions) # this is a serialized list, so it needs to be broken up to each processor # no degeneracies allowed! seedPositions = vector_of_Vector() nprocs = mpi.procs nlocal = int(n/nprocs) nrem = n - nlocal*nprocs myn = nlocal if mpi.rank == nprocs-1: myn += nrem for i in xrange(myn): j = i + mpi.rank*nlocal seedPositions.append(Vector(SphericallyConformalMap.positions[j][0], SphericallyConformalMap.positions[j][1], SphericallyConformalMap.positions[j][2])) # Now construct boundaries based on rmin and rmax bpoints = vector_of_Vector() nshell = 300 # fix this later for i in xrange(1,nshell+1): h = -1.0+(2.0*(i-1.0)/(nshell-1.0)) t = acos(h) if (i>1 and i<nshell): p = (p + 3.8/sqrt(nshell)*1.0/sqrt(1.0-h*h)) % (2.0*pi) else: p = 0 bpoints.append(Vector(rmax*sin(t)*cos(p), rmax*sin(t)*sin(p), rmax*cos(t))) bound1 = Polyhedron(bpoints) if (rmin > 0.0): for i in xrange(nshell): bpoints[i] *= rmin/rmax bound2 = Polyhedron(bpoints) # The base generator does most of the work. MedialGeneratorBase.__init__(self, ndim = 3, n = n, rho = rho, boundary = bound1, gradrho = gradrho, holes = bound2 if (rmin>0.0) else [], centroidFrac = centroidFrac, maxIterations = maxIterations, fracTol = fracTol, tessellationBaseDir = tessellationBaseDir, tessellationFileName = tessellationFileName, nNodePerh = nNodePerh, randomseed = randomseed, maxNodesPerDomain = maxNodesPerDomain, seedPositions = seedPositions, enforceConstantMassPoints = enforceConstantMassPoints, cacheFileName = cacheFileName) # Convert to our now regrettable standard coordinate storage for generators. self.x = [x.x + offset[0] for x in self.pos] self.y = [x.y + offset[1] for x in self.pos] self.z = [x.z + offset[2] for x in self.pos] del self.pos # If the user provided a "rejecter", give it a pass # at the nodes. if rejecter: self.x, self.y, self.z, self.m, self.H, self.vol, self.surface = rejecter(self.x, self.y, self.z, self.m, self.H, self.vol, self.surface) # Initialize the base class, taking into account the fact we've already broken # up the nodes between domains. NodeGeneratorBase.__init__(self, False, self.x, self.y, self.z, self.m, self.H, self.vol, self.surface) return
def __init__(self, surface, lconstant, lextrude, nextrude, dltarget, dstarget, rho, flags=None, nNodePerh=2.01, SPH=False): self.surface = surface surfaceFacets = surface.facets surfaceVertices = surface.vertices vertexNorms = surface.vertexUnitNorms facetNeighbors = surface.facetFacetConnectivity assert lconstant <= lextrude # Figure out the extent and resolution of the ratioed region. nconstant = int(lconstant / dltarget + 0.5) lratioed = lextrude - lconstant nratioed = nextrude - nconstant # Get the facets we need to extrude. if flags is None: facets = surfaceFacets realFacetIDs = range(len(facets)) flags = [1] * len(facets) else: assert len(flags) == len(surfaceFacets) realFacetIDs = [ fi for fi in xrange(len(surfaceFacets)) if (flags[fi] == 1) ] facets = [surfaceFacets[i] for i in realFacetIDs] # Find the maximum extent we need to use to cover the volumes of all extruded # facets. ymin, ymax, zmin, zmax = 1e200, -1e200, 1e200, -1e200 for f in facets: nhat = f.normal T = rotationMatrix(nhat) p = f.position verts = [T * (surfaceVertices[i] - p) for i in f.ipoints] ymin = min(ymin, min([v.y for v in verts])) ymax = max(ymax, max([v.y for v in verts])) zmin = min(zmin, min([v.z for v in verts])) zmax = max(zmax, max([v.z for v in verts])) # Find the ratio needed for the spacing in the x direction. # We have to check for ratio=1 explicitly, since the series sum # doesn't work in that case. if abs(lratioed - nratioed * dltarget) < 1e-5 * lratioed: ratio = 1.0 l = lratioed dx = dltarget else: stuff = [0.0] * (nratioed + 1) stuff[0:1] = [dltarget - lratioed, -lratioed] stuff[-1] = dltarget p = P(stuff, [1.0e-3, 1.0e10], [1.0e-3, 1.0e10]) complex_ratio = p.roots()[-1] assert complex_ratio.imag == 0.0 ratio = complex_ratio.real # Unfortunately the root finding above isn't 100% accurate, so we # adjust the initial step size to get the correct total length. l = dltarget * (1.0 - ratio**nratioed) / (1.0 - ratio) dx = dltarget # * lratioed/l if mpi.rank == 0: print "FacetedSurfaceGenerator: selected ratio=%g, dxfirst=%g, l=%g." % ( ratio, dx, l) # Build the template values we'll use to stamp into each facet volume. rt, mt, Ht = [], [], [] dxi = dx xi = 0.5 * dx ix = -1 while xi > -lextrude: ix += 1 if ix < nconstant: dxi = dx # lconstant/nconstant else: dxi = dx * ratio**(ix - nconstant) xi -= dxi ds = min(2.0 * dstarget, max(dstarget, dxi)) ny = max(1, int((ymax - ymin) / ds + 0.5)) nz = max(1, int((zmax - zmin) / ds + 0.5)) dy = (ymax - ymin) / ny dz = (zmax - zmin) / nz for iy in xrange(ny): yi = ymin + (iy + 0.5) * dy for iz in xrange(nz): zi = zmin + (iz + 0.5) * dz rt.append(Vector(xi, yi, zi)) mt.append(rho * dxi * dy * dz) Ht.append( SymTensor(1.0 / (nNodePerh * dxi), 0.0, 0.0, 0.0, 1.0 / (nNodePerh * dy), 0.0, 0.0, 0.0, 1.0 / (nNodePerh * dz))) if mpi.rank == 0: print "FacetedSurfaceGenerator: built template block of %i points per facet." % len( rt) # Figure out a crude partitioning of the facets between processors. if len(facets) > mpi.procs: ndomain0 = len(facets) / mpi.procs remainder = len(facets) % mpi.procs assert remainder < mpi.procs ndomain = ndomain0 if mpi.rank < remainder: ndomain += 1 imin = mpi.rank * ndomain0 + min(mpi.rank, remainder) imax = imin + ndomain else: if mpi.rank < len(facets): imin = mpi.rank imax = imin + 1 else: imin = 0 imax = 0 # We need all the extruded facet polyhedra. In general these may be intersecting! print "FacetedSurfaceGenerator: building extruded facets..." self.extrudedFacets, localExtrudedFacets = [], [] for i in xrange(imin, imax): f = facets[i] p = f.position verts = vector_of_Vector() for ip in f.ipoints: fphat = (p - surfaceVertices[ip]).unitVector() vi = surfaceVertices[ip] + fphat * 0.05 * dstarget verts.append(vi) verts.append(vi - vertexNorms[ip] * lextrude) localExtrudedFacets.append(Polyhedron(verts)) # Better be convex! for i in xrange(mpi.procs): self.extrudedFacets.extend(mpi.bcast(localExtrudedFacets, i)) assert len(self.extrudedFacets) == len(facets) # Now walk the facets and build our values. print "FacetedSurfaceGenerator: seeding points..." self.x, self.y, self.z, self.m, self.H, self.nodes2facets = [], [], [], [], [], [] for i in xrange(imin, imax): f = facets[i] fi = realFacetIDs[i] neighbors = facetNeighbors[fi] p = f.position nhat = f.normal T = rotationMatrix(nhat) Ti = T.Transpose() for j in xrange(len(rt)): rj = Ti * rt[j] + p if self.extrudedFacets[i].contains( rj): # and surface.contains(rj): stuff = [(surfaceFacets[k].distance(rj), k) for k in neighbors if flags[k] == 1] stuff.sort() if stuff[0][1] == fi: self.x.append(rj.x) self.y.append(rj.y) self.z.append(rj.z) self.m.append(mt[j]) self.H.append(SymTensor(Ht[j])) self.H[-1].rotationalTransform(Ti) self.nodes2facets.append(fi) self.rho = [rho] * len(self.x) # Invoke the base class to finish up. NodeGeneratorBase.__init__(self, False, self.x, self.y, self.z, self.m, self.H, self.rho, self.nodes2facets) return