Pseudo-spectral method for 2D Turbulence
Mathematical Formualtion
Vorticity equation
The vorticity (or Helmholtz’s) equation describes the transport of vorticity. We can obtain it by applying the curl operator to the Navier-Stokes equations
\begin{equation} \nabla \times\left( \frac{\partial\boldsymbol{u}}{\partial t} + (\boldsymbol{u}\cdot \nabla)\boldsymbol{u} = -\frac{1}{\rho}\nabla p + \nu \nabla^2 \boldsymbol{u}\right), \tag{1.1} \end{equation}
where $\boldsymbol{u}$ is the velocity field and $p$ is the pressure field. The convective term can be re-arranged to a more suitable form
\begin{equation} \boldsymbol{u}\times\left(\nabla\times\boldsymbol{u}\right) + \left(\boldsymbol{u}\cdot\nabla\right)\boldsymbol{u} = \nabla\left(\frac{\boldsymbol{u}^2}{2}\right) \rightarrow \left(\boldsymbol{u}\cdot\nabla\right)\boldsymbol{u} = \nabla\left(\frac{\boldsymbol{u}^2}{2}\right) + \boldsymbol{\omega}\times\boldsymbol{u}, \end{equation}
using definition of the vorticity ($\boldsymbol{\omega}=\nabla\times\boldsymbol{u}$). Substitution in (1.1) gives
\begin{equation} \nabla \times\left( \frac{\partial\boldsymbol{u}}{\partial t} + \nabla\left(\frac{\boldsymbol{u}^2}{2}\right) + \boldsymbol{\omega} \times\boldsymbol{u} = -\frac{1}{\rho}\nabla p + \nu \nabla^2 \boldsymbol{u}\right). \end{equation}
Distributing the curl operator and making use of the definition of the vorticity, we have
\begin{equation} \frac{\partial\boldsymbol{\omega}}{\partial t} + \nabla \times\nabla\left(\frac{\boldsymbol{u}^2}{2}\right) + \nabla \times\left(\boldsymbol{\omega} \times\boldsymbol{u}\right) = -\nabla \times\left( \frac{1}{\rho}\nabla p\right) + \nu \nabla^2 \boldsymbol{\omega}. \end{equation}
The third term can be expanded using the curl of the curl vector identity
\begin{equation} \frac{\partial\boldsymbol{\omega}}{\partial t} + \nabla \times\nabla\left(\frac{\boldsymbol{u}^2}{2}\right) + \boldsymbol{u}\cdot\nabla\boldsymbol{\omega} - \boldsymbol{u}\nabla\cdot\boldsymbol{\omega} - \boldsymbol{\omega}\cdot\nabla\boldsymbol{u} + \boldsymbol{\omega}\nabla\cdot\boldsymbol{u} = -\nabla \times\left( \frac{1}{\rho}\nabla p\right) + \nu \nabla^2 \boldsymbol{\omega}. \end{equation}
The fourth term vanishes as $\nabla\cdot\boldsymbol{\omega}\equiv 0$ (the divergence of the curl of a vector field is always zero). For an incompressible flow the sixth term equaly vanishes
\begin{equation} \frac{\partial\boldsymbol{\omega}}{\partial t} + \nabla \times\nabla\left(\frac{\boldsymbol{u}^2}{2}\right) + \boldsymbol{u}\cdot\nabla\boldsymbol{\omega} - \boldsymbol{\omega}\cdot\nabla\boldsymbol{u} = -\nabla \times\left( \frac{1}{\rho}\nabla p\right) + \nu \nabla^2 \boldsymbol{\omega}. \end{equation}
The second term, which is the curl of a tensor, can be shown to vanish as well. Indeed, the curl of a tensor $\boldsymbol{S}$ is defined as
\begin{equation} (\nabla\times\boldsymbol{S})\cdot\boldsymbol{a} = \nabla\times(\boldsymbol{S}^\top \cdot\boldsymbol{a}) \quad \forall \boldsymbol{a}, \end{equation}
where $\boldsymbol{a}$ is a vector. In this case, the tensor $\boldsymbol{S}$ is given by the gradient of a vector field, and as gradient and divergence commute
\begin{equation} \left(\nabla \times\nabla\left(\frac{\boldsymbol{u}^2}{2}\right)\right)\cdot\boldsymbol{a} = \nabla\times\left(\nabla^\top\left(\frac{\boldsymbol{u}^2}{2}\right)\cdot\boldsymbol{a}\right) = \nabla\times\left(\nabla\left(\frac{\boldsymbol{u}^2}{2}\cdot\boldsymbol{a}\right)\right) = \nabla\times\nabla\psi\equiv0. \end{equation}
As the curl of the gradient of a scalar field is always zero. Finally, the pressure term can be expanded using the product rule
\begin{equation} \nabla \times\left( \frac{1}{\rho}\nabla p\right) = \nabla\left( \frac{1}{\rho}\right) \times\nabla p + \left( \frac{1}{\rho}\right)\nabla \times\nabla p = \frac{1}{\rho^2}\nabla\rho\times\nabla p. \end{equation}
The last term is zero. For a flow with constant entropy (incompressible, homentropic), the pressure is solely a function of density, this means that the two vector $\nabla\rho$ and $\nabla p$ are aligned and the fist term equaly vanishes. (More precisely, the baroclinic term which account for the change in the vorticity field due to the interaction of density and pressure surfaces (Bailly et al.) vanishes). The vorticity equation is therefore given by
\begin{equation} \frac{\partial\boldsymbol{\omega}}{\partial t} + \boldsymbol{u}\cdot\nabla\boldsymbol{\omega} = \boldsymbol{\omega}\cdot\nabla\boldsymbol{u} + \nu \nabla^2 \boldsymbol{\omega}. \end{equation}
In 2D, these equations can be simplified further by noting that the component of the velocity field are
\begin{equation} \boldsymbol{u} = (u, v, 0), \quad \frac{\partial}{\partial z} =0. \end{equation}
The vorticity is, by definition, normal to the $x$-$y$ plane ($\boldsymbol{\omega}=(0, 0, \omega_z)$). This means that the term $\boldsymbol{\omega}\cdot\nabla\boldsymbol{u}$ is zero, as is easily demonstrated
\[\boldsymbol{\omega}\cdot\nabla\boldsymbol{u} = \left(\underbrace{\omega_x}_{0}\frac{\partial}{\partial x} + \underbrace{\omega_y}_{0}\frac{\partial}{\partial y} + \omega_z\underbrace{\frac{\partial}{\partial z}}_{0}\right)\boldsymbol{u}.\]This term is the so-called vortex-stretching term. It is the mean by which the energy is cascaded from the large scales to the smaller scales following the $k^{-5/3}$ rule. In 2D this means that the angular velocity of a particle is conserved, and the length of a vortex tube cannot change due to continuity , see MIT notes.
In 3D, the vortex-stretching term has the form $\omega_{j}\frac{\partial u_i}{\partial x_j}$, thus looking at, say the second component, we have
\begin{equation} \omega_{j}\frac{\partial u_i}{\partial x_j} = \omega_{1}\frac{\partial u_2}{\partial x_1} + \omega_{2}\frac{\partial u_2}{\partial x_2} + \omega_{3}\frac{\partial u_2}{\partial x_3}, \end{equation}
the first and the third components can be seen as vortex-turning and the second component is the vortex-stretching.
We also note that because the vorticity field has only one non-zero component, the only equation for the transport of vorticity is given by
\begin{equation} \frac{\partial\omega}{\partial t} +u\frac{\partial\omega}{\partial x} + v\frac{\partial\omega}{\partial y} = \frac{1}{Re} \left(\frac{\partial^2\omega}{\partial x^2}+ \frac{\partial^2\omega}{\partial y^2}\right). \tag{1.2} \end{equation}
Where $Re$ is the Reynold’s number of the flow.
Stream function
To remove the implicit dependency on the velocity field from the vorticity equation, we introduce a vector-valued stream function $\boldsymbol{\psi}$. We will now show that for 2D flows this is in fact a scalar function. Using the definition of the stream function, we have
\begin{equation} \boldsymbol{u} = \nabla\times\boldsymbol{\psi}, \qquad u_i = \varepsilon_{ijk}\frac{\partial \psi_k}{\partial x_j}, \end{equation}
where the only two non-zero components of the velocity field are
\begin{equation} u_1 = \varepsilon_{123}\frac{\partial \psi_3}{\partial x_2}=\frac{\partial \psi_3}{\partial x_2}, \qquad u_2 = \varepsilon_{213}\frac{\partial \psi_3}{\partial x_1}=-\frac{\partial \psi_3}{\partial x_1}. \end{equation}
With $\varepsilon_{ijk}$, the Levi-Civita permutation symbol. Thus only one component of the stream-function is non-zero, and it can be seen as a scalar field $\psi$, with the following relationship to the velocity field
\begin{equation} u = \frac{\partial \psi}{\partial y}, \,\,\,\, v = -\frac{\partial \psi}{\partial x}. \end{equation}
We can substitute these relation into the vorticity equation (1.2), giving
\begin{equation} \frac{\partial\omega}{\partial t} +\frac{\partial \psi}{\partial y}\frac{\partial\omega}{\partial x} - \frac{\partial \psi}{\partial x}\frac{\partial\omega}{\partial y} = \frac{1}{Re} \left(\frac{\partial^2\omega}{\partial x^2}+ \frac{\partial^2\omega}{\partial y^2}\right). \tag{1.3} \end{equation}
A very useful property of the stream function is that is existence guarantees the flow to be solenoidal (satisfies continuity). Indeed, substitution of the definition of the stream function into the continuity equation gives
\begin{equation} \nabla\cdot\boldsymbol{u} = \nabla\cdot(\nabla\times\boldsymbol{\psi})\equiv 0. \end{equation}
(1.3) still has 2 unknowns, $\psi$ and $\omega$, fortunately we can build a Poisson equation for the vorticity by substituting the velocity components, in terms of the stream function, in the definition of the only non-zero component of the vorticity
\begin{equation} \omega_{i}=\varepsilon_{ijk}\frac{\partial u_k}{\partial x_j} \qquad \rightarrow \qquad \omega =\omega_{z}=\frac{\partial v}{\partial x} - \frac{\partial u}{\partial y} \end{equation}
giving
\begin{eqnarray}
\omega =-\frac{\partial }{\partial x}\frac{\partial \psi}{\partial x} - \frac{\partial }{\partial y}\frac{\partial \psi}{\partial y} &=& -\frac{\partial^2 \psi}{\partial x^2} - \frac{\partial^2 \psi}{\partial x^2},\nonumber
-\omega&=&\frac{\partial^2 \psi}{\partial x^2} + \frac{\partial^2 \psi}{\partial x^2}.
\tag{1.4}
\end{eqnarray}
Equation (1.3) together with (1.4) can be solved to simulate the transport of a vorticity field.
Numerical method
Spectral collocation method
For periodic problems, such as the one of homogeneous isotropic decaying turbulence in a periodic domain, collocation methods using trigonometric polynomial expansions are unmatched in terms of accuracy and precision. However, they tend to be an order of magnitude more expensive (computationally) when compared to high-order finite difference schemes. Fortunately, when using trigonometric basis functions, the use of Fast Fourier Transform (FFT’s) routines allows for a reduction in the computational time. We describe here the implementation of such a method to solve (1.3) and (1.4).
We define the forward Fourier transform of a discrete field $u$ as (transforming from Fourier to physical space), following San et al.
\begin{equation} u_{i,j} = \sum_{m=-\frac{N_x}{2}}^{\frac{N_x}{2}-1}\sum_{n=-\frac{M_y}{2}}^{\frac{M_y}{2}-1}\tilde{u}_{m,n}e^{\boldsymbol{i}\left( \frac{2\pi m}{L_x} x_i + \frac{2\pi n}{L_y}y_j \right)}, \tag{2.1} \end{equation}
with its opposite transform, the backward Fourier transform (transforming from physical to Fourier space)
\[\tilde{u}_{m,n} = \frac{1}{N_x N_y} \sum_{i=0}^{N_x-1} \sum_{j=0}^{N_y-1} u_{i,j} e^{\boldsymbol{-i} \left( \frac{2\pi m}{L_x} x_i + \frac{2\pi n}{L_y}y_j \right)}.\]We note here that the transforms are normalised, a forward, followed by a backward transform recover the initial discrete field. In this case we have chosen to normalise the backward transform. The wave numbers are defined as
\begin{equation} k_x = \frac{2\pi m}{L_x}, \qquad k_y = \frac{2\pi n}{L_y}. \end{equation}
The natural ordering of Fourier coefficients is as shown in (2.1), however, FFT routines organise them in a different way, for a reason of algorithm efficiency
\begin{equation} k_x = \left[0, 1, \cdots, \frac{N_x}{2}-1, -\frac{N_x}{2}, \cdots, -2, -1 \right], \end{equation}
for an even number of grid points.
The $N_x$ discrete collocation (grid) points are uniformly space in our $[L_x, L_y]$ domain as
\begin{equation} x_i = \frac{iL_x}{N_x} ,\qquad y_i = \frac{iL_y}{N_y}, \end{equation}
with $i=0, 1, \cdots, N_x/N_y$. Because the problem is periodic, $x_0 = x_{N_x}$, we do not include the last grid point in the simulations, as collocation methods using periodic basis functions automatically impose the periodicity on the problem.
The high precision of the spectral collocation method comes from its ability to threat spatial derivatives. By transforming a discrete physical field to Fourier-space, what would otherwise be done using a differential scheme (truncated to a certain accuracy), derivatives are evaluated by multiplying the Fourier coefficients by the corresponding complex wave number, for example, the $n^{th}$ $x$-derivative of a discrete field $u$ is given by
\begin{equation} \frac{\partial^{(n)} u_{i, j}}{\partial x^{(n)}} = \sum_{m=-\frac{N_x}{2}}^{\frac{N_x}{2}-1}\sum_{n=-\frac{M_y}{2}}^{\frac{M_y}{2}-1}\tilde{u}_{m,n}(\boldsymbol{i}k_x)^{(n)}e^{\boldsymbol{i}\left( \frac{2\pi m}{L_x} x_i + \frac{2\pi n}{L_y}y_j \right)}, \end{equation}
this is the power of spectral collocation methods. The only errors associated with this operation are the interpolation and truncation errors \cite{spectral}, which are much smaller than the finite-difference equivalent.
Applying these operators to the vorticity transport equation result in a transport equation for the discrete Fourier coefficients
\[\frac{\partial\tilde{\omega}_{m,n}}{\partial t} + (\boldsymbol{i}k_y\tilde{\psi}_{m,n}\circ\boldsymbol{i}k_x\tilde{\omega}_{m,n}) - (\boldsymbol{i}k_x\tilde{\psi}_{m,n}\circ\boldsymbol{i}k_y\tilde{\omega}_{m,n}) = \frac{1}{Re}\left[\left(-k_x^2 - k_y^2\right)\tilde{\omega}_{m,n}\right]\]where the $(\cdots\circ\cdots)$ operator represents a convolution sum. Treating of this term in Fourier space involves solving triad interactions, this is very expansive, $O(N^2)$. In the pseudo-spectral approach, this term is treated in physical space with the help of the convolution theorem, which reduces the cost to $O(45/4N\log_2 (3/2N))$.
Aliasing
To prevent high frequencies modes of being falsly represented on the discrete grid dealiasing is employed. Here we use $3/2$ rule to pad the wave number during the transforms. Instead of using the inverse FFT with $N$ points, we use $M = 3/2N$ points. The new Fourier coefficients are zero-padded (Canuto et al.), that is
\[\begin{split} \tilde{\omega}_{m, n} &=& \tilde{\omega}_{m, n}, \quad\quad |m|\le N_x, \quad |n|\le N_y,\\ \tilde{\omega}_{m, n} &=& 0 \quad\quad\quad\quad |m|> N_x, \quad |n|> N_y. \end{split}\]Once we have obtained the two terms in the convolution sum in physical space via the backward transform and using $M$ points, we simply proceed to a multiplication. The result is then transformed back in Fourier space using the forward transform, still with $M$ points. We then discard all modes whose wave numbers are greater than $N_x$ and $N_y$. In summary, the convolution sums are treated as
\[(\boldsymbol{i}k_y\tilde{\psi}_{m,n}\circ\boldsymbol{i}k_x\tilde{\omega}_{m,n}) = \left[\mathcal{F}_{M}\left(\mathcal{F}^{-1}_{M}(\boldsymbol{i}k_y\tilde{\psi}_{m,n})\mathcal{F}^{-1}_{M}(\boldsymbol{i}k_x\tilde{\omega}_{m,n})\right)\right]_{N}\,,\]where \(\mathcal{F}_{M}\) represent a Fast Fourier Transform using $M$ points, but we are ultimately interested only in $N$ of them, and the remaining are discarded.
def _add_convection(self):
"""
Convective term. To prevent alliasing, we zero-pad the array before
using the convolution theorem to evaluate it in physical space.
"""
# initialize padded arrays
j1f_padded = np.zeros((self.mx,self.mk),dtype='complex128')
j2f_padded = np.zeros((self.mx,self.mk),dtype='complex128')
j3f_padded = np.zeros((self.mx,self.mk),dtype='complex128')
j4f_padded = np.zeros((self.mx,self.mk),dtype='complex128')
# populate
j1f_padded[self.padder, :self.nk] = 1.0j*self.kx[:self.nk ]*self.psih[:,:]
j2f_padded[self.padder, :self.nk] = 1.0j*self.ky[:, np.newaxis] *self.wh[:,:]
j3f_padded[self.padder, :self.nk] = 1.0j*self.ky[:, np.newaxis]*self.psih[:,:]
j4f_padded[self.padder, :self.nk] = 1.0j*self.kx[:self.nk ] *self.wh[:,:]
# backward transform
j1 = np.fft.irfft2(j1f_padded, axes=(-2,-1))
j2 = np.fft.irfft2(j2f_padded, axes=(-2,-1))
j3 = np.fft.irfft2(j3f_padded, axes=(-2,-1))
j4 = np.fft.irfft2(j4f_padded, axes=(-2,-1))
# forward transform
jacpf = np.fft.rfft2(j1*j2 - j3*j4, axes=(-2,-1))
# this term is the result of padding, padder allows for easier sclicing
self.dwhdt[:,:] = jacpf[self.padder, :self.nk]*self.pad**(2)
A note on FFTs in Python
These examples use the strandard numpy FFT routines. Those are highly inefficient. A much better FFT library is pyFFTw, but this increase in speed comes at the cost of more complexity. In brief, arrays that will be transformed must be aligned in memory and this requires modifying their content instead of assigning them new values every time we update their values, which explains the dwhdt[:,:]
part. For an example on how to use pyFFTw see here.
Stream-function
The Fourier coefficients of the stream function are obtained by the explicit relationship between vorticity and stream-function
\[-\tilde{\omega}_{m, n} = (-k_x^2 - k_y^2)\tilde{\psi}_{m,n} \qquad\rightarrow\qquad \tilde{\psi}_{m,n} = \frac{\tilde{\omega}_{m, n}}{(k_x^2 + k_y^2)}.\]We note here that the mode $\tilde{\psi}_{0,0}$ is the results of a division by zero and represents the mean value of $\psi$. To avoid issues with round-up errors accumulating and poluting the solution, it is explicitly set to zero each computation of the stream-function.
def _get_psih(self):
"""
Spectral stream-function from spectral vorticity
"""
# k2I stores inverse of k^2, with zero at [0, 0]
self.psih[:,:] = self.wh[:,:] * self.k2I[:,:]
Time integration
Using spectral operators for the spatial derivatives ensures that the discretisation error of spatial terms is kept to a minimum. In order to keep the global discretisation errors low, high-order temporal integrator are required. We implement both a third and a fourth-order Runge-Kutta method. The third-order TVD Runge-Kutta method is defined as~(spectral
\[\begin{split} \tilde{\omega}^{(1)} &= \tilde{\omega}^{n} + \Delta t \mathcal{L}(\tilde{\omega}^n),\\ \tilde{\omega}^{(2)} &= \frac{3}{4}\tilde{\omega}^{n} + \frac{1}{4}\tilde{\omega}^{(1)} +\frac{1}{4}\Delta t\mathcal{L}(\tilde{\omega}^{(1)}),\\ \tilde{\omega}^{n+1} &= \frac{1}{3}\tilde{\omega}^n + \frac{2}{3}\tilde{\omega}^{(2)} + \frac{2}{3}\Delta t\mathcal{L}(\tilde{\omega}^{(2)}), \end{split}\]where $\mathcal{L}(\tilde{\omega}_n)$ represents all the spatial operators of the transport equation of the Fourier coefficients. Another scheme of order $s$ (for linear problems) that is also TVD and can be easily implemented is
\[\begin{split} \tilde{\omega}^{(1)} &= \tilde{\omega}^{n} + \frac{1}{s}\Delta t \mathcal{L}(\tilde{\omega}^n),\\ \tilde{\omega}^{(2)} &= \tilde{\omega}^{n} + \frac{1}{s-1}\Delta t \mathcal{L}(\tilde{\omega}^{(1)}),\\ \cdots &\\ \tilde{\omega}^{n+1} &= \tilde{\omega}^n + \frac{1}{1}\Delta t\mathcal{L}(\tilde{\omega}^{(s)}). \end{split}\]Applying the time integration to the fourier coefficients allows us to save two transform per time-steps.
def update(self, s=3):
"""
Explicit low-storage S-order Runge-Kutta method from
Jameson, Schmidt and Turkel (1981).
Input:
s : float
- desired order of the method, default is 3rd order
"""
# initialise
self.w0 = self.wh
for k in range(s, 0, -1):
# invert Poisson equation for the stream function
self._get_psih()
# get convective forces (resets dwhdt)
self._add_convection()
# add diffusion
self._add_diffusion()
# step in time
self.wh = self.w0 + (self.dt/k) * self.dwhdt
self.time += self.dt
self.it += 1
self._cfl_limit()
Adaptive time-step
The time-step is adjusted based on the Courrant condition in the worst cell of the domain. For a third-order Runge-Kutta scheme, the maximum CFL number is $\sqrt{3}$. This gives the following time-setp, for stability
\begin{equation} \Delta t = \frac{\sqrt{3}}{D_c + D_{\mu}}, \end{equation}
where $D_c$ and $D_{\mu}$ are the convective and diffusive velocity scales
\[\begin{split} D_c &= \max\left(\pi\left(\frac{1+\vert u\vert}{\Delta x} +\frac{1+\vert v\vert}{\Delta y} \right)\right),\\ D_{\mu} &= \max\left(\pi^2\left(\frac{1}{\Delta x^2} + \frac{1}{\Delta y^2}\right)\right). \end{split}\]These are derived from the advection-diffusion equation (which is very similar to (1.3)), by writting it as a first order ODE and applying Fourier transform to the original equation. The convective and diffusive time-scales are then obtained by considering the worst case in the domain.
def _cfl_limit(self):
"""
Adjust time-step based on the courant condition
"""
self.get_u()
self.get_v()
Dc = np.max(np.pi * ((1.+abs(self.u)) / self.dx + (1.+abs(self.v)) / self.dy))
Dmu = np.max(np.pi**2*(self.dx**(-2) + self.dy**(-2)))
self.dt = np.sqrt(3.) / (Dc + Dmu)
Validation
Taylor-Green vortex
We validate the numerical method described above using the Taylor-Green vortex, a known solution to the Navier-Stokes equation. Expressed in its 2D vorticity formulation, it reads
\begin{equation} \omega^e(x, y, t) = 2\kappa\cos(\kappa x)\cos(\kappa y)e^{-2\kappa^2t/Re}, \tag{4.1} \end{equation}
where $\kappa=4$ is the number of vortices in each direction and $Re$ is the Reynolds number of the flow and is set to 1.0 for those simulations (dissipation is important in this flow).
flow = Fluid(128, 128, Re=1.) # generate a 128x128 grid
flow.init_solver()
flow.init_field(TaylorGreen)
finish = 0.1
start_time = t.time()
# loop to solve
while(flow.time<=finish):
# update using RK
flow.update()
# print every 100 iterations
if (flow.it % 100 == 0):
print("Iteration %d, time %f, time remaining %f. TKE: %f, ENS: %f" %(flow.it,
flow.time, finish-flow.time, flow.tke(), flow.enstrophy()))
end_time = t.time()
print("\nExecution time for %d iterations is %f seconds." %(flow.it, end_time-start_time))
and you should get the following results
Iteration 100, time 0.020564, time remaining 0.079436. TKE: 0.180244, ENS: 23585.873276
Iteration 200, time 0.041258, time remaining 0.058742. TKE: 0.129470, ENS: 16941.804099
Iteration 300, time 0.061970, time remaining 0.038030. TKE: 0.092971, ENS: 12165.670770
Iteration 400, time 0.082698, time remaining 0.017302. TKE: 0.066744, ENS: 8733.753359
Execution time for 484 iterations is 11.454845 seconds.
We use the $L_2$-norm of the error between the exact solution and the simulation to quantify the error
\[L_2 = \sqrt{\frac{1}{N_xN_y}\sum_{i=1}^{N_x} \sum_{j=1}^{N_y}|\omega^{e}_{i, j} - \omega_{i, j}|^2},\]and the $L_\infty$-norm
\[L\infty = \max{\vert \omega^{e}_{i, j} - \omega_{i, j} \vert}.\]# get final results
flow.wh_to_w()
w_n = flow.w
# exact solution
w_e = TaylorGreen(flow.x, flow.y, Re=1, time=flow.time))
# error norms
print("L2-norm of the error in the Taylor-Green vortex on a %dx%d grid is %e." % (flow.nx, flow.ny, L2(w_e - w_n)))
print("Linf-norm of the error in the Taylor-Green vortex on a %dx%d grid is %e." % (flow.nx, flow.ny, Linf(w_e - w_n)))
This is pretty good!
L2-norm of the error in the Taylor-Green vortex on a 128x128 grid is 4.829892e-13.
Linf-norm of the error in the Taylor-Green vortex on a 128x128 grid is 9.661161e-13..
Decaying Turbulence
We can also generate a random vorticity field, following J. C. McWilliams whose initial conditions are a Gaussian random realization for each Fourier component $\tilde{\psi}$
\[\tilde{\psi}_{ij} \leftarrow \mathcal{N}(\mu, \sigma^2),\]where at each vector wavenumber the ensemble variance is proportional to the scalar wavenumber function
\[\vert\psi\vert^2 = \kappa^{-1}\left[1 + \left(\frac{\kappa}{\kappa_0}\right)^4\right]^{-1},\]where $\kappa$ is the wavenumber magnitude. This spectrum is broad banded and peaks around $\kappa_0$ (set to $\kappa_0 = 6$ in the following). An aplitude factor is chosen such that the kinetic energy (4.2) is equal to 0.5 initially.
This field can simply be generated by passing the "McWilliams"
function to the flow field initialization function.
flow = Fluid(128, 128, Re=100.)
flow.init_solver()
flow.init_field(McWilliams)
Energy Spectrum
For homogeneous turbulence, we can define the energy spectrum to be a function of the stream-function
\begin{equation} E(k, t) = \sum_{k-\Delta k \le |\boldsymbol{ k}| \le k+\Delta k} \frac{1}{2} k^2 |\tilde{\psi}(\boldsymbol{ k}, t) |^2, \tag{4.2} \end{equation}
where $\tilde{\psi}$ is readily obtained from the known vorticity field $\tilde{\omega}$. Each contribution to the final energy spectrum consist of the sum of all the energy contribution at each wavenumber falling within a prescribed bin size, or spectral band, $\Delta k$. The default number of bin used is 200, and the spectral band is defined as the Nyquist frequency devided by the number of bins.
Results
References
[1] C. Bailly, G. Comte-Bellot. Turbulence. Springer Series in: Experimental Fluid Mechanics. 2015.
[2] MIT. Marine Hydrodynamics Lecture 9. MIT Marine Hydrodynamics lectures notes. 2005.
[3] O. San, A. E. Staples. High-order methods for decaying two-dimensional homogeneous isotropic turbulence. Computer & Fluids 63. p: 105–127. 2012.
[4] C. Canuto, M. Y. Hussaini, A.Quarteroni, T. A. Zang. Spectral Methods in Fluid Dynamics. Springer Series in: Computational Physics. 1988.
[4] J. C. McWilliams. The emergence of isolated coherent vortices in turbulent flow. Journal of fluid mechanics 146. p: 21–43. 1984.
2020
Compact Schemes for the Poisson Equation
This notebook demonstrates how to solve Poisson’s equation using Compact finite-difference schemes.
APS-Division of Fluid Dynamics
73rd Annual Meeting of the APS Division of Fluid Dynamics
Pseudo-spectral method for 2D Turbulence
Mathematical Formualtion
My First Post
Code Snippets


Toggle navigation
Transcriptulator
Raw Input
Put Your Transcript Here
### Rebecca's gestural pseudo-coding [33:33] Rebecca: and then my thinking at least, is you should be able to, um, say that "star p of i" /mmhmm/ equals, uh, the title, and then you just do i++, so then it’ll {{move to the next one}} ![makes looping gesture with left hand][1] /OK/ [34:00] Rebecca: and you just keep {{saving each of the pointers}} ![left hand makes horizontal chops in the air, like rungs down a ladder][2] [1]: images/rebecca1.jpg [2]: images/rebecca2.png{% endraw %}
Toggle Syntax Cheat Sheet
Live Preview
What you get


Curves
Curves are used to animate properties. They are typically set up once and shared across many assets, such as particle effects. Modifying a curve will affect all resources that use it. Therefore it is advisable to create common curves early during development.
The curve can be sampled along the X-axis. This is frequently used to sample a value over time, but other parameters may be used for the lookup as well. If a curve is supposed to be used in a looping fashion, the first and last control point have to be set up to match.
Curve Editor
To add a control point, double click where you want to insert one.
View
- Right click and drag to pan the view.
- Use the mouse wheel to zoom in and out.
- Hold
Shift
orCtrl
to zoom the view only along the X axis or the Y axis.
- Hold
- Press
Ctrl + F
or select Frame from the context menu to frame the view either on the selected control points, or the entire curve, when no point is selected.
Selection
- Left click a point to select it.
- Press
ESC
to clear any selection. - Drag a rectangle to select multiple points.
- Holding
Shift
always adds points to the selection. - Holding
Alt
always removes points from the selection. - Holding
Ctrl
toggles the selection of a control point. - Distinguishing between add and remove is particularly useful when changing the selection by dragging a rectangle.
- Left click and drag selected points to move them around.
- Press
Shift
after you started dragging, to limit modifications to either left/right or up/down. The axis along which you moved the control points the most, before you pressedShift
, determines which axis gets limited. - Drag the handles at the edges of the selection rect, to scale the selected points.
Tangents
Every control point has two tangents to determine the slope of the curve coming from the left into the point and going out to the right of the point. Each tangent can use one of four modes. Some modes are fully automatic, some allow you to edit the tangents. To not clutter the UI, tangents that can be edited are only shown for selected control points. To change the mode, select a control point, open the context menu and choose from Left/Right/Both Tangents > ....
- Auto: The default mode. Automatically configures the tangents to create a smooth curve.
- Bezier: Gives you full control over the tangents. Both slope and length of the tangents will affect the curve.
- Fixed Length: Although you can change both slope and length of the tangents, only the slope affects the curve. This is often easier to use than Bezier.
- Linear: This mode deactivates any curvature. Allows you to make hard corners.
Link / Break Tangents
By default adjusting one tangent at a control point, mirrors the change over to the other tangent. That's because the two tangents are linked. If you want the tangents to be independent of each other, you can break the link between the tangents. Use the context menu to do so.
Looping Curves
The rightmost control point determines the overall length of the curve. As you can see, the editor repeats the display of the curve at that point, overlayed with a grey pattern. This enables you to see how the curve would look when used in a looping fashion.
To make a curve loop nicely, open the context menu and select Curve > Loop: Adjust First/Last Point. This will modify either the first or the last control point in the curve to match up with the respective other point. Make sure that the two control points use the same tangent mode. You may need to switch to Bezier or Fixed Length tangents to make the curvature match perfectly.
Curve Presets
In the context menu under Presets you will find a number of presets for commonly used curves. You can also save the current curve as a preset. You can save presets anywhere, but as long as you save it under the path Editor/Presets/Curves (in any data directory), it will automatically show up in the context menu. You can also use sub-folders to organize presets, as folders will introduce sub-menus.


Currently, I’m based in Manchester, working on interesting UX/UI projects.
For the last two years, I’ve been living in the UK, working with variety of clients, helping them get the best from the web. I was given the opportunity to work on some great project, applying the user-centred design methods. My Master’s degree in a Computer Science, and a working experience as a Front-End developer have given me a deeper insight in a full process, from the very idea of a project to the final implementation.
Focusing on users and their needs
One of my favourite projects so far is a student accommodation platform.
If you want to find out more about me and my projects, please send me an e-mail on: jelena.herceg.personal@gmail.com.


{% extends "base.html" %} {% block header %}
Choose a Start Point and an End point. Add walls(optional) by clicking on the respective button
and holding you mouse button down while draggin it across the grid. Releasing the button will stop generating walls.
Choose the Find Path button to start discovering neighbor nodes until the Ending Node is found and the shortest
path back to the Start Node is generated! You can use the Clear button to clear the grid.


VacuumGantt supports intervals or one-time events
Customize your VacuumGantt to meet your needs using JSON object. Set locale date format, favourite colors and much more...
Using mobile, tablet or pc? VacuumGantt automatically adjusts to the size of the device screen
Plugin has been tested with IE9+, Firefox 24, Chrome 29, Safari 5+ (iOS 5+)


Compare the Interface specifications for the List and Sorted List Abstract Data Types then answer the following questions. The relevant interface files are provided via the first page of the module - Introduction to sorted lists.
Which of the following is not true?
SortedListInterface includes the method definition, T replace(int givenPosition, T newEntry), while ListInterface does not
- ListInterface includes the method definition, add(int newPosition, T newEntry), while SortedListInterface does not
- ListInterface includes the method definition, T replace(int givenPosition, T newEntry), while SortedListInterface does not.
- SortedListInterface includes an additional remove method definition, boolean remove(T anEntry).
- The SortedListInterface includes a new method, int getPosition(T anEntry).
There are no hints for this question


Phi Estimation of Silty Sand using SPT-N60 and Grain Size Analysis
In this study, a Machine Learning model is produced to estimate the angle of internal friction (Phi) of Sility Sand (SM) from SPT-N 60
and the particle size of the soil sample.
176 sample of Silty Sand from Joydevpur- Mymensingh- Jamalpur section in Bangladesh were used.
MLR, SVM and ANN were considered during the model preparation where SVM which is used in this web app have shown better performance.
The total features considered in the model are SPT-N60, Depth of Sample Collection, Sand(%), Silt(%), Clay(%), D10, D30, D60, Cu, and Cc, and the optimum features are selected through feature selection.


|
|
| Iraq ponders amnesty for insurgents |
|
|
Less than a week after taking power, Iraq's prime minister is considering offering amnesty to insurgents and could extend it to those who killed American troops, in an apparent bid to lure Saddam Hussein's loyalists from their campaign of violence.
|
| Independence Day 2004 |
|
|
Special Report: Members of the 91st Engineer Battalion's Alpha Company were trying to fix a broken armored personnel carrier in Baghdad's Amariyah neighborhood last month when three teenagers approached. One boy wore a "Titanic" T-shirt; another wore a September 11 shirt. It was the third boy who spoke. |
| At home, Americans remain fiercely patriotic |
|
|
Americans are intensely patriotic this July Fourth, focused on flag and country.
It's there in the poll numbers. A Gallup survey of more than 1,000 people released earlier this year, for example, found that 91 percent of us said we're "extremely" or "very" patriotic. |
Militants claim to behead Marine
A radical Islamic group claimed to have beheaded a captured U.S. Marine yesterday, while six Iraqi national guardsmen and a second Marine were killed on the deadliest day since Iraq received its new sovereignty. |
Black leaders back Cosby's straight talk
Black leaders and members of Congress are embracing comments by Bill Cosby illustrating the lack of social responsibility from some in the black community, but said the entertainer's charges are nothing new. |
|
|
|
|
|


海滩,海浪,阳光,浪漫的情怀
Anne Boleyn's ghost also appears in the grounds of blickling hall dressed all in white, seated in a ghostly carriage that is drawn
Pirates of the Caribbean: On Stranger Tides is an upcoming 3-D fantasy action-adventure film. It is the fourth film in the Pirates o..
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature Cras justo odio, dapibus ac facilisis in.
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature is quite a unique
Queen anne boleyn is one of the most enduring ghosts at the tower of London. Queen Anne is buried
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature Boleyn
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature
Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature
Having obtained his divorce and married Anne, the King's most desire was for Anne.


home
contact details
MGW Contact Details
email<EMAIL_ADDRESS>Phone: +353 1 888 2233
Post: 198 Main Street, Dublin, Ireland


Spine Event Engine is a framework for building cloud applications and transforming EventStorming into a working domain model code.
Our goal is to free developers from writing boilerplate code as much as possible. The primary language of our solution backend is Java. Client libraries are available for Java, JavaScript, and C++.
Spine promotes strong typing of all parts of a business model. You don't have to deal with JSON.
The model is defined and maintained in Protobuf. The code is automatically generated for all the languages of your project, as you update the model.
The framework promotes writing storage- and platform-agnostic code. You can start with JDBC and later switch to Google Cloud Platform Datastore by changing just a few lines of code.
With Protobuf support, a model can be extended preserving backward compatibility with clients running older code.
Commands, events, query results, entity states, and other data are immutable. This makes them automatically thread-safe, and thus freely shared or referenced.
Permissive Apache License allows using the framework in closed-source projects. You are also welcome to contribute to our framework development.
Constraints defined in a business model are automatically checked for commands, events, and entity states using our validation approach.
Transforming a single-tenant application into
a multi-tenant one requires a few lines of code. You don't have to introduce
tenantId
parameters for all the calls.
We started developing our framework after completing several CQRS/ES-related projects. This is when we got our hands-on knowledge in manual creation of commands, events, message handlers, delivering messages and data to web and mobile clients.
Using existing CQRS/ES frameworks made us compromise on a number of things, including type safety, immutability, writing conversion code for inter-platform communications, and others. So in June 2015 we decided to build a tool both for us and software developers who may have the same issues.


Hexed is delivered by Virginia Barnes, Gabriel Wild, Derek Li, TJ Samuels, and Zehao Qin.
Please navigate to our Github repository if you would like to contribute, provide feedback, or current issues.
Hexed currently only offers optimized feature for clients on PC. Give us a star to stay updated for latest features.


Can robots do my homework?
Hacking Online Foreign Language Tools
All research shown here is ethical because no active attacks are performed on Duolingo or Yabla servers. All exploits are performed locally and do not modify http requests at all when compared to normal usage of either services. All data used in the following exploits was sent intentionally to clients of both services. Additionally, tools created for this research were never used on official assignments that counted towards grades.
After a brief examination of the network traffic used by the Yabla online learning tool, it became apparent that it was incredibly easy to exploit the method by which Yabla loaded transcripts on the frontend in order to automate the completion of their games. A proof of concept chrome extension was written to take advantage of this exploit. Other online language tools such as Duolingo were evaluated, but similar exploits were not found.
Recently, my Spanish teacher announced that the class would begin to receive upwards of three Yabla listening activities per week. The class has also been subject to Duolingo quotas, where we are graded on completing hundreds of lessons in a given semester. Deciding to take advantage of some software development experience, I decided to examine if I could complete these assignments without spending vast amounts of time listening to native Spanish speakers repeatedly or typing for hours on end.
Duolingo is a much newer and much more advanced online foreign language tool. It is written in React and. It is quick at makes use of animations. Duolingo is a much more complicated application than Yabla.
I began be examining the possibility of automating the answering of multiple choice questions.
Yabla uses a PHP backend and a loose policy of one html page per application view. A detailed
analysis of XHR traffic was not necessary as almost all data and code to run the game is
provided within the first load of the php page player_cdn.php
. It would appear that
dynamic content is provided through global javascript variables populated in a script tag at the
top of the page by PHP. A quick search of the first lyric of the song revealed the transcript
information in the global javascript variable CAPTIONS
.
It is worth noting that upon opening the development console, Duolingo advertises that they are hiring software engineers.
It is apparent immediately that Duolingo utilizes a Single Page Application (SPA) architecture, so I choose to focus analysis on only XHR requests.
| Type | URL | Method | Status | Price |
|---|---|---|---|---|
| XHR | 2x Requests to ?https://api.mixpanel.com/track/?data={large base64 encoded
string} |
GET | 200 | The data parameter in the URL contained base64 encoded key-value paired tracking data. I found it interesting Duolingo was tracking user interaction in a very detailed manner; however, I didn’t find the information very interesting. It did contain sensitive-looking user ids. It seems to me that this could be done much more efficiently by posting a JSON blob. |
| XHR |
2x Requests to https://ljknv3sref.execute-api.us-east-1.amazonaws.com/prod/events
|
POST | 200 | This appears to be an additional tracking endpoint that, in fact does POST a JSON blob. Duolingo is likely experimenting with two different user-interaction tracking systems. |
| XHR |
https://www.duolingo.com/sessions/394864751773?name=Basics-1&language=es&lesson_number=3&type=lesson&speak_capable=true&web_speech_enabled=true&kc_strength_model_version=2&client_grading_data_version=2&_=1489702221619
|
GET | 200 | This request contained a very large amount of information regarding the lesson including references to “surface_forms,” “lexemes,” and other information. See below for a more detailed analysis of this data. |
| XHR |
https://www.duolingo.com/log_grading_result
|
POST | 200 | This endpoint is called whenever a question is answered. It accepts a lengthy form data input and returns only a status code. See below for detailed analysis. |
The response to the URL
https://www.duolingo.com/sessions/394864751773?name=Basics-1&language=es&lesson_number=3&type=lesson…
Appeared to contain all of the information relevant to the lesson. The response included a very
large amount of information regarding the lesson including all questions, which they call
session_elements.
A field titled solution_keys
was present; however,
they did not appear to match any data currently held in the browser. This could be a hash of the
correct solution or a database key. However, the correct answer is not held in obvious fashion
in the session information.
The property corresponding to the correct answer may not be immediately apparent from reading this data. A further review of traffic and code makes it far more clear. In this capture, the user is asked to translate “the bread” to Spanish. The correct answer is “el pan.” The correct answer was provided.
In this capture the user is asked to translate “the water” to Spanish. The correct answer is “el agua.” An incorrect answer of “el pan” was provided.
Notice that the result appears to be graded before being sent to the server. It would appear that Duolingo is processing the grading on the frontend before sending it to the backend for logging. This opens the doors for a potential exploit. However, it raises the question of which property is being used to validate the phrase.
In order to answer these questions, I decided to examine the code. I downloaded the javascript
file that appeared to contain the application from
http://d7mj4aqfscim2.cloudfront.net/proxy/js2/230720168c0b82eedd46-duolingo.js
.
Using free
online tools, I de-minified the code. The code appeared to be only partially obfuscated. As a
result, I was able to read all original function names. The code has some interesting features.
For instance, all instances of “true” have been replaced with “!0” and “!1” for “false.” This
was presumably done by a build engine to compress the file. The /log_graded_result endpoint is
called from the following function logGradedSolution():
These issues could be mitigated by creating a backend endpoint to validate question responses and ensuring that the correct answer is not passed to the client. If the backend validates responses, there is no way for the client to know what the correct response is until the user figures it out.
I decided to analyze the video-based fill in the blank game for the purposes of this research because it appeared to be a unique challenge to exploit and offered the possibility of quick massive time savings for students using an automated tool. The objective of the game is to fill in blanks in transcripts of a song in order to practice Spanish listening skills. Compared to Duolingo, Yabla is a somewhat simplistic application.
Yabla uses a PHP backend and a loose policy of one html page per application view. A detailed
analysis of XHR traffic was not necessary as almost all data and code to run the game is
provided within the first load of the php page player_cdn.php
. It would appear that
dynamic content is provided through global javascript variables populated in a script tag at the
top of the page by PHP. A quick search of the first lyric of the song revealed the transcript
information in the global javascript variable CAPTIONS
.
As a result, the game can be exploited very easily into giving up the answers to a student or
automation tool. I created a proof of concept chrome extension that automatically plays the game
using content scripts in a chrome extension. First, the script acquires and parses the
transcript data by bypassing chrome's content script sandboxing by parsing the DOM content of
the script
tag. Then, it uses DOM manipulation to complete the blank textboxes
automatically.
See the source code listing of the proof of concept here: Yabla Helper Chrome Content Script
These issues could be mitigated by creating a backend endpoint to validate question responses and ensuring that the correct answer is not passed to the client. If the backend validates responses, there is no way for the client to know what the correct response is until the user figures it out.
(function YablaInject(document) {
//API
function levenshteinDistance(a, b) {
if (a.length == 0) return b.length;
if (b.length == 0) return a.length;
var matrix = [];
// increment along the first column of each row
var i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
var j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
Math.min(matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1)); // deletion
}
}
}
return matrix[b.length][a.length];
}
//Config
var SCRIPT_SEARCH_TERM = 'CAPTIONS';
var EVENT_LOOP_TIMEOUT = 2000;
var ALPHANUMERIC_REGEX = /[^A-Za-z_]/g;
//Find the script tag containing the captions
var query = document.getElementsByTagName('script');
var scriptContents;
for (var i = 0; i < query.length; i++) {
if (query[i].innerHTML.indexOf(SCRIPT_SEARCH_TERM) >= 0) {
scriptContents = query[i].innerHTML;
}
}
if (!scriptContents) return console.warn('YablaInject could not find Yabla script on this page',
scriptContents);
//Process the contents of the script tag to find the JSON blob representing the captions
//Find the line with the captions JSON
var lines = scriptContents.split(';');
var line;
lines.forEach(function (l) {
if (l.indexOf(SCRIPT_SEARCH_TERM) >= 0) {
line = l;
}
});
if (!line) return console.warn('YablaInject could not find a line with captions in this script',
line);
//Process the line
var captionJsonString = line.split('=')[1].replace(';', '').trim();
//Parse the JSON from the line
var CAPTIONS;
try {
CAPTIONS = JSON.parse(captionJsonString);
} catch (e) {
return console.error('Error parsing captionsJsonString', e);
}
if (!CAPTIONS) return console.warn('YablaInject could not find valid captions on this page',
CAPTIONS);
//Process the captions into readable transcript
var TRANSCRIPT, TRANSCRIPT_LINES, TRANSLATION_LINES, TRANSLATION, PROCESSED_TRANSCRIPT_LINES;
TRANSCRIPT_LINES = CAPTIONS.map(function (a) {
return a.transcript;
});
PROCESSED_TRANSCRIPT_LINES = CAPTIONS.map(function (a) {
return {
processed: a.transcript.replace(ALPHANUMERIC_REGEX, '').toLowerCase().trim(),
unprocessed: a.transcript
}
});
TRANSCRIPT = TRANSCRIPT_LINES.join('\n\n');
TRANSLATION_LINES = CAPTIONS.map(function (a) {
return a.translation;
});
TRANSLATION = TRANSLATION_LINES.join('\n\n');
//Dump the transcript to the console before doing anything funky
console.info('Dumping Yabla transcript for your reading pleasure...');
console.info('English: ', TRANSLATION);
console.info('Spanish: ', TRANSCRIPT);
//DOM Manipulation loops
function loop() {
var question_wrap = document.getElementsByClassName('question_wrap')[0];
var question_answer = document.getElementById('cloze_answer');
if (question_wrap&&question_answer&&(question_answer.value==='')) {
var QUESTION_TEXT_BAD_WORDS = ['slow', 'replay', 'submit', 'answer', 'next', 'question']
var processedQuestionText = question_wrap.textContent.replace(ALPHANUMERIC_REGEX,
'').toLowerCase().trim();
QUESTION_TEXT_BAD_WORDS.forEach(function (word) {
processedQuestionText = processedQuestionText.replace(word, '');
});
//Remove any complete lines of transcript from the processed line because a complete transcript
line
//Will never hold the answer
PROCESSED_TRANSCRIPT_LINES.forEach(function (processedTranscriptLine) {
processedQuestionText=processedQuestionText.replace(processedTranscriptLine.processed, '');
});
// //Sort transcript entries by closeness and remove dupes
var candidates = PROCESSED_TRANSCRIPT_LINES
.filter(function (item, pos) {
var index;
PROCESSED_TRANSCRIPT_LINES.forEach(function (a, p) {
if (a.processed === item.processed) index = p;
});
return index === pos;
})
.sort(function (a, b) {
return levenshteinDistance(a.processed, processedQuestionText)-levenshteinDistance(b.processed,
processedQuestionText);
});
var processedTranscriptLine = candidates[0];
//Find the missing word
var missingWords = [];
processedTranscriptLine.unprocessed.replace(/[,?;':.\\\/\(\)]/g,'').split(' ').forEach(function
(word) {
var processedWord = word.replace(ALPHANUMERIC_REGEX, '').toLowerCase().trim();
if (processedQuestionText.indexOf(processedWord)>=0) return;
if (missingWords.indexOf(processedWord)>=0) return;
missingWords.push(word);
});
var missingPhrase = missingWords.join(' ');
question_answer.value=missingPhrase;
}
//Another iteration
return setTimeout(loop, EVENT_LOOP_TIMEOUT);
}
//Start the loop
loop();
})(document);
See more at https://github.com/jake-billings/YablaHelper


Launguage selector
Are you in for a challenge?
Do you like gems?
Have you used a computer before?
Have you ever programmed before?
Do you have a lot of time to study?
Ruby!
Click here to see more info on Ruby
C#!
Click here to see more info on C#
Javascript!
Click here to see more info on Javascript
Better luck next time!
You probably should go over the basics of computers before you learn one of these languages.
See Answer!!!


Select up to 6 candidates and hit "Submit" in the My Votes box on top. Please contact<EMAIL_ADDRESS>with any questions.
drop csv file here or click to browse for file
View Profile


An HSV color picker widget for JavaScript, with a modern SVG-based user interface
Off
Rainbow
Hyperspace
Fireworks
Strobe
White
Color Cycle
Sleep Timer


JSON: JavaScript Object Notation.
JSON is a syntax for storing and exchanging data.
JSON is text, written with JavaScript object notation.
When exchanging data between a browser and a server, the data can only be text.
JSON is text, and we can convert any JavaScript object into JSON, and send JSON to the server.
We can also convert any JSON received from the server into JavaScript objects.
This way we can work with the data as JavaScript objects, with no complicated parsing and translations.
ver el link: a07JS-JSON - 01Intro_2.html
ver el link: a07JS-JSON - 01Intro_3.html
Since the JSON format is text only, it can easily be sent to and from a server, and used as a data format by any programming language.
JavaScript has a built in function to convert a string, written in JSON format, into native JavaScript objects: JSON.parse()
So, if you receive data from a server, in JSON format, you can use it like any other JavaScript object.


| Youtube Video | Channel Name | Video Name | Date Published |
|---|---|---|---|
| Meditative Mind | Root Chakra Healing Music | Published on Jun 1, 2017 | |
| Meditative Mind | SACRAL CHAKRA Healing Music | Published on Jun 3, 2017 | |
| Meditative Mind | Solar Plexus Chakra Healing Music | Published on Jun 4, 2017 | |
| Meditative Mind | Heart Chakra Healing Music | Published on Jun 5, 2017 |


The objects in cairo can roughly be divided into two types: reference-counted, opaque types like cairo_surface_t and plain structures like cairo_glyph_t. cairo_path_t and cairo_path_data_t are special cases and are treated separately in this appendix.
Refcounted opaque types all have a
..._reference()
function to increase the refcount by one and a
..._destroy()
to decrease the refcount
by one. These should not be exposed to the user of the language
binding, but rather used to implement memory management within
the language binding. The simplest way to do memory management
for a language binding is to treat the language binding object
as a simple handle to the cairo object. The language binding
object references the cairo object, and unreferences it when
finalized. This is the recommended method, though there are
a couple of caveats to be noted:
Equality won't work as expected. You can have two language
objects for the same cairo and they won't necessarily
compare equal. If the language allows customizing the
equality operation, then this is fixable by comparing
the underlying pointers. It also can be fixed by creating
at most one language object per cairo object, and
uniquifying via a pin table (a hash
table that goes from cairo object to language object).
For cairo_surface_t you can use also
cairo_surface_set_user_data()
instead of a separate pin table.
Derivation from the language object doesn't work because you can lose the language object while keeping the Cairo object. Code like:
public class MySurface (ImageSurface) { public MySurface (width, height) { super (Format.ARGB32, width, height); } public int get42 () { return 42; } } cr = Cairo(MySurface(width, height)); surface = cr.getTarget();
Can result in surface
containing an
ImageSurface
not a MySurface
.
This is not easily fixable without creating memory leaks,
and it's probably best to simply forbid deriving from the
language objects.
When a plain structure is used as a return value from cairo, this is done by passing it as a “out parameter”.
cairo_font_extents_t extents; cairo_font_extents (cr, &extents);
In a language binding, this should typically be treated as a return value:
FontExtents extents = cr.fontExtents ();
A language binding has a choice in how it implements the language objects for plain structures. It can use a pure language object with fields corresponding to those of the C structure, and convert from and to the C structure when calling cairo functions or converting cairo return values. Or it can keep a pointer to the C structure internally and wrap it inside a language object much like occurs for refcounted objects. The choice should be invisible to the user: they should be able to imagine that it is implemented as a pure language object.


In last week’s Productivity Tuesday, I covered the power of habit-based productivity approaches. Today, I’ll cover the two most foundational habits: planning and retrospectives.
Planning and Retrospectives are the simple practices of thinking forwards and backwards in time. Planning obviously entails outlining the activities required to reach an outcome. Retrospectives entail reflecting on how well you did towards a plan. Both operate on a specific timeframe, and ideally each planning session should have some form of retrospective.
Most people plan to some degree - setting daily to-do’s, new years resolutions, monthly goals - all are planning exercises. I’d guess that personal retrospectives aren’t as common (although I don’t have any empirical evidence outside of my own experience). I believe it’s the more important of the two practices.
A good plan has (a) specific timeframe and (b) clear outcomes. A good retrospective answers how well you did against your intention, and where there is opportunity to improve.
Planning and retrospectives are the foundational habits, and they create the space to reflect and plan for any additional personal improvements - whatever it may be.
I do some form of both on a daily, weekly, monthly basis.
On a daily basis, plans include to do’s - discrete tasks and habits I’m actively tracking (currently, daily reading, writing, and coding). A daily retrospective is very quick - marking completed discrete tasks, and tracking which habits I actually stuck to. I currently daily plans in Google Sheets, of all things, because it helps me track my to-do completion rate (to see how much I overcommit), and measure habit streaks (there are some great apps to do all this individually, but a spreadsheet let’s me customize and analyse easily).
On a weekly basis, planning and retrospective happens together, about 30 minutes per week. Plans are divided into 2 sections. Goals (groups of discrete tasks I need to complete) and the habits I want to either start, improve upon, or stop. Given I’m on a parental leave, I’m limiting this to 1 group of discrete tasks a week, 1-2 improvements in habits. I do weekly planning in Simplenote, and my retrospective notes are added to the end of the plan from the previous week.
On a monthly basis, I follow largely the same structure as weekly, do the planning in Simplenote, and make notes about how well I was able to follow through on plans. Monthly plans take an extended period, I like to take 1-2 hours, sit outside and reflect on the month.
I use multiple frameworks for longer term planning and retrospectives, which deserve a separate post of themselves.


{% extends "base.html" %} {% block content %} {% load static %}
| Range of Weight | Ear Cleaning and Nail Trim | Bath & Brush | Full Service Grooming |
|---|---|---|---|
| up to 20 lbs | $5 | $25 | $35 |
| 21 - 60 lbs | $7 | $35 | $55 |
| 61 - up lbs | $10 | $55 | $75 |
| Hair Length | Price |
|---|---|
| Kittens | $25 |
| Short Hair | $35 |
| Medium Hair | $45 |
| Long Hair | $55 |


---
layout: post
title: 'Week 9 Day 1: O'' Auth Where Art Thou?'
date: '2014-11-10T05:58:00.000-08:00'
author: geoff purdy
tags:
modified_time: '2017-03-26T05:00:08.916-07:00'
thumbnail: http://4.bp.blogspot.com/-kygiuu5tf14/VGDDUpfBmVI/AAAAAAAABq8/s-_pKtAB9UU/s72-c/Stop_Digging_%5E_-_geograph.org.uk_-_195319.jpg
blogger_id: tag:blogger.com,1999:blog-1206336038417661147.post-6652782729727489351
blogger_orig_url: http://geoffreypurdy.blogspot.com/2014/11/week-9-day-1-o-auth-where-art-thou.html
---


| Days | Times |
|---|---|
| Wednesday | 12 - 8pm |
| Friday | 12 - 8pm |
| Saturday | 12 - 5pm |
Visit us on facebook
In the heat of things. #filletsteak #trattoriasedge #chef #cordonbleu #eatout
Posted by Trattoria da Vinci on Thursday, 19 July 2018
This has to be one of our favourite reviews through the years 😊👌🏼🇮🇹 #trattoriasedge #oldbutgold
Posted by Trattoria da Vinci on Monday, 28 January 2019
The first focaccia is in the new oven. Can’t wait to see you all at our new premises. Exciting times ahead..... #focaccia #italiano #davincisedge
Posted by Trattoria da Vinci on Friday, 2 August 2019
To view these pictures in Firefox browser, please disable 'Enhaced Tracking Protection'.


Welcome to pyMongoTree’s documentation!
Contents:
Lyle Scott, III
<EMAIL_ADDRESS>http://digitalfoo.net
Copyright (c) 2012 Lyle Scott, III
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
class mongotree.mongotree.MongoTree(host='localhost', port=27017, db_name='mongotree', uri=None, identifier='mongotree')[source]
Bases: object
An implEementation of modeling MongoDB values as a Tree with nodes
that have 1 parent and N children.
-
SEPARATOR = '|$|'
-
children(node=None, path=None)[source]
Get all children of a node.
- Args:
node (dict): A dict representing a node.
path (string): The path to use to find a node with a specific
path.
- Returns:
- list. All children of the node with path=parent_path.
-
fromXml(xml)[source]
Build a tree from an XML string.
- Args:
- xml (string): A string of valid XML.
-
get_dotgraph(roots=None)[source]
Generate a dot graph of the tree at a root via Graphviz.
- Args:
- roots (sequence): Roots to start graphing from.
- Default: all roots.
-
get_node(path)[source]
Return a node at specific path.
- Args:
- path (sequence): A sequence of tokens representing a path to a node.
- Returns:
- A dict representing a node || None.
-
get_roots()[source]
Get the root nodes that contain the start of a tree.
- Returns:
- list. A list of nodes with no parents (the “Top” nodes).
-
node_count(roots=None)[source]
Return how many nodes there are in the tree.
- Args (sequence): Optional. Instead of all roots, specify nodes to start
- the traversal from.
- Returns:
- int
-
parent(path)[source]
Get the parent of a node.
- Args:
- path (sequence): A sequence of tokens representing a path to a node.
- Returns:
- A dict representing a node || None.
-
path_exists(path)[source]
Check if a nodes exists at a specified path.
- Args:
- path (sequence): A sequence of tokens representing a path to a node.
- Returns:
- bool.
-
remove(node)[source]
Remove a node from the tree. If it has children, remove those, too.
- Arg:
- node (dict): A dict representing a node.
-
traverse(node, function=None, nodes=None)[source]
Traverse the tree, optionally running a function on each node.
- Args:
- node (dict): A dict representing a parent node that will have its
- children traversed (if there are any).
- function (function): A function to run on a node when it is
- traversed.
nodes (list): Holds all nodes that have been recursively traversed.
- Returns:
- list. A list of all nodes that were traversed.
-
upsert(path, obj=None, hit_inc=1)[source]
Add a node to the tree.
- Args:
- path (sequence): A sequence of tokens representing a path to a node.
obj (pickle): A pickled object stored as a blob on a node.
hit_inc (int): Incremenet the nodes hit counter.
-
valid_node(node)[source]
Indicate if a node is “valid”, where valid indicates that it has all
and only the keys it is supposed to have.
- Args:
- node (dict): A dict representing a node.
- Returns:
- bool


Like A Stone
Homepage
My Blog
About Me
Portfolio
Portfolio
Basketball League Website
Link to website
GitHub URL
Login Page
Register Team page
Create a Player
Mobile view of Register Team page part 1
Mobile view of Register Team page part 2
Creating a Blog using Angluar & Mongodb Part 1
GitHub URL
Creating a Blog using Angluar & Mongodb Part 2 - Displaying snippits of blog posts.
GitHub URL
Creating a Blog using Angluar & Mongodb Part 3 - Displaying full view of blog post.
GitHub URL
Creating a Blog using Angluar & Mongodb Part 4 - In this view you can create, edit or delete a blog post.
GitHub URL
Creating a Blog using Angluar & Mongodb Part 5 - Contact and social media section.
GitHub URL
Appbox Ad part 1
GitHub URL
Appbox Ad part 2
GitHub URL
Creative Design Agency part 1
GitHub URL
Creative Design Agency part 2
GitHub URL


cup.jenkinslib package¶
Subpackages¶
Module contents¶
Library for jenkins.
You can use Jenkins to access your jenkins server easily.
This library uses defensive programming with EAFP principle. Kinds of exceptions based on jenkins.Error may be raise. You should use this library with try … except.
Authors: liushuxian(liushuxian) Date: 2015/01/21
usage:
import cup
import cup.jenkinslib
############### quick start ###############
jenkins = cup.jenkinslib.Jenkins('cup.jenkins.baidu.com')
job = jenkins['cup_quick']
print job.name, job.last_stable_build_number, job.description
print job[5], job["lastSuccessBuild"], job.last_stable_build
qi = job.invoke()
build = qi.block_until_building()
print build.name, build.number, build.timestamp
try:
build.block_until_complete(timeout=20)
except cup.jenkinslib.RunTimeout as err:
print "timeout:", err
build.stop()
print build.duration, build.result, build.description
build.description = "new description"
jenkins.enable_ftp('ftp.baidu.com', 'cup', 'password', 22)
with build.ftp_artifacts as af:
af['artifacts_path'].download('./local_path')
-
class
cup.jenkinslib.
Jenkins
(url, username=None, password=None, static=False)[source]¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a jenkins server.
-
class
Artifacts
(build, name='', path='', is_dir=True)¶ Bases:
cup.jenkinslib.internal.artifacts.ArtifactsBase
Represents artifacts, file or directory.
-
class
Build
(url, build_number, job, depth=None)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a build.
-
actions
¶ get actions of build.
-
artifacts
¶ get artifacts object of build.
-
block
()¶ block until this build stop running.
Do not use this method too often, because it will request jenkins server every second.
-
block_until_complete
(delay=15, timeout=None)¶ block until this build stop running.
- Args:
- delay: check status every delay seconds, default is 15s. timeout: wait timeout seconds at most, default is forever.
- Returns:
- True if stopped, False if still running.
-
cause_description
¶ get short description of causes.
-
causes
¶ get causes of build, empty causes will be ignored.
-
changeset
¶ get changeset info, only support svn.
-
console
¶ get text console of build.
-
description
¶ get description of build if exists, otherwise None.
- Returns:
- description info of this build, encoding in utf-8. return None if not exists.
-
duration
¶ get build duration(s).
-
duration_ms
¶ get build duration(ms).
-
ftp_artifacts
¶ get ftp artifacts object of build.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
is_running
¶ check build is running or not.
-
is_started_by_scm_change
¶ check if is started by an SCM change.
-
is_started_by_timer
¶ check if is started by timer.
-
is_started_by_upstream_project
¶ check if is started by upstream project.
-
is_started_by_user
¶ check if is started by user.
-
is_success
¶ check build is success or not, return False if is running.
-
name
¶ get build name.
-
number
¶ get build number.
-
promote
(name)¶ force promotion by name.
-
result
¶ get build result.
-
revision
¶ get latest revision, only support svn.
-
revisions
¶ get all revisions info, only support svn.
-
stop
()¶ Stops the build execution if it’s running.
-
timestamp
¶ get build timestamp.
-
upstream_build
¶ get upstream build object if exists, otherwise None.
-
upstream_build_number
¶ get upstream build number if exists, otherwise None.
-
upstream_job
¶ get upstream job object if exists, otherwise None.
-
upstream_job_name
¶ get upstream job name if exists, otherwise None.
-
user_id
¶ get id of user who invoke this build if exists, otherwise None.
-
user_name
¶ get name of user who invoke this build if exists, otherwise None.
-
-
class
FTPArtifacts
(build, name='', path='', is_dir=True)¶ Bases:
cup.jenkinslib.internal.artifacts.ArtifactsBase
Represents artifacts on FTP.
Because ftp connection is used, close should be called if connected. It is recommended to use with as like:
- with FTPArtifacts(build) as af:
- bin_af = af[“bin”] bin_af.download(“./output”)
-
close
()¶ close ftp connection.
-
connect
()¶ connect to ftp, return ftp connection.
-
url
¶ get ftp artifact url.
-
class
Job
(url, name, jenkins)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a job.
-
build
(block=False, build_params=None, cause=None, files=None, delay=15)¶ trigger a new build.
- Args:
- block: block until the new build stopped. build_params: trigger new build with params. cause: set cause info. files: send build params in files. delay: if block is True, check status every delay seconds.
-
builds
¶ get container of all builds.
-
config
¶ get config element tree object of job.
-
config_text
¶ get config.xml text of job.
- Returns:
- config.xml text in Unicode type. You can encode it in ‘utf-8’ or ‘gb18030’.
-
description
¶ get description of job.
-
disable
()¶ disable job.
-
downstream_job_names
¶ get list of downstream job names.
-
downstream_jobs
¶ get list of downstream job objects.
-
enable
()¶ enable job.
-
first_build
¶ get first build.
-
first_build_number
¶ get number of first build.
-
get_build
(build_number, depth=None)¶ get build by number.
- Also support special build:
- firstBuild lastBuild lastStableBuild lastSuccessfulBuild lastCompletedBuild lastFailedBuild
-
get_build_trigger_url
(files)¶ get trigger url of job.
-
get_delete_url
()¶ get delete url of job.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
get_rename_url
()¶ get rename url of job.
-
has_params
¶ check build has params or not.
-
invoke
(block=False, build_params=None, cause=None, files=None, delay=15)¶ trigger a new build.
- Args:
- block: block until the new build stopped. build_params: trigger new build with params. cause: set cause info. files: send build params in files. delay: if block is True, check status every delay seconds.
-
is_enabled
¶ check if job is enabled.
-
is_queued
¶ check job is queued or not.
-
is_queued_or_running
¶ check job is queued/running or not.
-
is_running
¶ check job is running or not.
-
last_build
¶ get last build.
-
last_build_number
¶ get number of last build.
-
last_completed_build
¶ get last completed build.
-
last_completed_build_number
¶ get number of last completed build.
-
last_failed_build
¶ get last failed build.
-
last_failed_build_number
¶ get number of last failed build.
-
last_stable_build
¶ get last stable build.
-
last_stable_build_number
¶ get number of last stable build.
-
last_successful_build
¶ get last successful build.
-
last_successful_build_number
¶ get number of last successful build.
-
static
mk_json_from_build_parameters
(build_params, file_params=None)¶ make build parameters to json format.
-
next_build_number
¶ get number of next build.
-
promotions
¶ get promotions of job.
-
upstream_job_names
¶ get list of upstream job names.
-
upstream_jobs
¶ get list of upstream job objects.
-
-
class
Jobs
(jenkins)¶ Bases:
object
A container of Job objects.
-
create
(job_name, config)¶ create new job.
- Args:
- job_name: name of new job. config: configure for new job, xml text.
- Returns:
- new job object.
-
iterkeys
()¶ get all job name.
-
keys
()¶ get all job name.
-
rename
(job_name, new_job_name)¶ rename a job.
- Args:
- job_name: name of a existing job. new_job_name: new job name.
- Returns:
- new job object.
-
-
class
Label
(label, jenkins)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
A container of Node objects.
-
busy_node_num
¶ busy node num.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
get_node_url
(node_name)¶ get url of node.
- Args:
- node_name: node name.
- Returns:
- node url.
-
is_online
¶ label is online or not.
-
iteritems
()¶ get all nodes.
-
iterkeys
()¶ get all node name.
-
keys
()¶ get all node name.
-
node_num
¶ get node num.
-
tied_job_num
¶ get tied job num.
-
tied_jobs
¶ get all tied job name on this label.
-
tied_jobs_iterator
¶ get all tied job name on this label.
-
-
class
Node
(url, name, jenkins)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a node.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
is_idle
¶ node is idle or not.
-
is_online
¶ node is online or not.
-
is_temporarily_offline
¶ node is temporarily offline or not.
-
-
class
Nodes
(jenkins)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
A container of Node objects.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
get_node_url
(node_name)¶ get url of node.
- Args:
- node_name: node name.
- Returns:
- node url.
-
iteritems
()¶ get all nodes.
-
iterkeys
()¶ get all node name.
-
keys
()¶ get all node name.
-
-
class
Promotion
(url, name, job)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a promotion.
-
builds
¶ get container of all builds.
-
description
¶ get description of promotion.
-
first_build
¶ get first build.
-
first_build_number
¶ get number of first build.
-
get_build
(build_number, depth=None)¶ get build by number.
- Also support special build:
- firstBuild lastBuild lastStableBuild lastSuccessfulBuild lastCompletedBuild lastFailedBuild
-
get_jenkins_obj
()¶ get object of current jenkins.
-
is_queued
¶ check promotion is queued or not.
-
is_queued_or_running
¶ check promotion is queued/running or not.
-
is_running
¶ check promotion is running or not.
-
last_build
¶ get last build.
-
last_build_number
¶ get number of last build.
-
last_completed_build
¶ get last completed build.
-
last_completed_build_number
¶ get number of last completed build.
-
last_failed_build
¶ get last failed build.
-
last_failed_build_number
¶ get number of last failed build.
-
last_stable_build
¶ get last stable build.
-
last_stable_build_number
¶ get number of last stable build.
-
last_successful_build
¶ get last successful build.
-
last_successful_build_number
¶ get number of last successful build.
-
next_build_number
¶ get number of next build.
-
-
class
PromotionBuild
(url, build_number, promotion, depth=None)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
Represents a promotion build.
-
actions
¶ get actions of build.
-
block
()¶ block until this build stop running.
Do not use this method too often, because it will request jenkins server every second.
-
block_until_complete
(delay=15, timeout=None)¶ block until this build stop running.
- Args:
- delay: check status every delay seconds, default is 15s. timeout: wait timeout seconds at most, default is forever.
- Returns:
- True if stopped, False if still running.
-
cause_description
¶ get short description of causes.
-
causes
¶ get causes of build, empty causes will be ignored.
-
console
¶ get text console of build.
-
description
¶ get description of build if exists, otherwise None.
- Returns:
- description info of this build, encoding in utf-8. return None if not exists.
-
duration
¶ get build duration(s).
-
duration_ms
¶ get build duration(ms).
-
get_jenkins_obj
()¶ get object of current jenkins.
-
is_running
¶ check build is running or not.
-
is_started_by_scm_change
¶ check if is started by an SCM change.
-
is_started_by_timer
¶ check if is started by timer.
-
is_started_by_upstream_project
¶ check if is started by upstream project.
-
is_started_by_user
¶ check if is started by user.
-
is_success
¶ check build is success or not, return False if is running.
-
job_build
¶ get Build object of target job build.
-
job_build_number
¶ get build number of target job build.
-
name
¶ get build name.
-
number
¶ get build number.
-
result
¶ get build result.
-
revision
¶ get latest revision, only support svn.
-
stop
()¶ Stops the build execution if it’s running.
-
timestamp
¶ get build timestamp.
-
user_name
¶ get name of user who invoke this build if exists, otherwise None.
-
-
class
Promotions
(job, depth=None)¶ Bases:
cup.jenkinslib.internal.base.JenkinsBase
A container of Promotions objects.
-
get_jenkins_obj
()¶ get object of current jenkins.
-
iterkeys
()¶ get all promotion name.
-
keys
()¶ get all promotion name.
-
-
class
Requester
(username=None, password=None)¶ Bases:
object
A class which help you access jenkins.
-
VALID_STATUS_CODES
= [200]¶
-
get
(url, params=None, headers=None, allow_redirects=True)¶ request url in GET method.
- Returns:
- Response object.
-
get_and_confirm_status
(url, params=None, headers=None, valid=None)¶ request url in GET method, and check status code.
- Returns:
- Response object.
-
post
(url, params=None, data=None, files=None, headers=None, allow_redirects=True)¶ request url in POST method.
- Returns:
- Response object.
-
post_and_confirm_status
(url, params=None, data=None, files=None, headers=None, valid=None, allow_redirects=True)¶ request url in POST method, and check status code.
- Returns:
- Response object.
-
post_xml_and_confirm_status
(url, params=None, data=None, valid=None)¶ request url in POST method with text/xml context, and check status code.
- Returns:
- Response object.
-
-
create_job
(job_name, config)[source]¶ create a new job.
create a new job named ‘job_name’. same as self.jobs[‘job_name’] = config.
- Args:
- job_name: name of new job. config: configure for new job, xml text.
- Returns:
- new job object.
-
enable_ftp
(host, username='', password='', port=0)[source]¶ enable ftp server and set host, username, password, port.
-
static
get_jenkins_by_name
(name)[source]¶ get special jenkins class by name.
- Args:
- name: name of jenkins server.
- Returns:
- special jenkins class or Jenkins.
-
static
get_jenkins_by_url
(url)[source]¶ get special jenkins class by url.
- Args:
- url: url of jenkins server.
- Returns:
- special jenkins class or Jenkins.
-
jobs
¶ get container of all jobs.
-
nodes
¶ get nodes.
-
class


We illustrate the use of the tool with the smallish example below.
Two processes are spawned, the first starting an ``echo'' server
that echoes received messages, and the other process invokes the echo
server:
Let's run the example under the standard Erlang runtime system:
That worked fine. Let's try it under McErlang instead.
To do so we first have to recompile the module
using the McErlang compiler:
Then we run it:
Ah, so there was an error. Let's find out more:
Apparently in one execution trace the second process spawned (the one calling
the echo server) was run before the echo server itself, and of course
upon trying to send a message @echo!msg,self(),'hello world'@
the @echo@ name was not registered.


Capitol Corps
×
Notice
Login will be required every time you login to prevent unauthorized access.
Search Network Search


{% load static %}
Login
Want to create an account instead?
Username: {{ form.username }}
Password: {{ form.password }}
Your username and password did not match.
You do not have access to view this page.


I am a Graphic Designer specializing in both Front End Development and Film/Photo Production. I have experience with QA/Automation standards and practices and AGILE methodology.
Personal Site for Film Maker, posted HD Quicktime videos, create submission system for uploading footage to
Promotional Site for Play, Lists Cast Bios, Production info. Sliced and designed using Adobe Photoshop
Website for Private Swim School, Update Teacher Roster, Lesson Schedule and relevant info
I've trained in Theatre, and spent a good portion of my life as a part of a choir, a capella quartet or other groups of roving singers. I also collect old building toys, and Nerf Guns
My other passive hobbies include Video Games(Nintendo For Life), Music, and Comic Books. I also regularly study Art, Typhography and design techniques for print photo and web.


ORDER NOW!!
HOME
EXTRA LARGE
12 SLICES
Pepperoni
Mushrooms
Sausage
Extra Cheese
Green Peppers
Thick Crust
Thin Crust
Deep Crust
Cheese Filled Crust
Stuffed Crust
$25
85
LARGE
8 SLICES
Pepperoni
Mushrooms
Sausage
Extra Cheese
Green Peppers
Thick Crust
Thin Crust
Deep Crust
Cheese Filled Crust
Stuffed Crust
$20
65
MEDIUM
6 SLICES
Pepperoni
Mushrooms
Sausage
Extra Cheese
Green Peppers
Thick Crust
Thin Crust
Deep Crust
Cheese Filled Crust
Stuffed Crust
$10
10
SMALL
6 SLICES
Pepperoni
Mushrooms
Sausage
Extra Cheese
Green Peppers
Thick Crust
Thin Crust
Deep Crust
Cheese Filled Crust
Stuffed Crust
$5
10
CART
ITEM
<>
PRICE
<>
QUANTITY
Extra Large
<>
$25.85
<>
REMOVE
Large
<>
$20.65
<>
REMOVE
Total
$39.97
PURCHASE


--- layout: post title: horse show Storyboards date: '2013-08-03T19:33:00+02:00' categories: - Horses - Storyboards picture_url: https://film-Storyboards.tumblr.com/post/57288005056/horse-show-Storyboards ---
Horse show Storyboards.


You can easily exhaust your system resources if you do not limit the maximum number of concurrent processes that your program can spawn. Poolboy is a widely used lightweight, generic pooling library for Erlang that addresses this issue.
Table of Contents
Why use Poolboy?
Let’s think of a specific example for a moment. You are tasked to build an application for saving user profile information to the database. If you’ve created a process for every user registration, you would create an unbounded number of connections. At some point the number of those connections can exceed the capacity of your database server. Eventually your application can get timeouts and various exceptions.
The solution is to use a set of workers (processes) to limit the number of connections instead of creating a process for every user registration. Then you can easily avoid running out of your system resources.
That’s where Poolboy comes in.
It allows you to easily set up a pool of workers managed by a Supervisor
without much effort on your part.
There are many libraries which use Poolboy under the covers.
For example, postgrex
’s connection pool (which is leveraged by Ecto when using PostgreSQL) and redis_poolex
(Redis connection pool) are some popular libraries which use Poolboy.
Installation
Installation is a breeze with mix.
All we need to do is add Poolboy as a dependency to our mix.exs
.
Let’s create an application first:
$ mix new poolboy_app --sup
Add Poolboy as a dependency to our mix.exs
.
defp deps do
[{:poolboy, "~> 1.5.1"}]
end
Then fetch dependencies, including Poolboy.
$ mix deps.get
The configuration options
We need to know a little bit about the various configuration options in order to start using Poolboy.
:name
- the pool name. Scope can be:local
,:global
, or:via
.:worker_module
- the module that represents the worker.:size
- maximum pool size.:max_overflow
- maximum number of temporary workers created when the pool is empty. (optional):strategy
-:lifo
or:fifo
, determines whether the workers that return to the pool should be placed first or last in the line of available workers. Default is:lifo
. (optional)
Configuring Poolboy
For this example, we’ll create a pool of workers responsible for handling requests to calculate the square root of a number. We’ll keep the example simple so that we can keep our focus on Poolboy.
Let’s define the Poolboy configuration options and add the Poolboy worker pool as a child worker of our application.
Edit lib/poolboy_app/application.ex
:
defmodule PoolboyApp.Application do
@moduledoc false
use Application
defp poolboy_config do
[
name: {:local, :worker},
worker_module: PoolboyApp.Worker,
size: 5,
max_overflow: 2
]
end
def start(_type, _args) do
children = [
:poolboy.child_spec(:worker, poolboy_config())
]
opts = [strategy: :one_for_one, name: PoolboyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
The first thing we defined is the configuration options for the pool.
We named our pool :worker
and set the :scope
to :local
.
Then we designated PoolboyApp.Worker
module as the :worker_module
that this pool should use.
We also set the :size
of the pool to have total of 5
workers.
Also, in case all workers are under load, we tell it to create 2
more workers to help with the load using the :max_overflow
option.
(overflow
workers do go away once they complete their work.)
Next, we added :poolboy.child_spec/2
function to the array of children so that the pool of workers will be started when the application starts.
It takes two arguments: name of the pool, and pool configuration.
Creating Worker
The worker module will be a simple GenServer
that calculates the square root of a number, sleeps for one second, and prints out the pid of the worker.
Create lib/poolboy_app/worker.ex
:
defmodule PoolboyApp.Worker do
use GenServer
def start_link(_) do
GenServer.start_link(__MODULE__, nil)
end
def init(_) do
{:ok, nil}
end
def handle_call({:square_root, x}, _from, state) do
IO.puts("process #{inspect(self())} calculating square root of #{x}")
Process.sleep(1000)
{:reply, :math.sqrt(x), state}
end
end
Using Poolboy
Now that we have our PoolboyApp.Worker
, we can test Poolboy.
Let’s create a simple module that creates concurrent processes using Poolboy.
:poolboy.transaction/3
is the function that you can use to interface with the worker pool.
Create lib/poolboy_app/test.ex
:
defmodule PoolboyApp.Test do
@timeout 60000
def start do
1..20
|> Enum.map(fn i -> async_call_square_root(i) end)
|> Enum.each(fn task -> await_and_inspect(task) end)
end
defp async_call_square_root(i) do
Task.async(fn ->
:poolboy.transaction(
:worker,
fn pid -> GenServer.call(pid, {:square_root, i}) end,
@timeout
)
end)
end
defp await_and_inspect(task), do: task |> Task.await(@timeout) |> IO.inspect()
end
Run the test function to see the result.
$ iex -S mix
iex> PoolboyApp.Test.start()
process #PID<0.182.0> calculating square root of 7
process #PID<0.181.0> calculating square root of 6
process #PID<0.157.0> calculating square root of 2
process #PID<0.155.0> calculating square root of 4
process #PID<0.154.0> calculating square root of 5
process #PID<0.158.0> calculating square root of 1
process #PID<0.156.0> calculating square root of 3
...
If no worker is available in the pool, Poolboy will timeout after the default timeout period (five seconds) and won’t accept any new requests.
In our example, we’ve increased the default timeout to one minute in order to demonstrate how we can change the default timeout value.
In case of this app, you can observe the error if you change the value of @timeout
to less than 1000.
Even though we’re attempting to create multiple processes (total of twenty in the example above) :poolboy.transaction/3
function will limit the maximum number of created processes to five (plus two overflow workers if needed) as we have defined in our configuration.
All requests will be handled using the pool of workers rather than creating a new process for every request.
Caught a mistake or want to contribute to the lesson? Edit this page on GitHub!


Zipcall.io
The most advanced video chat ever created.
Peer to peer video calling provides quality and latency simply not available with traditional technology.
See the whole picture
Zipcall is built radically different. We left behind slow bulky servers, opting for decentralized peer to peer calling. We engineered a platform with maximum video quality and low latency. Its good, trust us.
Lowest Latency
Breakthrough peer to peer WebRTC technology means your video goes directly to the other person without a server. No middleman. No extra stops.
Best Video Quality
State of the art VP9 video compression combined with our scaling optimization makes yours calls crystal clear.
Total Privacy
Each chat is single use, data stays between you and your caller. Zipcall is built privacy first.
No Download Required
No downloads. No plugins. No nonsense. Just open Zipcall in your browser and get back to what matters most.
No Server Needed
Calls are entirely between you and your caller, decentralized from any server. Data never leaves the browser. Cool right?
Maximum Security
End to end state of the art encryption means your calls are exactly that. Your calls.


A summary of some new news related to CUNY's and CSI's response to the COVID-19 pandemic. See https://csi-covid19.github.io for the archive.
To add/suggest news, please email John Verzani
7/9 Student petition against cuts to adjuncts (thanks to Michael Paris)
What does this mean for us?
Having fewer teachers means having fewer courses offered and larger class sizes. It means losing trusted mentors and advisors. This dramatically increases the burden on those faculty remaining, both full-time and part-time.
Of course, adjunct layoffs mean a reduction in the quality of services to our students: fewer courses offered and/or larger class sizes in those courses that are offered. This also means more work for those of us lucky enough to remain on payroll.
But there is hope in the middle of this crisis. We need greater collective power to turn that hope into money for CUNY. Let's show CUNY that we are more organized than ever before by gathering virtually or in your car on July 18th for a fight back caravan across the boroughs. The action will run from 11 am - 1 pm. For those who do not have cars, it is possible to participate digitally or by bicycle. At our last action, we trended on Twitter thanks to our hundreds of digital participants!
First, if the resolution is “simply a delegation of authority to allow for the necessary planning for the Fall,” why does it have to be passed with such urgency? The last-minute publication of the resolution and the one-day notice of an emergency meeting do not comport with your suggestion that the resolution is a formality, in order to facilitate planning. Thus, the PSC does not accept the position you appear to take that the vote on the resolution must go ahead today - leaving no time for the legal requirement of consultation with the PSC. Your response fails to demonstrate that there is such urgency about passing this resolution that the vote could not be postponed. ...
PSC Chair mails the Board requesting consultation prior to voting on instruction for fall.
While it may be that the PSC would not disagree with many of the provisions of the proposed resolution, submitting the resolution for a vote without any consultation with the PSC is a violation of the Collective Bargaining Agreement, quite possibly a violation of the NYS reopening guidelines, and a profound insult to the faculty and professional staff on whose work the University depends.
Last night the CUNY Board of Trustees approved a resolution that gives us the most flexibility in making decisions and planning what the Fall semester will look like once New York City enters Phase 4, which signals the start of the reopening for CUNY.
We are preparing for a range of scenarios that combine in-person, virtual and hybrid instructional modalities. Thanks to the diligent work of so many in our system, 48 percent of the Fall 2020 courses that are open for student registration are already scheduled for hybrid or online delivery. We hope to increase this percentage in the weeks ahead in preparation for the start of the semester. I want to acknowledge and thank everyone across our university who has committed endless hours to getting the work done during these extraordinary times.
We are also getting ready to deliver a range of in-person courses and services, provided they meet New York State and University guidelines for re-opening and assuming that New York City enters Phase 4 over the next few weeks, as is the plan.
By Deborah Glick a nd Toby Ann Stavisky. Glick represents parts of lower Manhattan in the state Assembly, and Stavisky, who represents parts of Queens in the state Senate, are chairs of the Higher Education Committees in their respective chambers.
In one swift move this month, the City University of New York eliminated health care for hundreds of CUNY adjunct faculty, income for thousands, and reduced the quality of education it provides to its 245,000 undergraduates — all at a moment when residents of New York City are increasingly drawn to attend one of CUNY’s 25 colleges. Summer enrollment at CUNY is up 16%, and first-year enrollments for the fall are up in much of the system as well.
CUNY’s decision to lay off thousands of workers is counterproductive and devastating. It can and must be reversed, first by securing the $136 million in federal money that has been allocated to CUNY and remains untapped, and second by raising taxes on the ultra-wealthy and investing in our public higher education enterprise.
Harvard and MIT argue in their lawsuit that the policy change announced Monday by U.S. Immigration and Customs Enforcement threw virtually all of U.S. higher education “into chaos.” They say the decision, which would make international students enrolled exclusively in online courses subject to deportation, puts colleges in “the untenable situation of either moving forward with their carefully calibrated, thoughtful, and difficult decisions to proceed with their curricula fully or largely online in the fall of 2020 … or to attempt, with just weeks before classes resume, to provide in-person education despite the grave risk to public health and safety that such a change would entail.”


Inspired by twitter.com's autocomplete search functionality, typeahead.js is a flexible JavaScript library that provides a strong foundation for building robust typeaheads.
The typeahead.js library consists of 2 components: the suggestion engine, Bloodhound, and the UI view, Typeahead. The suggestion engine is responsible for computing suggestions for a given query. The UI view is responsible for rendering suggestions and handling DOM interactions. Both components can be used separately, but when used together, they can provide a rich typeahead experience.
How you acquire typeahead.js is up to you.
Preferred method:
$ bower install typeahead.js
Other methods:
Note: both bloodhound.js and typeahead.jquery.js have a dependency on jQuery 1.9+.
For some working examples of typeahead.js, visit the examples page.
NOTE: typeahead.js is not tested on mobile browers.
For general questions about typeahead.js, tweet at @typeahead.
For technical questions, you should post a question on Stack Overflow and tag it with typeahead.js.
Discovered a bug? Please create an issue here on GitHub!
https://github.com/twitter/typeahead.js/issues
For transparency and insight into our release cycle, releases will be numbered with the follow format:
<major>.<minor>.<patch>
And constructed with the following guidelines:
For more information on semantic versioning, please visit http://semver.org/.
Tests are written using Jasmine and ran with Karma. To run
the test suite with PhantomJS, run $ npm test
.
If you plan on contributing to typeahead.js, be sure to read the contributing guidelines. A good starting place for new contributors are issues labeled with entry-level. Entry-level issues tend to require minor changes and provide developers a chance to get more familiar with typeahead.js before taking on more challenging work.
In order to build and test typeahead.js, you'll need to install its dev
dependencies ($ npm install
) and have grunt-cli
installed ($ npm install -g grunt-cli
). Below is an overview of the available
Grunt tasks that'll be useful in development.
grunt build
– Builds typeahead.js from source.grunt lint
– Runs source and test files through JSHint.grunt watch
– Rebuilds typeahead.js whenever a source file is modified.grunt server
– Serves files from the root of typeahead.js on localhost:8888.
Useful for using test/playground.html for debugging/testing.grunt dev
– Runs grunt watch
and grunt server
in parallel.Jake Harding
You?
Jake Harding
Veljko Skarich
Tim Trueman
Copyright 2013 Twitter, Inc.
Licensed under the MIT License


| {{_enttdetails.psngrtype}} Name | Class | Father Name | Father Mobile | Father Email | Mother Name | Mother Mobile | Mother Email |
|---|---|---|---|---|---|---|---|
| {{row.psngrname}} | {{row.classname}} | {{row.fathername}} | {{row.mobileno1}} | {{row.email1}} | {{row.mothername}} | {{row.mobileno2}} | {{row.email2}} |


{include file="publicFile/top" /} {include file="publicFile/left" /} {include file="publicFile/foot" /}
开始


Honeycomb is a learning experience and an experiment in pushing the boundaries of what co-operative living can be. We're not flower-twirling laggards; we get anxious sitting about. We love to create, and have fun. Honeycomb's aim is to be a place for people like us to supplement, while remaining independent of harmful and expensive corporate food and energy practices.
Huh, that sounds cool. Tell me more.


SPG cover of Nehru-Gandhi family to be removed, Congress calls it political vendetta
by JKR StaffThe Congress has reacted angrily on the reports that the Centre’s Narendra Modi government has decided to withdraw the Special Protection Group (SPG) cover of Nehru-Gandhi family including Congress President Sonia Gandhi, her son Rahul Gandhi and daughter Priyanka Gandhi.
According to media reports, the government has decided to replace their security cover by Z+ cover, which will consist of CRPF men taking care of their security. The home ministry has reportedly concluded that the members of the Gandhi family did not face significant threats to their lives.
Reacting to the news, former union minister, Salman Khurshid, said the decision was unfortunate and smacked of political vendetta by the BJP-led government.
Congress MP and close aide of Sonia Gandhi, Ahmed Patel, tweeted, “The BJP has descended to the ultimate personal vendetta mechanism, compromising the lives of family members of 2 Former Prime Ministers to acts of terror and violence.”
The decision follows a similar step taken by the MHA to downgrade the security cover of former Prime Minister Manmohan Singh from SPG to Z+ category.
Many Congress supporters took to social media to remind the government that two members of the same family, both prime ministers, were assassinated in the past. While Indira Gandhi was killed by her Sikh bodyguards in 1984, her son Rajiv Gandhi was assassinated by Tamil terrorists seven years later.