Source code for sfepy.mesh.splinebox

import numpy as nm
from sfepy.base.base import Struct

[docs]class SplineBox(Struct): """ B-spline geometry parametrization. Geometry can be modified by moving spline control points. """ @staticmethod
[docs] def mmax(x, y): n = len(x) aux = nm.zeros((2,n), dtype=nm.int) aux[0,:] = x[:] aux[1,:] = nm.ones((1,n)) * y out = nm.max(aux, axis=0) return out
@staticmethod
[docs] def spsorted(meshsites, sites): n1 = len(meshsites) n2 = len(sites) aux = nm.zeros((n1 + n2,), dtype=nm.double) aux[:n1] = meshsites aux[n1:] = sites inx = nm.argsort(aux) out = nm.where(inx >= len(meshsites)) - nm.arange(len(sites)) return out[0]
@staticmethod
[docs] def augknt(knots, k, mults=1): if mults > 1: aux = [] for j in k[1:-1]: aux += [j] * mults; else: aux = knots[1:-1] augknot = [knots[0]] * k + list(aux) + [knots[-1]] * k return augknot
@staticmethod
[docs] def spcol(knots, k, tau): npk = len(knots) n = npk - k nrows = tau.shape[0] pts = tau km1 = k - 1 savl = SplineBox.mmax(SplineBox.spsorted(knots[:n], pts), k) b = nm.zeros((nrows, k), dtype=nm.double) b[:,0] = nm.ones((nrows,), dtype=nm.double) for j in range(km1): saved = nm.zeros((nrows,), dtype=nm.double); for r in range(j+1): tr = knots[savl + r] - pts tl = pts - knots[savl + r - j - 1] term = nm.double(b[:,r]) / (tr + tl) b[:,r] = saved + tr * term saved = tl * term b[:,j+1] = saved idx = nm.where((tau < knots[0]) | (tau > knots[npk-1]))[0] if len(idx) > 0: b[idx,:] = 0 idx1 = nm.tile(nm.arange(1-nrows, 1), (k,)) idx2 = nm.tile(nrows * savl, (k,)) idx3 = nm.tile(nrows * nm.arange(-km1, 1), (nrows, 1)) idx3 = nm.reshape(idx3, (nrows * k,), order='F') width = n + km1 + km1 nn = nrows * width cc = nm.zeros((nn,), dtype=nm.double) idx = idx1 + idx2 + idx3 - 1 cc[idx] = b.reshape((len(idx),), order='F') idx1 = nm.tile(nm.arange(1-nrows, 1), (n,)) idx2 = nm.tile(nrows * nm.arange(1, n + 1), (nrows, 1)) idx2 = nm.reshape(idx2, (nrows * n,), order='F') idx = idx1 + idx2 - 1 colloc = cc[idx].reshape((nrows, n), order='F') return colloc
@staticmethod
[docs] def create_spb(bbox, coors, nsg=None): if type(bbox) is not nm.ndarray: bbox = nm.array(bbox) if type(coors) is not nm.ndarray: coors = nm.array(coors) dim = coors.shape[1] axes = [] if nsg is None: nsg = nm.ones((dim,), dtype=nm.int) else: nsg = nm.array(nsg) cpt = [] ncpt = [] for idim in range(dim): axes.append({}) aux = nm.linspace(bbox[idim,0], bbox[idim,1], nsg[idim] + 1) knots = nm.array(SplineBox.augknt(aux, 4)) axes[idim]['knots'] = knots nn = 4 + nsg[idim] - 1 ncpt.append(nn) cpt.append(nm.zeros((nn,), dtype=nm.double)) for j in range(nn): cpt[idim][j] = nm.sum(knots[(j+1):(j+4)]) / 3.0 inx = nm.argsort(coors[:,idim]) aux = SplineBox.spcol(knots, 4, coors[inx,idim]) axes[idim]['bsc'] = nm.zeros_like(aux) axes[idim]['bsc'][inx,:] = aux[:,:] ncpts = nm.prod(ncpt) cpoints = nm.zeros((ncpts, dim), dtype=nm.double) cpoints_idx = nm.zeros(ncpt, dtype=nm.int) n2 = nm.prod(ncpt[:2]) aux = nm.arange(n2).reshape(ncpt[:2], order='F') if dim == 2: idx = nm.mgrid[0:ncpt[1],0:ncpt[0]] cpoints[:,0] = cpt[0][idx[1].reshape((ncpts,))] cpoints[:,1] = cpt[1][idx[0].reshape((ncpts,))] cpoints_idx[:,:] = aux elif dim == 3: idx = nm.mgrid[0:ncpt[2],0:ncpt[1],0:ncpt[0]] cpoints[:,0] = cpt[0][idx[2].reshape((ncpts,))] cpoints[:,1] = cpt[1][idx[1].reshape((ncpts,))] cpoints[:,2] = cpt[2][idx[0].reshape((ncpts,))] for j in range(ncpt[2]): cpoints_idx[:,:,j] = aux + j * n2 return axes, cpoints, cpoints_idx
def __init__(self, bbox, coors, name='spbox', **kwargs): """ Create a SplineBox. Parameters ---------- bbox : array Mesh bounding box. coors : array Coordinates of mesh nodes. name : str Object name. """ Struct.__init__(self, name=name, **kwargs) self.axes, self.control_points, self.control_points_idx\ = self.create_spb(bbox, coors) self.dim = self.control_points.shape[1] self.control_points0 = self.control_points.copy()
[docs] def get_control_points(self, init=False): """ Get spline control points coordinates. Return ------ cpt_coors : array The coordinates of the spline control points. init : bool If True, return initial state. """ if init: return self.control_points0 else: return self.control_points
[docs] def set_control_points(self, cpt_coors, add=False): """ Set spline control points position. Parameters ---------- cpt_coors : array The coordinates of the spline control points. add : bool If True, coors += cpt_coors """ if add: self.control_points += cpt_coors else: self.control_points = cpt_coors.copy()
[docs] def change_shape(self, cpoint, val): """ Change shape of spline parametrization. Parameters ---------- cpoint : list The indices of the spline control point. val : array Displacement. """ idx = self.control_points_idx[cpoint] self.control_points[idx] += val
[docs] def evaluate(self, cp_coors=None): """ Evaluate SplineBox. Returns ------- coors : array The coordinates corresponding to the actual spline control points position. cp_coors : array If is not None, use as control points cooardinates. """ coors = nm.zeros((self.axes[0]['bsc'].shape[0], self.dim), dtype=nm.double) if cp_coors is None: cp_coors = self.control_points cptidx = self.control_points_idx nn = self.control_points_idx.shape if self.dim == 2: for i in range(nn[0]): for j in range(nn[1]): aux = self.axes[0]['bsc'][:,i] * self.axes[1]['bsc'][:,j] inx = cptidx[i,j] coors += nm.dot(aux[:,nm.newaxis], cp_coors[inx,:][nm.newaxis,:]) elif self.dim == 3: for i in range(nn[0]): for j in range(nn[1]): aux = self.axes[0]['bsc'][:,i] * self.axes[1]['bsc'][:,j] for k in range(nn[2]): inx = cptidx[i,j,k] aux2 = aux * self.axes[2]['bsc'][:,k] coors += nm.dot(aux2[:,nm.newaxis], cp_coors[inx,:][nm.newaxis,:]) return coors
[docs] def dvelocity(self, cpoint, dir): """ Evaluate derivative of spline in a given control point and direction. Parameters ---------- cpoint : list The indices of the spline control point. dir : array The directional vector. Returns ------- dvel : array The design velocity field. """ if type(dir) is not nm.ndarray: dir = nm.array(dir) dvel = nm.zeros((self.axes[0]['bsc'].shape[0], self.dim), dtype=nm.double) ax = self.axes if self.dim == 2: aux = ax[0]['bsc'][:,cpoint[0]] * ax[1]['bsc'][:,cpoint[1]] dvel = nm.dot(aux[:,nm.newaxis], dir[nm.newaxis,:]) elif self.dim == 3: aux = ax[0]['bsc'][:,cpoint[0]] * ax[1]['bsc'][:,cpoint[1]]\ * ax[2]['bsc'][:,cpoint[2]] dvel = nm.dot(aux[:,nm.newaxis], dir[nm.newaxis,:]) return dvel
[docs] def write_vtk(self, filename): cptidx = self.control_points_idx ncpt = cptidx.shape nnd = nm.prod(ncpt) f = open(filename, 'w') f.write("# vtk DataFile Version 2.6\nspbox file\n" "ASCII\nDATASET UNSTRUCTURED_GRID\n\n") f.write("POINTS %d float\n" % nnd) if self.dim == 2: nel = (ncpt[0] - 1) * ncpt[1] + (ncpt[1] - 1) * ncpt[0] for cpt in self.control_points: f.write("%e %e 0.0\n" % (cpt[0], cpt[1])) f.write("\nCELLS %d %d\n" % (nel, 3 * nel)) for i in range(ncpt[0]): for j in range(ncpt[1] - 1): inx1 = cptidx[i,j] inx2 = cptidx[i,j + 1] f.write("2 %d %d\n" % (inx1, inx2)) for i in range(ncpt[0] - 1): for j in range(ncpt[1]): inx1 = cptidx[i,j] inx2 = cptidx[i + 1,j] f.write("2 %d %d\n" % (inx1, inx2)) elif self.dim == 3: nel = ((ncpt[0] - 1) * ncpt[1] + (ncpt[1] - 1) * ncpt[0]) * ncpt[2] nel += ncpt[0] * ncpt[1] * (ncpt[2] - 1) for cpt in self.control_points: f.write("%e %e %e\n" % (cpt[0], cpt[1], cpt[2])) f.write("\nCELLS %d %d\n" % (nel, 3 * nel)) for k in range(ncpt[2]): for i in range(ncpt[0]): for j in range(ncpt[1] - 1): inx1 = cptidx[i, j, k] inx2 = cptidx[i, j + 1, k] f.write("2 %d %d\n" % (inx1, inx2)) for i in range(ncpt[0] - 1): for j in range(ncpt[1]): inx1 = cptidx[i, j, k] inx2 = cptidx[i + 1, j, k] f.write("2 %d %d\n" % (inx1, inx2)) for k in range(ncpt[2] - 1): for i in range(ncpt[0]): for j in range(ncpt[1]): inx1 = cptidx[i, j, k] inx2 = cptidx[i, j, k + 1] f.write("2 %d %d\n" % (inx1, inx2)) f.write("\nCELL_TYPES %d\n" % nel ) f.write("3\n" * nel) f.close()