2024-09-11 08:58:17 +00:00

9703 lines
782 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>jacobi_method</title><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
<script src='../assets/iframeResizer.contentWindow.min.js'></script>
<style type="text/css">
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: var(--jp-cell-editor-active-background) }
.highlight { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }
.highlight .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */
.highlight .err { color: var(--jp-mirror-editor-error-color) } /* Error */
.highlight .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */
.highlight .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */
.highlight .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */
.highlight .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */
.highlight .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */
.highlight .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */
.highlight .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */
.highlight .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */
.highlight .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */
.highlight .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */
.highlight .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */
.highlight .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */
.highlight .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */
.highlight .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */
.highlight .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */
.highlight .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */
.highlight .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */
.highlight .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */
.highlight .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */
.highlight .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */
.highlight .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */
.highlight .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */
.highlight .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */
.highlight .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */
.highlight .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */
.highlight .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */
.highlight .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */
.highlight .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */
.highlight .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */
.highlight .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */
.highlight .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */
.highlight .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */
</style>
<style type="text/css">
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*
* Mozilla scrollbar styling
*/
/* use standard opaque scrollbars for most nodes */
[data-jp-theme-scrollbars='true'] {
scrollbar-color: rgb(var(--jp-scrollbar-thumb-color))
var(--jp-scrollbar-background-color);
}
/* for code nodes, use a transparent style of scrollbar. These selectors
* will match lower in the tree, and so will override the above */
[data-jp-theme-scrollbars='true'] .CodeMirror-hscrollbar,
[data-jp-theme-scrollbars='true'] .CodeMirror-vscrollbar {
scrollbar-color: rgba(var(--jp-scrollbar-thumb-color), 0.5) transparent;
}
/* tiny scrollbar */
.jp-scrollbar-tiny {
scrollbar-color: rgba(var(--jp-scrollbar-thumb-color), 0.5) transparent;
scrollbar-width: thin;
}
/* tiny scrollbar */
.jp-scrollbar-tiny::-webkit-scrollbar,
.jp-scrollbar-tiny::-webkit-scrollbar-corner {
background-color: transparent;
height: 4px;
width: 4px;
}
.jp-scrollbar-tiny::-webkit-scrollbar-thumb {
background: rgba(var(--jp-scrollbar-thumb-color), 0.5);
}
.jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal {
border-left: 0 solid transparent;
border-right: 0 solid transparent;
}
.jp-scrollbar-tiny::-webkit-scrollbar-track:vertical {
border-top: 0 solid transparent;
border-bottom: 0 solid transparent;
}
/*
* Lumino
*/
.lm-ScrollBar[data-orientation='horizontal'] {
min-height: 16px;
max-height: 16px;
min-width: 45px;
border-top: 1px solid #a0a0a0;
}
.lm-ScrollBar[data-orientation='vertical'] {
min-width: 16px;
max-width: 16px;
min-height: 45px;
border-left: 1px solid #a0a0a0;
}
.lm-ScrollBar-button {
background-color: #f0f0f0;
background-position: center center;
min-height: 15px;
max-height: 15px;
min-width: 15px;
max-width: 15px;
}
.lm-ScrollBar-button:hover {
background-color: #dadada;
}
.lm-ScrollBar-button.lm-mod-active {
background-color: #cdcdcd;
}
.lm-ScrollBar-track {
background: #f0f0f0;
}
.lm-ScrollBar-thumb {
background: #cdcdcd;
}
.lm-ScrollBar-thumb:hover {
background: #bababa;
}
.lm-ScrollBar-thumb.lm-mod-active {
background: #a0a0a0;
}
.lm-ScrollBar[data-orientation='horizontal'] .lm-ScrollBar-thumb {
height: 100%;
min-width: 15px;
border-left: 1px solid #a0a0a0;
border-right: 1px solid #a0a0a0;
}
.lm-ScrollBar[data-orientation='vertical'] .lm-ScrollBar-thumb {
width: 100%;
min-height: 15px;
border-top: 1px solid #a0a0a0;
border-bottom: 1px solid #a0a0a0;
}
.lm-ScrollBar[data-orientation='horizontal']
.lm-ScrollBar-button[data-action='decrement'] {
background-image: var(--jp-icon-caret-left);
background-size: 17px;
}
.lm-ScrollBar[data-orientation='horizontal']
.lm-ScrollBar-button[data-action='increment'] {
background-image: var(--jp-icon-caret-right);
background-size: 17px;
}
.lm-ScrollBar[data-orientation='vertical']
.lm-ScrollBar-button[data-action='decrement'] {
background-image: var(--jp-icon-caret-up);
background-size: 17px;
}
.lm-ScrollBar[data-orientation='vertical']
.lm-ScrollBar-button[data-action='increment'] {
background-image: var(--jp-icon-caret-down);
background-size: 17px;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-Widget {
box-sizing: border-box;
position: relative;
overflow: hidden;
}
.lm-Widget.lm-mod-hidden {
display: none !important;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.lm-AccordionPanel[data-orientation='horizontal'] > .lm-AccordionPanel-title {
/* Title is rotated for horizontal accordion panel using CSS */
display: block;
transform-origin: top left;
transform: rotate(-90deg) translate(-100%);
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-CommandPalette {
display: flex;
flex-direction: column;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lm-CommandPalette-search {
flex: 0 0 auto;
}
.lm-CommandPalette-content {
flex: 1 1 auto;
margin: 0;
padding: 0;
min-height: 0;
overflow: auto;
list-style-type: none;
}
.lm-CommandPalette-header {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.lm-CommandPalette-item {
display: flex;
flex-direction: row;
}
.lm-CommandPalette-itemIcon {
flex: 0 0 auto;
}
.lm-CommandPalette-itemContent {
flex: 1 1 auto;
overflow: hidden;
}
.lm-CommandPalette-itemShortcut {
flex: 0 0 auto;
}
.lm-CommandPalette-itemLabel {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.lm-close-icon {
border: 1px solid transparent;
background-color: transparent;
position: absolute;
z-index: 1;
right: 3%;
top: 0;
bottom: 0;
margin: auto;
padding: 7px 0;
display: none;
vertical-align: middle;
outline: 0;
cursor: pointer;
}
.lm-close-icon:after {
content: 'X';
display: block;
width: 15px;
height: 15px;
text-align: center;
color: #000;
font-weight: normal;
font-size: 12px;
cursor: pointer;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-DockPanel {
z-index: 0;
}
.lm-DockPanel-widget {
z-index: 0;
}
.lm-DockPanel-tabBar {
z-index: 1;
}
.lm-DockPanel-handle {
z-index: 2;
}
.lm-DockPanel-handle.lm-mod-hidden {
display: none !important;
}
.lm-DockPanel-handle:after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
}
.lm-DockPanel-handle[data-orientation='horizontal'] {
cursor: ew-resize;
}
.lm-DockPanel-handle[data-orientation='vertical'] {
cursor: ns-resize;
}
.lm-DockPanel-handle[data-orientation='horizontal']:after {
left: 50%;
min-width: 8px;
transform: translateX(-50%);
}
.lm-DockPanel-handle[data-orientation='vertical']:after {
top: 50%;
min-height: 8px;
transform: translateY(-50%);
}
.lm-DockPanel-overlay {
z-index: 3;
box-sizing: border-box;
pointer-events: none;
}
.lm-DockPanel-overlay.lm-mod-hidden {
display: none !important;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-Menu {
z-index: 10000;
position: absolute;
white-space: nowrap;
overflow-x: hidden;
overflow-y: auto;
outline: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lm-Menu-content {
margin: 0;
padding: 0;
display: table;
list-style-type: none;
}
.lm-Menu-item {
display: table-row;
}
.lm-Menu-item.lm-mod-hidden,
.lm-Menu-item.lm-mod-collapsed {
display: none !important;
}
.lm-Menu-itemIcon,
.lm-Menu-itemSubmenuIcon {
display: table-cell;
text-align: center;
}
.lm-Menu-itemLabel {
display: table-cell;
text-align: left;
}
.lm-Menu-itemShortcut {
display: table-cell;
text-align: right;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-MenuBar {
outline: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lm-MenuBar-content {
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
list-style-type: none;
}
.lm-MenuBar-item {
box-sizing: border-box;
}
.lm-MenuBar-itemIcon,
.lm-MenuBar-itemLabel {
display: inline-block;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-ScrollBar {
display: flex;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lm-ScrollBar[data-orientation='horizontal'] {
flex-direction: row;
}
.lm-ScrollBar[data-orientation='vertical'] {
flex-direction: column;
}
.lm-ScrollBar-button {
box-sizing: border-box;
flex: 0 0 auto;
}
.lm-ScrollBar-track {
box-sizing: border-box;
position: relative;
overflow: hidden;
flex: 1 1 auto;
}
.lm-ScrollBar-thumb {
box-sizing: border-box;
position: absolute;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-SplitPanel-child {
z-index: 0;
}
.lm-SplitPanel-handle {
z-index: 1;
}
.lm-SplitPanel-handle.lm-mod-hidden {
display: none !important;
}
.lm-SplitPanel-handle:after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
}
.lm-SplitPanel[data-orientation='horizontal'] > .lm-SplitPanel-handle {
cursor: ew-resize;
}
.lm-SplitPanel[data-orientation='vertical'] > .lm-SplitPanel-handle {
cursor: ns-resize;
}
.lm-SplitPanel[data-orientation='horizontal'] > .lm-SplitPanel-handle:after {
left: 50%;
min-width: 8px;
transform: translateX(-50%);
}
.lm-SplitPanel[data-orientation='vertical'] > .lm-SplitPanel-handle:after {
top: 50%;
min-height: 8px;
transform: translateY(-50%);
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-TabBar {
display: flex;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lm-TabBar[data-orientation='horizontal'] {
flex-direction: row;
align-items: flex-end;
}
.lm-TabBar[data-orientation='vertical'] {
flex-direction: column;
align-items: flex-end;
}
.lm-TabBar-content {
margin: 0;
padding: 0;
display: flex;
flex: 1 1 auto;
list-style-type: none;
}
.lm-TabBar[data-orientation='horizontal'] > .lm-TabBar-content {
flex-direction: row;
}
.lm-TabBar[data-orientation='vertical'] > .lm-TabBar-content {
flex-direction: column;
}
.lm-TabBar-tab {
display: flex;
flex-direction: row;
box-sizing: border-box;
overflow: hidden;
touch-action: none; /* Disable native Drag/Drop */
}
.lm-TabBar-tabIcon,
.lm-TabBar-tabCloseIcon {
flex: 0 0 auto;
}
.lm-TabBar-tabLabel {
flex: 1 1 auto;
overflow: hidden;
white-space: nowrap;
}
.lm-TabBar-tabInput {
user-select: all;
width: 100%;
box-sizing: border-box;
}
.lm-TabBar-tab.lm-mod-hidden {
display: none !important;
}
.lm-TabBar-addButton.lm-mod-hidden {
display: none !important;
}
.lm-TabBar.lm-mod-dragging .lm-TabBar-tab {
position: relative;
}
.lm-TabBar.lm-mod-dragging[data-orientation='horizontal'] .lm-TabBar-tab {
left: 0;
transition: left 150ms ease;
}
.lm-TabBar.lm-mod-dragging[data-orientation='vertical'] .lm-TabBar-tab {
top: 0;
transition: top 150ms ease;
}
.lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging {
transition: none;
}
.lm-TabBar-tabLabel .lm-TabBar-tabInput {
user-select: all;
width: 100%;
box-sizing: border-box;
background: inherit;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-TabPanel-tabBar {
z-index: 1;
}
.lm-TabPanel-stackedPanel {
z-index: 0;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-Collapse {
display: flex;
flex-direction: column;
align-items: stretch;
}
.jp-Collapse-header {
padding: 1px 12px;
background-color: var(--jp-layout-color1);
border-bottom: solid var(--jp-border-width) var(--jp-border-color2);
color: var(--jp-ui-font-color1);
cursor: pointer;
display: flex;
align-items: center;
font-size: var(--jp-ui-font-size0);
font-weight: 600;
text-transform: uppercase;
user-select: none;
}
.jp-Collapser-icon {
height: 16px;
}
.jp-Collapse-header-collapsed .jp-Collapser-icon {
transform: rotate(-90deg);
margin: auto 0;
}
.jp-Collapser-title {
line-height: 25px;
}
.jp-Collapse-contents {
padding: 0 12px;
background-color: var(--jp-layout-color1);
color: var(--jp-ui-font-color1);
overflow: auto;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/* This file was auto-generated by ensureUiComponents() in @jupyterlab/buildutils */
/**
* (DEPRECATED) Support for consuming icons as CSS background images
*/
/* Icons urls */
:root {
--jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);
--jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);
--jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);
--jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);
--jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);
--jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-code-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBzaGFwZS1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiI+CiAgICA8cGF0aCBkPSJNNi41OSwzLjQxTDIsOEw2LjU5LDEyLjZMOCwxMS4xOEw0LjgyLDhMOCw0LjgyTDYuNTksMy40MU0xMi40MSwzLjQxTDExLDQuODJMMTQuMTgsOEwxMSwxMS4xOEwxMi40MSwxMi42TDE3LDhMMTIuNDEsMy40MU0yMS41OSwxMS41OUwxMy41LDE5LjY4TDkuODMsMTZMOC40MiwxNy40MUwxMy41LDIyLjVMMjMsMTNMMjEuNTksMTEuNTlaIiAvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);
--jp-icon-collapse-all: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTggMmMxIDAgMTEgMCAxMiAwczIgMSAyIDJjMCAxIDAgMTEgMCAxMnMwIDItMiAyQzIwIDE0IDIwIDQgMjAgNFMxMCA0IDYgNGMwLTIgMS0yIDItMnoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTE4IDhjMC0xLTEtMi0yLTJTNSA2IDQgNnMtMiAxLTIgMmMwIDEgMCAxMSAwIDEyczEgMiAyIDJjMSAwIDExIDAgMTIgMHMyLTEgMi0yYzAtMSAwLTExIDAtMTJ6bS0yIDB2MTJINFY4eiIgLz4KICAgICAgICA8cGF0aCBkPSJNNiAxM3YyaDh2LTJ6IiAvPgogICAgPC9nPgo8L3N2Zz4K);
--jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);
--jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);
--jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-error: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjE5IiByPSIyIi8+PHBhdGggZD0iTTEwIDNoNHYxMmgtNHoiLz48L2c+CjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiLz4KPC9zdmc+Cg==);
--jp-icon-expand-all: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTggMmMxIDAgMTEgMCAxMiAwczIgMSAyIDJjMCAxIDAgMTEgMCAxMnMwIDItMiAyQzIwIDE0IDIwIDQgMjAgNFMxMCA0IDYgNGMwLTIgMS0yIDItMnoiIC8+CiAgICAgICAgPHBhdGgKICAgICAgICAgICAgZD0iTTE4IDhjMC0xLTEtMi0yLTJTNSA2IDQgNnMtMiAxLTIgMmMwIDEgMCAxMSAwIDEyczEgMiAyIDJjMSAwIDExIDAgMTIgMHMyLTEgMi0yYzAtMSAwLTExIDAtMTJ6bS0yIDB2MTJINFY4eiIgLz4KICAgICAgICA8cGF0aCBkPSJNMTEgMTBIOXYzSDZ2MmgzdjNoMnYtM2gzdi0yaC0zeiIgLz4KICAgIDwvZz4KPC9zdmc+Cg==);
--jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);
--jp-icon-filter-dot: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTE0LDEyVjE5Ljg4QzE0LjA0LDIwLjE4IDEzLjk0LDIwLjUgMTMuNzEsMjAuNzFDMTMuMzIsMjEuMSAxMi42OSwyMS4xIDEyLjMsMjAuNzFMMTAuMjksMTguN0MxMC4wNiwxOC40NyA5Ljk2LDE4LjE2IDEwLDE3Ljg3VjEySDkuOTdMNC4yMSw0LjYyQzMuODcsNC4xOSAzLjk1LDMuNTYgNC4zOCwzLjIyQzQuNTcsMy4wOCA0Ljc4LDMgNSwzVjNIMTlWM0MxOS4yMiwzIDE5LjQzLDMuMDggMTkuNjIsMy4yMkMyMC4wNSwzLjU2IDIwLjEzLDQuMTkgMTkuNzksNC42MkwxNC4wMywxMkgxNFoiIC8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWRvdCIgZmlsbD0iI0ZGRiI+CiAgICA8Y2lyY2xlIGN4PSIxOCIgY3k9IjE3IiByPSIzIj48L2NpcmNsZT4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-filter: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTE0LDEyVjE5Ljg4QzE0LjA0LDIwLjE4IDEzLjk0LDIwLjUgMTMuNzEsMjAuNzFDMTMuMzIsMjEuMSAxMi42OSwyMS4xIDEyLjMsMjAuNzFMMTAuMjksMTguN0MxMC4wNiwxOC40NyA5Ljk2LDE4LjE2IDEwLDE3Ljg3VjEySDkuOTdMNC4yMSw0LjYyQzMuODcsNC4xOSAzLjk1LDMuNTYgNC4zOCwzLjIyQzQuNTcsMy4wOCA0Ljc4LDMgNSwzVjNIMTlWM0MxOS4yMiwzIDE5LjQzLDMuMDggMTkuNjIsMy4yMkMyMC4wNSwzLjU2IDIwLjEzLDQuMTkgMTkuNzksNC42MkwxNC4wMywxMkgxNFoiIC8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);
--jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);
--jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);
--jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);
--jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);
--jp-icon-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUwLjk3OCA1MC45NzgiPgoJPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KCQk8cGF0aCBkPSJNNDMuNTIsNy40NThDMzguNzExLDIuNjQ4LDMyLjMwNywwLDI1LjQ4OSwwQzE4LjY3LDAsMTIuMjY2LDIuNjQ4LDcuNDU4LDcuNDU4CgkJCWMtOS45NDMsOS45NDEtOS45NDMsMjYuMTE5LDAsMzYuMDYyYzQuODA5LDQuODA5LDExLjIxMiw3LjQ1NiwxOC4wMzEsNy40NThjMCwwLDAuMDAxLDAsMC4wMDIsMAoJCQljNi44MTYsMCwxMy4yMjEtMi42NDgsMTguMDI5LTcuNDU4YzQuODA5LTQuODA5LDcuNDU3LTExLjIxMiw3LjQ1Ny0xOC4wM0M1MC45NzcsMTguNjcsNDguMzI4LDEyLjI2Niw0My41Miw3LjQ1OHoKCQkJIE00Mi4xMDYsNDIuMTA1Yy00LjQzMiw0LjQzMS0xMC4zMzIsNi44NzItMTYuNjE1LDYuODcyaC0wLjAwMmMtNi4yODUtMC4wMDEtMTIuMTg3LTIuNDQxLTE2LjYxNy02Ljg3MgoJCQljLTkuMTYyLTkuMTYzLTkuMTYyLTI0LjA3MSwwLTMzLjIzM0MxMy4zMDMsNC40NCwxOS4yMDQsMiwyNS40ODksMmM2LjI4NCwwLDEyLjE4NiwyLjQ0LDE2LjYxNyw2Ljg3MgoJCQljNC40MzEsNC40MzEsNi44NzEsMTAuMzMyLDYuODcxLDE2LjYxN0M0OC45NzcsMzEuNzcyLDQ2LjUzNiwzNy42NzUsNDIuMTA2LDQyLjEwNXoiLz4KCQk8cGF0aCBkPSJNMjMuNTc4LDMyLjIxOGMtMC4wMjMtMS43MzQsMC4xNDMtMy4wNTksMC40OTYtMy45NzJjMC4zNTMtMC45MTMsMS4xMS0xLjk5NywyLjI3Mi0zLjI1MwoJCQljMC40NjgtMC41MzYsMC45MjMtMS4wNjIsMS4zNjctMS41NzVjMC42MjYtMC43NTMsMS4xMDQtMS40NzgsMS40MzYtMi4xNzVjMC4zMzEtMC43MDcsMC40OTUtMS41NDEsMC40OTUtMi41CgkJCWMwLTEuMDk2LTAuMjYtMi4wODgtMC43NzktMi45NzljLTAuNTY1LTAuODc5LTEuNTAxLTEuMzM2LTIuODA2LTEuMzY5Yy0xLjgwMiwwLjA1Ny0yLjk4NSwwLjY2Ny0zLjU1LDEuODMyCgkJCWMtMC4zMDEsMC41MzUtMC41MDMsMS4xNDEtMC42MDcsMS44MTRjLTAuMTM5LDAuNzA3LTAuMjA3LDEuNDMyLTAuMjA3LDIuMTc0aC0yLjkzN2MtMC4wOTEtMi4yMDgsMC40MDctNC4xMTQsMS40OTMtNS43MTkKCQkJYzEuMDYyLTEuNjQsMi44NTUtMi40ODEsNS4zNzgtMi41MjdjMi4xNiwwLjAyMywzLjg3NCwwLjYwOCw1LjE0MSwxLjc1OGMxLjI3OCwxLjE2LDEuOTI5LDIuNzY0LDEuOTUsNC44MTEKCQkJYzAsMS4xNDItMC4xMzcsMi4xMTEtMC40MSwyLjkxMWMtMC4zMDksMC44NDUtMC43MzEsMS41OTMtMS4yNjgsMi4yNDNjLTAuNDkyLDAuNjUtMS4wNjgsMS4zMTgtMS43MywyLjAwMgoJCQljLTAuNjUsMC42OTctMS4zMTMsMS40NzktMS45ODcsMi4zNDZjLTAuMjM5LDAuMzc3LTAuNDI5LDAuNzc3LTAuNTY1LDEuMTk5Yy0wLjE2LDAuOTU5LTAuMjE3LDEuOTUxLTAuMTcxLDIuOTc5CgkJCUMyNi41ODksMzIuMjE4LDIzLjU3OCwzMi4yMTgsMjMuNTc4LDMyLjIxOHogTTIzLjU3OCwzOC4yMnYtMy40ODRoMy4wNzZ2My40ODRIMjMuNTc4eiIvPgoJPC9nPgo8L3N2Zz4K);
--jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);
--jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);
--jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);
--jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);
--jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);
--jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);
--jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4K);
--jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);
--jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);
--jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);
--jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);
--jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);
--jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);
--jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);
--jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);
--jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);
--jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);
--jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);
--jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);
--jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);
--jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);
--jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);
--jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);
--jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4K);
--jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);
--jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);
--jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);
--jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4K);
--jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);
--jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);
--jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);
--jp-icon-word: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KIDxnIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzQxNDE0MSI+CiAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiA8L2c+CiA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSguNDMgLjA0MDEpIiBmaWxsPSIjZmZmIj4KICA8cGF0aCBkPSJtNC4xNCA4Ljc2cTAuMDY4Mi0xLjg5IDIuNDItMS44OSAxLjE2IDAgMS42OCAwLjQyIDAuNTY3IDAuNDEgMC41NjcgMS4xNnYzLjQ3cTAgMC40NjIgMC41MTQgMC40NjIgMC4xMDMgMCAwLjItMC4wMjMxdjAuNzE0cS0wLjM5OSAwLjEwMy0wLjY1MSAwLjEwMy0wLjQ1MiAwLTAuNjkzLTAuMjItMC4yMzEtMC4yLTAuMjg0LTAuNjYyLTAuOTU2IDAuODcyLTIgMC44NzItMC45MDMgMC0xLjQ3LTAuNDcyLTAuNTI1LTAuNDcyLTAuNTI1LTEuMjYgMC0wLjI2MiAwLjA0NTItMC40NzIgMC4wNTY3LTAuMjIgMC4xMTYtMC4zNzggMC4wNjgyLTAuMTY4IDAuMjMxLTAuMzA0IDAuMTU4LTAuMTQ3IDAuMjYyLTAuMjQyIDAuMTE2LTAuMDkxNCAwLjM2OC0wLjE2OCAwLjI2Mi0wLjA5MTQgMC4zOTktMC4xMjYgMC4xMzYtMC4wNDUyIDAuNDcyLTAuMTAzIDAuMzM2LTAuMDU3OCAwLjUwNC0wLjA3OTggMC4xNTgtMC4wMjMxIDAuNTY3LTAuMDc5OCAwLjU1Ni0wLjA2ODIgMC43NzctMC4yMjEgMC4yMi0wLjE1MiAwLjIyLTAuNDQxdi0wLjI1MnEwLTAuNDMtMC4zNTctMC42NjItMC4zMzYtMC4yMzEtMC45NzYtMC4yMzEtMC42NjIgMC0wLjk5OCAwLjI2Mi0wLjMzNiAwLjI1Mi0wLjM5OSAwLjc5OHptMS44OSAzLjY4cTAuNzg4IDAgMS4yNi0wLjQxIDAuNTA0LTAuNDIgMC41MDQtMC45MDN2LTEuMDVxLTAuMjg0IDAuMTM2LTAuODYxIDAuMjMxLTAuNTY3IDAuMDkxNC0wLjk4NyAwLjE1OC0wLjQyIDAuMDY4Mi0wLjc2NiAwLjMyNi0wLjMzNiAwLjI1Mi0wLjMzNiAwLjcwNHQwLjMwNCAwLjcwNCAwLjg2MSAwLjI1MnoiIHN0cm9rZS13aWR0aD0iMS4wNSIvPgogIDxwYXRoIGQ9Im0xMCA0LjU2aDAuOTQ1djMuMTVxMC42NTEtMC45NzYgMS44OS0wLjk3NiAxLjE2IDAgMS44OSAwLjg0IDAuNjgyIDAuODQgMC42ODIgMi4zMSAwIDEuNDctMC43MDQgMi40Mi0wLjcwNCAwLjg4Mi0xLjg5IDAuODgyLTEuMjYgMC0xLjg5LTEuMDJ2MC43NjZoLTAuODV6bTIuNjIgMy4wNHEtMC43NDYgMC0xLjE2IDAuNjQtMC40NTIgMC42My0wLjQ1MiAxLjY4IDAgMS4wNSAwLjQ1MiAxLjY4dDEuMTYgMC42M3EwLjc3NyAwIDEuMjYtMC42MyAwLjQ5NC0wLjY0IDAuNDk0LTEuNjggMC0xLjA1LTAuNDcyLTEuNjgtMC40NjItMC42NC0xLjI2LTAuNjR6IiBzdHJva2Utd2lkdGg9IjEuMDUiLz4KICA8cGF0aCBkPSJtMi43MyAxNS44IDEzLjYgMC4wMDgxYzAuMDA2OSAwIDAtMi42IDAtMi42IDAtMC4wMDc4LTEuMTUgMC0xLjE1IDAtMC4wMDY5IDAtMC4wMDgzIDEuNS0wLjAwODMgMS41LTJlLTMgLTAuMDAxNC0xMS4zLTAuMDAxNC0xMS4zLTAuMDAxNGwtMC4wMDU5Mi0xLjVjMC0wLjAwNzgtMS4xNyAwLjAwMTMtMS4xNyAwLjAwMTN6IiBzdHJva2Utd2lkdGg9Ii45NzUiLz4KIDwvZz4KPC9zdmc+Cg==);
--jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K);
}
/* Icon CSS class declarations */
.jp-AddAboveIcon {
background-image: var(--jp-icon-add-above);
}
.jp-AddBelowIcon {
background-image: var(--jp-icon-add-below);
}
.jp-AddIcon {
background-image: var(--jp-icon-add);
}
.jp-BellIcon {
background-image: var(--jp-icon-bell);
}
.jp-BugDotIcon {
background-image: var(--jp-icon-bug-dot);
}
.jp-BugIcon {
background-image: var(--jp-icon-bug);
}
.jp-BuildIcon {
background-image: var(--jp-icon-build);
}
.jp-CaretDownEmptyIcon {
background-image: var(--jp-icon-caret-down-empty);
}
.jp-CaretDownEmptyThinIcon {
background-image: var(--jp-icon-caret-down-empty-thin);
}
.jp-CaretDownIcon {
background-image: var(--jp-icon-caret-down);
}
.jp-CaretLeftIcon {
background-image: var(--jp-icon-caret-left);
}
.jp-CaretRightIcon {
background-image: var(--jp-icon-caret-right);
}
.jp-CaretUpEmptyThinIcon {
background-image: var(--jp-icon-caret-up-empty-thin);
}
.jp-CaretUpIcon {
background-image: var(--jp-icon-caret-up);
}
.jp-CaseSensitiveIcon {
background-image: var(--jp-icon-case-sensitive);
}
.jp-CheckIcon {
background-image: var(--jp-icon-check);
}
.jp-CircleEmptyIcon {
background-image: var(--jp-icon-circle-empty);
}
.jp-CircleIcon {
background-image: var(--jp-icon-circle);
}
.jp-ClearIcon {
background-image: var(--jp-icon-clear);
}
.jp-CloseIcon {
background-image: var(--jp-icon-close);
}
.jp-CodeCheckIcon {
background-image: var(--jp-icon-code-check);
}
.jp-CodeIcon {
background-image: var(--jp-icon-code);
}
.jp-CollapseAllIcon {
background-image: var(--jp-icon-collapse-all);
}
.jp-ConsoleIcon {
background-image: var(--jp-icon-console);
}
.jp-CopyIcon {
background-image: var(--jp-icon-copy);
}
.jp-CopyrightIcon {
background-image: var(--jp-icon-copyright);
}
.jp-CutIcon {
background-image: var(--jp-icon-cut);
}
.jp-DeleteIcon {
background-image: var(--jp-icon-delete);
}
.jp-DownloadIcon {
background-image: var(--jp-icon-download);
}
.jp-DuplicateIcon {
background-image: var(--jp-icon-duplicate);
}
.jp-EditIcon {
background-image: var(--jp-icon-edit);
}
.jp-EllipsesIcon {
background-image: var(--jp-icon-ellipses);
}
.jp-ErrorIcon {
background-image: var(--jp-icon-error);
}
.jp-ExpandAllIcon {
background-image: var(--jp-icon-expand-all);
}
.jp-ExtensionIcon {
background-image: var(--jp-icon-extension);
}
.jp-FastForwardIcon {
background-image: var(--jp-icon-fast-forward);
}
.jp-FileIcon {
background-image: var(--jp-icon-file);
}
.jp-FileUploadIcon {
background-image: var(--jp-icon-file-upload);
}
.jp-FilterDotIcon {
background-image: var(--jp-icon-filter-dot);
}
.jp-FilterIcon {
background-image: var(--jp-icon-filter);
}
.jp-FilterListIcon {
background-image: var(--jp-icon-filter-list);
}
.jp-FolderFavoriteIcon {
background-image: var(--jp-icon-folder-favorite);
}
.jp-FolderIcon {
background-image: var(--jp-icon-folder);
}
.jp-HomeIcon {
background-image: var(--jp-icon-home);
}
.jp-Html5Icon {
background-image: var(--jp-icon-html5);
}
.jp-ImageIcon {
background-image: var(--jp-icon-image);
}
.jp-InfoIcon {
background-image: var(--jp-icon-info);
}
.jp-InspectorIcon {
background-image: var(--jp-icon-inspector);
}
.jp-JsonIcon {
background-image: var(--jp-icon-json);
}
.jp-JuliaIcon {
background-image: var(--jp-icon-julia);
}
.jp-JupyterFaviconIcon {
background-image: var(--jp-icon-jupyter-favicon);
}
.jp-JupyterIcon {
background-image: var(--jp-icon-jupyter);
}
.jp-JupyterlabWordmarkIcon {
background-image: var(--jp-icon-jupyterlab-wordmark);
}
.jp-KernelIcon {
background-image: var(--jp-icon-kernel);
}
.jp-KeyboardIcon {
background-image: var(--jp-icon-keyboard);
}
.jp-LaunchIcon {
background-image: var(--jp-icon-launch);
}
.jp-LauncherIcon {
background-image: var(--jp-icon-launcher);
}
.jp-LineFormIcon {
background-image: var(--jp-icon-line-form);
}
.jp-LinkIcon {
background-image: var(--jp-icon-link);
}
.jp-ListIcon {
background-image: var(--jp-icon-list);
}
.jp-MarkdownIcon {
background-image: var(--jp-icon-markdown);
}
.jp-MoveDownIcon {
background-image: var(--jp-icon-move-down);
}
.jp-MoveUpIcon {
background-image: var(--jp-icon-move-up);
}
.jp-NewFolderIcon {
background-image: var(--jp-icon-new-folder);
}
.jp-NotTrustedIcon {
background-image: var(--jp-icon-not-trusted);
}
.jp-NotebookIcon {
background-image: var(--jp-icon-notebook);
}
.jp-NumberingIcon {
background-image: var(--jp-icon-numbering);
}
.jp-OfflineBoltIcon {
background-image: var(--jp-icon-offline-bolt);
}
.jp-PaletteIcon {
background-image: var(--jp-icon-palette);
}
.jp-PasteIcon {
background-image: var(--jp-icon-paste);
}
.jp-PdfIcon {
background-image: var(--jp-icon-pdf);
}
.jp-PythonIcon {
background-image: var(--jp-icon-python);
}
.jp-RKernelIcon {
background-image: var(--jp-icon-r-kernel);
}
.jp-ReactIcon {
background-image: var(--jp-icon-react);
}
.jp-RedoIcon {
background-image: var(--jp-icon-redo);
}
.jp-RefreshIcon {
background-image: var(--jp-icon-refresh);
}
.jp-RegexIcon {
background-image: var(--jp-icon-regex);
}
.jp-RunIcon {
background-image: var(--jp-icon-run);
}
.jp-RunningIcon {
background-image: var(--jp-icon-running);
}
.jp-SaveIcon {
background-image: var(--jp-icon-save);
}
.jp-SearchIcon {
background-image: var(--jp-icon-search);
}
.jp-SettingsIcon {
background-image: var(--jp-icon-settings);
}
.jp-ShareIcon {
background-image: var(--jp-icon-share);
}
.jp-SpreadsheetIcon {
background-image: var(--jp-icon-spreadsheet);
}
.jp-StopIcon {
background-image: var(--jp-icon-stop);
}
.jp-TabIcon {
background-image: var(--jp-icon-tab);
}
.jp-TableRowsIcon {
background-image: var(--jp-icon-table-rows);
}
.jp-TagIcon {
background-image: var(--jp-icon-tag);
}
.jp-TerminalIcon {
background-image: var(--jp-icon-terminal);
}
.jp-TextEditorIcon {
background-image: var(--jp-icon-text-editor);
}
.jp-TocIcon {
background-image: var(--jp-icon-toc);
}
.jp-TreeViewIcon {
background-image: var(--jp-icon-tree-view);
}
.jp-TrustedIcon {
background-image: var(--jp-icon-trusted);
}
.jp-UndoIcon {
background-image: var(--jp-icon-undo);
}
.jp-UserIcon {
background-image: var(--jp-icon-user);
}
.jp-UsersIcon {
background-image: var(--jp-icon-users);
}
.jp-VegaIcon {
background-image: var(--jp-icon-vega);
}
.jp-WordIcon {
background-image: var(--jp-icon-word);
}
.jp-YamlIcon {
background-image: var(--jp-icon-yaml);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* (DEPRECATED) Support for consuming icons as CSS background images
*/
.jp-Icon,
.jp-MaterialIcon {
background-position: center;
background-repeat: no-repeat;
background-size: 16px;
min-width: 16px;
min-height: 16px;
}
.jp-Icon-cover {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/**
* (DEPRECATED) Support for specific CSS icon sizes
*/
.jp-Icon-16 {
background-size: 16px;
min-width: 16px;
min-height: 16px;
}
.jp-Icon-18 {
background-size: 18px;
min-width: 18px;
min-height: 18px;
}
.jp-Icon-20 {
background-size: 20px;
min-width: 20px;
min-height: 20px;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.lm-TabBar .lm-TabBar-addButton {
align-items: center;
display: flex;
padding: 4px;
padding-bottom: 5px;
margin-right: 1px;
background-color: var(--jp-layout-color2);
}
.lm-TabBar .lm-TabBar-addButton:hover {
background-color: var(--jp-layout-color1);
}
.lm-DockPanel-tabBar .lm-TabBar-tab {
width: var(--jp-private-horizontal-tab-width);
}
.lm-DockPanel-tabBar .lm-TabBar-content {
flex: unset;
}
.lm-DockPanel-tabBar[data-orientation='horizontal'] {
flex: 1 1 auto;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Support for icons as inline SVG HTMLElements
*/
/* recolor the primary elements of an icon */
.jp-icon0[fill] {
fill: var(--jp-inverse-layout-color0);
}
.jp-icon1[fill] {
fill: var(--jp-inverse-layout-color1);
}
.jp-icon2[fill] {
fill: var(--jp-inverse-layout-color2);
}
.jp-icon3[fill] {
fill: var(--jp-inverse-layout-color3);
}
.jp-icon4[fill] {
fill: var(--jp-inverse-layout-color4);
}
.jp-icon0[stroke] {
stroke: var(--jp-inverse-layout-color0);
}
.jp-icon1[stroke] {
stroke: var(--jp-inverse-layout-color1);
}
.jp-icon2[stroke] {
stroke: var(--jp-inverse-layout-color2);
}
.jp-icon3[stroke] {
stroke: var(--jp-inverse-layout-color3);
}
.jp-icon4[stroke] {
stroke: var(--jp-inverse-layout-color4);
}
/* recolor the accent elements of an icon */
.jp-icon-accent0[fill] {
fill: var(--jp-layout-color0);
}
.jp-icon-accent1[fill] {
fill: var(--jp-layout-color1);
}
.jp-icon-accent2[fill] {
fill: var(--jp-layout-color2);
}
.jp-icon-accent3[fill] {
fill: var(--jp-layout-color3);
}
.jp-icon-accent4[fill] {
fill: var(--jp-layout-color4);
}
.jp-icon-accent0[stroke] {
stroke: var(--jp-layout-color0);
}
.jp-icon-accent1[stroke] {
stroke: var(--jp-layout-color1);
}
.jp-icon-accent2[stroke] {
stroke: var(--jp-layout-color2);
}
.jp-icon-accent3[stroke] {
stroke: var(--jp-layout-color3);
}
.jp-icon-accent4[stroke] {
stroke: var(--jp-layout-color4);
}
/* set the color of an icon to transparent */
.jp-icon-none[fill] {
fill: none;
}
.jp-icon-none[stroke] {
stroke: none;
}
/* brand icon colors. Same for light and dark */
.jp-icon-brand0[fill] {
fill: var(--jp-brand-color0);
}
.jp-icon-brand1[fill] {
fill: var(--jp-brand-color1);
}
.jp-icon-brand2[fill] {
fill: var(--jp-brand-color2);
}
.jp-icon-brand3[fill] {
fill: var(--jp-brand-color3);
}
.jp-icon-brand4[fill] {
fill: var(--jp-brand-color4);
}
.jp-icon-brand0[stroke] {
stroke: var(--jp-brand-color0);
}
.jp-icon-brand1[stroke] {
stroke: var(--jp-brand-color1);
}
.jp-icon-brand2[stroke] {
stroke: var(--jp-brand-color2);
}
.jp-icon-brand3[stroke] {
stroke: var(--jp-brand-color3);
}
.jp-icon-brand4[stroke] {
stroke: var(--jp-brand-color4);
}
/* warn icon colors. Same for light and dark */
.jp-icon-warn0[fill] {
fill: var(--jp-warn-color0);
}
.jp-icon-warn1[fill] {
fill: var(--jp-warn-color1);
}
.jp-icon-warn2[fill] {
fill: var(--jp-warn-color2);
}
.jp-icon-warn3[fill] {
fill: var(--jp-warn-color3);
}
.jp-icon-warn0[stroke] {
stroke: var(--jp-warn-color0);
}
.jp-icon-warn1[stroke] {
stroke: var(--jp-warn-color1);
}
.jp-icon-warn2[stroke] {
stroke: var(--jp-warn-color2);
}
.jp-icon-warn3[stroke] {
stroke: var(--jp-warn-color3);
}
/* icon colors that contrast well with each other and most backgrounds */
.jp-icon-contrast0[fill] {
fill: var(--jp-icon-contrast-color0);
}
.jp-icon-contrast1[fill] {
fill: var(--jp-icon-contrast-color1);
}
.jp-icon-contrast2[fill] {
fill: var(--jp-icon-contrast-color2);
}
.jp-icon-contrast3[fill] {
fill: var(--jp-icon-contrast-color3);
}
.jp-icon-contrast0[stroke] {
stroke: var(--jp-icon-contrast-color0);
}
.jp-icon-contrast1[stroke] {
stroke: var(--jp-icon-contrast-color1);
}
.jp-icon-contrast2[stroke] {
stroke: var(--jp-icon-contrast-color2);
}
.jp-icon-contrast3[stroke] {
stroke: var(--jp-icon-contrast-color3);
}
.jp-icon-dot[fill] {
fill: var(--jp-warn-color0);
}
.jp-jupyter-icon-color[fill] {
fill: var(--jp-jupyter-icon-color, var(--jp-warn-color0));
}
.jp-notebook-icon-color[fill] {
fill: var(--jp-notebook-icon-color, var(--jp-warn-color0));
}
.jp-json-icon-color[fill] {
fill: var(--jp-json-icon-color, var(--jp-warn-color1));
}
.jp-console-icon-color[fill] {
fill: var(--jp-console-icon-color, white);
}
.jp-console-icon-background-color[fill] {
fill: var(--jp-console-icon-background-color, var(--jp-brand-color1));
}
.jp-terminal-icon-color[fill] {
fill: var(--jp-terminal-icon-color, var(--jp-layout-color2));
}
.jp-terminal-icon-background-color[fill] {
fill: var(
--jp-terminal-icon-background-color,
var(--jp-inverse-layout-color2)
);
}
.jp-text-editor-icon-color[fill] {
fill: var(--jp-text-editor-icon-color, var(--jp-inverse-layout-color3));
}
.jp-inspector-icon-color[fill] {
fill: var(--jp-inspector-icon-color, var(--jp-inverse-layout-color3));
}
/* CSS for icons in selected filebrowser listing items */
.jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill] {
fill: #fff;
}
.jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill] {
fill: var(--jp-brand-color1);
}
/* stylelint-disable selector-max-class, selector-max-compound-selectors */
/**
* TODO: come up with non css-hack solution for showing the busy icon on top
* of the close icon
* CSS for complex behavior of close icon of tabs in the main area tabbar
*/
.lm-DockPanel-tabBar
.lm-TabBar-tab.lm-mod-closable.jp-mod-dirty
> .lm-TabBar-tabCloseIcon
> :not(:hover)
> .jp-icon3[fill] {
fill: none;
}
.lm-DockPanel-tabBar
.lm-TabBar-tab.lm-mod-closable.jp-mod-dirty
> .lm-TabBar-tabCloseIcon
> :not(:hover)
> .jp-icon-busy[fill] {
fill: var(--jp-inverse-layout-color3);
}
/* stylelint-enable selector-max-class, selector-max-compound-selectors */
/* CSS for icons in status bar */
#jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill] {
fill: #fff;
}
#jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill] {
fill: var(--jp-brand-color1);
}
/* special handling for splash icon CSS. While the theme CSS reloads during
splash, the splash icon can loose theming. To prevent that, we set a
default for its color variable */
:root {
--jp-warn-color0: var(--md-orange-700);
}
/* not sure what to do with this one, used in filebrowser listing */
.jp-DragIcon {
margin-right: 4px;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/**
* Support for alt colors for icons as inline SVG HTMLElements
*/
/* alt recolor the primary elements of an icon */
.jp-icon-alt .jp-icon0[fill] {
fill: var(--jp-layout-color0);
}
.jp-icon-alt .jp-icon1[fill] {
fill: var(--jp-layout-color1);
}
.jp-icon-alt .jp-icon2[fill] {
fill: var(--jp-layout-color2);
}
.jp-icon-alt .jp-icon3[fill] {
fill: var(--jp-layout-color3);
}
.jp-icon-alt .jp-icon4[fill] {
fill: var(--jp-layout-color4);
}
.jp-icon-alt .jp-icon0[stroke] {
stroke: var(--jp-layout-color0);
}
.jp-icon-alt .jp-icon1[stroke] {
stroke: var(--jp-layout-color1);
}
.jp-icon-alt .jp-icon2[stroke] {
stroke: var(--jp-layout-color2);
}
.jp-icon-alt .jp-icon3[stroke] {
stroke: var(--jp-layout-color3);
}
.jp-icon-alt .jp-icon4[stroke] {
stroke: var(--jp-layout-color4);
}
/* alt recolor the accent elements of an icon */
.jp-icon-alt .jp-icon-accent0[fill] {
fill: var(--jp-inverse-layout-color0);
}
.jp-icon-alt .jp-icon-accent1[fill] {
fill: var(--jp-inverse-layout-color1);
}
.jp-icon-alt .jp-icon-accent2[fill] {
fill: var(--jp-inverse-layout-color2);
}
.jp-icon-alt .jp-icon-accent3[fill] {
fill: var(--jp-inverse-layout-color3);
}
.jp-icon-alt .jp-icon-accent4[fill] {
fill: var(--jp-inverse-layout-color4);
}
.jp-icon-alt .jp-icon-accent0[stroke] {
stroke: var(--jp-inverse-layout-color0);
}
.jp-icon-alt .jp-icon-accent1[stroke] {
stroke: var(--jp-inverse-layout-color1);
}
.jp-icon-alt .jp-icon-accent2[stroke] {
stroke: var(--jp-inverse-layout-color2);
}
.jp-icon-alt .jp-icon-accent3[stroke] {
stroke: var(--jp-inverse-layout-color3);
}
.jp-icon-alt .jp-icon-accent4[stroke] {
stroke: var(--jp-inverse-layout-color4);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content {
display: none !important;
}
/**
* Support for hover colors for icons as inline SVG HTMLElements
*/
/**
* regular colors
*/
/* recolor the primary elements of an icon */
.jp-icon-hover :hover .jp-icon0-hover[fill] {
fill: var(--jp-inverse-layout-color0);
}
.jp-icon-hover :hover .jp-icon1-hover[fill] {
fill: var(--jp-inverse-layout-color1);
}
.jp-icon-hover :hover .jp-icon2-hover[fill] {
fill: var(--jp-inverse-layout-color2);
}
.jp-icon-hover :hover .jp-icon3-hover[fill] {
fill: var(--jp-inverse-layout-color3);
}
.jp-icon-hover :hover .jp-icon4-hover[fill] {
fill: var(--jp-inverse-layout-color4);
}
.jp-icon-hover :hover .jp-icon0-hover[stroke] {
stroke: var(--jp-inverse-layout-color0);
}
.jp-icon-hover :hover .jp-icon1-hover[stroke] {
stroke: var(--jp-inverse-layout-color1);
}
.jp-icon-hover :hover .jp-icon2-hover[stroke] {
stroke: var(--jp-inverse-layout-color2);
}
.jp-icon-hover :hover .jp-icon3-hover[stroke] {
stroke: var(--jp-inverse-layout-color3);
}
.jp-icon-hover :hover .jp-icon4-hover[stroke] {
stroke: var(--jp-inverse-layout-color4);
}
/* recolor the accent elements of an icon */
.jp-icon-hover :hover .jp-icon-accent0-hover[fill] {
fill: var(--jp-layout-color0);
}
.jp-icon-hover :hover .jp-icon-accent1-hover[fill] {
fill: var(--jp-layout-color1);
}
.jp-icon-hover :hover .jp-icon-accent2-hover[fill] {
fill: var(--jp-layout-color2);
}
.jp-icon-hover :hover .jp-icon-accent3-hover[fill] {
fill: var(--jp-layout-color3);
}
.jp-icon-hover :hover .jp-icon-accent4-hover[fill] {
fill: var(--jp-layout-color4);
}
.jp-icon-hover :hover .jp-icon-accent0-hover[stroke] {
stroke: var(--jp-layout-color0);
}
.jp-icon-hover :hover .jp-icon-accent1-hover[stroke] {
stroke: var(--jp-layout-color1);
}
.jp-icon-hover :hover .jp-icon-accent2-hover[stroke] {
stroke: var(--jp-layout-color2);
}
.jp-icon-hover :hover .jp-icon-accent3-hover[stroke] {
stroke: var(--jp-layout-color3);
}
.jp-icon-hover :hover .jp-icon-accent4-hover[stroke] {
stroke: var(--jp-layout-color4);
}
/* set the color of an icon to transparent */
.jp-icon-hover :hover .jp-icon-none-hover[fill] {
fill: none;
}
.jp-icon-hover :hover .jp-icon-none-hover[stroke] {
stroke: none;
}
/**
* inverse colors
*/
/* inverse recolor the primary elements of an icon */
.jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill] {
fill: var(--jp-layout-color0);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill] {
fill: var(--jp-layout-color1);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill] {
fill: var(--jp-layout-color2);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill] {
fill: var(--jp-layout-color3);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill] {
fill: var(--jp-layout-color4);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke] {
stroke: var(--jp-layout-color0);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke] {
stroke: var(--jp-layout-color1);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke] {
stroke: var(--jp-layout-color2);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke] {
stroke: var(--jp-layout-color3);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke] {
stroke: var(--jp-layout-color4);
}
/* inverse recolor the accent elements of an icon */
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill] {
fill: var(--jp-inverse-layout-color0);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill] {
fill: var(--jp-inverse-layout-color1);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill] {
fill: var(--jp-inverse-layout-color2);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill] {
fill: var(--jp-inverse-layout-color3);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill] {
fill: var(--jp-inverse-layout-color4);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke] {
stroke: var(--jp-inverse-layout-color0);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke] {
stroke: var(--jp-inverse-layout-color1);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke] {
stroke: var(--jp-inverse-layout-color2);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke] {
stroke: var(--jp-inverse-layout-color3);
}
.jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke] {
stroke: var(--jp-inverse-layout-color4);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-IFrame {
width: 100%;
height: 100%;
}
.jp-IFrame > iframe {
border: none;
}
/*
When drag events occur, `lm-mod-override-cursor` is added to the body.
Because iframes steal all cursor events, the following two rules are necessary
to suppress pointer events while resize drags are occurring. There may be a
better solution to this problem.
*/
body.lm-mod-override-cursor .jp-IFrame {
position: relative;
}
body.lm-mod-override-cursor .jp-IFrame::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2016, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-HoverBox {
position: fixed;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-FormGroup-content fieldset {
border: none;
padding: 0;
min-width: 0;
width: 100%;
}
/* stylelint-disable selector-max-type */
.jp-FormGroup-content fieldset .jp-inputFieldWrapper input,
.jp-FormGroup-content fieldset .jp-inputFieldWrapper select,
.jp-FormGroup-content fieldset .jp-inputFieldWrapper textarea {
font-size: var(--jp-content-font-size2);
border-color: var(--jp-input-border-color);
border-style: solid;
border-radius: var(--jp-border-radius);
border-width: 1px;
padding: 6px 8px;
background: none;
color: var(--jp-ui-font-color0);
height: inherit;
}
.jp-FormGroup-content fieldset input[type='checkbox'] {
position: relative;
top: 2px;
margin-left: 0;
}
.jp-FormGroup-content button.jp-mod-styled {
cursor: pointer;
}
.jp-FormGroup-content .checkbox label {
cursor: pointer;
font-size: var(--jp-content-font-size1);
}
.jp-FormGroup-content .jp-root > fieldset > legend {
display: none;
}
.jp-FormGroup-content .jp-root > fieldset > p {
display: none;
}
/** copy of `input.jp-mod-styled:focus` style */
.jp-FormGroup-content fieldset input:focus,
.jp-FormGroup-content fieldset select:focus {
-moz-outline-radius: unset;
outline: var(--jp-border-width) solid var(--md-blue-500);
outline-offset: -1px;
box-shadow: inset 0 0 4px var(--md-blue-300);
}
.jp-FormGroup-content fieldset input:hover:not(:focus),
.jp-FormGroup-content fieldset select:hover:not(:focus) {
background-color: var(--jp-border-color2);
}
/* stylelint-enable selector-max-type */
.jp-FormGroup-content .checkbox .field-description {
/* Disable default description field for checkbox:
because other widgets do not have description fields,
we add descriptions to each widget on the field level.
*/
display: none;
}
.jp-FormGroup-content #root__description {
display: none;
}
.jp-FormGroup-content .jp-modifiedIndicator {
width: 5px;
background-color: var(--jp-brand-color2);
margin-top: 0;
margin-left: calc(var(--jp-private-settingeditor-modifier-indent) * -1);
flex-shrink: 0;
}
.jp-FormGroup-content .jp-modifiedIndicator.jp-errorIndicator {
background-color: var(--jp-error-color0);
margin-right: 0.5em;
}
/* RJSF ARRAY style */
.jp-arrayFieldWrapper legend {
font-size: var(--jp-content-font-size2);
color: var(--jp-ui-font-color0);
flex-basis: 100%;
padding: 4px 0;
font-weight: var(--jp-content-heading-font-weight);
border-bottom: 1px solid var(--jp-border-color2);
}
.jp-arrayFieldWrapper .field-description {
padding: 4px 0;
white-space: pre-wrap;
}
.jp-arrayFieldWrapper .array-item {
width: 100%;
border: 1px solid var(--jp-border-color2);
border-radius: 4px;
margin: 4px;
}
.jp-ArrayOperations {
display: flex;
margin-left: 8px;
}
.jp-ArrayOperationsButton {
margin: 2px;
}
.jp-ArrayOperationsButton .jp-icon3[fill] {
fill: var(--jp-ui-font-color0);
}
button.jp-ArrayOperationsButton.jp-mod-styled:disabled {
cursor: not-allowed;
opacity: 0.5;
}
/* RJSF form validation error */
.jp-FormGroup-content .validationErrors {
color: var(--jp-error-color0);
}
/* Hide panel level error as duplicated the field level error */
.jp-FormGroup-content .panel.errors {
display: none;
}
/* RJSF normal content (settings-editor) */
.jp-FormGroup-contentNormal {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.jp-FormGroup-contentNormal .jp-FormGroup-contentItem {
margin-left: 7px;
color: var(--jp-ui-font-color0);
}
.jp-FormGroup-contentNormal .jp-FormGroup-description {
flex-basis: 100%;
padding: 4px 7px;
}
.jp-FormGroup-contentNormal .jp-FormGroup-default {
flex-basis: 100%;
padding: 4px 7px;
}
.jp-FormGroup-contentNormal .jp-FormGroup-fieldLabel {
font-size: var(--jp-content-font-size1);
font-weight: normal;
min-width: 120px;
}
.jp-FormGroup-contentNormal fieldset:not(:first-child) {
margin-left: 7px;
}
.jp-FormGroup-contentNormal .field-array-of-string .array-item {
/* Display `jp-ArrayOperations` buttons side-by-side with content except
for small screens where flex-wrap will place them one below the other.
*/
display: flex;
align-items: center;
flex-wrap: wrap;
}
.jp-FormGroup-contentNormal .jp-objectFieldWrapper .form-group {
padding: 2px 8px 2px var(--jp-private-settingeditor-modifier-indent);
margin-top: 2px;
}
/* RJSF compact content (metadata-form) */
.jp-FormGroup-content.jp-FormGroup-contentCompact {
width: 100%;
}
.jp-FormGroup-contentCompact .form-group {
display: flex;
padding: 0.5em 0.2em 0.5em 0;
}
.jp-FormGroup-contentCompact
.jp-FormGroup-compactTitle
.jp-FormGroup-description {
font-size: var(--jp-ui-font-size1);
color: var(--jp-ui-font-color2);
}
.jp-FormGroup-contentCompact .jp-FormGroup-fieldLabel {
padding-bottom: 0.3em;
}
.jp-FormGroup-contentCompact .jp-inputFieldWrapper .form-control {
width: 100%;
box-sizing: border-box;
}
.jp-FormGroup-contentCompact .jp-arrayFieldWrapper .jp-FormGroup-compactTitle {
padding-bottom: 7px;
}
.jp-FormGroup-contentCompact
.jp-objectFieldWrapper
.jp-objectFieldWrapper
.form-group {
padding: 2px 8px 2px var(--jp-private-settingeditor-modifier-indent);
margin-top: 2px;
}
.jp-FormGroup-contentCompact ul.error-detail {
margin-block-start: 0.5em;
margin-block-end: 0.5em;
padding-inline-start: 1em;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.jp-SidePanel {
display: flex;
flex-direction: column;
min-width: var(--jp-sidebar-min-width);
overflow-y: auto;
color: var(--jp-ui-font-color1);
background: var(--jp-layout-color1);
font-size: var(--jp-ui-font-size1);
}
.jp-SidePanel-header {
flex: 0 0 auto;
display: flex;
border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
font-size: var(--jp-ui-font-size0);
font-weight: 600;
letter-spacing: 1px;
margin: 0;
padding: 2px;
text-transform: uppercase;
}
.jp-SidePanel-toolbar {
flex: 0 0 auto;
}
.jp-SidePanel-content {
flex: 1 1 auto;
}
.jp-SidePanel-toolbar,
.jp-AccordionPanel-toolbar {
height: var(--jp-private-toolbar-height);
}
.jp-SidePanel-toolbar.jp-Toolbar-micro {
display: none;
}
.lm-AccordionPanel .jp-AccordionPanel-title {
box-sizing: border-box;
line-height: 25px;
margin: 0;
display: flex;
align-items: center;
background: var(--jp-layout-color1);
color: var(--jp-ui-font-color1);
border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);
box-shadow: var(--jp-toolbar-box-shadow);
font-size: var(--jp-ui-font-size0);
}
.jp-AccordionPanel-title {
cursor: pointer;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
text-transform: uppercase;
}
.lm-AccordionPanel[data-orientation='horizontal'] > .jp-AccordionPanel-title {
/* Title is rotated for horizontal accordion panel using CSS */
display: block;
transform-origin: top left;
transform: rotate(-90deg) translate(-100%);
}
.jp-AccordionPanel-title .lm-AccordionPanel-titleLabel {
user-select: none;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.jp-AccordionPanel-title .lm-AccordionPanel-titleCollapser {
transform: rotate(-90deg);
margin: auto 0;
height: 16px;
}
.jp-AccordionPanel-title.lm-mod-expanded .lm-AccordionPanel-titleCollapser {
transform: rotate(0deg);
}
.lm-AccordionPanel .jp-AccordionPanel-toolbar {
background: none;
box-shadow: none;
border: none;
margin-left: auto;
}
.lm-AccordionPanel .lm-SplitPanel-handle:hover {
background: var(--jp-layout-color3);
}
.jp-text-truncated {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2017, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-Spinner {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: var(--jp-layout-color0);
outline: none;
}
.jp-SpinnerContent {
font-size: 10px;
margin: 50px auto;
text-indent: -9999em;
width: 3em;
height: 3em;
border-radius: 50%;
background: var(--jp-brand-color3);
background: linear-gradient(
to right,
#f37626 10%,
rgba(255, 255, 255, 0) 42%
);
position: relative;
animation: load3 1s infinite linear, fadeIn 1s;
}
.jp-SpinnerContent::before {
width: 50%;
height: 50%;
background: #f37626;
border-radius: 100% 0 0;
position: absolute;
top: 0;
left: 0;
content: '';
}
.jp-SpinnerContent::after {
background: var(--jp-layout-color0);
width: 75%;
height: 75%;
border-radius: 50%;
content: '';
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes load3 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
button.jp-mod-styled {
font-size: var(--jp-ui-font-size1);
color: var(--jp-ui-font-color0);
border: none;
box-sizing: border-box;
text-align: center;
line-height: 32px;
height: 32px;
padding: 0 12px;
letter-spacing: 0.8px;
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
input.jp-mod-styled {
background: var(--jp-input-background);
height: 28px;
box-sizing: border-box;
border: var(--jp-border-width) solid var(--jp-border-color1);
padding-left: 7px;
padding-right: 7px;
font-size: var(--jp-ui-font-size2);
color: var(--jp-ui-font-color0);
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
input[type='checkbox'].jp-mod-styled {
appearance: checkbox;
-webkit-appearance: checkbox;
-moz-appearance: checkbox;
height: auto;
}
input.jp-mod-styled:focus {
border: var(--jp-border-width) solid var(--md-blue-500);
box-shadow: inset 0 0 4px var(--md-blue-300);
}
.jp-select-wrapper {
display: flex;
position: relative;
flex-direction: column;
padding: 1px;
background-color: var(--jp-layout-color1);
box-sizing: border-box;
margin-bottom: 12px;
}
.jp-select-wrapper:not(.multiple) {
height: 28px;
}
.jp-select-wrapper.jp-mod-focused select.jp-mod-styled {
border: var(--jp-border-width) solid var(--jp-input-active-border-color);
box-shadow: var(--jp-input-box-shadow);
background-color: var(--jp-input-active-background);
}
select.jp-mod-styled:hover {
cursor: pointer;
color: var(--jp-ui-font-color0);
background-color: var(--jp-input-hover-background);
box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5);
}
select.jp-mod-styled {
flex: 1 1 auto;
width: 100%;
font-size: var(--jp-ui-font-size2);
background: var(--jp-input-background);
color: var(--jp-ui-font-color0);
padding: 0 25px 0 8px;
border: var(--jp-border-width) solid var(--jp-input-border-color);
border-radius: 0;
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
select.jp-mod-styled:not([multiple]) {
height: 32px;
}
select.jp-mod-styled[multiple] {
max-height: 200px;
overflow-y: auto;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-switch {
display: flex;
align-items: center;
padding-left: 4px;
padding-right: 4px;
font-size: var(--jp-ui-font-size1);
background-color: transparent;
color: var(--jp-ui-font-color1);
border: none;
height: 20px;
}
.jp-switch:hover {
background-color: var(--jp-layout-color2);
}
.jp-switch-label {
margin-right: 5px;
font-family: var(--jp-ui-font-family);
}
.jp-switch-track {
cursor: pointer;
background-color: var(--jp-switch-color, var(--jp-border-color1));
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
height: 16px;
width: 35px;
position: relative;
}
.jp-switch-track::before {
content: '';
position: absolute;
height: 10px;
width: 10px;
margin: 3px;
left: 0;
background-color: var(--jp-ui-inverse-font-color1);
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}
.jp-switch[aria-checked='true'] .jp-switch-track {
background-color: var(--jp-switch-true-position-color, var(--jp-warn-color0));
}
.jp-switch[aria-checked='true'] .jp-switch-track::before {
/* track width (35) - margins (3 + 3) - thumb width (10) */
left: 19px;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2016, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
:root {
--jp-private-toolbar-height: calc(
28px + var(--jp-border-width)
); /* leave 28px for content */
}
.jp-Toolbar {
color: var(--jp-ui-font-color1);
flex: 0 0 auto;
display: flex;
flex-direction: row;
border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);
box-shadow: var(--jp-toolbar-box-shadow);
background: var(--jp-toolbar-background);
min-height: var(--jp-toolbar-micro-height);
padding: 2px;
z-index: 8;
overflow-x: hidden;
}
/* Toolbar items */
.jp-Toolbar > .jp-Toolbar-item.jp-Toolbar-spacer {
flex-grow: 1;
flex-shrink: 1;
}
.jp-Toolbar-item.jp-Toolbar-kernelStatus {
display: inline-block;
width: 32px;
background-repeat: no-repeat;
background-position: center;
background-size: 16px;
}
.jp-Toolbar > .jp-Toolbar-item {
flex: 0 0 auto;
display: flex;
padding-left: 1px;
padding-right: 1px;
font-size: var(--jp-ui-font-size1);
line-height: var(--jp-private-toolbar-height);
height: 100%;
}
/* Toolbar buttons */
/* This is the div we use to wrap the react component into a Widget */
div.jp-ToolbarButton {
color: transparent;
border: none;
box-sizing: border-box;
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
padding: 0;
margin: 0;
}
button.jp-ToolbarButtonComponent {
background: var(--jp-layout-color1);
border: none;
box-sizing: border-box;
outline: none;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
padding: 0 6px;
margin: 0;
height: 24px;
border-radius: var(--jp-border-radius);
display: flex;
align-items: center;
text-align: center;
font-size: 14px;
min-width: unset;
min-height: unset;
}
button.jp-ToolbarButtonComponent:disabled {
opacity: 0.4;
}
button.jp-ToolbarButtonComponent > span {
padding: 0;
flex: 0 0 auto;
}
button.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label {
font-size: var(--jp-ui-font-size1);
line-height: 100%;
padding-left: 2px;
color: var(--jp-ui-font-color1);
font-family: var(--jp-ui-font-family);
}
#jp-main-dock-panel[data-mode='single-document']
.jp-MainAreaWidget
> .jp-Toolbar.jp-Toolbar-micro {
padding: 0;
min-height: 0;
}
#jp-main-dock-panel[data-mode='single-document']
.jp-MainAreaWidget
> .jp-Toolbar {
border: none;
box-shadow: none;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.jp-WindowedPanel-outer {
position: relative;
overflow-y: auto;
}
.jp-WindowedPanel-inner {
position: relative;
}
.jp-WindowedPanel-window {
position: absolute;
left: 0;
right: 0;
overflow: visible;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/* Sibling imports */
body {
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
}
/* Disable native link decoration styles everywhere outside of dialog boxes */
a {
text-decoration: unset;
color: unset;
}
a:hover {
text-decoration: unset;
color: unset;
}
/* Accessibility for links inside dialog box text */
.jp-Dialog-content a {
text-decoration: revert;
color: var(--jp-content-link-color);
}
.jp-Dialog-content a:hover {
text-decoration: revert;
}
/* Styles for ui-components */
.jp-Button {
color: var(--jp-ui-font-color2);
border-radius: var(--jp-border-radius);
padding: 0 12px;
font-size: var(--jp-ui-font-size1);
/* Copy from blueprint 3 */
display: inline-flex;
flex-direction: row;
border: none;
cursor: pointer;
align-items: center;
justify-content: center;
text-align: left;
vertical-align: middle;
min-height: 30px;
min-width: 30px;
}
.jp-Button:disabled {
cursor: not-allowed;
}
.jp-Button:empty {
padding: 0 !important;
}
.jp-Button.jp-mod-small {
min-height: 24px;
min-width: 24px;
font-size: 12px;
padding: 0 7px;
}
/* Use our own theme for hover styles */
.jp-Button.jp-mod-minimal:hover {
background-color: var(--jp-layout-color2);
}
.jp-Button.jp-mod-minimal {
background: none;
}
.jp-InputGroup {
display: block;
position: relative;
}
.jp-InputGroup input {
box-sizing: border-box;
border: none;
border-radius: 0;
background-color: transparent;
color: var(--jp-ui-font-color0);
box-shadow: inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color);
padding-bottom: 0;
padding-top: 0;
padding-left: 10px;
padding-right: 28px;
position: relative;
width: 100%;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
font-size: 14px;
font-weight: 400;
height: 30px;
line-height: 30px;
outline: none;
vertical-align: middle;
}
.jp-InputGroup input:focus {
box-shadow: inset 0 0 0 var(--jp-border-width)
var(--jp-input-active-box-shadow-color),
inset 0 0 0 3px var(--jp-input-active-box-shadow-color);
}
.jp-InputGroup input:disabled {
cursor: not-allowed;
resize: block;
background-color: var(--jp-layout-color2);
color: var(--jp-ui-font-color2);
}
.jp-InputGroup input:disabled ~ span {
cursor: not-allowed;
color: var(--jp-ui-font-color2);
}
.jp-InputGroup input::placeholder,
input::placeholder {
color: var(--jp-ui-font-color2);
}
.jp-InputGroupAction {
position: absolute;
bottom: 1px;
right: 0;
padding: 6px;
}
.jp-HTMLSelect.jp-DefaultStyle select {
background-color: initial;
border: none;
border-radius: 0;
box-shadow: none;
color: var(--jp-ui-font-color0);
display: block;
font-size: var(--jp-ui-font-size1);
font-family: var(--jp-ui-font-family);
height: 24px;
line-height: 14px;
padding: 0 25px 0 10px;
text-align: left;
-moz-appearance: none;
-webkit-appearance: none;
}
.jp-HTMLSelect.jp-DefaultStyle select:disabled {
background-color: var(--jp-layout-color2);
color: var(--jp-ui-font-color2);
cursor: not-allowed;
resize: block;
}
.jp-HTMLSelect.jp-DefaultStyle select:disabled ~ span {
cursor: not-allowed;
}
/* Use our own theme for hover and option styles */
/* stylelint-disable-next-line selector-max-type */
.jp-HTMLSelect.jp-DefaultStyle select:hover,
.jp-HTMLSelect.jp-DefaultStyle select > option {
background-color: var(--jp-layout-color2);
color: var(--jp-ui-font-color0);
}
select {
box-sizing: border-box;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Styles
|----------------------------------------------------------------------------*/
.jp-StatusBar-Widget {
display: flex;
align-items: center;
background: var(--jp-layout-color2);
min-height: var(--jp-statusbar-height);
justify-content: space-between;
padding: 0 10px;
}
.jp-StatusBar-Left {
display: flex;
align-items: center;
flex-direction: row;
}
.jp-StatusBar-Middle {
display: flex;
align-items: center;
}
.jp-StatusBar-Right {
display: flex;
align-items: center;
flex-direction: row-reverse;
}
.jp-StatusBar-Item {
max-height: var(--jp-statusbar-height);
margin: 0 2px;
height: var(--jp-statusbar-height);
white-space: nowrap;
text-overflow: ellipsis;
color: var(--jp-ui-font-color1);
padding: 0 6px;
}
.jp-mod-highlighted:hover {
background-color: var(--jp-layout-color3);
}
.jp-mod-clicked {
background-color: var(--jp-brand-color1);
}
.jp-mod-clicked:hover {
background-color: var(--jp-brand-color0);
}
.jp-mod-clicked .jp-StatusBar-TextItem {
color: var(--jp-ui-inverse-font-color1);
}
.jp-StatusBar-HoverItem {
box-shadow: '0px 4px 4px rgba(0, 0, 0, 0.25)';
}
.jp-StatusBar-TextItem {
font-size: var(--jp-ui-font-size1);
font-family: var(--jp-ui-font-family);
line-height: 24px;
color: var(--jp-ui-font-color1);
}
.jp-StatusBar-GroupItem {
display: flex;
align-items: center;
flex-direction: row;
}
.jp-Statusbar-ProgressCircle svg {
display: block;
margin: 0 auto;
width: 16px;
height: 24px;
align-self: normal;
}
.jp-Statusbar-ProgressCircle path {
fill: var(--jp-inverse-layout-color3);
}
.jp-Statusbar-ProgressBar-progress-bar {
height: 10px;
width: 100px;
border: solid 0.25px var(--jp-brand-color2);
border-radius: 3px;
overflow: hidden;
align-self: center;
}
.jp-Statusbar-ProgressBar-progress-bar > div {
background-color: var(--jp-brand-color2);
background-image: linear-gradient(
-45deg,
rgba(255, 255, 255, 0.2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.2) 50%,
rgba(255, 255, 255, 0.2) 75%,
transparent 75%,
transparent
);
background-size: 40px 40px;
float: left;
width: 0%;
height: 100%;
font-size: 12px;
line-height: 14px;
color: #fff;
text-align: center;
animation: jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite;
}
.jp-Statusbar-ProgressBar-progress-bar p {
color: var(--jp-ui-font-color1);
font-family: var(--jp-ui-font-family);
font-size: var(--jp-ui-font-size1);
line-height: 10px;
width: 100px;
}
@keyframes jp-Statusbar-ExecutionTime-progress-bar {
0% {
background-position: 0 0;
}
100% {
background-position: 40px 40px;
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Variables
|----------------------------------------------------------------------------*/
:root {
--jp-private-commandpalette-search-height: 28px;
}
/*-----------------------------------------------------------------------------
| Overall styles
|----------------------------------------------------------------------------*/
.lm-CommandPalette {
padding-bottom: 0;
color: var(--jp-ui-font-color1);
background: var(--jp-layout-color1);
/* This is needed so that all font sizing of children done in ems is
* relative to this base size */
font-size: var(--jp-ui-font-size1);
}
/*-----------------------------------------------------------------------------
| Modal variant
|----------------------------------------------------------------------------*/
.jp-ModalCommandPalette {
position: absolute;
z-index: 10000;
top: 38px;
left: 30%;
margin: 0;
padding: 4px;
width: 40%;
box-shadow: var(--jp-elevation-z4);
border-radius: 4px;
background: var(--jp-layout-color0);
}
.jp-ModalCommandPalette .lm-CommandPalette {
max-height: 40vh;
}
.jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon::after {
display: none;
}
.jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header {
display: none;
}
.jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item {
margin-left: 4px;
margin-right: 4px;
}
.jp-ModalCommandPalette
.lm-CommandPalette
.lm-CommandPalette-item.lm-mod-disabled {
display: none;
}
/*-----------------------------------------------------------------------------
| Search
|----------------------------------------------------------------------------*/
.lm-CommandPalette-search {
padding: 4px;
background-color: var(--jp-layout-color1);
z-index: 2;
}
.lm-CommandPalette-wrapper {
overflow: overlay;
padding: 0 9px;
background-color: var(--jp-input-active-background);
height: 30px;
box-shadow: inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color);
}
.lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper {
box-shadow: inset 0 0 0 1px var(--jp-input-active-box-shadow-color),
inset 0 0 0 3px var(--jp-input-active-box-shadow-color);
}
.jp-SearchIconGroup {
color: white;
background-color: var(--jp-brand-color1);
position: absolute;
top: 4px;
right: 4px;
padding: 5px 5px 1px;
}
.jp-SearchIconGroup svg {
height: 20px;
width: 20px;
}
.jp-SearchIconGroup .jp-icon3[fill] {
fill: var(--jp-layout-color0);
}
.lm-CommandPalette-input {
background: transparent;
width: calc(100% - 18px);
float: left;
border: none;
outline: none;
font-size: var(--jp-ui-font-size1);
color: var(--jp-ui-font-color0);
line-height: var(--jp-private-commandpalette-search-height);
}
.lm-CommandPalette-input::-webkit-input-placeholder,
.lm-CommandPalette-input::-moz-placeholder,
.lm-CommandPalette-input:-ms-input-placeholder {
color: var(--jp-ui-font-color2);
font-size: var(--jp-ui-font-size1);
}
/*-----------------------------------------------------------------------------
| Results
|----------------------------------------------------------------------------*/
.lm-CommandPalette-header:first-child {
margin-top: 0;
}
.lm-CommandPalette-header {
border-bottom: solid var(--jp-border-width) var(--jp-border-color2);
color: var(--jp-ui-font-color1);
cursor: pointer;
display: flex;
font-size: var(--jp-ui-font-size0);
font-weight: 600;
letter-spacing: 1px;
margin-top: 8px;
padding: 8px 0 8px 12px;
text-transform: uppercase;
}
.lm-CommandPalette-header.lm-mod-active {
background: var(--jp-layout-color2);
}
.lm-CommandPalette-header > mark {
background-color: transparent;
font-weight: bold;
color: var(--jp-ui-font-color1);
}
.lm-CommandPalette-item {
padding: 4px 12px 4px 4px;
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
font-weight: 400;
display: flex;
}
.lm-CommandPalette-item.lm-mod-disabled {
color: var(--jp-ui-font-color2);
}
.lm-CommandPalette-item.lm-mod-active {
color: var(--jp-ui-inverse-font-color1);
background: var(--jp-brand-color1);
}
.lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel > mark {
color: var(--jp-ui-inverse-font-color0);
}
.lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill] {
fill: var(--jp-layout-color0);
}
.lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled) {
color: var(--jp-ui-inverse-font-color1);
background: var(--jp-brand-color1);
}
.lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled) {
background: var(--jp-layout-color2);
}
.lm-CommandPalette-itemContent {
overflow: hidden;
}
.lm-CommandPalette-itemLabel > mark {
color: var(--jp-ui-font-color0);
background-color: transparent;
font-weight: bold;
}
.lm-CommandPalette-item.lm-mod-disabled mark {
color: var(--jp-ui-font-color2);
}
.lm-CommandPalette-item .lm-CommandPalette-itemIcon {
margin: 0 4px 0 0;
position: relative;
width: 16px;
top: 2px;
flex: 0 0 auto;
}
.lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon {
opacity: 0.6;
}
.lm-CommandPalette-item .lm-CommandPalette-itemShortcut {
flex: 0 0 auto;
}
.lm-CommandPalette-itemCaption {
display: none;
}
.lm-CommandPalette-content {
background-color: var(--jp-layout-color1);
}
.lm-CommandPalette-content:empty::after {
content: 'No results';
margin: auto;
margin-top: 20px;
width: 100px;
display: block;
font-size: var(--jp-ui-font-size2);
font-family: var(--jp-ui-font-family);
font-weight: lighter;
}
.lm-CommandPalette-emptyMessage {
text-align: center;
margin-top: 24px;
line-height: 1.32;
padding: 0 8px;
color: var(--jp-content-font-color3);
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-Dialog {
position: absolute;
z-index: 10000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: var(--jp-dialog-background);
}
.jp-Dialog-content {
display: flex;
flex-direction: column;
margin-left: auto;
margin-right: auto;
background: var(--jp-layout-color1);
padding: 24px 24px 12px;
min-width: 300px;
min-height: 150px;
max-width: 1000px;
max-height: 500px;
box-sizing: border-box;
box-shadow: var(--jp-elevation-z20);
word-wrap: break-word;
border-radius: var(--jp-border-radius);
/* This is needed so that all font sizing of children done in ems is
* relative to this base size */
font-size: var(--jp-ui-font-size1);
color: var(--jp-ui-font-color1);
resize: both;
}
.jp-Dialog-content.jp-Dialog-content-small {
max-width: 500px;
}
.jp-Dialog-button {
overflow: visible;
}
button.jp-Dialog-button:focus {
outline: 1px solid var(--jp-brand-color1);
outline-offset: 4px;
-moz-outline-radius: 0;
}
button.jp-Dialog-button:focus::-moz-focus-inner {
border: 0;
}
button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,
button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,
button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus {
outline-offset: 4px;
-moz-outline-radius: 0;
}
button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus {
outline: 1px solid var(--jp-accept-color-normal, var(--jp-brand-color1));
}
button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus {
outline: 1px solid var(--jp-warn-color-normal, var(--jp-error-color1));
}
button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus {
outline: 1px solid var(--jp-reject-color-normal, var(--md-grey-600));
}
button.jp-Dialog-close-button {
padding: 0;
height: 100%;
min-width: unset;
min-height: unset;
}
.jp-Dialog-header {
display: flex;
justify-content: space-between;
flex: 0 0 auto;
padding-bottom: 12px;
font-size: var(--jp-ui-font-size3);
font-weight: 400;
color: var(--jp-ui-font-color1);
}
.jp-Dialog-body {
display: flex;
flex-direction: column;
flex: 1 1 auto;
font-size: var(--jp-ui-font-size1);
background: var(--jp-layout-color1);
color: var(--jp-ui-font-color1);
overflow: auto;
}
.jp-Dialog-footer {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
flex: 0 0 auto;
margin-left: -12px;
margin-right: -12px;
padding: 12px;
}
.jp-Dialog-checkbox {
padding-right: 5px;
}
.jp-Dialog-checkbox > input:focus-visible {
outline: 1px solid var(--jp-input-active-border-color);
outline-offset: 1px;
}
.jp-Dialog-spacer {
flex: 1 1 auto;
}
.jp-Dialog-title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.jp-Dialog-body > .jp-select-wrapper {
width: 100%;
}
.jp-Dialog-body > button {
padding: 0 16px;
}
.jp-Dialog-body > label {
line-height: 1.4;
color: var(--jp-ui-font-color0);
}
.jp-Dialog-button.jp-mod-styled:not(:last-child) {
margin-right: 12px;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.jp-Input-Boolean-Dialog {
flex-direction: row-reverse;
align-items: end;
width: 100%;
}
.jp-Input-Boolean-Dialog > label {
flex: 1 1 auto;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2016, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-MainAreaWidget > :focus {
outline: none;
}
.jp-MainAreaWidget .jp-MainAreaWidget-error {
padding: 6px;
}
.jp-MainAreaWidget .jp-MainAreaWidget-error > pre {
width: auto;
padding: 10px;
background: var(--jp-error-color3);
border: var(--jp-border-width) solid var(--jp-error-color1);
border-radius: var(--jp-border-radius);
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/**
* google-material-color v1.2.6
* https://github.com/danlevan/google-material-color
*/
:root {
--md-red-50: #ffebee;
--md-red-100: #ffcdd2;
--md-red-200: #ef9a9a;
--md-red-300: #e57373;
--md-red-400: #ef5350;
--md-red-500: #f44336;
--md-red-600: #e53935;
--md-red-700: #d32f2f;
--md-red-800: #c62828;
--md-red-900: #b71c1c;
--md-red-A100: #ff8a80;
--md-red-A200: #ff5252;
--md-red-A400: #ff1744;
--md-red-A700: #d50000;
--md-pink-50: #fce4ec;
--md-pink-100: #f8bbd0;
--md-pink-200: #f48fb1;
--md-pink-300: #f06292;
--md-pink-400: #ec407a;
--md-pink-500: #e91e63;
--md-pink-600: #d81b60;
--md-pink-700: #c2185b;
--md-pink-800: #ad1457;
--md-pink-900: #880e4f;
--md-pink-A100: #ff80ab;
--md-pink-A200: #ff4081;
--md-pink-A400: #f50057;
--md-pink-A700: #c51162;
--md-purple-50: #f3e5f5;
--md-purple-100: #e1bee7;
--md-purple-200: #ce93d8;
--md-purple-300: #ba68c8;
--md-purple-400: #ab47bc;
--md-purple-500: #9c27b0;
--md-purple-600: #8e24aa;
--md-purple-700: #7b1fa2;
--md-purple-800: #6a1b9a;
--md-purple-900: #4a148c;
--md-purple-A100: #ea80fc;
--md-purple-A200: #e040fb;
--md-purple-A400: #d500f9;
--md-purple-A700: #a0f;
--md-deep-purple-50: #ede7f6;
--md-deep-purple-100: #d1c4e9;
--md-deep-purple-200: #b39ddb;
--md-deep-purple-300: #9575cd;
--md-deep-purple-400: #7e57c2;
--md-deep-purple-500: #673ab7;
--md-deep-purple-600: #5e35b1;
--md-deep-purple-700: #512da8;
--md-deep-purple-800: #4527a0;
--md-deep-purple-900: #311b92;
--md-deep-purple-A100: #b388ff;
--md-deep-purple-A200: #7c4dff;
--md-deep-purple-A400: #651fff;
--md-deep-purple-A700: #6200ea;
--md-indigo-50: #e8eaf6;
--md-indigo-100: #c5cae9;
--md-indigo-200: #9fa8da;
--md-indigo-300: #7986cb;
--md-indigo-400: #5c6bc0;
--md-indigo-500: #3f51b5;
--md-indigo-600: #3949ab;
--md-indigo-700: #303f9f;
--md-indigo-800: #283593;
--md-indigo-900: #1a237e;
--md-indigo-A100: #8c9eff;
--md-indigo-A200: #536dfe;
--md-indigo-A400: #3d5afe;
--md-indigo-A700: #304ffe;
--md-blue-50: #e3f2fd;
--md-blue-100: #bbdefb;
--md-blue-200: #90caf9;
--md-blue-300: #64b5f6;
--md-blue-400: #42a5f5;
--md-blue-500: #2196f3;
--md-blue-600: #1e88e5;
--md-blue-700: #1976d2;
--md-blue-800: #1565c0;
--md-blue-900: #0d47a1;
--md-blue-A100: #82b1ff;
--md-blue-A200: #448aff;
--md-blue-A400: #2979ff;
--md-blue-A700: #2962ff;
--md-light-blue-50: #e1f5fe;
--md-light-blue-100: #b3e5fc;
--md-light-blue-200: #81d4fa;
--md-light-blue-300: #4fc3f7;
--md-light-blue-400: #29b6f6;
--md-light-blue-500: #03a9f4;
--md-light-blue-600: #039be5;
--md-light-blue-700: #0288d1;
--md-light-blue-800: #0277bd;
--md-light-blue-900: #01579b;
--md-light-blue-A100: #80d8ff;
--md-light-blue-A200: #40c4ff;
--md-light-blue-A400: #00b0ff;
--md-light-blue-A700: #0091ea;
--md-cyan-50: #e0f7fa;
--md-cyan-100: #b2ebf2;
--md-cyan-200: #80deea;
--md-cyan-300: #4dd0e1;
--md-cyan-400: #26c6da;
--md-cyan-500: #00bcd4;
--md-cyan-600: #00acc1;
--md-cyan-700: #0097a7;
--md-cyan-800: #00838f;
--md-cyan-900: #006064;
--md-cyan-A100: #84ffff;
--md-cyan-A200: #18ffff;
--md-cyan-A400: #00e5ff;
--md-cyan-A700: #00b8d4;
--md-teal-50: #e0f2f1;
--md-teal-100: #b2dfdb;
--md-teal-200: #80cbc4;
--md-teal-300: #4db6ac;
--md-teal-400: #26a69a;
--md-teal-500: #009688;
--md-teal-600: #00897b;
--md-teal-700: #00796b;
--md-teal-800: #00695c;
--md-teal-900: #004d40;
--md-teal-A100: #a7ffeb;
--md-teal-A200: #64ffda;
--md-teal-A400: #1de9b6;
--md-teal-A700: #00bfa5;
--md-green-50: #e8f5e9;
--md-green-100: #c8e6c9;
--md-green-200: #a5d6a7;
--md-green-300: #81c784;
--md-green-400: #66bb6a;
--md-green-500: #4caf50;
--md-green-600: #43a047;
--md-green-700: #388e3c;
--md-green-800: #2e7d32;
--md-green-900: #1b5e20;
--md-green-A100: #b9f6ca;
--md-green-A200: #69f0ae;
--md-green-A400: #00e676;
--md-green-A700: #00c853;
--md-light-green-50: #f1f8e9;
--md-light-green-100: #dcedc8;
--md-light-green-200: #c5e1a5;
--md-light-green-300: #aed581;
--md-light-green-400: #9ccc65;
--md-light-green-500: #8bc34a;
--md-light-green-600: #7cb342;
--md-light-green-700: #689f38;
--md-light-green-800: #558b2f;
--md-light-green-900: #33691e;
--md-light-green-A100: #ccff90;
--md-light-green-A200: #b2ff59;
--md-light-green-A400: #76ff03;
--md-light-green-A700: #64dd17;
--md-lime-50: #f9fbe7;
--md-lime-100: #f0f4c3;
--md-lime-200: #e6ee9c;
--md-lime-300: #dce775;
--md-lime-400: #d4e157;
--md-lime-500: #cddc39;
--md-lime-600: #c0ca33;
--md-lime-700: #afb42b;
--md-lime-800: #9e9d24;
--md-lime-900: #827717;
--md-lime-A100: #f4ff81;
--md-lime-A200: #eeff41;
--md-lime-A400: #c6ff00;
--md-lime-A700: #aeea00;
--md-yellow-50: #fffde7;
--md-yellow-100: #fff9c4;
--md-yellow-200: #fff59d;
--md-yellow-300: #fff176;
--md-yellow-400: #ffee58;
--md-yellow-500: #ffeb3b;
--md-yellow-600: #fdd835;
--md-yellow-700: #fbc02d;
--md-yellow-800: #f9a825;
--md-yellow-900: #f57f17;
--md-yellow-A100: #ffff8d;
--md-yellow-A200: #ff0;
--md-yellow-A400: #ffea00;
--md-yellow-A700: #ffd600;
--md-amber-50: #fff8e1;
--md-amber-100: #ffecb3;
--md-amber-200: #ffe082;
--md-amber-300: #ffd54f;
--md-amber-400: #ffca28;
--md-amber-500: #ffc107;
--md-amber-600: #ffb300;
--md-amber-700: #ffa000;
--md-amber-800: #ff8f00;
--md-amber-900: #ff6f00;
--md-amber-A100: #ffe57f;
--md-amber-A200: #ffd740;
--md-amber-A400: #ffc400;
--md-amber-A700: #ffab00;
--md-orange-50: #fff3e0;
--md-orange-100: #ffe0b2;
--md-orange-200: #ffcc80;
--md-orange-300: #ffb74d;
--md-orange-400: #ffa726;
--md-orange-500: #ff9800;
--md-orange-600: #fb8c00;
--md-orange-700: #f57c00;
--md-orange-800: #ef6c00;
--md-orange-900: #e65100;
--md-orange-A100: #ffd180;
--md-orange-A200: #ffab40;
--md-orange-A400: #ff9100;
--md-orange-A700: #ff6d00;
--md-deep-orange-50: #fbe9e7;
--md-deep-orange-100: #ffccbc;
--md-deep-orange-200: #ffab91;
--md-deep-orange-300: #ff8a65;
--md-deep-orange-400: #ff7043;
--md-deep-orange-500: #ff5722;
--md-deep-orange-600: #f4511e;
--md-deep-orange-700: #e64a19;
--md-deep-orange-800: #d84315;
--md-deep-orange-900: #bf360c;
--md-deep-orange-A100: #ff9e80;
--md-deep-orange-A200: #ff6e40;
--md-deep-orange-A400: #ff3d00;
--md-deep-orange-A700: #dd2c00;
--md-brown-50: #efebe9;
--md-brown-100: #d7ccc8;
--md-brown-200: #bcaaa4;
--md-brown-300: #a1887f;
--md-brown-400: #8d6e63;
--md-brown-500: #795548;
--md-brown-600: #6d4c41;
--md-brown-700: #5d4037;
--md-brown-800: #4e342e;
--md-brown-900: #3e2723;
--md-grey-50: #fafafa;
--md-grey-100: #f5f5f5;
--md-grey-200: #eee;
--md-grey-300: #e0e0e0;
--md-grey-400: #bdbdbd;
--md-grey-500: #9e9e9e;
--md-grey-600: #757575;
--md-grey-700: #616161;
--md-grey-800: #424242;
--md-grey-900: #212121;
--md-blue-grey-50: #eceff1;
--md-blue-grey-100: #cfd8dc;
--md-blue-grey-200: #b0bec5;
--md-blue-grey-300: #90a4ae;
--md-blue-grey-400: #78909c;
--md-blue-grey-500: #607d8b;
--md-blue-grey-600: #546e7a;
--md-blue-grey-700: #455a64;
--md-blue-grey-800: #37474f;
--md-blue-grey-900: #263238;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2017, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| RenderedText
|----------------------------------------------------------------------------*/
:root {
/* This is the padding value to fill the gaps between lines containing spans with background color. */
--jp-private-code-span-padding: calc(
(var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2
);
}
.jp-RenderedText {
text-align: left;
padding-left: var(--jp-code-padding);
line-height: var(--jp-code-line-height);
font-family: var(--jp-code-font-family);
}
.jp-RenderedText pre,
.jp-RenderedJavaScript pre,
.jp-RenderedHTMLCommon pre {
color: var(--jp-content-font-color1);
font-size: var(--jp-code-font-size);
border: none;
margin: 0;
padding: 0;
}
.jp-RenderedText pre a:link {
text-decoration: none;
color: var(--jp-content-link-color);
}
.jp-RenderedText pre a:hover {
text-decoration: underline;
color: var(--jp-content-link-color);
}
.jp-RenderedText pre a:visited {
text-decoration: none;
color: var(--jp-content-link-color);
}
/* console foregrounds and backgrounds */
.jp-RenderedText pre .ansi-black-fg {
color: #3e424d;
}
.jp-RenderedText pre .ansi-red-fg {
color: #e75c58;
}
.jp-RenderedText pre .ansi-green-fg {
color: #00a250;
}
.jp-RenderedText pre .ansi-yellow-fg {
color: #ddb62b;
}
.jp-RenderedText pre .ansi-blue-fg {
color: #208ffb;
}
.jp-RenderedText pre .ansi-magenta-fg {
color: #d160c4;
}
.jp-RenderedText pre .ansi-cyan-fg {
color: #60c6c8;
}
.jp-RenderedText pre .ansi-white-fg {
color: #c5c1b4;
}
.jp-RenderedText pre .ansi-black-bg {
background-color: #3e424d;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-red-bg {
background-color: #e75c58;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-green-bg {
background-color: #00a250;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-yellow-bg {
background-color: #ddb62b;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-blue-bg {
background-color: #208ffb;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-magenta-bg {
background-color: #d160c4;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-cyan-bg {
background-color: #60c6c8;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-white-bg {
background-color: #c5c1b4;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-black-intense-fg {
color: #282c36;
}
.jp-RenderedText pre .ansi-red-intense-fg {
color: #b22b31;
}
.jp-RenderedText pre .ansi-green-intense-fg {
color: #007427;
}
.jp-RenderedText pre .ansi-yellow-intense-fg {
color: #b27d12;
}
.jp-RenderedText pre .ansi-blue-intense-fg {
color: #0065ca;
}
.jp-RenderedText pre .ansi-magenta-intense-fg {
color: #a03196;
}
.jp-RenderedText pre .ansi-cyan-intense-fg {
color: #258f8f;
}
.jp-RenderedText pre .ansi-white-intense-fg {
color: #a1a6b2;
}
.jp-RenderedText pre .ansi-black-intense-bg {
background-color: #282c36;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-red-intense-bg {
background-color: #b22b31;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-green-intense-bg {
background-color: #007427;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-yellow-intense-bg {
background-color: #b27d12;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-blue-intense-bg {
background-color: #0065ca;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-magenta-intense-bg {
background-color: #a03196;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-cyan-intense-bg {
background-color: #258f8f;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-white-intense-bg {
background-color: #a1a6b2;
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-default-inverse-fg {
color: var(--jp-ui-inverse-font-color0);
}
.jp-RenderedText pre .ansi-default-inverse-bg {
background-color: var(--jp-inverse-layout-color0);
padding: var(--jp-private-code-span-padding) 0;
}
.jp-RenderedText pre .ansi-bold {
font-weight: bold;
}
.jp-RenderedText pre .ansi-underline {
text-decoration: underline;
}
.jp-RenderedText[data-mime-type='application/vnd.jupyter.stderr'] {
background: var(--jp-rendermime-error-background);
padding-top: var(--jp-code-padding);
}
/*-----------------------------------------------------------------------------
| RenderedLatex
|----------------------------------------------------------------------------*/
.jp-RenderedLatex {
color: var(--jp-content-font-color1);
font-size: var(--jp-content-font-size1);
line-height: var(--jp-content-line-height);
}
/* Left-justify outputs.*/
.jp-OutputArea-output.jp-RenderedLatex {
padding: var(--jp-code-padding);
text-align: left;
}
/*-----------------------------------------------------------------------------
| RenderedHTML
|----------------------------------------------------------------------------*/
.jp-RenderedHTMLCommon {
color: var(--jp-content-font-color1);
font-family: var(--jp-content-font-family);
font-size: var(--jp-content-font-size1);
line-height: var(--jp-content-line-height);
/* Give a bit more R padding on Markdown text to keep line lengths reasonable */
padding-right: 20px;
}
.jp-RenderedHTMLCommon em {
font-style: italic;
}
.jp-RenderedHTMLCommon strong {
font-weight: bold;
}
.jp-RenderedHTMLCommon u {
text-decoration: underline;
}
.jp-RenderedHTMLCommon a:link {
text-decoration: none;
color: var(--jp-content-link-color);
}
.jp-RenderedHTMLCommon a:hover {
text-decoration: underline;
color: var(--jp-content-link-color);
}
.jp-RenderedHTMLCommon a:visited {
text-decoration: none;
color: var(--jp-content-link-color);
}
/* Headings */
.jp-RenderedHTMLCommon h1,
.jp-RenderedHTMLCommon h2,
.jp-RenderedHTMLCommon h3,
.jp-RenderedHTMLCommon h4,
.jp-RenderedHTMLCommon h5,
.jp-RenderedHTMLCommon h6 {
line-height: var(--jp-content-heading-line-height);
font-weight: var(--jp-content-heading-font-weight);
font-style: normal;
margin: var(--jp-content-heading-margin-top) 0
var(--jp-content-heading-margin-bottom) 0;
}
.jp-RenderedHTMLCommon h1:first-child,
.jp-RenderedHTMLCommon h2:first-child,
.jp-RenderedHTMLCommon h3:first-child,
.jp-RenderedHTMLCommon h4:first-child,
.jp-RenderedHTMLCommon h5:first-child,
.jp-RenderedHTMLCommon h6:first-child {
margin-top: calc(0.5 * var(--jp-content-heading-margin-top));
}
.jp-RenderedHTMLCommon h1:last-child,
.jp-RenderedHTMLCommon h2:last-child,
.jp-RenderedHTMLCommon h3:last-child,
.jp-RenderedHTMLCommon h4:last-child,
.jp-RenderedHTMLCommon h5:last-child,
.jp-RenderedHTMLCommon h6:last-child {
margin-bottom: calc(0.5 * var(--jp-content-heading-margin-bottom));
}
.jp-RenderedHTMLCommon h1 {
font-size: var(--jp-content-font-size5);
}
.jp-RenderedHTMLCommon h2 {
font-size: var(--jp-content-font-size4);
}
.jp-RenderedHTMLCommon h3 {
font-size: var(--jp-content-font-size3);
}
.jp-RenderedHTMLCommon h4 {
font-size: var(--jp-content-font-size2);
}
.jp-RenderedHTMLCommon h5 {
font-size: var(--jp-content-font-size1);
}
.jp-RenderedHTMLCommon h6 {
font-size: var(--jp-content-font-size0);
}
/* Lists */
/* stylelint-disable selector-max-type, selector-max-compound-selectors */
.jp-RenderedHTMLCommon ul:not(.list-inline),
.jp-RenderedHTMLCommon ol:not(.list-inline) {
padding-left: 2em;
}
.jp-RenderedHTMLCommon ul {
list-style: disc;
}
.jp-RenderedHTMLCommon ul ul {
list-style: square;
}
.jp-RenderedHTMLCommon ul ul ul {
list-style: circle;
}
.jp-RenderedHTMLCommon ol {
list-style: decimal;
}
.jp-RenderedHTMLCommon ol ol {
list-style: upper-alpha;
}
.jp-RenderedHTMLCommon ol ol ol {
list-style: lower-alpha;
}
.jp-RenderedHTMLCommon ol ol ol ol {
list-style: lower-roman;
}
.jp-RenderedHTMLCommon ol ol ol ol ol {
list-style: decimal;
}
.jp-RenderedHTMLCommon ol,
.jp-RenderedHTMLCommon ul {
margin-bottom: 1em;
}
.jp-RenderedHTMLCommon ul ul,
.jp-RenderedHTMLCommon ul ol,
.jp-RenderedHTMLCommon ol ul,
.jp-RenderedHTMLCommon ol ol {
margin-bottom: 0;
}
/* stylelint-enable selector-max-type, selector-max-compound-selectors */
.jp-RenderedHTMLCommon hr {
color: var(--jp-border-color2);
background-color: var(--jp-border-color1);
margin-top: 1em;
margin-bottom: 1em;
}
.jp-RenderedHTMLCommon > pre {
margin: 1.5em 2em;
}
.jp-RenderedHTMLCommon pre,
.jp-RenderedHTMLCommon code {
border: 0;
background-color: var(--jp-layout-color0);
color: var(--jp-content-font-color1);
font-family: var(--jp-code-font-family);
font-size: inherit;
line-height: var(--jp-code-line-height);
padding: 0;
white-space: pre-wrap;
}
.jp-RenderedHTMLCommon :not(pre) > code {
background-color: var(--jp-layout-color2);
padding: 1px 5px;
}
/* Tables */
.jp-RenderedHTMLCommon table {
border-collapse: collapse;
border-spacing: 0;
border: none;
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
table-layout: fixed;
margin-left: auto;
margin-bottom: 1em;
margin-right: auto;
}
.jp-RenderedHTMLCommon thead {
border-bottom: var(--jp-border-width) solid var(--jp-border-color1);
vertical-align: bottom;
}
.jp-RenderedHTMLCommon td,
.jp-RenderedHTMLCommon th,
.jp-RenderedHTMLCommon tr {
vertical-align: middle;
padding: 0.5em;
line-height: normal;
white-space: normal;
max-width: none;
border: none;
}
.jp-RenderedMarkdown.jp-RenderedHTMLCommon td,
.jp-RenderedMarkdown.jp-RenderedHTMLCommon th {
max-width: none;
}
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon td,
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon th,
:not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon tr {
text-align: right;
}
.jp-RenderedHTMLCommon th {
font-weight: bold;
}
.jp-RenderedHTMLCommon tbody tr:nth-child(odd) {
background: var(--jp-layout-color0);
}
.jp-RenderedHTMLCommon tbody tr:nth-child(even) {
background: var(--jp-rendermime-table-row-background);
}
.jp-RenderedHTMLCommon tbody tr:hover {
background: var(--jp-rendermime-table-row-hover-background);
}
.jp-RenderedHTMLCommon p {
text-align: left;
margin: 0;
margin-bottom: 1em;
}
.jp-RenderedHTMLCommon img {
-moz-force-broken-image-icon: 1;
}
/* Restrict to direct children as other images could be nested in other content. */
.jp-RenderedHTMLCommon > img {
display: block;
margin-left: 0;
margin-right: 0;
margin-bottom: 1em;
}
/* Change color behind transparent images if they need it... */
[data-jp-theme-light='false'] .jp-RenderedImage img.jp-needs-light-background {
background-color: var(--jp-inverse-layout-color1);
}
[data-jp-theme-light='true'] .jp-RenderedImage img.jp-needs-dark-background {
background-color: var(--jp-inverse-layout-color1);
}
.jp-RenderedHTMLCommon img,
.jp-RenderedImage img,
.jp-RenderedHTMLCommon svg,
.jp-RenderedSVG svg {
max-width: 100%;
height: auto;
}
.jp-RenderedHTMLCommon img.jp-mod-unconfined,
.jp-RenderedImage img.jp-mod-unconfined,
.jp-RenderedHTMLCommon svg.jp-mod-unconfined,
.jp-RenderedSVG svg.jp-mod-unconfined {
max-width: none;
}
.jp-RenderedHTMLCommon .alert {
padding: var(--jp-notebook-padding);
border: var(--jp-border-width) solid transparent;
border-radius: var(--jp-border-radius);
margin-bottom: 1em;
}
.jp-RenderedHTMLCommon .alert-info {
color: var(--jp-info-color0);
background-color: var(--jp-info-color3);
border-color: var(--jp-info-color2);
}
.jp-RenderedHTMLCommon .alert-info hr {
border-color: var(--jp-info-color3);
}
.jp-RenderedHTMLCommon .alert-info > p:last-child,
.jp-RenderedHTMLCommon .alert-info > ul:last-child {
margin-bottom: 0;
}
.jp-RenderedHTMLCommon .alert-warning {
color: var(--jp-warn-color0);
background-color: var(--jp-warn-color3);
border-color: var(--jp-warn-color2);
}
.jp-RenderedHTMLCommon .alert-warning hr {
border-color: var(--jp-warn-color3);
}
.jp-RenderedHTMLCommon .alert-warning > p:last-child,
.jp-RenderedHTMLCommon .alert-warning > ul:last-child {
margin-bottom: 0;
}
.jp-RenderedHTMLCommon .alert-success {
color: var(--jp-success-color0);
background-color: var(--jp-success-color3);
border-color: var(--jp-success-color2);
}
.jp-RenderedHTMLCommon .alert-success hr {
border-color: var(--jp-success-color3);
}
.jp-RenderedHTMLCommon .alert-success > p:last-child,
.jp-RenderedHTMLCommon .alert-success > ul:last-child {
margin-bottom: 0;
}
.jp-RenderedHTMLCommon .alert-danger {
color: var(--jp-error-color0);
background-color: var(--jp-error-color3);
border-color: var(--jp-error-color2);
}
.jp-RenderedHTMLCommon .alert-danger hr {
border-color: var(--jp-error-color3);
}
.jp-RenderedHTMLCommon .alert-danger > p:last-child,
.jp-RenderedHTMLCommon .alert-danger > ul:last-child {
margin-bottom: 0;
}
.jp-RenderedHTMLCommon blockquote {
margin: 1em 2em;
padding: 0 1em;
border-left: 5px solid var(--jp-border-color2);
}
a.jp-InternalAnchorLink {
visibility: hidden;
margin-left: 8px;
color: var(--md-blue-800);
}
h1:hover .jp-InternalAnchorLink,
h2:hover .jp-InternalAnchorLink,
h3:hover .jp-InternalAnchorLink,
h4:hover .jp-InternalAnchorLink,
h5:hover .jp-InternalAnchorLink,
h6:hover .jp-InternalAnchorLink {
visibility: visible;
}
.jp-RenderedHTMLCommon kbd {
background-color: var(--jp-rendermime-table-row-background);
border: 1px solid var(--jp-border-color0);
border-bottom-color: var(--jp-border-color2);
border-radius: 3px;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
display: inline-block;
font-size: var(--jp-ui-font-size0);
line-height: 1em;
padding: 0.2em 0.5em;
}
/* Most direct children of .jp-RenderedHTMLCommon have a margin-bottom of 1.0.
* At the bottom of cells this is a bit too much as there is also spacing
* between cells. Going all the way to 0 gets too tight between markdown and
* code cells.
*/
.jp-RenderedHTMLCommon > *:last-child {
margin-bottom: 0.5em;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Copyright (c) 2014-2017, PhosphorJS Contributors
|
| Distributed under the terms of the BSD 3-Clause License.
|
| The full license is in the file LICENSE, distributed with this software.
|----------------------------------------------------------------------------*/
.lm-cursor-backdrop {
position: fixed;
width: 200px;
height: 200px;
margin-top: -100px;
margin-left: -100px;
will-change: transform;
z-index: 100;
}
.lm-mod-drag-image {
will-change: transform;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.jp-lineFormSearch {
padding: 4px 12px;
background-color: var(--jp-layout-color2);
box-shadow: var(--jp-toolbar-box-shadow);
z-index: 2;
font-size: var(--jp-ui-font-size1);
}
.jp-lineFormCaption {
font-size: var(--jp-ui-font-size0);
line-height: var(--jp-ui-font-size1);
margin-top: 4px;
color: var(--jp-ui-font-color0);
}
.jp-baseLineForm {
border: none;
border-radius: 0;
position: absolute;
background-size: 16px;
background-repeat: no-repeat;
background-position: center;
outline: none;
}
.jp-lineFormButtonContainer {
top: 4px;
right: 8px;
height: 24px;
padding: 0 12px;
width: 12px;
}
.jp-lineFormButtonIcon {
top: 0;
right: 0;
background-color: var(--jp-brand-color1);
height: 100%;
width: 100%;
box-sizing: border-box;
padding: 4px 6px;
}
.jp-lineFormButton {
top: 0;
right: 0;
background-color: transparent;
height: 100%;
width: 100%;
box-sizing: border-box;
}
.jp-lineFormWrapper {
overflow: hidden;
padding: 0 8px;
border: 1px solid var(--jp-border-color0);
background-color: var(--jp-input-active-background);
height: 22px;
}
.jp-lineFormWrapperFocusWithin {
border: var(--jp-border-width) solid var(--md-blue-500);
box-shadow: inset 0 0 4px var(--md-blue-300);
}
.jp-lineFormInput {
background: transparent;
width: 200px;
height: 100%;
border: none;
outline: none;
color: var(--jp-ui-font-color0);
line-height: 28px;
}
/*-----------------------------------------------------------------------------
| Copyright (c) 2014-2016, Jupyter Development Team.
|
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-JSONEditor {
display: flex;
flex-direction: column;
width: 100%;
}
.jp-JSONEditor-host {
flex: 1 1 auto;
border: var(--jp-border-width) solid var(--jp-input-border-color);
border-radius: 0;
background: var(--jp-layout-color0);
min-height: 50px;
padding: 1px;
}
.jp-JSONEditor.jp-mod-error .jp-JSONEditor-host {
border-color: red;
outline-color: red;
}
.jp-JSONEditor-header {
display: flex;
flex: 1 0 auto;
padding: 0 0 0 12px;
}
.jp-JSONEditor-header label {
flex: 0 0 auto;
}
.jp-JSONEditor-commitButton {
height: 16px;
width: 16px;
background-size: 18px;
background-repeat: no-repeat;
background-position: center;
}
.jp-JSONEditor-host.jp-mod-focused {
background-color: var(--jp-input-active-background);
border: 1px solid var(--jp-input-active-border-color);
box-shadow: var(--jp-input-box-shadow);
}
.jp-Editor.jp-mod-dropTarget {
border: var(--jp-border-width) solid var(--jp-input-active-border-color);
box-shadow: var(--jp-input-box-shadow);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-DocumentSearch-input {
border: none;
outline: none;
color: var(--jp-ui-font-color0);
font-size: var(--jp-ui-font-size1);
background-color: var(--jp-layout-color0);
font-family: var(--jp-ui-font-family);
padding: 2px 1px;
resize: none;
}
.jp-DocumentSearch-overlay {
position: absolute;
background-color: var(--jp-toolbar-background);
border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);
border-left: var(--jp-border-width) solid var(--jp-toolbar-border-color);
top: 0;
right: 0;
z-index: 7;
min-width: 405px;
padding: 2px;
font-size: var(--jp-ui-font-size1);
--jp-private-document-search-button-height: 20px;
}
.jp-DocumentSearch-overlay button {
background-color: var(--jp-toolbar-background);
outline: 0;
}
.jp-DocumentSearch-overlay button:hover {
background-color: var(--jp-layout-color2);
}
.jp-DocumentSearch-overlay button:active {
background-color: var(--jp-layout-color3);
}
.jp-DocumentSearch-overlay-row {
display: flex;
align-items: center;
margin-bottom: 2px;
}
.jp-DocumentSearch-button-content {
display: inline-block;
cursor: pointer;
box-sizing: border-box;
width: 100%;
height: 100%;
}
.jp-DocumentSearch-button-content svg {
width: 100%;
height: 100%;
}
.jp-DocumentSearch-input-wrapper {
border: var(--jp-border-width) solid var(--jp-border-color0);
display: flex;
background-color: var(--jp-layout-color0);
margin: 2px;
}
.jp-DocumentSearch-input-wrapper:focus-within {
border-color: var(--jp-cell-editor-active-border-color);
}
.jp-DocumentSearch-toggle-wrapper,
.jp-DocumentSearch-button-wrapper {
all: initial;
overflow: hidden;
display: inline-block;
border: none;
box-sizing: border-box;
}
.jp-DocumentSearch-toggle-wrapper {
width: 14px;
height: 14px;
}
.jp-DocumentSearch-button-wrapper {
width: var(--jp-private-document-search-button-height);
height: var(--jp-private-document-search-button-height);
}
.jp-DocumentSearch-toggle-wrapper:focus,
.jp-DocumentSearch-button-wrapper:focus {
outline: var(--jp-border-width) solid
var(--jp-cell-editor-active-border-color);
outline-offset: -1px;
}
.jp-DocumentSearch-toggle-wrapper,
.jp-DocumentSearch-button-wrapper,
.jp-DocumentSearch-button-content:focus {
outline: none;
}
.jp-DocumentSearch-toggle-placeholder {
width: 5px;
}
.jp-DocumentSearch-input-button::before {
display: block;
padding-top: 100%;
}
.jp-DocumentSearch-input-button-off {
opacity: var(--jp-search-toggle-off-opacity);
}
.jp-DocumentSearch-input-button-off:hover {
opacity: var(--jp-search-toggle-hover-opacity);
}
.jp-DocumentSearch-input-button-on {
opacity: var(--jp-search-toggle-on-opacity);
}
.jp-DocumentSearch-index-counter {
padding-left: 10px;
padding-right: 10px;
user-select: none;
min-width: 35px;
display: inline-block;
}
.jp-DocumentSearch-up-down-wrapper {
display: inline-block;
padding-right: 2px;
margin-left: auto;
white-space: nowrap;
}
.jp-DocumentSearch-spacer {
margin-left: auto;
}
.jp-DocumentSearch-up-down-wrapper button {
outline: 0;
border: none;
width: var(--jp-private-document-search-button-height);
height: var(--jp-private-document-search-button-height);
vertical-align: middle;
margin: 1px 5px 2px;
}
.jp-DocumentSearch-up-down-button:hover {
background-color: var(--jp-layout-color2);
}
.jp-DocumentSearch-up-down-button:active {
background-color: var(--jp-layout-color3);
}
.jp-DocumentSearch-filter-button {
border-radius: var(--jp-border-radius);
}
.jp-DocumentSearch-filter-button:hover {
background-color: var(--jp-layout-color2);
}
.jp-DocumentSearch-filter-button-enabled {
background-color: var(--jp-layout-color2);
}
.jp-DocumentSearch-filter-button-enabled:hover {
background-color: var(--jp-layout-color3);
}
.jp-DocumentSearch-search-options {
padding: 0 8px;
margin-left: 3px;
width: 100%;
display: grid;
justify-content: start;
grid-template-columns: 1fr 1fr;
align-items: center;
justify-items: stretch;
}
.jp-DocumentSearch-search-filter-disabled {
color: var(--jp-ui-font-color2);
}
.jp-DocumentSearch-search-filter {
display: flex;
align-items: center;
user-select: none;
}
.jp-DocumentSearch-regex-error {
color: var(--jp-error-color0);
}
.jp-DocumentSearch-replace-button-wrapper {
overflow: hidden;
display: inline-block;
box-sizing: border-box;
border: var(--jp-border-width) solid var(--jp-border-color0);
margin: auto 2px;
padding: 1px 4px;
height: calc(var(--jp-private-document-search-button-height) + 2px);
}
.jp-DocumentSearch-replace-button-wrapper:focus {
border: var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);
}
.jp-DocumentSearch-replace-button {
display: inline-block;
text-align: center;
cursor: pointer;
box-sizing: border-box;
color: var(--jp-ui-font-color1);
/* height - 2 * (padding of wrapper) */
line-height: calc(var(--jp-private-document-search-button-height) - 2px);
width: 100%;
height: 100%;
}
.jp-DocumentSearch-replace-button:focus {
outline: none;
}
.jp-DocumentSearch-replace-wrapper-class {
margin-left: 14px;
display: flex;
}
.jp-DocumentSearch-replace-toggle {
border: none;
background-color: var(--jp-toolbar-background);
border-radius: var(--jp-border-radius);
}
.jp-DocumentSearch-replace-toggle:hover {
background-color: var(--jp-layout-color2);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.cm-editor {
line-height: var(--jp-code-line-height);
font-size: var(--jp-code-font-size);
font-family: var(--jp-code-font-family);
border: 0;
border-radius: 0;
height: auto;
/* Changed to auto to autogrow */
}
.cm-editor pre {
padding: 0 var(--jp-code-padding);
}
.jp-CodeMirrorEditor[data-type='inline'] .cm-dialog {
background-color: var(--jp-layout-color0);
color: var(--jp-content-font-color1);
}
.jp-CodeMirrorEditor {
cursor: text;
}
/* When zoomed out 67% and 33% on a screen of 1440 width x 900 height */
@media screen and (min-width: 2138px) and (max-width: 4319px) {
.jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {
border-left: var(--jp-code-cursor-width1) solid
var(--jp-editor-cursor-color);
}
}
/* When zoomed out less than 33% */
@media screen and (min-width: 4320px) {
.jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {
border-left: var(--jp-code-cursor-width2) solid
var(--jp-editor-cursor-color);
}
}
.cm-editor.jp-mod-readOnly .cm-cursor {
display: none;
}
.jp-CollaboratorCursor {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: none;
border-bottom: 3px solid;
background-clip: content-box;
margin-left: -5px;
margin-right: -5px;
}
.cm-searching,
.cm-searching span {
/* `.cm-searching span`: we need to override syntax highlighting */
background-color: var(--jp-search-unselected-match-background-color);
color: var(--jp-search-unselected-match-color);
}
.cm-searching::selection,
.cm-searching span::selection {
background-color: var(--jp-search-unselected-match-background-color);
color: var(--jp-search-unselected-match-color);
}
.jp-current-match > .cm-searching,
.jp-current-match > .cm-searching span,
.cm-searching > .jp-current-match,
.cm-searching > .jp-current-match span {
background-color: var(--jp-search-selected-match-background-color);
color: var(--jp-search-selected-match-color);
}
.jp-current-match > .cm-searching::selection,
.cm-searching > .jp-current-match::selection,
.jp-current-match > .cm-searching span::selection {
background-color: var(--jp-search-selected-match-background-color);
color: var(--jp-search-selected-match-color);
}
.cm-trailingspace {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);
background-position: center left;
background-repeat: repeat-x;
}
.jp-CollaboratorCursor-hover {
position: absolute;
z-index: 1;
transform: translateX(-50%);
color: white;
border-radius: 3px;
padding-left: 4px;
padding-right: 4px;
padding-top: 1px;
padding-bottom: 1px;
text-align: center;
font-size: var(--jp-ui-font-size1);
white-space: nowrap;
}
.jp-CodeMirror-ruler {
border-left: 1px dashed var(--jp-border-color2);
}
/* Styles for shared cursors (remote cursor locations and selected ranges) */
.jp-CodeMirrorEditor .cm-ySelectionCaret {
position: relative;
border-left: 1px solid black;
margin-left: -1px;
margin-right: -1px;
box-sizing: border-box;
}
.jp-CodeMirrorEditor .cm-ySelectionCaret > .cm-ySelectionInfo {
white-space: nowrap;
position: absolute;
top: -1.15em;
padding-bottom: 0.05em;
left: -1px;
font-size: 0.95em;
font-family: var(--jp-ui-font-family);
font-weight: bold;
line-height: normal;
user-select: none;
color: white;
padding-left: 2px;
padding-right: 2px;
z-index: 101;
transition: opacity 0.3s ease-in-out;
}
.jp-CodeMirrorEditor .cm-ySelectionInfo {
transition-delay: 0.7s;
opacity: 0;
}
.jp-CodeMirrorEditor .cm-ySelectionCaret:hover > .cm-ySelectionInfo {
opacity: 1;
transition-delay: 0s;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-MimeDocument {
outline: none;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Variables
|----------------------------------------------------------------------------*/
:root {
--jp-private-filebrowser-button-height: 28px;
--jp-private-filebrowser-button-width: 48px;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-FileBrowser .jp-SidePanel-content {
display: flex;
flex-direction: column;
}
.jp-FileBrowser-toolbar.jp-Toolbar {
flex-wrap: wrap;
row-gap: 12px;
border-bottom: none;
height: auto;
margin: 8px 12px 0;
box-shadow: none;
padding: 0;
justify-content: flex-start;
}
.jp-FileBrowser-Panel {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.jp-BreadCrumbs {
flex: 0 0 auto;
margin: 8px 12px;
}
.jp-BreadCrumbs-item {
margin: 0 2px;
padding: 0 2px;
border-radius: var(--jp-border-radius);
cursor: pointer;
}
.jp-BreadCrumbs-item:hover {
background-color: var(--jp-layout-color2);
}
.jp-BreadCrumbs-item:first-child {
margin-left: 0;
}
.jp-BreadCrumbs-item.jp-mod-dropTarget {
background-color: var(--jp-brand-color2);
opacity: 0.7;
}
/*-----------------------------------------------------------------------------
| Buttons
|----------------------------------------------------------------------------*/
.jp-FileBrowser-toolbar > .jp-Toolbar-item {
flex: 0 0 auto;
padding-left: 0;
padding-right: 2px;
align-items: center;
height: unset;
}
.jp-FileBrowser-toolbar > .jp-Toolbar-item .jp-ToolbarButtonComponent {
width: 40px;
}
/*-----------------------------------------------------------------------------
| Other styles
|----------------------------------------------------------------------------*/
.jp-FileDialog.jp-mod-conflict input {
color: var(--jp-error-color1);
}
.jp-FileDialog .jp-new-name-title {
margin-top: 12px;
}
.jp-LastModified-hidden {
display: none;
}
.jp-FileSize-hidden {
display: none;
}
.jp-FileBrowser .lm-AccordionPanel > h3:first-child {
display: none;
}
/*-----------------------------------------------------------------------------
| DirListing
|----------------------------------------------------------------------------*/
.jp-DirListing {
flex: 1 1 auto;
display: flex;
flex-direction: column;
outline: 0;
}
.jp-DirListing-header {
flex: 0 0 auto;
display: flex;
flex-direction: row;
align-items: center;
overflow: hidden;
border-top: var(--jp-border-width) solid var(--jp-border-color2);
border-bottom: var(--jp-border-width) solid var(--jp-border-color1);
box-shadow: var(--jp-toolbar-box-shadow);
z-index: 2;
}
.jp-DirListing-headerItem {
padding: 4px 12px 2px;
font-weight: 500;
}
.jp-DirListing-headerItem:hover {
background: var(--jp-layout-color2);
}
.jp-DirListing-headerItem.jp-id-name {
flex: 1 0 84px;
}
.jp-DirListing-headerItem.jp-id-modified {
flex: 0 0 112px;
border-left: var(--jp-border-width) solid var(--jp-border-color2);
text-align: right;
}
.jp-DirListing-headerItem.jp-id-filesize {
flex: 0 0 75px;
border-left: var(--jp-border-width) solid var(--jp-border-color2);
text-align: right;
}
.jp-id-narrow {
display: none;
flex: 0 0 5px;
padding: 4px;
border-left: var(--jp-border-width) solid var(--jp-border-color2);
text-align: right;
color: var(--jp-border-color2);
}
.jp-DirListing-narrow .jp-id-narrow {
display: block;
}
.jp-DirListing-narrow .jp-id-modified,
.jp-DirListing-narrow .jp-DirListing-itemModified {
display: none;
}
.jp-DirListing-headerItem.jp-mod-selected {
font-weight: 600;
}
/* increase specificity to override bundled default */
.jp-DirListing-content {
flex: 1 1 auto;
margin: 0;
padding: 0;
list-style-type: none;
overflow: auto;
background-color: var(--jp-layout-color1);
}
.jp-DirListing-content mark {
color: var(--jp-ui-font-color0);
background-color: transparent;
font-weight: bold;
}
.jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark {
color: var(--jp-ui-inverse-font-color0);
}
/* Style the directory listing content when a user drops a file to upload */
.jp-DirListing.jp-mod-native-drop .jp-DirListing-content {
outline: 5px dashed rgba(128, 128, 128, 0.5);
outline-offset: -10px;
cursor: copy;
}
.jp-DirListing-item {
display: flex;
flex-direction: row;
align-items: center;
padding: 4px 12px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.jp-DirListing-checkboxWrapper {
/* Increases hit area of checkbox. */
padding: 4px;
}
.jp-DirListing-header
.jp-DirListing-checkboxWrapper
+ .jp-DirListing-headerItem {
padding-left: 4px;
}
.jp-DirListing-content .jp-DirListing-checkboxWrapper {
position: relative;
left: -4px;
margin: -4px 0 -4px -8px;
}
.jp-DirListing-checkboxWrapper.jp-mod-visible {
visibility: visible;
}
/* For devices that support hovering, hide checkboxes until hovered, selected...
*/
@media (hover: hover) {
.jp-DirListing-checkboxWrapper {
visibility: hidden;
}
.jp-DirListing-item:hover .jp-DirListing-checkboxWrapper,
.jp-DirListing-item.jp-mod-selected .jp-DirListing-checkboxWrapper {
visibility: visible;
}
}
.jp-DirListing-item[data-is-dot] {
opacity: 75%;
}
.jp-DirListing-item.jp-mod-selected {
color: var(--jp-ui-inverse-font-color1);
background: var(--jp-brand-color1);
}
.jp-DirListing-item.jp-mod-dropTarget {
background: var(--jp-brand-color3);
}
.jp-DirListing-item:hover:not(.jp-mod-selected) {
background: var(--jp-layout-color2);
}
.jp-DirListing-itemIcon {
flex: 0 0 20px;
margin-right: 4px;
}
.jp-DirListing-itemText {
flex: 1 0 64px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
user-select: none;
}
.jp-DirListing-itemText:focus {
outline-width: 2px;
outline-color: var(--jp-inverse-layout-color1);
outline-style: solid;
outline-offset: 1px;
}
.jp-DirListing-item.jp-mod-selected .jp-DirListing-itemText:focus {
outline-color: var(--jp-layout-color1);
}
.jp-DirListing-itemModified {
flex: 0 0 125px;
text-align: right;
}
.jp-DirListing-itemFileSize {
flex: 0 0 90px;
text-align: right;
}
.jp-DirListing-editor {
flex: 1 0 64px;
outline: none;
border: none;
color: var(--jp-ui-font-color1);
background-color: var(--jp-layout-color1);
}
.jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon::before {
color: var(--jp-success-color1);
content: '\25CF';
font-size: 8px;
position: absolute;
left: -8px;
}
.jp-DirListing-item.jp-mod-running.jp-mod-selected
.jp-DirListing-itemIcon::before {
color: var(--jp-ui-inverse-font-color1);
}
.jp-DirListing-item.lm-mod-drag-image,
.jp-DirListing-item.jp-mod-selected.lm-mod-drag-image {
font-size: var(--jp-ui-font-size1);
padding-left: 4px;
margin-left: 4px;
width: 160px;
background-color: var(--jp-ui-inverse-font-color2);
box-shadow: var(--jp-elevation-z2);
border-radius: 0;
color: var(--jp-ui-font-color1);
transform: translateX(-40%) translateY(-58%);
}
.jp-Document {
min-width: 120px;
min-height: 120px;
outline: none;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Main OutputArea
| OutputArea has a list of Outputs
|----------------------------------------------------------------------------*/
.jp-OutputArea {
overflow-y: auto;
}
.jp-OutputArea-child {
display: table;
table-layout: fixed;
width: 100%;
overflow: hidden;
}
.jp-OutputPrompt {
width: var(--jp-cell-prompt-width);
color: var(--jp-cell-outprompt-font-color);
font-family: var(--jp-cell-prompt-font-family);
padding: var(--jp-code-padding);
letter-spacing: var(--jp-cell-prompt-letter-spacing);
line-height: var(--jp-code-line-height);
font-size: var(--jp-code-font-size);
border: var(--jp-border-width) solid transparent;
opacity: var(--jp-cell-prompt-opacity);
/* Right align prompt text, don't wrap to handle large prompt numbers */
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* Disable text selection */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.jp-OutputArea-prompt {
display: table-cell;
vertical-align: top;
}
.jp-OutputArea-output {
display: table-cell;
width: 100%;
height: auto;
overflow: auto;
user-select: text;
-moz-user-select: text;
-webkit-user-select: text;
-ms-user-select: text;
}
.jp-OutputArea .jp-RenderedText {
padding-left: 1ch;
}
/**
* Prompt overlay.
*/
.jp-OutputArea-promptOverlay {
position: absolute;
top: 0;
width: var(--jp-cell-prompt-width);
height: 100%;
opacity: 0.5;
}
.jp-OutputArea-promptOverlay:hover {
background: var(--jp-layout-color2);
box-shadow: inset 0 0 1px var(--jp-inverse-layout-color0);
cursor: zoom-out;
}
.jp-mod-outputsScrolled .jp-OutputArea-promptOverlay:hover {
cursor: zoom-in;
}
/**
* Isolated output.
*/
.jp-OutputArea-output.jp-mod-isolated {
width: 100%;
display: block;
}
/*
When drag events occur, `lm-mod-override-cursor` is added to the body.
Because iframes steal all cursor events, the following two rules are necessary
to suppress pointer events while resize drags are occurring. There may be a
better solution to this problem.
*/
body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated {
position: relative;
}
body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: transparent;
}
/* pre */
.jp-OutputArea-output pre {
border: none;
margin: 0;
padding: 0;
overflow-x: auto;
overflow-y: auto;
word-break: break-all;
word-wrap: break-word;
white-space: pre-wrap;
}
/* tables */
.jp-OutputArea-output.jp-RenderedHTMLCommon table {
margin-left: 0;
margin-right: 0;
}
/* description lists */
.jp-OutputArea-output dl,
.jp-OutputArea-output dt,
.jp-OutputArea-output dd {
display: block;
}
.jp-OutputArea-output dl {
width: 100%;
overflow: hidden;
padding: 0;
margin: 0;
}
.jp-OutputArea-output dt {
font-weight: bold;
float: left;
width: 20%;
padding: 0;
margin: 0;
}
.jp-OutputArea-output dd {
float: left;
width: 80%;
padding: 0;
margin: 0;
}
.jp-TrimmedOutputs pre {
background: var(--jp-layout-color3);
font-size: calc(var(--jp-code-font-size) * 1.4);
text-align: center;
text-transform: uppercase;
}
/* Hide the gutter in case of
* - nested output areas (e.g. in the case of output widgets)
* - mirrored output areas
*/
.jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt {
display: none;
}
/* Hide empty lines in the output area, for instance due to cleared widgets */
.jp-OutputArea-prompt:empty {
padding: 0;
border: 0;
}
/*-----------------------------------------------------------------------------
| executeResult is added to any Output-result for the display of the object
| returned by a cell
|----------------------------------------------------------------------------*/
.jp-OutputArea-output.jp-OutputArea-executeResult {
margin-left: 0;
width: 100%;
}
/* Text output with the Out[] prompt needs a top padding to match the
* alignment of the Out[] prompt itself.
*/
.jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output {
padding-top: var(--jp-code-padding);
border-top: var(--jp-border-width) solid transparent;
}
/*-----------------------------------------------------------------------------
| The Stdin output
|----------------------------------------------------------------------------*/
.jp-Stdin-prompt {
color: var(--jp-content-font-color0);
padding-right: var(--jp-code-padding);
vertical-align: baseline;
flex: 0 0 auto;
}
.jp-Stdin-input {
font-family: var(--jp-code-font-family);
font-size: inherit;
color: inherit;
background-color: inherit;
width: 42%;
min-width: 200px;
/* make sure input baseline aligns with prompt */
vertical-align: baseline;
/* padding + margin = 0.5em between prompt and cursor */
padding: 0 0.25em;
margin: 0 0.25em;
flex: 0 0 70%;
}
.jp-Stdin-input::placeholder {
opacity: 0;
}
.jp-Stdin-input:focus {
box-shadow: none;
}
.jp-Stdin-input:focus::placeholder {
opacity: 1;
}
/*-----------------------------------------------------------------------------
| Output Area View
|----------------------------------------------------------------------------*/
.jp-LinkedOutputView .jp-OutputArea {
height: 100%;
display: block;
}
.jp-LinkedOutputView .jp-OutputArea-output:only-child {
height: 100%;
}
/*-----------------------------------------------------------------------------
| Printing
|----------------------------------------------------------------------------*/
@media print {
.jp-OutputArea-child {
break-inside: avoid-page;
}
}
/*-----------------------------------------------------------------------------
| Mobile
|----------------------------------------------------------------------------*/
@media only screen and (max-width: 760px) {
.jp-OutputPrompt {
display: table-row;
text-align: left;
}
.jp-OutputArea-child .jp-OutputArea-output {
display: table-row;
margin-left: var(--jp-notebook-padding);
}
}
/* Trimmed outputs warning */
.jp-TrimmedOutputs > a {
margin: 10px;
text-decoration: none;
cursor: pointer;
}
.jp-TrimmedOutputs > a:hover {
text-decoration: none;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Table of Contents
|----------------------------------------------------------------------------*/
:root {
--jp-private-toc-active-width: 4px;
}
.jp-TableOfContents {
display: flex;
flex-direction: column;
background: var(--jp-layout-color1);
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
height: 100%;
}
.jp-TableOfContents-placeholder {
text-align: center;
}
.jp-TableOfContents-placeholderContent {
color: var(--jp-content-font-color2);
padding: 8px;
}
.jp-TableOfContents-placeholderContent > h3 {
margin-bottom: var(--jp-content-heading-margin-bottom);
}
.jp-TableOfContents .jp-SidePanel-content {
overflow-y: auto;
}
.jp-TableOfContents-tree {
margin: 4px;
}
.jp-TableOfContents ol {
list-style-type: none;
}
/* stylelint-disable-next-line selector-max-type */
.jp-TableOfContents li > ol {
/* Align left border with triangle icon center */
padding-left: 11px;
}
.jp-TableOfContents-content {
/* left margin for the active heading indicator */
margin: 0 0 0 var(--jp-private-toc-active-width);
padding: 0;
background-color: var(--jp-layout-color1);
}
.jp-tocItem {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.jp-tocItem-heading {
display: flex;
cursor: pointer;
}
.jp-tocItem-heading:hover {
background-color: var(--jp-layout-color2);
}
.jp-tocItem-content {
display: block;
padding: 4px 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow-x: hidden;
}
.jp-tocItem-collapser {
height: 20px;
margin: 2px 2px 0;
padding: 0;
background: none;
border: none;
cursor: pointer;
}
.jp-tocItem-collapser:hover {
background-color: var(--jp-layout-color3);
}
/* Active heading indicator */
.jp-tocItem-heading::before {
content: ' ';
background: transparent;
width: var(--jp-private-toc-active-width);
height: 24px;
position: absolute;
left: 0;
border-radius: var(--jp-border-radius);
}
.jp-tocItem-heading.jp-tocItem-active::before {
background-color: var(--jp-brand-color1);
}
.jp-tocItem-heading:hover.jp-tocItem-active::before {
background: var(--jp-brand-color0);
opacity: 1;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
.jp-Collapser {
flex: 0 0 var(--jp-cell-collapser-width);
padding: 0;
margin: 0;
border: none;
outline: none;
background: transparent;
border-radius: var(--jp-border-radius);
opacity: 1;
}
.jp-Collapser-child {
display: block;
width: 100%;
box-sizing: border-box;
/* height: 100% doesn't work because the height of its parent is computed from content */
position: absolute;
top: 0;
bottom: 0;
}
/*-----------------------------------------------------------------------------
| Printing
|----------------------------------------------------------------------------*/
/*
Hiding collapsers in print mode.
Note: input and output wrappers have "display: block" propery in print mode.
*/
@media print {
.jp-Collapser {
display: none;
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Header/Footer
|----------------------------------------------------------------------------*/
/* Hidden by zero height by default */
.jp-CellHeader,
.jp-CellFooter {
height: 0;
width: 100%;
padding: 0;
margin: 0;
border: none;
outline: none;
background: transparent;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Input
|----------------------------------------------------------------------------*/
/* All input areas */
.jp-InputArea {
display: table;
table-layout: fixed;
width: 100%;
overflow: hidden;
}
.jp-InputArea-editor {
display: table-cell;
overflow: hidden;
vertical-align: top;
/* This is the non-active, default styling */
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
border-radius: 0;
background: var(--jp-cell-editor-background);
}
.jp-InputPrompt {
display: table-cell;
vertical-align: top;
width: var(--jp-cell-prompt-width);
color: var(--jp-cell-inprompt-font-color);
font-family: var(--jp-cell-prompt-font-family);
padding: var(--jp-code-padding);
letter-spacing: var(--jp-cell-prompt-letter-spacing);
opacity: var(--jp-cell-prompt-opacity);
line-height: var(--jp-code-line-height);
font-size: var(--jp-code-font-size);
border: var(--jp-border-width) solid transparent;
/* Right align prompt text, don't wrap to handle large prompt numbers */
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* Disable text selection */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/*-----------------------------------------------------------------------------
| Mobile
|----------------------------------------------------------------------------*/
@media only screen and (max-width: 760px) {
.jp-InputArea-editor {
display: table-row;
margin-left: var(--jp-notebook-padding);
}
.jp-InputPrompt {
display: table-row;
text-align: left;
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Placeholder
|----------------------------------------------------------------------------*/
.jp-Placeholder {
display: table;
table-layout: fixed;
width: 100%;
}
.jp-Placeholder-prompt {
display: table-cell;
box-sizing: border-box;
}
.jp-Placeholder-content {
display: table-cell;
padding: 4px 6px;
border: 1px solid transparent;
border-radius: 0;
background: none;
box-sizing: border-box;
cursor: pointer;
}
.jp-Placeholder-contentContainer {
display: flex;
}
.jp-Placeholder-content:hover,
.jp-InputPlaceholder > .jp-Placeholder-content:hover {
border-color: var(--jp-layout-color3);
}
.jp-Placeholder-content .jp-MoreHorizIcon {
width: 32px;
height: 16px;
border: 1px solid transparent;
border-radius: var(--jp-border-radius);
}
.jp-Placeholder-content .jp-MoreHorizIcon:hover {
border: 1px solid var(--jp-border-color1);
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.25);
background-color: var(--jp-layout-color0);
}
.jp-PlaceholderText {
white-space: nowrap;
overflow-x: hidden;
color: var(--jp-inverse-layout-color3);
font-family: var(--jp-code-font-family);
}
.jp-InputPlaceholder > .jp-Placeholder-content {
border-color: var(--jp-cell-editor-border-color);
background: var(--jp-cell-editor-background);
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Private CSS variables
|----------------------------------------------------------------------------*/
:root {
--jp-private-cell-scrolling-output-offset: 5px;
}
/*-----------------------------------------------------------------------------
| Cell
|----------------------------------------------------------------------------*/
.jp-Cell {
padding: var(--jp-cell-padding);
margin: 0;
border: none;
outline: none;
background: transparent;
}
/*-----------------------------------------------------------------------------
| Common input/output
|----------------------------------------------------------------------------*/
.jp-Cell-inputWrapper,
.jp-Cell-outputWrapper {
display: flex;
flex-direction: row;
padding: 0;
margin: 0;
/* Added to reveal the box-shadow on the input and output collapsers. */
overflow: visible;
}
/* Only input/output areas inside cells */
.jp-Cell-inputArea,
.jp-Cell-outputArea {
flex: 1 1 auto;
}
/*-----------------------------------------------------------------------------
| Collapser
|----------------------------------------------------------------------------*/
/* Make the output collapser disappear when there is not output, but do so
* in a manner that leaves it in the layout and preserves its width.
*/
.jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser {
border: none !important;
background: transparent !important;
}
.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser {
min-height: var(--jp-cell-collapser-min-height);
}
/*-----------------------------------------------------------------------------
| Output
|----------------------------------------------------------------------------*/
/* Put a space between input and output when there IS output */
.jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper {
margin-top: 5px;
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea {
overflow-y: auto;
max-height: 24em;
margin-left: var(--jp-private-cell-scrolling-output-offset);
resize: vertical;
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea[style*='height'] {
max-height: unset;
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea::after {
content: ' ';
box-shadow: inset 0 0 6px 2px rgb(0 0 0 / 30%);
width: 100%;
height: 100%;
position: sticky;
bottom: 0;
top: 0;
margin-top: -50%;
float: left;
display: block;
pointer-events: none;
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child {
padding-top: 6px;
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt {
width: calc(
var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset)
);
}
.jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-promptOverlay {
left: calc(-1 * var(--jp-private-cell-scrolling-output-offset));
}
/*-----------------------------------------------------------------------------
| CodeCell
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| MarkdownCell
|----------------------------------------------------------------------------*/
.jp-MarkdownOutput {
display: table-cell;
width: 100%;
margin-top: 0;
margin-bottom: 0;
padding-left: var(--jp-code-padding);
}
.jp-MarkdownOutput.jp-RenderedHTMLCommon {
overflow: auto;
}
/* collapseHeadingButton (show always if hiddenCellsButton is _not_ shown) */
.jp-collapseHeadingButton {
display: flex;
min-height: var(--jp-cell-collapser-min-height);
font-size: var(--jp-code-font-size);
position: absolute;
background-color: transparent;
background-size: 25px;
background-repeat: no-repeat;
background-position-x: center;
background-position-y: top;
background-image: var(--jp-icon-caret-down);
right: 0;
top: 0;
bottom: 0;
}
.jp-collapseHeadingButton.jp-mod-collapsed {
background-image: var(--jp-icon-caret-right);
}
/*
set the container font size to match that of content
so that the nested collapse buttons have the right size
*/
.jp-MarkdownCell .jp-InputPrompt {
font-size: var(--jp-content-font-size1);
}
/*
Align collapseHeadingButton with cell top header
The font sizes are identical to the ones in packages/rendermime/style/base.css
*/
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='1'] {
font-size: var(--jp-content-font-size5);
background-position-y: calc(0.3 * var(--jp-content-font-size5));
}
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='2'] {
font-size: var(--jp-content-font-size4);
background-position-y: calc(0.3 * var(--jp-content-font-size4));
}
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='3'] {
font-size: var(--jp-content-font-size3);
background-position-y: calc(0.3 * var(--jp-content-font-size3));
}
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='4'] {
font-size: var(--jp-content-font-size2);
background-position-y: calc(0.3 * var(--jp-content-font-size2));
}
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='5'] {
font-size: var(--jp-content-font-size1);
background-position-y: top;
}
.jp-mod-rendered .jp-collapseHeadingButton[data-heading-level='6'] {
font-size: var(--jp-content-font-size0);
background-position-y: top;
}
/* collapseHeadingButton (show only on (hover,active) if hiddenCellsButton is shown) */
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-collapseHeadingButton {
display: none;
}
.jp-Notebook.jp-mod-showHiddenCellsButton
:is(.jp-MarkdownCell:hover, .jp-mod-active)
.jp-collapseHeadingButton {
display: flex;
}
/* showHiddenCellsButton (only show if jp-mod-showHiddenCellsButton is set, which
is a consequence of the showHiddenCellsButton option in Notebook Settings)*/
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton {
margin-left: calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));
margin-top: var(--jp-code-padding);
border: 1px solid var(--jp-border-color2);
background-color: var(--jp-border-color3) !important;
color: var(--jp-content-font-color0) !important;
display: flex;
}
.jp-Notebook.jp-mod-showHiddenCellsButton .jp-showHiddenCellsButton:hover {
background-color: var(--jp-border-color2) !important;
}
.jp-showHiddenCellsButton {
display: none;
}
/*-----------------------------------------------------------------------------
| Printing
|----------------------------------------------------------------------------*/
/*
Using block instead of flex to allow the use of the break-inside CSS property for
cell outputs.
*/
@media print {
.jp-Cell-inputWrapper,
.jp-Cell-outputWrapper {
display: block;
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Variables
|----------------------------------------------------------------------------*/
:root {
--jp-notebook-toolbar-padding: 2px 5px 2px 2px;
}
/*-----------------------------------------------------------------------------
/*-----------------------------------------------------------------------------
| Styles
|----------------------------------------------------------------------------*/
.jp-NotebookPanel-toolbar {
padding: var(--jp-notebook-toolbar-padding);
/* disable paint containment from lumino 2.0 default strict CSS containment */
contain: style size !important;
}
.jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused {
border: none;
box-shadow: none;
}
.jp-Notebook-toolbarCellTypeDropdown select {
height: 24px;
font-size: var(--jp-ui-font-size1);
line-height: 14px;
border-radius: 0;
display: block;
}
.jp-Notebook-toolbarCellTypeDropdown span {
top: 5px !important;
}
.jp-Toolbar-responsive-popup {
position: absolute;
height: fit-content;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-end;
border-bottom: var(--jp-border-width) solid var(--jp-toolbar-border-color);
box-shadow: var(--jp-toolbar-box-shadow);
background: var(--jp-toolbar-background);
min-height: var(--jp-toolbar-micro-height);
padding: var(--jp-notebook-toolbar-padding);
z-index: 1;
right: 0;
top: 0;
}
.jp-Toolbar > .jp-Toolbar-responsive-opener {
margin-left: auto;
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Variables
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
/*-----------------------------------------------------------------------------
| Styles
|----------------------------------------------------------------------------*/
.jp-Notebook-ExecutionIndicator {
position: relative;
display: inline-block;
height: 100%;
z-index: 9997;
}
.jp-Notebook-ExecutionIndicator-tooltip {
visibility: hidden;
height: auto;
width: max-content;
width: -moz-max-content;
background-color: var(--jp-layout-color2);
color: var(--jp-ui-font-color1);
text-align: justify;
border-radius: 6px;
padding: 0 5px;
position: fixed;
display: table;
}
.jp-Notebook-ExecutionIndicator-tooltip.up {
transform: translateX(-50%) translateY(-100%) translateY(-32px);
}
.jp-Notebook-ExecutionIndicator-tooltip.down {
transform: translateX(calc(-100% + 16px)) translateY(5px);
}
.jp-Notebook-ExecutionIndicator-tooltip.hidden {
display: none;
}
.jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip {
visibility: visible;
}
.jp-Notebook-ExecutionIndicator span {
font-size: var(--jp-ui-font-size1);
font-family: var(--jp-ui-font-family);
color: var(--jp-ui-font-color1);
line-height: 24px;
display: block;
}
.jp-Notebook-ExecutionIndicator-progress-bar {
display: flex;
justify-content: center;
height: 100%;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
/*
* Execution indicator
*/
.jp-tocItem-content::after {
content: '';
/* Must be identical to form a circle */
width: 12px;
height: 12px;
background: none;
border: none;
position: absolute;
right: 0;
}
.jp-tocItem-content[data-running='0']::after {
border-radius: 50%;
border: var(--jp-border-width) solid var(--jp-inverse-layout-color3);
background: none;
}
.jp-tocItem-content[data-running='1']::after {
border-radius: 50%;
border: var(--jp-border-width) solid var(--jp-inverse-layout-color3);
background-color: var(--jp-inverse-layout-color3);
}
.jp-tocItem-content[data-running='0'],
.jp-tocItem-content[data-running='1'] {
margin-right: 12px;
}
/*
* Copyright (c) Jupyter Development Team.
* Distributed under the terms of the Modified BSD License.
*/
.jp-Notebook-footer {
height: 27px;
margin-left: calc(
var(--jp-cell-prompt-width) + var(--jp-cell-collapser-width) +
var(--jp-cell-padding)
);
width: calc(
100% -
(
var(--jp-cell-prompt-width) + var(--jp-cell-collapser-width) +
var(--jp-cell-padding) + var(--jp-cell-padding)
)
);
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
color: var(--jp-ui-font-color3);
margin-top: 6px;
background: none;
cursor: pointer;
}
.jp-Notebook-footer:focus {
border-color: var(--jp-cell-editor-active-border-color);
}
/* For devices that support hovering, hide footer until hover */
@media (hover: hover) {
.jp-Notebook-footer {
opacity: 0;
}
.jp-Notebook-footer:focus,
.jp-Notebook-footer:hover {
opacity: 1;
}
}
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| Imports
|----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
| CSS variables
|----------------------------------------------------------------------------*/
:root {
--jp-side-by-side-output-size: 1fr;
--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size);
--jp-private-notebook-dragImage-width: 304px;
--jp-private-notebook-dragImage-height: 36px;
--jp-private-notebook-selected-color: var(--md-blue-400);
--jp-private-notebook-active-color: var(--md-green-400);
}
/*-----------------------------------------------------------------------------
| Notebook
|----------------------------------------------------------------------------*/
/* stylelint-disable selector-max-class */
.jp-NotebookPanel {
display: block;
height: 100%;
}
.jp-NotebookPanel.jp-Document {
min-width: 240px;
min-height: 120px;
}
.jp-Notebook {
padding: var(--jp-notebook-padding);
outline: none;
overflow: auto;
background: var(--jp-layout-color0);
}
.jp-Notebook.jp-mod-scrollPastEnd::after {
display: block;
content: '';
min-height: var(--jp-notebook-scroll-padding);
}
.jp-MainAreaWidget-ContainStrict .jp-Notebook * {
contain: strict;
}
.jp-Notebook .jp-Cell {
overflow: visible;
}
.jp-Notebook .jp-Cell .jp-InputPrompt {
cursor: move;
}
/*-----------------------------------------------------------------------------
| Notebook state related styling
|
| The notebook and cells each have states, here are the possibilities:
|
| - Notebook
| - Command
| - Edit
| - Cell
| - None
| - Active (only one can be active)
| - Selected (the cells actions are applied to)
| - Multiselected (when multiple selected, the cursor)
| - No outputs
|----------------------------------------------------------------------------*/
/* Command or edit modes */
.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt {
opacity: var(--jp-cell-prompt-not-active-opacity);
color: var(--jp-cell-prompt-not-active-font-color);
}
.jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt {
opacity: var(--jp-cell-prompt-not-active-opacity);
color: var(--jp-cell-prompt-not-active-font-color);
}
/* cell is active */
.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser {
background: var(--jp-brand-color1);
}
/* cell is dirty */
.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt {
color: var(--jp-warn-color1);
}
.jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt::before {
color: var(--jp-warn-color1);
content: '•';
}
.jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser {
background: var(--jp-warn-color1);
}
/* collapser is hovered */
.jp-Notebook .jp-Cell .jp-Collapser:hover {
box-shadow: var(--jp-elevation-z2);
background: var(--jp-brand-color1);
opacity: var(--jp-cell-collapser-not-active-hover-opacity);
}
/* cell is active and collapser is hovered */
.jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover {
background: var(--jp-brand-color0);
opacity: 1;
}
/* Command mode */
.jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected {
background: var(--jp-notebook-multiselected-color);
}
.jp-Notebook.jp-mod-commandMode
.jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected) {
background: transparent;
}
/* Edit mode */
.jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor {
border: var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);
box-shadow: var(--jp-input-box-shadow);
background-color: var(--jp-cell-editor-active-background);
}
/*-----------------------------------------------------------------------------
| Notebook drag and drop
|----------------------------------------------------------------------------*/
.jp-Notebook-cell.jp-mod-dropSource {
opacity: 0.5;
}
.jp-Notebook-cell.jp-mod-dropTarget,
.jp-Notebook.jp-mod-commandMode
.jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget {
border-top-color: var(--jp-private-notebook-selected-color);
border-top-style: solid;
border-top-width: 2px;
}
.jp-dragImage {
display: block;
flex-direction: row;
width: var(--jp-private-notebook-dragImage-width);
height: var(--jp-private-notebook-dragImage-height);
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
background: var(--jp-cell-editor-background);
overflow: visible;
}
.jp-dragImage-singlePrompt {
box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);
}
.jp-dragImage .jp-dragImage-content {
flex: 1 1 auto;
z-index: 2;
font-size: var(--jp-code-font-size);
font-family: var(--jp-code-font-family);
line-height: var(--jp-code-line-height);
padding: var(--jp-code-padding);
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
background: var(--jp-cell-editor-background-color);
color: var(--jp-content-font-color3);
text-align: left;
margin: 4px 4px 4px 0;
}
.jp-dragImage .jp-dragImage-prompt {
flex: 0 0 auto;
min-width: 36px;
color: var(--jp-cell-inprompt-font-color);
padding: var(--jp-code-padding);
padding-left: 12px;
font-family: var(--jp-cell-prompt-font-family);
letter-spacing: var(--jp-cell-prompt-letter-spacing);
line-height: 1.9;
font-size: var(--jp-code-font-size);
border: var(--jp-border-width) solid transparent;
}
.jp-dragImage-multipleBack {
z-index: -1;
position: absolute;
height: 32px;
width: 300px;
top: 8px;
left: 8px;
background: var(--jp-layout-color2);
border: var(--jp-border-width) solid var(--jp-input-border-color);
box-shadow: 2px 2px 4px 0 rgba(0, 0, 0, 0.12);
}
/*-----------------------------------------------------------------------------
| Cell toolbar
|----------------------------------------------------------------------------*/
.jp-NotebookTools {
display: block;
min-width: var(--jp-sidebar-min-width);
color: var(--jp-ui-font-color1);
background: var(--jp-layout-color1);
/* This is needed so that all font sizing of children done in ems is
* relative to this base size */
font-size: var(--jp-ui-font-size1);
overflow: auto;
}
.jp-ActiveCellTool {
padding: 12px 0;
display: flex;
}
.jp-ActiveCellTool-Content {
flex: 1 1 auto;
}
.jp-ActiveCellTool .jp-ActiveCellTool-CellContent {
background: var(--jp-cell-editor-background);
border: var(--jp-border-width) solid var(--jp-cell-editor-border-color);
border-radius: 0;
min-height: 29px;
}
.jp-ActiveCellTool .jp-InputPrompt {
min-width: calc(var(--jp-cell-prompt-width) * 0.75);
}
.jp-ActiveCellTool-CellContent > pre {
padding: 5px 4px;
margin: 0;
white-space: normal;
}
.jp-MetadataEditorTool {
flex-direction: column;
padding: 12px 0;
}
.jp-RankedPanel > :not(:first-child) {
margin-top: 12px;
}
.jp-KeySelector select.jp-mod-styled {
font-size: var(--jp-ui-font-size1);
color: var(--jp-ui-font-color0);
border: var(--jp-border-width) solid var(--jp-border-color1);
}
.jp-KeySelector label,
.jp-MetadataEditorTool label,
.jp-NumberSetter label {
line-height: 1.4;
}
.jp-NotebookTools .jp-select-wrapper {
margin-top: 4px;
margin-bottom: 0;
}
.jp-NumberSetter input {
width: 100%;
margin-top: 4px;
}
.jp-NotebookTools .jp-Collapse {
margin-top: 16px;
}
/*-----------------------------------------------------------------------------
| Presentation Mode (.jp-mod-presentationMode)
|----------------------------------------------------------------------------*/
.jp-mod-presentationMode .jp-Notebook {
--jp-content-font-size1: var(--jp-content-presentation-font-size1);
--jp-code-font-size: var(--jp-code-presentation-font-size);
}
.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,
.jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt {
flex: 0 0 110px;
}
/*-----------------------------------------------------------------------------
| Side-by-side Mode (.jp-mod-sideBySide)
|----------------------------------------------------------------------------*/
.jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell {
margin-top: 3em;
margin-bottom: 3em;
margin-left: 5%;
margin-right: 5%;
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell {
display: grid;
grid-template-columns: minmax(0, 1fr) min-content minmax(
0,
var(--jp-side-by-side-output-size)
);
grid-template-rows: auto minmax(0, 1fr) auto;
grid-template-areas:
'header header header'
'input handle output'
'footer footer footer';
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell {
grid-template-columns: minmax(0, 1fr) min-content minmax(
0,
var(--jp-side-by-side-resized-cell)
);
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader {
grid-area: header;
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper {
grid-area: input;
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper {
/* overwrite the default margin (no vertical separation needed in side by side move */
margin-top: 0;
grid-area: output;
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter {
grid-area: footer;
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle {
grid-area: handle;
user-select: none;
display: block;
height: 100%;
cursor: ew-resize;
padding: 0 var(--jp-cell-padding);
}
.jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle::after {
content: '';
display: block;
background: var(--jp-border-color2);
height: 100%;
width: 5px;
}
.jp-mod-sideBySide.jp-Notebook
.jp-CodeCell.jp-mod-resizedCell
.jp-CellResizeHandle::after {
background: var(--jp-border-color0);
}
.jp-CellResizeHandle {
display: none;
}
/*-----------------------------------------------------------------------------
| Placeholder
|----------------------------------------------------------------------------*/
.jp-Cell-Placeholder {
padding-left: 55px;
}
.jp-Cell-Placeholder-wrapper {
background: #fff;
border: 1px solid;
border-color: #e5e6e9 #dfe0e4 #d0d1d5;
border-radius: 4px;
-webkit-border-radius: 4px;
margin: 10px 15px;
}
.jp-Cell-Placeholder-wrapper-inner {
padding: 15px;
position: relative;
}
.jp-Cell-Placeholder-wrapper-body {
background-repeat: repeat;
background-size: 50% auto;
}
.jp-Cell-Placeholder-wrapper-body div {
background: #f6f7f8;
background-image: -webkit-linear-gradient(
left,
#f6f7f8 0%,
#edeef1 20%,
#f6f7f8 40%,
#f6f7f8 100%
);
background-repeat: no-repeat;
background-size: 800px 104px;
height: 104px;
position: absolute;
right: 15px;
left: 15px;
top: 15px;
}
div.jp-Cell-Placeholder-h1 {
top: 20px;
height: 20px;
left: 15px;
width: 150px;
}
div.jp-Cell-Placeholder-h2 {
left: 15px;
top: 50px;
height: 10px;
width: 100px;
}
div.jp-Cell-Placeholder-content-1,
div.jp-Cell-Placeholder-content-2,
div.jp-Cell-Placeholder-content-3 {
left: 15px;
right: 15px;
height: 10px;
}
div.jp-Cell-Placeholder-content-1 {
top: 100px;
}
div.jp-Cell-Placeholder-content-2 {
top: 120px;
}
div.jp-Cell-Placeholder-content-3 {
top: 140px;
}
</style>
<style type="text/css">
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
/*
The following CSS variables define the main, public API for styling JupyterLab.
These variables should be used by all plugins wherever possible. In other
words, plugins should not define custom colors, sizes, etc unless absolutely
necessary. This enables users to change the visual theme of JupyterLab
by changing these variables.
Many variables appear in an ordered sequence (0,1,2,3). These sequences
are designed to work well together, so for example, `--jp-border-color1` should
be used with `--jp-layout-color1`. The numbers have the following meanings:
* 0: super-primary, reserved for special emphasis
* 1: primary, most important under normal situations
* 2: secondary, next most important under normal situations
* 3: tertiary, next most important under normal situations
Throughout JupyterLab, we are mostly following principles from Google's
Material Design when selecting colors. We are not, however, following
all of MD as it is not optimized for dense, information rich UIs.
*/
:root {
/* Elevation
*
* We style box-shadows using Material Design's idea of elevation. These particular numbers are taken from here:
*
* https://github.com/material-components/material-components-web
* https://material-components-web.appspot.com/elevation.html
*/
--jp-shadow-base-lightness: 0;
--jp-shadow-umbra-color: rgba(
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
0.2
);
--jp-shadow-penumbra-color: rgba(
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
0.14
);
--jp-shadow-ambient-color: rgba(
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
var(--jp-shadow-base-lightness),
0.12
);
--jp-elevation-z0: none;
--jp-elevation-z1: 0 2px 1px -1px var(--jp-shadow-umbra-color),
0 1px 1px 0 var(--jp-shadow-penumbra-color),
0 1px 3px 0 var(--jp-shadow-ambient-color);
--jp-elevation-z2: 0 3px 1px -2px var(--jp-shadow-umbra-color),
0 2px 2px 0 var(--jp-shadow-penumbra-color),
0 1px 5px 0 var(--jp-shadow-ambient-color);
--jp-elevation-z4: 0 2px 4px -1px var(--jp-shadow-umbra-color),
0 4px 5px 0 var(--jp-shadow-penumbra-color),
0 1px 10px 0 var(--jp-shadow-ambient-color);
--jp-elevation-z6: 0 3px 5px -1px var(--jp-shadow-umbra-color),
0 6px 10px 0 var(--jp-shadow-penumbra-color),
0 1px 18px 0 var(--jp-shadow-ambient-color);
--jp-elevation-z8: 0 5px 5px -3px var(--jp-shadow-umbra-color),
0 8px 10px 1px var(--jp-shadow-penumbra-color),
0 3px 14px 2px var(--jp-shadow-ambient-color);
--jp-elevation-z12: 0 7px 8px -4px var(--jp-shadow-umbra-color),
0 12px 17px 2px var(--jp-shadow-penumbra-color),
0 5px 22px 4px var(--jp-shadow-ambient-color);
--jp-elevation-z16: 0 8px 10px -5px var(--jp-shadow-umbra-color),
0 16px 24px 2px var(--jp-shadow-penumbra-color),
0 6px 30px 5px var(--jp-shadow-ambient-color);
--jp-elevation-z20: 0 10px 13px -6px var(--jp-shadow-umbra-color),
0 20px 31px 3px var(--jp-shadow-penumbra-color),
0 8px 38px 7px var(--jp-shadow-ambient-color);
--jp-elevation-z24: 0 11px 15px -7px var(--jp-shadow-umbra-color),
0 24px 38px 3px var(--jp-shadow-penumbra-color),
0 9px 46px 8px var(--jp-shadow-ambient-color);
/* Borders
*
* The following variables, specify the visual styling of borders in JupyterLab.
*/
--jp-border-width: 1px;
--jp-border-color0: var(--md-grey-400);
--jp-border-color1: var(--md-grey-400);
--jp-border-color2: var(--md-grey-300);
--jp-border-color3: var(--md-grey-200);
--jp-inverse-border-color: var(--md-grey-600);
--jp-border-radius: 2px;
/* UI Fonts
*
* The UI font CSS variables are used for the typography all of the JupyterLab
* user interface elements that are not directly user generated content.
*
* The font sizing here is done assuming that the body font size of --jp-ui-font-size1
* is applied to a parent element. When children elements, such as headings, are sized
* in em all things will be computed relative to that body size.
*/
--jp-ui-font-scale-factor: 1.2;
--jp-ui-font-size0: 0.83333em;
--jp-ui-font-size1: 13px; /* Base font size */
--jp-ui-font-size2: 1.2em;
--jp-ui-font-size3: 1.44em;
--jp-ui-font-family: system-ui, -apple-system, blinkmacsystemfont, 'Segoe UI',
helvetica, arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol';
/*
* Use these font colors against the corresponding main layout colors.
* In a light theme, these go from dark to light.
*/
/* Defaults use Material Design specification */
--jp-ui-font-color0: rgba(0, 0, 0, 1);
--jp-ui-font-color1: rgba(0, 0, 0, 0.87);
--jp-ui-font-color2: rgba(0, 0, 0, 0.54);
--jp-ui-font-color3: rgba(0, 0, 0, 0.38);
/*
* Use these against the brand/accent/warn/error colors.
* These will typically go from light to darker, in both a dark and light theme.
*/
--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);
--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);
--jp-ui-inverse-font-color2: rgba(255, 255, 255, 0.7);
--jp-ui-inverse-font-color3: rgba(255, 255, 255, 0.5);
/* Content Fonts
*
* Content font variables are used for typography of user generated content.
*
* The font sizing here is done assuming that the body font size of --jp-content-font-size1
* is applied to a parent element. When children elements, such as headings, are sized
* in em all things will be computed relative to that body size.
*/
--jp-content-line-height: 1.6;
--jp-content-font-scale-factor: 1.2;
--jp-content-font-size0: 0.83333em;
--jp-content-font-size1: 14px; /* Base font size */
--jp-content-font-size2: 1.2em;
--jp-content-font-size3: 1.44em;
--jp-content-font-size4: 1.728em;
--jp-content-font-size5: 2.0736em;
/* This gives a magnification of about 125% in presentation mode over normal. */
--jp-content-presentation-font-size1: 17px;
--jp-content-heading-line-height: 1;
--jp-content-heading-margin-top: 1.2em;
--jp-content-heading-margin-bottom: 0.8em;
--jp-content-heading-font-weight: 500;
/* Defaults use Material Design specification */
--jp-content-font-color0: rgba(0, 0, 0, 1);
--jp-content-font-color1: rgba(0, 0, 0, 0.87);
--jp-content-font-color2: rgba(0, 0, 0, 0.54);
--jp-content-font-color3: rgba(0, 0, 0, 0.38);
--jp-content-link-color: var(--md-blue-900);
--jp-content-font-family: system-ui, -apple-system, blinkmacsystemfont,
'Segoe UI', helvetica, arial, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol';
/*
* Code Fonts
*
* Code font variables are used for typography of code and other monospaces content.
*/
--jp-code-font-size: 13px;
--jp-code-line-height: 1.3077; /* 17px for 13px base */
--jp-code-padding: 5px; /* 5px for 13px base, codemirror highlighting needs integer px value */
--jp-code-font-family-default: menlo, consolas, 'DejaVu Sans Mono', monospace;
--jp-code-font-family: var(--jp-code-font-family-default);
/* This gives a magnification of about 125% in presentation mode over normal. */
--jp-code-presentation-font-size: 16px;
/* may need to tweak cursor width if you change font size */
--jp-code-cursor-width0: 1.4px;
--jp-code-cursor-width1: 2px;
--jp-code-cursor-width2: 4px;
/* Layout
*
* The following are the main layout colors use in JupyterLab. In a light
* theme these would go from light to dark.
*/
--jp-layout-color0: white;
--jp-layout-color1: white;
--jp-layout-color2: var(--md-grey-200);
--jp-layout-color3: var(--md-grey-400);
--jp-layout-color4: var(--md-grey-600);
/* Inverse Layout
*
* The following are the inverse layout colors use in JupyterLab. In a light
* theme these would go from dark to light.
*/
--jp-inverse-layout-color0: #111;
--jp-inverse-layout-color1: var(--md-grey-900);
--jp-inverse-layout-color2: var(--md-grey-800);
--jp-inverse-layout-color3: var(--md-grey-700);
--jp-inverse-layout-color4: var(--md-grey-600);
/* Brand/accent */
--jp-brand-color0: var(--md-blue-900);
--jp-brand-color1: var(--md-blue-700);
--jp-brand-color2: var(--md-blue-300);
--jp-brand-color3: var(--md-blue-100);
--jp-brand-color4: var(--md-blue-50);
--jp-accent-color0: var(--md-green-900);
--jp-accent-color1: var(--md-green-700);
--jp-accent-color2: var(--md-green-300);
--jp-accent-color3: var(--md-green-100);
/* State colors (warn, error, success, info) */
--jp-warn-color0: var(--md-orange-900);
--jp-warn-color1: var(--md-orange-700);
--jp-warn-color2: var(--md-orange-300);
--jp-warn-color3: var(--md-orange-100);
--jp-error-color0: var(--md-red-900);
--jp-error-color1: var(--md-red-700);
--jp-error-color2: var(--md-red-300);
--jp-error-color3: var(--md-red-100);
--jp-success-color0: var(--md-green-900);
--jp-success-color1: var(--md-green-700);
--jp-success-color2: var(--md-green-300);
--jp-success-color3: var(--md-green-100);
--jp-info-color0: var(--md-cyan-900);
--jp-info-color1: var(--md-cyan-700);
--jp-info-color2: var(--md-cyan-300);
--jp-info-color3: var(--md-cyan-100);
/* Cell specific styles */
--jp-cell-padding: 5px;
--jp-cell-collapser-width: 8px;
--jp-cell-collapser-min-height: 20px;
--jp-cell-collapser-not-active-hover-opacity: 0.6;
--jp-cell-editor-background: var(--md-grey-100);
--jp-cell-editor-border-color: var(--md-grey-300);
--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);
--jp-cell-editor-active-background: var(--jp-layout-color0);
--jp-cell-editor-active-border-color: var(--jp-brand-color1);
--jp-cell-prompt-width: 64px;
--jp-cell-prompt-font-family: var(--jp-code-font-family-default);
--jp-cell-prompt-letter-spacing: 0;
--jp-cell-prompt-opacity: 1;
--jp-cell-prompt-not-active-opacity: 0.5;
--jp-cell-prompt-not-active-font-color: var(--md-grey-700);
/* A custom blend of MD grey and blue 600
* See https://meyerweb.com/eric/tools/color-blend/#546E7A:1E88E5:5:hex */
--jp-cell-inprompt-font-color: #307fc1;
/* A custom blend of MD grey and orange 600
* https://meyerweb.com/eric/tools/color-blend/#546E7A:F4511E:5:hex */
--jp-cell-outprompt-font-color: #bf5b3d;
/* Notebook specific styles */
--jp-notebook-padding: 10px;
--jp-notebook-select-background: var(--jp-layout-color1);
--jp-notebook-multiselected-color: var(--md-blue-50);
/* The scroll padding is calculated to fill enough space at the bottom of the
notebook to show one single-line cell (with appropriate padding) at the top
when the notebook is scrolled all the way to the bottom. We also subtract one
pixel so that no scrollbar appears if we have just one single-line cell in the
notebook. This padding is to enable a 'scroll past end' feature in a notebook.
*/
--jp-notebook-scroll-padding: calc(
100% - var(--jp-code-font-size) * var(--jp-code-line-height) -
var(--jp-code-padding) - var(--jp-cell-padding) - 1px
);
/* Rendermime styles */
--jp-rendermime-error-background: #fdd;
--jp-rendermime-table-row-background: var(--md-grey-100);
--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);
/* Dialog specific styles */
--jp-dialog-background: rgba(0, 0, 0, 0.25);
/* Console specific styles */
--jp-console-padding: 10px;
/* Toolbar specific styles */
--jp-toolbar-border-color: var(--jp-border-color1);
--jp-toolbar-micro-height: 8px;
--jp-toolbar-background: var(--jp-layout-color1);
--jp-toolbar-box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.24);
--jp-toolbar-header-margin: 4px 4px 0 4px;
--jp-toolbar-active-background: var(--md-grey-300);
/* Statusbar specific styles */
--jp-statusbar-height: 24px;
/* Input field styles */
--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);
--jp-input-active-background: var(--jp-layout-color1);
--jp-input-hover-background: var(--jp-layout-color1);
--jp-input-background: var(--md-grey-100);
--jp-input-border-color: var(--jp-inverse-border-color);
--jp-input-active-border-color: var(--jp-brand-color1);
--jp-input-active-box-shadow-color: rgba(19, 124, 189, 0.3);
/* General editor styles */
--jp-editor-selected-background: #d9d9d9;
--jp-editor-selected-focused-background: #d7d4f0;
--jp-editor-cursor-color: var(--jp-ui-font-color0);
/* Code mirror specific styles */
--jp-mirror-editor-keyword-color: #008000;
--jp-mirror-editor-atom-color: #88f;
--jp-mirror-editor-number-color: #080;
--jp-mirror-editor-def-color: #00f;
--jp-mirror-editor-variable-color: var(--md-grey-900);
--jp-mirror-editor-variable-2-color: rgb(0, 54, 109);
--jp-mirror-editor-variable-3-color: #085;
--jp-mirror-editor-punctuation-color: #05a;
--jp-mirror-editor-property-color: #05a;
--jp-mirror-editor-operator-color: #a2f;
--jp-mirror-editor-comment-color: #408080;
--jp-mirror-editor-string-color: #ba2121;
--jp-mirror-editor-string-2-color: #708;
--jp-mirror-editor-meta-color: #a2f;
--jp-mirror-editor-qualifier-color: #555;
--jp-mirror-editor-builtin-color: #008000;
--jp-mirror-editor-bracket-color: #997;
--jp-mirror-editor-tag-color: #170;
--jp-mirror-editor-attribute-color: #00c;
--jp-mirror-editor-header-color: blue;
--jp-mirror-editor-quote-color: #090;
--jp-mirror-editor-link-color: #00c;
--jp-mirror-editor-error-color: #f00;
--jp-mirror-editor-hr-color: #999;
/*
RTC user specific colors.
These colors are used for the cursor, username in the editor,
and the icon of the user.
*/
--jp-collaborator-color1: #ffad8e;
--jp-collaborator-color2: #dac83d;
--jp-collaborator-color3: #72dd76;
--jp-collaborator-color4: #00e4d0;
--jp-collaborator-color5: #45d4ff;
--jp-collaborator-color6: #e2b1ff;
--jp-collaborator-color7: #ff9de6;
/* Vega extension styles */
--jp-vega-background: white;
/* Sidebar-related styles */
--jp-sidebar-min-width: 250px;
/* Search-related styles */
--jp-search-toggle-off-opacity: 0.5;
--jp-search-toggle-hover-opacity: 0.8;
--jp-search-toggle-on-opacity: 1;
--jp-search-selected-match-background-color: rgb(245, 200, 0);
--jp-search-selected-match-color: black;
--jp-search-unselected-match-background-color: var(
--jp-inverse-layout-color0
);
--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);
/* Icon colors that work well with light or dark backgrounds */
--jp-icon-contrast-color0: var(--md-purple-600);
--jp-icon-contrast-color1: var(--md-green-600);
--jp-icon-contrast-color2: var(--md-pink-600);
--jp-icon-contrast-color3: var(--md-blue-600);
/* Button colors */
--jp-accept-color-normal: var(--md-blue-700);
--jp-accept-color-hover: var(--md-blue-800);
--jp-accept-color-active: var(--md-blue-900);
--jp-warn-color-normal: var(--md-red-700);
--jp-warn-color-hover: var(--md-red-800);
--jp-warn-color-active: var(--md-red-900);
--jp-reject-color-normal: var(--md-grey-600);
--jp-reject-color-hover: var(--md-grey-700);
--jp-reject-color-active: var(--md-grey-800);
/* File or activity icons and switch semantic variables */
--jp-jupyter-icon-color: #f37626;
--jp-notebook-icon-color: #f37626;
--jp-json-icon-color: var(--md-orange-700);
--jp-console-icon-background-color: var(--md-blue-700);
--jp-console-icon-color: white;
--jp-terminal-icon-background-color: var(--md-grey-800);
--jp-terminal-icon-color: var(--md-grey-200);
--jp-text-editor-icon-color: var(--md-grey-700);
--jp-inspector-icon-color: var(--md-grey-700);
--jp-switch-color: var(--md-grey-400);
--jp-switch-true-position-color: var(--md-orange-900);
}
</style>
<style type="text/css">
/* Force rendering true colors when outputing to pdf */
* {
-webkit-print-color-adjust: exact;
}
/* Misc */
a.anchor-link {
display: none;
}
/* Input area styling */
.jp-InputArea {
overflow: hidden;
}
.jp-InputArea-editor {
overflow: hidden;
}
.cm-editor.cm-s-jupyter .highlight pre {
/* weird, but --jp-code-padding defined to be 5px but 4px horizontal padding is hardcoded for pre.cm-line */
padding: var(--jp-code-padding) 4px;
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: inherit;
}
.jp-OutputArea-output pre {
line-height: inherit;
font-family: inherit;
}
.jp-RenderedText pre {
color: var(--jp-content-font-color1);
font-size: var(--jp-code-font-size);
}
/* Hiding the collapser by default */
.jp-Collapser {
display: none;
}
@page {
margin: 0.5in; /* Margin for each printed piece of paper */
}
@media print {
.jp-Cell-inputWrapper,
.jp-Cell-outputWrapper {
display: block;
}
}
</style>
<!-- Load mathjax -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-AMS_CHTML-full,Safe"> </script>
<!-- MathJax configuration -->
<script type="text/x-mathjax-config">
init_mathjax = function() {
if (window.MathJax) {
// MathJax loaded
MathJax.Hub.Config({
TeX: {
equationNumbers: {
autoNumber: "AMS",
useLabelIds: true
}
},
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true,
processEnvironments: true
},
displayAlign: 'center',
CommonHTML: {
linebreaks: {
automatic: true
}
}
});
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
}
init_mathjax();
</script>
<!-- End of mathjax configuration --><script type="module">
document.addEventListener("DOMContentLoaded", async () => {
const diagrams = document.querySelectorAll(".jp-Mermaid > pre.mermaid");
// do not load mermaidjs if not needed
if (!diagrams.length) {
return;
}
const mermaid = (await import("https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs")).default;
const parser = new DOMParser();
mermaid.initialize({
maxTextSize: 100000,
maxEdges: 100000,
startOnLoad: false,
fontFamily: window
.getComputedStyle(document.body)
.getPropertyValue("--jp-ui-font-family"),
theme: document.querySelector("body[data-jp-theme-light='true']")
? "default"
: "dark",
});
let _nextMermaidId = 0;
function makeMermaidImage(svg) {
const img = document.createElement("img");
const doc = parser.parseFromString(svg, "image/svg+xml");
const svgEl = doc.querySelector("svg");
const { maxWidth } = svgEl?.style || {};
const firstTitle = doc.querySelector("title");
const firstDesc = doc.querySelector("desc");
img.setAttribute("src", `data:image/svg+xml,${encodeURIComponent(svg)}`);
if (maxWidth) {
img.width = parseInt(maxWidth);
}
if (firstTitle) {
img.setAttribute("alt", firstTitle.textContent);
}
if (firstDesc) {
const caption = document.createElement("figcaption");
caption.className = "sr-only";
caption.textContent = firstDesc.textContent;
return [img, caption];
}
return [img];
}
async function makeMermaidError(text) {
let errorMessage = "";
try {
await mermaid.parse(text);
} catch (err) {
errorMessage = `${err}`;
}
const result = document.createElement("details");
result.className = 'jp-RenderedMermaid-Details';
const summary = document.createElement("summary");
summary.className = 'jp-RenderedMermaid-Summary';
const pre = document.createElement("pre");
const code = document.createElement("code");
code.innerText = text;
pre.appendChild(code);
summary.appendChild(pre);
result.appendChild(summary);
const warning = document.createElement("pre");
warning.innerText = errorMessage;
result.appendChild(warning);
return [result];
}
async function renderOneMarmaid(src) {
const id = `jp-mermaid-${_nextMermaidId++}`;
const parent = src.parentNode;
let raw = src.textContent.trim();
const el = document.createElement("div");
el.style.visibility = "hidden";
document.body.appendChild(el);
let results = null;
let output = null;
try {
let { svg } = await mermaid.render(id, raw, el);
svg = cleanMermaidSvg(svg);
results = makeMermaidImage(svg);
output = document.createElement("figure");
results.map(output.appendChild, output);
} catch (err) {
parent.classList.add("jp-mod-warning");
results = await makeMermaidError(raw);
output = results[0];
} finally {
el.remove();
}
parent.classList.add("jp-RenderedMermaid");
parent.appendChild(output);
}
/**
* Post-process to ensure mermaid diagrams contain only valid SVG and XHTML.
*/
function cleanMermaidSvg(svg) {
return svg.replace(RE_VOID_ELEMENT, replaceVoidElement);
}
/**
* A regular expression for all void elements, which may include attributes and
* a slash.
*
* @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element
*
* Of these, only `<br>` is generated by Mermaid in place of `\n`,
* but _any_ "malformed" tag will break the SVG rendering entirely.
*/
const RE_VOID_ELEMENT =
/<\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\s*([^>]*?)\s*>/gi;
/**
* Ensure a void element is closed with a slash, preserving any attributes.
*/
function replaceVoidElement(match, tag, rest) {
rest = rest.trim();
if (!rest.endsWith('/')) {
rest = `${rest} /`;
}
return `<${tag} ${rest}>`;
}
void Promise.all([...diagrams].map(renderOneMarmaid));
});
</script>
<style>
.jp-Mermaid:not(.jp-RenderedMermaid) {
display: none;
}
.jp-RenderedMermaid {
overflow: auto;
display: flex;
}
.jp-RenderedMermaid.jp-mod-warning {
width: auto;
padding: 0.5em;
margin-top: 0.5em;
border: var(--jp-border-width) solid var(--jp-warn-color2);
border-radius: var(--jp-border-radius);
color: var(--jp-ui-font-color1);
font-size: var(--jp-ui-font-size1);
white-space: pre-wrap;
word-wrap: break-word;
}
.jp-RenderedMermaid figure {
margin: 0;
overflow: auto;
max-width: 100%;
}
.jp-RenderedMermaid img {
max-width: 100%;
}
.jp-RenderedMermaid-Details > pre {
margin-top: 1em;
}
.jp-RenderedMermaid-Summary {
color: var(--jp-warn-color2);
}
.jp-RenderedMermaid:not(.jp-mod-warning) pre {
display: none;
}
.jp-RenderedMermaid-Summary > pre {
display: inline-block;
white-space: normal;
}
</style>
<!-- End of mermaid configuration --></head>
<body class="jp-Notebook" data-jp-theme-light="true" data-jp-theme-name="JupyterLab Light">
<main>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=2e15ced8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<img alt="No description has been provided for this image" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/VU_logo.png/800px-VU_logo.png?20161029201021" width="350"/>
<h3 id="Programming-large-scale-parallel-systems">Programming large-scale parallel systems<a class="anchor-link" href="#Programming-large-scale-parallel-systems"></a></h3>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=e8549215">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h1 id="Jacobi-method">Jacobi method<a class="anchor-link" href="#Jacobi-method"></a></h1>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6e0ef563">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Contents">Contents<a class="anchor-link" href="#Contents"></a></h2><p>In this notebook, we will learn</p>
<ul>
<li>How to paralleize the Jacobi method</li>
<li>How the data partition can impact the performance of a distributed algorithm</li>
<li>How to use latency hiding to improve parallel performance</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=48fd29d9">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-info">
<b>Note:</b> Do not forget to run the next cell before you start studying this notebook.
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=1dc78750">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">using</span><span class="w"> </span><span class="n">Printf</span>
<span class="k">function</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="n">solution</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">answer</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">solution</span>
<span class="w"> </span><span class="s">"🥳 Well done! "</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="s">"It's not correct. Keep trying! 💪"</span>
<span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="o">|&gt;</span><span class="w"> </span><span class="n">println</span>
<span class="k">end</span>
<span class="n">gauss_seidel_1_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"c"</span><span class="p">)</span>
<span class="n">jacobi_1_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"d"</span><span class="p">)</span>
<span class="n">jacobi_2_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"b"</span><span class="p">)</span>
<span class="n">jacobi_3_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"c"</span><span class="p">)</span>
<span class="n">lh_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"c"</span><span class="p">)</span>
<span class="n">sndrcv_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"b"</span><span class="p">)</span>
<span class="k">function</span><span class="w"> </span><span class="n">partition_1d_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s">- We update N^2/P items per iteration</span>
<span class="s">- We need data from 2 neighbors (2 messages per iteration)</span>
<span class="s">- We communicate N items per message</span>
<span class="s">- Communication/computation ratio is 2N/(N^2/P) = 2P/N =O(P/N)</span>
<span class="s"> """</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">partition_2d_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s">- We update N^2/P items per iteration</span>
<span class="s">- We need data from 4 neighbors (4 messages per iteration)</span>
<span class="s">- We communicate N/sqrt(P) items per message</span>
<span class="s">- Communication/computation ratio is (4N/sqrt(P)/(N^2/P)= 4sqrt(P)/N =O(sqrt(P)/N)</span>
<span class="s"> """</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">partition_cyclic_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s">- We update N^2/P items</span>
<span class="s">- We need data from 4 neighbors (4 messages per iteration)</span>
<span class="s">- We communicate N^2/P items per message (the full data owned by the neighbor)</span>
<span class="s">- Communication/computation ratio is O(1)</span>
<span class="s"> """</span>
<span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">sndrcv_fix_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s"> One needs to carefully order the sends and the receives to avoid cyclic dependencies</span>
<span class="s"> that might result in deadlocks. The actual implementation is left as an exercise. </span>
<span class="s"> """</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">jacobitest_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"a"</span><span class="p">)</span>
<span class="k">function</span><span class="w"> </span><span class="n">jacobitest_why</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s"> The test will pass. The parallel implementation does exactly the same operations</span>
<span class="s"> in exactly the same order than the sequential one. Thus, the result should be</span>
<span class="s"> exactly the same. Note however this is often not true in other parallel algorithms.</span>
<span class="s"> Specially, when one does parallel reductions.</span>
<span class="s"> """</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">gauss_seidel_2_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"d"</span><span class="p">)</span>
<span class="k">function</span><span class="w"> </span><span class="n">gauss_seidel_2_why</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
<span class="s"> All "red" cells can be updated in parallel as they only depend on the values of "black" cells.</span>
<span class="s"> In order workds, we can update the "red" cells in any order whithout changing the result. They only</span>
<span class="s"> depend on values in the "black" cells, which will not change during the loop over "red" cells.</span>
<span class="s"> Similarly, all "black" cells can be updated in parallel as they only depend on "red" cells.</span>
<span class="s"> """</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">println</span><span class="p">(</span><span class="s">"🥳 Well done! "</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d4cb59d5">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="The-Jacobi-method-for-the-Laplace-equation">The Jacobi method for the Laplace equation<a class="anchor-link" href="#The-Jacobi-method-for-the-Laplace-equation"></a></h2><p>The <a href="https://en.wikipedia.org/wiki/Jacobi_method">Jacobi method</a> is a numerical tool to solve systems of linear algebraic equations. One of the main applications of the Jacobi method is to solve the equations resulting from boundary value problems (BVPs). I.e., given the values at the boundary (of a grid), we are interested in finding the interior values that fulfill a certain equation.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6a2bdbc6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="300">
</img></div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=93e84ff8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>When solving a <a href="https://en.wikipedia.org/wiki/Laplace%27s_equation">Laplace equation</a> in 1D, the Jacobi method leads to the following iterative scheme: The entry $i$ of vector $u$ at iteration $t+1$ is computed as:</p>
<p>$u^{t+1}_i = \dfrac{u^t_{i-1}+u^t_{i+1}}{2}$</p>
<p>This algorithm is yet simple but shares fundamental challenges with many other algorithms used in scientific computing. This is why we are studying it here.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=e63a5792">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Serial-implementation">Serial implementation<a class="anchor-link" href="#Serial-implementation"></a></h3><p>The following code implements the iterative scheme above for boundary conditions -1 and 1 on a grid with $n$ interior points.</p>
<div class="alert alert-block alert-info">
<b>Note:</b> `u, u_new = u_new, u` is equivalent to `tmp = u; u = u_new; u_new = tmp`. I.e. we swap the arrays `u` and `u_new` are referring to.
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=14a58308">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=432bd862">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>If you run it for zero iterations, we will see the initial condition.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=76e1eba1">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">jacobi</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c75cb9a6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>If you run it for enough iterations, you will see the expected solution of the Laplace equation: values that vary linearly form -1 to 1.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=b52be374">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">jacobi</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">100</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=22fda724">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>In our version of the Jacobi method, we return after a given number of iterations. Other stopping criteria are possible. For instance, iterate until the maximum difference between u and u_new (in absolute value) is below a tolerance.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=15de7bf5">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">jacobi_with_tol</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">tol</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="nb">true</span>
<span class="w"> </span><span class="n">diff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">ui_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ui_new</span>
<span class="w"> </span><span class="n">diff_i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">ui_new</span><span class="o">-</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<span class="w"> </span><span class="n">diff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">max</span><span class="p">(</span><span class="n">diff_i</span><span class="p">,</span><span class="n">diff</span><span class="p">)</span><span class="w"> </span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">diff</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">tol</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">u_new</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=697ad307">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span>
<span class="n">tol</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1e-9</span>
<span class="n">jacobi_with_tol</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">tol</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6e085701">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>However, we are not going to parallelize this more complex in this notebook (left as an exercise). The simpler one is already challenging enough to start with.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9df06442">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Parallelization-of-the-Jacobi-method">Parallelization of the Jacobi method<a class="anchor-link" href="#Parallelization-of-the-Jacobi-method"></a></h2><p>Now, let us parallelize the Jacobi method.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d6918c31">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Where-can-we-exploit-parallelism?">Where can we exploit parallelism?<a class="anchor-link" href="#Where-can-we-exploit-parallelism?"></a></h3><p>Look at the two nested loops in the sequential implementation:</p>
<div class="highlight"><pre><span></span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">nsteps</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
<ul>
<li>The outer loop over <code>t</code> cannot be parallelized. The value of <code>u</code> at step <code>t+1</code> depends on the value at the previous step <code>t</code>.</li>
<li>The inner loop is trivially parallel. The loop iterations are independent (any order is possible).</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=97a2d7d5">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Parallelization-strategy">Parallelization strategy<a class="anchor-link" href="#Parallelization-strategy"></a></h3><p>Remember that a sufficiently large grain size is needed to achieve performance in a distributed algorithm. For Jacobi, one could update each entry of vector <code>u_new</code> in a different process, but this would not be efficient. Instead, we use a parallelization strategy with a larger grain size that is analogous to the algorithm 3 we studied for the matrix-matrix multiplication:</p>
<ul>
<li>Data partition: each worker updates a consecutive section of the array <code>u_new</code></li>
</ul>
<p>The following figure displays the data distribution over 3 processes.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=a9667c42">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=22dc6e54">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Data-dependencies">Data dependencies<a class="anchor-link" href="#Data-dependencies"></a></h3><p>Recall the Jacobi update:</p>
<p><code>u_new[i] = 0.5*(u[i-1]+u[i+1])</code></p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=ba4113af">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Note that an entry in the interior of the locally stored vector can be updated using local data only. For updating this one, communication is not needed.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=97a5079d">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=343e60c3">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>However, to update the entries on the boundary of the locally stored vector we need entries stored on other processors.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=fce954fe">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=3f90d701">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Thus, in order to update the local entries in <code>u_new</code>, we also need some remote entries of vector <code>u</code> located in neighboring processes. Figure below shows the entries of <code>u</code> needed to update the local entries of <code>u_new</code> in a particular process (CPU 2).</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8e156e29">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=513f1f7e">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Communication-overhead">Communication overhead<a class="anchor-link" href="#Communication-overhead"></a></h3><p>Now that we understand which are the data dependencies, we can do the theoretical performance analysis.</p>
<ul>
<li>We update $N/P$ entries in each process at each iteration, where $N$ is the total length of the vector and $P$ the number of processes</li>
<li>Thus, computation complexity is $O(N/P)$</li>
<li>We need to get remote entries from 2 neighbors (2 messages per iteration)</li>
<li>We need to communicate 1 entry per message</li>
<li>Thus, communication complexity is $O(1)$</li>
<li>Communication/computation ration is $O(P/N)$, making the algorithm potentially scalable if $P&lt;&lt;N$.</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=1b3c8c05">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Ghost-(aka-halo)-cells">Ghost (aka halo) cells<a class="anchor-link" href="#Ghost-(aka-halo)-cells"></a></h3><p>This parallel strategy is efficient according to the theoretical analysis. But how to implement it? A usual way of implementing the Jacobi method and related algorithms is using so-called ghost cells. Ghost cells represent the missing data dependencies in the data owned by each process. After importing the appropriate values from the neighbor processes one can perform the usual sequential Jacobi update locally in the processes. Cells with gray edges are ghost (or boundary) cells in the following figure. Note that we added one ghost cell at the front and end of the local array.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=98e0eb71">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=0148f9b3">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Thus, the algorithm is usually implemented following two main phases at each iteration Jacobi:</p>
<ol>
<li>Fill the ghost entries with communications</li>
<li>Do the Jacobi update sequentially at each process</li>
</ol>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=baccd833">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA6gAAAFACAYAAACxyVHuAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAewgAAHsIBbtB1PgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N15fFT19f/x12cmIQFkE1wANxBFrTu4b1itimQC2mKrtfrtRtXazbbWrmJba+1m7S5fv9Wqrbb5VWBugFatpe4buGvdFVcU2cISSOZ+fn+cO2QyTCAsmXszeT8fj/vIvXPv3Dm5M3PnnvvZ3DXXXOMRERERERERiVkq7gBEREREREREQAmqiIiIiIiIJERV0fLJzrlX4whEREREREREehbv/W7AP/PL7RJU59yrU6ZMeb7cQYmIiIiIiEjPM23aNLxv6xZJVXxFREREREQkEZSgioiIiIiISCIoQRUREREREZFEUIIqIiIiIiIiiaAEVURERERERBJBCaqIiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEZSgioiIiIiISCIoQRUREREREZFEUIIqIiIiIiIiiaAEVURERERERBKhKu4ARDbGe+8aGxsvizuODbnuuusOWLhw4SCAhQsXvvbiiy++EndMRXYBRkbzy4H5McZSSn/g4ILlu4FcTLGUdPjhhx+dTqerAE455ZSnDjzwwEVxx9QR59yDdXV1s8rxWtls9nPOueHleK3NMXv27BFPPPHErgArV65c8thjjz0ed0xFBgEHFCzPjSmODRlXMP84sCSmODpyAHYcARYAL8cYy3pGjBixy7Bhw0YCbLvttsunTJmStPNvO+l0+vJTTz11TVe/ThAEewFndfXrbK7m5ub0L3/5y2Pyy88+++z8xYsXL48zphIOxn4/wT73C2KMpZQRwK7R/FLgsRhjWc/gwYMH7rXXXgfmly+55JK5MYazUWEY3jBx4sQX446jHJSgSuJddtllbsyYMd+NO44NeeGFF3jyySfzi8dsaNuEmBB3ABuRuGP4wAMPrJsfN25c4uIr5L3/LVCWBBX4DDC2TK+1yd577z3uvffewofq44qlkxL92SL58SXOK6+8wiuv2D3LUaNGQcLPv9XV1T8HujxB9d6Pds4l+re96NyR9M9+0uMDyMQdQKH333+/3XschuExqVRyK5em0+l7gR6RoCb3XRAREREREZEeRSWo0h09jlUVSYwwDI8i+j717j1w5erVPBdzSEVW7AGt/Ww+HUK/RFWzgTVDYPUubcsDnwRaYgunBOeWHey9B2DNmjULgKRV494XGBxzDK+QsCpma9euPYioClxNTZ/cmjW9ElbFt3lHaB7WtjwwgdU/lxZUv+/7JlQvjC+WUpYdAD5t871WQp9EnX/79HGjVq1a0h/Ae58D7ok5pGL9aN/EIg4h1rQjMcIw7AUckV+uqdl2wZo1YcKadiw7EHxU2FTTBL1fiDeeYk17Qm4bm0/noF+izr+1tentm5vf3ym/7L2/C/AxhlTKcXEHEAclqNLteO8vqq+vvzPuOAqNGjVqCTAQYOTII196+ulZ58ccUpHBv4bFh9p87RpYkrD4jq+Hud9uW/7zxXDq4vjiWV91de8H165tBuCpp576y89+9rNvxhxSO42NjTO89xNjDuN/M5nMFTHH0M6RRx55P3A4wHbbjVj1xhtPJeyzP+YTMP/CtuWkfTcB3INt80dOh9tujC+WUqpvh9aoHd6Or8BriTqGu+/+4auffPLWwwFaWlqaM5nMuJhDaiebzR7inHso5jASd1zOPPPMHYB38sujR3/xxieeuDQbY0glVM2FXG+b3+m/8OKFG9y87AZNg6VRG/u+q5N2fttrr0vOfOyxK7+cX/7zn//8oYaGhrVxxlQsCIIcPbDGa4/7h0VERERERCSZlKCKiIiIiIhIIihBFRERERERkURQgioiIiIiIiKJoARVREREREREEkEJqoiIiIiIiCSChpmRnqwa2A/YPVp+Bng6vnBERERERHo2JajS0+wBXASMAfYHagrWfR+4NI6gRERERKTbGhlNAK8Dz8UYS7enBFV6mn2B8wqWffTXxRCLiIiIiHQ/w4AvYAUeY4FBBeuuBr4cR1CVQgmq9DSLgZuBedE0H3iV9icWEREREZGO7AVcEncQlUoJqvQ0/4kmEREREZHNsRKYQ1uBxzzgLmC3GGOqGEpQRUREREREOu9B4NS4g6hUGmZGREREREREEkEJqoiIiIiIiCSCElQRERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKBKpZiHjXFaPP0tzqBERERERKTzNMxM5doD+EfB8geA5o08pwZ4pmB5PPD8Vo6rqwwABpV4fJtyByIiIiIiIptHCWrl6gWMLFh2nXiOK3pOr60aUdcaQ+kaAS3lDkRERERERDaPElSpFMviDkBERERERLaM2qCKiIiIiIhIIqgEVXqig2h/cyYd/R2GVRXOewd4s1xBiYiIiIj0dEpQpSe6B+hT4vHPRFPelcAlZYlIRERERLqTXWkr5IC2vGoA7ft0WQ4sKldQlUAJqvRErwC9O7Hd4q4ORERERES6pQeAHUs8/j/RlPcH4PwyxFMxlKBKT7Rv3AGIiIiISLe2DBuicWNWdXUglUYJqoiIiIiIyKbZK+4AKpV68RUREREREZFEUIIqIiIiIiIiiaAEVQp1ph69iIiIiIhIl1CCWrlWFy13ptfaUj2RiYiIiIiIlIUS1Mq1rGh5eCeec0RXBCIiIiIiItIZSlAr1/u0HxT46I1s74DPdV04IiIiIiIiG6YEtbLdVzD/eaB6A9teBBzeteGIiIiIiIh0TAlqZftTwfwHgFuAIUXbDAGuBn4KLC1TXCIiIiIiIuupijsA6VIzgLuAY6Pl04EJwCNYG9XtgQOxz0ELcBYwu/xhbhrn3KFBENTGHUehr33ta+u+S8uXv90PPnZknPGsb+3AtvlcKnnxvT6q/fLvDoEbmuKJpbQwDNfNb7/99iODIDg1xnDW473fIe4YgNFJOy5XXXXVus9+c3NTOnmf/UW7tl9OWnzFXt81eTH6gmuZVYk7/y5b9vqg/HwqlUon7TsC7BF3AEDijsvChQsH3nzzzeuWFy26f1TSPlvgCwqaVg5IXnxr+7fNtybu/Lto0ZIRhcuTJ08+5ZxzzmmNKx5powS1soXAGcA/gQOix2qAo4q2WwKcC/y7fKFtkSviDqBYr1691s2//vqjI+DRq2IMZyOaa+CvCY4PYNb3446gWGvBT9bOO+98BvbdkvbOjabE2HbbbdfNL1q0oA8sSPhnP+nfzf9mbEqqRbsm7RguWNA2X1VVVQvMii2Y5KohYcdlwIAB7ZbfeuufHwU+Gk80nfHOnkn77Le3qnfS4nvjjfbLNTU1M+OJRIopQa18C4HDsDaoZwIHY1W7Q2AB8Dfgt9F8NTCt4LmLyxqpiIiIiIj0aEpQe4Y1wC+iKQUMBJqwar2FWkhgT76XXnqpb2xsXBN3HBuSTqerq6urUwC5XC4XhmHSqoikafu+h6z/3sfNAb0KlhP3fldXV/fC4gQ7fuEGNo+V975s728qlVrjvU/c+5WXSqWqqqur0wDe+7C1tTVpn/0U7TuwS+KxrCmYT+Jnv5q2PjVyQKLOv6lUKp1Op6sAqqqqknj+baelpcWX6aVyJPPzvk51dfW6z35ra+ta7325jk1nFX72W7FjmiSJvvZwzqWqqqqqC5YT/Xkkee9vl3HXXHPNui+bc270lClTno8zIBEREREREekZpk2btqf3/rn8snrxFRERERERkURQgioiIiIiIiKJoARVRCqZ2/gmIiLr6JwhIhIzJagiUomqgG8Ac9B5TrrGsLgDkK3uKOBRYP+4A5GKNAjoHXcQIt2BLtxEpBLtBnwXOBn4WryhSAUaDTwP3AD0jTkW2XouwcYMvwmojTkWqSwO+1w9jg39JyIboARVRCrRi8AXo/kfAofHGItUlhrgZiwx3QlYHW84shV9Cngb2A/4acyxSGX5CnAqsDM6Z4hslBJUEalUfwRuwcaJuwVVyZSt4yfAQcBC4CySNyaobL73gHOw9/TzwP/EGo1UijHAFdH8F4EnYoxFpFtQgioilew84FlgV2A2MCDecKSbm4JdYHrgM8A78YYjXeAO4AdYlcxpwPh4w5FubjgwHegF/B3433jDEekelKCKSCVbhl1gvoW1LbsVq6IpsqkmAr+L5r8LNMYYi3Sty4DrsNoXfwMOiTcc6aa2BW7DqvU+AXw63nBEug8lqCJS6V7DOktaCnwQK0ntF2tE0t0cg7U7TQN/AC6PNxzpYh74LDAT2AZLMo6ONSLpbvpin599gAVY+9NlsUYk0o0oQRWRnuApYBKwAktSb8PubotszAnYTY3eWKnpF+INR8okB5wN3A0MBP6JqvtK5wyi7abGMiADvBlrRCLdjBJUEekp/oMlp+9jvfreBewea0SSdGdiY+lugyWnZwCtsUYk5bQCq33RCPTBSsQ+GWtEknTDsN+WI4FFwIdQp0gim0wJqoj0JA9j1TVfBz4AzAc+EmtEkkQO+DY2bmF19Pd0NDxET7Qaq32Rb5P6R2z82z5xBiWJNBa4H9gXeAM4FvvNEZFNpARVRHqaZ4EjgHuB/lgnKFdivSyKbAsE2Pi5KeBq4FygJc6gJFY5rIOb70TznwDuAfaIMyhJlPOwz8QuwH+x6r3PxhqRSDemBFVEeqI3gXFYYgpwMVaaenhcAUkiHAM8AkzASs4+CXwZjXUq1nHS5Vib5HewsXAfB6ZiJavSM20L/Bn4PdZD/N+Bw7DO+URkMylBFZGeqhW4BPgwsBCr8nsv8Es0XmpPMwArKZ0LjABexG5WXB9fSJJQ/8Gqct6GdZx1KfBA9Jj0LBmsfelZtP2eTAaWxxmUSCVQgioiPd10YC9gGtb28EvAy8A3gNoY45Ku57COkJ4Bvhgt/wEYgzo2kY69iXWedAbWEc7BwENYc4FRMcYl5TEa6zgrCwwHngSOwmrk+BjjEqkYSlBFRGyM1M8BJwFPY9W2foy1Ifo0VnVLKsuJWHXev2A9b74UPXY+KgGRzmnAal78CUtMJmPnj98Au8UXlnSR7bCaFk9hzQBasKT0EOwGhYhsJUpQRUTa3AHsj5WMvIpdZF6LDbQ+FY2d2t05rOTrTuB2rORrGfAtrOfNO+MLTbqpd4H/AfbDEtZewOexGx4B1h5RurddgJ8Dr2A1LaqAGdh7fgmwJr7QRCqTElQRkfZC7EJzH+Cr2JA022NtzV7DEtYjYotONkcN1vPqo8A/gOOxi8qrsLFwrwCaY4tOKsEz2I2tcVj71BRQh7VPvRtLYvvGFJtsnoOAG7E26Rdh7999WA+9pwHPxReaSGVTgioiUtpq4BdYAnMO1mPnNliV3/uwqnwXY53qSDJ9AHsP38DGrjwAaMIS0z2xi873Y4tOKtF/sFL6A7Hxc1uwhOY64C2srfsHgXRcAcoGDcCaezyE9ex+NtZL8x3AKVhb03tji06kh1CCKiKyYS3YXfQDsWFIrgdWYiWsV2IdKj0CfDN6TOK1G/A14EGsrdhXgCFYSfglWHW9i7Bq2yJd5XGs1H5X7HP3PDbu8meBfwFvY8nqyagztrj1wXpz/wt2E+EPWLvSNdgQMgcDHwL+GVeAIj1NVdwBiIh0I/dE0xex6nwfw6r0jYmmH2FtV+dE039QhztdzWE3D8Zj1e4Kh/tYi7UDvBardqnxTKXc3sZuZP0Eu8H1cexzuh2WrH4WWIW1f56NtY1+MZZIe5btsZsDGeBU2le/fgo7Z9yEaliIxEIJqojIpmsC/i+ahgCTsDvw47ASvPOjKYcNV3I3bcnt22WPtvLshF3sn4glpkML1uWw8Uz/H/B34L1yBydSggfuiqYLsHPFR7B2qjtFf+uibd+m/TnjCexzLZuvD9Zh1TjsnDGG9rUIX8bOGQ1YjRgRiZESVBGRLbMIu9t+LXYRNA67ADoJa+d4UDR9Mdr+Jeyi827gYaxzldayRty9OKzq9NHRdAxWbbLQCqyN2Gysd00lpZJkOaya77+wG1n7Y+0bxwOHYzdczogmsFoY92FtH+/D2kYuLW/I3c4QrL3oMdHfMVhb0jwPzMM6TZsezYtIQihBFRHZelZhSdLsaHkH4FDsAulorF3T7tF0brRNC/ACdoGUn+ZH++qJdqAtqT8cO3aDi7ZpxY7T3dgF5t1YdV6R7uiJaPoJdl12AHa+OArrUGkwlsCeUvCct2l/zniEnls7owYb8uVgrIr/UcDe2M2tQguwc8UdWBOMhWWMUUQ2gRJUEZGusxBrAxlEy/2AI2lLWA8CBmIlhPtgnaqAJWDPYsOiPIl1uPIElXdBNYy29rv7YL3ulupoaiXwGFbyfC9WTXJZmWIUKaf8zZd5wNVYNdR9gWOx88ahwEislLWwWjBYBz+PYueK/DnjBSqrhsY2WJvz/PliDJaU1pTY9mXsfHEPlpS+XKYYRWQLKUEVESmfJqwnyMLeIEdid/4PKvi7A1YisF/R89+l7cIzPz2NlcImWW/sYvIA7H/aP5rftsS2OazH00exUqF7ovlKusgW6ayQtu/6b6LHBtJWyyB/3hiN3fAZBkwoeH4zdo7I7+NJ7GZP0jv/cdgQXvsXTAdg58tSI1C8i50n5gP3Y4np4rJEKiJbnRJUEZF4vUxbBx15w7CLzvxF2f7AHljPkx+Kpry12AXoY9H0KJbExtV78DDsovkA2sdeatzHfOzzsbjzsa8sS6Qi3dNS4N/RlNcH+64dSNv3bl9saJt8LYVCC2h/zngM64E8DvnYD8Di3x+7kdWvg+0X0Ha+yJ873uj6MEWkXJSgiogkz1vR1FjwWL4UMl+asB92MbctbSUpeR5Leh/FBpy/D6sy2LwVY0xhnUAdGE0HRX+372D7hbRVPXwymn8GtR0V2RpWAQ9EU15hKWRhzYXdsfGAdwHqC7ZfgiWq87ESyPuBd7ZynENoO1/lzx17UvoGVnHpb/78kfTSXxHZQkpQRUS6h9VYldfiIRDy7TgL22TtTVtnTB+JtmvFLu7uxZLVu9i0EpPtgCOwdnBHYheYfUtsl28/+xjt28JVWvtZ6YSJEyfuAwxLpVJPTJ8+/d244ylWV1c3Lp1OV82cOfOOuGPpAvkbVS9jvVvnbYNVCc6fL8ZgNTYGAcdH01ejbd+mre33POyGV2dvKvWK9ps/bxyGDalTylvYOeNxKrf9rIh0khJUEZHuLV/aGhQ8Noi2UoojsIRyKOtX9XsF69XydqwTkcLSkpG09SR6NKV7xVwBPIeVhKoHYllPLpf7qnPuU7lcbjLtq7EngnNuRhiGA7AaAT7ueMpkBW3f1xuix6qxm1wHYh0xHYmVug4FJkcTWDv6B7Ahcu7AammE0boBWE/l+fPGUVjNj2LqgVhENkgJqohI5VkC3BlNebthF4z5hHV/rPrfCOAc7OL8Laz951DWb/8VYtXt8mMxPoiVcISIJFB9ff3F3vsrvfdTGxsbL4s7noRroa308k/RY/1oGybriGgaQPt28MuxG1t9geEl9vsubZ0W3Y+Vkq7okv9ARCqGElQRkZ7h1Wj6c7TcH/gkcCZWalJD+wvMfML6b+AvWFKqoV1kk4Rh+H3n3O9I6BAfuVxunHMuTc8pPd0UTVhJ6b+i5RQ2LutnsWrA22Hnkf4Fz1mB1aL4K3Ab8GK5ghWRyqEEVUSk53BY9buPA5Ow4Wzy1mIXky1Y9d5+WMJ6NnZRejNwI1bCItIps2fPfg14Le44OjJ79uzH4o6hGxgOnAWcgTURKKzq/wZWSrodsDPWvvVY4HDgH9g5o5Gt20GbiFQ4JagiIpVvD6wa79lYVd+8xdjF40xsbNb88C7VwHHAaVjbs2FYpylfxdqM/Qa4hW520Tlx4sR9wjC8ELuA3h7rDfQVYGZra+v1c+bMWVOwuauvr/+o9/6TWPvbKu/9K865W1pbW6cVbUtdXd2hzrmvOefu8t7/EbgEuwmwHfAS8LMgCGYATJgwYe90Ov1t7/3hQB/n3APe+28FQfDfwn3W19eP9t7/wHv/xLBhw658++23LwI+ilXBft17/5vGxsYbACZNmrRba2vrt5xzx2LVMB8Lw/A7s2bNmle4zwkTJuybSqW+BzwUBMHPio9RJpM5GLjEOXdvNpu9uuDxk4DPOOeyNTU1M1avXv0t51wmOo4LvPfXNzY2/o6iksj6+vrzvffHA78IgqCwh9n8+uO9958FxmLje74LPOW9/2tjY+P0/Hbjx4/fqaqq6jSsaulI7ObK+8DD3vtfNzY2PlS03997748EcM5NzmQyH8ivc841ZLPZhuj/uh7oEwTBR0vEvkMYhhc558YDO2LVWR/03l9d/HrR9lO99/uk0+lvhmHY13v/LSxRqwYe9d5f3tjYeH/x8xKqL9bB2iew0tL82KM5rLruDOy8UVgyPgr7zH8Uez/ro2kx8H/A77Hvm4jIBpUa7FhERLq/FDAemIN1ZPQdLDldClwLnIBd5J8L3Er7sUdbsA5QPo+VntQDf8MS0jHAddhYhJfTvhQ2sTKZzGfCMHwcOB/rROoJrGfkY4E/1NTUDM1vO3Xq1FQmk7nJe38zdpzecs696Jw7GPhVVVXVv8ePH9+/6CWGA5O998di1aK/iZU0rcba8N2ayWTOzGQyR6dSqQe99xnn3FKg1nt/GnB3fX39sMIdOucGA5Odc8e//fbbWex493bOLQfGOuf+VF9f/6UJEybsm8vlHnbOnYV1UJUGTkmlUnMnTJiwd9E+d4j2eWSp4+ScGxr9H4cVrRoVPX5Mc3Pzfc65r0f/3zLgYOfcb+rr668s3l8YhmOj5xX33urq6up+7b2/E6tmHnrvH8c+t6c756YVblxVVfV14FdYDYA1WHvoPsDZzrl7M5nMmYXbe+/3o63H2HxP1/mp8DhPoq0DoHUmTpy4n/f+CefcxVhy+iT2vTjLOXd/XV3decXP8d4fB0xubW093Xv/ADDeObcIS1AnOOf+PXHixJLHPUFGAD8FXgeuxz7/AP/BqvbuiN28uor1q22/CPwM6yhpH+BHWOn5tsDXsTbrM6Lni4h0SAmqiEhl6QWcB/wXmA2cgpUMNWJV9IZiF5p30rkhHFqwHoI/il2cfhlry7od8C3sAvQa2l/0J0p9ff2xwB+wJOhTQRDsFATBiUEQHNzU1DTEe3+uc64pv/28efMuxKo0vgUcEATB4dls9tjq6uqRzrl5wBHpdPqqDl7udMCnUqmRQRDsFwTBSOfcFwDnnPsJcJNz7g9NTU2Ds9ns2Nra2uHOuX8CQ7z3X+tgn8cBuzjnPhAEwd7ZbHa0c+6jAN77y1Kp1M3AzNra2u2CIDh46NChw7Eq2dukUqnvbPkRbOdTwJtVVVU7BkGwbxAEezrn6rFje1Fxkt2RTCbzJefchcC7zrnjgiDYq7Gx8UNBEOxTVVU11Dn37aKn3OW9PzEIgsFBEIwJgmBcEAS7Ouc+gSXKfyi8aRAEwdHOuSsBvPdXB0Gwe34qLBkuZcqUKdVhGDZgpcPXtra27hwEwQlBEOztnDsTCJ1zv45Km9fjnPuR9/47Y8aMGZTNZsc2NTUNw24K1YRheHlnjk8MDsWSxxeBr2E3cV4Avo0lreOw/2FRJ/f3bPTckVipd0P0+ERgLjZ0TWarRC4iFUcJqohIZeiFVeN9FqtKtwdWJXEaNt5hBrtI3JJqucuAq7HStNOwjpNqgCnYhe0vsGqaieK9vwwrVby0sbHxOgqqcs6dO7e5sbHxhunTp78PVnoalQ7ivT8vCIKn89veeuutbwMfA3LOuXM6SMZawzA8a+bMma/nH8hms78FXvXe7+ScW5DNZi+eO3duK0BDQ8Nq59yl0aYdla6lnHPnZrPZ5wr22YCNSTkASDc1NZ3X0NCwGmDatGkt6XT6WxvZ5+ZaWVVVdW7+eEWxzMJuYqS994dubAfjxo2rxUr0SaVSH89ms3cVrp8+ffr72Wy2XQlqEAR/b2xs/Bftq+H6bDZ7U1Slun9VVdUpm/9vtXnrrbcmYuOEPjd06NALCqtzZ7PZW7Aq7lVYIldKY2Nj4y+mTp0aAsydO7c1nU5/HfvuHc76wzXF6XDsvXsASx4dVnviDKxq+4+w2hKbKyzY3z7A77DjcBSQxcZjPnwL9i8iFUgJqohI9+awTo9ewoaHGIlVz7sQKy39HFaaujXlsNKWo4BjsNLY3sBXoji+hCWEsZs8efIALEbCMLxmY9s//PDDo6PqqEvGjh07q3h9Npt9ERsuoyqq0lls/qxZs4qrPnrsxgHe+1uLn+C9fyaa3aWDsF7JZrOPlHg8/7xsPuHNmzFjxqtYdd/hkydP3prvxdzp06e/W+LxJ6K/u21sB/379z8CGAy8OHPmzDs25cXHjRtXW19fP6q+vv7YiRMnnjhx4sQTnXPNAM65fTZlXx1xzp0Yzf512rRpLcXrwzC8KZo9oXhd5G/FD8yYMWMpVtug9vTTT99xa8S5hfbEalXcD9RhtSn+COxFW4lnbiu/5vNYs4FdgSux6u/HYDe6/oZ1siQiogRVRKQbOwgrgbgJa2+3AKuCuyfwWyxB6Wr3YBfqJwFPYe3NfomNk1qyCmQ5rVy5cgSWLL87a9asJRvbPpVK7RbNvpovASvhpejviOIV3vuOeqxd2tH6bDbbhCUDgzp4bskSLO/9MgDn3IZesxrrWXVr6aiTmyVRLBstQffe7x7NPt/ZFz355JO3zWQyf+zXr99i7/0L3vv/hGF4exiGtwNfiPZb3C54szjndov+lhwap0+fPvmhU7afPHlyqWO7wWOUy+U6ep/LoS8wFbuhMAGrwn8jVsvi02zCe7IF3sU6Edsd6zzJY+2An8LOX7o2FenhdBIQEel+emNVbR/BOo1ZgV3w7RE9HkfvurdjCfPnsHZqY7Ak9cdYkhSLdDpdCxB1SLRR3vvaaHZDY77m19UWr3DOrVfiVqQz7X6Lldync84DhGG4OfvcLJ34/zqzj/xx69R7Mnny5HSvXr3mYOP2PoGV0E9yzh0XhuFY59wP87vehyroNQAAIABJREFU0tgAvPc1AGEYLu9gkxVEpYvNzc2lPgNlez82UR3WrvRSrGp+I1bt9pzo8XJ7G/gM1qnSvdh4qlcBd2PJq4j0UEpQRUS6l0OA+cAXsXN4I1b6cSU2lmmcWrE2r/tgVfaqgG9gPYCOiiMg7/370d9dpk6d2pnfvHwpa3Gvs+s45/JVERdvYXhll0+evPcd3TTo8tK9/HuCVfXcqObm5uOwTnzmDx069JggCH4VBMHMbDZ7VzSMzlatiuqcy5cGl/wMrF27dhhWKp9ramrqVJIdsz7YjassVu3/BSxZzWBtx+M2H6vqOwVowtpNz8MSZxHpgZSgioh0Dw7rWOY+rJ3Ym8DJ2EXmlnRi0hXew3r9PQNL4o7ALjjryh3I2LFjX8JKdGvnz5+/0SrH0VAnIbDraaedNrh4/dSpU1Pe+zHR4qNbNdgycM69Gc121Nvu/l0dQxiGD+Zfq4Mqsu147/eMZu8q1Sa04P0ofjzfNnWTSvC9949FsyU/L977Q6L9Plnc9jeBDsWGyPkiVpX2p8B+wHrtq2Pmgf/FPn//wTr/+hPWQ3hsNTBEJB5KUEVEkq8v1mnJD7BSyQbgAOC2OIPqhHycd2PV96Zj1TPLZurUqWHUyyve+5+NHz++poPtUgBRO9V/ANUtLS3fLd5u/vz5n8E6M1rQ1NR0b9dF3jVaWlpex0raD5g0aVK7apTjx4/fyXu/3vieW1vUidSdQL/Vq1dfUWqbwtLuVCr1VjS7XidI0RBC40vtwzn3RvR3t02JL5fL3YIlTB8rHkd23Lhxtd77bwOEYfiXTdlvDD6KDekyEuug6QTgYmwc2aR6FfggNkRNDitV/QfWqZaI9BBVcQcgIiIbtAswEzgQa1t6Hlay0F28AZyIddr0GawDpb2BC7CSyi6XSqV+6L3PAMdVVVXdV19ff1XUc+5AYF/n3Ccfe+yx07CLY1Kp1NfDMBznnPtSJpPZJgzDP1VVVa0NwzDjvb8YS16+1A1Kz9YzZ86cNZlM5m/A2blc7h/19fWXee/fwkquvoKVxn+gq+Nwzl3gvX/QOXdhJpPZ1Xv/v1Hp7g7AIfPmzZtEVILZ0tJyf1VV1SrgpEwm81vv/U2pVKrZe39ylCy+iA0L005ra+u8dDqd895PrqurW+Wcy3dudW8QBPd0FNvs2bOfz2QyVwNfTqVSd9bV1X3POTfPOTfUe//NKK5ne/fu/Zute1S2mhRwOVa93mE9bp+DVZ/tDkJseJvHgb9gCeuDWI2RlzbwPBGpECpBFRFJrg9gF2YHAu8Ax9O9ktO8tcBnsQ6UWqK/f6ZMN0mz2WxTa2vrcd77LHCw9/5GrMrxv4CrvffDwzBcnd9+5syZzzjnTgJeBj6dSqXuCsPwAaxUZznw8SAIZpQj9i7yFayDrVHRsfgX1jnNv4nGJ+1q2Wz2uVQqdQzW/jDjnMti78ls4LLCbefMmfOe9/5srHOiC5xz93nv5wNXOOf+BPys1GvMnj37Ne/9Z4ElzrnPYh12/bhgGJkO1dbWfs0591NgsHNuGjDPe9+IDa10Z3V19Qn5cWcTphq4Ges0DSxR/TDdJzktNAtrc/8c1mnSPZQoRReRyqMSVBGRZNofG+B+O+AxrK3pG7FGtOWmAW8B/w/4GFa6czale7b9OZYQbpUeiefMmfMeMPHUU0/ds6qq6mjv/XbAIu/9SytWrLinuDQ0m83eO2XKlL0WLlx4XBiG+2Cd4rxSW1t7R0NDw4ri/VdVVf27paVlbHV19fvF6yLfDsPw5wVDlBQ7NN8rb16vXr2eWLVq1VjnXMneZFOp1C9aW1tvSqVSJYeZcc6Nz+Vy1Vhit04QBIsmT558+KpVq050zn3AOdecSqXunjlz5pOTJ08esGrVqrGpVKpdB1Ctra0NqVTqwTAMF3bwWn/J5XJ3pdPptwsfD8Pw+86532HJfjszZ858EhibyWTGOufGhmG4DbDQOfdUEATzC7dtbGycnslkRgDHASOcc4tzudzcWbNmvZzJZIaEYfhoVVXVeuOzNjY2XgdcN2nSpIEtLS07ATWFMeZyuXHOuTRWKr5OQ0NDDrj49NNPv6q1tfUEYFgYhstTqdSD2Wy2ZNvjXC73Oedcv1Qq9Wyp9cAnwzDs29TUVHL4mq2gF3ALcBpWjfd/ouXu7HngWKyX8P2xquEnAE+X2PYUrHfimWWLTkS6hLvmmmvWnZSdc6OnTJlSjjGwRER6uv2AHwITS6w7CGtfOgQrVTqJbthj7AZMAv6KXVDfCJxL+wThbKykeB+s9EREzJ3Ap4iqoxfohX2nJmHJ6WQgKGtkXWsIdsPuAKw2yZG0H292EFbVeyZ2fESkG5k2bdqe3vt1v/eq4isiEo/RwKlYclZoFFZaMAS4HystqKTkFKxN3Iexqr+fAAo7IzoWq266gk4OQyLSg4zBOh8rrAHngJuw5HQV1lt2JSWnYD1xfxDrOXtH7P8bEK3bBqumPgCNnypSEZSgiojEYzR2kfkz7MISrBSgEeuxMt8pyLJYout6jVhbVICpWKnp14G/Y8n5NsBucQQmklD9gNVYJ2PTsVJTsN69J2Mlp3VYSWMlWozd1Hsda5//VyxhfxTYF6uGPzy26ERkq1EbVBGReOSHrxgCXAvUY8NBjMaGhJhI9+zYpDO2BXoD/8Sq+H4CuAG7+O4TbZOiDL3JinQju2KlpX2xmhVPYN+bb0XrP4t1dFWJqrAezZcCX8Da1p6M1bjoXbBdbflDE5GtTQmqiEg8RhXMD8aq+qawsf9uBcZhJSSPAU+WO7gudj5W6vMuVurhsQvvPkXb7VnmuESSbFfakrHe2M2sH2LfnYejv2dg36eGOALsQrtgCXkr1nFaOnq8d9F2VViSulU6VxOReChBFRGJx/ZFy/kmF2lsGJC12HiAx5UzqDK5HLuI/DxWrbkju5QnHJFuYSRW9b2Qi/4eAvwRO2dcS+UlqC8Dh2G1LjZWjXdn4IUuj0hEuozaoIqIxGNjVdEWA4cDD5Uhljh8FytFXbqBbfqVKRaR7mBf2hLSUlZgQzldUJ5wyu5p4BisCUTYwTa1qHM1kW5PCaqISPltQ8fnX491AnIM8HjZIorHVVhHSYs6WN+Ltqp8Ij3dHhtYtxi4FLiwTLHE5RXsxt1LlB4/uR8woqwRichWpwRVRKT88p2dFAuxqmxHYGP69QR/A84C3utg/dAyxiKSZDt18Pj7wJeAq8sYS5zeAQ4FnsGaQhRKYeMni0g3pgRVRKT8Cjs7yWsB/ou1s3qz7BHF63ZseIyFRY/XoHaoInnFnYiB3dj5H2wc1J5kKXYj7xGs9+9Co8sfjohsTUpQRUTKb3fad3ayGuut9zCsNKQnegj4IPBGwWP9UXsyEbDq7r2KHnsXOB0bU7gnWgUcD8ylfa+9o0puLSLdhhJUEZHyO4i2Kr5rsAuso7BOTnqyZ7C2t29Fy6quJ2J2ov1NrXeADwH3xBNOYqwFJgA3Y0N0wfo9HYtIN6MEVUSk/PKlgi3YmKd10bzAq8DB2DAROWCvWKMRSYZdaWtv+S5wNDYuqFjHcp8CfgoswYZQVOdqIt2YElQRkfLbGVgG/BbrIKijIRN6qoVYJyj/RVV8RcC+B9tgN272x3qxlfa+iSWpQ1DnaiLdWlXcAYiI9EADgB9Hk5S2FEtSPxR3ICIJsAfwLFZyuizmWJLsCuBJdIxEujUlqCIi5XcYVpVVNmwVMDPuIEQS4NfAD2jfGZCU1lM7jRKpGEpQRUTK79W4AxCRbuWduAMQESkXJaiSeN5719jY+ELccWzIFVdcscMLL7xQA7B69erlK1asWBp3TEX6AwOj+bUk72KnBtihYPl1rOOLxBgyZMjOzjkHcP755793yCGHFI+9lyQ3ZjKZy8rxQtls9u/Ouf3L8Vqb469//evA2267bQBAS0tL85IlS4rHWo1bLe0/+6/FFcgGFLYDXkjySvF2wI4jWNXORJ1/+/btO6Bv374DAXbZZZc1l156adLOv+2sXr36oDPOOKPLexQPguAE4A9d/Tqba82aNe6CCy5YNw7z0qVL31m7du2aOGMqYUfs9xPsc5+0qs0DsSYtYOeNRJ1/a2pqagcMGLDu/Hvttde+Fv3MJ9UnM5lMj+i5WwmqJN5ll13mxowZs3vccWxIU1MT7733Xn5xcDQlVTU2DmeSjYw7gGKLFi1aN5/L5YbFGEpnbFfG19qFBI872NzczLvvvptfrAb6xRhOZyT2WEZ2ijuAjRgSTYmxcuVKVq5cCUD//v2rSfh7PGjQoLL0gOu938Y5l9hj4b0vPHeAdW6XZNtR3nP/pkrc+XfNmjXt3mPv/agkJ6jOub5xx1Au6sVXREREREREEkElqNId/cI591zcQRRqaWm5CugDsMMOe725cOF2N8QcUpF5H4NVI2y+Zi0c+vN44yn2ygHwxqlty4f9CnqtjC+e9VVVPfDN1lYbqnTBgpX39+8/eG68EbU3YsTSD/fundszzhiWLq35z5tv9rk/zhiKLVmy+hPAcIBBg4Y1L1ky8pcxh1TkxcPgnePblo9OYM/O91zSNr/bv2GnB+OLpZT7vgxhVMV30FvwgUSdf3fccelH33nnqREAuVzY8vTTgxJ1/u3fv2XozjuvODfeKFzL008PTNRxaW5e2hf4Qn55yJDD5yxaVPV4jCGVcN9FEPay+cGvwt63xBrOeuadDaujWhe1a2DsVfHG097226895N13Hzohv9za2vr56urqXJwxFXPO/R5IbrFuF1GCKt2O935WJpO5M+44Co0aNepKogR1yJCR7y9cOGtGzCEVGXxCW4JalYO7Ehbf8WH7BPV7c+DUxfHFs75Uqvc3wRLUV19d9fyNNx6RqGN40023HxV3grp4cc3Tl1xy1PQ4Yyh22GFrJhAlqH37DmpZsuTuRMUHY7Zpn6AmLT4AV5Cg7vE03JawGKsvaEtQ+y1O2jHcbrsPjytIUHNJ+4586lPP7BN3guo9iTsuO+10/7YUJKjDhp0yf9GiS7MxhlRC1Zfa5ge+l7TPPgwa35ag9mpJWnzDhl1SW5ig3nLLLdc2NDSsjTOmYkEQ/I4emKCqiq+IiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEZSgioiIiIiISCIoQRUREREREZFE0DAzItAX2ANIA6uBZ+INR0REREQSLAWMBsYCY4C9sOvIZ4AvbeB50glKUKWnupC2k8re2EkF4Elg/7iCEhEREZFE6wMsBLYpsa5vmWOpSEpQpaf6ddwBiIiIiEi3k6ItOV0AzAP2wUpUZStQG1TpqZ4ArsNKUo8Abo43HBERERHpBtYApwI7ALsCpwOPxxpRhVEJamX6GtamEqABuKMTzzkXODKa/w/wly6IK0kOKFr+bCxRiIiIiEh30gLMiTuISqYEtTJlgGOj+efoXIJ6HPDJaL6Vyk9QRUREREQkYVTFV0RERERERBJBCaqIiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEdSLr1SSbwGf7mDdPti4VSIiIiIiklBKUKWSbAuM7GCdK2cgIiIiIiKy6ZSgSiW5AvhdB+tUeioiIiIiknBKUKWSvB9NIiIiIiLSDamTJMlLxx2AiIiIiIj0bCpBrUytBfPVnXzOtl0RSIL1BXoVLNdEf9PAoILHc8DycgUlIiIiIol3AXBAwfLY6O9I4JqCxxcAl5crqEqhBLUyFSZUnU089+uKQBJsGnBWicf3ARYXLD8PjC5LRCIiIiLSHZwM1Jd4fAdgSsHyfJSgbjIlqJXp9YL5gzqx/eHArl0Ui4iIiIhIJbkBuK8T2y3s6kAqkRLUyvRIwfw4YGfaJ62FqoCfd3VACfTxaBIRERER2RR/jzuASqZOkipTI9AczVcDf8LaXBbbFmgAjgR8eUITEREREREpTSWolWkx8HvgK9Hy8cB/gb8ALwK1WMPuDwMDgeeAZ4DTyh6piIiIiIhIRAlq5foucBhWOgqwE3Bxie1eATLAN8sUl4iIiIiISEmq4lu5VgInAT8DVnew/lrgYOAFYBWwJJpWlSlGERERERGRdVSCWtlWAl8HvoeVpA4HHNZh0iO0H47mwmgSERERERGJhRLUnmE18K+4gxAREREREdkQVfEVERERERGRRFCCKiIiIiIiIomgBFVEREREREQSQW1Qpdtxzn0zCIJPxR1HoW984xt98vOvvz5/Zxh+WZzxrK9p97b5Nb2SF9/Kndovf/rrkFobTyyltba2rJvff/+Bx3z603fsEGM46+nTp2WvuGMYOnTliddff8fIuOMo1NDQd+f8/OLFb9Qm77O/fET75aTFV+yRD8HwUXFH0V6ud9v8op2Sdgxfe82vO15VVenq66+/I1HxVVfnBsQdA/heSTsuq1ev6HX++W3LL730fxNh2pj4Iiol7NU2/87IpH32YcUubfOrE3f+ffHF1G6Fy2efffb155xzThhTOB1xcQcQByWo0h2dGHcAxdLp9Lr55cvfGQScEl80G9OahrcSHB/AOx+MO4JiYcFP1sCB1SMHD25OVCKWBL175/bs3Tu3Z9xxFOrdu3rd/KpVy6phWcI/+0n/bi4ZbVNSrRoIqxJ1DJcX9JefSrn04MHNiYovCZwjlbTj0tzc2m555crX9wX2jSeazlg5GFYm6hi211KVtPPbihXrPXRmDGFICariKyIiIiIiIomgElRJvEsvvdQ3NjZeF3ccG7LLLrvsV1VVNQDg/ffff33BggWvxR1TkZ2BXaP5JuDxGGMppR9wQMHy/UAuplhKOuCAA45IpVJpgJqammeB92MOaUPuL9cLpVKprPf+yXK93qYaNGjQbgcddNBOAKtWrVr63HPPPRV3TEUG0r5U5p64AtmAowvmnwKWxhVIB/bFjiPAG8Cr8YWyvuHDh++0/fbb7waw/fbbrwAeizeiDVuyZElZmlek0+nXwjBM8m97+qCDDjoiv/Diiy8+3tTU1BRnQCUcgP1+AryGjXOfJLti1x8Ay4BE/VYMHDhwwIgRI/bLL6dSqSSef9cJw/CNuGMoF3fNNdf4dQvOjZ4yZcrzcQYkIiIiIiIiPcO0adP29N4/l19WFV8RERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKCKiIiIiIhIIihBFRERERERkURQgioiIiIiIiKJoARVREREREREEkEJqoiIiIiIiCSCElQRERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKCKyJb4CfAI8JG4AxGRLrMf9j2fEXcgItKtjMHOHQ1xByLdS1XcAYhIt7Yr9gO0Y9yBiEiX6Y19zwfHHYiIdCt9sHPHNnEHIt2LSlBFZEvkor/pWKMQka7UGv3VTW0R2RQ6d8hmUYIqIlsin6Dqx0ekculGlIhsDp07ZLMoQRWRLZG/O6ofH5HKpRtRIrI5dO6QzaIEVUS2hO6OilQ+3YgSkc2hc4dsFiWoIrIl1L5EpPLpRpSIbA6dO2SzKEEVkS2hHx+RyqcbUSKyOXTukM2iBFVEtoSq74hUPt2IEpHNoXOHbBYlqCKyJdQBgkjlUymIiGwOnTtksyhBFZEtobujIpVP33MR2Rw6d8hmUYIqIltCd0dFKl/+ItOh6wYR6TzVspLNoh8aEdkSujsqUvlaC+b1XReRzlI/FbJZlKCKyJbQj49I5csVzKskREQ6S7UvZLPoh0ZEtoSq74hUPpWgSrdXV1d3aDqd7h+G4X1BEKyKO54eovjcEcYViHQvupshIltCVXxFKp9KUKXbS6VSvwvD8Hbv/fC4Y+lBdO6QzaIPi4hsCXWSJFL5VIIqW0UmkxkCvAe8GgTBiK213/r6+tO99393zt2QzWbP3Vr7lS2mc4dsFl1UisiWUAmqSOULAY+1I9N3XbqlXC73CaBPGIYL4o6lByksQdW5QzpNCaqIbAklqCI9Qw67ZtB1g3RLs2bNejbuGHogVfGVzaIPi4hsCVXxFekZ8gmqbkZtwNSpU1OPPPLIZOfc2cD+QG/gHeAR59yN2Wz234Xbn3zyydv26tXrIqAOGA6sBh4GfhsEwZ3F+89kMl8DDvXeX55Op8MwDL8DHAHgvb+3qqrqOzNmzHgJoK6u7uPOufOAPYAVwP9ramqaOnfu3OaifX4GOMk595tcLvdeKpX6DnAUUAM84b3/SWNj479KxPJnwAVBcFapY5HJZP7mnFudr3KbyWTO8N5/3DkHsF0mk/lbweaLgiC4INpuiPf+NOfcKcBoYAdgJfCY935aY2Pj7MLXqa+vnxqG4Yecc3jvjyva791BEPw62u+PgZHV1dVfuvXWW98u3Mf48eP7V1dXf8l7PwnY2Tm3xnv/mHPuD9lsdlbx/1ZXV3eec+6DqVTqly0tLW+m0+mpwHHANs65/3rvfx4EwcxSx6WHyaHaF7IZ1EmSiGwJlaCK9Ay6GbURkydP7j1v3rzAOXcLcCqwCHjSOVcDnOO9/37h9pMmTdq9V69ejwLfBnYGnnDOvQ+cDvwrk8l8u8TLHAFMBiaFYfggcBLwNpYYfSyXy91dX1+/QyaT+YVz7iYs6X0r2v83+vfvf2OJfR4U7XNiKpV6GDgeeNo59w6WuN6eyWQ+XeJ5pwMf3tAhiRK+vGHOuQOi+RpgTMG0X8F2ZznnpgEnYp+7J5xza4CJzrlZxcfFe7+nc273aHFw0X7XtXN1zp0ITF67du02hc+vq6sbXl1d/XD0/uwOPAUsBCZ47xszmczPiv8x59zY6P87KZ1OzwcmO+cWA6u998cA0zOZTMnEvQdSb/+yyZSgisiW0EWrSM+gm1Eb0dzc/EssMX3aObdPEARjgiA4IZvNjvbe7wr8rmBzl8vlbgZ2Af4K7Bxte5BzbjxWkvqDurq6E0q9lnPuu8BlY8aMGRwEwWFr1qzZGfgXMNR7Px04BzghCIKRQRAcHIbhGGCp9/4jEyZMGFNqn977LwMNtbW1uwVBMCGbzR4EfAR7739TX18/akuOTxAEvwTGRotvBEGwe8F0TMH/9qRzbmJTU9PgIAgOLDiGxwPLgO+feuqpexbs9yzn3AXRc28t2u9FnQjteu/9nsDs1tbWXYIg+GA2mx0LHAssB76ayWRKJuLe++8Af2ptbR2czWbHBkGwK/BNrMTwx1OnTtV1ts4dshn0xRGRLaEfHpGeQaUgG5DJZEYAnwbWAJlsNvtc4frGxsY3gyC4uWD744FDgDeBTxWOy5nNZv8B/ApwzrmLO3jJ/wRBcOXUqVNDgNtuu21lGIaXReuOcM59q7CK8KxZs54CbgRIp9NHdLDPpWvWrLmwoaFhbf6BIAj+7r3/A1Drvf98Jw7FFstms//OZrPZuXPnFvYAS2Nj41zv/eVAKp1Of2RrvFYmkzk4KlldEobh2XPmzFmeXxcEwT3AFdHiNzrYxRO1tbVfnzNnzpr8A7W1tT8FXgN2fvjhh0dvjTi7OZ07ZJMpQRWRLaEfHpGeIZ8s6GZUCVF7yTRwexAEr3TiKSdEz5tRmJzmhWE4LZo9dvLkyb1KPP/vxQ+kUql1nQB5728tXu+9fyaa3aWDmG657bbbVpbY7y2FMZfL5MmTe02YMGHkhAkTjpk4ceKJEydOPNE5lwZwzu2zNV4jSk5xzs2eNWvWkuL1YRheE82OnTRp0sDi9d77WxsaGgo7AiJafgoglUrtvDXi7OZ07pBNpgRVRLaEfnhEegbVltgA7/3uAM655zv5lN0AwjB8udTKQw455FVgLVC7cuXKocXrnXOvFT/W1NS0NJpdGQTBohLPWRa95nqJVrS+ZCxAPuHeauOWbsi4ceNqM5nML5qbm99LpVIvpVKpu8IwvD0Mw9uJSjS99/23xmtFVa/x3pf836Ok9T3ArV27drfi9alU6tUOdr0EwDlXuzXi7OZ07pBNpgRVRLaEfnhEega1N9+AgkRk6QY3bFMTPW95qZVR1d0VhdsWyuVyrcWPFdjQug1pKvVgTU1NPsayJFv9+vW7AfgK8Ib3/mJgknPuuDAMxwLnRZu5rfRyNQDe+5L/e2Q5QHV19XrvA5t/rHsSnTtkk+nDIiJbQj88Ij2DbkZt2CKAMAx36+T2+RK2nUqtPOmkk/oC2wKk0+nFWyG+jfLeDy/1eHNzcz7G94tWtQK9p06dmsq3hc2bMGHCoM2JYdKkSbvlcrnJwFu1tbVHNjQ0LCtcn8lktkrV3gL5ar0l/3csER4OkMvlyvI+VCCdO2STqQRVRLaEfnhEegbdjNoA7/2DAM65I+hc6d6j0fNK9qjbq1ev46LZ10tV1+0K3vsjO1h1VPT30aLH3wTSDz300PbFTygYTqad2tra/BispdrV4r3P9xQ8rzg5jdaXPF5hGDZHf0vudwMejeIdW2plXV3d4VjJ8bKxY8e+tIn7FqNzh2wyJagisiX0wyPSM+hm1AYMHTr0DuBVYO9MJvOFUtsUDjninPs71uPv+Lq6una96o4bN67KOfedaPHPXRPx+pxzJ2YymcOLYqkFvhqtv6XoKS8BpFKpdkOwTJkypdo5dxklNDQ0rMCGihlSX1/fr8Qmb0V/9xo3bly735VTTz11T+dcqfFYSaVSb0Qxjiy1viOtra2NWNXmo+rr608pXDd16tSUc+570eItxaXE0mk6d8gm00WliGwJ/fCI9AzqsXsDpk2b1pLJZD4N/AP4ZSaTOdA59zfv/ftYFdHj5s2bNwrIAGSz2YWZTOYHwA+dc7Pq6+svC8PwfmCIc+4i4AhgQTqdvrKM/8ZLQLa+vv47wAPAMO/9t4G9gUeWL1/eLll2zt3ovT/VOffT+vr6/mEYPgTs8vbbb1/Ahtur3g+c4r2fU1dXd7tzrtk5tzybzf5+2bJlz/fr128BsEe/fv0a6uvrf9Xa2roklUodFSWLbwB7Fe9w+fLlz/fr128xcGhdXd12xFpHAAAVo0lEQVTNzrmnsBuoTwdB0NhRIHPmzFmeyWQuAX7rvW/IZDI/TKVSc8MwHDBv3rwLgVOAd3O53NROH0UppnOHbDKVoIrIltAPj0jPoB67NyIad/QU4GXgk977OcBDwHTgy0Sd7RRs/yPg29gYo790zj3onJuFDedyfzqdPm7GjBmd7XRpa7gCuMN7f433/vEo/qO99/c55+qKxyXNZrO3AL+O4v+Rc+4O59wfnXNVuVyurqMXCcPw8865u4EjnXNTgR977y8BmDt3bmsqlToDWAhM8t7fmU6nH3XO/Qa42zn3lVL7nDt3brNz7mPAi9HfHwI/Bj66sX86CILfAV+MFn8chuEDwD+xmwmPhmE4bvbs2e9sbD/SIZ07ZJMpQRWRTVGciHb0w7N9iW1FpPso/v6Wqi2RAnYsTzjdQxAEdzY1Ne3lnDsO+DzwFefcmc65PYIg+HjR5j4Igh9VVVXt7L3/mPf+q977851zhwRBcNSMGTNeLd5/Op2+OAzDsVFpaztz587NhWE4NpfLjSsV29q1a/8ZPffyUuu99y1BEJzlvT8QOM8592Xn3HFjx449JpvNLuzg//1iGIb7R3F/OZVKfaimpmbs7NmzX4tiOa74ObNmzXo5m80eW1tbW5tOp0eEYTg2lUqtS2hnzpz54Jo1a3b33k/AevP9TBiG+wVB8JGampp7wjAcWypRzWaztwdBsAfQF9g76vU3X0WXXC73iSimBSX+j1+n0+mdgY8AF2Hv3RFjxowZO2vWrGeLt8/lcj8Iw3DsmjVrbit1XIDvRf/XXR2sr2SdOXek0blDNsBdc801ft2Cc6OnTJnS2TG8RKTn+QlwLHA+1rnEOODfwDPAB4BBWHulr2LVwl6NI0gR2SLbAi8AlwH/C6wGHgbGAhOAOcAHgd8DdwMl2wVK95DJZH4LXOC9P7exsfGGuOORbm1H4GngO8B1QDPwBLAfcCJwJ/Ah7NzxT+CCeMKUpJk2bdqe3vvn8ssq4RCRTfFn7Afln9hF69vR4ztjP0LbYxe3r6Hk9P+3d+9Rctb1Hcffs5ck5LZgkAYwgDXREBOMiEhpvWCItVYkeOmRHoxaFeyBY1UsJV6jHEtVopYeL8mxogVKKZATslC1hFBPhMZCIiRcAkFNsoZLICHJJiHZS57+8ZvJPjM7M3thd57f7L5f58zZ32+eZ2e+2cw+O5/5/Z7fI9WrXUAb8A1gEeG8v1Py2/6REFqPApqBn9S+PEmRegbYASwBvgJsAwqXKbqG8B7hKEL++GkWBao+GFAlDcRDhFBauBTASfmvkwifkAJ0Aj+qcV2ShtY1hFGOqRRPxUtfPmQ78KtaFiUpekuA7wJ/lL8VzE212wjnZ0tleQ6qpIH6AeHyCJXswk9GpXp3K3CgyvYEaM1/VX37DXBLQ0PDlqwL0YhwE7C/yvYEuA2PHarCEVRJA/Vj4AqKPxlN206Y5iOpfh0EVgF/XWH788D3a1eOhktra+uPcNaLhs5+4F7gggrbnyOcJiBV5AiqpIHaDTxcYduL+KZVGim+Qwii5ewHNtawFkn14xpgZ4VtewgLK0oVGVAlDcY3gBfK3L+XMDVQUv17gJJrd+Z1A/9e41ok1Y/7gH1l7u8Crq9xLapDBlRJg3E3YbS01CbCp6OSRoal9D7nfCdOCZVU3XVAR8l9O/P3S1UZUCUNxmHCCEp36r524NpsypE0TP6VMK0/7Tng9xnUIql+/JDex45nCJetkqoyoEoarO9R/MdnH3BnRrVIGh47gcdS/S5CaJWkap4FfpvqdxJmZEh9MqBKGqwthD9ABb+m+uVnJNWnbxHeXEKY2n9jhrVIqh/fpPjYcXOGtaiOGFAlvRTXEFbz3IPTe6WR6ueE6xsDbAZ2ZFiLpPpxBz0LKj5Kz3FEqsqAKuml+A/C1N4DwC8zrkXS8DhMGPnoxA+iJPVfF7CCcOz454xrUR0xoEp6KV4EVgP/RXgTK2lkupawKNptWRciqa58hxBQb8+6ENWPpqwLkFT3/g7DqTTS/RZ4PeWvbShJlWwC3kD5S9NJZRlQJb1Uz2VdgKSa2JR1AZLqkscODYhTfCVJkiRJUTCgSpIkSZKiYECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKXmZGdWHFihXTsq6hmhUrVkxpb28fC7Bjx472NWvWtGddU4mJwOR8+xCwM8NaymkGXp7qPw0kGdVS1nvf+96puVyuAWDu3Lm75syZczDrmipJkqT9ggsu2F2L51q+fPlxDQ0NY2vxXIOxZs2aSVu2bJkEsHfv3kN33XVXbK/9McCxqf5TWRVSxQmp9vNAR1aFVDAFKLwG2/O3aJx++ukTX/nKV04GmDRp0qEFCxbE9hoscv755/8hl8sN+/H3nnvuGbdnz56X971nNjo6OnI333zz8YX+/fff/9y2bds6s6ypjPRrfy/xXac46vce06ZNG3PmmWceOf5+6EMfivH4e0RLS8tz55xzTrTvPYaSAVXRW7x4cUNjY+O2rOuoZt26dWzcuDHrMjSMli9ffqQ9c+ZMGhsbM6ymT98DLqvFEzU1Nd2Zy+XOqMVzDcbWrVu57bbbsi5Do9j69etZv349ANOnT+d973tfxhVVt2rVqqOBPcP9PO3t7X/e2Ni4YrifZ7ByuZzHjhGura2Ntra2I/2FCxfS0BDv5NL9+/e/E/hF1nXUQrz/C5IkSZKkUcWAKkmSJEmKglN8VXeSJFmYy+XWZl1H2sGDBx8gf57F9Olv2fTkk+d/MeOSSnzty7DntNAefxCuuijbekpdPw8e/Nue/mc/BicO+xSzgWhu/vytnZ2HANi8efPSs846a0nGJZX6PnBuxjUsAZZmXEORHTt2/CcwF2Dq1Ffve+aZSz6SbUWlli2Ax1O/j0ven10tlVx+a0/7jTfAByOblnnFT6B7Ymif8ARc/vlMyykxY8bPvrh586q5AJ2dnS8Cr8u4pCK5XG5OkiRZz2WN7ueyZcuWY4H7Cv3p0z/6gyefnH13hiWV8fc3wOFxoT1tI3z6q9nWU2rxVdB+amhP2A9f+3C29RSbMePBd2/efP1HCv329vbXtrS0xHae8SZG4YCiAVX1aPt55523Oesi0qZPn3640B47dmIHfLat2v619/XUSfW5JL76WncV9+c9Be/aVX7fbORyXzjS3rt37wuxvQbvuOOO/UmS+bpSO2P7uZx99tlHXvtNTc0RvvZvLFnMKrb6AC5PtY/eHV+N/3C4p90U3fF33Lh7j7wGkyQ5HNvvyMqVK4/O5XJZl5HE9nO58MIL96b748efvCu21xZckTrojzkYX31XpRZUa4zu+DthwpVFx9/bb7/9yVtuuSWqReBaW1uzLiEToy6RS5IkSZLiZECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKBlRJkiRJUhS8zIxGo0bgNcAbgDPyX4/Pb/sEsDqjuiRJklR/JhFyVRfQnnEtdc+AqtHoKmBRhW3ja1mIJEmS6koDMJ/igY6T8tv+Fzg7o7pGDAOqRrOtwHqgDfhUxrVIkiQpfuOBn2ddxEhmQB2cBuCPgROBHPA08PgQPOargOOAo4AXgCeBPS/xcdXbUuDbwPP5/gwMqJIkSeqffcCDwLr87SPA27MsaCTJKqCeCXw/394HvK0f33MCsDLVPxfYPbRlFfkCcEG+fQewGBgDfA64GDi5ZP82YAnwPcL88/56NXAl8JeEcJrWBdwHXAO0VnmMqwlTDQBuAL5bZd9vAeek+ldQ/ZzLXwBT8u3PAGuq7FsvtmZdgCRJkurSfuBooDt137szqmVEyiqgTibM14b+jxCOTX0PDH/tJ6WebyNhEZ0VhHBdzjRCMDwH+ADQ2cfj54CvEIJwpX9LE/CW/O0WYCFwsMx+21O1dlE5oObyj5EOwudROaBOB96Rbx8GHq2wnyRJkjQaJBSHUw0xp/j2zzhgOSGcdgD3EELrAcL00POAifl9zyeMSn69j8dcBnw81d8N3EkIgfsJI8bvBmblt3+AMPX3PYRfjLR0wDyD8KlOudHlOfQepZ1Xpcb0tgeBnVX2lSRJkqSXxIDaP+8n/Kx+RRiB/H3J9hMJJ0vPzvevAL5DCLDlfJLicPovhJHU0mWpFwGXEc6XbCQE1svy+6c9CjxFCLWNwFuB28s8bzpwHiKMSs8GpgLP9LH/3RX+LZIkSZI0JBqyLqBONBFGTN9B73AKYYrthfSMbE4G3lXhsY4hnAda8G3CAj3lrpl0GLgW+FLqvkWEYFkqPYp6boXnTgfOpfmvOcqf1N1A8bmqBlRJkiRJw8qA2n+fBl6ssv1hYG2qf0aF/S6mZzpwG2HktC9LCCEYwrmw7yyzTzpAlpu220w4lxXCisM/7WP/1wHH5tsdhNFjSZIkSRo2TvHtn6eovtJtwQPAn+Tbp1TYZ0GqfSPlFz0q1UFYxfeT+f6b6T2FNx1QTyVMO96euu9MYFJq38I5pVMoH1DT960lnBcbs6OofKmYezFgS5IkSdEzoPbPb/q5345Uu6XM9vEUr0R83wBq2JRqzyqzvQ14gnDZGgjTdq9PbS89n/QwYbGn9xMumTMD2Jza5+0l+8duPPBPFbZ9FQOqJEmSFD0Dav+80M/9OlLtMWW2v4Iw1bbgm4RLzfTHlFT7ZRX2WU1PQJ1H+YDaTQimAKsIAbWwvRBQx9AzHRjqI6C+CHyjwrZ7a1mIJEmSpMExoPZP1xA9zjEl/ZmDfJwJFe6/m55pwOkR0wnAWfn2enoCd3ra8jzgh/n2m1LP0Q783yDrrKUDwJVZFyFJkiRp8AyotdVY0r+D6gsvVdJW4f57CFN3GwijtTMJU4P/jJ4R3fRo6GZgK2GK7zn57ztMcbhdA3QOokZJkiRJGpB6CqjlpszWm+dL+l+m/+e39sdOwuJHp+f78wgBtdr1TFcDHyVMIZ5LGGH1+qeSJEmSai6ry8ykV64d18/vOW44CqmxpyieLjxnGJ6jdNpu+utBep+Puapk/4mEKb4FIzGgngLclbr9JLXtqpJtb65xbZIkSdKoldUI6p5Ueyxh0Z9dfXzPm/rYXg/2AffTcyma84F/G+LnuBv4XL79NkKwn5vv30fvKcWrgQTIAecCj9CzkNNzwIYhri8GEwn/1nLmlvR/WHYvSZIkjVY3An+R6hfWbnkjxZlmA+H9uAYgq4D6O8JqsoVzMs8mnI9ZSQPwN8NdVI3cSnFAnQ08PISPv4awmvAYwqJMl9MzUr6qzP7PEELpbMK5qk+kthXC60jzFHBJP/ddP5yFSJIkqe5MpPfipxCyVfr+SbUpZ2TJKqDuJ3yi8Pp8/1KqB9QvAacOd1E1spSw2uzLCQH9ZsI00r5GkAumEa63eqjC9v3AWnouE3NZalul6bp3EwLqeIo/CFhdfve6twtYlnURkiRJqkuXAJ/px36V3q+riqzOQYXia3S+E7iGMN037RjgWmAxYXrsSLAf+DhhtVyAWYRRuguo/P8xhjCN4Abgt/T9aUw6iI7Pf30BWDeA/UvvlyRJkhRmIP6uH7ftWRVYz7JcxXcpYeT0Vfn+5cCHCedJ7iNcJuVNhNB6EPgEcFPtyxwWKwn/3iWEUHoysJwwMvpr4A+EAHs0MB04DThqAI+/GvhqyX3/Q5hWXc4vCYs3pV8PWwhhWJIkSZJqIsuAegBYAPw3cHz+vmOB95Tstwu4iHC5lJHku8DjhEV4TsrfdxxwXh/ft4W+pwv8mhDyJ6buqzYaupfixZv62l+SJEmShlzW10F9mDA6uAj4AOH8yoJnCSOm3wbaCOHtltT24Z7TvS71fPf383s2pb6nPwsf/QyYQQjgCwjnjbaU7LMHeJQwyvkzwiJIfS1c1EkYnZ1V8lzVLCWM3BaMlNFqSZIkSXUi64AK8DxhuuvlwBRCQNtJ8aVoIEx//asa1rWMgS+kszJ/G4gO4Mf5G8Bkws8hRxg93j3AxytYPMD9f5q/SZIkSVImYgioaTvzt9Fsb/4mSZIkSaNKlqv4SpIkSZJ0hAFVkiRJkhQFA6okSZIkKQqxnYM6GI3Ax4bosdYDDwzRY2mY5HK5m1tbWzuyriNt0aJFkwvtTZtWnQrj7syynt46J/e0D4yLr76uscX9BTdAQ1+rVddUZ2fPS27u3LmXXXrppQszLKeXJElelnUNwJWtra2XZV1E2nXXXXdsof30049PjPC1X3KN69jqK3XPR2HcB7OuolhX6pJq22fG9jN87DGOHH/HjBkzvrW1dXuW9ZTRnHUBwFGx/VwOHDjQcNNNPRc0eOSRqz8FV1+SYUlldI/raW+ZG9trHzpSV6ZonxBbfRs3Mi7dv+iii36/cGFUf9phlA4mjoSA2ky4RMpQ+BoG1HpwbN+71FYulzvS7u7uaCbCGnskOTgUcX0AnVOyrqBUkorLjY2NEym+zrCCyflbNBoaev62d3d35aAr8td+7L+bXRPCLVbdTdAd1c+wq6uomwNOyKaSqEX3c0kfOwC6uw9NAiZlU01/dDfH9tovFt97j+7uXndF9RoczUZlKpckSZIkxWckjKAeAoZqatvBIXocDaHFixcfXrlyZXRzLtJmzZo1e+rUqS0Azz77bNuGDRu2ZV1TiVcAJ+fb7cCGDGspZxJwWqq/Fuj92WaG5s2bd1ZDQ0MjwPjx4x9LkmRX1jVVsamGz/XlJEmi+lQ87fjjjz95/vz5rwBob2/fvXbt2keyrqlECzA71b83q0Kq+NNU+2F6X6c8a68Fjs63/wBszbCWXmbOnHnitGnTTgFoaWlpT5IktuNvkWOOOeZALZ6nqalpXVdXV7R/25MkaZw/f/5Zhf5DDz20YceOHe1Z1lTGafSM6m4D2jKspZyTgGn59h7C8SMaU6dObZkzZ86R42+SJPclSRLV6UVpzc3NUR87hlJu6dKlR/4jcrncay6++OInsixIkiRJkjQ6LFu27NVJkjxe6DvFV5IkSZIUBQOqJEmSJCkKBlRJkiRJUhQMqJIkSZKkKBhQJUmSJElRMKBKkiRJkqJgQJUkSZIkRcGAKkmSJEmKggFVkiRJkhQFA6okSZIkKQoGVEmSJElSFAyokiRJkqQoGFAlSZIkSVEwoEqSJEmSomBAlSRJkiRFwYAqSZIkSYqCAVWSJEmSFAUDqiRJkiQpCgZUSZIkSVIUDKiSJEmSpCgYUCVJkiRJUTCgSpIkSZKiYECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKBlRJkiRJUhQMqJIkSZKkKBhQJUmSJElRMKBKkiRJkqJgQJUkSZIkRcGAKkmSJEmKQlO6kyTJKcuWLcuqFkmSJEnSKJIkySnpflPJ9l8kSVK7aiRJkiRJynOKryRJkiQpCgZUSZIkSVIU/h9zhnJWRK6mqgAAAABJRU5ErkJggg==" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=0a40846c">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>We are going to implement this algorithm with MPI later in this notebook.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=75f735a2">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Extension-to-2D">Extension to 2D<a class="anchor-link" href="#Extension-to-2D"></a></h2><p>The Jacobi method studied so far was for a one dimensional Laplace equation. In real-world applications however, one solve equations in multiple dimensions. Typically 2D and 3D. The 2D and 3D cases are conceptually equivalent, but we will discuss the 2D case here for simplicity.</p>
<p>Now, the goal is to find the interior points of a 2D grid given the values at the boundary.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=18659ed7">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="400"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=ca411d89">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>For the Laplace equation in 2D, the interior values in the computational grid (represented by a matrix $u$) are computed with this iterative scheme. The entry $(i,j)$ of matrix $u$ at iteration $t+1$ is computed as:</p>
<p>$u^{t+1}_{(i,j)} = \dfrac{u^t_{(i-1,j)}+u^t_{(i+1,j)}+u^t_{(i,j-1)}+u^t_{(i,j+1)}}{4}$</p>
<p>Note that each entry is updated as the average of the four neighbors (top,bottom,left,right) of that entry in the previous iteration.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8c916627">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Serial-implementation">Serial implementation<a class="anchor-link" href="#Serial-implementation"></a></h3><p>The next code implements a simple example, where the boundary values are equal to 1.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=1e843565">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">jacobi_2d</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">,</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="o">:</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">,</span><span class="o">:</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="o">:</span><span class="p">,</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="o">:</span><span class="p">,</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">.=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">north</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="n">south</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="n">east</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="p">]</span>
<span class="w"> </span><span class="n">west</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="p">]</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.25</span><span class="o">*</span><span class="p">(</span><span class="n">north</span><span class="o">+</span><span class="n">south</span><span class="o">+</span><span class="n">east</span><span class="o">+</span><span class="n">west</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=f4dc50b1">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>If you run the function for zero iterations you will see the initial condition.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=4acf219e">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_2d</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=efd4df6a">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>If you run the problem for enough iterations, you should converge to the exact solution. In this case, the exact solution is a matrix with all values equal to one.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=5c120b8b">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">300</span>
<span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_2d</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=85895681">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Where-can-we-exploit-parallelism?">Where can we exploit parallelism?<a class="anchor-link" href="#Where-can-we-exploit-parallelism?"></a></h3><div class="highlight"><pre><span></span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">north</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="n">south</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="w"> </span><span class="n">east</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="p">]</span>
<span class="w"> </span><span class="n">west</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="n">j</span><span class="p">]</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">,</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.25</span><span class="o">*</span><span class="p">(</span><span class="n">north</span><span class="o">+</span><span class="n">south</span><span class="o">+</span><span class="n">east</span><span class="o">+</span><span class="n">west</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
<ul>
<li>The outer loop cannot be parallelized (like in the 1d case).</li>
<li>The two inner loops are trivially parallel</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=65e4f745">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Parallelization-strategies">Parallelization strategies<a class="anchor-link" href="#Parallelization-strategies"></a></h3><p>In 2d one has more flexibility in order to distribute the data over the processes. We consider these three alternatives:</p>
<ul>
<li>1D block row partition (each worker handles a subset of consecutive rows and all columns)</li>
<li>2D block partition (each worker handles a subset of consecutive rows and columns)</li>
<li>2D cyclic partition (each workers handles a subset of alternating rows ans columns)</li>
</ul>
<div class="alert alert-block alert-info">
<b>Note:</b> Other options are 1D block column partition and 1D cyclic (row or column) partition. They are not analyzed in this notebook since they are closely related to the other strategies. In Julia, in fact, it is often preferable to work with 1D block column partitions than with 1D block row partitions since matrices are stored in column major order.
</div>
<p>The three partition types are depicted in the following figure for 4 processes.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=11e834b5">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=7384ddfe">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Which of the thee alternatives is more efficient? To answer this question we need to quantify how much data is processed and communicated in each case. The following analysis assumes that the grid is of $N$ by $N$ cells and that the number of processes is $P$.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=f733d88f">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="1D-block-partition">1D block partition<a class="anchor-link" href="#1D-block-partition"></a></h3><p>The following figure shows the portion of vector <code>u_new</code> that is updated at each iteration by a particular process (CPU 3) left picture, and which entries of <code>u</code> are needed to update this data, right picture. We use analogous figures for the other partitions below.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6b983ffd">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="400"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=1bc21623">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=d01f8ce8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span><span class="w"> </span><span class="c"># Change to true to see the answer</span>
<span class="n">partition_1d_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=a9bed431">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="2D-block-partition">2D block partition<a class="anchor-link" href="#2D-block-partition"></a></h3>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6f7b5b36">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="400"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=09bd28ca">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=e94a1ea6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
<span class="n">partition_2d_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9aaf1ca6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="2D-cyclic-partition">2D cyclic partition<a class="anchor-link" href="#2D-cyclic-partition"></a></h3>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=77701278">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="400"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=b373e9ce">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=10fab825">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
<span class="n">partition_cyclic_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=191fa03b">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Summary">Summary<a class="anchor-link" href="#Summary"></a></h3><table>
<thead>
<tr>
<th>Partition</th>
<th>Messages <br/> per iteration</th>
<th>Communication <br/>per worker</th>
<th>Computation <br/>per worker</th>
<th>Ratio communication/<br/>computation</th>
</tr>
</thead>
<tbody>
<tr>
<td>1d block</td>
<td>2</td>
<td>O(N)</td>
<td>N²/P</td>
<td>O(P/N)</td>
</tr>
<tr>
<td>2d block</td>
<td>4</td>
<td>O(N/√P)</td>
<td>N²/P</td>
<td>O(√P/N)</td>
</tr>
<tr>
<td>2d cyclic</td>
<td>4</td>
<td>O(N²/P)</td>
<td>N²/P</td>
<td>O(1)</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c0c6d216">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Which-partition-is-the-best-one?">Which partition is the best one?<a class="anchor-link" href="#Which-partition-is-the-best-one?"></a></h3><ul>
<li>Both 1d and 2d block partitions are potentially scalable if $P&lt;&lt;N$</li>
<li>The 2d block partition has the lowest communication complexity</li>
<li>The 1d block partition requires to send less messages (It can be useful if the fixed cost of sending a message is high)</li>
<li>The best strategy for a given problem size will thus depend on the machine.</li>
<li>Cyclic partitions are impractical for this application (but they are useful in others)</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8caf9b30">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="The-Gauss-Seidel-method">The Gauss-Seidel method<a class="anchor-link" href="#The-Gauss-Seidel-method"></a></h2><p>Now let us study a slightly more challenging method. The implementation of Jacobi used an auxiliary array <code>u_new</code>. The usage of <code>u_new</code> seems a bit unnecessary at first sight, right? If we remove it, we get another method called Gauss-Seidel.</p>
<p>The following cell contains the sequential implementation of Gauss-Seidel. It is obtained taking the sequential implementation of Jacobi, removing <code>u_new</code>, and only using <code>u</code>. This method is more efficient in terms of memory consumed (only one vector required instead of two). However it is harder to parallelize.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=efd792c3">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=5a38cef6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Note that the final solution is nearly the same as for Jacobi for a large enough number of iterations.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=c7efa254">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1000</span>
<span class="n">gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=37b7c288">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=97d9ad59">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Which of the two loops in the Gauss-Seidel method are trivially parallelizable?
</div>
<div class="highlight"><pre><span></span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span>
</pre></div>
<pre><code>a) Both of them
b) The outer, but not the inner
c) None of them
d) The inner, but not the outer</code></pre>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=0b383598">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="w"> </span><span class="c"># replace x with a, b, c or d</span>
<span class="n">gauss_seidel_1_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6b06f709">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>If you look into the algorithm closely, you will realize that the steps in loop over <code>i</code> are not independent. To update <code>u[i]</code> we first need to update <code>u[i-1]</code>, which requires to update <code>u[i-2]</code> etc. This happens for Gauss-Seidel but not for Jacobi. For Jacobi the updates are written into the temporary array <code>u_new</code> instead of updating <code>u</code> directly. In other words, in Jacobi, updating <code>u_new[i]</code> does not require any entry updated entry of <code>u_new</code>. It only requires entries in vector <code>u</code>, which is not modified in the loop over <code>i</code>.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=099634d9">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Backwards-Gauss-Seidel">Backwards Gauss-Seidel<a class="anchor-link" href="#Backwards-Gauss-Seidel"></a></h3><p>In addition, the the result of the Gauss-Seidel method depends on the order of the steps in the loop over <code>i</code>. This is another symptom that tells you that this loop is hard (or impossible) to parallelize. For instance, if you do the iterations over <code>i</code> by reversing the loop order, you get another method called <em>backward</em> Gauss-Seidel.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=ff03c246">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">backward_gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:-</span><span class="mi">1</span><span class="o">:</span><span class="mi">2</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=63c4ce1f">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Both Jacobi and <em>forward</em> and <em>backward</em> Gauss-Seidel converge to the same result, but they lead to slightly different values during the iterations. Check it with the following cells. First, run the methods with <code>niters=1</code> and then with <code>niters=100</code>.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=abe31423">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="n">u_forward</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=23430f70">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">u_backward</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">backward_gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=0b2b2437">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">u_jacobi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=0deb5549">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Red-black-Gauss-Seidel">Red-black Gauss-Seidel<a class="anchor-link" href="#Red-black-Gauss-Seidel"></a></h3><p>There is yet another version called <em>red-black</em> Gauss-Seidel. This uses a very clever order for the steps in the loop over <code>i</code>. It does this loop in two phases. First, one updates the entries with even index, and then the entries with odd index.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=dda0a371">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="300">
</img></div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9707f13b">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>The implementation is given in the following cell. Note that we introduced an extra loop that represent
each one of the two phases.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=c0cbe2d8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">red_black_gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:-</span><span class="mi">1</span><span class="o">:</span><span class="mi">2</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">mod</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=13ce270f">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Run the method for several values of <code>niters</code>.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=59c1e7f8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1000</span>
<span class="n">red_black_gauss_seidel</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d1bacc26">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Which of the loops in the red-black Gauss-Seidel method are trivially parallelizable?
</div>
<div class="highlight"><pre><span></span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:-</span><span class="mi">1</span><span class="o">:</span><span class="mi">2</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">mod</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span>
</pre></div>
<pre><code>a) All loops
b) Loop over t only
c) Loop over color only
d) Loop over i only</code></pre>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=d511cc02">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="w"> </span><span class="c"># replace x with a, b, c or d</span>
<span class="n">gauss_seidel_2_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=8946b83f">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
<span class="n">gauss_seidel_2_why</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=41e90d60">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Changing-an-algorithm-to-make-it-parallel">Changing an algorithm to make it parallel<a class="anchor-link" href="#Changing-an-algorithm-to-make-it-parallel"></a></h3><p>Note that the original method (the forward Gauss-Seidel) cannot be parallelized, we needed to modify the method slightly with the red-black ordering in order to create a method that can be parallelized. However the method we parallelized is not equivalent to the original one. This happens in practice in many other applications. An algorithm might be impossible to parallelize and one needs to modify it to exploit parallelism. However, one needs to be careful when modifying the algorithm to not destroy the algorithmic properties of the original one. In this case, we succeeded. The red-black Gauss-Seidel converges as fast (if not faster) than the original forward Gauss-Seidel. However, this is not true in general. There is often a trade-off between the algorithmic properties and how parallelizable is the algorithm.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8ed4129c">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="MPI-implementation">MPI implementation<a class="anchor-link" href="#MPI-implementation"></a></h2><p>In the last part of this notebook, we consider the implementation of the Jacobi method using MPI. We will consider the 1D version for simplicity.</p>
<div class="alert alert-block alert-info">
<b>Note:</b> The programming model of MPI is generally better suited for data-parallel algorithms like this one than the task-based model provided by Distributed.jl. In any case, one can also implement it using Distributed.jl, but it requires some extra effort to setup the remote channels right for the communication between neighbor processes.
</div>
<p>We are going to implement the method in a function with the following signature</p>
<div class="highlight"><pre><span></span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_mpi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
</pre></div>
<p>The signature will be very similar to the sequential function <code>jacobi</code>, but there are some important differences:</p>
<ol>
<li>The parallel one takes an MPI communicator object. This allows the user to decide which communicator to use. For instance, <code>MPI.COMM_WORLD</code> directly or a duplicate of this one (which is the recommended approach).</li>
<li>Function <code>jacobi_mpi</code> will be called on multiple MPI ranks. Thus, the values of <code>n</code> and <code>niters</code> should be the same in all ranks. The caller of this function has to make sure that this is true. Otherwise, the parallel code will not work.</li>
<li>The result <code>u</code> is NOT the same as the result of the sequential function <code>jacobi</code>. It will contained only the local portion of <code>u</code> stored at each rank. To recover the same vector as in the sequential case, one needs to gather these pieces in a single rank. We will do this later.</li>
</ol>
<p>The implementation of the parallel function is given in the following code snipped:</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=d31c1e41">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">jacobi_mpi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="c"># Initialization</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="c"># Communication</span>
<span class="w"> </span><span class="n">ghost_exchange!</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="c"># Local computation</span>
<span class="w"> </span><span class="n">local_update!</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">u_new</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=04a38c37">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>In the following cells, we discuss the implementation of the helper functions <code>init</code>, <code>ghost_exchange</code>, and <code>local_update</code>.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=96b8d40e">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Initialization">Initialization<a class="anchor-link" href="#Initialization"></a></h3><p>Let us start with function <code>init</code>.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=b98a9348">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">mod</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">nranks</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"n must be a multiple of nranks"</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Abort</span><span class="p">(</span><span class="n">comm</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">div</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">nranks</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=1b9e75d8">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>This function crates and initializes the vector <code>u</code> and the auxiliary vector <code>u_new</code> and fills in the boundary values. Note that we are not creating the full arrays like in the sequential case. We are only creating the parts to be managed by the current rank. To this end, we start by computing the number of entries to be updated in this rank, i.e., variable <code>load</code>. We have assumed that <code>n</code> is a multiple of the number of ranks for simplicity. If this is not the case, we stop the computation with <code>MPI.Abort</code>. Note that we are allocating two extra elements in <code>u</code> (and <code>u_new</code>) for the ghost cells and boundary conditions. The following figure displays the arrays created for <code>n==9</code> and <code>nranks==3</code> (thus <code>load == 3</code>). Note that the first and last elements of the arrays are displayed with gray edges denoting that they are the extra elements allocated for ghost cells or boundary conditions.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=756b8d01">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,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" width="450">
</img></div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=3f0e49e4">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Communication">Communication<a class="anchor-link" href="#Communication"></a></h3><p>Once the working arrays have been created, we can start with the iterations of the Jacobi method. Remember that this is implemented in parallel by updating the ghost cells with data from neighboring processes and then performing the sequential Jacobi update. See figure:</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6b214777">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA6gAAAFACAYAAACxyVHuAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAewgAAHsIBbtB1PgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N15fFT19f/x12cmIQFkE1wANxBFrTu4b1itimQC2mKrtfrtRtXazbbWrmJba+1m7S5fv9Wqrbb5VWBugFatpe4buGvdFVcU2cISSOZ+fn+cO2QyTCAsmXszeT8fj/vIvXPv3Dm5M3PnnvvZ3DXXXOMRERERERERiVkq7gBEREREREREQAmqiIiIiIiIJERV0fLJzrlX4whEREREREREehbv/W7AP/PL7RJU59yrU6ZMeb7cQYmIiIiIiEjPM23aNLxv6xZJVXxFREREREQkEZSgioiIiIiISCIoQRUREREREZFEUIIqIiIiIiIiiaAEVURERERERBJBCaqIiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEZSgioiIiIiISCIoQRUREREREZFEUIIqIiIiIiIiiaAEVURERERERBKhKu4ARDbGe+8aGxsvizuODbnuuusOWLhw4SCAhQsXvvbiiy++EndMRXYBRkbzy4H5McZSSn/g4ILlu4FcTLGUdPjhhx+dTqerAE455ZSnDjzwwEVxx9QR59yDdXV1s8rxWtls9nPOueHleK3NMXv27BFPPPHErgArV65c8thjjz0ed0xFBgEHFCzPjSmODRlXMP84sCSmODpyAHYcARYAL8cYy3pGjBixy7Bhw0YCbLvttsunTJmStPNvO+l0+vJTTz11TVe/ThAEewFndfXrbK7m5ub0L3/5y2Pyy88+++z8xYsXL48zphIOxn4/wT73C2KMpZQRwK7R/FLgsRhjWc/gwYMH7rXXXgfmly+55JK5MYazUWEY3jBx4sQX446jHJSgSuJddtllbsyYMd+NO44NeeGFF3jyySfzi8dsaNuEmBB3ABuRuGP4wAMPrJsfN25c4uIr5L3/LVCWBBX4DDC2TK+1yd577z3uvffewofq44qlkxL92SL58SXOK6+8wiuv2D3LUaNGQcLPv9XV1T8HujxB9d6Pds4l+re96NyR9M9+0uMDyMQdQKH333+/3XschuExqVRyK5em0+l7gR6RoCb3XRAREREREZEeRSWo0h09jlUVSYwwDI8i+j717j1w5erVPBdzSEVW7AGt/Ww+HUK/RFWzgTVDYPUubcsDnwRaYgunBOeWHey9B2DNmjULgKRV494XGBxzDK+QsCpma9euPYioClxNTZ/cmjW9ElbFt3lHaB7WtjwwgdU/lxZUv+/7JlQvjC+WUpYdAD5t871WQp9EnX/79HGjVq1a0h/Ae58D7ok5pGL9aN/EIg4h1rQjMcIw7AUckV+uqdl2wZo1YcKadiw7EHxU2FTTBL1fiDeeYk17Qm4bm0/noF+izr+1tentm5vf3ym/7L2/C/AxhlTKcXEHEAclqNLteO8vqq+vvzPuOAqNGjVqCTAQYOTII196+ulZ58ccUpHBv4bFh9p87RpYkrD4jq+Hud9uW/7zxXDq4vjiWV91de8H165tBuCpp576y89+9rNvxhxSO42NjTO89xNjDuN/M5nMFTHH0M6RRx55P3A4wHbbjVj1xhtPJeyzP+YTMP/CtuWkfTcB3INt80dOh9tujC+WUqpvh9aoHd6Or8BriTqGu+/+4auffPLWwwFaWlqaM5nMuJhDaiebzR7inHso5jASd1zOPPPMHYB38sujR3/xxieeuDQbY0glVM2FXG+b3+m/8OKFG9y87AZNg6VRG/u+q5N2fttrr0vOfOyxK7+cX/7zn//8oYaGhrVxxlQsCIIcPbDGa4/7h0VERERERCSZlKCKiIiIiIhIIihBFRERERERkURQgioiIiIiIiKJoARVREREREREEkEJqoiIiIiIiCSChpmRnqwa2A/YPVp+Bng6vnBERERERHo2JajS0+wBXASMAfYHagrWfR+4NI6gRERERKTbGhlNAK8Dz8UYS7enBFV6mn2B8wqWffTXxRCLiIiIiHQ/w4AvYAUeY4FBBeuuBr4cR1CVQgmq9DSLgZuBedE0H3iV9icWEREREZGO7AVcEncQlUoJqvQ0/4kmEREREZHNsRKYQ1uBxzzgLmC3GGOqGEpQRUREREREOu9B4NS4g6hUGmZGREREREREEkEJqoiIiIiIiCSCElQRERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKBKpZiHjXFaPP0tzqBERERERKTzNMxM5doD+EfB8geA5o08pwZ4pmB5PPD8Vo6rqwwABpV4fJtyByIiIiIiIptHCWrl6gWMLFh2nXiOK3pOr60aUdcaQ+kaAS3lDkRERERERDaPElSpFMviDkBERERERLaM2qCKiIiIiIhIIqgEVXqig2h/cyYd/R2GVRXOewd4s1xBiYiIiIj0dEpQpSe6B+hT4vHPRFPelcAlZYlIRERERLqTXWkr5IC2vGoA7ft0WQ4sKldQlUAJqvRErwC9O7Hd4q4ORERERES6pQeAHUs8/j/RlPcH4PwyxFMxlKBKT7Rv3AGIiIiISLe2DBuicWNWdXUglUYJqoiIiIiIyKbZK+4AKpV68RUREREREZFEUIIqIiIiIiIiiaAEVQp1ph69iIiIiIhIl1CCWrlWFy13ptfaUj2RiYiIiIiIlIUS1Mq1rGh5eCeec0RXBCIiIiIiItIZSlAr1/u0HxT46I1s74DPdV04IiIiIiIiG6YEtbLdVzD/eaB6A9teBBzeteGIiIiIiIh0TAlqZftTwfwHgFuAIUXbDAGuBn4KLC1TXCIiIiIiIuupijsA6VIzgLuAY6Pl04EJwCNYG9XtgQOxz0ELcBYwu/xhbhrn3KFBENTGHUehr33ta+u+S8uXv90PPnZknPGsb+3AtvlcKnnxvT6q/fLvDoEbmuKJpbQwDNfNb7/99iODIDg1xnDW473fIe4YgNFJOy5XXXXVus9+c3NTOnmf/UW7tl9OWnzFXt81eTH6gmuZVYk7/y5b9vqg/HwqlUon7TsC7BF3AEDijsvChQsH3nzzzeuWFy26f1TSPlvgCwqaVg5IXnxr+7fNtybu/Lto0ZIRhcuTJ08+5ZxzzmmNKx5powS1soXAGcA/gQOix2qAo4q2WwKcC/y7fKFtkSviDqBYr1691s2//vqjI+DRq2IMZyOaa+CvCY4PYNb3446gWGvBT9bOO+98BvbdkvbOjabE2HbbbdfNL1q0oA8sSPhnP+nfzf9mbEqqRbsm7RguWNA2X1VVVQvMii2Y5KohYcdlwIAB7ZbfeuufHwU+Gk80nfHOnkn77Le3qnfS4nvjjfbLNTU1M+OJRIopQa18C4HDsDaoZwIHY1W7Q2AB8Dfgt9F8NTCt4LmLyxqpiIiIiIj0aEpQe4Y1wC+iKQUMBJqwar2FWkhgT76XXnqpb2xsXBN3HBuSTqerq6urUwC5XC4XhmHSqoikafu+h6z/3sfNAb0KlhP3fldXV/fC4gQ7fuEGNo+V975s728qlVrjvU/c+5WXSqWqqqur0wDe+7C1tTVpn/0U7TuwS+KxrCmYT+Jnv5q2PjVyQKLOv6lUKp1Op6sAqqqqknj+baelpcWX6aVyJPPzvk51dfW6z35ra+ta7325jk1nFX72W7FjmiSJvvZwzqWqqqqqC5YT/Xkkee9vl3HXXHPNui+bc270lClTno8zIBEREREREekZpk2btqf3/rn8snrxFRERERERkURQgioiIiIiIiKJoARVRCqZ2/gmIiLr6JwhIhIzJagiUomqgG8Ac9B5TrrGsLgDkK3uKOBRYP+4A5GKNAjoHXcQIt2BLtxEpBLtBnwXOBn4WryhSAUaDTwP3AD0jTkW2XouwcYMvwmojTkWqSwO+1w9jg39JyIboARVRCrRi8AXo/kfAofHGItUlhrgZiwx3QlYHW84shV9Cngb2A/4acyxSGX5CnAqsDM6Z4hslBJUEalUfwRuwcaJuwVVyZSt4yfAQcBC4CySNyaobL73gHOw9/TzwP/EGo1UijHAFdH8F4EnYoxFpFtQgioilew84FlgV2A2MCDecKSbm4JdYHrgM8A78YYjXeAO4AdYlcxpwPh4w5FubjgwHegF/B3433jDEekelKCKSCVbhl1gvoW1LbsVq6IpsqkmAr+L5r8LNMYYi3Sty4DrsNoXfwMOiTcc6aa2BW7DqvU+AXw63nBEug8lqCJS6V7DOktaCnwQK0ntF2tE0t0cg7U7TQN/AC6PNxzpYh74LDAT2AZLMo6ONSLpbvpin599gAVY+9NlsUYk0o0oQRWRnuApYBKwAktSb8PubotszAnYTY3eWKnpF+INR8okB5wN3A0MBP6JqvtK5wyi7abGMiADvBlrRCLdjBJUEekp/oMlp+9jvfreBewea0SSdGdiY+lugyWnZwCtsUYk5bQCq33RCPTBSsQ+GWtEknTDsN+WI4FFwIdQp0gim0wJqoj0JA9j1TVfBz4AzAc+EmtEkkQO+DY2bmF19Pd0NDxET7Qaq32Rb5P6R2z82z5xBiWJNBa4H9gXeAM4FvvNEZFNpARVRHqaZ4EjgHuB/lgnKFdivSyKbAsE2Pi5KeBq4FygJc6gJFY5rIOb70TznwDuAfaIMyhJlPOwz8QuwH+x6r3PxhqRSDemBFVEeqI3gXFYYgpwMVaaenhcAUkiHAM8AkzASs4+CXwZjXUq1nHS5Vib5HewsXAfB6ZiJavSM20L/Bn4PdZD/N+Bw7DO+URkMylBFZGeqhW4BPgwsBCr8nsv8Es0XmpPMwArKZ0LjABexG5WXB9fSJJQ/8Gqct6GdZx1KfBA9Jj0LBmsfelZtP2eTAaWxxmUSCVQgioiPd10YC9gGtb28EvAy8A3gNoY45Ku57COkJ4Bvhgt/wEYgzo2kY69iXWedAbWEc7BwENYc4FRMcYl5TEa6zgrCwwHngSOwmrk+BjjEqkYSlBFRGyM1M8BJwFPY9W2foy1Ifo0VnVLKsuJWHXev2A9b74UPXY+KgGRzmnAal78CUtMJmPnj98Au8UXlnSR7bCaFk9hzQBasKT0EOwGhYhsJUpQRUTa3AHsj5WMvIpdZF6LDbQ+FY2d2t05rOTrTuB2rORrGfAtrOfNO+MLTbqpd4H/AfbDEtZewOexGx4B1h5RurddgJ8Dr2A1LaqAGdh7fgmwJr7QRCqTElQRkfZC7EJzH+Cr2JA022NtzV7DEtYjYotONkcN1vPqo8A/gOOxi8qrsLFwrwCaY4tOKsEz2I2tcVj71BRQh7VPvRtLYvvGFJtsnoOAG7E26Rdh7999WA+9pwHPxReaSGVTgioiUtpq4BdYAnMO1mPnNliV3/uwqnwXY53qSDJ9AHsP38DGrjwAaMIS0z2xi873Y4tOKtF/sFL6A7Hxc1uwhOY64C2srfsHgXRcAcoGDcCaezyE9ex+NtZL8x3AKVhb03tji06kh1CCKiKyYS3YXfQDsWFIrgdWYiWsV2IdKj0CfDN6TOK1G/A14EGsrdhXgCFYSfglWHW9i7Bq2yJd5XGs1H5X7HP3PDbu8meBfwFvY8nqyagztrj1wXpz/wt2E+EPWLvSNdgQMgcDHwL+GVeAIj1NVdwBiIh0I/dE0xex6nwfw6r0jYmmH2FtV+dE039QhztdzWE3D8Zj1e4Kh/tYi7UDvBardqnxTKXc3sZuZP0Eu8H1cexzuh2WrH4WWIW1f56NtY1+MZZIe5btsZsDGeBU2le/fgo7Z9yEaliIxEIJqojIpmsC/i+ahgCTsDvw47ASvPOjKYcNV3I3bcnt22WPtvLshF3sn4glpkML1uWw8Uz/H/B34L1yBydSggfuiqYLsHPFR7B2qjtFf+uibd+m/TnjCexzLZuvD9Zh1TjsnDGG9rUIX8bOGQ1YjRgRiZESVBGRLbMIu9t+LXYRNA67ADoJa+d4UDR9Mdr+Jeyi827gYaxzldayRty9OKzq9NHRdAxWbbLQCqyN2Gysd00lpZJkOaya77+wG1n7Y+0bxwOHYzdczogmsFoY92FtH+/D2kYuLW/I3c4QrL3oMdHfMVhb0jwPzMM6TZsezYtIQihBFRHZelZhSdLsaHkH4FDsAulorF3T7tF0brRNC/ACdoGUn+ZH++qJdqAtqT8cO3aDi7ZpxY7T3dgF5t1YdV6R7uiJaPoJdl12AHa+OArrUGkwlsCeUvCct2l/zniEnls7owYb8uVgrIr/UcDe2M2tQguwc8UdWBOMhWWMUUQ2gRJUEZGusxBrAxlEy/2AI2lLWA8CBmIlhPtgnaqAJWDPYsOiPIl1uPIElXdBNYy29rv7YL3ulupoaiXwGFbyfC9WTXJZmWIUKaf8zZd5wNVYNdR9gWOx88ahwEislLWwWjBYBz+PYueK/DnjBSqrhsY2WJvz/PliDJaU1pTY9mXsfHEPlpS+XKYYRWQLKUEVESmfJqwnyMLeIEdid/4PKvi7A1YisF/R89+l7cIzPz2NlcImWW/sYvIA7H/aP5rftsS2OazH00exUqF7ovlKusgW6ayQtu/6b6LHBtJWyyB/3hiN3fAZBkwoeH4zdo7I7+NJ7GZP0jv/cdgQXvsXTAdg58tSI1C8i50n5gP3Y4np4rJEKiJbnRJUEZF4vUxbBx15w7CLzvxF2f7AHljPkx+Kpry12AXoY9H0KJbExtV78DDsovkA2sdeatzHfOzzsbjzsa8sS6Qi3dNS4N/RlNcH+64dSNv3bl9saJt8LYVCC2h/zngM64E8DvnYD8Di3x+7kdWvg+0X0Ha+yJ873uj6MEWkXJSgiogkz1vR1FjwWL4UMl+asB92MbctbSUpeR5Leh/FBpy/D6sy2LwVY0xhnUAdGE0HRX+372D7hbRVPXwymn8GtR0V2RpWAQ9EU15hKWRhzYXdsfGAdwHqC7ZfgiWq87ESyPuBd7ZynENoO1/lzx17UvoGVnHpb/78kfTSXxHZQkpQRUS6h9VYldfiIRDy7TgL22TtTVtnTB+JtmvFLu7uxZLVu9i0EpPtgCOwdnBHYheYfUtsl28/+xjt28JVWvtZ6YSJEyfuAwxLpVJPTJ8+/d244ylWV1c3Lp1OV82cOfOOuGPpAvkbVS9jvVvnbYNVCc6fL8ZgNTYGAcdH01ejbd+mre33POyGV2dvKvWK9ps/bxyGDalTylvYOeNxKrf9rIh0khJUEZHuLV/aGhQ8Noi2UoojsIRyKOtX9XsF69XydqwTkcLSkpG09SR6NKV7xVwBPIeVhKoHYllPLpf7qnPuU7lcbjLtq7EngnNuRhiGA7AaAT7ueMpkBW3f1xuix6qxm1wHYh0xHYmVug4FJkcTWDv6B7Ahcu7AammE0boBWE/l+fPGUVjNj2LqgVhENkgJqohI5VkC3BlNebthF4z5hHV/rPrfCOAc7OL8Laz951DWb/8VYtXt8mMxPoiVcISIJFB9ff3F3vsrvfdTGxsbL4s7noRroa308k/RY/1oGybriGgaQPt28MuxG1t9geEl9vsubZ0W3Y+Vkq7okv9ARCqGElQRkZ7h1Wj6c7TcH/gkcCZWalJD+wvMfML6b+AvWFKqoV1kk4Rh+H3n3O9I6BAfuVxunHMuTc8pPd0UTVhJ6b+i5RQ2LutnsWrA22Hnkf4Fz1mB1aL4K3Ab8GK5ghWRyqEEVUSk53BY9buPA5Ow4Wzy1mIXky1Y9d5+WMJ6NnZRejNwI1bCItIps2fPfg14Le44OjJ79uzH4o6hGxgOnAWcgTURKKzq/wZWSrodsDPWvvVY4HDgH9g5o5Gt20GbiFQ4JagiIpVvD6wa79lYVd+8xdjF40xsbNb88C7VwHHAaVjbs2FYpylfxdqM/Qa4hW520Tlx4sR9wjC8ELuA3h7rDfQVYGZra+v1c+bMWVOwuauvr/+o9/6TWPvbKu/9K865W1pbW6cVbUtdXd2hzrmvOefu8t7/EbgEuwmwHfAS8LMgCGYATJgwYe90Ov1t7/3hQB/n3APe+28FQfDfwn3W19eP9t7/wHv/xLBhw658++23LwI+ilXBft17/5vGxsYbACZNmrRba2vrt5xzx2LVMB8Lw/A7s2bNmle4zwkTJuybSqW+BzwUBMHPio9RJpM5GLjEOXdvNpu9uuDxk4DPOOeyNTU1M1avXv0t51wmOo4LvPfXNzY2/o6iksj6+vrzvffHA78IgqCwh9n8+uO9958FxmLje74LPOW9/2tjY+P0/Hbjx4/fqaqq6jSsaulI7ObK+8DD3vtfNzY2PlS03997748EcM5NzmQyH8ivc841ZLPZhuj/uh7oEwTBR0vEvkMYhhc558YDO2LVWR/03l9d/HrR9lO99/uk0+lvhmHY13v/LSxRqwYe9d5f3tjYeH/x8xKqL9bB2iew0tL82KM5rLruDOy8UVgyPgr7zH8Uez/ro2kx8H/A77Hvm4jIBpUa7FhERLq/FDAemIN1ZPQdLDldClwLnIBd5J8L3Er7sUdbsA5QPo+VntQDf8MS0jHAddhYhJfTvhQ2sTKZzGfCMHwcOB/rROoJrGfkY4E/1NTUDM1vO3Xq1FQmk7nJe38zdpzecs696Jw7GPhVVVXVv8ePH9+/6CWGA5O998di1aK/iZU0rcba8N2ayWTOzGQyR6dSqQe99xnn3FKg1nt/GnB3fX39sMIdOucGA5Odc8e//fbbWex493bOLQfGOuf+VF9f/6UJEybsm8vlHnbOnYV1UJUGTkmlUnMnTJiwd9E+d4j2eWSp4+ScGxr9H4cVrRoVPX5Mc3Pzfc65r0f/3zLgYOfcb+rr668s3l8YhmOj5xX33urq6up+7b2/E6tmHnrvH8c+t6c756YVblxVVfV14FdYDYA1WHvoPsDZzrl7M5nMmYXbe+/3o63H2HxP1/mp8DhPoq0DoHUmTpy4n/f+CefcxVhy+iT2vTjLOXd/XV3decXP8d4fB0xubW093Xv/ADDeObcIS1AnOOf+PXHixJLHPUFGAD8FXgeuxz7/AP/BqvbuiN28uor1q22/CPwM6yhpH+BHWOn5tsDXsTbrM6Lni4h0SAmqiEhl6QWcB/wXmA2cgpUMNWJV9IZiF5p30rkhHFqwHoI/il2cfhlry7od8C3sAvQa2l/0J0p9ff2xwB+wJOhTQRDsFATBiUEQHNzU1DTEe3+uc64pv/28efMuxKo0vgUcEATB4dls9tjq6uqRzrl5wBHpdPqqDl7udMCnUqmRQRDsFwTBSOfcFwDnnPsJcJNz7g9NTU2Ds9ns2Nra2uHOuX8CQ7z3X+tgn8cBuzjnPhAEwd7ZbHa0c+6jAN77y1Kp1M3AzNra2u2CIDh46NChw7Eq2dukUqnvbPkRbOdTwJtVVVU7BkGwbxAEezrn6rFje1Fxkt2RTCbzJefchcC7zrnjgiDYq7Gx8UNBEOxTVVU11Dn37aKn3OW9PzEIgsFBEIwJgmBcEAS7Ouc+gSXKfyi8aRAEwdHOuSsBvPdXB0Gwe34qLBkuZcqUKdVhGDZgpcPXtra27hwEwQlBEOztnDsTCJ1zv45Km9fjnPuR9/47Y8aMGZTNZsc2NTUNw24K1YRheHlnjk8MDsWSxxeBr2E3cV4Avo0lreOw/2FRJ/f3bPTckVipd0P0+ERgLjZ0TWarRC4iFUcJqohIZeiFVeN9FqtKtwdWJXEaNt5hBrtI3JJqucuAq7HStNOwjpNqgCnYhe0vsGqaieK9vwwrVby0sbHxOgqqcs6dO7e5sbHxhunTp78PVnoalQ7ivT8vCIKn89veeuutbwMfA3LOuXM6SMZawzA8a+bMma/nH8hms78FXvXe7+ScW5DNZi+eO3duK0BDQ8Nq59yl0aYdla6lnHPnZrPZ5wr22YCNSTkASDc1NZ3X0NCwGmDatGkt6XT6WxvZ5+ZaWVVVdW7+eEWxzMJuYqS994dubAfjxo2rxUr0SaVSH89ms3cVrp8+ffr72Wy2XQlqEAR/b2xs/Bftq+H6bDZ7U1Slun9VVdUpm/9vtXnrrbcmYuOEPjd06NALCqtzZ7PZW7Aq7lVYIldKY2Nj4y+mTp0aAsydO7c1nU5/HfvuHc76wzXF6XDsvXsASx4dVnviDKxq+4+w2hKbKyzY3z7A77DjcBSQxcZjPnwL9i8iFUgJqohI9+awTo9ewoaHGIlVz7sQKy39HFaaujXlsNKWo4BjsNLY3sBXoji+hCWEsZs8efIALEbCMLxmY9s//PDDo6PqqEvGjh07q3h9Npt9ERsuoyqq0lls/qxZs4qrPnrsxgHe+1uLn+C9fyaa3aWDsF7JZrOPlHg8/7xsPuHNmzFjxqtYdd/hkydP3prvxdzp06e/W+LxJ6K/u21sB/379z8CGAy8OHPmzDs25cXHjRtXW19fP6q+vv7YiRMnnjhx4sQTnXPNAM65fTZlXx1xzp0Yzf512rRpLcXrwzC8KZo9oXhd5G/FD8yYMWMpVtug9vTTT99xa8S5hfbEalXcD9RhtSn+COxFW4lnbiu/5vNYs4FdgSux6u/HYDe6/oZ1siQiogRVRKQbOwgrgbgJa2+3AKuCuyfwWyxB6Wr3YBfqJwFPYe3NfomNk1qyCmQ5rVy5cgSWLL87a9asJRvbPpVK7RbNvpovASvhpejviOIV3vuOeqxd2tH6bDbbhCUDgzp4bskSLO/9MgDn3IZesxrrWXVr6aiTmyVRLBstQffe7x7NPt/ZFz355JO3zWQyf+zXr99i7/0L3vv/hGF4exiGtwNfiPZb3C54szjndov+lhwap0+fPvmhU7afPHlyqWO7wWOUy+U6ep/LoS8wFbuhMAGrwn8jVsvi02zCe7IF3sU6Edsd6zzJY+2An8LOX7o2FenhdBIQEel+emNVbR/BOo1ZgV3w7RE9HkfvurdjCfPnsHZqY7Ak9cdYkhSLdDpdCxB1SLRR3vvaaHZDY77m19UWr3DOrVfiVqQz7X6Lldync84DhGG4OfvcLJ34/zqzj/xx69R7Mnny5HSvXr3mYOP2PoGV0E9yzh0XhuFY59wP87vehyroNQAAIABJREFU0tgAvPc1AGEYLu9gkxVEpYvNzc2lPgNlez82UR3WrvRSrGp+I1bt9pzo8XJ7G/gM1qnSvdh4qlcBd2PJq4j0UEpQRUS6l0OA+cAXsXN4I1b6cSU2lmmcWrE2r/tgVfaqgG9gPYCOiiMg7/370d9dpk6d2pnfvHwpa3Gvs+s45/JVERdvYXhll0+evPcd3TTo8tK9/HuCVfXcqObm5uOwTnzmDx069JggCH4VBMHMbDZ7VzSMzlatiuqcy5cGl/wMrF27dhhWKp9ramrqVJIdsz7YjassVu3/BSxZzWBtx+M2H6vqOwVowtpNz8MSZxHpgZSgioh0Dw7rWOY+rJ3Ym8DJ2EXmlnRi0hXew3r9PQNL4o7ALjjryh3I2LFjX8JKdGvnz5+/0SrH0VAnIbDraaedNrh4/dSpU1Pe+zHR4qNbNdgycM69Gc121Nvu/l0dQxiGD+Zfq4Mqsu147/eMZu8q1Sa04P0ofjzfNnWTSvC9949FsyU/L977Q6L9Plnc9jeBDsWGyPkiVpX2p8B+wHrtq2Pmgf/FPn//wTr/+hPWQ3hsNTBEJB5KUEVEkq8v1mnJD7BSyQbgAOC2OIPqhHycd2PV96Zj1TPLZurUqWHUyyve+5+NHz++poPtUgBRO9V/ANUtLS3fLd5u/vz5n8E6M1rQ1NR0b9dF3jVaWlpex0raD5g0aVK7apTjx4/fyXu/3vieW1vUidSdQL/Vq1dfUWqbwtLuVCr1VjS7XidI0RBC40vtwzn3RvR3t02JL5fL3YIlTB8rHkd23Lhxtd77bwOEYfiXTdlvDD6KDekyEuug6QTgYmwc2aR6FfggNkRNDitV/QfWqZaI9BBVcQcgIiIbtAswEzgQa1t6Hlay0F28AZyIddr0GawDpb2BC7CSyi6XSqV+6L3PAMdVVVXdV19ff1XUc+5AYF/n3Ccfe+yx07CLY1Kp1NfDMBznnPtSJpPZJgzDP1VVVa0NwzDjvb8YS16+1A1Kz9YzZ86cNZlM5m/A2blc7h/19fWXee/fwkquvoKVxn+gq+Nwzl3gvX/QOXdhJpPZ1Xv/v1Hp7g7AIfPmzZtEVILZ0tJyf1VV1SrgpEwm81vv/U2pVKrZe39ylCy+iA0L005ra+u8dDqd895PrqurW+Wcy3dudW8QBPd0FNvs2bOfz2QyVwNfTqVSd9bV1X3POTfPOTfUe//NKK5ne/fu/Zute1S2mhRwOVa93mE9bp+DVZ/tDkJseJvHgb9gCeuDWI2RlzbwPBGpECpBFRFJrg9gF2YHAu8Ax9O9ktO8tcBnsQ6UWqK/f6ZMN0mz2WxTa2vrcd77LHCw9/5GrMrxv4CrvffDwzBcnd9+5syZzzjnTgJeBj6dSqXuCsPwAaxUZznw8SAIZpQj9i7yFayDrVHRsfgX1jnNv4nGJ+1q2Wz2uVQqdQzW/jDjnMti78ls4LLCbefMmfOe9/5srHOiC5xz93nv5wNXOOf+BPys1GvMnj37Ne/9Z4ElzrnPYh12/bhgGJkO1dbWfs0591NgsHNuGjDPe9+IDa10Z3V19Qn5cWcTphq4Ges0DSxR/TDdJzktNAtrc/8c1mnSPZQoRReRyqMSVBGRZNofG+B+O+AxrK3pG7FGtOWmAW8B/w/4GFa6czale7b9OZYQbpUeiefMmfMeMPHUU0/ds6qq6mjv/XbAIu/9SytWrLinuDQ0m83eO2XKlL0WLlx4XBiG+2Cd4rxSW1t7R0NDw4ri/VdVVf27paVlbHV19fvF6yLfDsPw5wVDlBQ7NN8rb16vXr2eWLVq1VjnXMneZFOp1C9aW1tvSqVSJYeZcc6Nz+Vy1Vhit04QBIsmT558+KpVq050zn3AOdecSqXunjlz5pOTJ08esGrVqrGpVKpdB1Ctra0NqVTqwTAMF3bwWn/J5XJ3pdPptwsfD8Pw+86532HJfjszZ858EhibyWTGOufGhmG4DbDQOfdUEATzC7dtbGycnslkRgDHASOcc4tzudzcWbNmvZzJZIaEYfhoVVXVeuOzNjY2XgdcN2nSpIEtLS07ATWFMeZyuXHOuTRWKr5OQ0NDDrj49NNPv6q1tfUEYFgYhstTqdSD2Wy2ZNvjXC73Oedcv1Qq9Wyp9cAnwzDs29TUVHL4mq2gF3ALcBpWjfd/ouXu7HngWKyX8P2xquEnAE+X2PYUrHfimWWLTkS6hLvmmmvWnZSdc6OnTJlSjjGwRER6uv2AHwITS6w7CGtfOgQrVTqJbthj7AZMAv6KXVDfCJxL+wThbKykeB+s9EREzJ3Ap4iqoxfohX2nJmHJ6WQgKGtkXWsIdsPuAKw2yZG0H292EFbVeyZ2fESkG5k2bdqe3vt1v/eq4isiEo/RwKlYclZoFFZaMAS4HystqKTkFKxN3Iexqr+fAAo7IzoWq266gk4OQyLSg4zBOh8rrAHngJuw5HQV1lt2JSWnYD1xfxDrOXtH7P8bEK3bBqumPgCNnypSEZSgiojEYzR2kfkz7MISrBSgEeuxMt8pyLJYout6jVhbVICpWKnp14G/Y8n5NsBucQQmklD9gNVYJ2PTsVJTsN69J2Mlp3VYSWMlWozd1Hsda5//VyxhfxTYF6uGPzy26ERkq1EbVBGReOSHrxgCXAvUY8NBjMaGhJhI9+zYpDO2BXoD/8Sq+H4CuAG7+O4TbZOiDL3JinQju2KlpX2xmhVPYN+bb0XrP4t1dFWJqrAezZcCX8Da1p6M1bjoXbBdbflDE5GtTQmqiEg8RhXMD8aq+qawsf9uBcZhJSSPAU+WO7gudj5W6vMuVurhsQvvPkXb7VnmuESSbFfakrHe2M2sH2LfnYejv2dg36eGOALsQrtgCXkr1nFaOnq8d9F2VViSulU6VxOReChBFRGJx/ZFy/kmF2lsGJC12HiAx5UzqDK5HLuI/DxWrbkju5QnHJFuYSRW9b2Qi/4eAvwRO2dcS+UlqC8Dh2G1LjZWjXdn4IUuj0hEuozaoIqIxGNjVdEWA4cDD5Uhljh8FytFXbqBbfqVKRaR7mBf2hLSUlZgQzldUJ5wyu5p4BisCUTYwTa1qHM1kW5PCaqISPltQ8fnX491AnIM8HjZIorHVVhHSYs6WN+Ltqp8Ij3dHhtYtxi4FLiwTLHE5RXsxt1LlB4/uR8woqwRichWpwRVRKT88p2dFAuxqmxHYGP69QR/A84C3utg/dAyxiKSZDt18Pj7wJeAq8sYS5zeAQ4FnsGaQhRKYeMni0g3pgRVRKT8Cjs7yWsB/ou1s3qz7BHF63ZseIyFRY/XoHaoInnFnYiB3dj5H2wc1J5kKXYj7xGs9+9Co8sfjohsTUpQRUTKb3fad3ayGuut9zCsNKQnegj4IPBGwWP9UXsyEbDq7r2KHnsXOB0bU7gnWgUcD8ylfa+9o0puLSLdhhJUEZHyO4i2Kr5rsAuso7BOTnqyZ7C2t29Fy6quJ2J2ov1NrXeADwH3xBNOYqwFJgA3Y0N0wfo9HYtIN6MEVUSk/PKlgi3YmKd10bzAq8DB2DAROWCvWKMRSYZdaWtv+S5wNDYuqFjHcp8CfgoswYZQVOdqIt2YElQRkfLbGVgG/BbrIKijIRN6qoVYJyj/RVV8RcC+B9tgN272x3qxlfa+iSWpQ1DnaiLdWlXcAYiI9EADgB9Hk5S2FEtSPxR3ICIJsAfwLFZyuizmWJLsCuBJdIxEujUlqCIi5XcYVpVVNmwVMDPuIEQS4NfAD2jfGZCU1lM7jRKpGEpQRUTK79W4AxCRbuWduAMQESkXJaiSeN5719jY+ELccWzIFVdcscMLL7xQA7B69erlK1asWBp3TEX6AwOj+bUk72KnBtihYPl1rOOLxBgyZMjOzjkHcP755793yCGHFI+9lyQ3ZjKZy8rxQtls9u/Ouf3L8Vqb469//evA2267bQBAS0tL85IlS4rHWo1bLe0/+6/FFcgGFLYDXkjySvF2wI4jWNXORJ1/+/btO6Bv374DAXbZZZc1l156adLOv+2sXr36oDPOOKPLexQPguAE4A9d/Tqba82aNe6CCy5YNw7z0qVL31m7du2aOGMqYUfs9xPsc5+0qs0DsSYtYOeNRJ1/a2pqagcMGLDu/Hvttde+Fv3MJ9UnM5lMj+i5WwmqJN5ll13mxowZs3vccWxIU1MT7733Xn5xcDQlVTU2DmeSjYw7gGKLFi1aN5/L5YbFGEpnbFfG19qFBI872NzczLvvvptfrAb6xRhOZyT2WEZ2ijuAjRgSTYmxcuVKVq5cCUD//v2rSfh7PGjQoLL0gOu938Y5l9hj4b0vPHeAdW6XZNtR3nP/pkrc+XfNmjXt3mPv/agkJ6jOub5xx1Au6sVXREREREREEkElqNId/cI591zcQRRqaWm5CugDsMMOe725cOF2N8QcUpF5H4NVI2y+Zi0c+vN44yn2ygHwxqlty4f9CnqtjC+e9VVVPfDN1lYbqnTBgpX39+8/eG68EbU3YsTSD/fundszzhiWLq35z5tv9rk/zhiKLVmy+hPAcIBBg4Y1L1ky8pcxh1TkxcPgnePblo9OYM/O91zSNr/bv2GnB+OLpZT7vgxhVMV30FvwgUSdf3fccelH33nnqREAuVzY8vTTgxJ1/u3fv2XozjuvODfeKFzL008PTNRxaW5e2hf4Qn55yJDD5yxaVPV4jCGVcN9FEPay+cGvwt63xBrOeuadDaujWhe1a2DsVfHG097226895N13Hzohv9za2vr56urqXJwxFXPO/R5IbrFuF1GCKt2O935WJpO5M+44Co0aNepKogR1yJCR7y9cOGtGzCEVGXxCW4JalYO7Ehbf8WH7BPV7c+DUxfHFs75Uqvc3wRLUV19d9fyNNx6RqGN40023HxV3grp4cc3Tl1xy1PQ4Yyh22GFrJhAlqH37DmpZsuTuRMUHY7Zpn6AmLT4AV5Cg7vE03JawGKsvaEtQ+y1O2jHcbrsPjytIUHNJ+4586lPP7BN3guo9iTsuO+10/7YUJKjDhp0yf9GiS7MxhlRC1Zfa5ge+l7TPPgwa35ag9mpJWnzDhl1SW5ig3nLLLdc2NDSsjTOmYkEQ/I4emKCqiq+IiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEZSgioiIiIiISCIoQRUREREREZFE0DAzItAX2ANIA6uBZ+INR0REREQSLAWMBsYCY4C9sOvIZ4AvbeB50glKUKWnupC2k8re2EkF4Elg/7iCEhEREZFE6wMsBLYpsa5vmWOpSEpQpaf6ddwBiIiIiEi3k6ItOV0AzAP2wUpUZStQG1TpqZ4ArsNKUo8Abo43HBERERHpBtYApwI7ALsCpwOPxxpRhVEJamX6GtamEqABuKMTzzkXODKa/w/wly6IK0kOKFr+bCxRiIiIiEh30gLMiTuISqYEtTJlgGOj+efoXIJ6HPDJaL6Vyk9QRUREREQkYVTFV0RERERERBJBCaqIiIiIiIgkghJUERERERERSQQlqCIiIiIiIpIISlBFREREREQkEdSLr1SSbwGf7mDdPti4VSIiIiIiklBKUKWSbAuM7GCdK2cgIiIiIiKy6ZSgSiW5AvhdB+tUeioiIiIiknBKUKWSvB9NIiIiIiLSDamTJMlLxx2AiIiIiIj0bCpBrUytBfPVnXzOtl0RSIL1BXoVLNdEf9PAoILHc8DycgUlIiIiIol3AXBAwfLY6O9I4JqCxxcAl5crqEqhBLUyFSZUnU089+uKQBJsGnBWicf3ARYXLD8PjC5LRCIiIiLSHZwM1Jd4fAdgSsHyfJSgbjIlqJXp9YL5gzqx/eHArl0Ui4iIiIhIJbkBuK8T2y3s6kAqkRLUyvRIwfw4YGfaJ62FqoCfd3VACfTxaBIRERER2RR/jzuASqZOkipTI9AczVcDf8LaXBbbFmgAjgR8eUITEREREREpTSWolWkx8HvgK9Hy8cB/gb8ALwK1WMPuDwMDgeeAZ4DTyh6piIiIiIhIRAlq5foucBhWOgqwE3Bxie1eATLAN8sUl4iIiIiISEmq4lu5VgInAT8DVnew/lrgYOAFYBWwJJpWlSlGERERERGRdVSCWtlWAl8HvoeVpA4HHNZh0iO0H47mwmgSERERERGJhRLUnmE18K+4gxAREREREdkQVfEVERERERGRRFCCKiIiIiIiIomgBFVEREREREQSQW1Qpdtxzn0zCIJPxR1HoW984xt98vOvvz5/Zxh+WZzxrK9p97b5Nb2SF9/Kndovf/rrkFobTyyltba2rJvff/+Bx3z603fsEGM46+nTp2WvuGMYOnTliddff8fIuOMo1NDQd+f8/OLFb9Qm77O/fET75aTFV+yRD8HwUXFH0V6ud9v8op2Sdgxfe82vO15VVenq66+/I1HxVVfnBsQdA/heSTsuq1ev6HX++W3LL730fxNh2pj4Iiol7NU2/87IpH32YcUubfOrE3f+ffHF1G6Fy2efffb155xzThhTOB1xcQcQByWo0h2dGHcAxdLp9Lr55cvfGQScEl80G9OahrcSHB/AOx+MO4JiYcFP1sCB1SMHD25OVCKWBL175/bs3Tu3Z9xxFOrdu3rd/KpVy6phWcI/+0n/bi4ZbVNSrRoIqxJ1DJcX9JefSrn04MHNiYovCZwjlbTj0tzc2m555crX9wX2jSeazlg5GFYm6hi211KVtPPbihXrPXRmDGFICariKyIiIiIiIomgElRJvEsvvdQ3NjZeF3ccG7LLLrvsV1VVNQDg/ffff33BggWvxR1TkZ2BXaP5JuDxGGMppR9wQMHy/UAuplhKOuCAA45IpVJpgJqammeB92MOaUPuL9cLpVKprPf+yXK93qYaNGjQbgcddNBOAKtWrVr63HPPPRV3TEUG0r5U5p64AtmAowvmnwKWxhVIB/bFjiPAG8Cr8YWyvuHDh++0/fbb7waw/fbbrwAeizeiDVuyZElZmlek0+nXwjBM8m97+qCDDjoiv/Diiy8+3tTU1BRnQCUcgP1+AryGjXOfJLti1x8Ay4BE/VYMHDhwwIgRI/bLL6dSqSSef9cJw/CNuGMoF3fNNdf4dQvOjZ4yZcrzcQYkIiIiIiIiPcO0adP29N4/l19WFV8RERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKCKiIiIiIhIIihBFRERERERkURQgioiIiIiIiKJoARVREREREREEkEJqoiIiIiIiCSCElQRERERERFJBCWoIiIiIiIikghKUEVERERERCQRlKCKyJb4CfAI8JG4AxGRLrMf9j2fEXcgItKtjMHOHQ1xByLdS1XcAYhIt7Yr9gO0Y9yBiEiX6Y19zwfHHYiIdCt9sHPHNnEHIt2LSlBFZEvkor/pWKMQka7UGv3VTW0R2RQ6d8hmUYIqIlsin6Dqx0ekculGlIhsDp07ZLMoQRWRLZG/O6ofH5HKpRtRIrI5dO6QzaIEVUS2hO6OilQ+3YgSkc2hc4dsFiWoIrIl1L5EpPLpRpSIbA6dO2SzKEEVkS2hHx+RyqcbUSKyOXTukM2iBFVEtoSq74hUPt2IEpHNoXOHbBYlqCKyJdQBgkjlUymIiGwOnTtksyhBFZEtobujIpVP33MR2Rw6d8hmUYIqIltCd0dFKl/+ItOh6wYR6TzVspLNoh8aEdkSujsqUvlaC+b1XReRzlI/FbJZlKCKyJbQj49I5csVzKskREQ6S7UvZLPoh0ZEtoSq74hUPpWgSrdXV1d3aDqd7h+G4X1BEKyKO54eovjcEcYViHQvupshIltCVXxFKp9KUKXbS6VSvwvD8Hbv/fC4Y+lBdO6QzaIPi4hsCXWSJFL5VIIqW0UmkxkCvAe8GgTBiK213/r6+tO99393zt2QzWbP3Vr7lS2mc4dsFl1UisiWUAmqSOULAY+1I9N3XbqlXC73CaBPGIYL4o6lByksQdW5QzpNCaqIbAklqCI9Qw67ZtB1g3RLs2bNejbuGHogVfGVzaIPi4hsCVXxFekZ8gmqbkZtwNSpU1OPPPLIZOfc2cD+QG/gHeAR59yN2Wz234Xbn3zyydv26tXrIqAOGA6sBh4GfhsEwZ3F+89kMl8DDvXeX55Op8MwDL8DHAHgvb+3qqrqOzNmzHgJoK6u7uPOufOAPYAVwP9ramqaOnfu3OaifX4GOMk595tcLvdeKpX6DnAUUAM84b3/SWNj479KxPJnwAVBcFapY5HJZP7mnFudr3KbyWTO8N5/3DkHsF0mk/lbweaLgiC4INpuiPf+NOfcKcBoYAdgJfCY935aY2Pj7MLXqa+vnxqG4Yecc3jvjyva791BEPw62u+PgZHV1dVfuvXWW98u3Mf48eP7V1dXf8l7PwnY2Tm3xnv/mHPuD9lsdlbx/1ZXV3eec+6DqVTqly0tLW+m0+mpwHHANs65/3rvfx4EwcxSx6WHyaHaF7IZ1EmSiGwJlaCK9Ay6GbURkydP7j1v3rzAOXcLcCqwCHjSOVcDnOO9/37h9pMmTdq9V69ejwLfBnYGnnDOvQ+cDvwrk8l8u8TLHAFMBiaFYfggcBLwNpYYfSyXy91dX1+/QyaT+YVz7iYs6X0r2v83+vfvf2OJfR4U7XNiKpV6GDgeeNo59w6WuN6eyWQ+XeJ5pwMf3tAhiRK+vGHOuQOi+RpgTMG0X8F2ZznnpgEnYp+7J5xza4CJzrlZxcfFe7+nc273aHFw0X7XtXN1zp0ITF67du02hc+vq6sbXl1d/XD0/uwOPAUsBCZ47xszmczPiv8x59zY6P87KZ1OzwcmO+cWA6u998cA0zOZTMnEvQdSb/+yyZSgisiW0EWrSM+gm1Eb0dzc/EssMX3aObdPEARjgiA4IZvNjvbe7wr8rmBzl8vlbgZ2Af4K7Bxte5BzbjxWkvqDurq6E0q9lnPuu8BlY8aMGRwEwWFr1qzZGfgXMNR7Px04BzghCIKRQRAcHIbhGGCp9/4jEyZMGFNqn977LwMNtbW1uwVBMCGbzR4EfAR7739TX18/akuOTxAEvwTGRotvBEGwe8F0TMH/9qRzbmJTU9PgIAgOLDiGxwPLgO+feuqpexbs9yzn3AXRc28t2u9FnQjteu/9nsDs1tbWXYIg+GA2mx0LHAssB76ayWRKJuLe++8Af2ptbR2czWbHBkGwK/BNrMTwx1OnTtV1ts4dshn0xRGRLaEfHpGeQaUgG5DJZEYAnwbWAJlsNvtc4frGxsY3gyC4uWD744FDgDeBTxWOy5nNZv8B/ApwzrmLO3jJ/wRBcOXUqVNDgNtuu21lGIaXReuOcM59q7CK8KxZs54CbgRIp9NHdLDPpWvWrLmwoaFhbf6BIAj+7r3/A1Drvf98Jw7FFstms//OZrPZuXPnFvYAS2Nj41zv/eVAKp1Of2RrvFYmkzk4KlldEobh2XPmzFmeXxcEwT3AFdHiNzrYxRO1tbVfnzNnzpr8A7W1tT8FXgN2fvjhh0dvjTi7OZ07ZJMpQRWRLaEfHpGeIZ8s6GZUCVF7yTRwexAEr3TiKSdEz5tRmJzmhWE4LZo9dvLkyb1KPP/vxQ+kUql1nQB5728tXu+9fyaa3aWDmG657bbbVpbY7y2FMZfL5MmTe02YMGHkhAkTjpk4ceKJEydOPNE5lwZwzu2zNV4jSk5xzs2eNWvWkuL1YRheE82OnTRp0sDi9d77WxsaGgo7AiJafgoglUrtvDXi7OZ07pBNpgRVRLaEfnhEegbVltgA7/3uAM655zv5lN0AwjB8udTKQw455FVgLVC7cuXKocXrnXOvFT/W1NS0NJpdGQTBohLPWRa95nqJVrS+ZCxAPuHeauOWbsi4ceNqM5nML5qbm99LpVIvpVKpu8IwvD0Mw9uJSjS99/23xmtFVa/x3pf836Ok9T3ArV27drfi9alU6tUOdr0EwDlXuzXi7OZ07pBNpgRVRLaEfnhEega1N9+AgkRk6QY3bFMTPW95qZVR1d0VhdsWyuVyrcWPFdjQug1pKvVgTU1NPsayJFv9+vW7AfgK8Ib3/mJgknPuuDAMxwLnRZu5rfRyNQDe+5L/e2Q5QHV19XrvA5t/rHsSnTtkk+nDIiJbQj88Ij2DbkZt2CKAMAx36+T2+RK2nUqtPOmkk/oC2wKk0+nFWyG+jfLeDy/1eHNzcz7G94tWtQK9p06dmsq3hc2bMGHCoM2JYdKkSbvlcrnJwFu1tbVHNjQ0LCtcn8lktkrV3gL5ar0l/3csER4OkMvlyvI+VCCdO2STqQRVRLaEfnhEegbdjNoA7/2DAM65I+hc6d6j0fNK9qjbq1ev46LZ10tV1+0K3vsjO1h1VPT30aLH3wTSDz300PbFTygYTqad2tra/BispdrV4r3P9xQ8rzg5jdaXPF5hGDZHf0vudwMejeIdW2plXV3d4VjJ8bKxY8e+tIn7FqNzh2wyJagisiX0wyPSM+hm1AYMHTr0DuBVYO9MJvOFUtsUDjninPs71uPv+Lq6una96o4bN67KOfedaPHPXRPx+pxzJ2YymcOLYqkFvhqtv6XoKS8BpFKpdkOwTJkypdo5dxklNDQ0rMCGihlSX1/fr8Qmb0V/9xo3bly735VTTz11T+dcqfFYSaVSb0Qxjiy1viOtra2NWNXmo+rr608pXDd16tSUc+570eItxaXE0mk6d8gm00WliGwJ/fCI9AzqsXsDpk2b1pLJZD4N/AP4ZSaTOdA59zfv/ftYFdHj5s2bNwrIAGSz2YWZTOYHwA+dc7Pq6+svC8PwfmCIc+4i4AhgQTqdvrKM/8ZLQLa+vv47wAPAMO/9t4G9gUeWL1/eLll2zt3ovT/VOffT+vr6/mEYPgTs8vbbb1/Ahtur3g+c4r2fU1dXd7tzrtk5tzybzf5+2bJlz/fr128BsEe/fv0a6uvrf9Xa2roklUodFSWLbwB7Fe9w+fLlz/fr128xcGhdXd12xFpHAAAVo0lEQVTNzrmnsBuoTwdB0NhRIHPmzFmeyWQuAX7rvW/IZDI/TKVSc8MwHDBv3rwLgVOAd3O53NROH0UppnOHbDKVoIrIltAPj0jPoB67NyIad/QU4GXgk977OcBDwHTgy0Sd7RRs/yPg29gYo790zj3onJuFDedyfzqdPm7GjBmd7XRpa7gCuMN7f433/vEo/qO99/c55+qKxyXNZrO3AL+O4v+Rc+4O59wfnXNVuVyurqMXCcPw8865u4EjnXNTgR977y8BmDt3bmsqlToDWAhM8t7fmU6nH3XO/Qa42zn3lVL7nDt3brNz7mPAi9HfHwI/Bj66sX86CILfAV+MFn8chuEDwD+xmwmPhmE4bvbs2e9sbD/SIZ07ZJMpQRWRTVGciHb0w7N9iW1FpPso/v6Wqi2RAnYsTzjdQxAEdzY1Ne3lnDsO+DzwFefcmc65PYIg+HjR5j4Igh9VVVXt7L3/mPf+q977851zhwRBcNSMGTNeLd5/Op2+OAzDsVFpaztz587NhWE4NpfLjSsV29q1a/8ZPffyUuu99y1BEJzlvT8QOM8592Xn3HFjx449JpvNLuzg//1iGIb7R3F/OZVKfaimpmbs7NmzX4tiOa74ObNmzXo5m80eW1tbW5tOp0eEYTg2lUqtS2hnzpz54Jo1a3b33k/AevP9TBiG+wVB8JGampp7wjAcWypRzWaztwdBsAfQF9g76vU3X0WXXC73iSimBSX+j1+n0+mdgY8AF2Hv3RFjxowZO2vWrGeLt8/lcj8Iw3DsmjVrbit1XIDvRf/XXR2sr2SdOXek0blDNsBdc801ft2Cc6OnTJnS2TG8RKTn+QlwLHA+1rnEOODfwDPAB4BBWHulr2LVwl6NI0gR2SLbAi8AlwH/C6wGHgbGAhOAOcAHgd8DdwMl2wVK95DJZH4LXOC9P7exsfGGuOORbm1H4GngO8B1QDPwBLAfcCJwJ/Ah7NzxT+CCeMKUpJk2bdqe3vvn8ssq4RCRTfFn7Afln9hF69vR4ztjP0LbYxe3r6Hk9P+3d+9Rctb1Hcffs5ck5LZgkAYwgDXREBOMiEhpvWCItVYkeOmRHoxaFeyBY1UsJV6jHEtVopYeL8mxogVKKZATslC1hFBPhMZCIiRcAkFNsoZLICHJJiHZS57+8ZvJPjM7M3thd57f7L5f58zZ32+eZ2e+2cw+O5/5/Z7fI9WrXUAb8A1gEeG8v1Py2/6REFqPApqBn9S+PEmRegbYASwBvgJsAwqXKbqG8B7hKEL++GkWBao+GFAlDcRDhFBauBTASfmvkwifkAJ0Aj+qcV2ShtY1hFGOqRRPxUtfPmQ78KtaFiUpekuA7wJ/lL8VzE212wjnZ0tleQ6qpIH6AeHyCJXswk9GpXp3K3CgyvYEaM1/VX37DXBLQ0PDlqwL0YhwE7C/yvYEuA2PHarCEVRJA/Vj4AqKPxlN206Y5iOpfh0EVgF/XWH788D3a1eOhktra+uPcNaLhs5+4F7gggrbnyOcJiBV5AiqpIHaDTxcYduL+KZVGim+Qwii5ewHNtawFkn14xpgZ4VtewgLK0oVGVAlDcY3gBfK3L+XMDVQUv17gJJrd+Z1A/9e41ok1Y/7gH1l7u8Crq9xLapDBlRJg3E3YbS01CbCp6OSRoal9D7nfCdOCZVU3XVAR8l9O/P3S1UZUCUNxmHCCEp36r524NpsypE0TP6VMK0/7Tng9xnUIql+/JDex45nCJetkqoyoEoarO9R/MdnH3BnRrVIGh47gcdS/S5CaJWkap4FfpvqdxJmZEh9MqBKGqwthD9ABb+m+uVnJNWnbxHeXEKY2n9jhrVIqh/fpPjYcXOGtaiOGFAlvRTXEFbz3IPTe6WR6ueE6xsDbAZ2ZFiLpPpxBz0LKj5Kz3FEqsqAKuml+A/C1N4DwC8zrkXS8DhMGPnoxA+iJPVfF7CCcOz454xrUR0xoEp6KV4EVgP/RXgTK2lkupawKNptWRciqa58hxBQb8+6ENWPpqwLkFT3/g7DqTTS/RZ4PeWvbShJlWwC3kD5S9NJZRlQJb1Uz2VdgKSa2JR1AZLqkscODYhTfCVJkiRJUTCgSpIkSZKiYECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKXmZGdWHFihXTsq6hmhUrVkxpb28fC7Bjx472NWvWtGddU4mJwOR8+xCwM8NaymkGXp7qPw0kGdVS1nvf+96puVyuAWDu3Lm75syZczDrmipJkqT9ggsu2F2L51q+fPlxDQ0NY2vxXIOxZs2aSVu2bJkEsHfv3kN33XVXbK/9McCxqf5TWRVSxQmp9vNAR1aFVDAFKLwG2/O3aJx++ukTX/nKV04GmDRp0qEFCxbE9hoscv755/8hl8sN+/H3nnvuGbdnz56X971nNjo6OnI333zz8YX+/fff/9y2bds6s6ypjPRrfy/xXac46vce06ZNG3PmmWceOf5+6EMfivH4e0RLS8tz55xzTrTvPYaSAVXRW7x4cUNjY+O2rOuoZt26dWzcuDHrMjSMli9ffqQ9c+ZMGhsbM6ymT98DLqvFEzU1Nd2Zy+XOqMVzDcbWrVu57bbbsi5Do9j69etZv349ANOnT+d973tfxhVVt2rVqqOBPcP9PO3t7X/e2Ni4YrifZ7ByuZzHjhGura2Ntra2I/2FCxfS0BDv5NL9+/e/E/hF1nXUQrz/C5IkSZKkUcWAKkmSJEmKglN8VXeSJFmYy+XWZl1H2sGDBx8gf57F9Olv2fTkk+d/MeOSSnzty7DntNAefxCuuijbekpdPw8e/Nue/mc/BicO+xSzgWhu/vytnZ2HANi8efPSs846a0nGJZX6PnBuxjUsAZZmXEORHTt2/CcwF2Dq1Ffve+aZSz6SbUWlli2Ax1O/j0ven10tlVx+a0/7jTfAByOblnnFT6B7Ymif8ARc/vlMyykxY8bPvrh586q5AJ2dnS8Cr8u4pCK5XG5OkiRZz2WN7ueyZcuWY4H7Cv3p0z/6gyefnH13hiWV8fc3wOFxoT1tI3z6q9nWU2rxVdB+amhP2A9f+3C29RSbMePBd2/efP1HCv329vbXtrS0xHae8SZG4YCiAVX1aPt55523Oesi0qZPn3640B47dmIHfLat2v619/XUSfW5JL76WncV9+c9Be/aVX7fbORyXzjS3rt37wuxvQbvuOOO/UmS+bpSO2P7uZx99tlHXvtNTc0RvvZvLFnMKrb6AC5PtY/eHV+N/3C4p90U3fF33Lh7j7wGkyQ5HNvvyMqVK4/O5XJZl5HE9nO58MIL96b748efvCu21xZckTrojzkYX31XpRZUa4zu+DthwpVFx9/bb7/9yVtuuSWqReBaW1uzLiEToy6RS5IkSZLiZECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKBlRJkiRJUhS8zIxGo0bgNcAbgDPyX4/Pb/sEsDqjuiRJklR/JhFyVRfQnnEtdc+AqtHoKmBRhW3ja1mIJEmS6koDMJ/igY6T8tv+Fzg7o7pGDAOqRrOtwHqgDfhUxrVIkiQpfuOBn2ddxEhmQB2cBuCPgROBHPA08PgQPOargOOAo4AXgCeBPS/xcdXbUuDbwPP5/gwMqJIkSeqffcCDwLr87SPA27MsaCTJKqCeCXw/394HvK0f33MCsDLVPxfYPbRlFfkCcEG+fQewGBgDfA64GDi5ZP82YAnwPcL88/56NXAl8JeEcJrWBdwHXAO0VnmMqwlTDQBuAL5bZd9vAeek+ldQ/ZzLXwBT8u3PAGuq7FsvtmZdgCRJkurSfuBooDt137szqmVEyiqgTibM14b+jxCOTX0PDH/tJ6WebyNhEZ0VhHBdzjRCMDwH+ADQ2cfj54CvEIJwpX9LE/CW/O0WYCFwsMx+21O1dlE5oObyj5EOwudROaBOB96Rbx8GHq2wnyRJkjQaJBSHUw0xp/j2zzhgOSGcdgD3EELrAcL00POAifl9zyeMSn69j8dcBnw81d8N3EkIgfsJI8bvBmblt3+AMPX3PYRfjLR0wDyD8KlOudHlOfQepZ1Xpcb0tgeBnVX2lSRJkqSXxIDaP+8n/Kx+RRiB/H3J9hMJJ0vPzvevAL5DCLDlfJLicPovhJHU0mWpFwGXEc6XbCQE1svy+6c9CjxFCLWNwFuB28s8bzpwHiKMSs8GpgLP9LH/3RX+LZIkSZI0JBqyLqBONBFGTN9B73AKYYrthfSMbE4G3lXhsY4hnAda8G3CAj3lrpl0GLgW+FLqvkWEYFkqPYp6boXnTgfOpfmvOcqf1N1A8bmqBlRJkiRJw8qA2n+fBl6ssv1hYG2qf0aF/S6mZzpwG2HktC9LCCEYwrmw7yyzTzpAlpu220w4lxXCisM/7WP/1wHH5tsdhNFjSZIkSRo2TvHtn6eovtJtwQPAn+Tbp1TYZ0GqfSPlFz0q1UFYxfeT+f6b6T2FNx1QTyVMO96euu9MYFJq38I5pVMoH1DT960lnBcbs6OofKmYezFgS5IkSdEzoPbPb/q5345Uu6XM9vEUr0R83wBq2JRqzyqzvQ14gnDZGgjTdq9PbS89n/QwYbGn9xMumTMD2Jza5+0l+8duPPBPFbZ9FQOqJEmSFD0Dav+80M/9OlLtMWW2v4Iw1bbgm4RLzfTHlFT7ZRX2WU1PQJ1H+YDaTQimAKsIAbWwvRBQx9AzHRjqI6C+CHyjwrZ7a1mIJEmSpMExoPZP1xA9zjEl/ZmDfJwJFe6/m55pwOkR0wnAWfn2enoCd3ra8jzgh/n2m1LP0Q783yDrrKUDwJVZFyFJkiRp8AyotdVY0r+D6gsvVdJW4f57CFN3GwijtTMJU4P/jJ4R3fRo6GZgK2GK7zn57ztMcbhdA3QOokZJkiRJGpB6CqjlpszWm+dL+l+m/+e39sdOwuJHp+f78wgBtdr1TFcDHyVMIZ5LGGH1+qeSJEmSai6ry8ykV64d18/vOW44CqmxpyieLjxnGJ6jdNpu+utBep+Puapk/4mEKb4FIzGgngLclbr9JLXtqpJtb65xbZIkSdKoldUI6p5Ueyxh0Z9dfXzPm/rYXg/2AffTcyma84F/G+LnuBv4XL79NkKwn5vv30fvKcWrgQTIAecCj9CzkNNzwIYhri8GEwn/1nLmlvR/WHYvSZIkjVY3An+R6hfWbnkjxZlmA+H9uAYgq4D6O8JqsoVzMs8mnI9ZSQPwN8NdVI3cSnFAnQ08PISPv4awmvAYwqJMl9MzUr6qzP7PEELpbMK5qk+kthXC60jzFHBJP/ddP5yFSJIkqe5MpPfipxCyVfr+SbUpZ2TJKqDuJ3yi8Pp8/1KqB9QvAacOd1E1spSw2uzLCQH9ZsI00r5GkAumEa63eqjC9v3AWnouE3NZalul6bp3EwLqeIo/CFhdfve6twtYlnURkiRJqkuXAJ/px36V3q+riqzOQYXia3S+E7iGMN037RjgWmAxYXrsSLAf+DhhtVyAWYRRuguo/P8xhjCN4Abgt/T9aUw6iI7Pf30BWDeA/UvvlyRJkhRmIP6uH7ftWRVYz7JcxXcpYeT0Vfn+5cCHCedJ7iNcJuVNhNB6EPgEcFPtyxwWKwn/3iWEUHoysJwwMvpr4A+EAHs0MB04DThqAI+/GvhqyX3/Q5hWXc4vCYs3pV8PWwhhWJIkSZJqIsuAegBYAPw3cHz+vmOB95Tstwu4iHC5lJHku8DjhEV4TsrfdxxwXh/ft4W+pwv8mhDyJ6buqzYaupfixZv62l+SJEmShlzW10F9mDA6uAj4AOH8yoJnCSOm3wbaCOHtltT24Z7TvS71fPf383s2pb6nPwsf/QyYQQjgCwjnjbaU7LMHeJQwyvkzwiJIfS1c1EkYnZ1V8lzVLCWM3BaMlNFqSZIkSXUi64AK8DxhuuvlwBRCQNtJ8aVoIEx//asa1rWMgS+kszJ/G4gO4Mf5G8Bkws8hRxg93j3AxytYPMD9f5q/SZIkSVImYgioaTvzt9Fsb/4mSZIkSaNKlqv4SpIkSZJ0hAFVkiRJkhQFA6okSZIkKQqxnYM6GI3Ax4bosdYDDwzRY2mY5HK5m1tbWzuyriNt0aJFkwvtTZtWnQrj7syynt46J/e0D4yLr76uscX9BTdAQ1+rVddUZ2fPS27u3LmXXXrppQszLKeXJElelnUNwJWtra2XZV1E2nXXXXdsof30049PjPC1X3KN69jqK3XPR2HcB7OuolhX6pJq22fG9jN87DGOHH/HjBkzvrW1dXuW9ZTRnHUBwFGx/VwOHDjQcNNNPRc0eOSRqz8FV1+SYUlldI/raW+ZG9trHzpSV6ZonxBbfRs3Mi7dv+iii36/cGFUf9phlA4mjoSA2ky4RMpQ+BoG1HpwbN+71FYulzvS7u7uaCbCGnskOTgUcX0AnVOyrqBUkorLjY2NEym+zrCCyflbNBoaev62d3d35aAr8td+7L+bXRPCLVbdTdAd1c+wq6uomwNOyKaSqEX3c0kfOwC6uw9NAiZlU01/dDfH9tovFt97j+7uXndF9RoczUZlKpckSZIkxWckjKAeAoZqatvBIXocDaHFixcfXrlyZXRzLtJmzZo1e+rUqS0Azz77bNuGDRu2ZV1TiVcAJ+fb7cCGDGspZxJwWqq/Fuj92WaG5s2bd1ZDQ0MjwPjx4x9LkmRX1jVVsamGz/XlJEmi+lQ87fjjjz95/vz5rwBob2/fvXbt2keyrqlECzA71b83q0Kq+NNU+2F6X6c8a68Fjs63/wBszbCWXmbOnHnitGnTTgFoaWlpT5IktuNvkWOOOeZALZ6nqalpXVdXV7R/25MkaZw/f/5Zhf5DDz20YceOHe1Z1lTGafSM6m4D2jKspZyTgGn59h7C8SMaU6dObZkzZ86R42+SJPclSRLV6UVpzc3NUR87hlJu6dKlR/4jcrncay6++OInsixIkiRJkjQ6LFu27NVJkjxe6DvFV5IkSZIUBQOqJEmSJCkKBlRJkiRJUhQMqJIkSZKkKBhQJUmSJElRMKBKkiRJkqJgQJUkSZIkRcGAKkmSJEmKggFVkiRJkhQFA6okSZIkKQoGVEmSJElSFAyokiRJkqQoGFAlSZIkSVEwoEqSJEmSomBAlSRJkiRFwYAqSZIkSYqCAVWSJEmSFAUDqiRJkiQpCgZUSZIkSVIUDKiSJEmSpCgYUCVJkiRJUTCgSpIkSZKiYECVJEmSJEXBgCpJkiRJioIBVZIkSZIUBQOqJEmSJCkKBlRJkiRJUhQMqJIkSZKkKBhQJUmSJElRMKBKkiRJkqJgQJUkSZIkRcGAKkmSJEmKQlO6kyTJKcuWLcuqFkmSJEnSKJIkySnpflPJ9l8kSVK7aiRJkiRJynOKryRJkiQpCgZUSZIkSVIU/h9zhnJWRK6mqgAAAABJRU5ErkJggg==" width="450">
</img></div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c1bd8413">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>The communication step happens in function <code>ghost_exchange!</code>. This one modifies the ghost cells in the input vector <code>u</code> by importing data using MPI point-to-point communication. See the following code:</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=688638a1">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">ghost_exchange!</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">2</span><span class="o">:</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">1</span><span class="o">:</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Sendrecv!</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">dest</span><span class="p">,</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">))</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Sendrecv!</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">dest</span><span class="p">,</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=5bf5408c">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Note that we have used <code>MPI.Sendrecv!</code> to send and receive values.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d2ce54e4">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Is this other implementation based on `MPI.Send` and `MPI.Recv!` correct?
</div>
<div class="highlight"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">ghost_exchange!</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">2</span><span class="o">:</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">1</span><span class="o">:</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Send</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">dest</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Recv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">))</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Send</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">dest</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Recv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
</pre></div>
<pre><code>a) It is correct.
c) It is incorrect, but it might provide the right result depending on the MPI implementation.
b) It is incorrect, and it is guaranteed that it will result in a dead lock.
d) This implementation does not work when distributing over just a single MPI rank.</code></pre>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=8498c7e2">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="w"> </span><span class="c"># replace x with a, b, c or d</span>
<span class="n">sndrcv_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d863cb89">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> How would you fix the implementation above, while still using `MPI.Send` and `MPI.Recv!` instead of `MPI.Sendrecv!` ?
</div>
<p>Think about the answer. To uncover the the solution run next cell.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=629a3356">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
<span class="n">sndrcv_fix_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=82e21f4e">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Local-computation">Local computation<a class="anchor-link" href="#Local-computation"></a></h3><p>Once the ghost cells have the right values, we can perform the Jacobi update locally at each process. This is done in function <code>local_update!</code>. Note that here we only update the data <em>owned</em> by the current MPI rank, i.e. we do not modify the ghost values. There is no need to modify the ghost values since they will updated by another rank. In the code, this is reflected in the loop over <code>i</code>. We do not visit the first nor the last entry in <code>u_new</code>.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=f43560e5">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">local_update!</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">u_new</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=47861c19">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Running-the-code">Running the code<a class="anchor-link" href="#Running-the-code"></a></h3><p>Let us put all pieces together and run the code. If not done yet, install MPI.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=53674411">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="p">]</span><span class="w"> </span><span class="n">add</span><span class="w"> </span><span class="n">MPI</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c966375a">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>The following cells includes all previous code snippets into a final one. We are eventually calling function <code>jacobi_mpi</code> and showing the result vector <code>u</code>. Run the following code for 1 MPI rank, then for 2 and 3 MPI ranks. Look into the values of <code>u</code>. Does it make sense?</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=f91e4759">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="k">using</span><span class="w"> </span><span class="n">MPI</span>
<span class="n">code</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="n">MPI</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Init</span><span class="p">()</span>
<span class="w"> </span><span class="o">$</span><span class="n">code1</span>
<span class="w"> </span><span class="o">$</span><span class="n">code2</span>
<span class="w"> </span><span class="o">$</span><span class="n">code3</span>
<span class="w"> </span><span class="o">$</span><span class="n">code4</span>
<span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">9</span>
<span class="w"> </span><span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">200</span>
<span class="w"> </span><span class="n">comm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_dup</span><span class="p">(</span><span class="n">MPI</span><span class="o">.</span><span class="n">COMM_WORLD</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_mpi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="nd">@show</span><span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
<span class="n">run</span><span class="p">(</span><span class="sb">`</span><span class="si">$</span><span class="p">(</span><span class="n">mpiexec</span><span class="p">())</span><span class="sb"> -np 1 julia --project=. -e </span><span class="si">$code</span><span class="sb">`</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8e4fe21d">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Checking-the-result">Checking the result<a class="anchor-link" href="#Checking-the-result"></a></h3><p>Checking the result visually is not enough in general. To check the parallel implementation we want to compare it against the sequential implementation. However, how can we compare the sequential and the parallel result? The parallel version gives a distributed vector. We cannot compare this one directly with the result of the sequential function. A possible solution is to gather all the pieces of the parallel result in a single rank and compare there against the parallel implementation.</p>
<p>The following function gather the distributed vector in rank 0.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=49a220c6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code5</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">gather_final_result</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="mi">0</span>
<span class="w"> </span><span class="c"># If I am not rank 0</span>
<span class="w"> </span><span class="c"># I send my own data to rank 0</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Send</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">dest</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="c"># This will nevel be used</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="c"># If I am rank 0</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">load</span><span class="o">*</span><span class="n">nranks</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="c"># Set boundary</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="c"># Set data for rank 0</span>
<span class="w"> </span><span class="n">lb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="n">ub</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">load</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">)</span>
<span class="w"> </span><span class="c"># Receive and set data from other ranks</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">other_rank</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">lb</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">load</span>
<span class="w"> </span><span class="n">ub</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">load</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u_root</span><span class="p">,</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Recv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">source</span><span class="o">=</span><span class="n">other_rank</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="c"># NB onle the root (rank 0) will</span>
<span class="w"> </span><span class="c"># contain meaningfull data</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">u_root</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=e66bad1b">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Run the following cell to see the result. Is the result as expected?</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=4a9f4a54">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="n">MPI</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Init</span><span class="p">()</span>
<span class="w"> </span><span class="o">$</span><span class="n">code1</span>
<span class="w"> </span><span class="o">$</span><span class="n">code2</span>
<span class="w"> </span><span class="o">$</span><span class="n">code3</span>
<span class="w"> </span><span class="o">$</span><span class="n">code4</span>
<span class="w"> </span><span class="o">$</span><span class="n">code5</span>
<span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">9</span>
<span class="w"> </span><span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">200</span>
<span class="w"> </span><span class="n">comm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_dup</span><span class="p">(</span><span class="n">MPI</span><span class="o">.</span><span class="n">COMM_WORLD</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_mpi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gather_final_result</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="nd">@show</span><span class="w"> </span><span class="n">u_root</span>
<span class="k">end</span>
<span class="n">run</span><span class="p">(</span><span class="sb">`</span><span class="si">$</span><span class="p">(</span><span class="n">mpiexec</span><span class="p">())</span><span class="sb"> -np 3 julia --project=. -e </span><span class="si">$code</span><span class="sb">`</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=dc9b2b51">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<p>Now that we have collected the parallel vector into a single array, we can compare it against the sequential implementation. This is done in the following cells.</p>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=cb053382">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code6</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">function</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=ffe6c605">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">code</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">quote</span>
<span class="w"> </span><span class="k">using</span><span class="w"> </span><span class="n">MPI</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Init</span><span class="p">()</span>
<span class="w"> </span><span class="o">$</span><span class="n">code1</span>
<span class="w"> </span><span class="o">$</span><span class="n">code2</span>
<span class="w"> </span><span class="o">$</span><span class="n">code3</span>
<span class="w"> </span><span class="o">$</span><span class="n">code4</span>
<span class="w"> </span><span class="o">$</span><span class="n">code5</span>
<span class="w"> </span><span class="o">$</span><span class="n">code6</span>
<span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">12</span>
<span class="w"> </span><span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span>
<span class="w"> </span><span class="n">comm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_dup</span><span class="p">(</span><span class="n">MPI</span><span class="o">.</span><span class="n">COMM_WORLD</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_mpi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gather_final_result</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="c"># Compare agains serial</span>
<span class="w"> </span><span class="n">u_seq</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">isapprox</span><span class="p">(</span><span class="n">u_root</span><span class="p">,</span><span class="n">u_seq</span><span class="p">)</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Test passed 🥳"</span><span class="p">)</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Test failed"</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span>
<span class="n">run</span><span class="p">(</span><span class="sb">`</span><span class="si">$</span><span class="p">(</span><span class="n">mpiexec</span><span class="p">())</span><span class="sb"> -np 3 julia --project=. -e </span><span class="si">$code</span><span class="sb">`</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c9aa2901">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Latency-hiding">Latency hiding<a class="anchor-link" href="#Latency-hiding"></a></h2><p>We have now a correct parallel implementation. But. can our implementation above be improved? Note that we only need communications to update the values at the boundary of the portion owned by each process. The other values (the one in green in the figure below) can be updated without communications. This provides the opportunity of overlapping the computation of the interior values (green cells in the figure) with the communication of the ghost values. This technique is called latency hiding, since we are hiding communication latency by overlapping it with computation that we need to do anyway. The actual implementation is left as an exercise (see Exercise 1).</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=7d66b1a2">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div>
<img align="left" alt="No description has been provided for this image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA6gAAADyCAYAAABAvOgkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAewgAAHsIBbtB1PgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7d17nFxlYf/xz9lssrmQm4EQkhACRi7h1kD4YSIqEGuwEi4tSNEakWpqBWuLtEKrgtW2WkDbn1VJ0Cra3w8lKMKGCIJc1BBCxCgghGsSJIEk5ELut93pH89s9uxkZnez7M7z7O7n/XqdV84zc2bmm9nNZL97Lk82e/bsApIkSZIkRVYTO4AkSZIkSWBBlSRJkiQlorZkPD3LsuUxgkiSJEmSepdCoTAeuKdp3KKgZlm2fNasWc9WO5QkSZIkqfeZM2cOhULzZZE8xFeSJEmSlAQLqiRJkiQpCRZUSZIkSVISLKiSJEmSpCRYUCVJkiRJSbCgSpIkSZKSYEGVJEmSJCXBgipJkiRJSoIFVZIkSZKUBAuqJEmSJCkJFlRJkiRJUhIsqJIkSZKkJFhQJUmSJElJsKBKkiRJkpJgQZUkSZIkJcGCKkmSJElKggVVkiRJkpQEC6okSZIkKQkWVEmSJElSEiyokiRJkqQkWFAlSZIkSUmwoEqSJEmSkmBBlSRJkiQlwYIqSZIkSUqCBVWSJEmSlAQLqiRJkiQpCRZUSZIkSVISLKiSJEmSpCTUxg4gSZKSMxB4b3F9PrA1YpZq619cdtO7/t6SlAQLqiRJKjUCuLW4/mbgxQ4+Tw3wFmAyMAkYXLz9CtItf/8IfBa4H5gWOYsk9ToWVEmS1BW+AXwAGFLmvqtJt6DG8F7gHOA54PrIWSQpKguqJEkqtRG4qri+voPPMZHmcrqy+JzHvsFc1fAH4BHg91V8zZOAWcAvqF5BPRQ4ObccCWTAbcCnq5RBkvZhQZUkSaU2A19+g89xE3Ad8BjwKvAh4Ltv8Dmr4abi0pNNBhZXuO+gagaRpFIWVEmS1BX+X+wA3ci3CBej2rKfjzsSOJFwjvBjHXjdDcCvi4/9IDCmA88hSZ3KaWYkSVKpQ4FCcTkicpZquwR4ALihiq/5CqEkPrOfj5tBuJjVrP183LOEi1+9CXg34Zzgdfv5HJLUJdyDKkmS1OwI4HSgsYqvOZFwfu5a4MEqvN6m4iJJyXEPqiRJUlx/RtgT+vnYQSQpNguqJEmSJCkJFlRJkiRJUhI8B1WSJLXXUGBChfuew/MaJUlvkAVVkiS11zuAOyvcdxZwTxWz9BZHUPkqvacU/zwV+FKFbW4HFnV2KEnqKhZUSZLUXhupPN+me0+7xjjg021sc2JxKWcZFlRJ3YgFVZIktdcvgcmxQ/QyLwFfrnDfKcCZwO+Auyts89uuCCVJXcWCKkmSlK4Xgasq3PcpQkFd1Mo2ktSteBVfSZIkSVIS3IMqSZK6womECyc1OSm3/klgW278dWBLNUJJktJmQZUkSV2htSvLfq5k/D0sqJIkLKiSJGlfW4A5xfWOXp336dxztGVb25tUzRZgLbAhdpAu9h1gbG58RPHP6cC9udsfAP61WqEkyYIqSZJKbQD+6g0+xy+LS3fz78Wlp5sCHFXm9tHFpcna6sSRpMCCKkmSFNePgKXsfxmsJ0xD82IHXvNvgcHt2O6lDjy3JHWYBVWSJCmup4rL/nq2uHREpXlTJSkqp5mRJEmSJCXBgipJkiRJSoIFVZIkSZKUBAuqJEmSJCkJFlRJkiRJUhIsqJIkSZKkJDjNjJJXKBSy+vr6R2PnaM0NN9xw2LJlywYCbN68+bUNGzakNrH5gcBBxfXtwPJ4UcoaAIzPjZ8BGuNEKW/cuHFHUfyl3iWXXPLy5MmTN0eOVFGWZbfOmDHjumq8Vn19/XcLhcKx1Xitjpg7d+7Ihx56aATAzp07t65evTq1OR0HAeNy46djBWnFMbn1l4CtsYJUMI7wPgKsA9ZEzLKPYcOGjRgyZMhIgDFjxuy4+uqrl8XO1Jq6urrTp0+f3uVf47vuuusdDQ0NN3T163TUjh07aq688sqjmsarV69evnPnzu0xM5UxnvD/J4Q5dF+LF6Wsgwg/fwBsA1ZEzLKP/v37Dxw5cuRhTeOvfe1rT2dZFjNSWz5xzjnnPBI7RDVYUJW8z3/+89nJJ588OXaO1qxfv56XXtr7c+8g4LBWNo9tEM3/YaTqpNgBSuW+vjQ0NByV+H9ii6r1QoVC4dgsy5L997l9+/bSf5sjI8Zpj2Tfy6Jj2t4kqtLCH93GjRvZuHEjAP369RuUZdmIyJFaVVNTU5WfDRsaGoan/NmRZVmLz30g2V/EFQ2i5S96UzOI5l+UJ2HHjh2lX+PJKf/fnmXZ0NgZqsVDfCVJkiRJSXAPqrqjm7IseyF2iLzdu3dfQ/EwmzFjxqxYuXLlNyNHKvWXwFuK67uAz0XMUs5k4ILc+IvAlkhZyqqtrf3Snj17AFi/fv0DWZbdEzlSqZmFQmFizACFQuHumpqaB2NmKLV58+aPU9yjNmLEiO3r1q37fORIpd4B/ElufFWsIK34UvPqmIfh4CXxopTz249AY11x8BLwjZhpSo0dO/bSl19++UiAhobCnhdfHDY7dqa8gQN3jRw1atuFkWPszrLss5EztLBz584DgM80jUeNGnXbq6+++uuIkcr5Z6Bfcf154FsRs5TzMZr36u4Aro2WpIzRo0eftmrVqrObxnv27Pmnurq6hpiZShUKhX8D0t2t20UsqOp2CoXCD2bMmHF/7Bx5EyZMuIpiQR03btzKlStXfjlypFLvormg7gZSy/cRWhbU/wJWR8pSVp8+ffYW1GXLli06++yzk3oP582bNwWIWlCzLPtFau/L1KlTz6NYUIcPH75j3bp1SeUjnGudL6j/DhQiZakkV1An/gZ+9v14Ucrp+8FcQV1FYp9vRxxxxJnNBbVhzyc/edr3YmfKu/TSpyaef/6L0Qtqap8dF1988cHkCuopp5xyT319fWoF8DM0F9QVJPa9D8ygZUFNKt/JJ5+8K19Qf/CDH1w/d+7cXTEzlaqvr/9XemFB9RBfSZIkSVISLKiSJEmSpCRYUCVJkiRJSbCgSpIkSZKSYEGVJEmSJCXBgipJkiRJSoIFVZIkSZKUBAuqJEmSJCkJFlRJkiRJUhIsqJIkSZKkJFhQJUmSJElJsKBKkiRJkpJgQZUkSZIkJcGCKkmSJElKggVVkiRJkpQEC6okSZIkKQkWVEmSJElSEmpjB1CXGQBMzI2XAI1tPKYGmJQbPwVs7+RckiRJklSWBbXnOgL4dW48kLbLZr+SxxwPPNnJuSRJkiSpLA/xlSRJkiQlwYIqSZIkSUqCBVWSJEmSlAQLqiRJkiQpCRZUSZIkSVISLKiSJEmSpCRYUCVJkiRJSbCgSpIkSZKSYEGVJEmSJCXBgipJkiRJSoIFtecqlIyzdjzmgK4IIkmSJEntYUHtubaUjNtTPg/riiCSJEmS1B4W1J5rPS33ok5ox2Pe1UVZJEmSJKlNFtSeawuwLDc+q43tBwOXdV0cSZIkSWqdBbVnuy+3fjkwpsJ2dcDNwKFdnkiSJEmSKrCg9mxzgMbi+nDgl8AFNJ+PeiBwEfAocD7w22oHlCRJkqQmtbEDqEs9BnwN+GRxfDgwt7jeSMtfUKwilNfnq5au4y6rr68/N3aIvH/4h38Y0LT+/PPPHw78Z8Q45RyZW+9HevmOLRl/EdgWI0gle/bs2bs+YcKEd9XX1w+MGGcfhULh+NgZgLPr6+tHxQ6R981vfnN80/ratWsHkN73/kkl4/+IkqLdfvt2mHBQ7BQtNfbPDcaT2Nd46dKlRzet9+lT0/emmx64ImaeUn377nlT7AxAv/r6+qS+bps2bRp4yy237B0vWLDgz4EUPmfz6nLrR5LY9z7h584myX3+Lly4cFJ+/P73v/+GmTNnNlbaPpL2zMLR41hQe75PFf/8BC0LaX79V8CfA+uqFeqNyLLsT2NnKFVb2/xPae3atYcAfxMvTZv6knY+gI/EDlCqoaFh7/rQoUMnA5PjpUnW1OKSjIEDm3+P8Prrr/cn/e/9xPOtPTEsyRpFYu/hmjVr9q736VPTZ9SorRdFjJOqWhL7uvXr16/FeP369dOAaXHStMuhJPYelqgjsXyvvfZai3FNTc3lkaKohAW152sA/hb4NqGEngQcRLjK7wuEPaoPEvao9gHel3vsH6oZVJIkSVLvZkHtPZ4oLq1poPkQ4GRcc801hXnz5t0ZO0drRo8efXRDQ8MQgA0bNqx65ZVXXo6dqcRoYGxxfQvwVMQs5RwATMyNf03z+dNJOProo0+uqanpA9C3b9/ngA2RI1WUZdnjVXythwinCCRpyJAhYydOnDgaYPv27ZuWLVu2NHamEkOAo3PjR2MFacX/ya0vBTbFClLBUcDQ4vorJPbL1YMPPviQESNGHFpc3wr8PnKkVu3YsWN3NV4ny7JXgJT/b6+ZOHHi3iNlVqxY8dTWrVtL55iPbSLN1xV5mfQ+i8cSfv6A8LmR1OfvAQccMHjcuHHHNI0LhcJiWk7RmJSGhoY1bW/VM2SzZ8/e+4XIsuyoWbNmPRszkCRJkiSpd5gzZ86RhULhmaaxV/GVJEmSJCXBgipJkpS+fm1vIkndnwVVkiQpfZ8lXHX/wNhBJKkrWVAlSZLS9yvgZOBx4MzIWSSpy1hQJUmS0rcQeB04BLiLMH1c36iJJKkLWFAlSZLStwnYU1zvD7wfWAIcES2ROqp/7ABSyiyokiRJ3cP9ufX+hHkwFwJ/ESeOOqA/4XDt2XjhK6ksC6okSVL3cCewNTfOgJHAfxXvGxgjlPbLjYRzic8DDoqcRUqSBVWSJKl7eAjYUub2ocB04GnghKom0v74OPAhoIGw13tl3DhSmiyokiRJ3cNaYFeF+/oB4wiHAV9VtURqrynAV4vrnwbujZhFSpoFVZIkqft4rI373wR8Abi9ClnUPgcDtxJ+iXA78JW4caS01cYOIEmSpHa7A3gPUFdy+zbgeeA24DfA+irnUnm1wA+BscAzwCVAIWYgKXUWVEmSpO7jQWAjYa8chEN++xGuDnslHjqamn8H3glsBs4nTBckqRUe4itJktR9LCdcZAfCFX1/Cnyb8DPd94FD4sRSGRcBf0fYY/phwkWsJLXBgipJktS9PEUoPU8DfwZ8AniCsFf1Zvz5LgWTCb84APg34EcRs0jdih9gkiRJ3cudhL2oFxT/3E7YW7cV+GPgc/GiCRgP1AODgPn49ZD2iwVVkiSpe5kP/F9gRe62p4GPFdc/B5xX7VACYDjh6zOKcLGqi2g+JFtSO1hQJUmSupcXgE+Vuf1/CHNtZoTzUY+rZijRD5gLHAOsBM4FtkRNJHVDFlRJkqSe4++Bu4EDgB8Dw+LG6TUy4FvANMKVev8EeDlqIqmbsqBKkiT1HA3AXwDLgLcA/x9/3quGLwIfJEz7cz7weNw4UvflB5YkSVLPso5wDupW4D3A1+PG6fH+EvhHwpWVZwH3x40jdW8WVEmSpJ7nceASoJFw8aQroqbpud4L3Fhcv4YwzY+kN8CCKkmS1DPdRjgnFeA64MKIWXqiMwnvcS3w38AX4saRegYLqiRJUs/1FeA/CT/zfQ84LW6cHmMKcAfQH/gJ8Fdx40g9hwVVkiSpZ7uCcEXfpjLl9DNvzCnATwlXSp5PmOt0T9REUg9iQZUkSerZGglX9n0YGAHcCxwVNVH3dSrwM2Ao4WJIFxCu3Cupk1hQJUmSer7thAv6/AYYBfwceHPURN3PaYRyOgz4BXAu4X2V1IksqJIkSb3DRmAasAQYAzwAjI8ZqBt5B+Fw3iHAQ4SyvyVqIqmHsqBKkiT1HhsJc6MuBQ4F7sOS2pZzgLuBwcU/34PlVOoyFlRJkqTeZTXwLuB5wmG+vwSOiZooXR8lXGBqAOGqvefhYb1Sl7KgSpIk9T4rgbcDvwPGAguAt0ZNlJ5PA3OAPsB3CRdE2hkzkNQbWFAlSZJ6p1eBM4FFwHDCBYDOiJooDXXAd4AvFcf/DHwYp5KRqsKCKkmS1HutJxzuex/N51heGjVRXAcTpo+5hFBIPwZcEzOQ1NtYUCVJknq3LcDZwA+BfsC3gRsIh7b2JpOAR4GphOL+HmB21ERSL2RBlSRJ0k7gYuAqoBG4AriLMOdnbzAT+BUwDngOeBthr7KkKrOgSpIkCaAAfBl4H7AVmA4sBibHDNXFhgFzgZuBgcCdwCmEaXgkRWBBlSRJUt6PCFf4XQ5MIFzh91NAFjFTVzgd+A3h6ry7gL8jTCPzesRMUq9nQZUkSWr2l4R5Qb8aO0hkSwjnZN5KOC/1emA+cEjMUJ3kAOC/CBdDOhx4gXBI738Q9iJLisiCKkmS1Oww4DTghNhBErARuAj4KLANOAt4Gvg43fdnyLOAx4HLiuMbCUX819ESSWqhu364SJIkqTq+RTgP9RFgKPB1wgWFjo8Zaj+9hXB+6U8Je02XEabX+Wtgc8RckkpYUCVJkpp9CTgIOD92kMQ8TTgM9jLCOZpTCOdv3gSMjZirLQcRDk9+EphBONf0esIe8vsj5pJUgQVVkiSp2TbgNWBT7CAJagS+AUwkXPm2FvgIYVqW64ED40Xbx0jgOsKe0k8RzqO9i7DX9+8Jc79KSpAFVZIkqdkUwhygF8QOkrBVhKlopgAPAP0JJXAFMIe4h/5OKmZYBlwJDAIWEabMORt4Nl40Se1hQZUkSWr2HuAGwrmJat0jwJnAuwklcCDhgkqPE4rrTMI8o13toOLrPkI47PijxSyPAH8CvBX4WRVySOoEtbEDSJIkqVu7t7hMBf4G+FPCHKOnE875vBf4MfAQYUqXN6oGOBY4g3Cu8NuBPsX7dhLmcb2RMF2QpG7GgipJkqTO8HBxGU2YT/YCwsWI3ltcAF4FFhD2dL5QXFYA6wjnuOb1J1w1+AjgSMKVeCcRinB+z2wBWEyYs/VmYG3n/rUkVZMFVZIkSZ1pFfCF4nIUoaieRZiqZhTwZ8Wl1G6aL140mNZ/Tt0MLCRMG/Nj4KXOCC4pPguqJEmSusozwL8UlzpCSZ0KHAO8mbB3dAyQAX2B4SWPbySUz+cJVwt+irAH9nGgoevjS6o2C6okSZKqYSehXC4oub0PMAQYQDisNyNM97MVp/uReh0LqiRJkmJqADYUF0m9nNPMSJIkSZKSYEGVJEmSJCXBgipJkiRJSoIFVZIkSZKUBAuqJEmSJCkJFlRJkiRJUhKcZkaSJKnZbOAu4PXYQSSpN7KgSpIkNVtZXCRJEXiIryRJkiQpCRZUSZIkSVISLKiSJEmSpCRYUCVJkiRJSbCgSpIkSZKSYEGVJEmSJCXBaWbULdx+++3jY2doTX19/YEbNmzoD7Bq1apNixYt2hQ7U4nBwNDi+i5gTcQs5fQDRubGK4FCpCxlnXvuuaNrampqAE466aR1xx133PbYmSoZMGDAprPOOmt9NV7r7rvvPmT79u111XitjliwYMGQF154YQjAli1bdtx7772vxc5Uog44KDd+OVaQVozNra8FdsYKUsGBQP/i+mYSm790ypQpg0eNGjUUYPDgwbvOP//81D5/WzjvvPNWZFnW5Z+/t95664C+ffse3NWv01G7d+/ObrnlljFN40cffXTNypUrd8XMVMZIwv+fEL7vN0fMUs6Q4gLhc2NtxCz7OPzww+v+6I/+aO/n78yZM1P8/N1r2LBhr55xxhk7YueoBguqknfttdfW1NbWLoudozWLFy/miSeeiB1DXeiOO+7Yuz5x4kRqa9P9+Ny9e/fXgcur8Vq7du26s7a2dnI1Xqsjli9fzu233x47hnqxhQsX7l2fMGECF154YcQ0bbvvvvuGUYWS379//3dnWfaTrn6djtqzZ4+fHT3csmXLWLas+cfLSy65hOLvoZO0devWs4B7YueohnS/CpIkSZKkXsWCKkmSJElKQrrHqEmV/UWWZQvb3qx6duzYsYTieRaTJk16bMmSJe+LHKnUzcBpxfVtwPERs5TzPuDfcuNTgaTOFayrq3th585w6t3SpUtvnDJlynWRI5W6sVAo/HHkDNdlWXZj5AwtrFmz5jZgEsD48eNfX758+UmRI5X6KHDV3tFX+Xi8KBX8Hd/Yu/5Obuc87o2YZl9/z/XsYWAYjH4W/vGq1h9QXUceecdnn3323kkAu3fv3p5l2XGxM+U1NjYen8Chtsm9L3/4wx8OBBY1jU899dSrFy1adGvESOU8AU3f+ywAZkbMUs4PgaZTQDZR/CxOxdSpUy99+OGH/6lpvGnTpqOHDx++O2amUoVC4Tl64Q5FC6q6nUKh8MqMGTNejJ0jb8KECY1N6/37998JJJUPyJ9UXyC9fKVldAWwOkaQ9ti6devGs88+O6n3cN68edtiZwA2pPa+TJ06de8FfWpraxtJ73u/5cWszmQNNWldIKyFYWzhXYn928xobB7U7oLLVsYLs6+6uvv3fg8WCoXG1P6N3HnnnSNiZwAKqb0vF1988db8eOTIka+R3udH7nufHaSXL39BteQ+f0eMGLEuP77zzjuXzZ07N6kLYdXX18eOEEWva+SSJEmSpDRZUCVJkiRJSbCgSpIkSZKSYEGVJEmSJCXBgipJkiRJSoIFVZIkSZKUBAuqJEmSJCkJFlRJkiRJUhIsqJIkSZKkJNTGDtDDZcCbgTFAf2AV8BTQ8AafdwIwChgMbAReBFa/weeUJEmSpKhS34M6Hnghtwxux2NqSh5zXFeFK/p47rX+J5fhE8BS4DngQeBu4HFCkfwCMHA/X+dQ4OvAy8Xn/CUwH3gYeAX4DfBhWv+aXp3L+p9tvN4/0fJ9/HAb29+W2/ZDbWwrSZIkSftIfQ9qX+CI3Li9hTr/mLrOi1PW8NzrLSeU6NuAd1fYfgTwGeBdwHRgUzte4zLgesJe2HIyYBLw34QieR6wvsx2T+ayXgj8LVCo8Jzn0/J9PAf4ToVtDwBmAP2K499W2E6SJEmSKkq9oHY3NYS9qO8mHMb7EPAYsBk4DDgXOLC47VsJpXNWG895LXBNbrwV+CmwBHgdGEkouqcW7387cC/wNmBHyXM9BOwhfN0PASYCvy/zmm8iFN6804E+lD88+e00l9O1hD3FkiRJkrRfLKid6zTCe/p74CL2LX9XAj8CziyOLwW+CLxU4flmAJ/LjX9I2Ju6rmS7awh7RL9LOHT4JOBfgE+VbLcJWAxMKY6nlckIcAbNe6t3EvZCDwNOBh4ts/203Pr9VN4rK0mSJEkVpX4OandTC6wkFLxyxW8j8H5gS3Hch1Asy+lLOOc0K45vBS5m33LaZC7wkdz444S9q6V+nlufVub+0ttv3M/t76+wjSRJkiS1yoLa+T5DOMy1ktXAvNx4coXtLiRcGAlCob2ctvdM3kLYQwrhfNWLy2yTL5DvpPxe9KbCuRn4MtBYcnvegcAJufHPy2wjSZIkSW2yoHau3YQ9nW15LLc+vsI25+TW76D10pv349z628vc/zCwvbg+FDil5P5DgSOL678gXCH4d8Xx24ABJdufSfP30XLCVXwlSZIkab9ZUDvXM8C2dmy3Jrc+tMI2+XK5cD8yLM2tH1Pm/p3Ar3Lj0r2i+fF9xT+b9or2B6a2sr17TyVJkiR1mBdJ6lzlpnYpZ1duvV+Z++uA0bnxFbQ9DymEKW7yc8W+qcJ2Pwf+uLg+jXChJnLj/HZNf16Zuz9fRM8ss70kSZIk7TcLaufa00nPM7xkfETZrdo2qMLt+fNQpxCu/Nu057epcL5KmDcV4JeEUt2PlgX2MGBCcb0APNDBnJIkSZJkQU1Un5Lx/VS+em9rtle4/TfABkIRriNMj/MzwryoTXtu89PFbAUeAd5BmGpmePHx+bL6e0KplSRJkqQO6YkFtdwhs91NaRn9GvCTTnz+BuBB4PzieBqhoLZ2uO7PCQW1D3A6cDuefypJkiSpE6V+kaQdJeP+7XhMubk/u5sdtNwbeUKlDd+AcvOhlrtAUqXtMzz/VJIkSVInSr2gbioZH9KOx5zaFUEiyJ/PeU7FrTouXygnEYr96cXxc8BLJds/SpgXFUJBPRYYVRzvAR7qgoySJEmSepHUC+rrwOrc+G3teMxHuyhLtf0ot34y8J5Ofv6lwMrieg3hKr3DiuNye0N3E+ZFBTgamJm779fs+8sESZIkSdovqRdUaDkH6Mdo/bzZD9M8fUp3dzvhwkNN/hs4fD8efxDNhbOS/NV8L8+tlx7e2yRfXC+vcLskSZIkdUh3KKjfz60fB9wMDCnZZiDwOeAmYEuVcnW1RkLhbjoPdxSwGLiUyheC6gOcAcwBVgBvbuM18sVyQO51K00XU2770tslSZIkqUO6w1V8fwIsoPnw3vcDZxdve52wp/CthDk/GwmHnv64+jG7xGLC3+d7hAtEjQC+DXyFsGf5ZUKBHUbYu3oicMB+PH+5YrkEWF9h+yeANbS8ENV2Wu7lliRJkqQO6Q4FtRG4CLgXOKZ42xD2PSdzG/DXwB3Vi1YVc4HlwHcJ85QCDAXOauNxrwAb29jmZeAZ4KjcbZUO74UwL+r9wJ/nblvAvldbliRJkqT91h0KKoSL+ZwCXAF8gJaFagOhxP0H8DRh+pO5Jfd3padzr/dkOx/zUu4xq1vbsGgxcDzwp8AFhMN4S6fT2UK48NEvgHsIe0cb2vHcXwPemRv/qNKGRd8nHErc3u0lSZIkqV26S0EF2Ap8obgMJhzau5F9D0ctAO+rYq4fs/+HFD9cXPZHI3BbcYFwSPMIwtew3PvQXl8vLu01v7hIkiRJUqfqTgU1bzPNc3L2VluLiyRJkiT1CN3hKr6SJEmSpF7AgipJkiRJSoIFVZIkSZKUhO56DmpHfRAY0AnP8yzwYCc8jzogy7Jb6+vrd8XOkXf11VcPaVpfvHjxZGBVxDjlvCm3PpD08pX+u/wd4cJgydi1q/lbbtKkSZdfdtllH4oYZx+FQmF47AzA1fX19Z+IHSLvO9/5zoim9WXLlg0lve/9QS1Gp3JTpBztM58LuIezY8doYU/+PVx5NPS7K16YfT31VDa0ab1fv34D6+vrNL98BAAAAwFJREFUU/se7Bs7ADAgtfdl27ZtNbfccsve8fz5868D/jleorLynx+nkd7n24jcenKfv/Pnz2/x+fuBD3xg+cyZM2PFqaRX7kzsbQX1OuDgTniem7GgxjSi7U2qK8uyvet79uzpBxwSL02bMtLOB53z77RTFQqFves1NTUHAAfES5OswcUlGTU1zf+3NzQ01JD69/4OUvhFQ2W7GcDuTvlFbxdpqIWGA2OnyGtoOeFbd/j8jSG59yX/2QHQ0NAwDBgWJ0271JHYe1giua9xQ+k/zixLKl9v1itbuSRJkiQpPb1tD+pRdE4pT+rw0p7u2muvbZw3b94HY+dozQknnHDs6NGjhwGsXLnyD08++eRLsTOVGAscVlzfDDweMUs5g4ETcuNHgIYK20Yxbdq0t9bW1vYBGDRo0NNZlnV07uEu19jY+Ey1XqtPnz6fLRQKSe2xyhs9evRh06dPHwuwadOmjQsXLvx97EwlhgLH5cYLYgVpxdty608Cr8cKUsGxNO/ZehlYETHLPo455pgx48aNGw8wbNiwzVmWpfb528Lw4cO3VeN1amtrH2tsbEz2//Ysy/pMnz79rU3jJUuWPL5mzZrUpjg8Hmg6xWgF4fs/JeOAQ4vrrxM+P5IxatSooSeeeOLez98syx7OsqzQ2mNiqq2tTfqzozNls2fP3vuFyLLsqFmzZj0bM5AkSZIkqXeYM2fOkYVCYe8v1z3EV5IkSZKUBAuqJEmSJCkJFlRJkiRJUhIsqJIkSZKkJFhQJUmSJElJsKBKkiRJkpJgQZUkSZIkJcGCKkmSJElKggVVkiRJkpQEC6okSZIkKQkWVEmSJElSEiyokiRJkqQkWFAlSZIkSUmwoEqSJEmSkmBBlSRJkiQlwYIqSZIkSUqCBVWSJEmSlAQLqiRJkiQpCRZUSZIkSVISLKiSJEmSpCRYUCVJkiRJSajNDwqFwvg5c+bEyiJJkiRJ6kUKhcL4/Li25P57CoVC9dJIkiRJklTkIb6SJEmSpCRYUCVJkiRJSfhf0SSRmgN3HHEAAAAASUVORK5CYII=" width="450"/>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c2d48c45">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="alert alert-block alert-success">
<b>Question:</b> Which MPI directives would you use to implement latency hiding in the communication the ghost values?
</div>
<pre><code>a) MPI_Send and MPI_Recv
b) MPI_Bsend and MPI_Recv
c) MPI_Isend and MPI_Irecv
d) MPI_Sendrecv</code></pre>
</div>
</div>
</div>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=29ade8f6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea">
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="cm-editor cm-s-jupyter">
<div class="highlight hl-julia"><pre><span></span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="w"> </span><span class="c"># replace x with a, b, c or d</span>
<span class="n">lh_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9bd014b0">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Conclusion">Conclusion<a class="anchor-link" href="#Conclusion"></a></h2><ul>
<li>We learned how to parallelize the Jacobi method efficiently.</li>
<li>Using block partitions the communication overhead is small if the problem size is larger than the number of processors.</li>
<li>In addition, one can use latency hiding to further reduce the overhead caused by communication.</li>
<li>Both are not true if we use cyclic data partitions.</li>
<li>Gauss-Seidel is a simple variation of Jacobi but is much more challenging to parallelize.</li>
<li>One needs to consider a special order (red-black) when updating the values to parallelize the method.</li>
<li>We learned how to implement a 1D Jacobi method with MPI.</li>
<li>Once needs to be careful when using blocking directives to avoid dead locks.</li>
</ul>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=47643bf6">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h2 id="Exercises">Exercises<a class="anchor-link" href="#Exercises"></a></h2>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6527d24f">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Exercise-1">Exercise 1<a class="anchor-link" href="#Exercise-1"></a></h3><p>The following code implements the 1D Jacobi method studied in this notebook, but using non-blocking sends and receives. Modify this code so that you overlap the communication of the ghost values with local computations as explained above in the section "latency hiding". You only need to modify function <code>jacobi_mpi_latency_hiding</code>. Copy the code below to a file called <code>ex1.jl</code>. Modify the file (e.g. with vscode). Run it from the Julia REPL using the <code>run</code> function as explained in the <a href="https://www.francescverdugo.com/XM_40017/dev/getting_started_with_julia/#Running-MPI-code">Getting Started tutorial</a>.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9b57f876">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<div class="highlight"><pre><span></span><span class="c"># file ex1.jl (begin)</span>
<span class="k">using</span><span class="w"> </span><span class="n">MPI</span>
<span class="n">MPI</span><span class="o">.</span><span class="n">Init</span><span class="p">()</span>
<span class="k">function</span><span class="w"> </span><span class="n">jacobi_mpi_latency_hiding</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nreqs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="o">*</span><span class="p">((</span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)))</span>
<span class="w"> </span><span class="n">reqs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">MultiRequest</span><span class="p">(</span><span class="n">nreqs</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="n">ireq</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">2</span><span class="o">:</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">1</span><span class="o">:</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">ireq</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Isend</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">reqs</span><span class="p">[</span><span class="n">ireq</span><span class="p">];</span><span class="n">dest</span><span class="p">)</span>
<span class="w"> </span><span class="n">ireq</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Irecv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">reqs</span><span class="p">[</span><span class="n">ireq</span><span class="p">];</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">neig_rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">rank</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">))</span>
<span class="w"> </span><span class="n">dest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">source</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">neig_rank</span>
<span class="w"> </span><span class="n">ireq</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Isend</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">reqs</span><span class="p">[</span><span class="n">ireq</span><span class="p">];</span><span class="n">dest</span><span class="p">)</span>
<span class="w"> </span><span class="n">ireq</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Irecv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">reqs</span><span class="p">[</span><span class="n">ireq</span><span class="p">];</span><span class="n">source</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Waitall</span><span class="p">(</span><span class="n">reqs</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">init</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">mod</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">nranks</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"n must be a multiple of nranks"</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Abort</span><span class="p">(</span><span class="n">comm</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">div</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">nranks</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">gather_final_result</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">load</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">length</span><span class="p">(</span><span class="n">u</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span>
<span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">!=</span><span class="mi">0</span>
<span class="w"> </span><span class="n">u_snd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">load</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Send</span><span class="p">(</span><span class="n">u_snd</span><span class="p">,</span><span class="n">comm</span><span class="p">,</span><span class="n">dest</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="n">nranks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_size</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">load</span><span class="o">*</span><span class="n">nranks</span>
<span class="w"> </span><span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">lb</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="n">ub</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">load</span><span class="o">+</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_root</span><span class="p">[</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">other_rank</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="p">(</span><span class="n">nranks</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">lb</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">load</span>
<span class="w"> </span><span class="n">ub</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">load</span>
<span class="w"> </span><span class="n">u_rcv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">view</span><span class="p">(</span><span class="n">u_root</span><span class="p">,</span><span class="n">lb</span><span class="o">:</span><span class="n">ub</span><span class="p">)</span>
<span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Recv!</span><span class="p">(</span><span class="n">u_rcv</span><span class="p">,</span><span class="n">comm</span><span class="p">;</span><span class="n">source</span><span class="o">=</span><span class="n">other_rank</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">u_root</span>
<span class="k">end</span>
<span class="k">function</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">1</span>
<span class="w"> </span><span class="n">u</span><span class="p">[</span><span class="k">end</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">copy</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">:</span><span class="n">niters</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">2</span><span class="o">:</span><span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="n">u_new</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="o">*</span><span class="p">(</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">+</span><span class="n">u</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span><span class="p">,</span><span class="w"> </span><span class="n">u_new</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">u_new</span><span class="p">,</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">u</span>
<span class="k">end</span>
<span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">12</span>
<span class="n">niters</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span>
<span class="n">comm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_dup</span><span class="p">(</span><span class="n">MPI</span><span class="o">.</span><span class="n">COMM_WORLD</span><span class="p">)</span>
<span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi_mpi_latency_hiding</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="n">u_root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gather_final_result</span><span class="p">(</span><span class="n">u</span><span class="p">,</span><span class="n">comm</span><span class="p">)</span>
<span class="n">rank</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">Comm_rank</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
<span class="k">if</span><span class="w"> </span><span class="n">rank</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">u_seq</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">jacobi</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">niters</span><span class="p">)</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">isapprox</span><span class="p">(</span><span class="n">u_root</span><span class="p">,</span><span class="n">u_seq</span><span class="p">)</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Test passed 🥳"</span><span class="p">)</span>
<span class="w"> </span><span class="k">else</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Test failed 😢"</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span>
<span class="c"># file ex1.jl (end)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=1af362aa">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h3 id="Exercise-2">Exercise 2<a class="anchor-link" href="#Exercise-2"></a></h3><p>In the parallel implementation of the Jacobi method, we assumed that the method runs for a given number of iterations. In function, <code>jacobi_with_tol</code> at the beginning of the notebook shows how the Jacobi iterations can be stopped when the difference between iterations is small. Implement a parallel version of this function. Start with the in Exercise 1 and add the stopping criterion implemented in <code>jacobi_with_tol</code>. Use a text editor and the Julia REPL. Do not try to implement the code in a notebook.</p>
</div>
</div>
</div>
</div>
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=6d3430ad">
<div class="jp-Cell-inputWrapper" tabindex="0">
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
</div>
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
<h1 id="License">License<a class="anchor-link" href="#License"></a></h1><p>This notebook is part of the course <a href="https://www.francescverdugo.com/XM_40017">Programming Large Scale Parallel Systems</a> at Vrije Universiteit Amsterdam and may be used under a <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a> license.</p>
</div>
</div>
</div>
</div>
</main>
</body>
</html>