def test_interpolation(self): from sfepy import data_dir from sfepy.discrete.fem import Mesh from sfepy.linalg import make_axis_rotation_matrix fname = in_dir(self.options.out_dir) meshes = { 'tp' : Mesh.from_file(data_dir + '/meshes/3d/block.mesh'), 'si' : Mesh.from_file(data_dir + '/meshes/3d/cylinder.mesh'), } datas = gen_datas(meshes) for field_name in ['scalar_si', 'vector_si', 'scalar_tp', 'vector_tp']: m1 = meshes[field_name[-2:]] for ia, angle in enumerate(nm.linspace(0.0, nm.pi, 11)): self.report('%s: %d. angle: %f' % (field_name, ia, angle)) shift = [0.0, 0.0, 0.0] mtx = make_axis_rotation_matrix([0, 1, 0], angle) m2 = m1.copy('rotated mesh') m2.transform_coors(mtx) data = datas[field_name] u1, u2 = do_interpolation(m2, m1, data, field_name) if ia == 0: u1.save_as_mesh(fname('test_mesh_interp_%s_u1.vtk' % field_name)) u2.save_as_mesh(fname('test_mesh_interp_%s_u2.%03d.vtk' % (field_name, ia))) return True
def prepare_cylindrical_transform(coors, origin, mode='axes'): """ Prepare matrices for transforming tensors into cylindrical coordinates with the axis 'z' in a given origin. Parameters ---------- coors : array The Cartesian coordinates. origin : array of length 3 The origin. mode : 'axes' or 'data' In 'axes' (default) mode the matrix transforms data to different coordinate system, while in 'data' mode the matrix transforms the data in the same coordinate system and is transpose of the matrix in the 'axes' mode. Returns ------- mtx : array The array of transformation matrices for each coordinate in `coors`. """ assert_(mode in ['axes', 'data']) x, y = coors[:,0] - origin[0], coors[:,1] - origin[1] theta = nm.arctan2(y, x) if mode == 'data': theta = -theta mtx = nm.zeros((coors.shape[0], 3, 3), dtype=nm.float64) for ii, th in enumerate(theta): mtx[ii] = make_axis_rotation_matrix([0.0, 0.0, 1.0], th) return mtx
def __init__(self, anchor, normal, bounds): Struct.__init__(self, anchor=nm.array(anchor, dtype=nm.float64), bounds=nm.asarray(bounds, dtype=nm.float64)) self.normal = nm.asarray(normal, dtype=nm.float64) norm = nm.linalg.norm self.normal /= norm(self.normal) e3 = [0.0, 0.0, 1.0] dd = nm.dot(e3, self.normal) rot_angle = nm.arccos(dd) if nm.abs(rot_angle) < 1e-14: mtx = nm.eye(3, dtype=nm.float64) bounds2d = self.bounds[:, :2] else: rot_axis = nm.cross([0.0, 0.0, 1.0], self.normal) mtx = la.make_axis_rotation_matrix(rot_axis, rot_angle) mm = la.insert_strided_axis(mtx, 0, self.bounds.shape[0]) rbounds = la.dot_sequences(mm, self.bounds) bounds2d = rbounds[:, :2] assert_(nm.allclose(nm.dot(mtx, self.normal), e3, rtol=0.0, atol=1e-12)) self.adotn = nm.dot(self.anchor, self.normal) self.rot_angle = rot_angle self.mtx = mtx self.bounds2d = bounds2d
def prepare_cylindrical_transform(coors, origin, mode='axes'): """ Prepare matrices for transforming tensors into cylindrical coordinates with the axis 'z' in a given origin. Parameters ---------- coors : array The Cartesian coordinates. origin : array of length 3 The origin. mode : 'axes' or 'data' In 'axes' (default) mode the matrix transforms data to different coordinate system, while in 'data' mode the matrix transforms the data in the same coordinate system and is transpose of the matrix in the 'axes' mode. Returns ------- mtx : array The array of transformation matrices for each coordinate in `coors`. """ assert_(mode in ['axes', 'data']) x, y = coors[:, 0] - origin[0], coors[:, 1] - origin[1] theta = nm.arctan2(y, x) if mode == 'data': theta = -theta mtx = nm.zeros((coors.shape[0], 3, 3), dtype=nm.float64) for ii, th in enumerate(theta): mtx[ii] = make_axis_rotation_matrix([0.0, 0.0, 1.0], th) return mtx
def prepare_cylindrical_transform(coors, origin): """ Prepare matrices for transforming tensors into cylindrical coordinates with the axis 'z' in a given origin. Parameters ---------- coors : array The Cartesian coordinates. origin : array of length 3 The origin. Returns ------- mtx : array The array of transformation matrices for each coordinate in `coors`. """ x, y = coors[:,0] - origin[0], coors[:,1] - origin[1] theta = nm.arctan2(y, x) mtx = nm.zeros((coors.shape[0], 3, 3), dtype=nm.float64) for ii, th in enumerate(theta): mtx[ii] = make_axis_rotation_matrix([0.0, 0.0, 1.0], th) return mtx
def get_points(self, refine_flag=None): """ Get the probe points. Returns ------- pars : array_like The independent coordinate of the probe. points : array_like The probe points, parametrized by pars. """ # Vector of angles. if self.is_refined: return self.pars, self.points if refine_flag is None: pars = nm.linspace(0.0, 2.0 * nm.pi, self.n_point + 1)[:-1] else: pars = Probe.refine_pars(self.pars, refine_flag, cyclic_val=2.0 * nm.pi) self.n_point = pars.shape[0] self.pars = pars # Create the points in xy plane, centered at the origin. x = self.radius * nm.cos(pars[:, None]) y = self.radius * nm.sin(pars[:, None]) if len(self.centre) == 3: z = nm.zeros((self.n_point, 1), dtype=nm.float64) points = nm.c_[x, y, z] # Rotate to satisfy the normal, shift to the centre. n1 = nm.array([0.0, 0.0, 1.0], dtype=nm.float64) axis = nm.cross(n1, self.normal) angle = nm.arccos(nm.dot(n1, self.normal)) if nla.norm(axis) < 0.1: # n1 == self.normal rot_mtx = nm.eye(3, dtype=nm.float64) else: rot_mtx = make_axis_rotation_matrix(axis, angle) points = nm.dot(points, rot_mtx) else: points = nm.c_[x, y] points += self.centre self.points = points return pars, points
def get_points(self, refine_flag=None): """ Get the probe points. Returns ------- pars : array_like The independent coordinate of the probe. points : array_like The probe points, parametrized by pars. """ # Vector of angles. if self.is_refined: return self.pars, self.points if refine_flag is None: pars = nm.linspace(0.0, 2.0*nm.pi, self.n_point + 1)[:-1] else: pars = Probe.refine_pars(self.pars, refine_flag, cyclic_val=2.0 * nm.pi) self.n_point = pars.shape[0] self.pars = pars # Create the points in xy plane, centered at the origin. x = self.radius * nm.cos(pars[:,None]) y = self.radius * nm.sin(pars[:,None]) if self.mesh.dim == 3: z = nm.zeros((self.n_point, 1), dtype=nm.float64) points = nm.c_[x, y, z] # Rotate to satisfy the normal, shift to the centre. n1 = nm.array([0.0, 0.0, 1.0], dtype=nm.float64) axis = nm.cross(n1, self.normal) angle = nm.arccos(nm.dot(n1, self.normal)) if nla.norm(axis) < 0.1: # n1 == self.normal rot_mtx = nm.eye(3, dtype=nm.float64) else: rot_mtx = make_axis_rotation_matrix(axis, angle) points = nm.dot(points, rot_mtx) else: points = nm.c_[x, y] points += self.centre self.points = points return pars, points
def make_mesh(dims, shape, transform=None): """ Generate a 2D rectangle mesh in 3D space, and optionally apply a coordinate transform. """ _mesh = gen_block_mesh(dims, shape, [0, 0], name='shell10x', verbose=False) coors = nm.c_[_mesh.coors, nm.zeros(_mesh.n_nod, dtype=nm.float64)] coors = nm.ascontiguousarray(coors) conns = [_mesh.get_conn(_mesh.descs[0])] mesh = Mesh.from_data(_mesh.name, coors, _mesh.cmesh.vertex_groups, conns, [_mesh.cmesh.cell_groups], _mesh.descs) if transform == 'bend': bbox = mesh.get_bounding_box() x0, x1 = bbox[:, 0] angles = 0.5 * nm.pi * (coors[:, 0] - x0) / (x1 - x0) mtx = make_axis_rotation_matrix([0, -1, 0], angles[:, None, None]) coors = mesh.coors.copy() coors[:, 0] = 0 coors[:, 2] = (x1 - x0) mesh.coors[:] = transform_data(coors, mtx=mtx) mesh.coors[:, 0] -= 0.5 * (x1 - x0) elif transform == 'twist': bbox = mesh.get_bounding_box() x0, x1 = bbox[:, 0] angles = 0.5 * nm.pi * (coors[:, 0] - x0) / (x1 - x0) mtx = make_axis_rotation_matrix([-1, 0, 0], angles[:, None, None]) mesh.coors[:] = transform_data(mesh.coors, mtx=mtx) return mesh
def test_interpolation(self): from sfepy import data_dir from sfepy.fem import Mesh from sfepy.linalg import make_axis_rotation_matrix fname = in_dir(self.options.out_dir) meshes = { 'tp' : Mesh('original mesh', data_dir + '/meshes/3d/block.mesh'), 'si' : Mesh('original mesh', data_dir + '/meshes/3d/cylinder.mesh'), } datas = {} for key, mesh in meshes.iteritems(): bbox = mesh.get_bounding_box() nx = bbox[1,0] - bbox[0,0] centre = 0.5 * bbox.sum(axis=0) mesh.coors -= centre data = nm.sin(4.0 * nm.pi * mesh.coors[:,0:1] / nx) datas['scalar_' + key] = data data = nm.zeros_like(mesh.coors) data[:,0] = 0.05 * nx * nm.sin(4.0 * nm.pi * mesh.coors[:,0] / nx) data[:,2] = 0.05 * nx * nm.cos(4.0 * nm.pi * mesh.coors[:,0] / nx) datas['vector_' + key] = data for field_name in ['scalar_si', 'vector_si', 'scalar_tp', 'vector_tp']: m1 = meshes[field_name[-2:]] for ia, angle in enumerate(nm.linspace(0.0, nm.pi, 11)): self.report('%s: %d. angle: %f' % (field_name, ia, angle)) shift = [0.0, 0.0, 0.0] mtx = make_axis_rotation_matrix([0, 1, 0], angle) m2 = m1.copy('rotated mesh') m2.transform_coors(mtx) data = datas[field_name] u1, u2 = do_interpolation(m2, m1, data, field_name) if ia == 0: u1.save_as_mesh(fname('test_mesh_interp_%s_u1.vtk' % field_name)) u2.save_as_mesh(fname('test_mesh_interp_%s_u2.%03d.vtk' % (field_name, ia))) return True
def add_circle_probe(self, name, centre, normal, radius, n_point): """ Create the ray (line) probe - VTK object. Parameters ---------- name : str The probe name. centre : array The coordinates of the circle center point. normal : array The normal vector perpendicular to the circle plane. radius : float The radius of the circle. n_point : int The number of probe points. """ pars = nm.linspace(0.0, 2.0*nm.pi, n_point + 1)[:-1] # Create the points in xy plane, centered at the origin. x = radius * nm.cos(pars[:,None]) y = radius * nm.sin(pars[:,None]) if len(centre) == 3: z = nm.zeros((n_point, 1), dtype=nm.float64) points = nm.c_[x, y, z] # Rotate to satisfy the normal, shift to the centre. n1 = nm.array([0.0, 0.0, 1.0], dtype=nm.float64) axis = nm.cross(n1, normal) angle = nm.arccos(nm.dot(n1, normal)) if nm.linalg.norm(axis) < 0.1: # n1 == self.normal rot_mtx = nm.eye(3, dtype=nm.float64) else: rot_mtx = make_axis_rotation_matrix(axis, angle) points = nm.dot(points, rot_mtx) else: points = nm.c_[x, y] points += centre circle = self.new_vtk_polyline(points, closed=True) self.probes[name] = (circle, pars) self.probes_png[name] = False
def plot_faces(ax, gel, radius, n_point, show=False): """ Plot faces of a 3D geometry element as numbered oriented arcs. An arc centre corresponds to the first node of a face. It points from the first edge towards the last edge of the face. """ dim = gel.dim ax = _get_axes(ax, dim) if dim < 3: return ax for ii, face in enumerate(gel.faces): cc = gel.coors[face] t1 = cc[1, :] - cc[0, :] t2 = cc[-1, :] - cc[0, :] n = nm.cross(t1, t2) nt1 = nm.linalg.norm(t1) nt2 = nm.linalg.norm(t2) angle = nm.arccos(nm.dot(t1, t2) / (nt1 * nt2)) da = angle / (n_point - 1) mtx = make_axis_rotation_matrix(n, da) rt = cc[0] + radius * t1 / nt1 coors = [rt] for ip in range(n_point - 1): rt = nm.dot(mtx.T, (rt - cc[0])) + cc[0] coors.append(rt) coors = nm.array(coors, dtype=nm.float64) centre = coors.sum(axis=0) / coors.shape[0] draw_arrow(ax, coors, length=0.3*radius, linewidth=3, color='r') if dim == 3: cx, cy, cz = centre ax.text(cx, cy, cz, ii, color='r', fontsize=10, weight='light') else: cx, cy = centre ax.text(cx, cy, ii, color='r', fontsize=10, weight='light') return ax
def plot_faces(ax, gel, radius, n_point, show=False): """ Plot faces of a 3D geometry element as numbered oriented arcs. An arc centre corresponds to the first node of a face. It points from the first edge towards the last edge of the face. """ dim = gel.dim ax = _get_axes(ax, dim) if dim < 3: return ax for ii, face in enumerate(gel.faces): cc = gel.coors[face] t1 = cc[1, :] - cc[0, :] t2 = cc[-1, :] - cc[0, :] n = nm.cross(t1, t2) nt1 = nm.linalg.norm(t1) nt2 = nm.linalg.norm(t2) angle = nm.arccos(nm.dot(t1, t2) / (nt1 * nt2)) da = angle / (n_point - 1) mtx = make_axis_rotation_matrix(n, da) rt = cc[0] + radius * t1 / nt1 coors = [rt] for ip in range(n_point - 1): rt = nm.dot(mtx.T, (rt - cc[0])) + cc[0] coors.append(rt) coors = nm.array(coors, dtype=nm.float64) centre = coors.sum(axis=0) / coors.shape[0] draw_arrow(ax, coors, length=0.3 * radius, linewidth=3, color='r') if dim == 3: cx, cy, cz = centre ax.text(cx, cy, cz, ii, color='r', fontsize=10, weight='light') else: cx, cy = centre ax.text(cx, cy, ii, color='r', fontsize=10, weight='light') return ax