def sensitivity(self, dp_var_data, state_ap, select=None): """ Sensitivity of objective function evaluation for given direct and adjoint problem states. """ apb = self.apb var_data = state_ap.get_parts() var_data.update(dp_var_data) self.ofg_equations.set_data(var_data, ignore_unknown=True) dim = self.sp_boxes.dim n_mesh_nod = apb.domain.shape.n_nod if select is None: idsgs = nm.arange(self.dsg_vars.n_dsg, dtype=nm.int32) else: idsgs = select sa = [] pbar = MyBar('sensitivity:') pbar.init(len(idsgs)) shape = (n_mesh_nod, dim) for ii, nu in enumerate(self.generate_mesh_velocity(shape, idsgs)): pbar.update(ii) self.ofg_variables['Nu'].data_from_any(nu.ravel()) ## from sfepy.base.ioutils import write_vtk ## cc = nla.norm( vec_nu ) ## nun = nu / cc ## out = {'v' : Struct( mode = 'vertex', data = nun, ## ap_name = 'nic', dof_types = (0,1,2) )} ## fd = open( 'anim/pert_%03d.pvtk' % (ii+1), 'w' ) ## write_vtk( fd, domain.mesh, out ) ## fd.close() ## print ii val = eval_equations(self.ofg_equations, self.ofg_variables, term_mode=1, preserve_caches=True) sa.append(val) vec_sa = nm.array(sa, nm.float64) return vec_sa
def sensitivity(self, dp_var_data, state_ap, select=None): """ Sensitivity of objective function evaluation for given direct and adjoint problem states. """ apb = self.apb var_data = state_ap.get_parts() var_data.update(dp_var_data) self.ofg_equations.set_data(var_data, ignore_unknown=True) dim = self.sp_boxes.dim n_mesh_nod = apb.domain.shape.n_nod if select is None: idsgs = nm.arange( self.dsg_vars.n_dsg, dtype = nm.int32 ) else: idsgs = select sa = [] pbar = MyBar('sensitivity:') pbar.init(len(idsgs)) shape = (n_mesh_nod, dim) for ii, nu in enumerate(self.generate_mesh_velocity(shape, idsgs)): pbar.update(ii) self.ofg_variables['Nu'].set_data(nu.ravel()) ## from sfepy.base.ioutils import write_vtk ## cc = nla.norm( vec_nu ) ## nun = nu / cc ## out = {'v' : Struct( mode = 'vertex', data = nun, ## ap_name = 'nic', dof_types = (0,1,2) )} ## fd = open( 'anim/pert_%03d.pvtk' % (ii+1), 'w' ) ## write_vtk( fd, domain.mesh, out ) ## fd.close() ## print ii val = eval_equations(self.ofg_equations, self.ofg_variables, term_mode=1, preserve_caches=True) sa.append( val ) vec_sa = nm.array( sa, nm.float64 ) return vec_sa
def gen_cylinder_mesh(dims, shape, centre, axis='x', force_hollow=False, is_open=False, open_angle=0.0, non_uniform=False, name='cylinder', verbose=True): """ Generate a cylindrical mesh along an axis. Its cross-section can be ellipsoidal. Parameters ---------- dims : array of 5 floats Dimensions of the cylinder: inner surface semi-axes a1, b1, outer surface semi-axes a2, b2, length. shape : array of 3 ints Shape (counts of nodes in radial, circumferential and longitudinal directions) of the cylinder mesh. centre : array of 3 floats Centre of the cylinder. axis: one of 'x', 'y', 'z' The axis of the cylinder. force_hollow : boolean Force hollow mesh even if inner radii a1 = b1 = 0. is_open : boolean Generate an open cylinder segment. open_angle : float Opening angle in radians. non_uniform : boolean If True, space the mesh nodes in radial direction so that the element volumes are (approximately) the same, making thus the elements towards the outer surface thinner. name : string Mesh name. verbose : bool If True, show progress of the mesh generation. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) a1, b1, a2, b2, length = dims nr, nfi, nl = shape origin = centre - nm.array([0.5 * length, 0.0, 0.0]) dfi = 2.0 * (nm.pi - open_angle) / nfi if is_open: nnfi = nfi + 1 else: nnfi = nfi is_hollow = force_hollow or not (max(abs(a1), abs(b1)) < 1e-15) if is_hollow: mr = 0 else: mr = (nnfi - 1) * nl grid = nm.zeros((nr, nnfi, nl), dtype=nm.int32) n_nod = nr * nnfi * nl - mr coors = nm.zeros((n_nod, 3), dtype=nm.float64) angles = nm.linspace(open_angle, open_angle + (nfi) * dfi, nfi + 1) xs = nm.linspace(0.0, length, nl) if non_uniform: ras = nm.zeros((nr, ), dtype=nm.float64) rbs = nm.zeros_like(ras) advol = (a2**2 - a1**2) / (nr - 1) bdvol = (b2**2 - b1**2) / (nr - 1) ras[0], rbs[0] = a1, b1 for ii in range(1, nr): ras[ii] = nm.sqrt(advol + ras[ii - 1]**2) rbs[ii] = nm.sqrt(bdvol + rbs[ii - 1]**2) else: ras = nm.linspace(a1, a2, nr) rbs = nm.linspace(b1, b2, nr) # This is 3D only... bar = MyBar(" nodes:", verbose=verbose) bar.init(n_nod) ii = 0 for ix in range(nr): a, b = ras[ix], rbs[ix] for iy, fi in enumerate(angles[:nnfi]): for iz, x in enumerate(xs): grid[ix, iy, iz] = ii coors[ii] = origin + [x, a * nm.cos(fi), b * nm.sin(fi)] if not (ii % 100): bar.update(ii) ii += 1 if not is_hollow and (ix == 0): if iy > 0: grid[ix, iy, iz] = grid[ix, 0, iz] ii -= 1 assert_(ii == n_nod) n_el = (nr - 1) * nnfi * (nl - 1) conn = nm.zeros((n_el, 8), dtype=nm.int32) bar = MyBar(" elements:", verbose=verbose) bar.init(n_el) ii = 0 for (ix, iy, iz) in cycle([nr - 1, nnfi, nl - 1]): if iy < (nnfi - 1): conn[ii, :] = [ grid[ix, iy, iz], grid[ix + 1, iy, iz], grid[ix + 1, iy + 1, iz], grid[ix, iy + 1, iz], grid[ix, iy, iz + 1], grid[ix + 1, iy, iz + 1], grid[ix + 1, iy + 1, iz + 1], grid[ix, iy + 1, iz + 1] ] ii += 1 elif not is_open: conn[ii, :] = [ grid[ix, iy, iz], grid[ix + 1, iy, iz], grid[ix + 1, 0, iz], grid[ix, 0, iz], grid[ix, iy, iz + 1], grid[ix + 1, iy, iz + 1], grid[ix + 1, 0, iz + 1], grid[ix, 0, iz + 1] ] ii += 1 if not (ii % 100): bar.update(ii) mat_id = nm.zeros((n_el, ), dtype=nm.int32) desc = '3_8' assert_(n_nod == (conn.max() + 1)) if axis == 'z': coors = coors[:, [1, 2, 0]] elif axis == 'y': coors = coors[:, [2, 0, 1]] mesh = Mesh.from_data(name, coors, None, [conn], [mat_id], [desc]) return mesh
def gen_tiled_mesh(mesh, grid=None, scale=1.0, eps=1e-6, ret_ndmap=False): """ Generate a new mesh by repeating a given periodic element along each axis. Parameters ---------- mesh : Mesh instance The input periodic FE mesh. grid : array Number of repetition along each axis. scale : float, optional Scaling factor. eps : float, optional Tolerance for boundary detection. ret_ndmap : bool, optional If True, return global node map. Returns ------- mesh_out : Mesh instance FE mesh. ndmap : array Maps: actual node id --> node id in the reference cell. """ bbox = mesh.get_bounding_box() if grid is None: iscale = max(int(1.0 / scale), 1) grid = [iscale] * mesh.dim conns = mesh.conns[0] for ii in mesh.conns[1:]: conns = nm.vstack((conns, ii)) mat_ids = mesh.mat_ids[0] for ii in mesh.mat_ids[1:]: mat_ids = nm.hstack((mat_ids, ii)) coors = mesh.coors ngrps = mesh.ngroups nrep = nm.prod(grid) ndmap = None bar = MyBar(" repeating:") bar.init(nrep) nblk = 1 for ii, gr in enumerate(grid): if ret_ndmap: (conns, coors, ngrps, ndmap0) = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, mybar=(bar, nblk), ndmap=ndmap) ndmap = ndmap0 else: conns, coors, ngrps = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, mybar=(bar, nblk)) nblk *= gr bar.update(nblk) mat_ids = nm.tile(mat_ids, (nrep, )) mesh_out = Mesh.from_data('tiled mesh', coors * scale, ngrps, [conns], [mat_ids], [mesh.descs[0]]) if ret_ndmap: return mesh_out, ndmap else: return mesh_out
def gen_block_mesh(dims, shape, centre, mat_id=0, name='block', verbose=True): """ Generate a 2D or 3D block mesh. The dimension is determined by the lenght of the shape argument. Parameters ---------- dims : array of 2 or 3 floats Dimensions of the block. shape : array of 2 or 3 ints Shape (counts of nodes in x, y, z) of the block mesh. centre : array of 2 or 3 floats Centre of the block. mat_id : int, optional The material id of all elements. name : string Mesh name. verbose : bool If True, show progress of the mesh generation. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) dim = shape.shape[0] centre = centre[:dim] dims = dims[:dim] x0 = centre - 0.5 * dims dd = dims / (shape - 1) grid = nm.zeros(shape, dtype=nm.int32) n_nod = nm.prod(shape) coors = nm.zeros((n_nod, dim), dtype=nm.float64) bar = MyBar(" nodes:", verbose=verbose) bar.init(n_nod) for ii, ic in enumerate(cycle(shape)): grid[tuple(ic)] = ii coors[ii] = x0 + ic * dd if not (ii % 100): bar.update(ii) bar.update(ii + 1) n_el = nm.prod(shape - 1) mat_ids = nm.empty((n_el, ), dtype=nm.int32) mat_ids.fill(mat_id) if (dim == 2): conn = nm.zeros((n_el, 4), dtype=nm.int32) bar = MyBar(" elements:", verbose=verbose) bar.init(n_el) for ii, (ix, iy) in enumerate(cycle(shape - 1)): conn[ii, :] = [ grid[ix, iy], grid[ix + 1, iy], grid[ix + 1, iy + 1], grid[ix, iy + 1] ] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '2_4' else: conn = nm.zeros((n_el, 8), dtype=nm.int32) bar = MyBar(" elements:", verbose=verbose) bar.init(n_el) for ii, (ix, iy, iz) in enumerate(cycle(shape - 1)): conn[ii, :] = [ grid[ix, iy, iz], grid[ix + 1, iy, iz], grid[ix + 1, iy + 1, iz], grid[ix, iy + 1, iz], grid[ix, iy, iz + 1], grid[ix + 1, iy, iz + 1], grid[ix + 1, iy + 1, iz + 1], grid[ix, iy + 1, iz + 1] ] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '3_8' mesh = Mesh.from_data(name, coors, None, [conn], [mat_ids], [desc]) return mesh
def gen_block_mesh(dims, shape, centre, name='block'): """ Generate a 2D or 3D block mesh. The dimension is determined by the lenght of the shape argument. Parameters ---------- dims : array of 2 or 3 floats Dimensions of the block. shape : array of 2 or 3 ints Shape (counts of nodes in x, y, z) of the block mesh. centre : array of 2 or 3 floats Centre of the block. name : string Mesh name. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) dim = shape.shape[0] centre = centre[:dim] dims = dims[:dim] x0 = centre - 0.5 * dims dd = dims / (shape - 1) grid = nm.zeros(shape, dtype = nm.int32) n_nod = nm.prod(shape) coors = nm.zeros((n_nod, dim), dtype = nm.float64) bar = MyBar(" nodes:") bar.init(n_nod) for ii, ic in enumerate(cycle(shape)): grid[tuple(ic)] = ii coors[ii] = x0 + ic * dd if not (ii % 100): bar.update(ii) bar.update(ii + 1) n_el = nm.prod(shape - 1) mat_id = nm.zeros((n_el,), dtype = nm.int32) if (dim == 2): conn = nm.zeros((n_el, 4), dtype = nm.int32) bar = MyBar(" elements:") bar.init(n_el) for ii, (ix, iy) in enumerate(cycle(shape - 1)): conn[ii,:] = [grid[ix ,iy], grid[ix+1,iy ], grid[ix+1,iy+1], grid[ix ,iy+1]] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '2_4' else: conn = nm.zeros((n_el, 8), dtype = nm.int32) bar = MyBar(" elements:") bar.init(n_el) for ii, (ix, iy, iz) in enumerate(cycle(shape - 1)): conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,iy+1,iz ], grid[ix ,iy+1,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,iy+1,iz+1], grid[ix ,iy+1,iz+1]] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '3_8' mesh = Mesh.from_data(name, coors, None, [conn], [mat_id], [desc]) return mesh
def gen_cylinder_mesh(dims, shape, centre, axis='x', force_hollow=False, is_open=False, open_angle=0.0, non_uniform=False, name='cylinder'): """ Generate a cylindrical mesh along an axis. Its cross-section can be ellipsoidal. Parameters ---------- axis: one of 'x', 'y', 'z' The axis of the cylinder. dims : array of 5 floats Dimensions of the cylinder: inner surface semi-axes a1, b1, outer surface semi-axes a2, b2, length. shape : array of 3 ints Shape (counts of nodes in radial, circumferential and longitudinal directions) of the cylinder mesh. centre : array of 3 floats Centre of the cylinder. force_hollow : boolean Force hollow mesh even if inner radii a1 = b1 = 0. is_open : boolean Generate an open cylinder segment. open_angle : float Opening angle in radians. non_uniform : boolean If True, space the mesh nodes in radial direction so that the element volumes are (approximately) the same, making thus the elements towards the outer surface thinner. name : string Mesh name. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) a1, b1, a2, b2, length = dims nr, nfi, nl = shape origin = centre - nm.array([0.5 * length, 0.0, 0.0]) dfi = 2.0 * (nm.pi - open_angle) / nfi if is_open: nnfi = nfi + 1 else: nnfi = nfi is_hollow = force_hollow or not (max(abs(a1), abs(b1)) < 1e-15) if is_hollow: mr = 0 else: mr = (nnfi - 1) * nl grid = nm.zeros((nr, nnfi, nl), dtype=nm.int32) n_nod = nr * nnfi * nl - mr coors = nm.zeros((n_nod, 3), dtype=nm.float64) angles = nm.linspace(open_angle, open_angle+(nfi)*dfi, nfi+1) xs = nm.linspace(0.0, length, nl) if non_uniform: ras = nm.zeros((nr,), dtype=nm.float64) rbs = nm.zeros_like(ras) advol = (a2**2 - a1**2) / (nr - 1) bdvol = (b2**2 - b1**2) / (nr - 1) ras[0], rbs[0] = a1, b1 for ii in range(1, nr): ras[ii] = nm.sqrt(advol + ras[ii-1]**2) rbs[ii] = nm.sqrt(bdvol + rbs[ii-1]**2) else: ras = nm.linspace(a1, a2, nr) rbs = nm.linspace(b1, b2, nr) # This is 3D only... bar = MyBar(" nodes:") bar.init(n_nod) ii = 0 for ix in range(nr): a, b = ras[ix], rbs[ix] for iy, fi in enumerate(angles[:nnfi]): for iz, x in enumerate(xs): grid[ix,iy,iz] = ii coors[ii] = origin + [x, a * nm.cos(fi), b * nm.sin(fi)] if not (ii % 100): bar.update(ii) ii += 1 if not is_hollow and (ix == 0): if iy > 0: grid[ix,iy,iz] = grid[ix,0,iz] ii -= 1 print assert_(ii == n_nod) n_el = (nr - 1) * nnfi * (nl - 1) conn = nm.zeros((n_el, 8), dtype=nm.int32) bar = MyBar(" elements:") bar.init(n_el) ii = 0 for (ix, iy, iz) in cycle([nr-1, nnfi, nl-1]): if iy < (nnfi - 1): conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,iy+1,iz ], grid[ix ,iy+1,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,iy+1,iz+1], grid[ix ,iy+1,iz+1]] ii += 1 elif not is_open: conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,0,iz ], grid[ix ,0,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,0,iz+1], grid[ix ,0,iz+1]] ii += 1 if not (ii % 100): bar.update(ii) print mat_id = nm.zeros((n_el,), dtype = nm.int32) desc = '3_8' assert_(n_nod == (conn.max() + 1)) if axis == 'z': coors = coors[:,[1,2,0]] elif axis == 'y': coors = coors[:,[2,0,1]] mesh = Mesh.from_data(name, coors, None, [conn], [mat_id], [desc]) return mesh
def gen_tiled_mesh(mesh, grid=None, scale=1.0, eps=1e-6, ret_ndmap=False): """ Generate a new mesh by repeating a given periodic element along each axis. Parameters ---------- mesh : Mesh instance The input periodic FE mesh. grid : array Number of repetition along each axis. scale : float, optional Scaling factor. eps : float, optional Tolerance for boundary detection. ret_ndmap : bool, optional If True, return global node map. Returns ------- mesh_out : Mesh instance FE mesh. ndmap : array Maps: actual node id --> node id in the reference cell. """ bbox = mesh.get_bounding_box() if grid is None: iscale = max(int(1.0 / scale), 1) grid = [iscale] * mesh.dim conns = mesh.conns[0] for ii in mesh.conns[1:]: conns = nm.vstack((conns, ii)) mat_ids = mesh.mat_ids[0] for ii in mesh.mat_ids[1:]: mat_ids = nm.hstack((mat_ids, ii)) coors = mesh.coors ngrps = mesh.ngroups nrep = nm.prod(grid) ndmap = None bar = MyBar(" repeating:") bar.init(nrep) nblk = 1 for ii, gr in enumerate(grid): if ret_ndmap: (conns, coors, ngrps, ndmap0) = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, mybar=(bar, nblk), ndmap=ndmap) ndmap = ndmap0 else: conns, coors, ngrps = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, mybar=(bar, nblk)) nblk *= gr bar.update(nblk) mat_ids = nm.tile(mat_ids, (nrep,)) mesh_out = Mesh.from_data('tiled mesh', coors * scale, ngrps, [conns], [mat_ids], [mesh.descs[0]]) if ret_ndmap: return mesh_out, ndmap else: return mesh_out
def main(): parser = OptionParser(usage=usage, version="%prog") parser.add_option( "-o", "", metavar="filename", action="store", dest="output_filename", default="out.vtk", help=help["filename"] ) parser.add_option( "-d", "--dims", metavar="dims", action="store", dest="dims", default="[1.0, 1.0, 1.0]", help=help["dims"] ) parser.add_option( "-s", "--shape", metavar="shape", action="store", dest="shape", default="[11, 11, 11]", help=help["shape"] ) parser.add_option( "-c", "--centre", metavar="centre", action="store", dest="centre", default="[0.0, 0.0, 0.0]", help=help["centre"], ) (options, args) = parser.parse_args() dims = eval("nm.array( %s, dtype = nm.float64 )" % options.dims) shape = eval("nm.array( %s, dtype = nm.int32 )" % options.shape) centre = eval("nm.array( %s, dtype = nm.float64 )" % options.centre) print dims print shape print centre dim = shape.shape[0] x0 = centre - 0.5 * dims dd = dims / (shape - 1) grid = nm.zeros(shape, dtype=nm.float64) n_nod = nm.prod(shape) coors = nm.zeros((n_nod, dim + 1), dtype=nm.float64) # This is 3D only... bar = MyBar(" nodes:") bar.init(n_nod) for ii, ic in enumerate(cycle(shape)): ix, iy, iz = ic grid[ix, iy, iz] = ii coors[ii, :-1] = x0 + ic * dd if not (ii % 100): bar.update(ii) print n_el = nm.prod(shape - 1) conn = nm.zeros((n_el, 8), dtype=nm.int32) bar = MyBar(" elements:") bar.init(n_el) for ii, (ix, iy, iz) in enumerate(cycle(shape - 1)): conn[ii, :] = [ grid[ix, iy, iz], grid[ix + 1, iy, iz], grid[ix + 1, iy + 1, iz], grid[ix, iy + 1, iz], grid[ix, iy, iz + 1], grid[ix + 1, iy, iz + 1], grid[ix + 1, iy + 1, iz + 1], grid[ix, iy + 1, iz + 1], ] if not (ii % 100): bar.update(ii) print mat_id = nm.zeros((n_el,), dtype=nm.int32) desc = "3_8" mesh = Mesh.from_data(options.output_filename, coors, [conn], [mat_id], [desc]) mesh.write(options.output_filename, io="auto")