def _fld_xform_common(fld, base, target, unit, crd_xform, dat_xform, raw=False): dcrd, _ = _get_axinds(fld, base) unit_xform = _make_transform_unit_func(fld.crds.get_unit(base), unit) if not unit: unit = fld.crds.get_unit(base) xforms = (unit_xform, crd_xform, dat_xform) if base == target and all(f is arr_noop for f in xforms): return fld else: clist = fld.get_clist() clist[dcrd][0] = target if fld.crds.is_uniform() and not raw: clist[dcrd][1][:2] = crd_xform(unit_xform(clist[dcrd][1][:2])) else: clist[dcrd][1] = crd_xform(unit_xform(clist[dcrd][1])) units = list(fld.crds.units) units[dcrd] = unit crds = wrap_crds(fld.crds.crdtype, clist, dtype=fld.crds.dtype, units=units) ctx = dict(crds=crds) return fld.wrap(dat_xform(fld.data), context=ctx)
def _parse(self): g = self._make_grid(self) with open(self.fname, 'r') as fin: ndim = int(fin.readline().strip().split()[1]) nfields = int(fin.readline().strip().split()[1]) clist = [] for _ in range(ndim): ax_name, ax_dtype = fin.readline().strip().split() crd_dat = np.fromstring(fin.readline().strip(), sep=' ', dtype=ax_dtype) clist.append([ax_name, crd_dat]) crds = coordinate.wrap_crds("nonuniform_cartesian", clist) g.set_crds(crds) for _ in range(nfields): fld_name, fld_dtype = fin.readline().strip().split() fld_dat = np.fromstring(fin.readline().strip(), sep=' ', dtype=fld_dtype) fld = self._make_field(g, "Scalar", fld_name, crds, fld_dat) g.add_field(fld) self.add(g) self.activate(0)
def get_trilinear_field(): xl, xh, nx = -1.0, 1.0, 41 yl, yh, ny = -1.5, 1.5, 41 zl, zh, nz = -2.0, 2.0, 41 x = np.linspace(xl, xh, nx) y = np.linspace(yl, yh, ny) z = np.linspace(zl, zh, nz) crds = coordinate.wrap_crds("nonuniform_cartesian", [('x', x), ('y', y), ('z', z)]) b = field.empty(crds, name="f", nr_comps=3, center="Cell", layout="interlaced") X, Y, Z = b.get_crds(shaped=True) x01, y01, z01 = 0.5, 0.5, 0.5 x02, y02, z02 = 0.5, 0.5, 0.5 x03, y03, z03 = 0.5, 0.5, 0.5 b['x'][:] = 0.0 + 1.0 * (X - x01) + 1.0 * (Y - y01) + 1.0 * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) + 1.0 * (Y - y01) * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) * (Z - z01) b['y'][:] = 0.0 + 1.0 * (X - x02) - 1.0 * (Y - y02) + 1.0 * (Z - z02) + \ 1.0 * (X - x02) * (Y - y02) + 1.0 * (Y - y02) * (Z - z02) - \ 1.0 * (X - x02) * (Y - y02) * (Z - z02) b['z'][:] = 0.0 + 1.0 * (X - x03) + 1.0 * (Y - y03) - 1.0 * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) + 1.0 * (Y - y03) * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) * (Z - z03) return b
def read_crds(cls, fname, dims=None): # dims are xyz order unlike all other interfaces if dims is None: dims = cls.parse_header(fname)['dims'] dat = np.loadtxt(fname, usecols=list(range(len(dims), 2 * len(dims))), unpack=True, ndmin=2) dxmin = np.inf cclist = [] nclist = [] for i, dim, axis in zip(count(), dims, "xyz"): stop = int(np.prod(dims[:i + 1])) step = int(np.prod(dims[:i])) cc = dat[i][:stop:step] dxmin = np.min([dxmin, np.min(cc[1:] - cc[:-1])]) assert len(cc) == dim cclist.append((axis, cc)) for axis, cc in cclist: if len(cc) > 1: hd = 0.5 * (cc[1:] - cc[:-1]) nc = np.hstack([cc[0] - hd[0], cc[:-1] + hd, cc[-1] + hd[-1]]) else: hd = 0.5 * dxmin nc = np.array([cc[0] - hd, cc[0] + hd]) nclist.append((axis, nc)) return coordinate.wrap_crds("nonuniform_cartesian", nclist)
def _make_crds(self, filename): fw = AthenaBinFileWrapper(filename, keep_crd_clist=True, float_type_name=self.float_type_name, var_type=self.var_type) with fw as f: crd_clist = f.crd_clist new_clist = [] dxmin = np.inf for c in crd_clist: if len(c[1]) > 1: dxmin = np.min([dxmin, np.min(c[1][1:] - c[1][:-1])]) for i, cli in enumerate(crd_clist): cc = cli[1] try: hd = 0.5 * (cc[1:] - cc[:-1]) nc = np.hstack( [cc[0] - hd[0], cc[:-1] + hd, cc[-1] + hd[-1]]) except IndexError: dxminh = 0.5 * dxmin nc = np.array([cc[0] - dxminh, cc[0] + dxminh]) new_clist.append([crd_clist[i][0], nc]) crds = coordinate.wrap_crds("nonuniform_cartesian", new_clist[::-1]) return crds
def _parse(self): # get field names from header with open(self.fname, 'r') as f: line = f.readline() line = f.readline().lstrip("#").strip() fld_names = re.split(r"\[[0-9]+\]=", line)[1:] fld_names = [fn.strip() for fn in fld_names] # crds here are really times dat = np.loadtxt(self.fname, unpack=True) t = dat[0] crds = coordinate.wrap_crds("nonuniform_cartesian", [('t', t)]) g = self._make_grid(self, name="AthenaHstGrid") g.set_crds(crds) g.time = 0 for i in range(1, len(fld_names)): fld = self._make_field(g, "Scalar", fld_names[i], crds, dat[i], center="Node") g.add_field(fld) self.add(g) self.activate(0)
def make_dipole(m=None, twod=False): dtype = 'float64' n = 256 x = np.array(np.linspace(-5, 5, n), dtype=dtype) y = np.array(np.linspace(-5, 5, n), dtype=dtype) z = np.array(np.linspace(-5, 5, n), dtype=dtype) if twod: y = np.array(np.linspace(-0.1, 0.1, 2), dtype=dtype) crds = coordinate.wrap_crds("nonuniform_cartesian", (('z', z), ('y', y), ('x', x))) one = np.array([1.0], dtype=dtype) # pylint: disable=W0612 three = np.array([3.0], dtype=dtype) # pylint: disable=W0612 if not m: m = [0.0, 0.0, -1.0] m = np.array(m, dtype=dtype) mx, my, mz = m # pylint: disable=W0612 Zcc, Ycc, Xcc = crds.get_crds_cc(shaped=True) # pylint: disable=W0612 rsq = ne.evaluate("Xcc**2 + Ycc**2 + Zcc**2") # pylint: disable=W0612 mdotr = ne.evaluate("mx * Xcc + my * Ycc + mz * Zcc") # pylint: disable=W0612 Bx = ne.evaluate("((three * Xcc * mdotr / rsq) - mx) / rsq**1.5") By = ne.evaluate("((three * Ycc * mdotr / rsq) - my) / rsq**1.5") Bz = ne.evaluate("((three * Zcc * mdotr / rsq) - mz) / rsq**1.5") fld = field.VectorField("B_cc", crds, [Bx, By, Bz], center="Cell", forget_source=True, _force_layout=field.LAYOUT_INTERLACED, ) # fld_rsq = field.ScalarField("r", crds, hmm, # center="Cell", forget_source=True) return fld # , fld_rsq
def make_crds(self): if self.get_info('fieldtype') == 'iof': # 181, 61 nphi, ntheta = self._shape_discovery_hack(self._collection[0]) crdlst = [['phi', [0.0, 360.0, nphi]], ['theta', [0.0, 180.0, ntheta]]] return wrap_crds("uniform_spherical", crdlst, units='deg') else: return self.read_grid2()
def make_crds(self): if self.get_info('fieldtype') == 'iof': # 181, 61 nlon, nlat = self._shape_discovery_hack(self._collection[0]) crdlst = [['lon', [0.0, 360.0, nlon]], ['lat', [0.0, 180.0, nlat]]] return wrap_crds("uniform_spherical", crdlst) else: return self.read_grid2()
def read_grid2(self): # TODO: iof files can be hacked in here grid2_basename = "{0}.grid2".format(self.find_info('run')) self.grid2 = find_file_uptree(self.dirname, grid2_basename) if self.grid2 is None: self.grid2 = find_file_uptree(".", grid2_basename) if self.grid2 is None: raise IOError("Could not find a grid2 file for " "{0}".format(self.fname)) # load the cell centered grid with open(self.grid2, 'r') as fin: nx = int(next(fin).split()[0]) gx = list(islice(fin, 0, nx, 1)) gx = np.array(gx, dtype='f4') ny = int(next(fin).split()[0]) gy = list(islice(fin, 0, ny, 1)) gy = np.array(gy, dtype='f4') nz = int(next(fin).split()[0]) gz = list(islice(fin, 0, nz, 1)) gz = np.array(gz, dtype='f4') xnc = np.empty(len(gx) + 1, dtype=gx.dtype) ync = np.empty(len(gy) + 1, dtype=gy.dtype) znc = np.empty(len(gz) + 1, dtype=gz.dtype) for cc, nc in [(gx, xnc), (gy, ync), (gz, znc)]: hd = 0.5 * (cc[1:] - cc[:-1]) nc[:] = np.hstack([cc[0] - hd[0], cc[:-1] + hd, cc[-1] + hd[-1]]) # for 2d files crdlst = [] for dim, nc, cc in zip("xyz", [xnc, ync, znc], [gx, gy, gz]): fieldtype = self.get_info('fieldtype') if fieldtype.startswith('p'): self.set_info('plane', fieldtype[1]) if fieldtype[1] == dim: planeloc = float(fieldtype.split('_')[1]) planeloc /= 10 # value is in tenths of Re # FIXME: it is not good to depend on an attribute of # GGCMGrid like this... it could lead to unexpected # behavior if the user starts playing with the value # of an instance, but I'm not sure in practice how or why # since reading the grid should happen fairly early in # the construction process if GGCMGrid.mhd_to_gse_on_read and dim in 'xy': planeloc *= -1 self.set_info('planeloc', planeloc) ccind = np.argmin(np.abs(cc - planeloc)) nc = nc[ccind:ccind + 2] crdlst.append([dim, nc]) return wrap_crds("nonuniform_cartesian", crdlst, units='Re')
def make_crds(self, fname): with h5py.File(fname, 'r') as f: clist = [] # FIXME: xyz crds = "xyz" nr_crds = len(f['StructGridField'].shape) - 1 for i in range(nr_crds): try: clist.append((crds[i], self._get_single_crd(f, i, nr_crds))) except IndexError: pass if f['StructGrid'].attrs['vsKind'].decode() in ['uniform']: # FIXME: this goes xyz -> zyx crds = wrap_crds("uniform_cartesian", clist) else: crds = wrap_crds("nonuniform_cartesian", clist) return crds
def _parse(self): g = self._make_grid(self) arr = np.loadtxt(self.fname) crds = coordinate.wrap_crds("nonuniform_cartesian", [['x', arr[:, 0]]]) g.set_crds(crds) if len(arr.shape) > 1: for i in range(1, arr.shape[1]): fld = self._make_field(g, "Scalar", 'c' + str(i), crds, arr[:, i]) g.add_field(fld) self.add(g) self.activate(0)
def _parse(self): g = self._make_grid(self, **self._grid_opts) with np.load(self.fname) as f: fld_names = list(f.keys()) crd_names = [] # try to get crds names from an array of strings called _KEY_CRDS # else, assume it's x, y, z and see if that works try: clist = [(ax, f[ax]) for ax in f[self._KEY_CRDS]] crd_names = f[self._KEY_CRDS] fld_names.remove(self._KEY_CRDS) except KeyError: for axisname in "xyz": if axisname in f: crd_names.append(axisname) clist = [(cn, NPZDataWrapper(self.fname, cn)) for cn in crd_names] crds = coordinate.wrap_crds("nonuniform_cartesian", clist) g.set_crds(crds) for c in clist: # we should be sure by now that the keys exist fld_names.remove(c[0]) # try to get field names from arrays of nc, cc, ec, fc # fields for fld_center, names_key in self._KEY_FLDS.items(): try: names = f[names_key] fld_names.remove(names_key) except KeyError: names = [] for name in names: fld = self._wrap_lazy_field(g, self.fname, name, crds, fld_center) g.add_field(fld) fld_names.remove(name) # load any remaining fields as though they were node centered for name in fld_names: fld = self._wrap_lazy_field(g, self.fname, name, crds, "Node") g.add_field(fld) self.add(g) self.activate(0)
def _parse(self): g = self._make_grid(self, **self._grid_opts) with np.load(self.fname) as f: fld_names = f.keys() crd_names = [] # try to get crds names from an array of strings called _KEY_CRDS # else, assume it's x, y, z and see if that works try: clist = [(ax, f[ax]) for ax in f[self._KEY_CRDS]] crd_names = f[self._KEY_CRDS] fld_names.remove(self._KEY_CRDS) except KeyError: for axisname in "xyz": if axisname in f: crd_names.append(axisname) clist = [(cn, NPZDataWrapper(self.fname, cn)) for cn in crd_names] crds = coordinate.wrap_crds("nonuniform_cartesian", clist) g.set_crds(crds) for c in clist: # we should be sure by now that the keys exist fld_names.remove(c[0]) # try to get field names from arrays of nc, cc, ec, fc # fields for fld_center, names_key in self._KEY_FLDS.items(): try: names = f[names_key] fld_names.remove(names_key) except KeyError: names = [] for name in names: fld = self._wrap_lazy_field(g, self.fname, name, crds, fld_center) g.add_field(fld) fld_names.remove(name) # load any remaining fields as though they were node centered for name in fld_names: fld = self._wrap_lazy_field(g, self.fname, name, crds, "Node") g.add_field(fld) self.add(g) self.activate(0)
def _make_crds(self, filename): fw = AthenaBinFileWrapper(filename, keep_crd_clist=True, float_type_name=self.float_type_name, var_type=self.var_type) with fw as f: crd_clist = f.crd_clist new_clist = [] dxmin = np.inf for c in crd_clist: if len(c[1]) > 1: dxmin = np.min([dxmin, np.min(c[1][1:] - c[1][:-1])]) for i, cli in enumerate(crd_clist): cc = cli[1] try: hd = 0.5 * (cc[1:] - cc[:-1]) nc = np.hstack([cc[0] - hd[0], cc[:-1] + hd, cc[-1] + hd[-1]]) except IndexError: dxminh = 0.5 * dxmin nc = np.array([cc[0] - dxminh, cc[0] + dxminh]) new_clist.append([crd_clist[i][0], nc]) crds = coordinate.wrap_crds("nonuniform_cartesian", new_clist[::-1]) return crds
def _parse_geometry(self, geo, topoattrs): """ geo is the element tree item, returns Coordinate object and xml attributes """ geoattrs = self._fill_attrs(geo) # crds = None crdlist = None crdtype = None crdkwargs = {} topotype = topoattrs["TopologyType"] # parse geometry into crds geotype = geoattrs["GeometryType"] if geotype.upper() == "XYZ": data, attrs = self._parse_dataitem(geo.find("./DataItem"), keep_flat=True) # x = data[0::3] # y = data[1::3] # z = data[2::3] # crdlist = (('z', z), ('y', y), ('x', x)) # quietly do nothing... we don't support unstructured grids # or 3d spherical yet, and 2d spherical can be figured out # if we assume the grid spans the whole sphere crdlist = None elif geotype.upper() == "XY": data, attrs = self._parse_dataitem(geo.find("./DataItem"), keep_flat=True) # x = data[0::2] # y = data[1::2] # z = np.zeros(len(x)) # crdlist = (('z', z), ('y', y), ('x', x)) # quietly do nothing... we don't support unstructured grids # or 3d spherical yet, and 2d spherical can be figured out # if we assume the grid spans the whole sphere crdlist = None elif geotype.upper() == "X_Y_Z": crdlookup = {'x': 0, 'y': 1, 'z': 2} crdlist = [['x', None], ['y', None], ['z', None]] # can't use ./DataItem[@Name='X'] so python2.6 works dataitems = geo.findall("./DataItem") for di in dataitems: crd_name = di.attrib["Name"].lower() data, attrs = self._parse_dataitem(di, keep_flat=True) crdlist[crdlookup.pop(crd_name)][1] = data if len(crdlookup) > 0: raise RuntimeError("XDMF format error: Coords not specified " "for {0} dimesions" "".format(list(crdlookup.keys()))) crdkwargs["full_arrays"] = True elif geotype.upper() == "VXVYVZ": crdlookup = {'x': 0, 'y': 1, 'z': 2} crdlist = [['x', None], ['y', None], ['z', None]] # can't use ./DataItem[@Name='VX'] so python2.6 works dataitems = geo.findall("./DataItem") for di in dataitems: crd_name = di.attrib["Name"].lstrip('V').lower() data, attrs = self._parse_dataitem(di, keep_flat=True) crdlist[crdlookup.pop(crd_name)][1] = data if len(crdlookup) > 0: raise RuntimeError("XDMF format error: Coords not specified " "for {0} dimesions" "".format(list(crdlookup.keys()))) crdkwargs["full_arrays"] = True elif geotype.upper() == "ORIGIN_DXDYDZ": # this is for grids with uniform spacing dataitems = geo.findall("./DataItem") data_o, _ = self._parse_dataitem(dataitems[0]) data_dx, _ = self._parse_dataitem(dataitems[1]) dtyp = data_o.dtype nstr = None if topoattrs["Dimensions"]: nstr = topoattrs["Dimensions"] elif topoattrs["NumberOfElements"]: nstr = topoattrs["NumberOfElements"] else: raise ValueError("ORIGIN_DXDYDZ has no number of elements...") n = [int(num) for num in nstr.split()] # FIXME: OpenGGCM output uses ZYX ordering even though the xdmf # website says it should be XYZ, BUT, the file opens correctly # in Paraview with zyx, so... I guess i need to do this [::-1] # nonsense here data_o, data_dx, n = data_o[::-1], data_dx[::-1], n[::-1] crdlist = [None] * 3 for i, crd in enumerate(['x', 'y', 'z']): n_nc, n_cc = n[i], n[i] - 1 crd_arr = [data_o[i], data_o[i] + (n_cc * data_dx[i]), n_nc] crdlist[i] = (crd, crd_arr) crdkwargs["dtype"] = dtyp crdkwargs["full_arrays"] = False else: logger.warn("Invalid GeometryType: %s", geotype) if topotype in ['3DCoRectMesh', '2DCoRectMesh']: crdtype = "uniform_cartesian" elif topotype in ['3DRectMesh', '2DRectMesh']: if crdkwargs.get("full_arrays", True): crdtype = "nonuniform_cartesian" else: # HACK, hopefully not used ever crdtype = "uniform_cartesian" elif topotype in ['2DSMesh']: crdtype = "uniform_spherical" # HACK! ######## this doesn't quite work, but it's too heavy to be useful ######## anyway... if we assume a 2d spherical grid spans the ######## whole sphere, and radius doesnt matter, all we need are ######## the nr_phis / nr_thetas, so let's just do that # # this asserts that attrs["Dimensions"] will have the xyz # # dimensions # # turn x, y, z -> phi, theta, r # dims = [int(s) for # s in reversed(topoattrs["Dimensions"].split(' '))] # dims = [1] * (3 - len(dims)) + dims # nr, ntheta, nphi = [d for d in dims] # # dtype = crdlist[0][1].dtype # # phi, theta, r = [np.empty((n,), dtype=dtype) for n in dims] # x, y, z = (crdlist[i][1].reshape(dims) for i in range(3)) # nphitheta = nphi * ntheta # r = np.sqrt(x[::nphitheta, 0, 0]**2 + y[::nphitheta, 0, 0]**2 + # z[::nphitheta, 0, 0]**2) # ir = nr // 2 # things get squirrly near the extrema # theta = (180.0 / np.pi) * \ # (np.arccos(z[ir, :, ::nphi] / r[ir]).reshape(-1)) # itheta = ntheta // 2 # phi = (180.0 / np.pi) * \ # np.arctan2(y[ir, itheta, :], x[ir, itheta, :]) # print(dims, nr, ntheta, nphi) # print("r:", r.shape, r) # print("theta:", theta.shape, theta) # print("phi:", phi.shape, phi) # raise RuntimeError() ######## general names in spherical crds # ntheta, nphi = [int(s) for s in topoattrs["Dimensions"].split(' ')] # crdlist = [['theta', [0.0, 180.0, ntheta]], # ['phi', [0.0, 360.0, nphi]]] ######## names on a map ntheta, nphi = [int(s) for s in topoattrs["Dimensions"].split(' ')] crdlist = [['phi', [0.0, 360.0, nphi]], ['theta', [0.0, 180.0, ntheta]]] crdkwargs["full_arrays"] = False crdkwargs["units"] = 'deg' elif topotype in ['3DSMesh']: raise NotImplementedError("3D spherical grids not yet supported") else: raise NotImplementedError("Unstructured grids not yet supported") crds = coordinate.wrap_crds(crdtype, crdlist, **crdkwargs) return crds, geoattrs
def main(): xl, xh, nx = -1.0, 1.0, 41 yl, yh, ny = -1.5, 1.5, 41 zl, zh, nz = -2.0, 2.0, 41 x = np.linspace(xl, xh, nx) y = np.linspace(yl, yh, ny) z = np.linspace(zl, zh, nz) crds = coordinate.wrap_crds("nonuniform_cartesian", [('z', z), ('y', y), ('x', x)]) bx = field.empty(crds, name="$B_x$", center="Node") by = field.empty(crds, name="$B_y$", center="Node") bz = field.empty(crds, name="$B_z$", center="Node") fld = field.empty(crds, name="B", nr_comps=3, center="Node", layout="interlaced") X, Y, Z = crds.get_crds(shaped=True) x01, y01, z01 = 0.5, 0.5, 0.5 x02, y02, z02 = 0.5, 0.5, 0.5 x03, y03, z03 = 0.5, 0.5, 0.5 bx[:] = 0.0 + 1.0 * (X - x01) + 1.0 * (Y - y01) + 1.0 * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) + 1.0 * (Y - y01) * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) * (Z - z01) by[:] = 0.0 + 1.0 * (X - x02) - 1.0 * (Y - y02) + 1.0 * (Z - z02) + \ 1.0 * (X - x02) * (Y - y02) + 1.0 * (Y - y02) * (Z - z02) - \ 1.0 * (X - x02) * (Y - y02) * (Z - z02) bz[:] = 0.0 + 1.0 * (X - x03) + 1.0 * (Y - y03) - 1.0 * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) + 1.0 * (Y - y03) * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) * (Z - z03) fld[..., 0] = bx fld[..., 1] = by fld[..., 2] = bz fig = mlab.figure(size=(1150, 850), bgcolor=(1.0, 1.0, 1.0), fgcolor=(0.0, 0.0, 0.0)) f1_src = vlab.add_field(bx) f2_src = vlab.add_field(by) f3_src = vlab.add_field(bz) mlab.pipeline.iso_surface(f1_src, contours=[0.0], opacity=1.0, color=(1.0, 0.0, 0.0)) mlab.pipeline.iso_surface(f2_src, contours=[0.0], opacity=1.0, color=(0.0, 1.0, 0.0)) mlab.pipeline.iso_surface(f3_src, contours=[0.0], opacity=1.0, color=(0.0, 0.0, 1.0)) mlab.axes() mlab.show() nullpt = cycalc.interp_trilin(fld, [(0.5, 0.5, 0.5)]) print("f(0.5, 0.5, 0.5):", nullpt) ax1 = plt.subplot2grid((4, 3), (0, 0)) all_roots = [] positive_roots = [] ix = iy = iz = 0 for di, d in enumerate([0, -1]): #### XY face a1 = bx[iz + d, iy, ix] b1 = bx[iz + d, iy, ix - 1] - a1 c1 = bx[iz + d, iy - 1, ix] - a1 d1 = bx[iz + d, iy - 1, ix - 1] - c1 - b1 - a1 a2 = by[iz + d, iy, ix] b2 = by[iz + d, iy, ix - 1] - a2 c2 = by[iz + d, iy - 1, ix] - a2 d2 = by[iz + d, iy - 1, ix - 1] - c2 - b2 - a2 a3 = bz[iz + d, iy, ix] b3 = bz[iz + d, iy, ix - 1] - a3 c3 = bz[iz + d, iy - 1, ix] - a3 d3 = bz[iz + d, iy - 1, ix - 1] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((rt1, rt2, d)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((rt1, rt2, d)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (xh - xl) * roots1 + xl roots2 = (yh - yl) * roots2 + yl xp = np.linspace(0.0, 1.0, nx) # plt.subplot(121) plt.subplot2grid((4, 3), (0 + 2 * di, 0), sharex=ax1, sharey=ax1) vlt.plot(fld['x'], "z={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( xl, xh, yl, yh)) y1 = -(a1 + b1 * xp) / (c1 + d1 * xp) plt.plot(x, (yh - yl) * y1 + yl, 'k') for i, xrt, yrt in zip(count(), roots1, roots2): plt.plot(xrt, yrt, markers[i]) # plt.subplot(122) plt.subplot2grid((4, 3), (1 + 2 * di, 0), sharex=ax1, sharey=ax1) vlt.plot(fld['y'], "z={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( xl, xh, yl, yh)) y2 = -(a2 + b2 * xp) / (c2 + d2 * xp) plt.plot(x, (yh - yl) * y2 + yl, 'k') for xrt, yrt in zip(roots1, roots2): plt.plot(xrt, yrt, markers[i]) #### YZ face a1 = bx[iz, iy, ix + d] b1 = bx[iz, iy - 1, ix + d] - a1 c1 = bx[iz - 1, iy, ix + d] - a1 d1 = bx[iz - 1, iy - 1, ix + d] - c1 - b1 - a1 a2 = by[iz, iy, ix + d] b2 = by[iz, iy - 1, ix + d] - a2 c2 = by[iz - 1, iy, ix + d] - a2 d2 = by[iz - 1, iy - 1, ix + d] - c2 - b2 - a2 a3 = bz[iz, iy, ix + d] b3 = bz[iz, iy - 1, ix + d] - a3 c3 = bz[iz - 1, iy, ix + d] - a3 d3 = bz[iz - 1, iy - 1, ix + d] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((d, rt1, rt2)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((d, rt1, rt2)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (yh - yl) * roots1 + yl roots2 = (zh - zl) * roots2 + zl yp = np.linspace(0.0, 1.0, ny) # plt.subplot(121) plt.subplot2grid((4, 3), (0 + 2 * di, 1), sharex=ax1, sharey=ax1) vlt.plot(fld['x'], "x={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( yl, yh, zl, zh)) z1 = -(a1 + b1 * yp) / (c1 + d1 * yp) plt.plot(y, (zh - zl) * z1 + zl, 'k') for i, yrt, zrt in zip(count(), roots1, roots2): plt.plot(yrt, zrt, markers[i]) # plt.subplot(122) plt.subplot2grid((4, 3), (1 + 2 * di, 1), sharex=ax1, sharey=ax1) vlt.plot(fld['y'], "x={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( yl, yh, zl, zh)) z1 = -(a2 + b2 * yp) / (c2 + d2 * yp) plt.plot(y, (zh - zl) * z1 + zl, 'k') for i, yrt, zrt in zip(count(), roots1, roots2): plt.plot(yrt, zrt, markers[i]) #### ZX face a1 = bx[iz, iy + d, ix] b1 = bx[iz - 1, iy + d, ix] - a1 c1 = bx[iz, iy + d, ix - 1] - a1 d1 = bx[iz - 1, iy + d, ix - 1] - c1 - b1 - a1 a2 = by[iz, iy + d, ix] b2 = by[iz - 1, iy + d, ix] - a2 c2 = by[iz, iy + d, ix - 1] - a2 d2 = by[iz - 1, iy + d, ix - 1] - c2 - b2 - a2 a3 = bz[iz, iy + d, ix] b3 = bz[iz - 1, iy + d, ix] - a3 c3 = bz[iz, iy + d, ix - 1] - a3 d3 = bz[iz - 1, iy + d, ix - 1] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((rt2, d, rt1)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((rt2, d, rt1)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (zh - zl) * roots1 + zl roots2 = (xh - xl) * roots2 + xl zp = np.linspace(0.0, 1.0, nz) # plt.subplot(121) plt.subplot2grid((4, 3), (0 + 2 * di, 2), sharex=ax1, sharey=ax1) vlt.plot(fld['x'], "y={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( xl, xh, zl, zh)) x1 = -(a1 + b1 * zp) / (c1 + d1 * zp) plt.plot(z, (xh - xl) * x1 + xl, 'k') for i, zrt, xrt in zip(count(), roots1, roots2): plt.plot(xrt, zrt, markers[i]) # plt.subplot(121) plt.subplot2grid((4, 3), (1 + 2 * di, 2), sharex=ax1, sharey=ax1) vlt.plot(fld['y'], "y={0}i".format(d), plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format( xl, xh, zl, zh)) x1 = -(a2 + b2 * zp) / (c2 + d2 * zp) plt.plot(z, (xh - xl) * x1 + xl, 'k') for i, zrt, xrt in zip(count(), roots1, roots2): plt.plot(xrt, zrt, markers[i]) print("all:", len(all_roots), "positive:", len(positive_roots)) if len(all_roots) % 2 == 1: print("something is fishy, there are an odd number of root points " "on the surface of your cube, there is probably a degenerate " "line or surface of nulls") print("Null Point?", (len(positive_roots) % 2 == 1)) plt.show()
def as_polar_mapfield(fld, bounding_lat=None, hemisphere='north', make_periodic=False): """Prepare a theta/phi or lat/lon field for polar projection Args: fld (Field): Some scalar or vector field bounding_lat (float, optional): Used to slice the field, i.e., gives data from the pole to bounding_lat degrees equator-ward of the pole hemisphere (str, optional): 'north' or 'south' Returns: Field: a field that can be mapfield plotted on polar axes Raises: ValueError: on bad hemisphere """ hemisphere = hemisphere.strip().lower() mfld = as_mapfield(fld, order=('lon', 'lat'), units='rad') # set a sensible default for bounding_lat... full spheres get cut off # at 40 deg, but hemispheres or smaller are shown in full if bounding_lat is None: if abs(mfld.xh[1] - mfld.xl[1]) >= 1.01 * np.pi: bounding_lat = 40.0 else: bounding_lat = 90.0 bounding_lat = (np.pi / 180.0) * bounding_lat abs_bounding_lat = abs(bounding_lat) if hemisphere in ("north", 'n'): if np.all(mfld.get_crd('lat') < abs_bounding_lat): raise ValueError("fld {0} contains no values north of bounding lat " "{1:g} deg" "".format(fld.name, bounding_lat * 180 / np.pi)) # mfld = mfld["lat=:{0}j:-1".format(abs_bounding_lat)] mfld = mfld.loc[:, :np.pi / 2 - abs_bounding_lat:-1] elif hemisphere in ("south", 's'): if np.all(mfld.get_crd('lat') > -abs_bounding_lat): raise ValueError("fld {0} contains no values south of bounding lat " "{1:g} deg" "".format(fld.name, bounding_lat * 180 / np.pi)) # mfld = mfld["lat=:{0}j".format(-abs_bounding_lat)] mfld = mfld.loc[:, :-np.pi / 2 + abs_bounding_lat] else: raise ValueError("hemisphere should be either north or south") clist = mfld.get_clist() offset = np.pi / 2 scale = -1 if hemisphere in ('north', 'n') else 1 if mfld.crds.is_uniform(): for i in range(2): clist[1][1][i] = scale * clist[1][1][i] + offset else: clist[1][1] = scale * clist[1][1] + offset mfld_dat = mfld.data if make_periodic: if mfld.crds.is_uniform(): phi_diff = clist[0][1][1] - clist[0][1][0] else: phi_diff = clist[0][1][-1] - clist[0][1][0] if phi_diff < 2 * np.pi - 1e-5: if mfld.crds.is_uniform(): clist[0][1][1] += phi_diff / clist[0][1][2] if not np.isclose(clist[0][1][1] - clist[0][1][0], 2 * np.pi): viscid.logger.warning("Tried unsuccessfully to make uniform " "polar mapfield periodic: {0:g}" "".format(clist[0][1][1] - clist[0][1][0])) else: clist[0][1] = np.concatenate([clist[0][1], [clist[0][1][0] + 2 * np.pi]]) mfld_dat = np.concatenate([mfld_dat, mfld_dat[0:1, :]], axis=0) crds = wrap_crds(mfld.crds.crdtype, clist, dtype=mfld.crds.dtype) ctx = dict(crds=crds) return mfld.wrap(mfld_dat, context=ctx)
def as_polar_mapfield(fld, bounding_lat=None, hemisphere='north', make_periodic=False): """Prepare a theta/phi or lat/lon field for polar projection Args: fld (Field): Some scalar or vector field bounding_lat (float, optional): Used to slice the field, i.e., gives data from the pole to bounding_lat degrees equator-ward of the pole hemisphere (str, optional): 'north' or 'south' Returns: Field: a field that can be mapfield plotted on polar axes Raises: ValueError: on bad hemisphere """ hemisphere = hemisphere.strip().lower() mfld = as_mapfield(fld, order=('lon', 'lat'), units='rad') # set a sensible default for bounding_lat... full spheres get cut off # at 40 deg, but hemispheres or smaller are shown in full if bounding_lat is None: if abs(mfld.xh[1] - mfld.xl[1]) >= 1.01 * np.pi: bounding_lat = 40.0 else: bounding_lat = 90.0 bounding_lat = (np.pi / 180.0) * bounding_lat abs_bounding_lat = abs(bounding_lat) if hemisphere in ("north", 'n'): if np.all(mfld.get_crd('lat') < abs_bounding_lat): raise ValueError( "fld {0} contains no values north of bounding lat " "{1:g} deg" "".format(fld.name, bounding_lat * 180 / np.pi)) # mfld = mfld["lat=:{0}j:-1".format(abs_bounding_lat)] mfld = mfld.loc[:, :np.pi / 2 - abs_bounding_lat:-1] elif hemisphere in ("south", 's'): if np.all(mfld.get_crd('lat') > -abs_bounding_lat): raise ValueError( "fld {0} contains no values south of bounding lat " "{1:g} deg" "".format(fld.name, bounding_lat * 180 / np.pi)) # mfld = mfld["lat=:{0}j".format(-abs_bounding_lat)] mfld = mfld.loc[:, :-np.pi / 2 + abs_bounding_lat] else: raise ValueError("hemisphere should be either north or south") clist = mfld.get_clist() offset = np.pi / 2 scale = -1 if hemisphere in ('north', 'n') else 1 if mfld.crds.is_uniform(): for i in range(2): clist[1][1][i] = scale * clist[1][1][i] + offset else: clist[1][1] = scale * clist[1][1] + offset mfld_dat = mfld.data if make_periodic: if mfld.crds.is_uniform(): phi_diff = clist[0][1][1] - clist[0][1][0] else: phi_diff = clist[0][1][-1] - clist[0][1][0] if phi_diff < 2 * np.pi - 1e-5: if mfld.crds.is_uniform(): clist[0][1][1] += phi_diff / clist[0][1][2] if not np.isclose(clist[0][1][1] - clist[0][1][0], 2 * np.pi): viscid.logger.warning( "Tried unsuccessfully to make uniform " "polar mapfield periodic: {0:g}" "".format(clist[0][1][1] - clist[0][1][0])) else: clist[0][1] = np.concatenate( [clist[0][1], [clist[0][1][0] + 2 * np.pi]]) mfld_dat = np.concatenate([mfld_dat, mfld_dat[0:1, :]], axis=0) crds = wrap_crds(mfld.crds.crdtype, clist, dtype=mfld.crds.dtype) ctx = dict(crds=crds) return mfld.wrap(mfld_dat, context=ctx)
def main(): xl, xh, nx = -1.0, 1.0, 41 yl, yh, ny = -1.5, 1.5, 41 zl, zh, nz = -2.0, 2.0, 41 x = np.linspace(xl, xh, nx) y = np.linspace(yl, yh, ny) z = np.linspace(zl, zh, nz) crds = coordinate.wrap_crds("nonuniform_cartesian", [('z', z), ('y', y), ('x', x)]) bx = field.empty(crds, name="$B_x$", center="Node") by = field.empty(crds, name="$B_y$", center="Node") bz = field.empty(crds, name="$B_z$", center="Node") fld = field.empty(crds, name="B", nr_comps=3, center="Node", layout="interlaced") X, Y, Z = crds.get_crds(shaped=True) x01, y01, z01 = 0.5, 0.5, 0.5 x02, y02, z02 = 0.5, 0.5, 0.5 x03, y03, z03 = 0.5, 0.5, 0.5 bx[:] = 0.0 + 1.0 * (X - x01) + 1.0 * (Y - y01) + 1.0 * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) + 1.0 * (Y - y01) * (Z - z01) + \ 1.0 * (X - x01) * (Y - y01) * (Z - z01) by[:] = 0.0 + 1.0 * (X - x02) - 1.0 * (Y - y02) + 1.0 * (Z - z02) + \ 1.0 * (X - x02) * (Y - y02) + 1.0 * (Y - y02) * (Z - z02) - \ 1.0 * (X - x02) * (Y - y02) * (Z - z02) bz[:] = 0.0 + 1.0 * (X - x03) + 1.0 * (Y - y03) - 1.0 * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) + 1.0 * (Y - y03) * (Z - z03) + \ 1.0 * (X - x03) * (Y - y03) * (Z - z03) fld[..., 0] = bx fld[..., 1] = by fld[..., 2] = bz fig = mlab.figure(size=(1150, 850), bgcolor=(1.0, 1.0, 1.0), fgcolor=(0.0, 0.0, 0.0)) f1_src = vlab.add_field(bx) f2_src = vlab.add_field(by) f3_src = vlab.add_field(bz) mlab.pipeline.iso_surface(f1_src, contours=[0.0], opacity=1.0, color=(1.0, 0.0, 0.0)) mlab.pipeline.iso_surface(f2_src, contours=[0.0], opacity=1.0, color=(0.0, 1.0, 0.0)) mlab.pipeline.iso_surface(f3_src, contours=[0.0], opacity=1.0, color=(0.0, 0.0, 1.0)) mlab.axes() mlab.show() nullpt = cycalc.interp_trilin(fld, [(0.5, 0.5, 0.5)]) print("f(0.5, 0.5, 0.5):", nullpt) _, axes = plt.subplots(4, 3, sharex=True, sharey=True) all_roots = [] positive_roots = [] ix = iy = iz = 0 for di, d in enumerate([0, -1]): #### XY face a1 = bx[iz + d, iy, ix] b1 = bx[iz + d, iy, ix - 1] - a1 c1 = bx[iz + d, iy - 1, ix] - a1 d1 = bx[iz + d, iy - 1, ix - 1] - c1 - b1 - a1 a2 = by[iz + d, iy, ix] b2 = by[iz + d, iy, ix - 1] - a2 c2 = by[iz + d, iy - 1, ix] - a2 d2 = by[iz + d, iy - 1, ix - 1] - c2 - b2 - a2 a3 = bz[iz + d, iy, ix] b3 = bz[iz + d, iy, ix - 1] - a3 c3 = bz[iz + d, iy - 1, ix] - a3 d3 = bz[iz + d, iy - 1, ix - 1] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((rt1, rt2, d)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((rt1, rt2, d)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (xh - xl) * roots1 + xl roots2 = (yh - yl) * roots2 + yl xp = np.linspace(0.0, 1.0, nx) vlt.plot(fld['x'], "z={0}i".format(d), ax=axes[0 + 2 * di, 0], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(xl, xh, yl, yh)) y1 = - (a1 + b1 * xp) / (c1 + d1 * xp) plt.plot(x, (yh - yl) * y1 + yl, 'k') for i, xrt, yrt in zip(count(), roots1, roots2): plt.plot(xrt, yrt, markers[i]) vlt.plot(fld['y'], "z={0}i".format(d), ax=axes[1 + 2 * di, 0], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(xl, xh, yl, yh)) y2 = - (a2 + b2 * xp) / (c2 + d2 * xp) plt.plot(x, (yh - yl) * y2 + yl, 'k') for xrt, yrt in zip(roots1, roots2): plt.plot(xrt, yrt, markers[i]) #### YZ face a1 = bx[iz, iy, ix + d] b1 = bx[iz, iy - 1, ix + d] - a1 c1 = bx[iz - 1, iy, ix + d] - a1 d1 = bx[iz - 1, iy - 1, ix + d] - c1 - b1 - a1 a2 = by[iz, iy, ix + d] b2 = by[iz, iy - 1, ix + d] - a2 c2 = by[iz - 1, iy, ix + d] - a2 d2 = by[iz - 1, iy - 1, ix + d] - c2 - b2 - a2 a3 = bz[iz, iy, ix + d] b3 = bz[iz, iy - 1, ix + d] - a3 c3 = bz[iz - 1, iy, ix + d] - a3 d3 = bz[iz - 1, iy - 1, ix + d] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((d, rt1, rt2)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((d, rt1, rt2)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (yh - yl) * roots1 + yl roots2 = (zh - zl) * roots2 + zl yp = np.linspace(0.0, 1.0, ny) # plt.subplot(121) vlt.plot(fld['x'], "x={0}i".format(d), ax=axes[0 + 2 * di, 1], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(yl, yh, zl, zh)) z1 = - (a1 + b1 * yp) / (c1 + d1 * yp) plt.plot(y, (zh - zl) * z1 + zl, 'k') for i, yrt, zrt in zip(count(), roots1, roots2): plt.plot(yrt, zrt, markers[i]) # plt.subplot(122) vlt.plot(fld['y'], "x={0}i".format(d), ax=axes[1 + 2 * di, 1], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(yl, yh, zl, zh)) z1 = - (a2 + b2 * yp) / (c2 + d2 * yp) plt.plot(y, (zh - zl) * z1 + zl, 'k') for i, yrt, zrt in zip(count(), roots1, roots2): plt.plot(yrt, zrt, markers[i]) #### ZX face a1 = bx[iz, iy + d, ix] b1 = bx[iz - 1, iy + d, ix] - a1 c1 = bx[iz, iy + d, ix - 1] - a1 d1 = bx[iz - 1, iy + d, ix - 1] - c1 - b1 - a1 a2 = by[iz, iy + d, ix] b2 = by[iz - 1, iy + d, ix] - a2 c2 = by[iz, iy + d, ix - 1] - a2 d2 = by[iz - 1, iy + d, ix - 1] - c2 - b2 - a2 a3 = bz[iz, iy + d, ix] b3 = bz[iz - 1, iy + d, ix] - a3 c3 = bz[iz, iy + d, ix - 1] - a3 d3 = bz[iz - 1, iy + d, ix - 1] - c3 - b3 - a3 roots1, roots2 = find_roots_face(a1, b1, c1, d1, a2, b2, c2, d2) # for rt1, rt2 in zip(roots1, roots2): # print("=") # print("fx", a1 + b1 * rt1 + c1 * rt2 + d1 * rt1 * rt2) # print("fy", a2 + b2 * rt1 + c2 * rt2 + d2 * rt1 * rt2) # print("=") # find f3 at the root points f3 = np.empty_like(roots1) markers = [None] * len(f3) for i, rt1, rt2 in zip(count(), roots1, roots2): f3[i] = a3 + b3 * rt1 + c3 * rt2 + d3 * rt1 * rt2 all_roots.append((rt2, d, rt1)) # switch order here if f3[i] >= 0.0: markers[i] = 'k^' positive_roots.append((rt2, d, rt1)) # switch order here else: markers[i] = 'w^' # rescale the roots to the original domain roots1 = (zh - zl) * roots1 + zl roots2 = (xh - xl) * roots2 + xl zp = np.linspace(0.0, 1.0, nz) # plt.subplot(121) vlt.plot(fld['x'], "y={0}i".format(d), ax=axes[0 + 2 * di, 2], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(xl, xh, zl, zh)) x1 = - (a1 + b1 * zp) / (c1 + d1 * zp) plt.plot(z, (xh - xl) * x1 + xl, 'k') for i, zrt, xrt in zip(count(), roots1, roots2): plt.plot(xrt, zrt, markers[i]) # plt.subplot(121) vlt.plot(fld['y'], "y={0}i".format(d), ax=axes[1 + 2 * di, 2], plot_opts="x={0}_{1},y={2}_{3},lin_-10_10".format(xl, xh, zl, zh)) x1 = - (a2 + b2 * zp) / (c2 + d2 * zp) plt.plot(z, (xh - xl) * x1 + xl, 'k') for i, zrt, xrt in zip(count(), roots1, roots2): plt.plot(xrt, zrt, markers[i]) print("all:", len(all_roots), "positive:", len(positive_roots)) if len(all_roots) % 2 == 1: print("something is fishy, there are an odd number of root points " "on the surface of your cube, there is probably a degenerate " "line or surface of nulls") print("Null Point?", (len(positive_roots) % 2 == 1)) plt.show()