def createMesh(self, ctrs, fd, frame, plot=False): self.frame = frame pfix = None # Extract bounding box xmin, ymin, xmax, ymax = self.bbox if pfix is not None: pfix = np.array(pfix, dtype='d') #1. Set up initial points x, y = np.mgrid[xmin:(xmax + self.h0):self.h0, ymin:(ymax + self.h0 * np.sqrt(3) / 2):self.h0 * np.sqrt(3) / 2] x[:, 1::2] += self.h0 / 2 # Shift even rows p = np.vstack((x.flat, y.flat)).T # List of node coordinates # 2. Remove points outside the region, apply the rejection method a = fd(p) p = p[np.where(a < self.geps)] # Keep only d<0 points r0 = 1 / self.fh(p)**2 # Probability to keep point p = p[np.random.random(p.shape[0]) < r0 / r0.max()] # Rejection method if pfix is not None: p = ml.setdiff_rows(p, pfix) # Remove duplicated nodes pfix = ml.unique_rows(pfix) nfix = pfix.shape[0] p = np.vstack((pfix, p)) # Prepend fix points else: nfix = 0 N = p.shape[0] # Number of points N self.N = N count = 0 pold = float('inf') # For first iteration ################################################################################ #Mesh creation ################################################################################ while count < self.maxiter: print 'DistMesh create count: %d/%d' % (count, self.maxiter) count += 1 # 3. Retriangulation by the Delaunay algorithm dist = lambda p1, p2: np.sqrt(((p1 - p2)**2).sum(1)) if (dist(p, pold) / self.h0).max() > self.ttol: # Any large movement? pold = p.copy() # Save current positions self.delaunay = spspatial.Delaunay(p) t = self.delaunay.vertices # List of triangles pmid = p[t].sum(1) / 3 # Compute centroids t = t[fd(pmid) < -self.geps] # Keep interior triangles # 4. Describe each bar by a unique pair of nodes bars = np.vstack((t[:, [0, 1]], t[:, [1, 2]], t[:, [2, 0]])) # Interior bars duplicated bars.sort(axis=1) bars = ml.unique_rows(bars) # Bars as node pairs #Plot fc = frame.copy() if frame is not None: drawGrid(fc, p, bars) if plot: cv2.imshow('Initial mesh', fc) k = cv2.waitKey(30) & 0xff if k == 27: break # 6. Move mesh points based on bar lengths L and forces F barvec = p[bars[:, 0]] - p[bars[:, 1]] # List of bar vectors L = np.sqrt((barvec**2).sum(1)) # L = Bar lengths hbars = self.fh(p[bars].sum(1) / 2) L0 = 1.5 * self.h0 * np.ones_like(L) #(hbars*Fscale #*np.sqrt((L**2).sum()/(hbars**2).sum())) # L0 = Desired lengths F = self.k * (L0 - L) F[F < 0] = 0 #F[F<0]*.5#0 # Bar forces (scalars) Fvec = F[:, None] / L[:, None].dot( [[1, 1]]) * barvec # Bar forces (x,y components) Ftot = ml.dense(bars[:, [0, 0, 1, 1]], np.repeat([[0, 1, 0, 1]], len(F), axis=0), np.hstack((Fvec, -Fvec)), shape=(N, 2)) Ftot[:nfix] = 0 # Force = 0 at fixed points p += self.deltat * Ftot # Update node positions # 7. Bring outside points back to the boundary d = fd(p) ix = d > 0 # Find points outside (d>0) ddeps = 1e-1 for idx in range(10): if ix.any(): dgradx = (fd(p[ix] + [ddeps, 0]) - d[ix]) / ddeps # Numerical dgrady = (fd(p[ix] + [0, ddeps]) - d[ix]) / ddeps # gradient dgrad2 = dgradx**2 + dgrady**2 p[ix] -= (d[ix] * np.vstack( (dgradx, dgrady)) / dgrad2).T # Project # 8. Termination criterion: All interior nodes move less than dptol (scaled) if (np.sqrt((self.deltat * Ftot[d < -self.geps]**2).sum(1)) / self.h0).max() < self.dptol: break self.p = p self.t = t self.bars = bars self.L = L
def createMesh(self, ctrs, fd, frame, plot = False): self.frame = frame pfix = None # Extract bounding box xmin, ymin, xmax, ymax = self.bbox if pfix is not None: pfix = np.array(pfix, dtype='d') #1. Set up initial points x, y = np.mgrid[xmin:(xmax+self.h0):self.h0, ymin:(ymax+self.h0*np.sqrt(3)/2):self.h0*np.sqrt(3)/2] x[:, 1::2] += self.h0/2 # Shift even rows p = np.vstack((x.flat, y.flat)).T # List of node coordinates # 2. Remove points outside the region, apply the rejection method a = fd(p) p = p[np.where(a<self.geps)] # Keep only d<0 points r0 = 1/self.fh(p)**2 # Probability to keep point p = p[np.random.random(p.shape[0])<r0/r0.max()] # Rejection method if pfix is not None: p = ml.setdiff_rows(p, pfix) # Remove duplicated nodes pfix = ml.unique_rows(pfix); nfix = pfix.shape[0] p = np.vstack((pfix, p)) # Prepend fix points else: nfix = 0 N = p.shape[0] # Number of points N self.N = N count = 0 pold = float('inf') # For first iteration ################################################################################ #Mesh creation ################################################################################ while count < self.maxiter: #print count count += 1 # 3. Retriangulation by the Delaunay algorithm dist = lambda p1, p2: np.sqrt(((p1-p2)**2).sum(1)) if (dist(p, pold)/self.h0).max() > self.ttol: # Any large movement? pold = p.copy() # Save current positions self.delaunay = spspatial.Delaunay(p) t = self.delaunay.vertices # List of triangles pmid = p[t].sum(1)/3 # Compute centroids t = t[fd(pmid) < -self.geps] # Keep interior triangles # 4. Describe each bar by a unique pair of nodes bars = np.vstack((t[:, [0,1]], t[:, [1,2]], t[:, [2,0]])) # Interior bars duplicated bars.sort(axis=1) bars = ml.unique_rows(bars) # Bars as node pairs #Plot fc = frame.copy() if frame is not None: drawGrid(fc, p, bars) if plot: cv2.imshow('Initial mesh',fc) k = cv2.waitKey(30) & 0xff if k == 27: break # 6. Move mesh points based on bar lengths L and forces F barvec = p[bars[:,0]] - p[bars[:,1]] # List of bar vectors L = np.sqrt((barvec**2).sum(1)) # L = Bar lengths hbars = self.fh(p[bars].sum(1)/2) L0 = 1.5*self.h0*np.ones_like(L); #(hbars*Fscale #*np.sqrt((L**2).sum()/(hbars**2).sum())) # L0 = Desired lengths F = self.k*(L0-L) F[F<0] = 0#F[F<0]*.5#0 # Bar forces (scalars) Fvec = F[:,None]/L[:,None].dot([[1,1]])*barvec # Bar forces (x,y components) Ftot = ml.dense(bars[:,[0,0,1,1]], np.repeat([[0,1,0,1]], len(F), axis=0), np.hstack((Fvec, -Fvec)), shape=(N, 2)) Ftot[:nfix] = 0 # Force = 0 at fixed points p += self.deltat*Ftot # Update node positions # 7. Bring outside points back to the boundary d = fd(p); ix = d>0 # Find points outside (d>0) ddeps = 1e-1 for idx in range(10): if ix.any(): dgradx = (fd(p[ix]+[ddeps,0])-d[ix])/ddeps # Numerical dgrady = (fd(p[ix]+[0,ddeps])-d[ix])/ddeps # gradient dgrad2 = dgradx**2 + dgrady**2 p[ix] -= (d[ix]*np.vstack((dgradx, dgrady))/dgrad2).T # Project # 8. Termination criterion: All interior nodes move less than dptol (scaled) if (np.sqrt((self.deltat*Ftot[d<-self.geps]**2).sum(1))/self.h0).max() < self.dptol: break self.p = p self.t = t self.bars = bars self.L = L
def plot(self): fc = self.frame.copy() if self.bars is not None: drawGrid(fc, self.p, self.bars) cv2.imshow('Current mesh', fc) k = cv2.waitKey(30) & 0xff
def plot(self): fc = self.frame.copy() if self.bars is not None: drawGrid(fc, self.p, self.bars) cv2.imshow('Current mesh',fc) k = cv2.waitKey(30) & 0xff