Go back to the Contents page.
Press Show to reveal the code chunks.
# Set seed for reproducibility
set.seed(1982)
# Set global options for all code chunks
knitr::opts_chunk$set(
# Disable messages printed by R code chunks
message = FALSE,
# Disable warnings printed by R code chunks
warning = FALSE,
# Show R code within code chunks in output
echo = TRUE,
# Include both R code and its results in output
include = TRUE,
# Evaluate R code chunks
eval = TRUE,
# Enable caching of R code chunks for faster rendering
cache = FALSE,
# Align figures in the center of the output
fig.align = "center",
# Enable retina display for high-resolution figures
retina = 2,
# Show errors in the output instead of stopping rendering
error = TRUE,
# Do not collapse code and output into a single block
collapse = FALSE
)
# Start the figure counter
fig_count <- 0
# Define the captioner function
captioner <- function(caption) {
fig_count <<- fig_count + 1
paste0("Figure ", fig_count, ": ", caption)
}
capture.output(
knitr::purl(here::here("functionality.Rmd"), output = here::here("functionality.R")),
file = here::here("purl_log.txt")
)
source(here::here("functionality.R"))
library(fmesher)
library(Matrix)
We now consider the following equation on the unit square \(D=[0,1]^2\), that is, \[\begin{equation}
\label{eq:maineq_on_square_neumann}
\tag{1}
\left\{
\begin{aligned}
\partial_t u(x,y,t) + (\kappa^2 - \Delta)^{\alpha/2} u(x,y,t) &=
f(x,y,t), && \quad (x,y,t) \in D \times (0, T), \\
u(x,y,0) &= u_0(x,y), && \quad (x,y) \in D, \\
\partial_n u(x,y,t) &= 0, && \quad (x,y,t) \in \partial D
\times (0,T),
\end{aligned}
\right.
\end{equation}\] where \(\Delta\) denotes the Laplacian on \(D\) with homogeneous Neumann boundary
conditions, and \(\partial_n\) denotes
the outward normal derivative on \(\partial
D\). The eigenvalues of \(-\Delta\) are known and given by \(\lambda_{m,n} = \pi^2(m^2+n^2)\) for \(m,n=0,1,2,\dots\), and the eigenfunctions
are \(\phi_{m,n}(x,y)=\cos(m \pi x)\cos(n\pi
y)\).
Below we use the eigenpairs to construct an exact solution to
equation \(\eqref{eq:maineq_on_square_neumann}\) and
compare it with the numerical approximation. We take \(u_0(x,y) = x_3 \phi_{1,0}(x,y)\) with \(x_3 = 1\) and \(f(x,y,t) = y_2 \sin(\pi t)
\phi_{0,1}(x,y)\) with \(y_2 =
10\). Then the exact solution is given by \[\begin{equation}
u(x,y,t) = x_3\text{e}^{-\lambda^{\alpha/2}_{1,0}t}\phi_{1,0}(x,y)+y_2
G_2(t)\text{e}^{-\lambda^{\alpha/2}_{0,1}t}\phi_{0,1}(x,y),
\end{equation}\] where \(G_2(t)=
\displaystyle\int_0^t \text{e}^{\lambda^{\alpha/2}_{0,1}r}\sin(\pi
r)dr\). Below the exact solution is computed as
U_true and compared with the numerical approximation
U_approx.
We take parameters \(T = 2\), \(\kappa = 4\), \(\alpha = 1.8\), \(m=4\), \(h =
0.05\), and time step size \(\tau =
0.05\).
T_final <- 2
kappa <- 4
a <- b <- 1
m_max <- 1
n_max <- 1
N_eig <- (m_max + 1) * (n_max + 1)
coeff_U_0 <- rep(0, N_eig)
coeff_U_0[3] <- 1
coeff_FF <- rep(0, N_eig)
coeff_FF[2] <- 10
AAA = 1
OMEGA = pi
alpha <- 1.8
m = 4
beta <- alpha/2
time_step <- 0.05
time_seq <- seq(0, T_final, length.out = ((T_final - 0) / time_step + 1))
h <- 0.05
n_coarse <- ceiling(-1+sqrt(a*b)/h)
n_fine <- 2*n_coarse
mesh_and_FEM_coarse <- gets.mesh.and.FEM.on.rectangle(a, b, n_coarse)
mesh_coarse <- mesh_and_FEM_coarse$mesh
G <- mesh_and_FEM_coarse$G
C <- mesh_and_FEM_coarse$C
L <- kappa^2*C + G
eig <- compute_true_eigen_rectangle(
a = a,
b = b,
loc = mesh_coarse$loc,
kappa = kappa,
alpha = alpha,
m_max = m_max,
n_max = n_max)
m_vector = eig$m_vector
n_vector = eig$n_vector
EIGENVAL_ALPHA <- eig$EIGENVAL_ALPHA
EIGENFUN <- eig$EIGENFUN
U_0 <- EIGENFUN %*% coeff_U_0
U_true <- EIGENFUN %*%
outer(1:length(coeff_U_0),
1:length(time_seq),
function(i, j) (coeff_U_0[i] + coeff_FF[i] * G_sin(t = time_seq[j], A = AAA, lambda_j_alpha_half = EIGENVAL_ALPHA[i], omega = OMEGA)) * exp(-EIGENVAL_ALPHA[i] * time_seq[j]))
mesh_and_FEM_fine <- gets.mesh.and.FEM.on.rectangle(a, b, n_fine)
mesh_fine <- mesh_and_FEM_fine$mesh
Psi <- fm_basis(mesh_coarse, mesh_fine$loc)
eig_fine <- compute_true_eigen_rectangle(
a = a,
b = b,
loc = mesh_fine$loc,
kappa = kappa,
alpha = alpha,
m_max = m_max,
n_max = n_max)
EIGENFUN_fine <- eig_fine$EIGENFUN
# Compute matrix F with columns F^k
FF_approx <- t(Psi) %*%
mesh_and_FEM_fine$C %*%
EIGENFUN_fine %*%
outer(1:length(coeff_FF),
1:length(time_seq),
function(i, j) coeff_FF[i] * g_sin(r = time_seq[j], A = AAA, omega = OMEGA))
my_op_frac <- my.fractional.operators.frac(L, beta, C, scale.factor = kappa^2, m = m, time_step)
U_approx <- solve_fractional_evolution(my_op_frac, time_step, time_seq, val_at_0 = U_0, RHST = FF_approx)
diff <- U_true - U_approx
error <- sqrt(as.double(time_step * sum(diff * (C %*% diff))))
error
## [1] 0.03092878
# Plot results
plot_3d_rectangle_scatter(mesh_coarse$loc, time_seq, abs(diff), fixed_colorscale = FALSE)
# Plot results
idx <- which.min(abs(time_seq - 0.5))
error_rectangle <- plot_3d_rectangle_onecol(mesh_coarse, as.vector(abs(diff[,idx])))
save(error_rectangle, file = here::here("data_files/exp_1_error_rectangle.RData"))
error_rectangle
f_rect <- plot_3d_rectangle_onecol(mesh_coarse, as.vector(U_approx[,idx]))
f_rect
save(f_rect, file = here::here("data_files/exp_1_f_rect.RData"))
LS0tCnRpdGxlOiAiRXhhbXBsZSBvbiB0aGUgc3BoZXJlIgpkYXRlOiAiTGFzdCBtb2RpZmllZDogYHIgZm9ybWF0KFN5cy50aW1lKCksICclZC0lbS0lWS4nKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgbWF0aGpheDogImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbWF0aGpheEAzL2VzNS90ZXgtbW1sLWNodG1sLmpzIgogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdGhlbWU6IGZsYXRseQogICAgY29kZV9mb2xkaW5nOiBzaG93ICMgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIgdG8gaGlkZSBjb2RlIGFuZCBhZGQgYSBidXR0b24gdG8gc2hvdyBpdAogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgZmlnX2NhcHRpb246IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNzczogdmlzdWFsLmNzcwphbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQpiaWJsaW9ncmFwaHk6IAogIC0gcmVmZXJlbmNlcy5iaWIKICAtIGdyYXRlZnVsLXJlZnMuYmliCmhlYWRlci1pbmNsdWRlczoKICAtIFxuZXdjb21tYW5ke1xhcn17XG1hdGhiYntSfX0KICAtIFxuZXdjb21tYW5ke1xsbGF2fVsxXXtcbGVmdFx7IzFccmlnaHRcfX0KICAtIFxuZXdjb21tYW5ke1xwYXJlfVsxXXtcbGVmdCgjMVxyaWdodCl9CiAgLSBcbmV3Y29tbWFuZHtcTmNhbH17XG1hdGhjYWx7Tn19CiAgLSBcbmV3Y29tbWFuZHtcVmNhbH17XG1hdGhjYWx7Vn19CiAgLSBcbmV3Y29tbWFuZHtcRWNhbH17XG1hdGhjYWx7RX19CiAgLSBcbmV3Y29tbWFuZHtcV2NhbH17XG1hdGhjYWx7V319Ci0tLQoKR28gYmFjayB0byB0aGUgW0NvbnRlbnRzXShhYm91dC5odG1sKSBwYWdlLgoKPGRpdiBzdHlsZT0iY29sb3I6ICMyYzNlNTA7IHRleHQtYWxpZ246IHJpZ2h0OyI+CioqKioqKioqICAKPHN0cm9uZz5QcmVzcyBTaG93IHRvIHJldmVhbCB0aGUgY29kZSBjaHVua3MuPC9zdHJvbmc+ICAKCioqKioqKioqCjwvZGl2PgoKCmBgYHtyLCBwdXJsID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBDcmVhdGUgYSBjbGlwYm9hcmQgYnV0dG9uIG9uIHRoZSByZW5kZXJlZCBIVE1MIHBhZ2UKc291cmNlKGhlcmU6OmhlcmUoImNsaXBib2FyZC5SIikpOyBjbGlwYm9hcmQKYGBgCgoKYGBge3IsIHB1cmwgPSBGQUxTRSwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSJ9CiMgU2V0IHNlZWQgZm9yIHJlcHJvZHVjaWJpbGl0eQpzZXQuc2VlZCgxOTgyKSAKIyBTZXQgZ2xvYmFsIG9wdGlvbnMgZm9yIGFsbCBjb2RlIGNodW5rcwprbml0cjo6b3B0c19jaHVuayRzZXQoCiAgIyBEaXNhYmxlIG1lc3NhZ2VzIHByaW50ZWQgYnkgUiBjb2RlIGNodW5rcwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgCiAgIyBEaXNhYmxlIHdhcm5pbmdzIHByaW50ZWQgYnkgUiBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgCiAgIyBTaG93IFIgY29kZSB3aXRoaW4gY29kZSBjaHVua3MgaW4gb3V0cHV0CiAgZWNobyA9IFRSVUUsICAgICAgICAKICAjIEluY2x1ZGUgYm90aCBSIGNvZGUgYW5kIGl0cyByZXN1bHRzIGluIG91dHB1dAogIGluY2x1ZGUgPSBUUlVFLCAgICAgCiAgIyBFdmFsdWF0ZSBSIGNvZGUgY2h1bmtzCiAgZXZhbCA9IFRSVUUsICAgICAgIAogICMgRW5hYmxlIGNhY2hpbmcgb2YgUiBjb2RlIGNodW5rcyBmb3IgZmFzdGVyIHJlbmRlcmluZwogIGNhY2hlID0gRkFMU0UsICAgICAgCiAgIyBBbGlnbiBmaWd1cmVzIGluIHRoZSBjZW50ZXIgb2YgdGhlIG91dHB1dAogIGZpZy5hbGlnbiA9ICJjZW50ZXIiLAogICMgRW5hYmxlIHJldGluYSBkaXNwbGF5IGZvciBoaWdoLXJlc29sdXRpb24gZmlndXJlcwogIHJldGluYSA9IDIsCiAgIyBTaG93IGVycm9ycyBpbiB0aGUgb3V0cHV0IGluc3RlYWQgb2Ygc3RvcHBpbmcgcmVuZGVyaW5nCiAgZXJyb3IgPSBUUlVFLAogICMgRG8gbm90IGNvbGxhcHNlIGNvZGUgYW5kIG91dHB1dCBpbnRvIGEgc2luZ2xlIGJsb2NrCiAgY29sbGFwc2UgPSBGQUxTRQopCiMgU3RhcnQgdGhlIGZpZ3VyZSBjb3VudGVyCmZpZ19jb3VudCA8LSAwCiMgRGVmaW5lIHRoZSBjYXB0aW9uZXIgZnVuY3Rpb24KY2FwdGlvbmVyIDwtIGZ1bmN0aW9uKGNhcHRpb24pIHsKICBmaWdfY291bnQgPDwtIGZpZ19jb3VudCArIDEKICBwYXN0ZTAoIkZpZ3VyZSAiLCBmaWdfY291bnQsICI6ICIsIGNhcHRpb24pCn0KYGBgCgoKYGBge3J9CmNhcHR1cmUub3V0cHV0KAogIGtuaXRyOjpwdXJsKGhlcmU6OmhlcmUoImZ1bmN0aW9uYWxpdHkuUm1kIiksIG91dHB1dCA9IGhlcmU6OmhlcmUoImZ1bmN0aW9uYWxpdHkuUiIpKSwKICBmaWxlID0gaGVyZTo6aGVyZSgicHVybF9sb2cudHh0IikKKQpzb3VyY2UoaGVyZTo6aGVyZSgiZnVuY3Rpb25hbGl0eS5SIikpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGZtZXNoZXIpCmxpYnJhcnkoTWF0cml4KQpgYGAKCgpXZSBub3cgY29uc2lkZXIgdGhlIGZvbGxvd2luZyBlcXVhdGlvbiBvbiB0aGUgdW5pdCBzcXVhcmUgJEQ9WzAsMV1eMiQsIHRoYXQgaXMsClxiZWdpbntlcXVhdGlvbn0KXGxhYmVse2VxOm1haW5lcV9vbl9zcXVhcmVfbmV1bWFubn0KXHRhZ3sxfQpcbGVmdFx7ClxiZWdpbnthbGlnbmVkfQpccGFydGlhbF90IHUoeCx5LHQpICsgKFxrYXBwYV4yIC0gXERlbHRhKV57XGFscGhhLzJ9IHUoeCx5LHQpICY9IGYoeCx5LHQpLCAmJiBccXVhZCAoeCx5LHQpIFxpbiBEIFx0aW1lcyAoMCwgVCksIFxcCnUoeCx5LDApICY9IHVfMCh4LHkpLCAmJiBccXVhZCAoeCx5KSBcaW4gRCwgXFwKXHBhcnRpYWxfbiB1KHgseSx0KSAmPSAwLCAmJiBccXVhZCAoeCx5LHQpIFxpbiBccGFydGlhbCBEIFx0aW1lcyAoMCxUKSwKXGVuZHthbGlnbmVkfQpccmlnaHQuClxlbmR7ZXF1YXRpb259CndoZXJlICRcRGVsdGEkIGRlbm90ZXMgdGhlIExhcGxhY2lhbiBvbiAkRCQgd2l0aCBob21vZ2VuZW91cyBOZXVtYW5uIGJvdW5kYXJ5IGNvbmRpdGlvbnMsIGFuZCAkXHBhcnRpYWxfbiQgZGVub3RlcyB0aGUgb3V0d2FyZCBub3JtYWwgZGVyaXZhdGl2ZSBvbiAkXHBhcnRpYWwgRCQuIFRoZSBlaWdlbnZhbHVlcyBvZiAkLVxEZWx0YSQgYXJlIGtub3duIGFuZCBnaXZlbiBieSAkXGxhbWJkYV97bSxufSA9IFxwaV4yKG1eMituXjIpJCBmb3IgJG0sbj0wLDEsMixcZG90cyQsIGFuZCB0aGUgZWlnZW5mdW5jdGlvbnMgYXJlICRccGhpX3ttLG59KHgseSk9XGNvcyhtIFxwaSB4KVxjb3MoblxwaSB5KSQuCgoKQmVsb3cgd2UgdXNlIHRoZSBlaWdlbnBhaXJzIHRvIGNvbnN0cnVjdCBhbiBleGFjdCBzb2x1dGlvbiB0byBlcXVhdGlvbiBcZXFyZWZ7ZXE6bWFpbmVxX29uX3NxdWFyZV9uZXVtYW5ufSBhbmQgY29tcGFyZSBpdCB3aXRoIHRoZSBudW1lcmljYWwgYXBwcm94aW1hdGlvbi4gV2UgdGFrZSAkdV8wKHgseSkgPSB4XzMgXHBoaV97MSwwfSh4LHkpJCB3aXRoICR4XzMgPSAxJCBhbmQgJGYoeCx5LHQpID0geV8yIFxzaW4oXHBpIHQpIFxwaGlfezAsMX0oeCx5KSQgd2l0aCAkeV8yID0gMTAkLiBUaGVuIHRoZSBleGFjdCBzb2x1dGlvbiBpcyBnaXZlbiBieSAKXGJlZ2lue2VxdWF0aW9ufQp1KHgseSx0KSA9IHhfM1x0ZXh0e2V9XnstXGxhbWJkYV57XGFscGhhLzJ9X3sxLDB9dH1ccGhpX3sxLDB9KHgseSkreV8yIEdfMih0KVx0ZXh0e2V9XnstXGxhbWJkYV57XGFscGhhLzJ9X3swLDF9dH1ccGhpX3swLDF9KHgseSksClxlbmR7ZXF1YXRpb259CndoZXJlICRHXzIodCk9IFxkaXNwbGF5c3R5bGVcaW50XzBedCBcdGV4dHtlfV57XGxhbWJkYV57XGFscGhhLzJ9X3swLDF9cn1cc2luKFxwaSByKWRyJC4gQmVsb3cgdGhlIGV4YWN0IHNvbHV0aW9uICBpcyBjb21wdXRlZCBhcyBgVV90cnVlYCBhbmQgY29tcGFyZWQgd2l0aCB0aGUgbnVtZXJpY2FsIGFwcHJveGltYXRpb24gYFVfYXBwcm94YC4KCgpXZSB0YWtlIHBhcmFtZXRlcnMgJFQgPSAyJCwgJFxrYXBwYSA9IDQkLCAkXGFscGhhID0gMS44JCwgJG09NCQsICRoID0gMC4wNSQsIGFuZCB0aW1lIHN0ZXAgc2l6ZSAkXHRhdSA9IDAuMDUkLgoKCgpgYGB7cn0KVF9maW5hbCA8LSAyCmthcHBhIDwtIDQKCmEgPC0gYiA8LSAxCgptX21heCA8LSAxCm5fbWF4IDwtIDEKTl9laWcgPC0gKG1fbWF4ICsgMSkgKiAobl9tYXggKyAxKQpjb2VmZl9VXzAgPC0gcmVwKDAsIE5fZWlnKQpjb2VmZl9VXzBbM10gPC0gMQpjb2VmZl9GRiA8LSByZXAoMCwgTl9laWcpCmNvZWZmX0ZGWzJdIDwtIDEwCgpBQUEgPSAxCk9NRUdBID0gcGkKCmFscGhhIDwtIDEuOAptID0gNApiZXRhIDwtIGFscGhhLzIKCgp0aW1lX3N0ZXAgPC0gMC4wNQp0aW1lX3NlcSA8LSBzZXEoMCwgVF9maW5hbCwgbGVuZ3RoLm91dCA9ICgoVF9maW5hbCAtIDApIC8gdGltZV9zdGVwICsgMSkpCmggPC0gMC4wNQpuX2NvYXJzZSA8LSBjZWlsaW5nKC0xK3NxcnQoYSpiKS9oKQpuX2ZpbmUgPC0gMipuX2NvYXJzZQoKYGBgCgoKCmBgYHtyfQptZXNoX2FuZF9GRU1fY29hcnNlIDwtIGdldHMubWVzaC5hbmQuRkVNLm9uLnJlY3RhbmdsZShhLCBiLCBuX2NvYXJzZSkKbWVzaF9jb2Fyc2UgPC0gbWVzaF9hbmRfRkVNX2NvYXJzZSRtZXNoCkcgPC0gbWVzaF9hbmRfRkVNX2NvYXJzZSRHCkMgPC0gbWVzaF9hbmRfRkVNX2NvYXJzZSRDCkwgPC0ga2FwcGFeMipDICsgRwoKZWlnIDwtIGNvbXB1dGVfdHJ1ZV9laWdlbl9yZWN0YW5nbGUoCiAgICBhID0gYSwgCiAgICBiID0gYiwgCiAgICBsb2MgPSBtZXNoX2NvYXJzZSRsb2MsCiAgICBrYXBwYSA9IGthcHBhLAogICAgYWxwaGEgPSBhbHBoYSwKICAgIG1fbWF4ID0gbV9tYXgsIAogICAgbl9tYXggPSBuX21heCkKCm1fdmVjdG9yID0gZWlnJG1fdmVjdG9yCm5fdmVjdG9yID0gZWlnJG5fdmVjdG9yCgpFSUdFTlZBTF9BTFBIQSA8LSBlaWckRUlHRU5WQUxfQUxQSEEKRUlHRU5GVU4gPC0gZWlnJEVJR0VORlVOCgpVXzAgPC0gRUlHRU5GVU4gJSolIGNvZWZmX1VfMApVX3RydWUgPC0gRUlHRU5GVU4gJSolIAogICAgb3V0ZXIoMTpsZW5ndGgoY29lZmZfVV8wKSwgCiAgICAgICAgICAxOmxlbmd0aCh0aW1lX3NlcSksIAogICAgICAgICAgZnVuY3Rpb24oaSwgaikgKGNvZWZmX1VfMFtpXSArIGNvZWZmX0ZGW2ldICogR19zaW4odCA9IHRpbWVfc2VxW2pdLCBBID0gQUFBLCBsYW1iZGFfal9hbHBoYV9oYWxmID0gRUlHRU5WQUxfQUxQSEFbaV0sIG9tZWdhID0gT01FR0EpKSAqIGV4cCgtRUlHRU5WQUxfQUxQSEFbaV0gKiB0aW1lX3NlcVtqXSkpCmBgYAoKCgpgYGB7cn0KbWVzaF9hbmRfRkVNX2ZpbmUgPC0gZ2V0cy5tZXNoLmFuZC5GRU0ub24ucmVjdGFuZ2xlKGEsIGIsIG5fZmluZSkKbWVzaF9maW5lIDwtIG1lc2hfYW5kX0ZFTV9maW5lJG1lc2gKUHNpIDwtIGZtX2Jhc2lzKG1lc2hfY29hcnNlLCBtZXNoX2ZpbmUkbG9jKQoKZWlnX2ZpbmUgPC0gY29tcHV0ZV90cnVlX2VpZ2VuX3JlY3RhbmdsZSgKICAgIGEgPSBhLCAKICAgIGIgPSBiLCAKICAgIGxvYyA9IG1lc2hfZmluZSRsb2MsCiAgICBrYXBwYSA9IGthcHBhLAogICAgYWxwaGEgPSBhbHBoYSwKICAgIG1fbWF4ID0gbV9tYXgsIAogICAgbl9tYXggPSBuX21heCkKRUlHRU5GVU5fZmluZSA8LSBlaWdfZmluZSRFSUdFTkZVTgoKICAgICMgQ29tcHV0ZSBtYXRyaXggRiB3aXRoIGNvbHVtbnMgRl5rCkZGX2FwcHJveCA8LSB0KFBzaSkgJSolIAogIG1lc2hfYW5kX0ZFTV9maW5lJEMgJSolCiAgRUlHRU5GVU5fZmluZSAlKiUKICAgICAgb3V0ZXIoMTpsZW5ndGgoY29lZmZfRkYpLCAKICAgICAgICAgICAgMTpsZW5ndGgodGltZV9zZXEpLCAKICAgICAgICBmdW5jdGlvbihpLCBqKSBjb2VmZl9GRltpXSAqIGdfc2luKHIgPSB0aW1lX3NlcVtqXSwgQSA9IEFBQSwgb21lZ2EgPSBPTUVHQSkpCgpteV9vcF9mcmFjIDwtIG15LmZyYWN0aW9uYWwub3BlcmF0b3JzLmZyYWMoTCwgYmV0YSwgQywgc2NhbGUuZmFjdG9yID0ga2FwcGFeMiwgbSA9IG0sIHRpbWVfc3RlcCkKVV9hcHByb3ggPC0gc29sdmVfZnJhY3Rpb25hbF9ldm9sdXRpb24obXlfb3BfZnJhYywgdGltZV9zdGVwLCB0aW1lX3NlcSwgdmFsX2F0XzAgPSBVXzAsIFJIU1QgPSBGRl9hcHByb3gpCgoKZGlmZiA8LSBVX3RydWUgLSBVX2FwcHJveAplcnJvciA8LSBzcXJ0KGFzLmRvdWJsZSh0aW1lX3N0ZXAgKiBzdW0oZGlmZiAqIChDICUqJSBkaWZmKSkpKQplcnJvcgpgYGAKCgoKYGBge3IsIGZpZy5oZWlnaHQgPSA2LCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSBjYXB0aW9uZXIoIlRpbWUgZXZvbHV0aW9uIG9mIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGV4YWN0IGFuZCBhcHByb3hpbWF0ZSBzb2x1dGlvbi4iKX0KIyBQbG90IHJlc3VsdHMKcGxvdF8zZF9yZWN0YW5nbGVfc2NhdHRlcihtZXNoX2NvYXJzZSRsb2MsIHRpbWVfc2VxLCBhYnMoZGlmZiksIGZpeGVkX2NvbG9yc2NhbGUgPSBGQUxTRSkKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQgPSA2LCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSBjYXB0aW9uZXIoIlRpbWUgZXZvbHV0aW9uIG9mIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGV4YWN0IGFuZCBhcHByb3hpbWF0ZSBzb2x1dGlvbi4iKX0KIyBQbG90IHJlc3VsdHMKaWR4IDwtIHdoaWNoLm1pbihhYnModGltZV9zZXEgLSAwLjUpKQplcnJvcl9yZWN0YW5nbGUgPC0gcGxvdF8zZF9yZWN0YW5nbGVfb25lY29sKG1lc2hfY29hcnNlLCBhcy52ZWN0b3IoYWJzKGRpZmZbLGlkeF0pKSkKc2F2ZShlcnJvcl9yZWN0YW5nbGUsIGZpbGUgPSBoZXJlOjpoZXJlKCJkYXRhX2ZpbGVzL2V4cF8xX2Vycm9yX3JlY3RhbmdsZS5SRGF0YSIpKQplcnJvcl9yZWN0YW5nbGUKYGBgCgoKYGBge3IsIGZpZy5oZWlnaHQgPSA2LCBvdXQud2lkdGggPSAiMTAwJSIsIGZpZy5jYXAgPSBjYXB0aW9uZXIoIlRpbWUgZXZvbHV0aW9uIG9mIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGV4YWN0IGFuZCBhcHByb3hpbWF0ZSBzb2x1dGlvbi4iKX0KZl9yZWN0IDwtIHBsb3RfM2RfcmVjdGFuZ2xlX29uZWNvbChtZXNoX2NvYXJzZSwgYXMudmVjdG9yKFVfYXBwcm94WyxpZHhdKSkKZl9yZWN0CnNhdmUoZl9yZWN0LCBmaWxlID0gaGVyZTo6aGVyZSgiZGF0YV9maWxlcy9leHBfMV9mX3JlY3QuUkRhdGEiKSkKYGBgCgoKCgo=