From 98f7c4a87deed992765525a1a1161c995eac3aaf Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Tue, 31 Oct 2023 14:26:36 -0400 Subject: [PATCH 01/36] For some reason, typing extensions was not installing bundled with flax. It has now been added to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 1914608..6b84e25 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,5 +6,6 @@ flax>=0.7.2 tensorflow>=2.13.0 tensorflow-hub>=0.14.0 typeguard==2.13.3 +typing_extensions>=4.8.0 jaxtyping pytest From dcc0dacc49b5bde2f79b63c410e7ddcf34fddff6 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Tue, 31 Oct 2023 18:08:59 -0400 Subject: [PATCH 02/36] Added a new solid class to handle the full BZ sampling periodic case. We also have a kpoint info class, able to take information about the IBZ if required. New PySCF parsers in pyscf.py for making solid objects from PySCF output --- grad_dft/__init__.py | 6 +- grad_dft/interface/__init__.py | 1 + grad_dft/interface/pyscf.py | 133 ++++++++++++++++++++++++++++++++- grad_dft/molecule.py | 5 +- grad_dft/solid.py | 119 +++++++++++++++++++++++++++++ 5 files changed, 256 insertions(+), 8 deletions(-) create mode 100644 grad_dft/solid.py diff --git a/grad_dft/__init__.py b/grad_dft/__init__.py index bdea5d0..d95b263 100644 --- a/grad_dft/__init__.py +++ b/grad_dft/__init__.py @@ -24,6 +24,9 @@ grad_density, coulomb_energy ) +from .solid import ( + Solid +) from .functional import ( DispersionFunctional, Functional, @@ -59,7 +62,8 @@ diff_scf_loop ) from .interface import ( - molecule_from_pyscf, + molecule_from_pyscf, + solid_from_pyscf, loader, saver ) diff --git a/grad_dft/interface/__init__.py b/grad_dft/interface/__init__.py index 29cebee..177738d 100644 --- a/grad_dft/interface/__init__.py +++ b/grad_dft/interface/__init__.py @@ -14,6 +14,7 @@ from .pyscf import ( molecule_from_pyscf, + solid_from_pyscf, grid_from_pyscf, mol_from_Molecule, saver, diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 6abd096..4ddfc99 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -27,9 +27,11 @@ from pyscf.gto import Mole import pyscf.data.elements as elements from pyscf.pbc.gto.cell import Cell +from pyscf.pbc.lib.kpts import KPoints # from qdft.reaction import Reaction, make_reaction, get_grad from grad_dft.molecule import Grid, Molecule, Reaction, make_reaction +from grad_dft.solid import Solid, KPointInfo from grad_dft.utils import DType, default_dtype, DensityFunctional, HartreeFock from jax.tree_util import tree_map from grad_dft.external import NeuralNumInt @@ -52,6 +54,36 @@ def grid_from_pyscf(grids: Grids, dtype: Optional[DType] = None) -> Grid: return Grid(coords, weights) +def kpt_info_from_pyscf(kmf: DensityFunctional): + kpts = kmf.kpts + if isinstance(kpts, KPoints): + kpts_abs = kpts.kpts + kpts_scaled = kpts.kpts_scaled + weights = kpts.weights_ibz + bz2ibz_map = kpts.bz2ibz + ibz2bz_map = kpts.ibz2bz + kpts_ir_abs = kpts.kpts_ibz + kpts_ir_scaled = kpts.kpts_scaled_ibz + else: + kpts_abs = kpts + kpts_scaled = kmf.cell.get_scaled_kpts(kpts_abs) + # Equal weights + weights = jnp.ones(shape=(kpts_abs.shape[0],))/kpts_abs.shape[0] + bz2ibz_map = None + ibz2bz_map = None + kpts_ir_abs = None + kpts_ir_scaled = None + return KPointInfo( + kpts_abs, + kpts_scaled, + weights, + bz2ibz_map, + ibz2bz_map, + kpts_ir_abs, + kpts_ir_scaled + ) + + def molecule_from_pyscf( mf: DensityFunctional, @@ -85,7 +117,7 @@ def molecule_from_pyscf( atom_index, nuclear_pos = to_device_arrays( [elements.ELEMENTS.index(e) for e in mf.mol.elements], - mf.mol.atom_coords(unit="angstrom"), + mf.mol.atom_coords(unit="bohr"), dtype=dtype, ) @@ -146,6 +178,103 @@ def molecule_from_pyscf( scf_iteration, fock, ) + +def solid_from_pyscf( + kmf: DensityFunctional, + dtype: Optional[DType] = None, + omegas: Optional[Array] = None, + energy: Optional[Scalar] = None, + name: Optional[Array] = None, + scf_iteration: Scalar = jnp.int32(50), + chunk_size: Optional[Scalar] = jnp.int32(1024), + grad_order: Optional[Scalar] = jnp.int32(2), +) -> Molecule: + # mf, grids = _maybe_run_kernel(mf, grids) + grid = grid_from_pyscf(kmf.grids, dtype=dtype) + + ( + ao, + grad_ao, + grad_n_ao, + rdm1, + energy_nuc, + h1e, + vj, + mo_coeff, + mo_energy, + mo_occ, + mf_e_tot, + s1e, + fock, + rep_tensor, + ) = to_device_arrays(*_package_outputs(kmf, kmf.grids, scf_iteration, grad_order), dtype=dtype) + + atom_index, nuclear_pos = to_device_arrays( + [elements.ELEMENTS.index(e) for e in kmf.mol.elements], + kmf.mol.atom_coords(unit="bohr"), + dtype=dtype, + ) + + basis = jnp.array( + [ord(char) for char in kmf.mol.basis] + ) # jax doesn't support strings, so we convert it to integers + unit_Angstrom = True + if name: + name = jnp.array([ord(char) for char in name]) + + if omegas is not None: + chi = generate_chi_tensor( + rdm1=rdm1, + ao=ao, + grid_coords=grid.coords, + mol=kmf.mol, + omegas=omegas, + chunk_size=chunk_size, + ) + # chi = to_device_arrays(chi, dtype=dtype) + # omegas = to_device_arrays(omegas, dtype=dtype) + else: + chi = None + + spin = jnp.int32(kmf.mol.spin) + charge = jnp.int32(kmf.mol.charge) + if isinstance(kmf.grids, Grids): # check if it's the open boundary grid. Otherwise we have a uniform grid with no level + grid_level = jnp.int32(kmf.grids.level) + else: + grid_level = None + lattice_vectors = kmf.cell.lattice_vectors() + kpt_info = kpt_info_from_pyscf(kmf) + return Solid( + grid, + atom_index, + lattice_vectors, + nuclear_pos, + ao, + grad_ao, + grad_n_ao, + rdm1, + energy_nuc, + h1e, + vj, + mo_coeff, + mo_occ, + mo_energy, + kpt_info, + mf_e_tot, + s1e, + omegas, + chi, + rep_tensor, + energy, + basis, + name, + spin, + charge, + unit_Angstrom, + grid_level, + scf_iteration, + fock, + ) def mol_from_Molecule(molecule: Molecule): @@ -608,7 +737,6 @@ def _package_outputs( # Restricted (non-spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] != 1: - print(rdm1.shape) s1e = mf.get_ovlp(mf.mol) h1e = mf.get_hcore(mf.mol) @@ -643,7 +771,6 @@ def _package_outputs( ) dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) - print("right") fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) diff --git a/grad_dft/molecule.py b/grad_dft/molecule.py index f8532bd..6436c97 100644 --- a/grad_dft/molecule.py +++ b/grad_dft/molecule.py @@ -10,7 +10,7 @@ # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and -# limitations under the License. +# limitations under the License. from typing import List, Optional, Union, Sequence, Tuple, NamedTuple from dataclasses import fields @@ -37,9 +37,6 @@ class Grid: coords: Array weights: Array - # def __repr__(self): - # return f"{self.__class__.__name__}(size={len(self)})" - def __len__(self): return self.weights.shape[0] diff --git a/grad_dft/solid.py b/grad_dft/solid.py new file mode 100644 index 0000000..8fc8ce1 --- /dev/null +++ b/grad_dft/solid.py @@ -0,0 +1,119 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import jax.numpy as jnp +from typing import List, Optional + +from flax import struct +from jaxtyping import Array, PyTree, Scalar, Float, Int, jaxtyped + + +@struct.dataclass +class Grid: + r""" Base class for the grid coordinates and integration grids.""" + coords: Array + weights: Array + + def __len__(self): + return self.weights.shape[0] + + def to_dict(self) -> dict: + return {"coords": self.coords, "weights": self.weights} + + def integrate(self, vals: Array, axis: int = 0) -> Array: + r""" + A function that performs grid quadrature (integration) in a differentiable way (using jax.numpy). + + This function is glorified tensor contraction but it sometimes helps + with readability and expresing intent in the rest of the code. + + Parameters + ---------- + vals : Array + Local features/ function values to weigh. + Expected shape: (..., n_lattice, ...) + axis : int, optional + Axis to contract. vals.shape[axis] == n_lattice + has to hold. + + Returns + ------- + Array + Integrals of the same as `vals` but with `axis` contracted out. + If vals.ndim==(1,), then the output is squeezed to a scalar. + """ + + return jnp.tensordot(self.weights, vals, axes=(0, axis)) + +@struct.dataclass +class KPointInfo: + r"""Contains the neccesary information about BZ sampling needed for total energy calculations. + Most simply, we need the array of k-points in absolute and fractional forms with equal weights. + To properly take advantage of space-group and time-reversal symmetry, informations about mappings + between the BZ -> IBZ and vice versa is needed as well as weights which are not neccesarily equal. + + n_kpts_or_n_ikpts in weights could be the total number of points in the full BZ or the number of + points in the IBZ, context dependent. I.e, if the next variables are set to None, + the first case applies. If they are not None, the second does. + """ + + kpts_abs: Float[Array, "n_kpts 3"] + kpts_scaled: Float[Array, "n_kpts 3"] + weights: Float[Array, "n_kpts_or_n_ir_kpts"] + bz2ibz_map: Optional[Float[Array, "n_kpts"]] + ibz2bz_map: Optional[Float[Array, "n_kpts_ir"]] + kpts_ir_abs: Optional[Float[Array, "n_kpts_ir 3"]] + kpts_ir_scaled: Optional[Float[Array, "n_kpts_ir 3"]] + + +@struct.dataclass +class Solid: + r"""Base class for storing data pertaining to DFT calculations with solids. + This shares many simlarities ~/grad_dft/molecule.py's `Molecule` class, but many arrays + must have an extra dimension to house the number of k-points. + + Typically, for those arrays which need a k-point index, if a spin index is required, + dimension 1 will be dimension n_kpt. If spin is not required, dimension 0 will be + n_kpt. + """ + + grid: Grid + atom_index: Int[Array, "n_atom"] + lattice_vectors: Float[Array, "3 3"] + nuclear_pos: Float[Array, "n_atom 3"] + ao: Float[Array, "n_flat_grid n_orbitals"] + grad_ao: Float[Array, "n_flat_grid n_orbitals 3"] + grad_n_ao: PyTree + rdm1: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + nuclear_repulsion: Scalar + h1e: Float[Array, "n_kpt n_orbitals n_orbitals"] + vj: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + mo_coeff: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + mo_occ: Float[Array, "n_spin n_kpt n_orbitals"] + mo_energy: Float[Array, "n_spin n_kpt n_orbitals"] + kpt_info: KPointInfo + mf_energy: Optional[Scalar] = None + s1e: Optional[Float[Array, "n_kpt n_orbitals n_orbitals"]] = None + omegas: Optional[Float[Array, "omega"]] = None + chi: Optional[Float[Array, "grid omega spin orbitals"]] = None # Come back to this to figure out correct dims for k-points + rep_tensor: Optional[Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"]] = None + energy: Optional[Scalar] = None + basis: Optional[Int[Array, '...']] = None # The name is saved as a list of integers, JAX does not accept str + name: Optional[Int[Array, '...']] = None # The name is saved as a list of integers, JAX does not accept str + spin: Optional[Scalar] = 0 + charge: Optional[Scalar] = 0 + unit_Angstrom: Optional[bool] = True + grid_level: Optional[Scalar] = 2 + scf_iteration: Optional[Scalar] = 50 + fock: Optional[Float[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None \ No newline at end of file From 4d66af883d0816161f78ebe9584659582af3fad4 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 1 Nov 2023 01:35:21 -0400 Subject: [PATCH 03/36] kinetic + external is correct, but I need to reconsider array typing as I forgot that BZ samping makes many quantities complex valued. Jax is yet to complain though. --- grad_dft/solid.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 8fc8ce1..d9aedd6 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -13,6 +13,7 @@ # limitations under the License. import jax.numpy as jnp +from jax.lax import Precision from typing import List, Optional from flax import struct @@ -116,4 +117,37 @@ class Solid: unit_Angstrom: Optional[bool] = True grid_level: Optional[Scalar] = 2 scf_iteration: Optional[Scalar] = 50 - fock: Optional[Float[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None \ No newline at end of file + fock: Optional[Float[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None + + + +def one_body_energy( + rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], + h1e: Float[Array, "n_kpt n_orbitals n_orbitals"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision=Precision.HIGHEST, +) -> Scalar: + r"""A function that computes the one-body energy of a DFT functional. + + Parameters + ---------- + rdm1 : Float[Array, "n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix for each k-point. + h1e : Float[Array, "orbitals orbitals"] + The 1-electron Hamiltonian for each k-point. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + + Returns + ------- + Scalar + """ + # Compute one-body energy for each k-point + h1e_energy_per_k = jnp.einsum("kij,kij->k", rdm1, h1e, precision=precision) + + # Weighted sum over k-points + total_h1e_energy = jnp.sum(weights * h1e_energy_per_k) + return total_h1e_energy \ No newline at end of file From dde47adbce5b8a917d21d4b91eb47bb9a971b4ba Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 1 Nov 2023 20:43:20 -0400 Subject: [PATCH 04/36] Figured out that the coulomb energy needs a repulsion_tensor for every crystal momentum conserving k-point quartet in the 1BZ. Tihs is now dealt with in _package_outputs (which I hope to refactor at some point). We now have this for the full and irreducible BZ. We should now be able to calculate the coulomb energy --- grad_dft/interface/pyscf.py | 56 +++++++++++++++++---- grad_dft/solid.py | 99 ++++++++++++++++++++++++++++++++++--- 2 files changed, 140 insertions(+), 15 deletions(-) diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 4ddfc99..824ade7 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -14,7 +14,7 @@ from random import shuffle from typing import List, Optional, Tuple, Union, Sequence, Dict -from itertools import chain, combinations_with_replacement +from itertools import chain, combinations_with_replacement, product import os import numpy as np @@ -54,9 +54,10 @@ def grid_from_pyscf(grids: Grids, dtype: Optional[DType] = None) -> Grid: return Grid(coords, weights) -def kpt_info_from_pyscf(kmf: DensityFunctional): +def kpt_info_from_pyscf(kmf: DensityFunctional, sym="s1"): kpts = kmf.kpts if isinstance(kpts, KPoints): + # 1BZ single k-points: kinetic + external terms kpts_abs = kpts.kpts kpts_scaled = kpts.kpts_scaled weights = kpts.weights_ibz @@ -64,23 +65,40 @@ def kpt_info_from_pyscf(kmf: DensityFunctional): ibz2bz_map = kpts.ibz2bz kpts_ir_abs = kpts.kpts_ibz kpts_ir_scaled = kpts.kpts_scaled_ibz + + # 1BZ k-point quartets: used for ERI to compute coulomb energy + k4_idx, k4_weights, k4_bz2ibz = kpts.make_k4_ibz(sym=sym, return_ops=False) else: + # No symmetries used kpts_abs = kpts kpts_scaled = kmf.cell.get_scaled_kpts(kpts_abs) # Equal weights - weights = jnp.ones(shape=(kpts_abs.shape[0],))/kpts_abs.shape[0] + weights = np.ones(shape=(kpts_abs.shape[0],))/kpts_abs.shape[0] + + from pyscf.pbc.lib.kpts_helper import get_kconserv + + # manually retrieve the crystal momentum conserving kpts indices from + # the whole 1BZ + k_indices = get_kconserv(kmf.cell, kpts=kpts_abs) + all_3tuple_idx = product(range(kpts_abs.shape[0]), repeat=3) + k4_idx = np.asarray([[k, l, m, k_indices[k, l, m]] for k, l, m in all_3tuple_idx]) + k4_weights = np.ones(shape=(k4_idx.shape[0],))/k4_idx.shape[0] bz2ibz_map = None ibz2bz_map = None kpts_ir_abs = None kpts_ir_scaled = None + k4_bz2ibz = None return KPointInfo( kpts_abs, kpts_scaled, weights, + k4_idx, + k4_weights, bz2ibz_map, ibz2bz_map, kpts_ir_abs, - kpts_ir_scaled + kpts_ir_scaled, + k4_bz2ibz ) @@ -191,7 +209,8 @@ def solid_from_pyscf( ) -> Molecule: # mf, grids = _maybe_run_kernel(mf, grids) grid = grid_from_pyscf(kmf.grids, dtype=dtype) - + pyscf_dat = _package_outputs(kmf, kmf.grids, scf_iteration, grad_order) + kpt_info = pyscf_dat[-1] ( ao, grad_ao, @@ -207,7 +226,7 @@ def solid_from_pyscf( s1e, fock, rep_tensor, - ) = to_device_arrays(*_package_outputs(kmf, kmf.grids, scf_iteration, grad_order), dtype=dtype) + ) = to_device_arrays(*pyscf_dat[0:-1], dtype=dtype) atom_index, nuclear_pos = to_device_arrays( [elements.ELEMENTS.index(e) for e in kmf.mol.elements], @@ -243,7 +262,6 @@ def solid_from_pyscf( else: grid_level = None lattice_vectors = kmf.cell.lattice_vectors() - kpt_info = kpt_info_from_pyscf(kmf) return Solid( grid, atom_index, @@ -688,6 +706,7 @@ def _package_outputs( grids: Optional[Grids] = None, scf_iteration: Scalar = jnp.int32(50), grad_order: Scalar = jnp.int32(2), + sym: Optional[str] = "s1" ): ao_ = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) ao = ao_[0] @@ -755,7 +774,16 @@ def _package_outputs( ) # The 2 is to compensate for the /2 in the definition of the density matrix dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) + kpt_info = kpt_info_from_pyscf(mf, sym=sym) + # Compute ERIs + density_fitter = df.DF(mf.cell, kpts=kpt_info.kpts_abs) + rep_tensor = np.empty(shape=(kpt_info.k4_idx.shape[0], nao, nao, nao, nao), dtype=np.complex128) + all_kpts = kpt_info.kpts_abs + for four_idx in kpt_info.k4_idx: + kpt_4 = np.array([all_kpts[i] for i in four_idx]) + rep_tensor_k4 =\ + density_fitter.get_eri(compact=False, kpts=kpt_4).reshape(nao, nao, nao, nao) + rep_tensor[0, :, :, :, :] = rep_tensor_k4 # Unrestricted (spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] != 1: @@ -772,7 +800,16 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) + kpt_info = kpt_info_from_pyscf(mf) + # Compute ERIs + density_fitter = df.DF(mf.cell, kpts=kpt_info.kpts_abs) + rep_tensor = np.empty(shape=(kpt_info.k4_idx.shape[0], nao, nao, nao, nao), dtype=np.complex128) + all_kpts = kpt_info.kpts_abs + for four_idx in kpt_info.k4_idx: + kpt_4 = np.array([all_kpts[i] for i in four_idx]) + rep_tensor_k4 =\ + density_fitter.get_eri(compact=False, kpts=kpt_4).reshape(nao, nao, nao, nao) + rep_tensor[0, :, :, :, :] = rep_tensor_k4 # Restricted (non-spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] == 1: @@ -860,6 +897,7 @@ def _package_outputs( s1e, fock, rep_tensor, + kpt_info ) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index d9aedd6..a0bd845 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -64,6 +64,9 @@ class KPointInfo: To properly take advantage of space-group and time-reversal symmetry, informations about mappings between the BZ -> IBZ and vice versa is needed as well as weights which are not neccesarily equal. + variables containing *k4* pertain to the momentum conserving quarters of k-points which are needed to + compute electron repulsion integrals (ERI's). + n_kpts_or_n_ikpts in weights could be the total number of points in the full BZ or the number of points in the IBZ, context dependent. I.e, if the next variables are set to None, the first case applies. If they are not None, the second does. @@ -72,10 +75,13 @@ class KPointInfo: kpts_abs: Float[Array, "n_kpts 3"] kpts_scaled: Float[Array, "n_kpts 3"] weights: Float[Array, "n_kpts_or_n_ir_kpts"] + k4_idx: Int[Array, "n_k4pts 4"] + k4_weights: Float[Array, "n_k4pts_or_n_ir_k4pts"] bz2ibz_map: Optional[Float[Array, "n_kpts"]] ibz2bz_map: Optional[Float[Array, "n_kpts_ir"]] kpts_ir_abs: Optional[Float[Array, "n_kpts_ir 3"]] kpts_ir_scaled: Optional[Float[Array, "n_kpts_ir 3"]] + k4_bz2ibz: Optional[Int[Array, "n_kpt**3"]] # This ends up being None is s4 symmetry is used in k4 identification @struct.dataclass @@ -133,7 +139,7 @@ def one_body_energy( ---------- rdm1 : Float[Array, "n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix for each k-point. - h1e : Float[Array, "orbitals orbitals"] + h1e : Float[Array, "n_kpt orbitals orbitals"] The 1-electron Hamiltonian for each k-point. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which sum to 1. If we are working @@ -145,9 +151,90 @@ def one_body_energy( ------- Scalar """ - # Compute one-body energy for each k-point - h1e_energy_per_k = jnp.einsum("kij,kij->k", rdm1, h1e, precision=precision) + h1e_energy = jnp.einsum("k,kij,kij->", weights, rdm1, h1e, precision=precision) + return h1e_energy + +def coulomb_potential( + rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], + rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"], + precision=Precision.HIGHEST, +) -> Float[Array, "n_knpt n_orbitals n_orbitals"]: + r""" + Compute the Coulomb potential matrix. + + Parameters + ---------- + rdm1 : Float[Array, "n_kpt orbitals orbitals"] + The 1-body reduced density matrix. + Equivalent to mf.make_rdm1() in pyscf. + rep_tensor : Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor. + Equivalent to df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) in pyscf. + precision : Precision, optional + The precision to use for the computation, by default Precision.HIGHEST + + Returns + ------- + Float[Array, "spin orbitals orbitals"] + """ + v_coul_k = jnp.einsum("pqrt,krt->kpq", rep_tensor, rdm1, precision=precision) + return v_coul_k + +# def coulomb_energy( +# rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], +# rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals orbitals"], +# weights: Float[Array, "n_kpts_or_n_ir_kpts"], +# precision=Precision.HIGHEST, +# ) -> Scalar: +# r"""A function that computes the Coulomb two-body energy of a DFT functional. + +# Parameters +# ---------- +# rdm1 : Float[Array, "n_kpt orbitals orbitals"] +# The 1-body reduced density matrix. +# rep_tensor : Float[Array, "orbitals orbitals orbitals orbitals"] +# The repulsion tensor. +# weights : Float[Array, "n_kpts_or_n_ir_kpts"] +# The weights for each k-point which sum to 1. If we are working +# in the full 1BZ, weights are equal. If we are working in the +# irreducible 1BZ, weights may not be equal if symmetry can be +# exploited. + +# Returns +# ------- +# Scalar +# """ +# v_coul_k = coulomb_potential(rdm1, rep_tensor, precision) +# coulomb_energy = jnp.einsum("k,kpq,kpq->", weights, rdm1, v_coul_k, precision=precision) / 2.0 +# return coulomb_energy + +def coulomb_energy( + rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], + rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision=Precision.HIGHEST, +) -> Scalar: + r"""A function that computes the Coulomb two-body energy of a DFT functional. + + Parameters + ---------- + rdm1 : Float[Array, "n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + rep_tensor : Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + + Returns + ------- + Scalar + """ + v_coul_k = coulomb_potential(rdm1, rep_tensor, precision) + + # Summing over k-points with weights + coulomb_energy = sum(weights[k] * jnp.einsum("pq,pq->", rdm1[k], v_coul_k[k], precision=precision) for k in range(len(weights))) / 2.0 - # Weighted sum over k-points - total_h1e_energy = jnp.sum(weights * h1e_energy_per_k) - return total_h1e_energy \ No newline at end of file + return coulomb_energy From 9d6d2d32264173ee2d8a8dd3296fd6de6a43a05c Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 6 Nov 2023 20:06:17 -0500 Subject: [PATCH 05/36] Disabled symmetry adaptive functions for now. Will come back to this later. All k-pairs now computer for coulomb energy --- grad_dft/interface/pyscf.py | 99 ++++++++++---------- grad_dft/solid.py | 175 +++++++++++++++++------------------- 2 files changed, 131 insertions(+), 143 deletions(-) diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 824ade7..3af097c 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -42,7 +42,7 @@ import h5py from pyscf import cc, dft, scf -from jaxtyping import Array, Scalar, Int +from jaxtyping import Array, Scalar, Int, Bool from grad_dft.external import _nu_chunk @@ -54,9 +54,13 @@ def grid_from_pyscf(grids: Grids, dtype: Optional[DType] = None) -> Grid: return Grid(coords, weights) -def kpt_info_from_pyscf(kmf: DensityFunctional, sym="s1"): +def kpt_info_from_pyscf(kmf: DensityFunctional): kpts = kmf.kpts if isinstance(kpts, KPoints): + msg = """PySCF KPoint object detected. Symmetry adapted calculations are not yet possible. Please ensure + that the supplied k-points to the PySCF Molecule object have space_group_symmetry=False and time_reversal_symmetry=False. + """ + raise NotImplementedError(msg) # 1BZ single k-points: kinetic + external terms kpts_abs = kpts.kpts kpts_scaled = kpts.kpts_scaled @@ -65,40 +69,30 @@ def kpt_info_from_pyscf(kmf: DensityFunctional, sym="s1"): ibz2bz_map = kpts.ibz2bz kpts_ir_abs = kpts.kpts_ibz kpts_ir_scaled = kpts.kpts_scaled_ibz - - # 1BZ k-point quartets: used for ERI to compute coulomb energy - k4_idx, k4_weights, k4_bz2ibz = kpts.make_k4_ibz(sym=sym, return_ops=False) else: # No symmetries used - kpts_abs = kpts - kpts_scaled = kmf.cell.get_scaled_kpts(kpts_abs) + # Equal weights - weights = np.ones(shape=(kpts_abs.shape[0],))/kpts_abs.shape[0] - - from pyscf.pbc.lib.kpts_helper import get_kconserv - - # manually retrieve the crystal momentum conserving kpts indices from - # the whole 1BZ - k_indices = get_kconserv(kmf.cell, kpts=kpts_abs) - all_3tuple_idx = product(range(kpts_abs.shape[0]), repeat=3) - k4_idx = np.asarray([[k, l, m, k_indices[k, l, m]] for k, l, m in all_3tuple_idx]) - k4_weights = np.ones(shape=(k4_idx.shape[0],))/k4_idx.shape[0] - bz2ibz_map = None - ibz2bz_map = None - kpts_ir_abs = None - kpts_ir_scaled = None - k4_bz2ibz = None + + # bz2ibz_map = None + # ibz2bz_map = None + # kpts_ir_abs = None + # kpts_ir_scaled = None + kpts_abs, kpts_scaled, weights = \ + to_device_arrays( + kpts, + kmf.cell.get_scaled_kpts(kpts), + np.ones(shape=(kpts.shape[0],))/kpts.shape[0], + dtype=None + ) return KPointInfo( kpts_abs, kpts_scaled, weights, - k4_idx, - k4_weights, - bz2ibz_map, - ibz2bz_map, - kpts_ir_abs, - kpts_ir_scaled, - k4_bz2ibz + # bz2ibz_map, + # ibz2bz_map, + # kpts_ir_abs, + # kpts_ir_scaled, ) @@ -706,7 +700,6 @@ def _package_outputs( grids: Optional[Grids] = None, scf_iteration: Scalar = jnp.int32(50), grad_order: Scalar = jnp.int32(2), - sym: Optional[str] = "s1" ): ao_ = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) ao = ao_[0] @@ -774,16 +767,19 @@ def _package_outputs( ) # The 2 is to compensate for the /2 in the definition of the density matrix dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - kpt_info = kpt_info_from_pyscf(mf, sym=sym) - # Compute ERIs - density_fitter = df.DF(mf.cell, kpts=kpt_info.kpts_abs) - rep_tensor = np.empty(shape=(kpt_info.k4_idx.shape[0], nao, nao, nao, nao), dtype=np.complex128) - all_kpts = kpt_info.kpts_abs - for four_idx in kpt_info.k4_idx: - kpt_4 = np.array([all_kpts[i] for i in four_idx]) - rep_tensor_k4 =\ - density_fitter.get_eri(compact=False, kpts=kpt_4).reshape(nao, nao, nao, nao) - rep_tensor[0, :, :, :, :] = rep_tensor_k4 + + # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation + all_kpts = mf.kpts + nkpt = all_kpts.shape[0] + density_fitter = df.DF(mf.cell, kpts=all_kpts) + rep_tensor = np.empty(shape=(nkpt, nkpt, nao, nao, nao, nao), dtype=np.complex128) + for ikpt in range(nkpt): + for jkpt in range(nkpt): + k_quartet = np.array([all_kpts[ikpt], all_kpts[ikpt], all_kpts[jkpt], all_kpts[jkpt]]) + rep_tensor_kquartet =\ + density_fitter.get_eri(compact=False, kpts=k_quartet).reshape(nao, nao, nao, nao) + rep_tensor[ikpt, jkpt, :, :, :, :] = rep_tensor_kquartet + kpt_info = kpt_info_from_pyscf(mf) # Unrestricted (spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] != 1: @@ -800,16 +796,19 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) + + # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation + all_kpts = mf.kpts + nkpt = all_kpts.shape[0] + density_fitter = df.DF(mf.cell, kpts=all_kpts) + rep_tensor = np.empty(shape=(nkpt, nkpt, nao, nao, nao, nao), dtype=np.complex128) + for ikpt in range(nkpt): + for jkpt in range(nkpt): + k_quartet = np.array([all_kpts[ikpt], all_kpts[ikpt], all_kpts[jkpt], all_kpts[jkpt]]) + rep_tensor_kquartet =\ + density_fitter.get_eri(compact=False, kpts=k_quartet).reshape(nao, nao, nao, nao) + rep_tensor[ikpt, jkpt, :, :, :, :] = rep_tensor_kquartet kpt_info = kpt_info_from_pyscf(mf) - # Compute ERIs - density_fitter = df.DF(mf.cell, kpts=kpt_info.kpts_abs) - rep_tensor = np.empty(shape=(kpt_info.k4_idx.shape[0], nao, nao, nao, nao), dtype=np.complex128) - all_kpts = kpt_info.kpts_abs - for four_idx in kpt_info.k4_idx: - kpt_4 = np.array([all_kpts[i] for i in four_idx]) - rep_tensor_k4 =\ - density_fitter.get_eri(compact=False, kpts=kpt_4).reshape(nao, nao, nao, nao) - rep_tensor[0, :, :, :, :] = rep_tensor_k4 # Restricted (non-spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] == 1: @@ -844,6 +843,7 @@ def _package_outputs( vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) + kpt_info = kpt_info_from_pyscf(mf) # Unrestricted (spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] == 1: @@ -871,6 +871,7 @@ def _package_outputs( vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) rep_tensor = df.DF(mf.cell).get_ao_eri(compact=False).reshape(nao, nao, nao, nao) + kpt_info = kpt_info_from_pyscf(mf) else: raise RuntimeError( diff --git a/grad_dft/solid.py b/grad_dft/solid.py index a0bd845..098eee4 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -16,8 +16,13 @@ from jax.lax import Precision from typing import List, Optional +from typeguard import typechecked +from grad_dft.utils import vmap_chunked +from functools import partial +from jax import jit + from flax import struct -from jaxtyping import Array, PyTree, Scalar, Float, Int, jaxtyped +from jaxtyping import Array, PyTree, Scalar, Float, Int, Complex, jaxtyped @struct.dataclass @@ -63,10 +68,7 @@ class KPointInfo: Most simply, we need the array of k-points in absolute and fractional forms with equal weights. To properly take advantage of space-group and time-reversal symmetry, informations about mappings between the BZ -> IBZ and vice versa is needed as well as weights which are not neccesarily equal. - - variables containing *k4* pertain to the momentum conserving quarters of k-points which are needed to - compute electron repulsion integrals (ERI's). - + n_kpts_or_n_ikpts in weights could be the total number of points in the full BZ or the number of points in the IBZ, context dependent. I.e, if the next variables are set to None, the first case applies. If they are not None, the second does. @@ -75,14 +77,11 @@ class KPointInfo: kpts_abs: Float[Array, "n_kpts 3"] kpts_scaled: Float[Array, "n_kpts 3"] weights: Float[Array, "n_kpts_or_n_ir_kpts"] - k4_idx: Int[Array, "n_k4pts 4"] - k4_weights: Float[Array, "n_k4pts_or_n_ir_k4pts"] - bz2ibz_map: Optional[Float[Array, "n_kpts"]] - ibz2bz_map: Optional[Float[Array, "n_kpts_ir"]] - kpts_ir_abs: Optional[Float[Array, "n_kpts_ir 3"]] - kpts_ir_scaled: Optional[Float[Array, "n_kpts_ir 3"]] - k4_bz2ibz: Optional[Int[Array, "n_kpt**3"]] # This ends up being None is s4 symmetry is used in k4 identification - + # Coming Soon: take advantage of Space Group symmetry for efficient simulation + # bz2ibz_map: Optional[Float[Array, "n_kpts"]] + # ibz2bz_map: Optional[Float[Array, "n_kpts_ir"]] + # kpts_ir_abs: Optional[Float[Array, "n_kpts_ir 3"]] + # kpts_ir_scaled: Optional[Float[Array, "n_kpts_ir 3"]] @struct.dataclass class Solid: @@ -102,19 +101,19 @@ class Solid: ao: Float[Array, "n_flat_grid n_orbitals"] grad_ao: Float[Array, "n_flat_grid n_orbitals 3"] grad_n_ao: PyTree - rdm1: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] nuclear_repulsion: Scalar - h1e: Float[Array, "n_kpt n_orbitals n_orbitals"] - vj: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + h1e: Complex[Array, "n_kpt n_orbitals n_orbitals"] + vj: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] mo_coeff: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] mo_occ: Float[Array, "n_spin n_kpt n_orbitals"] mo_energy: Float[Array, "n_spin n_kpt n_orbitals"] kpt_info: KPointInfo mf_energy: Optional[Scalar] = None - s1e: Optional[Float[Array, "n_kpt n_orbitals n_orbitals"]] = None + s1e: Optional[Complex[Array, "n_kpt n_orbitals n_orbitals"]] = None omegas: Optional[Float[Array, "omega"]] = None chi: Optional[Float[Array, "grid omega spin orbitals"]] = None # Come back to this to figure out correct dims for k-points - rep_tensor: Optional[Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"]] = None + rep_tensor: Optional[Complex[Array, "n_k4pt n_orbitals n_orbitals n_orbitals n_orbitals"]] = None energy: Optional[Scalar] = None basis: Optional[Int[Array, '...']] = None # The name is saved as a list of integers, JAX does not accept str name: Optional[Int[Array, '...']] = None # The name is saved as a list of integers, JAX does not accept str @@ -123,13 +122,14 @@ class Solid: unit_Angstrom: Optional[bool] = True grid_level: Optional[Scalar] = 2 scf_iteration: Optional[Scalar] = 50 - fock: Optional[Float[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None + fock: Optional[Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None - - +@jaxtyped +@typechecked +@partial(jit, static_argnames=["precision"]) def one_body_energy( - rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], - h1e: Float[Array, "n_kpt n_orbitals n_orbitals"], + rdm1: Complex[Array, "n_kpt n_orbitals n_orbitals"], + h1e: Complex[Array, "n_kpt n_orbitals n_orbitals"], weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision=Precision.HIGHEST, ) -> Scalar: @@ -142,7 +142,7 @@ def one_body_energy( h1e : Float[Array, "n_kpt orbitals orbitals"] The 1-electron Hamiltonian for each k-point. weights : Float[Array, "n_kpts_or_n_ir_kpts"] - The weights for each k-point which sum to 1. If we are working + The weights for each k-point which together sum to 1. If we are working in the full 1BZ, weights are equal. If we are working in the irreducible 1BZ, weights may not be equal if symmetry can be exploited. @@ -152,89 +152,76 @@ def one_body_energy( Scalar """ h1e_energy = jnp.einsum("k,kij,kij->", weights, rdm1, h1e, precision=precision) - return h1e_energy - -def coulomb_potential( - rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], - rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"], - precision=Precision.HIGHEST, -) -> Float[Array, "n_knpt n_orbitals n_orbitals"]: - r""" - Compute the Coulomb potential matrix. + return h1e_energy.real - Parameters - ---------- - rdm1 : Float[Array, "n_kpt orbitals orbitals"] - The 1-body reduced density matrix. - Equivalent to mf.make_rdm1() in pyscf. - rep_tensor : Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"] - The repulsion tensor. - Equivalent to df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) in pyscf. - precision : Precision, optional - The precision to use for the computation, by default Precision.HIGHEST - Returns - ------- - Float[Array, "spin orbitals orbitals"] - """ - v_coul_k = jnp.einsum("pqrt,krt->kpq", rep_tensor, rdm1, precision=precision) - return v_coul_k - -# def coulomb_energy( -# rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], -# rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals orbitals"], -# weights: Float[Array, "n_kpts_or_n_ir_kpts"], -# precision=Precision.HIGHEST, -# ) -> Scalar: -# r"""A function that computes the Coulomb two-body energy of a DFT functional. - -# Parameters -# ---------- -# rdm1 : Float[Array, "n_kpt orbitals orbitals"] -# The 1-body reduced density matrix. -# rep_tensor : Float[Array, "orbitals orbitals orbitals orbitals"] -# The repulsion tensor. -# weights : Float[Array, "n_kpts_or_n_ir_kpts"] -# The weights for each k-point which sum to 1. If we are working -# in the full 1BZ, weights are equal. If we are working in the -# irreducible 1BZ, weights may not be equal if symmetry can be -# exploited. - -# Returns -# ------- -# Scalar -# """ -# v_coul_k = coulomb_potential(rdm1, rep_tensor, precision) -# coulomb_energy = jnp.einsum("k,kpq,kpq->", weights, rdm1, v_coul_k, precision=precision) / 2.0 -# return coulomb_energy def coulomb_energy( rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], - rep_tensor: Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"], - weights: Float[Array, "n_kpts_or_n_ir_kpts"], + rep_tensor: Float[Array, "n_kpt_quartets n_orbitals n_orbitals n_orbitals n_orbitals"], + weights_k4: Float[Array, "n_kpt_quartets"], + k4_idxs: Int[Array, "n_k4pts 4"], + bz2ibz_map: Float[Array, "n_kpts"], precision=Precision.HIGHEST, ) -> Scalar: - r"""A function that computes the Coulomb two-body energy of a DFT functional. - + """ + Compute the Coulomb energy considering crystal momentum conserving k-point quartets. + Parameters ---------- - rdm1 : Float[Array, "n_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix. - rep_tensor : Float[Array, "n_orbitals n_orbitals n_orbitals n_orbitals"] - The repulsion tensor. - weights : Float[Array, "n_kpts_or_n_ir_kpts"] - The weights for each k-point which sum to 1. If we are working - in the full 1BZ, weights are equal. If we are working in the - irreducible 1BZ, weights may not be equal if symmetry can be - exploited. + rdm1 : Float[Array, "n_ir_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix at each irreducible k-point. + rep_tensor : Float[Array, "n_ir_kpt_quartets n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor indexed by k-point quartets and orbitals. + weights_k4 : Float[Array, "n_ir_kpt_quartets"] + The weights associated with each k-point quartet. + k4_idxs : Int[Array, "n_ir_kpt_quartets 4"]. + Each element in the first dimension gives the indices in the full 1BZ for + four crystal momentum conserving k-points. I.e, the k-point quartet indices. + bz2ibz_map : Float[Array, "n_kpts"]. + Given an index in the 1BZ, return the corresponding index in the irreducible 1BZ. + precision : Precision, optional + The precision to use for the computation. Returns ------- Scalar + The Coulomb energy as: + .. math:: + E_C = \frac{1}{2} \sum_{\mathbf{k}_1, \mathbf{k}_2, \mathbf{k}_3, \mathbf{k}_4} \delta_{\mathbf{k}_1 - \mathbf{k}_2 + \mathbf{k}_3 - \mathbf{k}_4, \mathbf{G}} w(\mathbf{k}_1, \mathbf{k}_2, \mathbf{k}_3, \mathbf{k}_4) \sum_{pqrs} D_{pq}(\mathbf{k}_1) (pq|rs)_{\mathbf{k}_1\mathbf{k}_2\mathbf{k}_3\mathbf{k}_4} D_{rs}(\mathbf{k}_3) """ - v_coul_k = coulomb_potential(rdm1, rep_tensor, precision) - - # Summing over k-points with weights - coulomb_energy = sum(weights[k] * jnp.einsum("pq,pq->", rdm1[k], v_coul_k[k], precision=precision) for k in range(len(weights))) / 2.0 + + # Initialize Coulomb energy to zero + coulomb_energy = 0.0 + + # Loop over all k-point quartets + for i, k_quartet_idxs in enumerate(k4_idxs): + # Extract the ERIs for this k-point quartet + eri_kpt_quartet = rep_tensor[i] + + # Determine the indices for the k-points involved in this quartet + k1_idx = k_quartet_idxs[0] + k2_idx = k_quartet_idxs[1] + k3_idx = k_quartet_idxs[2] + k4_idx = k_quartet_idxs[3] + + # k1_idx_ibz = bz2ibz_map[k1_idx] + # k3_idx_ibz = bz2ibz_map[k3_idx] + + + # Compute the contribution to the Coulomb energy from this k-point quartet + # energy_contribution = jnp.einsum( + # "qp,pqrs,sr->", rdm1[k1_idx], eri_kpt_quartet, rdm1[k3_idx], precision=precision + # ) + energy_contribution = jnp.trace( + rdm1[k1_idx] @ eri_kpt_quartet @ rdm1[k3_idx] + ) + # Accumulate the weighted energy contribution + coulomb_energy += weights_k4[i] * energy_contribution + # Account for double-counting in the ERI + coulomb_energy /= 2.0 + return coulomb_energy + + From afadeeb52b0020368a36cf86d21374b98f31acaa Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 6 Nov 2023 22:05:40 -0500 Subject: [PATCH 06/36] Non XC conribution to total energy is correct --- grad_dft/solid.py | 160 +++++++++++++++++++++++++++++----------------- 1 file changed, 103 insertions(+), 57 deletions(-) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 098eee4..f58c1d6 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -124,6 +124,12 @@ class Solid: scf_iteration: Optional[Scalar] = 50 fock: Optional[Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None + def nonXC(self, *args, **kwargs) -> Scalar: + r"""Compute all terms in the KS total energy with the exception of the XC component + """ + return nonXC(self.rdm1.sum(axis=0), self.h1e, self.rep_tensor, self.nuclear_repulsion, self.kpt_info.weights, *args, **kwargs) + + @jaxtyped @typechecked @partial(jit, static_argnames=["precision"]) @@ -133,13 +139,13 @@ def one_body_energy( weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision=Precision.HIGHEST, ) -> Scalar: - r"""A function that computes the one-body energy of a DFT functional. + r"""Compute the one-body (kinetic + external) component of the KS total energy. Parameters ---------- - rdm1 : Float[Array, "n_kpt n_orbitals n_orbitals"] + rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix for each k-point. - h1e : Float[Array, "n_kpt orbitals orbitals"] + h1e : Complex[Array, "n_kpt orbitals orbitals"] The 1-electron Hamiltonian for each k-point. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which together sum to 1. If we are working @@ -151,77 +157,117 @@ def one_body_energy( ------- Scalar """ - h1e_energy = jnp.einsum("k,kij,kij->", weights, rdm1, h1e, precision=precision) + h1e_energy = jnp.einsum("k,kij,kji->", weights, rdm1, h1e, precision=precision) return h1e_energy.real +@jaxtyped +@typechecked +@partial(jit, static_argnames=["precision"]) +def coulomb_potential( + rdm1: Complex[Array, "n_kpt n_orbitals n_orbitals"], + rep_tensor: Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision=Precision.HIGHEST +) -> Complex[Array, "n_kpts_or_n_ir_kpts n_orbitals n_orbitals"]: + r""" + Computes the Coulomb potential matrix for all k-points. + + Parameters + ---------- + rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + rep_tensor : Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor computed on a grid of nkpt x nkpt + precision : Precision, optional + The precision to use for the computation, by default Precision.HIGHEST + Returns + ------- + Complex[Array, "n_kpts_or_n_ir_kpts n_orbitals n_orbitals"] + """ + + # k and q are k-point indices while i, j, l and m are orbital indices + v_k = jnp.einsum("k,kqijlm,qml->kij", weights, rep_tensor, rdm1, precision=precision) + return v_k + +@jaxtyped +@typechecked +@partial(jit, static_argnames=["precision"]) def coulomb_energy( - rdm1: Float[Array, "n_kpt n_orbitals n_orbitals"], - rep_tensor: Float[Array, "n_kpt_quartets n_orbitals n_orbitals n_orbitals n_orbitals"], - weights_k4: Float[Array, "n_kpt_quartets"], - k4_idxs: Int[Array, "n_k4pts 4"], - bz2ibz_map: Float[Array, "n_kpts"], - precision=Precision.HIGHEST, + rdm1: Complex[Array, "n_kpt n_orbitals n_orbitals"], + rep_tensor: Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision=Precision.HIGHEST ) -> Scalar: """ - Compute the Coulomb energy considering crystal momentum conserving k-point quartets. - + Compute the Coulomb energy + Parameters ---------- - rdm1 : Float[Array, "n_ir_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix at each irreducible k-point. - rep_tensor : Float[Array, "n_ir_kpt_quartets n_orbitals n_orbitals n_orbitals n_orbitals"] - The repulsion tensor indexed by k-point quartets and orbitals. - weights_k4 : Float[Array, "n_ir_kpt_quartets"] - The weights associated with each k-point quartet. - k4_idxs : Int[Array, "n_ir_kpt_quartets 4"]. - Each element in the first dimension gives the indices in the full 1BZ for - four crystal momentum conserving k-points. I.e, the k-point quartet indices. - bz2ibz_map : Float[Array, "n_kpts"]. - Given an index in the 1BZ, return the corresponding index in the irreducible 1BZ. + rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + rep_tensor : Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor computed on a grid of nkpt x nkpt + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. precision : Precision, optional - The precision to use for the computation. + The precision to use for the computation, by default Precision.HIGHEST Returns ------- Scalar - The Coulomb energy as: - .. math:: - E_C = \frac{1}{2} \sum_{\mathbf{k}_1, \mathbf{k}_2, \mathbf{k}_3, \mathbf{k}_4} \delta_{\mathbf{k}_1 - \mathbf{k}_2 + \mathbf{k}_3 - \mathbf{k}_4, \mathbf{G}} w(\mathbf{k}_1, \mathbf{k}_2, \mathbf{k}_3, \mathbf{k}_4) \sum_{pqrs} D_{pq}(\mathbf{k}_1) (pq|rs)_{\mathbf{k}_1\mathbf{k}_2\mathbf{k}_3\mathbf{k}_4} D_{rs}(\mathbf{k}_3) """ + v_k = coulomb_potential(rdm1, rep_tensor, weights, precision) + coulomb_energy = jnp.einsum("k,kij,kji->", weights, rdm1, v_k)/2.0 + return coulomb_energy.real - # Initialize Coulomb energy to zero - coulomb_energy = 0.0 +@jaxtyped +@typechecked +@partial(jit, static_argnames=["precision"]) +def nonXC( + rdm1: Complex[Array, "n_kpt n_orbitals n_orbitals"], + h1e: Complex[Array, "n_kpt n_orbitals n_orbitals"], + rep_tensor: Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"], + nuclear_repulsion: Scalar, + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision=Precision.HIGHEST, +) -> Scalar: + r"""Compute all terms in the KS total energy with the exception of the XC component - # Loop over all k-point quartets - for i, k_quartet_idxs in enumerate(k4_idxs): - # Extract the ERIs for this k-point quartet - eri_kpt_quartet = rep_tensor[i] - - # Determine the indices for the k-points involved in this quartet - k1_idx = k_quartet_idxs[0] - k2_idx = k_quartet_idxs[1] - k3_idx = k_quartet_idxs[2] - k4_idx = k_quartet_idxs[3] - - # k1_idx_ibz = bz2ibz_map[k1_idx] - # k3_idx_ibz = bz2ibz_map[k3_idx] - - - # Compute the contribution to the Coulomb energy from this k-point quartet - # energy_contribution = jnp.einsum( - # "qp,pqrs,sr->", rdm1[k1_idx], eri_kpt_quartet, rdm1[k3_idx], precision=precision - # ) - energy_contribution = jnp.trace( - rdm1[k1_idx] @ eri_kpt_quartet @ rdm1[k3_idx] - ) - # Accumulate the weighted energy contribution - coulomb_energy += weights_k4[i] * energy_contribution - - # Account for double-counting in the ERI - coulomb_energy /= 2.0 + Parameters + ---------- + rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + h1e : Complex[Array, "n_kpt orbitals orbitals"] + The 1-electron Hamiltonian for each k-point. + Equivalent to mf.get_hcore(mf.mol) in pyscf. + rep_tensor : Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"] + The repulsion tensor computed on a grid of nkpt x nkpt + nuclear_repulsion : Scalar + The nuclear repulsion energy. + Equivalent to mf.mol.energy_nuc() in pyscf. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + precision : Precision, optional + The precision to use for the computation, by default Precision.HIGHEST + + Returns + ------- + Scalar + """ + kinetic_and_external = one_body_energy(rdm1, h1e, weights, precision) + # jax.debug.print("h1e_energy is {x}", x=h1e_energy) + coulomb = coulomb_energy(rdm1, rep_tensor, weights, precision) + # jax.debug.print("coulomb2e_energy is {x}", x=coulomb2e_energy) + # jax.debug.print("nuclear_repulsion is {x}", x=nuclear_repulsion) - return coulomb_energy + return nuclear_repulsion + kinetic_and_external + coulomb From 357c850904473a69c7eefe8d632145b5e195ee18 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 11:02:14 -0500 Subject: [PATCH 07/36] density and its gradients are now computable --- grad_dft/interface/pyscf.py | 5 +- grad_dft/solid.py | 325 +++++++++++++++++++++++++++++++++++- 2 files changed, 321 insertions(+), 9 deletions(-) diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 3af097c..a6f34d9 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -125,6 +125,7 @@ def molecule_from_pyscf( s1e, fock, rep_tensor, + kpt_info, ) = to_device_arrays(*_package_outputs(mf, mf.grids, scf_iteration, grad_order), dtype=dtype) atom_index, nuclear_pos = to_device_arrays( @@ -258,6 +259,7 @@ def solid_from_pyscf( lattice_vectors = kmf.cell.lattice_vectors() return Solid( grid, + kpt_info, atom_index, lattice_vectors, nuclear_pos, @@ -271,7 +273,6 @@ def solid_from_pyscf( mo_coeff, mo_occ, mo_energy, - kpt_info, mf_e_tot, s1e, omegas, @@ -732,6 +733,7 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) rep_tensor = mf.mol.intor("int2e") + kpt_info = None # Unrestricted (spin polarized), open boundary conditions elif rdm1.ndim == 3 and not hasattr(mf, "cell"): @@ -746,6 +748,7 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) rep_tensor = mf.mol.intor("int2e") + kpt_info = None # Restricted (non-spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] != 1: diff --git a/grad_dft/solid.py b/grad_dft/solid.py index f58c1d6..d495c3d 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -20,6 +20,9 @@ from grad_dft.utils import vmap_chunked from functools import partial from jax import jit +from jax.lax import fori_loop, cond + +from dataclasses import fields from flax import struct from jaxtyping import Array, PyTree, Scalar, Float, Int, Complex, jaxtyped @@ -82,6 +85,14 @@ class KPointInfo: # ibz2bz_map: Optional[Float[Array, "n_kpts_ir"]] # kpts_ir_abs: Optional[Float[Array, "n_kpts_ir 3"]] # kpts_ir_scaled: Optional[Float[Array, "n_kpts_ir 3"]] + + def to_dict(self) -> dict: + info = { + "kpts_abs": self.kpts_abs, + "kpts_scaled": self.kpts_scaled, + "kpt_weights": self.weights + } + return info @struct.dataclass class Solid: @@ -95,6 +106,7 @@ class Solid: """ grid: Grid + kpt_info: KPointInfo atom_index: Int[Array, "n_atom"] lattice_vectors: Float[Array, "3 3"] nuclear_pos: Float[Array, "n_atom 3"] @@ -105,10 +117,9 @@ class Solid: nuclear_repulsion: Scalar h1e: Complex[Array, "n_kpt n_orbitals n_orbitals"] vj: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] - mo_coeff: Float[Array, "n_spin n_kpt n_orbitals n_orbitals"] + mo_coeff: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] mo_occ: Float[Array, "n_spin n_kpt n_orbitals"] mo_energy: Float[Array, "n_spin n_kpt n_orbitals"] - kpt_info: KPointInfo mf_energy: Optional[Scalar] = None s1e: Optional[Complex[Array, "n_kpt n_orbitals n_orbitals"]] = None omegas: Optional[Float[Array, "omega"]] = None @@ -124,10 +135,85 @@ class Solid: scf_iteration: Optional[Scalar] = 50 fock: Optional[Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"]] = None + def density(self, *args, **kwargs) -> Array: + r"""Compute the electronic density at each grid point. + + Returns + ------- + Float[Array, "grid spin"] + """ + return density(self.rdm1, self.ao, self.kpt_info.weights, *args, **kwargs) + def nonXC(self, *args, **kwargs) -> Scalar: r"""Compute all terms in the KS total energy with the exception of the XC component + + Returns + ------- + Scalar + """ + return non_xc(self.rdm1.sum(axis=0), self.h1e, self.rep_tensor, self.nuclear_repulsion, self.kpt_info.weights, *args, **kwargs) + + def make_rdm1(self, *args, **kwargs) -> Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"]: + r"""Compute the 1-body reduced density matrix for each k-point. + + Returns + ------- + Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] """ - return nonXC(self.rdm1.sum(axis=0), self.h1e, self.rep_tensor, self.nuclear_repulsion, self.kpt_info.weights, *args, **kwargs) + return make_rdm1(self.mo_coeff, self.mo_occ, *args, **kwargs) + + def get_occ(self) -> Array: + r"""Compute the occupations of the molecular orbitals for each spin and k-point. + + Returns + ------- + Float[Array, "n_spin n_kpt n_orbitals"] + """ + # each k-channel has same total number of electrons, so just use index 0 in nelec calculation + # when indexing self.mo_occ + nelecs = jnp.array([self.mo_occ[i, 0].sum() for i in range(2)], dtype=jnp.int64) + return get_occ(self.mo_energy, nelecs) + + def grad_density(self, *args, **kwargs) -> Array: + r"""Compute the gradient of the electronic density at each grid point. + + Returns + ------- + Float[Array, "n_flat_grid n_spin 3"] + """ + return grad_density(self.rdm1, self.ao, self.grad_ao, self.kpt_info.weights, *args, **kwargs) + + def lapl_density(self, *args, **kwargs) -> Array: + r"""Compute the laplacian of the electronic density at each grid point. + + Returns + ------- + Float[Array, "n_flat_grid n_spin"] + """ + return lapl_density(self.rdm1, self.ao, self.grad_ao, self.grad_n_ao[2], self.kpt_info.weights, *args, **kwargs) + + def kinetic_density(self, *args, **kwargs) -> Array: + r"""Compute the kinetic energy density at each grid point. + + Returns + ------- + Float[Array, "n_flat_grid n_spin"] + """ + return kinetic_density(self.rdm1, self.grad_ao, self.kpt_info.weights, *args, **kwargs) + + def to_dict(self) -> dict: + r"""Return a dictionary with the attributes of the solid. + + Returns + ------- + Dict + """ + grid_dict = self.grid.to_dict() + kpt_dict = self.kpt_info.to_dict() + rest = {field.name: getattr(self, field.name) for field in fields(self)[2:]} + return dict(**grid_dict, **kpt_dict, **rest) + + @jaxtyped @@ -144,7 +230,7 @@ def one_body_energy( Parameters ---------- rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix for each k-point. + The 1-body reduced density matrix for each k-point. Spin has been summed over before input. h1e : Complex[Array, "n_kpt orbitals orbitals"] The 1-electron Hamiltonian for each k-point. weights : Float[Array, "n_kpts_or_n_ir_kpts"] @@ -175,7 +261,7 @@ def coulomb_potential( Parameters ---------- rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix. + The 1-body reduced density matrix. Spin has been summed over before input. rep_tensor : Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"] The repulsion tensor computed on a grid of nkpt x nkpt precision : Precision, optional @@ -206,7 +292,7 @@ def coulomb_energy( Parameters ---------- rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix. + The 1-body reduced density matrix. Spin has been summed over before input. rep_tensor : Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"] The repulsion tensor computed on a grid of nkpt x nkpt weights : Float[Array, "n_kpts_or_n_ir_kpts"] @@ -228,7 +314,7 @@ def coulomb_energy( @jaxtyped @typechecked @partial(jit, static_argnames=["precision"]) -def nonXC( +def non_xc( rdm1: Complex[Array, "n_kpt n_orbitals n_orbitals"], h1e: Complex[Array, "n_kpt n_orbitals n_orbitals"], rep_tensor: Complex[Array, "n_kpt n_kpt n_orbitals n_orbitals n_orbitals n_orbitals"], @@ -241,7 +327,7 @@ def nonXC( Parameters ---------- rdm1 : Complex[Array, "n_kpt n_orbitals n_orbitals"] - The 1-body reduced density matrix. + The 1-body reduced density matrix. Spin has been summed over before input. h1e : Complex[Array, "n_kpt orbitals orbitals"] The 1-electron Hamiltonian for each k-point. Equivalent to mf.get_hcore(mf.mol) in pyscf. @@ -271,3 +357,226 @@ def nonXC( return nuclear_repulsion + kinetic_and_external + coulomb +@jaxtyped +@typechecked +@partial(jit, static_argnames=["precision"]) +def make_rdm1( + mo_coeff: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + mo_occ: Float[Array, "n_spin n_kpt n_orbitals"], + precision=Precision.HIGHEST +) -> Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"]: + r""" + One-body reduced density matrix for each k-point in AO representation + + Parameters: + ---------- + mo_coeff : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + Spin-orbital coefficients for each k-point. + mo_occ : Float[Array, "n_spin n_kpt n_orbitals"] + Spin-orbital occupancies for each k-point. + + Returns: + ------- + Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + """ + + return jnp.einsum("skij,skj,sklj -> skil", mo_coeff, mo_occ, mo_coeff.conj(), precision=precision) + + +@jaxtyped +@typechecked +def get_occ( + mo_energies: Float[Array, "n_spin n_kpt n_orbitals"], + nelecs: Int[Array, "spin"], +) -> Float[Array, "n_spin n_kpt n_orbitals"]: + r"""Compute the occupations of the molecular orbitals for each + spin and k-point. + + Parameters + ---------- + mo_energies : Float[Array, "n_spin n_kpt n_orbitals"] + The molecular orbital energies. + nelecs : Int[Array, "n_spin"] + The number of electrons in each spin channel. + + Returns + ------- + Int[Array, "n_spin n_kpt n_orbitals"] + """ + nkpt = mo_energies.shape[1] + nmo = mo_energies.shape[2] + def get_occ_spin_k_pair(mo_energy_spin_k, nelec_spin, nmo): + sorted_indices = jnp.argsort(mo_energy_spin_k) + + mo_occ = jnp.zeros_like(mo_energy_spin_k) + + def assign_values(i, mo_occ): + value = cond(jnp.less(i, nelec_spin), lambda _: 1, lambda _: 0, operand=None) + idx = sorted_indices[i] + mo_occ = mo_occ.at[idx].set(value) + return mo_occ + + mo_occ = fori_loop(0, nmo, assign_values, mo_occ) + + return mo_occ + + + mo_occ = jnp.stack( + jnp.asarray([[get_occ_spin_k_pair(mo_energies[s, k], jnp.int64(nelecs[s]), nmo) for k in range(nkpt)] for s in range(2)]), axis=0 + ) + + return mo_occ + + +""" +Note: while the below functions related to the density and it's gradients take a k-point weights parameter, +modification is needed before they support unequal weights as they would appear in a symmetry adapted code. I.e, +the whole 1BZ need to be considered which would involve use of rotation matrices to map 1RDM's in the IBZ to the full +1BZ. +""" + +@jaxtyped +@typechecked +@partial(jit, static_argnames="precision") +def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + ao: Float[Array, "n_flat_grid n_orbitals"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision: Precision = Precision.HIGHEST +) -> Float[Array, "n_flat_grid n_spin"]: + r""" Calculates electronic density from atomic orbitals. + + Parameters + ---------- + rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + ao : Float[Array, "n_flat_grid n_orbitals"] + Atomic orbitals. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + precision : jax.lax.Precision, optional + Jax `Precision` enum member, indicating desired numerical precision. + By default jax.lax.Precision.HIGHEST. + + Returns + ------- + Float[Array, "n_flat_grid n_spin"] + """ + + return jnp.einsum("k,...kab,ra,rb->r...", weights, rdm1, ao, ao, precision=precision).real + +@jaxtyped +@typechecked +@partial(jit, static_argnames="precision") +def grad_density( + rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + ao: Float[Array, "n_flat_grid n_orbitals"], + grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision: Precision = Precision.HIGHEST +) -> Float[Array, "n_flat_grid n_spin 3"]: + r"""Compute the electronic density gradient using atomic orbitals. + + Parameters + ---------- + rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + ao : Float[Array, "n_flat_grid n_orbitals"] + Atomic orbitals. + grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] + Gradients of atomic orbitals. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + precision : jax.lax.Precision, optional + Jax `Precision` enum member, indicating desired numerical precision. + By default jax.lax.Precision.HIGHEST. + + Returns + ------- + Array + The density gradient: Float[Array, "n_flat_grid n_spin 3"] + """ + + return 2 * jnp.einsum("k,...kab,ra,rbj->r...j", weights, rdm1, ao, grad_ao, precision=precision).real + +@jaxtyped +@typechecked +@partial(jit, static_argnames="precision") +def lapl_density( + rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + ao: Float[Array, "n_flat_grid n_orbitals"], + grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], + grad_2_ao: Float[Array, "n_flat_grid n_orbitals 3"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision: Precision = Precision.HIGHEST, +) -> Float[Array, "n_flat_grid n_spin"]: + r"""Compute the laplacian of the electronic density. + + Parameters + ---------- + rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + ao : Float[Array, "b_flat_grid n_orbitals"] + Atomic orbitals. + grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] + Gradients of atomic orbitals. + grad_2_ao : Float[Array, "n_flat_grid n_orbitals 3"] + Vector of second derivatives of atomic orbitals. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + precision : jax.lax.Precision, optional + Jax `Precision` enum member, indicating desired numerical precision. + By default jax.lax.Precision.HIGHEST. + + Returns + ------- + Float[Array, "n_flat_grid n_spin"] + """ + return (2 * jnp.einsum( + "k,...kab,raj,rbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision + ) + 2 * jnp.einsum("k,...kab,ra,rbi->r...", weights, rdm1, ao, grad_2_ao, precision=precision)).real + +@jaxtyped +@typechecked +@partial(jit, static_argnames="precision") +def kinetic_density( + rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], + weights: Float[Array, "n_kpts_or_n_ir_kpts"], + precision: Precision = Precision.HIGHEST +) -> Float[Array, "n_flat_grid n_spin"]: + r""" Compute the kinetic energy density using atomic orbitals. + + Parameters + ---------- + rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + The 1-body reduced density matrix. + grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] + Gradients of atomic orbitals. + weights : Float[Array, "n_kpts_or_n_ir_kpts"] + The weights for each k-point which together sum to 1. If we are working + in the full 1BZ, weights are equal. If we are working in the + irreducible 1BZ, weights may not be equal if symmetry can be + exploited. + precision : jax.lax.Precision, optional + Jax `Precision` enum member, indicating desired numerical precision. + By default jaxx.lax.Precision.HIGHEST. + + Returns + ------- + Array + The kinetic energy density: Float[Array, "n_flat_grid n_spin"] + """ + + return 0.5 * jnp.einsum("k,...kab,raj,rbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision).real + + + From 9831b35cb977a84101c7190c188c9f8edafb80d6 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 11:47:51 -0500 Subject: [PATCH 08/36] Refactoring of functional.py to accept Solid --- grad_dft/functional.py | 135 +++++++++++++++++++++-------------------- grad_dft/solid.py | 4 ++ 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/grad_dft/functional.py b/grad_dft/functional.py index 37ffb1f..feb1f65 100644 --- a/grad_dft/functional.py +++ b/grad_dft/functional.py @@ -39,7 +39,8 @@ from grad_dft import ( abs_clip, Grid, - Molecule + Molecule, + Solid ) from grad_dft.utils.types import DType, default_dtype @@ -68,13 +69,13 @@ class Functional(nn.Module): A function that computes and returns the energy densities e_\theta that can be autodifferentiated with respect to the reduced density matrix. - densities(molecule: Molecule, *args, **kwargs) -> Array + densities(atoms: Union[Molecule, Solid], *args, **kwargs) -> Array nograd_densities : Callable, optional - A function that calculates the molecule energy densities e_\theta where gradient with respect to the + A function that calculates the energy densities e_\theta where gradient with respect to the reduced density matrix is computed via in densitygrads. - nograd_densities(molecule: Molecule, *args, **kwargs) -> Array + nograd_densities(atoms: Union[Molecule, Solid], *args, **kwargs) -> Array featuregrads: Callable, optional A function to compute contributions to the Fock matrix for energy densities @@ -82,7 +83,7 @@ class Functional(nn.Module): If given has signature - featuregrads(functional: nn.Module, params: PyTree, molecule: Molecule, + featuregrads(functional: nn.Module, params: PyTree, atoms: Union[Molecule, Solid], nograd_densities: Array, coefficient_inputs: Array, grad_densities, *args) - > Fock matrix: Array of shape (2, nao, nao) combine_densities : Callable, optional @@ -93,13 +94,13 @@ class Functional(nn.Module): A function that computes the inputs to the coefficients function, that can be autodifferentiated with respect to the reduced density matrix. - coefficient_inputs(molecule: Molecule, *args, **kwargs) -> Array + coefficient_inputs(atoms: Union[Molecule, Solid], *args, **kwargs) -> Array nograd_coefficient_inputs : Callable, optional A function that computes the inputs to the coefficients function, where gradient with respect to the reduced density matrix is computed via in coefficient_input_grads. - nograd_coefficient_inputs(molecule: Molecule, *args, **kwargs) -> Array + nograd_coefficient_inputs(atoms: Union[Molecule, Solid], *args, **kwargs) -> Array coefficient_inputs_grads: Callable, optional A function to compute contributions to the Fock matrix for coefficient inputs @@ -107,7 +108,7 @@ class Functional(nn.Module): If given has signature - coefficient_inputs_grads(functional: nn.Module, params: PyTree, molecule: Molecule, + coefficient_inputs_grads(functional: nn.Module, params: PyTree, atoms: Union[Molecule, Solid], nograd_coefficient_inputs: Array, grad_coefficient_inputs: Array, densities, *args) - > Fock matrix: Array of shape (2, nao, nao) combine_coefficient_inputs : Callable, optional @@ -156,14 +157,14 @@ def __call__(self, coefficient_inputs) -> Scalar: return self.coefficients(self, coefficient_inputs) - def compute_densities(self, molecule: Molecule, clip_cte: float = 1e-30, *args, **kwargs): + def compute_densities(self, atoms: Union[Molecule, Solid], clip_cte: float = 1e-30, *args, **kwargs): r""" Computes the densities for the functional, both with and without autodifferentiation. Parameters ---------- - molecule: Molecule - The molecule to compute the densities for + atoms: Union[Molecule, Solid] + The atoms to compute the densities for Returns ------- @@ -171,26 +172,26 @@ def compute_densities(self, molecule: Molecule, clip_cte: float = 1e-30, *args, """ if self.nograd_densities and self.energy_densities: - densities = self.energy_densities(molecule, *args, **kwargs) - nograd_densities = stop_gradient(self.nograd_densities(molecule, *args, **kwargs)) + densities = self.energy_densities(atoms, *args, **kwargs) + nograd_densities = stop_gradient(self.nograd_densities(atoms, *args, **kwargs)) densities = self.combine_densities(densities, nograd_densities) elif self.energy_densities: - densities = self.energy_densities(molecule, *args, **kwargs) + densities = self.energy_densities(atoms, *args, **kwargs) elif self.nograd_densities: - densities = stop_gradient(self.nograd_densities(molecule, *args, **kwargs)) + densities = stop_gradient(self.nograd_densities(atoms, *args, **kwargs)) densities = abs_clip(densities, clip_cte) #todo: investigate if we can lower this return densities - def compute_coefficient_inputs(self, molecule: Molecule, *args, **kwargs): + def compute_coefficient_inputs(self, atoms: Union[Molecule, Solid], *args, **kwargs): r""" Computes the inputs to the coefficients method in the functional Parameters ---------- - molecule: Molecule - The molecule to compute the inputs for the coefficients + atoms: Union[Molecule, Solid] + The atoms to compute the inputs for the coefficients Returns ------- @@ -198,17 +199,17 @@ def compute_coefficient_inputs(self, molecule: Molecule, *args, **kwargs): """ if self.nograd_coefficient_inputs and self.coefficient_inputs: - cinputs = self.coefficient_inputs(molecule, *args, **kwargs) + cinputs = self.coefficient_inputs(atoms, *args, **kwargs) nograd_cinputs = stop_gradient( - self.nograd_coefficient_inputs(molecule, *args, **kwargs) + self.nograd_coefficient_inputs(atoms, *args, **kwargs) ) cinputs = self.combine_inputs(cinputs, nograd_cinputs) elif self.coefficient_inputs: - cinputs = self.coefficient_inputs(molecule, *args, **kwargs) + cinputs = self.coefficient_inputs(atoms, *args, **kwargs) elif self.nograd_coefficient_inputs: - cinputs = stop_gradient(self.nograd_coefficient_inputs(molecule, *args, **kwargs)) + cinputs = stop_gradient(self.nograd_coefficient_inputs(atoms, *args, **kwargs)) else: cinputs = None @@ -251,7 +252,7 @@ def xc_energy( xc_energy_density = abs_clip(xc_energy_density, clip_cte) return self._integrate(xc_energy_density, grid.weights) - def energy(self, params: PyTree, molecule: Molecule, *args, **kwargs) -> Scalar: + def energy(self, params: PyTree, atoms: Union[Molecule, Solid], *args, **kwargs) -> Scalar: r""" Total energy of local functional @@ -259,7 +260,7 @@ def energy(self, params: PyTree, molecule: Molecule, *args, **kwargs) -> Scalar: --------- params: PyTree params of the neural network if there is one in self.f - molecule: Molecule + atoms: Union[Molecule, Solid] *args: other arguments to compute_densities or compute_coefficient_inputs **kwargs: other key word arguments to densities and self.xc_energy @@ -272,17 +273,17 @@ def energy(self, params: PyTree, molecule: Molecule, *args, **kwargs) -> Scalar: ------- Integrates the energy over the grid. If the function is_xc, it will add the rest of the energy components - computed with function molecule.nonXC() + computed with function atoms.nonXC() """ - densities = self.compute_densities(molecule, *args, **kwargs) - # sys.exit() - cinputs = self.compute_coefficient_inputs(molecule, *args) + densities = self.compute_densities(atoms, *args, **kwargs) + + cinputs = self.compute_coefficient_inputs(atoms, *args) - energy = self.xc_energy(params, molecule.grid, cinputs, densities, **kwargs) + energy = self.xc_energy(params, atoms.grid, cinputs, densities, **kwargs) if self.is_xc: - energy += molecule.nonXC() + energy += atoms.nonXC() return energy @@ -474,14 +475,13 @@ def load_checkpoint( ######################## DM21 ######################## -def dm21_coefficient_inputs(molecule: Molecule, clip_cte: Optional[float] = 1e-30, *_, **__): +def dm21_coefficient_inputs(atoms: Union[Molecule, Solid], clip_cte: Optional[float] = 1e-30, *_, **__): r""" Computes the electronic density and derivatives Parameters ---------- - molecule: - class Molecule + atoms: Union[Molecule, Solid] clip_cte: Optional[float] Needed to make sure it default 1e-30 (chosen carefully, take care if decrease) @@ -491,11 +491,11 @@ class Molecule Array: shape (n_grid, 7) where 7 is the number of features """ - rho = molecule.density() + rho = atoms.density() # We need to clip rho away from 0 to obtain good gradients. rho = jnp.maximum(abs(rho), clip_cte) * jnp.sign(rho) - grad_rho = molecule.grad_density() - tau = molecule.kinetic_density() + grad_rho = atoms.grad_density() + tau = atoms.kinetic_density() grad_rho_norm = jnp.sum(grad_rho**2, axis=-1) grad_rho_norm_sumspin = jnp.sum(grad_rho.sum(axis=1, keepdims=True) ** 2, axis=-1) @@ -506,7 +506,7 @@ class Molecule def dm21_densities( - molecule: Molecule, + atoms: Union[Molecule, Solid], functional_type: Optional[Union[str, Dict[str, int]]] = "LDA", clip_cte: float = 1e-30, *_, @@ -517,8 +517,7 @@ def dm21_densities( Parameters: ---------- - molecule: - class Molecule + atoms: Union[Molecule, Solid] functional_type: Either one of 'LDA', 'GGA', 'MGGA' or Dictionary @@ -559,10 +558,10 @@ class Molecule f"Functional type {functional_type} not recognized, must be one of LDA, GGA, MGGA." ) - # Molecule preprocessing data - rho = molecule.density() - grad_rho = molecule.grad_density() - tau = molecule.kinetic_density() + # Atoms preprocessing data + rho = atoms.density() + grad_rho = atoms.grad_density() + tau = atoms.kinetic_density() grad_rho_norm_sq = jnp.sum(grad_rho**2, axis=-1) # LDA preprocessing data @@ -654,7 +653,7 @@ def dm21_combine_densities( def dm21_hfgrads_densities( functional: nn.Module, params: PyTree, - molecule: Molecule, + atoms: Union[Molecule, Solid], ehf: Float[Array, "omega spin grid"], coefficient_inputs: Float[Array, "grid cinputs"], densities_wout_hf: Float[Array, "grid densities_whf"], @@ -670,8 +669,8 @@ def dm21_hfgrads_densities( The functional to calculate the Hartree-Fock matrix contribution for. params: PyTree The parameters of the functional. - molecule: Molecule - The molecule to calculate the Hartree-Fock matrix contribution for. + atoms: Union[Molecule, Solid] + The atoms to calculate the Hartree-Fock matrix contribution for. ehf: Float[Array, "omega spin grid"] The Hartree-Fock energy density. coefficient_inputs: Float[Array, "grid cinputs"] @@ -686,7 +685,7 @@ def dm21_hfgrads_densities( ---------- Float[Array, "spin orbitals orbitals"] """ - vxc_hf = molecule.HF_density_grad_2_Fock( + vxc_hf = atoms.HF_density_grad_2_Fock( functional, params, omegas, ehf, coefficient_inputs, densities_wout_hf ) return vxc_hf.sum(axis=0) # Sum over omega @@ -696,7 +695,7 @@ def dm21_hfgrads_densities( def dm21_hfgrads_cinputs( functional: nn.Module, params: PyTree, - molecule: Molecule, + atoms: Union[Molecule, Solid], ehf: Float[Array, "omega spin grid"], cinputs_wout_hf: Float[Array, "grid cinputs_whf"], densities: Float[Array, "grid densities"], @@ -712,8 +711,8 @@ def dm21_hfgrads_cinputs( The functional to calculate the Hartree-Fock matrix contribution for. params: PyTree The parameters of the functional. - molecule: Molecule - The molecule to calculate the Hartree-Fock matrix contribution for. + atoms: Union[Molecule, Solid] + The atoms to calculate the Hartree-Fock matrix contribution for. ehf: Float[Array, "omega spin grid"] The Hartree-Fock energy density. cinputs_wout_hf: Float[Array, "grid cinputs_whf"] @@ -727,7 +726,7 @@ def dm21_hfgrads_cinputs( ---------- Float[Array, "spin orbitals orbitals"] """ - vxc_hf = molecule.HF_coefficient_input_grad_2_Fock( + vxc_hf = atoms.HF_coefficient_input_grad_2_Fock( functional, params, omegas, ehf, cinputs_wout_hf, densities ) return vxc_hf.sum(axis=0) # Sum over omega @@ -743,20 +742,20 @@ class DM21(NeuralFunctional): coefficients: Callable = lambda self, inputs: self.default_nn(inputs) energy_densities: Callable = dm21_densities - nograd_densities: staticmethod = lambda molecule, *_, **__: molecule.HF_energy_density( + nograd_densities: staticmethod = lambda atoms, *_, **__: atoms.HF_energy_density( jnp.array([0.0, 0.4]) ) - densitygrads: staticmethod = lambda self, params, molecule, nograd_densities, cinputs, grad_densities, *_, **__: dm21_hfgrads_densities( - self, params, molecule, nograd_densities, cinputs, grad_densities, jnp.array([0.0, 0.4]) + densitygrads: staticmethod = lambda self, params, atoms, nograd_densities, cinputs, grad_densities, *_, **__: dm21_hfgrads_densities( + self, params, atoms, nograd_densities, cinputs, grad_densities, jnp.array([0.0, 0.4]) ) combine_densities: staticmethod = dm21_combine_densities coefficient_inputs: staticmethod = dm21_coefficient_inputs - nograd_coefficient_inputs: staticmethod = lambda molecule, *_, **__: molecule.HF_energy_density( + nograd_coefficient_inputs: staticmethod = lambda atoms, *_, **__: atoms.HF_energy_density( jnp.array([0.0, 0.4]) ) - coefficient_input_grads: staticmethod = lambda self, params, molecule, nograd_cinputs, grad_cinputs, densities, *_, **__: dm21_hfgrads_cinputs( - self, params, molecule, nograd_cinputs, grad_cinputs, densities, jnp.array([0.0, 0.4]) + coefficient_input_grads: staticmethod = lambda self, params, atoms, nograd_cinputs, grad_cinputs, densities, *_, **__: dm21_hfgrads_cinputs( + self, params, atoms, nograd_cinputs, grad_cinputs, densities, jnp.array([0.0, 0.4]) ) combine_inputs: staticmethod = dm21_combine_cinputs @@ -1021,7 +1020,7 @@ def fzeta(z): def densities( - molecule: Molecule, + atoms: Union[Molecule, Solid], functional_type: Optional[Union[str, Dict[str, int]]] = "LDA", clip_cte: float = 1e-30, *_, @@ -1032,8 +1031,7 @@ def densities( Parameters: ---------- - molecule: - class Molecule + atoms: Union[Molecule, Solid] functional_type: Either one of 'LDA', 'GGA', 'MGGA' or Dictionary @@ -1074,10 +1072,10 @@ class Molecule f"Functional type {functional_type} not recognized, must be one of LDA, GGA, MGGA." ) - # Molecule preprocessing data - rho = molecule.density() - grad_rho = molecule.grad_density() - tau = molecule.kinetic_density() + # Atoms preprocessing data + rho = atoms.density() + grad_rho = atoms.grad_density() + tau = atoms.kinetic_density() grad_rho_norm_sq = jnp.sum(grad_rho**2, axis=-1) # LDA preprocessing data @@ -1234,11 +1232,14 @@ def head(self, x: Array, local_features, sigmoid_scale_factor): return jnp.squeeze(out) # Eliminating unnecessary dimensions - def energy(self, params: PyTree, molecule: Molecule): + def energy(self, params: PyTree, atoms: Union[Molecule, Solid]): r""" Calculates the energy of the functional. """ - R_AB, ai = calculate_distances(molecule.nuclear_pos, molecule.atom_index) + if isinstance(atoms, Solid): + raise NotImplementedError("Dispersion functionals are not presently implemented for solids") + + R_AB, ai = calculate_distances(atoms.nuclear_pos, atoms.atom_index) result = 0 for n in range(3, 6): @@ -1250,7 +1251,7 @@ def energy(self, params: PyTree, molecule: Molecule): def calculate_distances(positions, atoms): r""" - Calculates the distances between all atoms in the molecule. + Calculates the distances between all atoms. """ pairwise_distances = jnp.linalg.norm(positions[:, None] - positions, axis=-1) atom_pairs = jnp.array( diff --git a/grad_dft/solid.py b/grad_dft/solid.py index d495c3d..7cff665 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -213,6 +213,10 @@ def to_dict(self) -> dict: rest = {field.name: getattr(self, field.name) for field in fields(self)[2:]} return dict(**grid_dict, **kpt_dict, **rest) + """ + Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release. + """ + From cded621f41f8405d8278b7d2cc15861acf116960 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 11:52:25 -0500 Subject: [PATCH 09/36] Added NotImplementedErrors for HFX methods in solids. --- grad_dft/solid.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 7cff665..06b43f1 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -25,6 +25,7 @@ from dataclasses import fields from flax import struct +from flax import linen as nn from jaxtyping import Array, PyTree, Scalar, Float, Int, Complex, jaxtyped @@ -213,13 +214,39 @@ def to_dict(self) -> dict: rest = {field.name: getattr(self, field.name) for field in fields(self)[2:]} return dict(**grid_dict, **kpt_dict, **rest) - """ - Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release. - """ + def select_HF_omegas(self, omegas: Float[Array, "omega"]) -> Array: + raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") + + def HF_energy_density(self, omegas: Float[Array, "omega"], *args, **kwargs) -> Array: + raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") + + def HF_density_grad_2_Fock( + self, + functional: nn.Module, + params: PyTree, + omegas: Float[Array, "omega"], + ehf: Float[Array, "omega spin grid"], + coefficient_inputs: Float[Array, "grid cinputs"], + densities_wout_hf: Float[Array, "grid densities_w"], + **kwargs, + ) -> Float[Array, "omega spin orbitals orbitals"]: + raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") + + def HF_coefficient_input_grad_2_Fock( + self, + functional: nn.Module, + params: PyTree, + omegas: Float[Array, "omega"], + ehf: Float[Array, "omega spin grid"], + cinputs_wout_hf: Float[Array, "grid cinputs_w"], + densities: Float[Array, "grid densities"], + **kwargs, + ) -> Float[Array, "omega spin orbitals orbitals"]: + raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") + - - + @jaxtyped @typechecked @partial(jit, static_argnames=["precision"]) From 7cf95d63c86703c408808e94665f314232da362a Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 16:03:14 -0500 Subject: [PATCH 10/36] Raised B3LYP tests tolerance. We should perhaps remove this test entirely as the version of B3LYP we implement is actually different to the LibXC version --- tests/integration/test_predict_B3LYP.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/test_predict_B3LYP.py b/tests/integration/test_predict_B3LYP.py index 8dc8af8..f0bbc2e 100644 --- a/tests/integration/test_predict_B3LYP.py +++ b/tests/integration/test_predict_B3LYP.py @@ -74,4 +74,4 @@ def test_predict(mol_and_name: tuple[gto.Mole, str]) -> None: molecule_out = iterator(PARAMS, molecule) e_XND = molecule_out.energy kcalmoldiff = (e_XND - e_DM) * Hartree2kcalmol - assert jnp.allclose(kcalmoldiff, 0, atol=1), f"Energy difference with PySCF for B3LYP on {name} exceeds the threshold." \ No newline at end of file + assert jnp.allclose(kcalmoldiff, 0, atol=10), f"Energy difference with PySCF for B3LYP on {name} exceeds the threshold." \ No newline at end of file From 2fd5d1f258cdf5b89ad9aa41893c2983f9c1bd8c Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 16:26:04 -0500 Subject: [PATCH 11/36] Taken B3LYP tests from CI --- .github/workflows/install_and_test.yml | 1 - tests/integration/test_predict_B3LYP.py | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index a4949fe..e2b7199 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -40,6 +40,5 @@ jobs: pytest -v tests/integration/test_functional_implementations.py pytest -v tests/integration/test_Harris.py pytest -v tests/integration/test_predict_B88.py - pytest -v tests/integration/test_predict_B3LYP.py pytest -v tests/integration/test_training.py diff --git a/tests/integration/test_predict_B3LYP.py b/tests/integration/test_predict_B3LYP.py index f0bbc2e..fdab7d3 100644 --- a/tests/integration/test_predict_B3LYP.py +++ b/tests/integration/test_predict_B3LYP.py @@ -48,9 +48,14 @@ # This test will only pass if you set B3LYP_WITH_VWN5 = True in pyscf_conf.py. # See pyscf_conf.py in .github/workflows + # This test differs slightly due to the use of the original LYP functional definition # in C. Lee, W. Yang, and R. G. Parr., Phys. Rev. B 37, 785 (1988) (doi: 10.1103/PhysRevB.37.785) # instead of the one in libxc: B. Miehlich, A. Savin, H. Stoll, and H. Preuss., Chem. Phys. Lett. 157, 200 (1989) (doi: 10.1016/0009-2614(89)87234-3) + +# This test is now NOT included in the CI because of implementation differences between B3LYP in Grad DFT +# versus PySCF. See above. + @pytest.mark.parametrize("mol_and_name", [(MOL_WATER, "water"), (MOL_LI, "Li")]) def test_predict(mol_and_name: tuple[gto.Mole, str]) -> None: r"""Compare the total energy predicted by Grad-DFT for the B3LYP functional versus PySCF. From 7006426aa7bf5face77c7d6b32f7ea79eaa63fd4 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 16:49:23 -0500 Subject: [PATCH 12/36] re-worked train.py to take Solid instances --- grad_dft/train.py | 209 +++++++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 85 deletions(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index bd2e930..0e133ef 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, Optional, Tuple +from typing import Callable, Optional, Tuple, Union from functools import partial -from jaxtyping import Array, PRNGKeyArray, PyTree, Scalar, Float +from jaxtyping import Array, PRNGKeyArray, PyTree, Scalar, Float, Complex from jax import numpy as jnp, vmap from jax import value_and_grad @@ -26,7 +26,8 @@ coulomb_energy, DispersionFunctional, Functional, - Molecule, + Molecule, + Solid, abs_clip, ) @@ -37,7 +38,7 @@ def energy_predictor( **kwargs, ) -> Callable: r"""Generate a function that predicts the energy - energy of a `Molecule` and a corresponding Fock matrix + energy of a `Molecule` or `Solid` and a corresponding Fock matrix Parameters ---------- @@ -46,10 +47,10 @@ def energy_predictor( exchange-correlation energy given some parameters. A callable must have the following signature: - fxc.energy(params: Array, molecule: Molecule, **functional_kwargs) -> Scalar + fxc.energy(params: Array, atoms: Union[Molecule, Solid], **functional_kwargs) -> Scalar - where `params` is any parameter pytree, and `molecule` - is a Molecule class instance. + where `params` is any parameter pytree, and `atoms` + is a `Molecule` or `Solid` class instance. Returns ------- @@ -58,7 +59,7 @@ def energy_predictor( the predicted energy with the corresponding Fock matrix. Signature: - (params: PyTree, molecule: Molecule, *args) -> Tuple[Scalar, Array] + (params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scalar, Array] Notes ----- @@ -85,8 +86,10 @@ def energy_predictor( @partial(value_and_grad, argnums=1) def energy_and_grads( params: PyTree, - rdm1: Float[Array, "spin orbitals orbitals"], - molecule: Molecule, + rdm1: Union[Float[Array, "spin orbitals orbitals"], + Complex[Array, "spin kpt orbitals orbitals"] + ], + atoms: Union[Molecule, Solid], *args, **functional_kwargs, ) -> Scalar: @@ -98,27 +101,27 @@ def energy_and_grads( params: Pytree Functional parameters rdm1: Float[Array, "spin orbitals orbitals"] - The reduced density matrix. - molecule: Molecule - the molecule + The 1-body reduced density matrix. + atoms: Union[Molecule, Solid] + The collection of atoms. Returns ----------- Scalar - The energy of the molecule when the state of the system is given by rdm1. + The energy of the atoms when the state of the system is given by rdm1. """ - molecule = molecule.replace(rdm1=rdm1) + atoms = atoms.replace(rdm1=rdm1) - e = functional.energy(params, molecule, *args, **functional_kwargs) + e = functional.energy(params, atoms, *args, **functional_kwargs) if nlc_functional: e = e + nlc_functional.energy( - {"params": params["dispersion"]}, molecule, **functional_kwargs + {"params": params["dispersion"]}, atoms, **functional_kwargs ) return e @partial(annotate_function, name="predict") - def predict(params: PyTree, molecule: Molecule, *args) -> Tuple[Scalar, Array]: + def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scalar, Array]: r"""A DFT functional wrapper, returning the predicted exchange-correlation energy as well as the corresponding Fock matrix. This function does **not** require that the provided `feature_fn` returns derivatives (Jacobian matrix) of provided @@ -128,53 +131,54 @@ def predict(params: PyTree, molecule: Molecule, *args) -> Tuple[Scalar, Array]: ---------- params : PyTree The functional parameters. - molecule : Molecule - The `Molecule` object to predict properties of. + atoms: Union[Molecule, Solid] + The collection of atoms. *args Returns ------- Tuple[Scalar, Array] A tuple of the predicted exchange-correlation energy and the corresponding - Fock matrix of the same shape as `molecule.density_matrix`: - (*batch_size, n_spin, n_orbitals, n_orbitals). + Fock matrix of the same shape as `atoms.rdm1`: + (*batch_size, n_spin, n_orbitals, n_orbitals) for a `Molecule` or + (*batch_size, n_spin, n_kpt, n_orbitals, n_orbitals) for a `Solid`. """ - energy, fock = energy_and_grads(params, molecule.rdm1, molecule, *args) + energy, fock = energy_and_grads(params, atoms.rdm1, atoms, *args) fock = abs_clip(fock, clip_cte) fock = 1 / 2 * (fock + fock.transpose(0, 2, 1)) fock = abs_clip(fock, clip_cte) # Compute the features that should be autodifferentiated if functional.energy_densities and functional.densitygrads: - grad_densities = functional.energy_densities(molecule, *args, **kwargs) - nograd_densities = stop_gradient(functional.nograd_densities(molecule, *args, **kwargs)) + grad_densities = functional.energy_densities(atoms, *args, **kwargs) + nograd_densities = stop_gradient(functional.nograd_densities(atoms, *args, **kwargs)) densities = functional.combine_densities(grad_densities, nograd_densities) elif functional.energy_densities: - grad_densities = functional.energy_densities(molecule, *args, **kwargs) + grad_densities = functional.energy_densities(atoms, *args, **kwargs) nograd_densities = None densities = grad_densities elif functional.densitygrads: grad_densities = None - nograd_densities = stop_gradient(functional.nograd_densities(molecule, *args, **kwargs)) + nograd_densities = stop_gradient(functional.nograd_densities(atoms, *args, **kwargs)) densities = nograd_densities else: densities, grad_densities, nograd_densities = None, None, None if functional.coefficient_input_grads and functional.coefficient_inputs: - grad_cinputs = functional.coefficient_inputs(molecule, *args, **kwargs) + grad_cinputs = functional.coefficient_inputs(atoms, *args, **kwargs) nograd_cinputs = stop_gradient( - functional.nograd_coefficient_inputs(molecule, *args, **kwargs) + functional.nograd_coefficient_inputs(atoms, *args, **kwargs) ) cinputs = functional.combine_inputs(grad_cinputs, nograd_cinputs) elif functional.coefficient_inputs: - grad_cinputs = functional.coefficient_inputs(molecule, *args, **kwargs) + grad_cinputs = functional.coefficient_inputs(atoms, *args, **kwargs) nograd_cinputs = None cinputs = grad_cinputs elif functional.coefficient_input_grads: grad_cinputs = None nograd_cinputs = stop_gradient( - functional.nograd_coefficient_inputs(molecule, *args, **kwargs) + functional.nograd_coefficient_inputs(atoms, *args, **kwargs) ) cinputs = nograd_cinputs else: @@ -183,14 +187,14 @@ def predict(params: PyTree, molecule: Molecule, *args) -> Tuple[Scalar, Array]: # Compute the derivatives with respect to nograd_densities if functional.densitygrads: vxc_expl = functional.densitygrads( - functional, params, molecule, nograd_densities, cinputs, grad_densities + functional, params, atoms, nograd_densities, cinputs, grad_densities ) fock += vxc_expl + vxc_expl.transpose(0, 2, 1) # Sum over omega fock = abs_clip(fock, clip_cte) if functional.coefficient_input_grads: vxc_expl = functional.coefficient_input_grads( - functional, params, molecule, nograd_cinputs, grad_cinputs, densities + functional, params, atoms, nograd_cinputs, grad_cinputs, densities ) fock += vxc_expl + vxc_expl.transpose(0, 2, 1) # Sum over omega fock = abs_clip(fock, clip_cte) @@ -226,7 +230,7 @@ def Harris_energy_predictor( def xc_energy_and_grads( params: PyTree, rdm1: Float[Array, "spin orbitals orbitals"], - molecule: Molecule, + atoms: Union[Molecule, Solid], *args, **kwargs ) -> Scalar: @@ -239,8 +243,8 @@ def xc_energy_and_grads( Functional parameters rdm1: Float[Array, "spin orbitals orbitals"] The reduced density matrix. - molecule: Molecule - the molecule + atoms: Union[Molecule, Solid] + The collection of atoms. *args **kwargs @@ -248,12 +252,13 @@ def xc_energy_and_grads( ----------- Tuple[Scalar, Float[Array, "spin orbitals orbitals"]] """ - molecule = molecule.replace(rdm1 = rdm1) - densities = functional.compute_densities(molecule, *args, **kwargs) - cinputs = functional.compute_coefficient_inputs(molecule, *args) - return functional.xc_energy(params, molecule.grid, cinputs, densities, **kwargs) - + atoms = atoms.replace(rdm1=rdm1) + densities = functional.compute_densities(atoms, *args, **kwargs) + cinputs = functional.compute_coefficient_inputs(atoms, *args) + return functional.xc_energy(params, atoms.grid, cinputs, densities, **kwargs) + + # Works for Molecules only for now def Harris_energy( params: PyTree, molecule: Molecule, @@ -300,7 +305,7 @@ def train_kernel(tx: GradientTransformation, loss: Callable) -> Callable: tx : GradientTransformation An optax gradient transformation. loss : Callable - A loss function that takes in the parameters, a `Molecule` object, and the ground truth energy + A loss function that takes in the parameters, a `Molecule` or `Solid` object, and the ground truth energy and returns a tuple of the loss value and the gradients. Returns @@ -309,7 +314,7 @@ def train_kernel(tx: GradientTransformation, loss: Callable) -> Callable: """ def kernel( - params: PyTree, opt_state: OptState, molecule: Molecule, ground_truth_energy: float, *args + params: PyTree, opt_state: OptState, atoms: Union[Molecule, Solid], ground_truth_energy: float, *args ) -> Tuple[PyTree, OptState, Scalar, Scalar]: r"""" The training kernel updating the parameters according to the loss @@ -321,8 +326,8 @@ def kernel( The parameters of the functional. opt_state : OptState The optimizer state. - molecule : Molecule - The molecule. + atoms: Union[Molecule, Solid] + The collection of atoms ground_truth_energy : float The ground truth energy. *args @@ -332,7 +337,7 @@ def kernel( Tuple[PyTree, OptState, Scalar, Scalar] The updated parameters, optimizer state, loss value, and predicted energy. """ - (cost_value, predictedenergy), grads = loss(params, molecule, ground_truth_energy) + (cost_value, predictedenergy), grads = loss(params, atoms, ground_truth_energy) updates, opt_state = tx.update(grads, opt_state, params) params = apply_updates(params, updates) @@ -344,6 +349,7 @@ def kernel( ##################### Regularization ##################### +# Regularization terms only support `Molecule` object for now def fock_grad_regularization(molecule: Molecule, F: Float[Array, "spin ao ao"]) -> Scalar: """Calculates the Fock alternative regularization term for a `Molecule` given a Fock matrix. @@ -460,15 +466,20 @@ def get_grad( def mse_energy_loss( params: PyTree, compute_energy: Callable, - molecules: list[Molecule], + atoms_list: Union[list[Molecule], + list[Solid], + list[Union[Molecule,Solid]], + Molecule, + Solid + ], truth_energies: Float[Array, "energy"], elec_num_norm: Scalar = True, ) -> Scalar: r""" Computes the mean-squared error between predicted and truth energies. - This loss function does not yet support parallel execution for the loss contributions - and instead implemented a simple for loop. + This loss function does not yet support parallel execution for the loss contributions. + We instead use a simple serial for loop. Parameters ---------- @@ -476,8 +487,9 @@ def mse_energy_loss( functional parameters (weights) compute_energy: Callable(molecule, params) -> molecule. any non SCF or SCF method in evaluate.py. The output molecule contains the predicted energy. - molecule: Molecule - a Grad-DFT Molecule object + atoms_list: Union[list[Molecule], list[Solid], list[Union[Molecule,Solid]], Molecule, Solid] + A list of `Molecule` or `Solid` objects or a combination of both. Passing + a single `Molecule` or `Solid` wraps it in a list internally. truth_energies: Float[Array, "energy"] the truth values of the energy to measure the predictions against elec_num_norm: Scalar @@ -487,25 +499,28 @@ def mse_energy_loss( ---------- Scalar: the mean-squared error between predicted and truth energies """ - if isinstance(molecules, Molecule): molecules = [molecules] + # Catch the case where a list of atoms was not passed. I.e, dealing with a single + # instance. + if isinstance(atoms_list, Molecule) or isinstance(atoms_list, Solid): + atoms_list = [atoms_list] sum = 0 - for i, molecule in enumerate(molecules): - molecule_out = compute_energy(params, molecule) - E_predict = molecule_out.energy + for i, atoms in enumerate(atoms_list): + atoms_out = compute_energy(params, atoms) + E_predict = atoms_out.energy diff = E_predict - truth_energies[i] # Not jittable because of if. - num_elec = jnp.sum(molecule.atom_index) - molecule.charge + num_elec = jnp.sum(atoms.atom_index) - atoms.charge if elec_num_norm: diff = diff / num_elec sum += (diff) ** 2 - cost_value = sum / len(molecules) + cost_value = sum / len(atoms) return cost_value @partial(value_and_grad, has_aux=True) def simple_energy_loss(params: PyTree, compute_energy: Callable, - molecule: Molecule, + atoms: Union[Molecule, Solid], truth_energy: Float, ): r""" @@ -517,9 +532,13 @@ def simple_energy_loss(params: PyTree, functional parameters (weights) compute_energy: Callable. any non SCF or SCF method in evaluate.py + atoms: Union[Molecule, Solid] + The collcection of atoms. + truth_energy: Float + The energy value we are training against """ - molecule_out = compute_energy(params, molecule) - E_predict = molecule_out.energy + atoms_out = compute_energy(params, atoms) + E_predict = atoms_out.energy diff = E_predict - truth_energy return diff**2, E_predict @@ -527,7 +546,7 @@ def simple_energy_loss(params: PyTree, def sq_electron_err_int( pred_density: Float[Array, "ngrid nspin"], truth_density: Float[Array, "ngrid nspin"], - molecule: Molecule, + atoms: Union[Molecule, Solid], clip_cte=1e-30 ) -> Scalar: r""" @@ -541,8 +560,8 @@ def sq_electron_err_int( Density predicted by a neural functional truth_density: Float[Array, "ngrid nspin"] A accurate density used as a truth value in training - molecule: Molecule - A Grad-DFT Molecule + atoms: Union[Molecule, Solid] + The collection of atoms. Returns Scalar: the value epsilon described above @@ -552,14 +571,19 @@ def sq_electron_err_int( truth_density = jnp.clip(truth_density, a_min=clip_cte) diff_up = jnp.clip(jnp.clip(pred_density[:, 0] - truth_density[:, 0], a_min=clip_cte) ** 2, a_min=clip_cte) diff_dn = jnp.clip(jnp.clip(pred_density[:, 1] - truth_density[:, 1], a_min=clip_cte) ** 2, a_min=clip_cte) - err_int = jnp.sum(diff_up * molecule.grid.weights) + jnp.sum(diff_dn * molecule.grid.weights) + err_int = jnp.sum(diff_up * atoms.grid.weights) + jnp.sum(diff_dn * atoms.grid.weights) return err_int def mse_density_loss( params: PyTree, compute_energy: Callable, - molecules: list[Molecule], + atoms_list: Union[list[Molecule], + list[Solid], + list[Union[Molecule,Solid]], + Molecule, + Solid + ], truth_rhos: list[Float[Array, "ngrid nspin"]], elec_num_norm: Scalar = True, ) -> Scalar: @@ -575,8 +599,9 @@ def mse_density_loss( functional parameters (weights) compute_energy: Callable. any non SCF or SCF method in evaluate.py - molecule: Molecule - a Grad-DFT Molecule object + atoms_list: Union[list[Molecule], list[Solid], list[Union[Molecule,Solid]], Molecule, Solid] + A list of `Molecule` or `Solid` objects or a combination of both. Passing + a single `Molecule` or `Solid` wraps it in a list internally. truth_densities: list[Float[Array, "ngrid nspin"]] the truth values of the density to measure the predictions against elec_num_norm: Scalar @@ -586,17 +611,21 @@ def mse_density_loss( ---------- Scalar: the mean-squared error between predicted and truth densities """ + # Catch the case where a list of atoms was not passed. I.e, dealing with a single + # instance. + if isinstance(atoms_list, Molecule) or isinstance(atoms_list, Solid): + atoms_list = [atoms_list] sum = 0 - for i, molecule in enumerate(molecules): - molecule_out = compute_energy(params, molecule) - rho_predict = molecule_out.density() - diff = sq_electron_err_int(rho_predict, truth_rhos[i], molecule) + for i, atoms in enumerate(atoms_list): + atoms_out = compute_energy(params, atoms) + rho_predict = atoms_out.density() + diff = sq_electron_err_int(rho_predict, truth_rhos[i], atoms) # Not jittable because of if. - num_elec = jnp.sum(molecule.atom_index) - molecule.charge + num_elec = jnp.sum(atoms.atom_index) - atoms.charge if elec_num_norm: diff = diff / num_elec**2 sum += diff - cost_value = sum / len(molecules) + cost_value = sum / len(atoms_list) return cost_value @@ -604,7 +633,12 @@ def mse_density_loss( def mse_energy_and_density_loss( params: PyTree, compute_energy: Callable, - molecules: list[Molecule], + atoms_list: Union[list[Molecule], + list[Solid], + list[Union[Molecule,Solid]], + Molecule, + Solid + ], truth_densities: list[Float[Array, "ngrid nspin"]], truth_energies: Float[Array, "energy"], rho_factor: Scalar = 1.0, @@ -623,8 +657,9 @@ def mse_energy_and_density_loss( functional parameters (weights) compute_energy: Callable. any non SCF or SCF method in evaluate.py - molecule: Molecule - a Grad-DFT Molecule object + atoms_list: Union[list[Molecule], list[Solid], list[Union[Molecule,Solid]], Molecule, Solid] + A list of `Molecule` or `Solid` objects or a combination of both. Passing + a single `Molecule` or `Solid` wraps it in a list internally. truth_densities: list[Float[Array, "ngrid, nspin"]] the truth values of the density to measure the predictions against truth_energies: Float[Array, "energy"] @@ -634,28 +669,32 @@ def mse_energy_and_density_loss( density_factor: Scalar A weighting factor for the density portion of the loss. Default = 1.0 elec_num_norm: Scalar - True to normalize the loss function by the number of electrons in a Molecule. + True to normalize the loss function by the number of electrons in an atoms instance. Returns ---------- Scalar: the mean-squared error of both energies and densities each with it's own weight. """ + # Catch the case where a list of atoms was not passed. I.e, dealing with a single + # instance. + if isinstance(atoms_list, Molecule) or isinstance(atoms_list, Solid): + atoms_list = [atoms_list] sum_energy = 0 sum_rho = 0 - for i, molecule in enumerate(molecules): - molecule_out = compute_energy(params, molecule) - rho_predict = molecule_out.density() - energy_predict = molecule_out.energy - diff_rho = sq_electron_err_int(rho_predict, truth_densities[i], molecule) + for i, atoms in enumerate(atoms_list): + atoms_out = compute_energy(params, atoms) + rho_predict = atoms_out.density() + energy_predict = atoms_out.energy + diff_rho = sq_electron_err_int(rho_predict, truth_densities[i], atoms) diff_energy = energy_predict - truth_energies[i] # Not jittable because of if. - num_elec = jnp.sum(molecule.atom_index) - molecule.charge + num_elec = jnp.sum(atoms.atom_index) - atoms.charge if elec_num_norm: diff_rho = diff_rho / num_elec**2 diff_energy = diff_energy / num_elec sum_rho += diff_rho sum_energy += diff_energy**2 - energy_contrib = energy_factor * sum_energy / len(molecules) - rho_contrib = rho_factor * sum_rho / len(molecules) + energy_contrib = energy_factor * sum_energy / len(atoms) + rho_contrib = rho_factor * sum_rho / len(atoms) return energy_contrib + rho_contrib From 973e5a70d98e3d04e287ab00e00a668bf2b750e3 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 16:58:12 -0500 Subject: [PATCH 13/36] Fixing tests --- tests/unit/test_loss.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/test_loss.py b/tests/unit/test_loss.py index 805f786..501b3a5 100644 --- a/tests/unit/test_loss.py +++ b/tests/unit/test_loss.py @@ -51,23 +51,23 @@ @struct.dataclass -class dummy_grid: +class Grid: r"""A dummy Grid object used only to access the weights attribute used in the density loss functions """ weights: Array -GRID = dummy_grid(GRID_WEIGHTS) +GRID = Grid(GRID_WEIGHTS) @struct.dataclass -class dummy_molecule: +class Molecule: r"""A dummy Molecule object used only to access the atom_index and charge attributes used in loss functions """ atom_index: Int[Array, "atoms"] - grid: dummy_grid + grid: Grid charge: Scalar = 0 energy: Optional[Scalar] = 0 rdm1: Optional[Float[Array, "spin orbitals orbitals"]] = 0 @@ -77,11 +77,11 @@ def density(self): return self.rho -MOLECULES = [dummy_molecule(jnp.array([1, 1]), GRID), - dummy_molecule(jnp.array([1, 8, 1]), GRID)] +MOLECULES = [Molecule(jnp.array([1, 1]), GRID), + Molecule(jnp.array([1, 8, 1]), GRID)] -def dummy_predictor(params: PyTree, molecule: dummy_molecule) -> dummy_molecule: +def dummy_predictor(params: PyTree, molecule: Molecule) -> Molecule: r"""A dummy function matching the signature of the predictor functions in Grad-DFT Args: From 8a03e5dadf627a19025f9d78fad98b2dda2d7c4b Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 17:45:10 -0500 Subject: [PATCH 14/36] Fixed bug in training functiojs --- grad_dft/train.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index 0e133ef..5aa0d8e 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -513,7 +513,7 @@ def mse_energy_loss( if elec_num_norm: diff = diff / num_elec sum += (diff) ** 2 - cost_value = sum / len(atoms) + cost_value = sum / len(atoms_list) return cost_value @@ -695,6 +695,6 @@ def mse_energy_and_density_loss( sum_rho += diff_rho sum_energy += diff_energy**2 energy_contrib = energy_factor * sum_energy / len(atoms) - rho_contrib = rho_factor * sum_rho / len(atoms) + rho_contrib = rho_factor * sum_rho / len(atoms_list) return energy_contrib + rho_contrib From f4ca97be04f46a7f322b895a13254bc63588e56b Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 17:51:59 -0500 Subject: [PATCH 15/36] Another bug fixed --- grad_dft/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index 5aa0d8e..15763fe 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -694,7 +694,7 @@ def mse_energy_and_density_loss( diff_energy = diff_energy / num_elec sum_rho += diff_rho sum_energy += diff_energy**2 - energy_contrib = energy_factor * sum_energy / len(atoms) + energy_contrib = energy_factor * sum_energy / len(atoms_list) rho_contrib = rho_factor * sum_rho / len(atoms_list) return energy_contrib + rho_contrib From 290cb388bd9b1860726cd0693afe293f82f3740f Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 8 Nov 2023 19:01:13 -0500 Subject: [PATCH 16/36] Changes to allow solid computaiton in train.py --- grad_dft/train.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index 15763fe..60c74e6 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -143,10 +143,16 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala (*batch_size, n_spin, n_orbitals, n_orbitals) for a `Molecule` or (*batch_size, n_spin, n_kpt, n_orbitals, n_orbitals) for a `Solid`. """ - + energy, fock = energy_and_grads(params, atoms.rdm1, atoms, *args) + + # Improve stability by clipping and symmetrizing + if isinstance(atoms, Molecule): + transpose_dims = (0, 2, 1) + elif isinstance(atoms, Solid): + transpose_dims = (0, 1, 3, 2) fock = abs_clip(fock, clip_cte) - fock = 1 / 2 * (fock + fock.transpose(0, 2, 1)) + fock = 1 / 2 * (fock + fock.transpose(transpose_dims).conj()) fock = abs_clip(fock, clip_cte) # Compute the features that should be autodifferentiated @@ -189,14 +195,15 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala vxc_expl = functional.densitygrads( functional, params, atoms, nograd_densities, cinputs, grad_densities ) - fock += vxc_expl + vxc_expl.transpose(0, 2, 1) # Sum over omega + print(vxc_expl.shape) + fock += vxc_expl + vxc_expl.transpose(transpose_dims) # Sum over omega fock = abs_clip(fock, clip_cte) if functional.coefficient_input_grads: vxc_expl = functional.coefficient_input_grads( functional, params, atoms, nograd_cinputs, grad_cinputs, densities ) - fock += vxc_expl + vxc_expl.transpose(0, 2, 1) # Sum over omega + fock += vxc_expl + vxc_expl.transpose(transpose_dims) # Sum over omega fock = abs_clip(fock, clip_cte) fock = abs_clip(fock, clip_cte) From 0e1cf90d2e5fa1c848e40b72a053f960499d9eb4 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Thu, 9 Nov 2023 21:29:22 -0500 Subject: [PATCH 17/36] (1) changes to how the fock matrix is computed in auto diff. We only ever need to autodiff the xc part because we already have the one electron and coulomb potentials from when we computed the energy. (2) Most method in train.py now support solids. --- grad_dft/functional.py | 26 +++++++++++++++++++ grad_dft/interface/pyscf.py | 4 +-- grad_dft/molecule.py | 9 +++++++ grad_dft/solid.py | 9 +++++++ grad_dft/train.py | 50 +++++++++++++++++++++++-------------- 5 files changed, 77 insertions(+), 21 deletions(-) diff --git a/grad_dft/functional.py b/grad_dft/functional.py index feb1f65..6e5ffef 100644 --- a/grad_dft/functional.py +++ b/grad_dft/functional.py @@ -286,6 +286,32 @@ def energy(self, params: PyTree, atoms: Union[Molecule, Solid], *args, **kwargs) energy += atoms.nonXC() return energy + + def energy_xc_only(self, params: PyTree, atoms: Union[Molecule, Solid], *args, **kwargs) -> Scalar: + r""" + Compute the XC only using the same function signature as functional.energy + + Parameters + --------- + params: PyTree + params of the neural network if there is one in self.f + atoms: Union[Molecule, Solid] + + *args: other arguments to compute_densities or compute_coefficient_inputs + **kwargs: other key word arguments to densities and self.xc_energy + + Returns + ------- + Scalar + """ + + densities = self.compute_densities(atoms, *args, **kwargs) + + cinputs = self.compute_coefficient_inputs(atoms, *args) + + Exc = self.xc_energy(params, atoms.grid, cinputs, densities, **kwargs) + + return Exc def _integrate( self, diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index a6f34d9..21e04a4 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -846,7 +846,7 @@ def _package_outputs( vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) - kpt_info = kpt_info_from_pyscf(mf) + kpt_info = None # Unrestricted (spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] == 1: @@ -874,7 +874,7 @@ def _package_outputs( vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) rep_tensor = df.DF(mf.cell).get_ao_eri(compact=False).reshape(nao, nao, nao, nao) - kpt_info = kpt_info_from_pyscf(mf) + kpt_info = None else: raise RuntimeError( diff --git a/grad_dft/molecule.py b/grad_dft/molecule.py index 6436c97..ba4550e 100644 --- a/grad_dft/molecule.py +++ b/grad_dft/molecule.py @@ -104,6 +104,15 @@ class Molecule: @property def grid_size(self): return len(self.grid) + + def get_coulomb_potential(self, *args, **kwargs) -> Float[Array, "orbitals orbitals"]: + r"""Compute the Coulomb potential matrix. + + Returns + ------- + Float[Array, "spin orbitals orbitals"] + """ + return coulomb_potential(self.rdm1.sum(axis=0), self.rep_tensor, *args, **kwargs) def density(self, *args, **kwargs) -> Array: r""" Computes the electronic density of a molecule at each grid point. diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 06b43f1..189742b 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -214,6 +214,15 @@ def to_dict(self) -> dict: rest = {field.name: getattr(self, field.name) for field in fields(self)[2:]} return dict(**grid_dict, **kpt_dict, **rest) + def get_coulomb_potential(self, *args, **kwargs) -> Complex[Array, "n_kpts_or_n_ir_kpts n_orbitals n_orbitals"]: + r""" + Computes the Coulomb potential matrix for all k-points. + + Returns + ------- + Complex[Array, "n_kpts_or_n_ir_kpts n_orbitals n_orbitals"] + """ + return coulomb_potential(self.rdm1.sum(axis=0), self.rep_tensor, self.kpt_info.weights, *args, **kwargs) def select_HF_omegas(self, omegas: Float[Array, "omega"]) -> Array: raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") diff --git a/grad_dft/train.py b/grad_dft/train.py index 60c74e6..02b6465 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -17,7 +17,7 @@ from jaxtyping import Array, PRNGKeyArray, PyTree, Scalar, Float, Complex from jax import numpy as jnp, vmap -from jax import value_and_grad +from jax import value_and_grad, grad from jax.profiler import annotate_function from jax.lax import stop_gradient from optax import OptState, GradientTransformation, apply_updates @@ -82,43 +82,43 @@ def energy_predictor( >>> fock.shape == molecule.density_matrix.shape True """ - + @partial(value_and_grad, argnums=1) - def energy_and_grads( - params: PyTree, + def xc_energy_and_grads( + params: PyTree, rdm1: Union[Float[Array, "spin orbitals orbitals"], Complex[Array, "spin kpt orbitals orbitals"] - ], - atoms: Union[Molecule, Solid], - *args, - **functional_kwargs, + ], + atoms: Union[Molecule, Solid], + *args, + **functional_kwargs ) -> Scalar: r""" - Computes the energy and gradients with respect to the density matrix + Computes the xc energy and gradients with respect to the density matrix. Parameters ---------- params: Pytree Functional parameters rdm1: Float[Array, "spin orbitals orbitals"] - The 1-body reduced density matrix. + The reduced density matrix. atoms: Union[Molecule, Solid] The collection of atoms. + *args + **kwargs Returns ----------- - Scalar - The energy of the atoms when the state of the system is given by rdm1. + Tuple[Scalar, Float[Array, "spin orbitals orbitals"]] """ - atoms = atoms.replace(rdm1=rdm1) - - e = functional.energy(params, atoms, *args, **functional_kwargs) + densities = functional.compute_densities(atoms, *args, **kwargs) + cinputs = functional.compute_coefficient_inputs(atoms, *args) if nlc_functional: e = e + nlc_functional.energy( {"params": params["dispersion"]}, atoms, **functional_kwargs ) - return e + return functional.xc_energy(params, atoms.grid, cinputs, densities, **kwargs) @partial(annotate_function, name="predict") def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scalar, Array]: @@ -144,13 +144,26 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala (*batch_size, n_spin, n_kpt, n_orbitals, n_orbitals) for a `Solid`. """ - energy, fock = energy_and_grads(params, atoms.rdm1, atoms, *args) + Exc, fock_xc = xc_energy_and_grads(params, atoms.rdm1, atoms, *args) + fock_noxc = atoms.h1e + atoms.get_coulomb_potential() + + energy = Exc + atoms.nonXC() - # Improve stability by clipping and symmetrizing if isinstance(atoms, Molecule): transpose_dims = (0, 2, 1) + fock = fock_noxc + fock_xc elif isinstance(atoms, Solid): transpose_dims = (0, 1, 3, 2) + # auto-diffed xc gradient is divided by n_k=number of k-points. Undo this. + fock = fock_noxc + (fock_xc*atoms.rdm1.shape[1]) + + """Note: the summed difference between the fock matrix elements computed here and the fock + matrix computed directly by PySCF is correct to ~1e-16 for the Molecule + case but only matches PySCF to ~1e-9 for a Solid. This may not be cause for concern, + but I will leave this note here in the event that somebody is chasing a bug. + """ + + # Improve stability by clipping and symmetrizing fock = abs_clip(fock, clip_cte) fock = 1 / 2 * (fock + fock.transpose(transpose_dims).conj()) fock = abs_clip(fock, clip_cte) @@ -207,7 +220,6 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala fock = abs_clip(fock, clip_cte) fock = abs_clip(fock, clip_cte) - return energy, fock return predict From 8aff96156eee47ae4e04bd963bdb1ec0c59c45b7 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Thu, 9 Nov 2023 21:41:58 -0500 Subject: [PATCH 18/36] Fix wrong kwargs being passed --- grad_dft/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index 02b6465..0399b84 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -112,7 +112,7 @@ def xc_energy_and_grads( Tuple[Scalar, Float[Array, "spin orbitals orbitals"]] """ atoms = atoms.replace(rdm1=rdm1) - densities = functional.compute_densities(atoms, *args, **kwargs) + densities = functional.compute_densities(atoms, *args, **functional_kwargs) cinputs = functional.compute_coefficient_inputs(atoms, *args) if nlc_functional: e = e + nlc_functional.energy( From c680dab86874a3fc13e52cfd2ed7d88b0722b456 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Thu, 9 Nov 2023 21:45:36 -0500 Subject: [PATCH 19/36] another wrong kwarg problem --- grad_dft/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grad_dft/train.py b/grad_dft/train.py index 0399b84..f2decf3 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -118,7 +118,7 @@ def xc_energy_and_grads( e = e + nlc_functional.energy( {"params": params["dispersion"]}, atoms, **functional_kwargs ) - return functional.xc_energy(params, atoms.grid, cinputs, densities, **kwargs) + return functional.xc_energy(params, atoms.grid, cinputs, densities, **functional_kwargs) @partial(annotate_function, name="predict") def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scalar, Array]: From 357434a968e27c62e378a634f979617765cfe7e2 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Fri, 10 Nov 2023 12:39:59 -0500 Subject: [PATCH 20/36] MO gradients implemented. Began modifying linear mixing SCF loop to deal with solids --- grad_dft/evaluate.py | 34 ++++++++++++++-------------- grad_dft/solid.py | 53 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/grad_dft/evaluate.py b/grad_dft/evaluate.py index b075349..60eac18 100644 --- a/grad_dft/evaluate.py +++ b/grad_dft/evaluate.py @@ -23,16 +23,16 @@ import sys -from typing import Callable, Tuple, Optional +from typing import Callable, Tuple, Optional, Union from functools import partial, reduce import time from scipy.optimize import bisect from grad_dft import ( - Molecule, + Molecule, + Solid, abs_clip, make_rdm1, - orbital_grad, Functional, energy_predictor, ) @@ -91,7 +91,7 @@ def non_scf_predictor( **kwargs, ) -> Callable: r""" - Creates an non_scf_predictor function which when called non-self consistently + Creates an non_scf_predictor function, which when called, non-self consistently calculates the total energy at a fixed density. Main parameters @@ -103,25 +103,25 @@ def non_scf_predictor( Callable """ compute_energy = energy_predictor(functional, chunk_size=chunk_size, **kwargs) - def non_scf_predictor(params: PyTree, molecule: Molecule, *args) -> Molecule: + def non_scf_predictor(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Union[Molecule, Solid]: r"""Calculates the total energy at a fixed density non-self consistently. Main parameters --------------- params: Pytree Parameters of the neural functional - molecule: Molecule - A Grad-DFT molecule object + atoms: Union[Molecule, Solid] + A Grad-DFT Molecule or Solid object Returns --------- Molecule - A Grad-DFT Molecule object with updated attributes + A Grad-DFT Molecule or Solid object with updated attributes """ - predicted_e, fock = compute_energy(params, molecule, *args) - molecule = molecule.replace(fock=fock) - molecule = molecule.replace(energy=predicted_e) - return molecule + predicted_e, fock = compute_energy(params, atoms, *args) + atoms = atoms.replace(fock=fock) + atoms = atoms.replace(energy=predicted_e) + return atoms return non_scf_predictor @@ -231,7 +231,7 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a ) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(orbital_grad(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) if verbose > 1: print( @@ -338,7 +338,7 @@ def loop_body(cycle, state): molecule = molecule.replace(fock=fock) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(orbital_grad(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) state = (molecule, predicted_e, old_e, norm_gorb) @@ -535,7 +535,7 @@ def nelec_cost_fn(m, mo_es, sigma, _nelectron): ) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(orbital_grad(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) if verbose > 1: print( @@ -578,7 +578,7 @@ def nelec_cost_fn(m, mo_es, sigma, _nelectron): predicted_e, fock = compute_energy(params, molecule, *args) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(orbital_grad(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) if verbose > 1: print( @@ -1006,7 +1006,7 @@ def loop_body(cycle, state): molecule = molecule.replace(fock=fock) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(orbital_grad(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) state = (molecule, predicted_e, old_e, norm_gorb, diis_data) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 189742b..8c9f829 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -19,7 +19,7 @@ from typeguard import typechecked from grad_dft.utils import vmap_chunked from functools import partial -from jax import jit +from jax import jit, vmap from jax.lax import fori_loop, cond from dataclasses import fields @@ -253,7 +253,16 @@ def HF_coefficient_input_grad_2_Fock( **kwargs, ) -> Float[Array, "omega spin orbitals orbitals"]: raise NotImplementedError("Hartree-Fock methods (for computation of Hybrid functionals) will come in a later release.") + + def get_mo_grads(self, *args, **kwargs): + r"""Compute the gradient of the electronic energy with respect + to the molecular orbital coefficients. + Returns: + ------- + Float[Array, "orbitals orbitals"] + """ + return orbital_grad(self.mo_coeff, self.mo_occ, self.fock, *args, **kwargs) @jaxtyped @@ -618,5 +627,47 @@ def kinetic_density( return 0.5 * jnp.einsum("k,...kab,raj,rbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision).real +@jaxtyped +@typechecked +@partial(jit, static_argnames="precision") +def orbital_grad( + mo_coeff: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], + mo_occ: Float[Array, "n_spin n_kpt n_orbitals"], + F: Complex[Array, "n_spin n_orbitals n_orbitals"], + precision: Precision = Precision.HIGHEST + ) -> Float[Array, "n_kpt n_orbitals n_orbitals"]: + r"""Compute the gradient of the electronic energy with respect + to the molecular orbital coefficients. + + Parameters: + ---------- + mo_coeff: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + Orbital coefficients + mo_occ: Float[Array, "n_spin n_kpt n_orbitals"] + Orbital occupancy + F: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + Fock matrix in AO representation + precision: jax.lax.Precision, optional + + Returns: + ------- + Float[Array, "n_kpt n_orbitals n_orbitals"] + + + Notes: + ----- + # Performs same task as pyscf/scf/hf.py but we have k-point sampling: + occidx = mo_occ > 0 + viridx = ~occidx + g = reduce(jnp.dot, (mo_coeff[:,viridx].conj().T, fock_ao, + mo_coeff[:,occidx])) * 2 + return g.ravel() + """ + + C_occ = vmap(jnp.where, in_axes=(None, 2, None), out_axes=2)(mo_occ > 0, mo_coeff, 0) + C_vir = vmap(jnp.where, in_axes=(None, 2, None), out_axes=2)(mo_occ == 0, mo_coeff, 0) + + return jnp.einsum("skab,skac,skcd->kbd", C_vir.conj(), F, C_occ, precision = precision) + From 005af276ba5c957f3aec39cd65a436e76e346dcb Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Fri, 10 Nov 2023 13:29:09 -0500 Subject: [PATCH 21/36] Forgot to commit molecule changes for mo grads --- grad_dft/molecule.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/grad_dft/molecule.py b/grad_dft/molecule.py index ba4550e..580430b 100644 --- a/grad_dft/molecule.py +++ b/grad_dft/molecule.py @@ -318,6 +318,16 @@ def get_occ(self) -> Array: nelecs = jnp.array([self.mo_occ[i].sum() for i in range(2)], dtype=jnp.int64) naos = self.mo_occ.shape[1] return get_occ(self.mo_energy, nelecs, naos) + + def get_mo_grads(self, *args, **kwargs): + r"""Compute the gradient of the electronic energy with respect + to the molecular orbital coefficients. + + Returns: + ------- + Float[Array, "orbitals orbitals"] + """ + return orbital_grad(self.mo_coeff, self.mo_occ, self.fock, *args, **kwargs) def to_dict(self) -> dict: r""" Returns a dictionary with the attributes of the molecule.""" @@ -337,7 +347,8 @@ def orbital_grad( F: Float[Array, "spin orbitals orbitals"], precision: Precision = Precision.HIGHEST ) -> Float[Array, "orbitals orbitals"]: - r""" Computes the restricted Hartree Fock orbital gradients + r"""Compute the gradient of the electronic energy with respect + to the molecular orbital coefficients. Parameters: ---------- @@ -356,7 +367,7 @@ def orbital_grad( Notes: ----- - # Similar to pyscf/scf/hf.py: + # Performs same task as pyscf/scf/hf.py: occidx = mo_occ > 0 viridx = ~occidx g = reduce(jnp.dot, (mo_coeff[:,viridx].conj().T, fock_ao, From 44690a80cc82b4e46bc5d5a0346b72e684b493ec Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Fri, 10 Nov 2023 13:47:42 -0500 Subject: [PATCH 22/36] Whoops, shouln't have left arguments --- grad_dft/evaluate.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/grad_dft/evaluate.py b/grad_dft/evaluate.py index 60eac18..8ebef49 100644 --- a/grad_dft/evaluate.py +++ b/grad_dft/evaluate.py @@ -231,7 +231,7 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a ) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) if verbose > 1: print( @@ -338,7 +338,7 @@ def loop_body(cycle, state): molecule = molecule.replace(fock=fock) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) state = (molecule, predicted_e, old_e, norm_gorb) @@ -535,7 +535,7 @@ def nelec_cost_fn(m, mo_es, sigma, _nelectron): ) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) if verbose > 1: print( @@ -578,7 +578,7 @@ def nelec_cost_fn(m, mo_es, sigma, _nelectron): predicted_e, fock = compute_energy(params, molecule, *args) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) if verbose > 1: print( @@ -1006,7 +1006,7 @@ def loop_body(cycle, state): molecule = molecule.replace(fock=fock) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads(mo_coeff, mo_occ, fock)) + norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) state = (molecule, predicted_e, old_e, norm_gorb, diis_data) From 689c57b739944cad590a782b4e509b94bc284eca Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Fri, 10 Nov 2023 18:03:56 -0500 Subject: [PATCH 23/36] changes to eigenproblem to allow for N_k fock matrices to be diagonalized. Broadcasting is appropriate even for input matrices without an N_k dimension should should work for molecules and solids --- grad_dft/utils/eigenproblem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grad_dft/utils/eigenproblem.py b/grad_dft/utils/eigenproblem.py index b04f128..7a17115 100644 --- a/grad_dft/utils/eigenproblem.py +++ b/grad_dft/utils/eigenproblem.py @@ -122,9 +122,9 @@ def safe_general_eigh(A: Array, B: Array) -> tuple[Array, Array]: """ L = jnp.linalg.cholesky(B) L_inv = jnp.linalg.inv(L) - C = L_inv @ A @ L_inv.T + C = L_inv @ A @ jnp.moveaxis(L_inv, -1, -2) eigenvalues, eigenvectors_transformed = safe_eigh(C) - eigenvectors_original = L_inv.T @ eigenvectors_transformed + eigenvectors_original = jnp.moveaxis(L_inv, -1, -2) @ eigenvectors_transformed return eigenvalues, eigenvectors_original From 7685b3ffaa32a44371050b4d14d8ce9bde29f951 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Tue, 14 Nov 2023 22:31:32 -0500 Subject: [PATCH 24/36] fixes to eigenproblem to allow vectorization along k-point dimension --- grad_dft/solid.py | 6 +++--- grad_dft/utils/eigenproblem.py | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 8c9f829..1b9ad30 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -633,7 +633,7 @@ def kinetic_density( def orbital_grad( mo_coeff: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], mo_occ: Float[Array, "n_spin n_kpt n_orbitals"], - F: Complex[Array, "n_spin n_orbitals n_orbitals"], + fock: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], precision: Precision = Precision.HIGHEST ) -> Float[Array, "n_kpt n_orbitals n_orbitals"]: r"""Compute the gradient of the electronic energy with respect @@ -645,7 +645,7 @@ def orbital_grad( Orbital coefficients mo_occ: Float[Array, "n_spin n_kpt n_orbitals"] Orbital occupancy - F: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] + fock: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] Fock matrix in AO representation precision: jax.lax.Precision, optional @@ -667,7 +667,7 @@ def orbital_grad( C_occ = vmap(jnp.where, in_axes=(None, 2, None), out_axes=2)(mo_occ > 0, mo_coeff, 0) C_vir = vmap(jnp.where, in_axes=(None, 2, None), out_axes=2)(mo_occ == 0, mo_coeff, 0) - return jnp.einsum("skab,skac,skcd->kbd", C_vir.conj(), F, C_occ, precision = precision) + return jnp.einsum("skab,skac,skcd->kbd", C_vir.conj(), fock, C_occ, precision = precision).real diff --git a/grad_dft/utils/eigenproblem.py b/grad_dft/utils/eigenproblem.py index 7a17115..2afcfc8 100644 --- a/grad_dft/utils/eigenproblem.py +++ b/grad_dft/utils/eigenproblem.py @@ -34,8 +34,8 @@ def safe_eigh(A: Array) -> tuple[Array, Array]: Returns: tuple[Array, Array]: the eigenvalues and eigenvectors of the input real symmetric matrix. """ - evecs, evals = jnp.linalg.eigh(A) - return evecs, evals + evals, evecs = jnp.linalg.eigh(A) + return evals, evecs def safe_eigh_fwd(A: Array) -> tuple[tuple[Array, Array], tuple[tuple[Array, Array], Array]]: @@ -104,6 +104,7 @@ def safe_eigh_rev(res: tuple[tuple[Array, Array], Array], g: Array) -> tuple[Arr safe_eigh.defvjp(safe_eigh_fwd, safe_eigh_rev) +safe_eigh_vec = jnp.vectorize(safe_eigh, signature="(m,m)->(n),(n,n)") def safe_general_eigh(A: Array, B: Array) -> tuple[Array, Array]: @@ -123,7 +124,7 @@ def safe_general_eigh(A: Array, B: Array) -> tuple[Array, Array]: L = jnp.linalg.cholesky(B) L_inv = jnp.linalg.inv(L) C = L_inv @ A @ jnp.moveaxis(L_inv, -1, -2) - eigenvalues, eigenvectors_transformed = safe_eigh(C) + eigenvalues, eigenvectors_transformed = safe_eigh_vec(C) eigenvectors_original = jnp.moveaxis(L_inv, -1, -2) @ eigenvectors_transformed return eigenvalues, eigenvectors_original From 536c80b4a5c2d9f8e2e58323a28d8fb38af9703e Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 20 Nov 2023 00:57:52 -0500 Subject: [PATCH 25/36] Crystal orbitals now are used in density calculations. --- grad_dft/evaluate.py | 9 ++-- grad_dft/interface/pyscf.py | 92 ++++++++++++++++++++++++++++++++----- grad_dft/solid.py | 13 ++++-- grad_dft/train.py | 1 - 4 files changed, 93 insertions(+), 22 deletions(-) diff --git a/grad_dft/evaluate.py b/grad_dft/evaluate.py index 8ebef49..502046d 100644 --- a/grad_dft/evaluate.py +++ b/grad_dft/evaluate.py @@ -211,12 +211,13 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a old_rdm1 = rdm1 - computed_charge = jnp.einsum( - "r,ra,rb,sab->", molecule.grid.weights, molecule.ao, molecule.ao, molecule.rdm1 - ) + # computed_charge = jnp.einsum( + # "r,ra,rb,ksab->", molecule.grid.weights, molecule.ao, molecule.ao, molecule.rdm1 + # ) + computed_charge = jnp.einsum("r,rs->", molecule.grid.weights, molecule.density()) assert jnp.isclose( nelectron, computed_charge, atol=1e-3 - ), "Total charge is not conserved" + ), "Total charge is not conserved. given electrons: %.3f, computed electrons: %.3f" % (nelectron, computed_charge) exc_start_time = time.time() diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 21e04a4..485fc38 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -24,6 +24,7 @@ from pyscf import scf # type: ignore from pyscf.dft import Grids, numint # type: ignore +from pyscf.pbc.dft import numint as pbc_numint from pyscf.gto import Mole import pyscf.data.elements as elements from pyscf.pbc.gto.cell import Cell @@ -667,10 +668,6 @@ def ao_grads(mol: Mole, coords: Array, order=2) -> Dict: .. math:: \nabla^n \psi - Parameters - ---------- - mf: PySCF Density Functional object. - Outputs ---------- Dict @@ -695,17 +692,44 @@ def ao_grads(mol: Mole, coords: Array, order=2) -> Dict: i += 1 return result +def pbc_ao_grads(cell: Cell, coords: Array, order=2, kpts=[np.zeros(3)]) -> Dict: + r"""Function to compute nth order crystal atomic orbital grads, for n > 1. + + .. math:: + \nabla^n \psi + + Outputs + ---------- + Dict + For each order n > 1, result[n] is an array of shape + (n_kpt, n_grid, n_ao, 3) where the fourth coordinate indicates + .. math:: + \frac{\partial^n \psi}{\partial x_i^n} + + for :math:`x_i` is one of the usual cartesian coordinates x, y or z. + """ + ao_ = pbc_numint.eval_ao_kpts(cell, coords, kpts=kpts[0], deriv=order) + ao_ = np.asarray(ao_) + aos = ao_[:, 0, :, :] + if order == 0: + return ao_ + result = {} + i = 4 + for n in range(2, order + 1): + result[n] = jnp.empty((len(kpts), aos.shape[1], aos.shape[2], 0)) + for c in combinations_with_replacement("xyz", r=n): + if len(set(c)) == 1: + result[n] = jnp.concatenate((result[n], jnp.expand_dims(ao_[:, i, :, :], axis=3)), axis=3) + i += 1 + return result + def _package_outputs( mf: DensityFunctional, grids: Optional[Grids] = None, scf_iteration: Scalar = jnp.int32(50), grad_order: Scalar = jnp.int32(2), -): - ao_ = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) - ao = ao_[0] - nao = ao.shape[1] - +): if scf_iteration != 0: rdm1 = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) else: @@ -716,6 +740,11 @@ def _package_outputs( # Restricted (non-spin polarized), open boundary conditions if rdm1.ndim == 2 and not hasattr(mf, "cell"): + ao_and_1deriv = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) + ao = ao_and_1deriv[0] + nao = ao.shape[1] + grad_ao = ao_and_1deriv[1:4].transpose(1, 2, 0) + grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) s1e = mf.get_ovlp(mf.mol) h1e = mf.get_hcore(mf.mol) half_dm = rdm1 / 2 @@ -737,6 +766,11 @@ def _package_outputs( # Unrestricted (spin polarized), open boundary conditions elif rdm1.ndim == 3 and not hasattr(mf, "cell"): + ao_and_1deriv = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) + ao = ao_and_1deriv[0] + nao = ao.shape[1] + grad_ao = ao_and_1deriv[1:4].transpose(1, 2, 0) + grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) s1e = mf.get_ovlp(mf.mol) h1e = mf.get_hcore(mf.mol) mo_coeff = np.stack(mf.mo_coeff, axis=0) @@ -752,6 +786,13 @@ def _package_outputs( # Restricted (non-spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] != 1: + ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) + ao_and_1deriv = np.asarray(ao_and_1deriv) + ao = ao_and_1deriv[:, 0, :, :] + nao = ao.shape[2] + grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) + grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order, kpts=mf.kpts) + # grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) s1e = mf.get_ovlp(mf.mol) h1e = mf.get_hcore(mf.mol) @@ -787,6 +828,13 @@ def _package_outputs( # Unrestricted (spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] != 1: + ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) + ao_and_1deriv = np.asarray(ao_and_1deriv) + ao = ao_and_1deriv[:, 0, :, :] + nao = ao.shape[2] + grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) + grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order, kpts=mf.kpts) + s1e = mf.get_ovlp(mf.mol) h1e = mf.get_hcore(mf.mol) mo_coeff = np.stack(mf.mo_coeff, axis=0) @@ -815,7 +863,18 @@ def _package_outputs( # Restricted (non-spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] == 1: + ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) + ao_and_1deriv = np.asarray(ao_and_1deriv) + ao = ao_and_1deriv[:, 0, :, :] + nao = ao.shape[2] + grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) + grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order) # Collapse the redundant extra dimension from k-points: gamma only + ao = np.squeeze(ao, axis=0) + grad_ao = np.squeeze(grad_ao, axis=0) + for key in grad_n_ao.keys(): + grad_n_ao[key] = np.squeeze(grad_n_ao[key], axis=0) + s1e = mf.get_ovlp(mf.mol) s1e = np.squeeze(s1e, axis=0) h1e = mf.get_hcore(mf.mol) @@ -850,6 +909,18 @@ def _package_outputs( # Unrestricted (spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] == 1: + ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) + ao_and_1deriv = np.asarray(ao_and_1deriv) + ao = ao_and_1deriv[:, 0, :, :] + nao = ao.shape[2] + grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) + grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order) + + # Collapse the redundant extra dimension from k-points: gamma only + for key in grad_n_ao.keys(): + grad_n_ao[key] = np.squeeze(grad_n_ao[key], axis=0) + ao = np.squeeze(ao, axis=0) + grad_ao = np.squeeze(grad_ao, axis=0) s1e = mf.get_ovlp(mf.mol) s1e = np.squeeze(s1e, axis=0) h1e = mf.get_hcore(mf.mol) @@ -880,9 +951,6 @@ def _package_outputs( raise RuntimeError( f"Invalid density matrix shape. Got {rdm1.shape} for AO shape {ao.shape}" ) - - grad_ao = ao_[1:4].transpose(1, 2, 0) - grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) mf_e_tot = mf.e_tot energy_nuc = mf.energy_nuc() diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 1b9ad30..4ccfa0c 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -15,6 +15,7 @@ import jax.numpy as jnp from jax.lax import Precision from typing import List, Optional +import jax from typeguard import typechecked from grad_dft.utils import vmap_chunked @@ -111,8 +112,8 @@ class Solid: atom_index: Int[Array, "n_atom"] lattice_vectors: Float[Array, "3 3"] nuclear_pos: Float[Array, "n_atom 3"] - ao: Float[Array, "n_flat_grid n_orbitals"] - grad_ao: Float[Array, "n_flat_grid n_orbitals 3"] + ao: Float[Array, "n_kpt n_flat_grid n_orbitals"] # ao = Crystal Atomic Orbitals in PBC case + grad_ao: Float[Array, "nkpt n_flat_grid n_orbitals 3"] grad_n_ao: PyTree rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] nuclear_repulsion: Scalar @@ -513,9 +514,11 @@ def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], ------- Float[Array, "n_flat_grid n_spin"] """ - - return jnp.einsum("k,...kab,ra,rb->r...", weights, rdm1, ao, ao, precision=precision).real - + den = jnp.einsum("skab,ra,rb->rs", rdm1, ao, ao, precision=precision).real/weights.shape[0] + # den = jnp.einsum("...kab,ra,rb->r...", rdm1, ao, ao, precision=precision) + print(jnp.sum(den.imag)) + jax.debug.print("imag remainder is {x}", x=jnp.sum(den.imag)) + return den @jaxtyped @typechecked @partial(jit, static_argnames="precision") diff --git a/grad_dft/train.py b/grad_dft/train.py index f2decf3..2237ae1 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -208,7 +208,6 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala vxc_expl = functional.densitygrads( functional, params, atoms, nograd_densities, cinputs, grad_densities ) - print(vxc_expl.shape) fock += vxc_expl + vxc_expl.transpose(transpose_dims) # Sum over omega fock = abs_clip(fock, clip_cte) From 7200cdc94eed1437fcfcf115c1fa6fea251a3abf Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 20 Nov 2023 19:06:20 -0500 Subject: [PATCH 26/36] Proper handling of all ERI types in PySCF input parsing. --- grad_dft/interface/pyscf.py | 128 +++++++++++++++++++++++++----------- grad_dft/solid.py | 60 ++++++++--------- grad_dft/train.py | 6 -- 3 files changed, 119 insertions(+), 75 deletions(-) diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 485fc38..a2e0285 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -29,6 +29,10 @@ import pyscf.data.elements as elements from pyscf.pbc.gto.cell import Cell from pyscf.pbc.lib.kpts import KPoints +from pyscf.pbc.df.fft import FFTDF +from pyscf.pbc.df.mdf import MDF +from pyscf.pbc.df.df import GDF +from pyscf.ao2mo import restore # from qdft.reaction import Reaction, make_reaction, get_grad from grad_dft.molecule import Grid, Molecule, Reaction, make_reaction @@ -202,8 +206,9 @@ def solid_from_pyscf( scf_iteration: Scalar = jnp.int32(50), chunk_size: Optional[Scalar] = jnp.int32(1024), grad_order: Optional[Scalar] = jnp.int32(2), -) -> Molecule: - # mf, grids = _maybe_run_kernel(mf, grids) +) -> Solid: + if np.array_equal(kmf.kpts, np.array([[0.0, 0.0, 0.0]])): + raise RuntimeError("Use molecule_from_pyscf for Gamma point only calculations") grid = grid_from_pyscf(kmf.grids, dtype=dtype) pyscf_dat = _package_outputs(kmf, kmf.grids, scf_iteration, grad_order) kpt_info = pyscf_dat[-1] @@ -692,7 +697,7 @@ def ao_grads(mol: Mole, coords: Array, order=2) -> Dict: i += 1 return result -def pbc_ao_grads(cell: Cell, coords: Array, order=2, kpts=[np.zeros(3)]) -> Dict: +def pbc_ao_grads(cell: Cell, coords: Array, order=2, kpts=None) -> Dict: r"""Function to compute nth order crystal atomic orbital grads, for n > 1. .. math:: @@ -708,21 +713,90 @@ def pbc_ao_grads(cell: Cell, coords: Array, order=2, kpts=[np.zeros(3)]) -> Dict for :math:`x_i` is one of the usual cartesian coordinates x, y or z. """ - ao_ = pbc_numint.eval_ao_kpts(cell, coords, kpts=kpts[0], deriv=order) - ao_ = np.asarray(ao_) - aos = ao_[:, 0, :, :] + if kpts is None: + # Default is Gamma only + ao_ = pbc_numint.eval_ao_kpts(cell, coords, kpts=np.zeros(3), deriv=order) + ao_ = np.asarray(ao_) + aos = ao_[:, 0, :, :] + res_shape = (1, aos.shape[1], aos.shape[2], 0) + else: + ao_ = pbc_numint.eval_ao_kpts(cell, coords, kpts=kpts, deriv=order) + ao_ = np.asarray(ao_) + aos = ao_[:, 0, :, :] + res_shape = (kpts.shape[0], aos.shape[1], aos.shape[2], 0) if order == 0: return ao_ result = {} i = 4 for n in range(2, order + 1): - result[n] = jnp.empty((len(kpts), aos.shape[1], aos.shape[2], 0)) + result[n] = jnp.empty(res_shape) for c in combinations_with_replacement("xyz", r=n): if len(set(c)) == 1: result[n] = jnp.concatenate((result[n], jnp.expand_dims(ao_[:, i, :, :], axis=3)), axis=3) i += 1 return result +def calc_eri_with_pyscf(mf, kpts=None) -> np.ndarray: + r"""Calculate the ERIs using the method detected from the PySCF mean field object. + + Inputs + ---------- + + mf: + PySCF mean field object + kpts: + Array of k-points (absolute, not fractional). + + Outputs + ---------- + np.ndarray + + The ERIs. Output shape is (nao, nao, nao, nao) for isolated molecules and gamma-point only + periodic calculations. For full BZ calculations, the output shape is (nkpt, nkpt, nao, nao, nao, nao). + """ + # Solid or Isolated molecule? + if hasattr(mf, "cell"): # Periodic system + + # Check for the three density fitting methods. DF is always used for periodic calculations + if isinstance(mf.with_df, FFTDF): + density_fitter = FFTDF(mf.cell, kpts=kpts) + elif isinstance(mf.with_df, MDF): # Check for MDF before GDF becuase MDF inherits from GDF + density_fitter = MDF(mf.cell, kpts=kpts) + elif isinstance(mf.with_df, GDF): + density_fitter = GDF(mf.cell, kpts=kpts) + + # Calculate the Periodic ERI's. + if kpts is None: + # Assume Gamma point only + eri_compressed = density_fitter.get_eri(kpts=kpts) + eri = restore(1, eri_compressed, mf.cell.nao_nr()) + else: + # Loop over all k-pairs. This will be a fall back in the future. We will encourage users + # to save ERIs to disk after a PySCF calculation. + nkpt = kpts.shape[0] + nao = mf.cell.nao_nr() + # Empty array for all k points in uncompressed format. + eri = np.empty(shape=(nkpt, nkpt, nao, nao, nao, nao), dtype=np.complex128) + for ikpt, jkpt in product(range(nkpt), range(nkpt)): + k_quartet = np.array([kpts[ikpt], kpts[ikpt], kpts[jkpt], kpts[jkpt]]) + eri_kquartet =\ + density_fitter.get_eri(compact=False, kpts=k_quartet).reshape(nao, nao, nao, nao) + eri[ikpt, jkpt, :, :, :, :] = eri_kquartet + + else: # Isolated system + try: + _ = mf.with_df + except(AttributeError): + eri = mf.mol.intor("int2e") + return eri + # Use default DF method when DF is used on molecules + density_fitter = df.DF(mf.mol) + eri_compressed = density_fitter.get_eri() + eri = restore(1, eri_compressed, mf.mol.nao_nr()) + return eri + + + def _package_outputs( mf: DensityFunctional, @@ -742,7 +816,6 @@ def _package_outputs( if rdm1.ndim == 2 and not hasattr(mf, "cell"): ao_and_1deriv = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) ao = ao_and_1deriv[0] - nao = ao.shape[1] grad_ao = ao_and_1deriv[1:4].transpose(1, 2, 0) grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) s1e = mf.get_ovlp(mf.mol) @@ -761,14 +834,13 @@ def _package_outputs( ) # The 2 is to compensate for the /2 in the definition of the density matrix dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - rep_tensor = mf.mol.intor("int2e") + rep_tensor = calc_eri_with_pyscf(mf) kpt_info = None # Unrestricted (spin polarized), open boundary conditions elif rdm1.ndim == 3 and not hasattr(mf, "cell"): ao_and_1deriv = numint.eval_ao(mf.mol, grids.coords, deriv=1) # , non0tab=grids.non0tab) ao = ao_and_1deriv[0] - nao = ao.shape[1] grad_ao = ao_and_1deriv[1:4].transpose(1, 2, 0) grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) s1e = mf.get_ovlp(mf.mol) @@ -781,7 +853,7 @@ def _package_outputs( ) # The 2 is to compensate for the /2 in the definition of the density matrix dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - rep_tensor = mf.mol.intor("int2e") + rep_tensor = calc_eri_with_pyscf(mf) kpt_info = None # Restricted (non-spin polarized), periodic boundary conditions, full BZ sampling @@ -789,7 +861,6 @@ def _package_outputs( ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) ao_and_1deriv = np.asarray(ao_and_1deriv) ao = ao_and_1deriv[:, 0, :, :] - nao = ao.shape[2] grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order, kpts=mf.kpts) # grad_n_ao = ao_grads(mf.mol, jnp.array(mf.grids.coords), order=grad_order) @@ -812,18 +883,9 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation - all_kpts = mf.kpts - nkpt = all_kpts.shape[0] - density_fitter = df.DF(mf.cell, kpts=all_kpts) - rep_tensor = np.empty(shape=(nkpt, nkpt, nao, nao, nao, nao), dtype=np.complex128) - for ikpt in range(nkpt): - for jkpt in range(nkpt): - k_quartet = np.array([all_kpts[ikpt], all_kpts[ikpt], all_kpts[jkpt], all_kpts[jkpt]]) - rep_tensor_kquartet =\ - density_fitter.get_eri(compact=False, kpts=k_quartet).reshape(nao, nao, nao, nao) - rep_tensor[ikpt, jkpt, :, :, :, :] = rep_tensor_kquartet kpt_info = kpt_info_from_pyscf(mf) + # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation + rep_tensor = calc_eri_with_pyscf(mf, kpts=mf.kpts) # Unrestricted (spin polarized), periodic boundary conditions, full BZ sampling elif rdm1.ndim == 4 and hasattr(mf, "cell") and rdm1.shape[1] != 1: @@ -831,7 +893,6 @@ def _package_outputs( ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) ao_and_1deriv = np.asarray(ao_and_1deriv) ao = ao_and_1deriv[:, 0, :, :] - nao = ao.shape[2] grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order, kpts=mf.kpts) @@ -848,25 +909,15 @@ def _package_outputs( dm = mf.make_rdm1(mf.mo_coeff, mf.mo_occ) fock = np.stack([h1e, h1e], axis=0) + mf.get_veff(mf.mol, dm) - # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation - all_kpts = mf.kpts - nkpt = all_kpts.shape[0] - density_fitter = df.DF(mf.cell, kpts=all_kpts) - rep_tensor = np.empty(shape=(nkpt, nkpt, nao, nao, nao, nao), dtype=np.complex128) - for ikpt in range(nkpt): - for jkpt in range(nkpt): - k_quartet = np.array([all_kpts[ikpt], all_kpts[ikpt], all_kpts[jkpt], all_kpts[jkpt]]) - rep_tensor_kquartet =\ - density_fitter.get_eri(compact=False, kpts=k_quartet).reshape(nao, nao, nao, nao) - rep_tensor[ikpt, jkpt, :, :, :, :] = rep_tensor_kquartet kpt_info = kpt_info_from_pyscf(mf) + # Compute ERIs for all pairs of k-points. Needed for Coulomb energy calculation + rep_tensor = calc_eri_with_pyscf(mf, kpts=mf.kpts) # Restricted (non-spin polarized), periodic boundary conditions, gamma point only elif rdm1.ndim == 3 and hasattr(mf, "cell") and rdm1.shape[0] == 1: ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) ao_and_1deriv = np.asarray(ao_and_1deriv) ao = ao_and_1deriv[:, 0, :, :] - nao = ao.shape[2] grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order) # Collapse the redundant extra dimension from k-points: gamma only @@ -904,7 +955,7 @@ def _package_outputs( fock = np.squeeze(fock, axis=1) vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) - rep_tensor = df.DF(mf.cell).get_eri(compact=False).reshape(nao, nao, nao, nao) + rep_tensor = calc_eri_with_pyscf(mf) kpt_info = None # Unrestricted (spin polarized), periodic boundary conditions, gamma point only @@ -912,7 +963,6 @@ def _package_outputs( ao_and_1deriv = pbc_numint.eval_ao_kpts(mf.cell, grids.coords, kpts=mf.kpts, deriv=1) ao_and_1deriv = np.asarray(ao_and_1deriv) ao = ao_and_1deriv[:, 0, :, :] - nao = ao.shape[2] grad_ao = ao_and_1deriv[:, 1:4, :, :].transpose(0, 2, 3, 1) grad_n_ao = pbc_ao_grads(mf.cell, jnp.array(mf.grids.coords), order=grad_order) @@ -944,7 +994,7 @@ def _package_outputs( fock = np.squeeze(fock, axis=1) vj = np.squeeze(vj, axis=1) h1e = np.squeeze(h1e, axis=0) - rep_tensor = df.DF(mf.cell).get_ao_eri(compact=False).reshape(nao, nao, nao, nao) + rep_tensor = calc_eri_with_pyscf(mf) kpt_info = None else: diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 4ccfa0c..53c527c 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -112,8 +112,8 @@ class Solid: atom_index: Int[Array, "n_atom"] lattice_vectors: Float[Array, "3 3"] nuclear_pos: Float[Array, "n_atom 3"] - ao: Float[Array, "n_kpt n_flat_grid n_orbitals"] # ao = Crystal Atomic Orbitals in PBC case - grad_ao: Float[Array, "nkpt n_flat_grid n_orbitals 3"] + ao: Complex[Array, "n_kpt n_flat_grid n_orbitals"] # ao = Crystal Atomic Orbitals in PBC case + grad_ao: Complex[Array, "nkpt n_flat_grid n_orbitals 3"] grad_n_ao: PyTree rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] nuclear_repulsion: Scalar @@ -489,7 +489,7 @@ def assign_values(i, mo_occ): @typechecked @partial(jit, static_argnames="precision") def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], - ao: Float[Array, "n_flat_grid n_orbitals"], + ao: Complex[Array, "n_kpt n_flat_grid n_orbitals"], weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision: Precision = Precision.HIGHEST ) -> Float[Array, "n_flat_grid n_spin"]: @@ -499,8 +499,8 @@ def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], ---------- rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix. - ao : Float[Array, "n_flat_grid n_orbitals"] - Atomic orbitals. + ao : Complex[Array, "n_kpt n_flat_grid n_orbitals"] + Crystal atomic orbitals. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which together sum to 1. If we are working in the full 1BZ, weights are equal. If we are working in the @@ -514,7 +514,7 @@ def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], ------- Float[Array, "n_flat_grid n_spin"] """ - den = jnp.einsum("skab,ra,rb->rs", rdm1, ao, ao, precision=precision).real/weights.shape[0] + den = jnp.einsum("k,skab,kra,krb->rs", weights, rdm1, ao, ao, precision=precision).real # den = jnp.einsum("...kab,ra,rb->r...", rdm1, ao, ao, precision=precision) print(jnp.sum(den.imag)) jax.debug.print("imag remainder is {x}", x=jnp.sum(den.imag)) @@ -524,21 +524,21 @@ def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], @partial(jit, static_argnames="precision") def grad_density( rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], - ao: Float[Array, "n_flat_grid n_orbitals"], - grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], + ao: Complex[Array, "n_kpt n_flat_grid n_orbitals"], + grad_ao: Complex[Array, "n_kpt n_flat_grid n_orbitals 3"], weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision: Precision = Precision.HIGHEST ) -> Float[Array, "n_flat_grid n_spin 3"]: - r"""Compute the electronic density gradient using atomic orbitals. + r"""Compute the electronic density gradient using crystal atomic orbitals. Parameters ---------- rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix. - ao : Float[Array, "n_flat_grid n_orbitals"] - Atomic orbitals. - grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] - Gradients of atomic orbitals. + ao : Complex[Array, "n_kpt n_flat_grid n_orbitals"] + Crystal atomic orbitals. + grad_ao : Complex[Array, "n_kpt n_flat_grid n_orbitals 3"] + Gradients of crystal atomic orbitals. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which together sum to 1. If we are working in the full 1BZ, weights are equal. If we are working in the @@ -554,16 +554,16 @@ def grad_density( The density gradient: Float[Array, "n_flat_grid n_spin 3"] """ - return 2 * jnp.einsum("k,...kab,ra,rbj->r...j", weights, rdm1, ao, grad_ao, precision=precision).real + return 2 * jnp.einsum("k,...kab,kra,krbj->r...j", weights, rdm1, ao, grad_ao, precision=precision).real @jaxtyped @typechecked @partial(jit, static_argnames="precision") def lapl_density( rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], - ao: Float[Array, "n_flat_grid n_orbitals"], - grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], - grad_2_ao: Float[Array, "n_flat_grid n_orbitals 3"], + ao: Complex[Array, "n_kpt n_flat_grid n_orbitals"], + grad_ao: Complex[Array, "n_kpt n_flat_grid n_orbitals 3"], + grad_2_ao: Complex[Array, "n_kpt n_flat_grid n_orbitals 3"], weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision: Precision = Precision.HIGHEST, ) -> Float[Array, "n_flat_grid n_spin"]: @@ -573,12 +573,12 @@ def lapl_density( ---------- rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix. - ao : Float[Array, "b_flat_grid n_orbitals"] - Atomic orbitals. - grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] - Gradients of atomic orbitals. - grad_2_ao : Float[Array, "n_flat_grid n_orbitals 3"] - Vector of second derivatives of atomic orbitals. + ao : Complex[Array, "b_flat_grid n_orbitals"] + Crystal atomic orbitals. + grad_ao : Complex[Array, "n_flat_grid n_orbitals 3"] + Gradients of crystal atomic orbitals. + grad_2_ao : Complex[Array, "n_flat_grid n_orbitals 3"] + Vector of second derivatives of crystal atomic orbitals. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which together sum to 1. If we are working in the full 1BZ, weights are equal. If we are working in the @@ -593,26 +593,26 @@ def lapl_density( Float[Array, "n_flat_grid n_spin"] """ return (2 * jnp.einsum( - "k,...kab,raj,rbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision - ) + 2 * jnp.einsum("k,...kab,ra,rbi->r...", weights, rdm1, ao, grad_2_ao, precision=precision)).real + "k,...kab,kraj,krbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision + ) + 2 * jnp.einsum("k,...kab,kra,krbi->r...", weights, rdm1, ao, grad_2_ao, precision=precision)).real @jaxtyped @typechecked @partial(jit, static_argnames="precision") def kinetic_density( rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], - grad_ao: Float[Array, "n_flat_grid n_orbitals 3"], + grad_ao: Complex[Array, "n_kpt n_flat_grid n_orbitals 3"], weights: Float[Array, "n_kpts_or_n_ir_kpts"], precision: Precision = Precision.HIGHEST ) -> Float[Array, "n_flat_grid n_spin"]: - r""" Compute the kinetic energy density using atomic orbitals. + r""" Compute the kinetic energy density using crystal atomic orbitals. Parameters ---------- rdm1 : Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"] The 1-body reduced density matrix. - grad_ao : Float[Array, "n_flat_grid n_orbitals 3"] - Gradients of atomic orbitals. + grad_ao : Complex[Array, "n_kpt n_flat_grid n_orbitals 3"] + Gradients of crystal atomic orbitals. weights : Float[Array, "n_kpts_or_n_ir_kpts"] The weights for each k-point which together sum to 1. If we are working in the full 1BZ, weights are equal. If we are working in the @@ -628,7 +628,7 @@ def kinetic_density( The kinetic energy density: Float[Array, "n_flat_grid n_spin"] """ - return 0.5 * jnp.einsum("k,...kab,raj,rbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision).real + return 0.5 * jnp.einsum("k,...kab,kraj,krbj->r...", weights, rdm1, grad_ao, grad_ao, precision=precision).real @jaxtyped @typechecked diff --git a/grad_dft/train.py b/grad_dft/train.py index 2237ae1..e81680f 100644 --- a/grad_dft/train.py +++ b/grad_dft/train.py @@ -157,12 +157,6 @@ def predict(params: PyTree, atoms: Union[Molecule, Solid], *args) -> Tuple[Scala # auto-diffed xc gradient is divided by n_k=number of k-points. Undo this. fock = fock_noxc + (fock_xc*atoms.rdm1.shape[1]) - """Note: the summed difference between the fock matrix elements computed here and the fock - matrix computed directly by PySCF is correct to ~1e-16 for the Molecule - case but only matches PySCF to ~1e-9 for a Solid. This may not be cause for concern, - but I will leave this note here in the event that somebody is chasing a bug. - """ - # Improve stability by clipping and symmetrizing fock = abs_clip(fock, clip_cte) fock = 1 / 2 * (fock + fock.transpose(transpose_dims).conj()) From 1b02768cb2a4f3800fe7848028564e40c8acaca1 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 20 Nov 2023 19:46:42 -0500 Subject: [PATCH 27/36] Added some input handling --- grad_dft/interface/pyscf.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index a2e0285..2c2a3ce 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -112,6 +112,9 @@ def molecule_from_pyscf( chunk_size: Optional[Scalar] = jnp.int32(1024), grad_order: Optional[Scalar] = jnp.int32(2), ) -> Molecule: + if hasattr(mf, "kpts"): + if not np.array_equal(mf.kpts, np.array([[0.0, 0.0, 0.0]])): + raise RuntimeError("Input was periodic with BZ sampling beyond gamma-point only. Use solid_from_pyscf instead.") # mf, grids = _maybe_run_kernel(mf, grids) grid = grid_from_pyscf(mf.grids, dtype=dtype) @@ -209,6 +212,10 @@ def solid_from_pyscf( ) -> Solid: if np.array_equal(kmf.kpts, np.array([[0.0, 0.0, 0.0]])): raise RuntimeError("Use molecule_from_pyscf for Gamma point only calculations") + elif not hasattr(kmf, "cell"): + raise RuntimeError("Input was an isolated system. Use molecule_from_pyscf instead.") + + grid = grid_from_pyscf(kmf.grids, dtype=dtype) pyscf_dat = _package_outputs(kmf, kmf.grids, scf_iteration, grad_order) kpt_info = pyscf_dat[-1] @@ -736,7 +743,7 @@ def pbc_ao_grads(cell: Cell, coords: Array, order=2, kpts=None) -> Dict: i += 1 return result -def calc_eri_with_pyscf(mf, kpts=None) -> np.ndarray: +def calc_eri_with_pyscf(mf, kpts=np.zeros(3)) -> np.ndarray: r"""Calculate the ERIs using the method detected from the PySCF mean field object. Inputs @@ -766,9 +773,9 @@ def calc_eri_with_pyscf(mf, kpts=None) -> np.ndarray: density_fitter = GDF(mf.cell, kpts=kpts) # Calculate the Periodic ERI's. - if kpts is None: + if np.array_equal(kpts, np.zeros(3)): # Assume Gamma point only - eri_compressed = density_fitter.get_eri(kpts=kpts) + eri_compressed = density_fitter.get_eri(kpts=np.zeros(3)) eri = restore(1, eri_compressed, mf.cell.nao_nr()) else: # Loop over all k-pairs. This will be a fall back in the future. We will encourage users From dce443d2cf12f75296109aec52b67399eac74233 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Mon, 20 Nov 2023 23:20:55 -0500 Subject: [PATCH 28/36] minor scf refactoring --- grad_dft/evaluate.py | 109 +++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/grad_dft/evaluate.py b/grad_dft/evaluate.py index 502046d..f21dfe3 100644 --- a/grad_dft/evaluate.py +++ b/grad_dft/evaluate.py @@ -156,7 +156,7 @@ def simple_scf_loop( compute_energy = energy_predictor(functional, chunk_size=chunk_size, **kwargs) - def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *args) -> Molecule: + def simple_scf_iterator(params: PyTree, atoms: Union[Molecule, Solid], clip_cte = 1e-30, *args) -> Union[Molecule, Solid]: r""" Implements a scf loop for a Molecule and a functional implicitly defined compute_energy with parameters params @@ -164,15 +164,15 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a Parameters ---------- params: PyTree - molecule: Molecule + atoms: Molecule or Solid class *args: Arguments to be passed to compute_energy function Returns ------- - Molecule + Molecule or solid class with updated attributes """ - nelectron = molecule.atom_index.sum() - molecule.charge + nelectron = atoms.atom_index.sum() - atoms.charge # predicted_e, fock = compute_energy(params, molecule, *args) # fock = abs_clip(fock, clip_cte) @@ -181,21 +181,20 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a for cycle in range(cycles): # Convergence criterion is energy difference (default 1) kcal/mol and norm of gradient of orbitals < g_conv start_time = time.time() - # old_e = molecule.energy if cycle == 0: - mo_energy = molecule.mo_energy - mo_coeff = molecule.mo_coeff - fock = molecule.fock + mo_energy = atoms.mo_energy + mo_coeff = atoms.mo_coeff + fock = atoms.fock else: # Diagonalize Fock matrix - overlap = abs_clip(molecule.s1e, clip_cte) + overlap = abs_clip(atoms.s1e, clip_cte) mo_energy, mo_coeff = safe_fock_solver(fock, overlap) - molecule = molecule.replace(mo_coeff=mo_coeff) - molecule = molecule.replace(mo_energy=mo_energy) + atoms = atoms.replace(mo_coeff=mo_coeff) + atoms = atoms.replace(mo_energy=mo_energy) # Update the molecular occupation - mo_occ = molecule.get_occ() - molecule = molecule.replace(mo_occ=mo_occ) + mo_occ = atoms.get_occ() + atoms = atoms.replace(mo_occ=mo_occ) if verbose > 2: print( f"Cycle {cycle} took {time.time() - start_time:.1e} seconds to compute and diagonalize Fock matrix" @@ -203,25 +202,21 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a # Update the density matrix if cycle == 0: - old_rdm1 = molecule.make_rdm1() + old_rdm1 = atoms.make_rdm1() else: - rdm1 = (1 - mixing_factor)*old_rdm1 + mixing_factor*abs_clip(molecule.make_rdm1(), clip_cte) + rdm1 = (1 - mixing_factor)*old_rdm1 + mixing_factor*abs_clip(atoms.make_rdm1(), clip_cte) rdm1 = abs_clip(rdm1, clip_cte) - molecule = molecule.replace(rdm1=rdm1) + atoms = atoms.replace(rdm1=rdm1) old_rdm1 = rdm1 - - # computed_charge = jnp.einsum( - # "r,ra,rb,ksab->", molecule.grid.weights, molecule.ao, molecule.ao, molecule.rdm1 - # ) - computed_charge = jnp.einsum("r,rs->", molecule.grid.weights, molecule.density()) + computed_charge = jnp.einsum("r,rs->", atoms.grid.weights, atoms.density()) assert jnp.isclose( nelectron, computed_charge, atol=1e-3 ), "Total charge is not conserved. given electrons: %.3f, computed electrons: %.3f" % (nelectron, computed_charge) exc_start_time = time.time() - predicted_e, fock = compute_energy(params, molecule, *args) + predicted_e, fock = compute_energy(params, atoms, *args) fock = abs_clip(fock, clip_cte) exc_time = time.time() @@ -232,7 +227,7 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a ) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) + norm_gorb = jnp.linalg.norm(atoms.get_mo_grads()) if verbose > 1: print( @@ -248,10 +243,10 @@ def simple_scf_iterator(params: PyTree, molecule: Molecule, clip_cte = 1e-30, *a print( f"cycle: {cycle}, predicted energy: {predicted_e:.7e}, energy difference: {abs(predicted_e - old_e):.4e}, norm_gradient_orbitals: {norm_gorb:.2e}" ) - # Ensure molecule is fully updated - molecule = molecule.replace(fock=fock) - molecule = molecule.replace(energy=predicted_e) - return molecule + # Ensure atoms are fully updated + atoms = atoms.replace(fock=fock) + atoms = atoms.replace(energy=predicted_e) + return atoms return simple_scf_iterator @@ -277,25 +272,25 @@ def diff_simple_scf_loop(functional: Functional, cycles: int = 25, mixing_factor @jit def simple_scf_jitted_iterator( params: PyTree, - molecule: Molecule, + atoms: Union[Molecule, Solid], *args - ) -> Molecule: + ) -> Union[Molecule, Solid]: r""" Implements a scf loop intented for use in a jax.jit compiled function (training loop). If you are looking for a more flexible but not differentiable scf loop, see evaluate.py scf_loop. - It asks for a Molecule and a functional implicitly defined compute_energy with + It asks for a Molecule or Solid and a functional implicitly defined compute_energy with parameters params Parameters ---------- params: PyTree - molecule: Molecule + atoms: Molecule or Solid *args: Arguments to be passed to compute_energy function Returns ------- - molecule: Molecule + atoms: Molecule or Solid with updated attributes Notes: ------ @@ -306,50 +301,50 @@ def simple_scf_jitted_iterator( old_e = jnp.inf norm_gorb = jnp.inf - predicted_e, fock = compute_energy(params, molecule, *args) - molecule = molecule.replace(fock=fock) - molecule = molecule.replace(energy=predicted_e) + predicted_e, fock = compute_energy(params, atoms, *args) + atoms = atoms.replace(fock=fock) + atoms = atoms.replace(energy=predicted_e) - state = (molecule, predicted_e, old_e, norm_gorb) + state = (atoms, predicted_e, old_e, norm_gorb) def loop_body(cycle, state): old_state = state - molecule, predicted_e, old_e, norm_gorb = old_state + atoms, predicted_e, old_e, norm_gorb = old_state old_e = predicted_e - old_rdm1 = molecule.rdm1 - fock = molecule.fock + old_rdm1 = atoms.rdm1 + fock = atoms.fock # Diagonalize Fock matrix - mo_energy, mo_coeff = safe_fock_solver(fock, molecule.s1e) - molecule = molecule.replace(mo_coeff=mo_coeff) - molecule = molecule.replace(mo_energy=mo_energy) + mo_energy, mo_coeff = safe_fock_solver(fock, atoms.s1e) + atoms = atoms.replace(mo_coeff=mo_coeff) + atoms = atoms.replace(mo_energy=mo_energy) # Update the molecular occupation - mo_occ = molecule.get_occ() - molecule = molecule.replace(mo_occ=mo_occ) + mo_occ = atoms.get_occ() + atoms = atoms.replace(mo_occ=mo_occ) # Update the density matrix with linear mixing - unmixed_new_rdm1 = molecule.make_rdm1() + unmixed_new_rdm1 = atoms.make_rdm1() rdm1 = (1 - mixing_factor)*old_rdm1 + mixing_factor*unmixed_new_rdm1 - molecule = molecule.replace(rdm1=rdm1) + atoms = atoms.replace(rdm1=rdm1) # Compute the new energy and Fock matrix - predicted_e, fock = compute_energy(params, molecule, *args) - molecule = molecule.replace(fock=fock) + predicted_e, fock = compute_energy(params, atoms, *args) + atoms = atoms.replace(fock=fock) # Compute the norm of the gradient - norm_gorb = jnp.linalg.norm(molecule.get_mo_grads()) + norm_gorb = jnp.linalg.norm(atoms.get_mo_grads()) - state = (molecule, predicted_e, old_e, norm_gorb) + state = (atoms, predicted_e, old_e, norm_gorb) return state # Compute the scf loop final_state = fori_loop(0, cycles, body_fun=loop_body, init_val=state) - molecule, predicted_e, old_e, norm_gorb = final_state - molecule = molecule.replace(energy=predicted_e) - return molecule + atoms, predicted_e, old_e, norm_gorb = final_state + atoms = atoms.replace(energy=predicted_e) + return atoms return simple_scf_jitted_iterator @@ -401,7 +396,8 @@ def scf_iterator(params: PyTree, molecule: Molecule, *args) -> Molecule: ------- Molecule """ - + if isinstance(molecule, Solid): + raise NotImplementedError("Solids with full BZ zampling not yet supported. Use simple_scf_loop or diff_simple_scf_loop instead.") # Needed to be able to update the chi tensor mol = mol_from_Molecule(molecule) _, mf = process_mol( @@ -717,7 +713,8 @@ def neural_iterator( ------- molecule: Molecule """ - + if isinstance(molecule, Solid): + raise NotImplementedError("Solids with full BZ zampling not yet supported. Use simple_scf_loop instead.") old_e = jnp.inf cycle = 0 @@ -932,6 +929,8 @@ def diff_scf_loop(functional: Functional, cycles: int = 25, **kwargs) -> Callabl compute_energy = energy_predictor(functional, chunk_size=None, **kwargs) + @jaxtyped + @typechecked @jit def scf_jitted_iterator( params: PyTree, From 0ef698c4e7f18e1f98e596f2a05ced293412180a Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 22 Nov 2023 15:51:48 -0500 Subject: [PATCH 29/36] test restructure to add solids, sold training test added --- .github/workflows/install_and_test.yml | 12 +- grad_dft/evaluate.py | 10 +- grad_dft/interface/pyscf.py | 2 +- grad_dft/solid.py | 4 +- .../{ => molecules}/test_Harris.py | 0 .../test_functional_implementations.py | 0 .../{ => molecules}/test_non_xc_energy.py | 0 .../{ => molecules}/test_predict_B3LYP.py | 0 .../{ => molecules}/test_predict_B88.py | 0 .../{ => molecules}/test_predict_DM21.py | 0 .../{ => molecules}/test_training.py | 0 tests/integration/solids/test_training.py | 234 ++++++++++++++++++ 12 files changed, 248 insertions(+), 14 deletions(-) rename tests/integration/{ => molecules}/test_Harris.py (100%) rename tests/integration/{ => molecules}/test_functional_implementations.py (100%) rename tests/integration/{ => molecules}/test_non_xc_energy.py (100%) rename tests/integration/{ => molecules}/test_predict_B3LYP.py (100%) rename tests/integration/{ => molecules}/test_predict_B88.py (100%) rename tests/integration/{ => molecules}/test_predict_DM21.py (100%) rename tests/integration/{ => molecules}/test_training.py (100%) create mode 100644 tests/integration/solids/test_training.py diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index e2b7199..c257b39 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -36,9 +36,11 @@ jobs: pytest -v tests/unit/test_loss.py - name: Run integration tests run: | - pytest -v tests/integration/test_non_xc_energy.py - pytest -v tests/integration/test_functional_implementations.py - pytest -v tests/integration/test_Harris.py - pytest -v tests/integration/test_predict_B88.py - pytest -v tests/integration/test_training.py + pytest -v tests/integration/molecules/test_non_xc_energy.py + pytest -v tests/integration/molecules/test_functional_implementations.py + pytest -v tests/integration/molecules/test_Harris.py + pytest -v tests/integration/molecules/test_predict_B88.py + pytest -v tests/integration/molecules/test_training.py + pytest -v tests/integration/solids/test_training.py + diff --git a/grad_dft/evaluate.py b/grad_dft/evaluate.py index f21dfe3..92967d1 100644 --- a/grad_dft/evaluate.py +++ b/grad_dft/evaluate.py @@ -187,7 +187,7 @@ def simple_scf_iterator(params: PyTree, atoms: Union[Molecule, Solid], clip_cte fock = atoms.fock else: # Diagonalize Fock matrix - overlap = abs_clip(atoms.s1e, clip_cte) + overlap = atoms.s1e mo_energy, mo_coeff = safe_fock_solver(fock, overlap) atoms = atoms.replace(mo_coeff=mo_coeff) atoms = atoms.replace(mo_energy=mo_energy) @@ -204,12 +204,13 @@ def simple_scf_iterator(params: PyTree, atoms: Union[Molecule, Solid], clip_cte if cycle == 0: old_rdm1 = atoms.make_rdm1() else: - rdm1 = (1 - mixing_factor)*old_rdm1 + mixing_factor*abs_clip(atoms.make_rdm1(), clip_cte) - rdm1 = abs_clip(rdm1, clip_cte) + rdm1 = (1 - mixing_factor)*old_rdm1 + mixing_factor*atoms.make_rdm1() atoms = atoms.replace(rdm1=rdm1) old_rdm1 = rdm1 computed_charge = jnp.einsum("r,rs->", atoms.grid.weights, atoms.density()) + # This assertion was removed because the forward pass number of electrons is correct, but in backward pass, this assertion will fail. + # This doesn't mean there is an error though. Just because of batching in backwrd pass. assert jnp.isclose( nelectron, computed_charge, atol=1e-3 ), "Total charge is not conserved. given electrons: %.3f, computed electrons: %.3f" % (nelectron, computed_charge) @@ -217,8 +218,7 @@ def simple_scf_iterator(params: PyTree, atoms: Union[Molecule, Solid], clip_cte exc_start_time = time.time() predicted_e, fock = compute_energy(params, atoms, *args) - fock = abs_clip(fock, clip_cte) - + exc_time = time.time() if verbose > 2: diff --git a/grad_dft/interface/pyscf.py b/grad_dft/interface/pyscf.py index 2c2a3ce..387e683 100644 --- a/grad_dft/interface/pyscf.py +++ b/grad_dft/interface/pyscf.py @@ -111,7 +111,7 @@ def molecule_from_pyscf( scf_iteration: Scalar = jnp.int32(50), chunk_size: Optional[Scalar] = jnp.int32(1024), grad_order: Optional[Scalar] = jnp.int32(2), -) -> Molecule: +) -> Molecule: if hasattr(mf, "kpts"): if not np.array_equal(mf.kpts, np.array([[0.0, 0.0, 0.0]])): raise RuntimeError("Input was periodic with BZ sampling beyond gamma-point only. Use solid_from_pyscf instead.") diff --git a/grad_dft/solid.py b/grad_dft/solid.py index 53c527c..f6a3ea2 100644 --- a/grad_dft/solid.py +++ b/grad_dft/solid.py @@ -515,10 +515,8 @@ def density(rdm1: Complex[Array, "n_spin n_kpt n_orbitals n_orbitals"], Float[Array, "n_flat_grid n_spin"] """ den = jnp.einsum("k,skab,kra,krb->rs", weights, rdm1, ao, ao, precision=precision).real - # den = jnp.einsum("...kab,ra,rb->r...", rdm1, ao, ao, precision=precision) - print(jnp.sum(den.imag)) - jax.debug.print("imag remainder is {x}", x=jnp.sum(den.imag)) return den + @jaxtyped @typechecked @partial(jit, static_argnames="precision") diff --git a/tests/integration/test_Harris.py b/tests/integration/molecules/test_Harris.py similarity index 100% rename from tests/integration/test_Harris.py rename to tests/integration/molecules/test_Harris.py diff --git a/tests/integration/test_functional_implementations.py b/tests/integration/molecules/test_functional_implementations.py similarity index 100% rename from tests/integration/test_functional_implementations.py rename to tests/integration/molecules/test_functional_implementations.py diff --git a/tests/integration/test_non_xc_energy.py b/tests/integration/molecules/test_non_xc_energy.py similarity index 100% rename from tests/integration/test_non_xc_energy.py rename to tests/integration/molecules/test_non_xc_energy.py diff --git a/tests/integration/test_predict_B3LYP.py b/tests/integration/molecules/test_predict_B3LYP.py similarity index 100% rename from tests/integration/test_predict_B3LYP.py rename to tests/integration/molecules/test_predict_B3LYP.py diff --git a/tests/integration/test_predict_B88.py b/tests/integration/molecules/test_predict_B88.py similarity index 100% rename from tests/integration/test_predict_B88.py rename to tests/integration/molecules/test_predict_B88.py diff --git a/tests/integration/test_predict_DM21.py b/tests/integration/molecules/test_predict_DM21.py similarity index 100% rename from tests/integration/test_predict_DM21.py rename to tests/integration/molecules/test_predict_DM21.py diff --git a/tests/integration/test_training.py b/tests/integration/molecules/test_training.py similarity index 100% rename from tests/integration/test_training.py rename to tests/integration/molecules/test_training.py diff --git a/tests/integration/solids/test_training.py b/tests/integration/solids/test_training.py new file mode 100644 index 0000000..ace766a --- /dev/null +++ b/tests/integration/solids/test_training.py @@ -0,0 +1,234 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""The goal of this module is to test that the loss functions in ~/grad_dft/train.py are +trainable and minimizable given a simple neural functional and only two H Solid objects in +the training set. These tests do the same as in ~/tests/molecules/test_training.py but we are testing for Solids +instead. + +For SCF and non-SCF training, we should have: + + +(1) Loss function gradients free of NaN's + +(2) Decreased loss after 5 iterations of an optimizer + +""" + +from jax.random import PRNGKey +import jax.numpy as jnp +import numpy as np +from jax import grad +import pytest +from pyscf.pbc import gto, scf, cc, ci + +from grad_dft import ( + solid_from_pyscf, + mse_energy_loss, + mse_density_loss, + mse_energy_and_density_loss, + diff_simple_scf_loop, + simple_scf_loop, + non_scf_predictor, + Solid, + NeuralFunctional +) + +from jax.nn import sigmoid, gelu +from flax import linen as nn +from optax import adam, apply_updates +from jax import config, value_and_grad +config.update("jax_enable_x64", True) + +# Two H solid geometries. Small basis set +LAT_VEC = np.array( + [[3.6, 0.0, 0.0], + [0.0, 3.6, 0.0], + [0.0, 0.0, 3.6]] +) + +PYSCF_SOLS = [ + gto.M( + a = LAT_VEC, + atom = """H 0.0 0.0 0.0 + H 1.4 0.0 0.0""", + basis = 'sto-3g', + space_group_symmetry=False, + symmorphic=False, + ), + + gto.M( + a = LAT_VEC, + atom = """H 0.0 0.0 0. + H 1.4 0.0 0.0""", + basis = 'sto-3g', + space_group_symmetry=False, + symmorphic=False, + ), + +] + +SCF_ITERS = 5 + +# Truth values are decided to be from MP2 calculations. +TRUTH_ENERGIES = [] +TRUTH_DENSITIES = [] +SOLIDS = [] +KPTS = [2, 1, 1] + +for sol in PYSCF_SOLS: + kmf = scf.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf.xc = "LDA" + E_pyscf = kmf.kernel(max_cycle=SCF_ITERS) + solid = solid_from_pyscf(kmf) + SOLIDS.append(solid) + + khf = scf.KRHF(sol, kpts=sol.make_kpts(KPTS)) + khf = khf.run() + mp2 = khf.MP2().run() + mp2_rdm1 = np.asarray(mp2.make_rdm1()) + E_tr = mp2.e_tot + + # DFT calculations used for their grids to calculate MP2 densities + kmf_dft_dummy = scf.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf_dft_dummy.kernel(max_cycle=1) + grad_dft_sol_dummy = solid_from_pyscf(kmf_dft_dummy) + dft_kccsd_rdm1 = grad_dft_sol_dummy.replace(rdm1=jnp.asarray(mp2_rdm1)) + # Works because we use the same AOs for DFT and MP2 + den_tr = grad_dft_sol_dummy.density() + + TRUTH_ENERGIES.append(E_tr) + TRUTH_DENSITIES.append(den_tr) + +# Define a simple neural functional and its initial parameters + +def coefficient_inputs(solid: Solid, clip_cte: float = 1e-30, *_, **__): + rho = jnp.clip(solid.density(), a_min = clip_cte) + return jnp.concatenate((rho, ), axis = 1) + +def energy_densities(solid: Solid, clip_cte: float = 1e-30, *_, **__): + r"""Auxiliary function to generate the features of LSDA.""" + rho = solid.density() + # To avoid numerical issues in JAX we limit too small numbers. + rho = jnp.clip(rho, a_min = clip_cte) + # Now we can implement the LSDA exchange energy density + lda_e = -3/2 * (3/(4*jnp.pi)) ** (1/3) * (rho**(4/3)).sum(axis = 1, keepdims = True) + return lda_e + +out_features = 1 +def coefficients(instance, rhoinputs): + r""" + Instance is an instance of the class Functional or NeuralFunctional. + rhoinputs is the input to the neural network, in the form of an array. + localfeatures represents the potentials e_\theta(r). + + The output of this function is the energy density of the system. + """ + + x = nn.Dense(features=out_features)(rhoinputs) + x = nn.LayerNorm()(x) + x = gelu(x) + return sigmoid(x) + +NF = NeuralFunctional(coefficients, energy_densities, coefficient_inputs) +KEY = PRNGKey(42) +CINPUTS = coefficient_inputs(SOLIDS[0]) +PARAMS = NF.init(KEY, CINPUTS) + + +# Only linear mixing SCF and non SCF training implemented for Solid objects at present +TRAIN_RECIPES = [ + # Non-SCF training on the energy only + (mse_energy_loss, [PARAMS, non_scf_predictor(NF), SOLIDS, TRUTH_ENERGIES, True]), + + # Linear mixing SCF training on the energy only + (mse_energy_loss, [PARAMS, simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_ENERGIES, True]), + # Linear mixing SCF training on the density only + (mse_density_loss, [PARAMS, simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_DENSITIES, True]), + # Linear SCF training on energy and density + (mse_energy_and_density_loss, [PARAMS, simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_DENSITIES, TRUTH_ENERGIES, 1.0, 1.0, True]), + + # Jitted Linear mixing SCF training on the energy only + (mse_energy_loss, [PARAMS, diff_simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_ENERGIES, True]), + # Jitted Linear mixing SCF training on the density only + (mse_density_loss, [PARAMS, diff_simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_DENSITIES, True]), + # Jitted Linear SCF training on energy and density + (mse_energy_and_density_loss, [PARAMS, diff_simple_scf_loop(NF, cycles=SCF_ITERS), SOLIDS, TRUTH_DENSITIES, TRUTH_ENERGIES, 1.0, 1.0, True]), +] + + +@pytest.mark.parametrize("train_recipe", TRAIN_RECIPES) +def test_loss_functions(train_recipe: tuple) -> None: + r"""Same objectives as the unit test: test_loss.py but the predictors are now real DFT calculations + with Neural functionals. + + Args: + train_recipe (tuple): information regarding the loss, its arguments and the predictor. See TRAIN_RECIPES variable above. + """ + loss_func, loss_args = train_recipe + predictor_name = loss_args[1].__name__ + loss = loss_func(*loss_args) + # Pure loss test + assert not jnp.isnan( + loss + ).any(), f"Loss for loss function {loss_func.__name__} contains a NaN. It should not." + + assert ( + loss >= 0 + ), f"Loss for loss function {loss_func.__name__} is less than 0 which shouldn't be possible" + + # Gradient tests + grad_fn = grad(loss_func) + gradient = grad_fn(*loss_args) + assert not jnp.isnan( + gradient["params"]["Dense_0"]["bias"] + ).any(), f"Bias loss gradients for loss function {loss_func.__name__} and predictor {predictor_name} contains a NaN. It should not." + assert not jnp.isnan( + gradient["params"]["Dense_0"]["kernel"] + ).any(), f"Kernel loss gradients for loss function {loss_func.__name__} and predictor {predictor_name} contains a NaN. It should not." + +LR = 0.001 +MOMENTUM = 0.9 + +# and implement the optimization loop +N_EPOCHS = 5 + +@pytest.mark.parametrize("train_recipe", TRAIN_RECIPES) +def test_minimize(train_recipe: tuple) -> None: + r"""Check that the loss functions with different predictords are minimizable in 5 iterations. + + Args: + train_recipe (tuple):train_recipe (tuple): information regarding the loss, its arguments and the predictor. See TRAIN_RECIPES variable above. + """ + + loss_func, loss_args = train_recipe + predictor_name = loss_args[1].__name__ + + tr_params = NF.init(KEY, CINPUTS) + loss_args[0] = tr_params + + tx = adam(learning_rate=LR, b1=MOMENTUM) + opt_state = tx.init(PARAMS) + loss_and_grad = value_and_grad(loss_func) + cost_history = [] + for i in range(N_EPOCHS): + cost_value, grads = loss_and_grad(*loss_args) + # print(grads) + cost_history.append(cost_value) + updates, opt_state = tx.update(grads, opt_state, tr_params) + tr_params = apply_updates(tr_params, updates) + loss_args[0] = tr_params + assert ( + cost_history[-1] <= cost_history[0] + ), f"Training recipe for loss function {loss_func.__name__} and {predictor_name} did not reduce the cost in 5 iterations" \ No newline at end of file From 3c2c05deb4f194c356de108c594d256ac6dcd8a7 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 22 Nov 2023 20:21:51 -0500 Subject: [PATCH 30/36] New tutorial for BZ sampling and updated the gamma only notebook --- .../periodic_systems_bz_sampling_05.ipynb | 603 ++++++++++++++++++ ...eriodic_systems_gamma_point_only_04.ipynb} | 11 +- 2 files changed, 605 insertions(+), 9 deletions(-) create mode 100644 examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb rename examples/intermediate_notebooks/{periodic_systems_04.ipynb => periodic_systems_gamma_point_only_04.ipynb} (99%) diff --git a/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb new file mode 100644 index 0000000..e22aa0e --- /dev/null +++ b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb @@ -0,0 +1,603 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Periodic systems with k-point sampling in Grad DFT\n", + "\n", + "In this tutorial, you will learn how to train a simple neural functional for solids with full integration over the 1BZ. Calculations in this tutorial are certainly not converged with respect to k-point sampling or basis sets, so please consider this when adapting to your own calculations.\n", + "\n", + "## Perform solid-state calculations with PySCF\n", + "\n", + "PySCF implements DFT and some wavefunction methods in periodic boundary conditions with integration over the 1BZ. To begin, we need:\n", + "\n", + "(1) A DFT starting point to prime Grad DFT. We'll use the PBE functional.\n", + "\n", + "(2) Accurate training and validation data. We'll use the periodic MP2 solver implemented in PySCF.\n", + "\n", + "Our calculations will be run using Sodium Chloride (NaCl) in the rock salt structure.\n", + "\n", + "Let's import the modules required for the PySCF pre-computations." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/pyscf/dft/libxc.py:771: UserWarning: Since PySCF-2.3, B3LYP (and B3P86) are changed to the VWN-RPA variant, corresponding to the original definition by Stephens et al. (issue 1480) and the same as the B3LYP functional in Gaussian. To restore the VWN5 definition, you can put the setting \"B3LYP_WITH_VWN5 = True\" in pyscf_conf.py\n", + " warnings.warn('Since PySCF-2.3, B3LYP (and B3P86) are changed to the VWN-RPA variant, '\n" + ] + } + ], + "source": [ + "from pyscf.pbc import gto, scf, mp\n", + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we define the primitive cell for NaCl in the Rocksalt struture. This structural data was taken from [The Materials Project](https://next-gen.materialsproject.org/materials/mp-22862). \n", + "\n", + "We will train using the pristine geometry and validate using a slightly expanded cell." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING!\n", + " Very diffused basis functions are found in the basis set. They may lead to severe\n", + " linear dependence and numerical instability. You can set cell.exp_to_discard=0.1\n", + " to remove the diffused Gaussians whose exponents are less than 0.1.\n", + "\n", + "WARNING!\n", + " Very diffused basis functions are found in the basis set. They may lead to severe\n", + " linear dependence and numerical instability. You can set cell.exp_to_discard=0.1\n", + " to remove the diffused Gaussians whose exponents are less than 0.1.\n", + "\n" + ] + } + ], + "source": [ + "# Training geometry: pristine NaCl\n", + "\n", + "param = 5.272336\n", + "lat_vec = np.array(\n", + " [\n", + " [0.0, param, param],\n", + " [param, 0.0, param],\n", + " [param, param, 0.0]\n", + " ]\n", + ")\n", + "\n", + "cell_tr = gto.M(\n", + " a = lat_vec,\n", + " atom = \"\"\"Na 0.0 0.0 0.0\n", + " Cl %.5f %.5f %.5f\"\"\" % (param, param, param),\n", + " basis = '631g*',\n", + ")\n", + "cell_tr.exp_to_discard=0.1\n", + "\n", + "# Validation geometry: NaCl with a 5% larger lattice parameter\n", + "\n", + "param_strain = param*1.05\n", + "lat_vec_strain = np.array(\n", + " [\n", + " [0.0, param_strain, param_strain],\n", + " [param_strain, 0.0, param_strain],\n", + " [param_strain, param_strain, 0.0]\n", + " ]\n", + ")\n", + "cell_val = gto.M(\n", + " a = lat_vec_strain,\n", + " atom = \"\"\"Na 0.0 0.0 0.0 \n", + " Cl %.5f %.5f %.5f\"\"\" % (param_strain, param_strain, param_strain), # Na atom was displaced slightly.\n", + " basis = '631g*'\n", + ")\n", + "cell_val.exp_to_discard=0.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we get the DFT starting point to prime Grad DFT. We use PBE and a small number of k-points. We also use Gaussian density fitting for the electronic coulomb terms. [All other PBC density fitting approaches](https://pyscf.org/user/pbc/df.html) in PySCF are also compatible with Grad DFT." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "converged SCF energy = -622.178071472529\n", + "converged SCF energy = -622.168799570356\n" + ] + } + ], + "source": [ + "# Run training DFT starting point\n", + "kmf_tr = scf.KRKS(cell_tr, kpts=cell_tr.make_kpts([2,1,1])).density_fit()\n", + "kmf_tr.xc = \"PBE\"\n", + "kmf_tr.max_cycle = 10\n", + "kmf_tr = kmf_tr.run()\n", + "\n", + "# Run validation DFT starting point\n", + "kmf_val = scf.KRKS(cell_val, kpts=cell_val.make_kpts([2,1,1])).density_fit()\n", + "kmf_val.xc = \"PBE\"\n", + "kmf_val.max_cycle = 10\n", + "kmf_val = kmf_val.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can perform the MP2 calculations which will be used for truth values in training." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "converged SCF energy = -621.379366154699\n", + "E(KMP2) = -621.513466780104 E_corr = -0.134100625404806\n", + "E(SCS-KMP2) = -621.509253400475 E_corr = -0.129887245775369\n", + "converged SCF energy = -621.368407929544\n", + "E(KMP2) = -621.502082008919 E_corr = -0.133674079374634\n", + "E(SCS-KMP2) = -621.497876632087 E_corr = -0.129468702543138\n" + ] + } + ], + "source": [ + "# Make one training data-point and one validation using MP2\n", + "\n", + "# Training\n", + "khf_tr = scf.KRHF(cell_tr, kpts=cell_tr.make_kpts([2,1,1])).density_fit()\n", + "khf_tr = khf_tr.run()\n", + "mp2_tr = mp.KRMP2(khf_tr)\n", + "mp2_tr = mp2_tr.run()\n", + "E_tr = mp2_tr.e_tot\n", + "\n", + "\n", + "# Validation\n", + "khf_val = scf.KRHF(cell_val, kpts=cell_val.make_kpts([2,1,1])).density_fit()\n", + "khf_val = khf_val.run()\n", + "mp2_val = mp.KRMP2(khf_val)\n", + "mp2_val = mp2_val.run()\n", + "E_val = mp2_val.e_tot\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Loading into Grad DFT\n", + "\n", + "The DFT starting points from PySCF can be loaded into Grad DFT with the convenience function `solid_from_pyscf`. This mirrors `molecule_from_pyscf` but now many arrays have an additional k-points dimension." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/k8/81tnbcsx5lv94kjrw7pj513r0000gq/T/ipykernel_87611/2351384841.py:1: DeprecationWarning: Accessing jax.config via the jax.config submodule is deprecated.\n", + " from jax.config import config\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From /Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/tensorflow/python/compat/v2_compat.py:108: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "non-resource variables are not supported in the long term\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From /Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/tensorflow/python/compat/v2_compat.py:108: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "non-resource variables are not supported in the long term\n" + ] + } + ], + "source": [ + "from jax.config import config\n", + "config.update(\"jax_enable_x64\", True)\n", + "import grad_dft as gd\n", + "\n", + "gd_sol_tr = gd.solid_from_pyscf(kmf_tr)\n", + "gd_sol_val = gd.solid_from_pyscf(kmf_val)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Make a simple neural functional\n", + "\n", + "Like in `~/examples/intermediate_notebooks/training_methods_03.ipynb`, we create a scaled down version of the net used the original Grad DFT reference article" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from grad_dft.functional import canonicalize_inputs, dm21_coefficient_inputs, dm21_densities\n", + "from jax.nn import gelu\n", + "from functools import partial\n", + "import jax.numpy as jnp\n", + "from jax.random import PRNGKey\n", + "\n", + "seed = 1984 # Random seed used throughout this notebok for reproducibility reasons.\n", + "key = PRNGKey(seed)\n", + "\n", + "squash_offset = 1e-4\n", + "layer_widths = [6] * 2\n", + "\n", + "out_features = 2\n", + "sigmoid_scale_factor = 2.0\n", + "activation = gelu\n", + "\n", + "def nn_coefficients(instance, rhoinputs, *_, **__):\n", + " x = canonicalize_inputs(rhoinputs) # Making sure dimensions are correct\n", + " # Initial layer: log -> dense -> tanh\n", + " x = jnp.log(jnp.abs(x) + squash_offset) # squash_offset = 1e-4\n", + " instance.sow(\"intermediates\", \"log\", x)\n", + " x = instance.dense(features=layer_widths[0])(x) # features = 256\n", + " instance.sow(\"intermediates\", \"initial_dense\", x)\n", + " x = jnp.tanh(x)\n", + " instance.sow(\"intermediates\", \"norm\", x)\n", + " # 2 Residual blocks with 6-features dense layer and layer norm\n", + " for features, i in zip(layer_widths, range(len(layer_widths))): # layer_widths = [256]*6\n", + " res = x\n", + " x = instance.dense(features=features)(x)\n", + " instance.sow(\"intermediates\", \"residual_dense_\" + str(i), x)\n", + " x = x + res # nn.Dense + Residual connection\n", + " instance.sow(\"intermediates\", \"residual_residual_\" + str(i), x)\n", + " x = instance.layer_norm()(x) # + res # nn.LayerNorm\n", + " instance.sow(\"intermediates\", \"residual_layernorm_\" + str(i), x)\n", + " x = activation(x) # activation = jax.nn.gelu\n", + " instance.sow(\"intermediates\", \"residual_elu_\" + str(i), x)\n", + " return instance.head(x, out_features, sigmoid_scale_factor)\n", + " \n", + "functional = gd.NeuralFunctional(\n", + " coefficients=nn_coefficients,\n", + " coefficient_inputs=dm21_coefficient_inputs,\n", + " energy_densities=partial(dm21_densities, functional_type=\"GGA\"),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Non self-consistent training using the energy only\n", + "\n", + "Once again, borrowing from `~/examples/intermediate_notebooks/training_methods_03.ipynb`, we define a training and validation regime" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from optax import adam, apply_updates\n", + "from tqdm import tqdm\n", + "from jax import value_and_grad\n", + "\n", + "def train_neural_functional(train_recipe: tuple, validate_recipe: tuple) -> None:\n", + " r\"\"\"Minimize a Grad DFT loss function using 50 epochs of the Adam optimizer.\n", + "\n", + " Args:\n", + " train_recipe (tuple):train_recipe (tuple): information regarding the loss, its arguments and the predictor.\n", + " validate_recipe (tuple):train_recipe (tuple): the same information as train_recipe, but for the validation calculation.\n", + " Returns:\n", + " tuple: the training and validation loss history over the number of training epochs\n", + " \"\"\"\n", + " \n", + " loss_func, loss_args = train_recipe\n", + " val_func, val_args = validate_recipe\n", + " \n", + " tr_params = functional.init(key, dm21_coefficient_inputs(loss_args[2][0]))\n", + " loss_args[0] = tr_params\n", + " val_args[0] = tr_params\n", + " \n", + " tx = adam(learning_rate=0.01, b1=0.9)\n", + " opt_state = tx.init(tr_params)\n", + " loss_and_grad = value_and_grad(loss_func)\n", + " tr_loss_history = []\n", + " val_loss_history = []\n", + " for i in tqdm(range(10), desc=\"Training epoch\"):\n", + " tr_loss_value, grads = loss_and_grad(*loss_args)\n", + " val_loss_value = val_func(*val_args)\n", + " tr_loss_history.append(tr_loss_value)\n", + " val_loss_history.append(val_loss_value)\n", + " updates, opt_state = tx.update(grads, opt_state, tr_params)\n", + " tr_params = apply_updates(tr_params, updates)\n", + " loss_args[0] = tr_params\n", + " val_args[0] = tr_params\n", + " if (i + 1) % 5 == 0:\n", + " print(f\"At epoch {i+1} training loss = {tr_loss_value}, validation loss = {val_loss_value}\")\n", + " return tr_loss_history, val_loss_history\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "non_sc_en_train_recipe = (\n", + " gd.mse_energy_loss, \n", + " [None, gd.non_scf_predictor(functional), [gd_sol_tr], [E_tr], True]\n", + ")\n", + "non_sc_en_validate_recipe = (\n", + " gd.mse_energy_loss, \n", + " [None, gd.non_scf_predictor(functional), [gd_sol_val], [E_val], True]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can perform the non-self consistent training." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Training epoch: 50%|█████ | 5/10 [00:37<00:34, 6.95s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "At epoch 5 training loss = 0.0001737845401721004, validation loss = 0.0001757714747113059\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Training epoch: 100%|██████████| 10/10 [01:10<00:00, 7.01s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "At epoch 10 training loss = 0.00018310176622873998, validation loss = 0.00018106695140976598\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# Begin training\n", + "tr_loss_his_non_sc_en, val_loss_his_non_sc_en = train_neural_functional(non_sc_en_train_recipe, non_sc_en_validate_recipe)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and check out the loss as a function of epochs" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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AG+88QaTJk3CZDJdch8nT54sUObn53fJU2xPPPEEkydPZsCAAfzpT3/i2LFjPP/889xwww189913HuufOnWKPn36cNdddzFgwADeeecd/v73v9O2bVv3cblcLm6//Xa++uorRo8eTcuWLdm2bRvPPvssP/30EytWrPDY/6effsrbb7/NmDFjqFmzJo0aNeLQoUPceOONmEwmJk6cSFBQEP/6178KnIocMmQIb7zxBp988onHNVwpKSl8+umnTJ069ZLv2+8ZhsHtt9/O2rVrGTlyJDExMXzyySdMmDCBQ4cOuT/zP/zwA7feeivt2rVjxowZ2Gw2du/ezddff+3e1ssvv8wDDzzAPffcw7hx48jKyuL7779n/fr1hSbFUkEZIpXY4sWLDcDYuHGj8csvvxh+fn7GAw884F7evXt3o3Xr1u7XW7ZsMQDjT3/6k8d2HnroIQMwPv30U3dZw4YNDcD44osv3GVHjx41bDab8eCDD14ytlWrVhkWi8WwWCxGbGys8fDDDxuffPKJkZOT41Hvb3/7mwEY3333XYmOubDHpfTr189o2LBhgfK1a9cagNGkSRMjIyPDY1lWVpbhdDo9yvbs2WPYbDZjxowZHmWAsXjxYnfZsGHDDMCjnmEYxtVXX2106NDBowwwpk6d6n49depUAzD++Mc/etS78847jRo1arhfb9q0yQCM8ePHe9QbPnx4gW3m76d79+4F3oML/f6zNX/+fCMkJMT93vTv39+48cYbDcPI+5z069fPvV5GRobRvHlzAzAaNmxoDB8+3HjllVeM1NTUAvvIP8bCHs2bN79ofHv37jUsFovxxBNPeJRv27bN8PPz8yjv3r27ARhvvPGGuyw7O9uIjIw07r77bnfZv//9b8NsNhtffvmlxzYXLlxoAMbXX3/tLgMMs9ls/PDDDx51x44da5hMJo/P84kTJ4zq1asbgLFnzx7DMAzD6XQa9erVMwYOHOix/pw5cwyTyWT8+uuvFz3+YcOGeXyWV6xYYQDG448/7lHvnnvuMUwmk7F7927DMAzj2WefNQDj2LFjRW77jjvu8Pi7IZWTTrFJldGkSROGDBnCokWLOHLkSKF1PvroIwASEhI8yh988EEAPvzwQ4/yVq1acf3117tf16pVi+bNm/Prr79eMp5evXqRnJzM7bffztatW3nqqaeIi4ujbt26rFy50l0vLS0NgJCQkGIc5W8WLFhAUlKSx+NyDRs2jICAAI8ym83mvg7J6XRy4sQJ92mJzZs3F2u7f/7znz1eX3/99cV6D4ta98SJE+73Lf+0zl//+lePer+/CP73DMModu9RvgEDBpCZmckHH3zA2bNn+eCDD4rsSQgICGD9+vVMmDAByBsNN3LkSKKiohg7dmyBU1UA7777boG2XLx48UVjeu+993C5XAwYMIDjx4+7H5GRkURHR7N27VqP+sHBwfzhD39wv/b396dTp04e7bB8+XJatmxJixYtPLZ50003ARTYZvfu3WnVqpVHWWJiIrGxscTExLjLqlevzn333edRz2w2c99997Fy5UrOnj3rLn/rrbfo0qVLgQEIl/LRRx9hsVh44IEHPMoffPBBDMPg448/Bn678P2///0vLper0G2Fh4dz8OBBNm7cWKIYpGJRgiRVyqRJk8jNzS3yWqR9+/ZhNptp1qyZR3lkZCTh4eHs27fPo7xBgwYFtlGtWjVOnToF5CUMKSkpHo/fX4R77bXX8t5773Hq1Ck2bNjAxIkTOXv2LPfccw8//vgjgPualN9/SRRHp06d6Nmzp8fjchX2peRyuXj22WeJjo7GZrNRs2ZNatWqxffff8+ZM2cuuU273U6tWrU8yn7/Hl7KhW1QrVo1APf6+W16YewXtvHlqFWrFj179mTJkiW89957OJ1O7rnnniLrh4WF8dRTT7F371727t3LK6+8QvPmzZk/fz4zZ84sUP+GG24o0JaxsbEXjennn3/GMAyio6OpVauWx2PHjh0FBgLUq1evwOm+C9vh559/5ocffiiwvauuugooOLigsM/Lvn37Cn3vCysbOnQomZmZ7lPbu3btYtOmTSU+3Zy/3zp16hT4R6Nly5bu5QADBw6ka9eu/OlPfyIiIoJBgwbx9ttveyRLf//73wkODqZTp05ER0dz//33e5yCk8pB1yBJldKkSRP+8Ic/sGjRooveE6g414VA3gXShTHOX/R54MCBAl8Sa9eupUePHh5l/v7+XHvttVx77bVcddVVjBgxguXLlzN16lRatGgB5N0z6ff/dXvDhb1HAP/4xz+YPHkyf/zjH5k5cybVq1fHbDYzfvz4Iv8D/72i3sPiulQbXCn33nsvo0aNIiUlhVtuuaXYQ/AbNmzIH//4R+68806aNGnCW2+9xeOPP37Z8bhcLkwmEx9//HGh79GF15cV5310uVy0bduWOXPmFFq3fv36Hq8L+7yURKtWrejQoQNvvvkmQ4cO5c0338Tf358BAwZc1nYvJiAggC+++IK1a9fy4YcfkpiYyLJly7jppptYtWoVFouFli1bsmvXLj744AMSExN59913eeGFF5gyZQrTp08vt9jkylKCJFXOpEmTePPNNz0u4s3XsGFDXC4XP//8s/s/S4DU1FROnz7tvsC2uCIjIwuc2mrfvv1F18kfmp9/GvCWW27BYrHw5ptvluo/55IobmL4e++88w433ngjr7zyikf56dOnfWJoen6b7tmzh+joaHf57t27y3Q/d955J//3f//HN998w7Jly0q8frVq1WjatCnbt28vk3iaNm2KYRg0btzY3cNTFtvcunUrN998c6k+K5DXHoW990W1x9ChQ0lISODIkSMsWbKEfv36uXsJS7rf1atXc/bsWY9epJ07d7qX5zObzdx8883cfPPNzJkzh3/84x889thjrF271t0TGxQUxMCBAxk4cCA5OTncddddPPHEE0ycOFG3MqgkdIpNqpymTZvyhz/8gZdeeqnAnYj79u0LUOBu0vn/MRc18qkodru9wKmR/D/ua9euLbSXI/86qPxhzPXr12fUqFGsWrWq0BtdulwuZs+ezcGDB0sUW2GCgoKKdVrs9ywWS4HjWL58eaF3LveGuLg4AF544QWP8qJuGlrSYf75goODefHFF5k2bRq33XZbkfW2bt1aYHQh5J3i+fHHH0s1fL0wd911FxaLhenTpxdoH8MwOHHiRIm3OWDAAA4dOsTLL79cYFlmZibp6emX3EZcXBzJycls2bLFXXby5EneeuutQusPHjwYk8nEuHHj+PXXXz2ukyqJvn374nQ6mT9/vkf5s88+i8lkco/UK2zEYH7Pbf71YRe+d/7+/rRq1QrDMAq9LYFUTOpBkirpscce49///je7du3yGI7fvn17hg0bxqJFizh9+jTdu3dnw4YNvP7668THx3PjjTeWWQxjx44lIyODO++8kxYtWpCTk8O6detYtmyZewqRfLNnz+aXX37hgQce4L333uPWW2+lWrVq7N+/n+XLl7Nz504GDRp02TF16NCBZcuWkZCQwLXXXktwcPBFv+wBbr31VmbMmMGIESPo0qUL27Zt46233qJJkyaXHU9Z6NChA3fffTdz587lxIkT7mH+P/30E1Cw16ykw/x/b9iwYZesk5SUxNSpU7n99tu57rrrCA4O5tdff+XVV18lOzu70Pnm3nnnnULvpN2rVy8iIiIK3U/Tpk15/PHHmThxInv37iU+Pp6QkBD27NnD+++/z+jRo3nooYdKdHxDhgzh7bff5s9//jNr166la9euOJ1Odu7cydtvv80nn3xyyZuTPvzww7z55pv06tWLsWPHuof5N2jQgJMnTxZoj1q1atGnTx+WL19OeHh4if9JyXfbbbdx44038thjj7F3717at2/PqlWr+O9//8v48eNp2rQpkHcH+i+++IJ+/frRsGFDjh49ygsvvEC9evXcd0vv3bs3kZGRdO3alYiICHbs2MH8+fPp169fiQdTiA/zzuA5kSvj90OxL5Q/xPzC4boOh8OYPn260bhxY8NqtRr169c3Jk6caGRlZXnUu3D4dr7u3bsXa5j4xx9/bPzxj380WrRoYQQHBxv+/v5Gs2bNjLFjxxY65Ds3N9f417/+ZVx//fVGWFiYYbVajYYNGxojRozwGDJ9sWO+lHPnzhn33nuvER4e7h6Gbhi/DfNfvnx5gXWysrKMBx980IiKijICAgKMrl27GsnJyQXeh6KG+QcFBRXYZv7w9t+jiGH+Fw7Hzj/+/OHihmEY6enpxv33329Ur17dCA4ONuLj441du3YZgPHPf/6zwH5KOsz/Yi78nPz666/GlClTjOuuu86oXbu24efnZ9SqVcvo16+fx20kfn+MRT3Wrl17yTjfffddo1u3bkZQUJARFBRktGjRwrj//vuNXbt2uetceLuLfBcOlTcMw8jJyTGefPJJo3Xr1obNZjOqVatmdOjQwZg+fbpx5swZdz3AuP/++wuN6bvvvjOuv/56w2azGfXq1TNmzZplzJs3zwCMlJSUAvXffvttAzBGjx59yeO9WOxnz541/va3vxl16tQxrFarER0dbTz99NOGy+Vy11mzZo1xxx13GHXq1DH8/f2NOnXqGIMHDzZ++uknd52XXnrJuOGGG4waNWoYNpvNaNq0qTFhwgSP45eKz2QYV/hKRhERH7Blyxauvvpq3nzzzQJDzOXKGz9+PC+99BLnzp0rcMH4f//7X+Lj4/niiy88bqshUp50DZKIVHqZmZkFyubOnYvZbOaGG27wQkRV24XtceLECf7973/TrVu3QkfTvfzyyzRp0qTAhMAi5UnXIIlIpffUU0+xadMmbrzxRvz8/Pj444/5+OOPGT16dIGh6VL+YmNj6dGjBy1btiQ1NZVXXnmFtLQ0Jk+e7FFv6dKlfP/993z44Yc899xzpR45J1IaOsUmIpVeUlIS06dP58cff+TcuXM0aNCAIUOG8Nhjj+Hnp/8Tr7RHH32Ud955h4MHD2IymbjmmmuYOnVqgZuZmkwmgoODGThwIAsXLlRbyRWlBElERETkAroGSUREROQCSpBERERELqATuqXkcrk4fPgwISEhunBQRESkgjAMg7Nnz1KnTh3M5qL7iZQgldLhw4c1+kVERKSCOnDgAPXq1StyuRKkUsq/nfyBAwcIDQ0ts+06HA5WrVpF7969sVqtZbZdKT21iW9Re/gWtYdvUXtcWlpaGvXr17/ktDBKkEop/7RaaGhomSdIgYGBhIaG6sPtI9QmvkXt4VvUHr5F7VF8l7o8Rhdpi4iIiFxACZKIiIjIBZQgiYiIiFzA69cgLViwgKeffpqUlBTat2/P888/T6dOnYqsv3z5ciZPnszevXuJjo7mySefpG/fvu7l7733HgsXLmTTpk2cPHmS7777jpiYmEK3ZRgGffv2JTExkffff5/4+PgyPjoRESkup9OJw+HwdhgVmsPhwM/Pj6ysLJxOp7fD8Qqr1VropMcl5dUEadmyZSQkJLBw4UI6d+7M3LlziYuLY9euXdSuXbtA/XXr1jF48GBmzZrFrbfeypIlS4iPj2fz5s20adMGgPT0dLp168aAAQMYNWrURfc/d+5c3cNIRMTLDMMgJSWF06dPezuUCs8wDCIjIzlw4ECV/n4LDw8nMjLyst4DryZIc+bMYdSoUYwYMQKAhQsX8uGHH/Lqq6/yyCOPFKj/3HPP0adPHyZMmADAzJkzSUpKYv78+SxcuBCAIUOGALB3796L7nvLli3Mnj2bb7/9lqioqDI8KhERKYn85Kh27doEBgZW6S/2y+VyuTh37hzBwcEXvQliZWUYBhkZGRw9ehTgsr7fvZYg5eTksGnTJiZOnOguM5vN9OzZk+Tk5ELXSU5OJiEhwaMsLi6OFStWlGjfGRkZ3HvvvSxYsIDIyMhirZOdnU12drb7dVpaGpDXnVmWXcL521I3s+9Qm/gWtYdvudz2cDqdnDp1ilq1alGtWrWyDK1KMgyDnJwcbDZblU00bTYbLpeLY8eOUa1atQKn24r7WfVagnT8+HGcTicREREe5REREezcubPQdVJSUgqtn5KSUqJ9/+1vf6NLly7ccccdxV5n1qxZTJ8+vUD5qlWrCAwMLNH+iyMpKanMtymXR23iW9QevqW07eHn50dkZCQul8v9j6dcvrNnz3o7BK9yuVxkZmayZs0acnNzPZZlZGQUaxtev0j7Slu5ciWffvop3333XYnWmzhxokfvVf6dOHv37l3mN4pMSkqiV69eusmXj1Cb+Ba1h2+53PbIysriwIEDhISEYLfbyyHCqiV/nrGqPk9oVlYWAQEB3HDDDQU+V8VNxL2WINWsWROLxUJqaqpHeWpqapGnvSIjI0tUvzCffvopv/zyC+Hh4R7ld999N9dffz2fffZZoevZbDZsNluBcqvVWi5/pMtru1J6ahPfovbwLaVtD6fTiclkwmw2V8lrZsqay+UCcL+nVZXZbMZkMhX6uSzu59Rr756/vz8dOnRgzZo17jKXy8WaNWuIjY0tdJ3Y2FiP+pDXrVtU/cI88sgjfP/992zZssX9AHj22WdZvHhxyQ9ERESkDDRq1Ii5c+cWu/5nn32GyWQq99F/r732WoFOharAq6fYEhISGDZsGB07dqRTp07MnTuX9PR096i2oUOHUrduXWbNmgXAuHHj6N69O7Nnz6Zfv34sXbqUb7/9lkWLFrm3efLkSfbv38/hw4cB2LVrF5DX+/T7x4UaNGhA48aNy/uQRUSkgrvUqaupU6cybdq0Em9348aNBAUFFbt+ly5dOHLkCGFhYSXel1yaVxOkgQMHcuzYMaZMmUJKSgoxMTEkJia6L8Tev3+/Rxdhly5dWLJkCZMmTeLRRx8lOjqaFStWuO+BBHnXGOUnWACDBg0CSv+BvdJycl0cyYCzWblU1+kDERGfc+TIEffzZcuWMWXKFPc/4wDBwcHu54Zh4HQ68fO79NdtrVq1ShSHv79/iS4xkZLx+gnKMWPGsG/fPrKzs1m/fj2dO3d2L/vss8947bXXPOr379+fXbt2kZ2dzfbt2z3uog0wfPhwDMMo8LhYcmQYhs/cRfud5yfQ/MfZ7Nj8hbdDERGRQvz+bERYWBgmk8n9eufOnYSEhPDxxx/ToUMHbDYbX331Fb/88gt33HEHERERBAcHc+2117J69WqP7V54is1kMvGvf/2LO++8k8DAQKKjo1m5cqV7+YWn2F577TWqV6/OmjVraN26NcHBwfTp08cjocvNzeWBBx4gPDycGjVq8Pe//51hw4aV+DvwxRdfpGnTpvj7+9O8eXP+/e9/u5flf+c2aNAAm81GnTp1eOCBB9zLX3jhBaKjo7Hb7URERHDPPfeUaN9XitcTJPF0LTu40bKV7AMlG2UnIlJZGIZBRk7uFX8YhlFmx/DII4/wz3/+kx07dtCuXTvOnTtH3759WbNmDd999x19+vThtttuY//+/RfdzvTp0xkwYADff/89ffv25b777uPkyZNF1s/IyGD+/Pm8/vrrfPHFF+zfv5+HHnrIvfzJJ5/krbfeYvHixXz99dekpaWV+F6C77//PuPGjePBBx9k+/bt/N///R8jRoxg7dq1ALz77rs8++yzvPTSS/z888+sWLGCtm3bAvDtt9/ywAMPMGPGDHbt2kViYiI33HBDifZ/pVS5Yf6+LqtaNGRswHx816Uri4hUQpkOJ62mfHLF9/vjjDgC/cvma3HGjBn06tXL/bp69eq0b9/e/XrmzJm8//77rFy5kjFjxhS5neHDhzN48GAA/vGPfzBv3jw2bNhAnz59Cq3vcDiYM2cO7du3x2w2M2bMGGbMmOFe/vzzzzNx4kTuvPNOAObPn89HH31UomN75plnGD58OH/961+BvOuJv/nmG5555hluvPFG9u/fT2RkJD179sRqtdKgQQP3HKv79+8nKCiIW2+9lZCQEBo2bMjVV19dov1fKepB8jHWiBYAhJ371cuRiIhIaXXs2NHj9blz53jooYdo2bIl4eHhBAcHs2PHjkv2ILVr1879PCgoiNDQUPc0GoUJDAz0GHAUFRXlrn/mzBlSU1M9JoS3WCx06NChRMe2Y8cOunbt6lHWtWtXduzYAeRdCpOZmUmTJk0YNWoU77//vvtmjb169aJhw4Y0adKEIUOG8NZbbxX7xo1XmnqQfEx4w3awGeo69uF0GVjMVfdGXyJSNQVYLfw4I84r+y0rF45Ge+ihh0hKSuKZZ56hWbNmBAQEcM8995CTk3PR7Vx4zx6TyeS+11Fx65flqcPiqF+/Prt27WL16tUkJSXx17/+laeffprPP/+ckJAQNm/ezGeffcaqVauYMmUK06ZNY+PGjT53KwH1IPmYWo3zztPWNp3i8JHDXo5GROTKM5lMBPr7XfFHed55+uuvv2b48OHceeedtG3blsjIyEtOql7WwsLCiIiIYOPGje4yp9PJ5s2bS7Sdli1b8vXXX3uUff3117Rq1cr9OiAggNtuu4158+bx2WefkZyczLZt24C86WV69uzJU089xffff8/evXv59NNPL+PIyod6kHyMJSCUFGoQyQmO/LKV+nXrejskERG5TNHR0bz33nvcdtttmEwmJk+efNGeoPIyduxYZs2aRbNmzWjRogXPP/88p06dKlFyOGHCBAYMGMDVV19Nz549+d///sd7773nHpX32muv4XQ66dy5M4GBgbz55psEBATQsGFDPvjgA3799VduuOEGqlWrxkcffYTL5aJ58+bldcilph4kH3TEUgeA9IPbvRyJiIiUhTlz5lCtWjW6dOnCbbfdRlxcHNdcc80Vj+Pvf/87gwcPZujQocTGxhIcHExcXFyJ5sGLj4/nueee45lnnqF169a89NJLLF68mB49egAQHh7Oyy+/TNeuXWnXrh2rV6/mf//7HzVq1CA8PJz33nuPm266iZYtW7Jw4UL+85//0Lp163I64tIzGVf65GQlkZaWRlhYGGfOnCnzyWq/mDOEmzM/5vNq99B93Ctltm0pHYfDwUcffUTfvn0195cPUHv4lsttj6ysLPbs2UPjxo01WW0ZcLlcpKWlERoaWqy52FwuFy1btmTAgAHMnDnzCkR4ZVzsc1Xc72+dYvNBGQF1IBNCzv3i7VBERKQS2bdvH6tWraJ79+5kZ2czf/589uzZw7333uvt0HyOTrH5IFdI3nVHdXP24nKpg09ERMqG2Wzmtdde49prr6Vr165s27aN1atX07JlS2+H5nPUg+SDzKF5CVKE6RT7U47QoE4dL0ckIiKVQf369QuMQJPCqQfJB7n8AjhmqglA6u6tXo5GRESk6lGC5KOOBeTdCfXcwW1ejkRERKTqUYLko7LCmwFgPv6TlyMRERGpepQg+Si/iLwL5kLO7vZyJCIiIlWPEiQfFd6gDQB1cvZpJJuIiMgVpgTJR9VqnDeDc6TpJIdSUrwcjYiISNWiBMlH+QWF/zaS7Zct3g1GRETKXI8ePRg/frz7daNGjZg7d+5F1zGZTKxYseKy911W27mYadOmERMTU677KE9KkHzY8fyRbAd+8HIkIiKS77bbbqNPnz6FLvvyyy8xmUx8//33Jd7uxo0b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Fx07duQf//gHAFdffTXbt29n4cKFSpC85O233+att95iyZIltG7dmi1btjB+/Hjq1KmjNiklJUg+ombNmlgsFlJTUz3KU1NTiYyM9FJUMmbMGD744AO++OIL6tWr5+1wqqxNmzZx9OhRrrnmGneZ0+nkiy++YP78+WRnZ2OxWLwYYdUSFRVFq1atPMpatmzJu+++66WIZMKECTzyyCMMGjQIgLZt27Jv3z5mzZqlBKmUdA2Sj/D396dDhw6sWbPGXeZyuVizZg2xsbFejKxqMgyDMWPG8P777/Ppp5/SuHFjb4dUpd18881s27aNLVu2uB8dO3bkvvvuY8uWLUqOrrCuXbsWuO3FTz/9RMOGDb0UkWRkZGA2e36lWywWXC6XlyKq+NSD5EMSEhIYNmwYHTt2pFOnTsydO5f09HRGjBjh7dCqnPvvv58lS5bw3//+l5CQEFJSUgAICwsjICDAy9FVPSEhIQWu/woKCqJGjRq6LswL/va3v9GlSxf+8Y9/MGDAADZs2MCiRYtYtGiRt0Orsm677TaeeOIJGjRoQOvWrfnuu++YM2cOf/zjH70dWoWlYf4+Zv78+Tz99NOkpKQQExPDvHnz6Ny5s7fDqnJMJlOh5YsXL2b48OFXNhgpVI8ePTTM34s++OADJk6cyM8//0zjxo1JSEhg1KhR3g6ryjp79iyTJ0/m/fff5+jRo9SpU4fBgwczZcoU/P39vR1ehaQESUREROQCugZJRERE5AJKkEREREQuoARJRERE5AJKkEREREQuoARJRERE5AJKkEREREQuoARJRERE5AJKkERESslkMrFixQpvhyEi5UAJkohUSMOHD8dkMhV49OnTx9uhiUgloLnYRKTC6tOnD4sXL/Yos9lsXopGRCoT9SCJSIVls9mIjIz0eFSrVg3IO/314osvcssttxAQEECTJk145513PNbftm0bN910EwEBAdSoUYPRo0dz7tw5jzqvvvoqrVu3xmazERUVxZgxYzyWHz9+nDvvvJPAwECio6NZuXKle9mpU6e47777qFWrFgEBAURHRxdI6ETENylBEpFKa/Lkydx9991s3bqV++67j0GDBrFjxw4A0tPTiYuLo1q1amzcuJHly5ezevVqjwToxRdf5P7772f06NFs27aNlStX0qxZM499TJ8+nQEDBvD999/Tt29f7rvvPk6ePOne/48//sjHH3/Mjh07ePHFF6lZs+aVewNEpPQMEZEKaNiwYYbFYjGCgoI8Hk888YRhGIYBGH/+85891uncubPxl7/8xTAMw1i0aJFRrVo149y5c+7lH374oWE2m42UlBTDMAyjTp06xmOPPVZkDIAxadIk9+tz584ZgPHxxx8bhmEYt912mzFixIiyOWARuaJ0DZKIVFg33ngjL774okdZ9erV3c9jY2M9lsXGxrJlyxYAduzYQfv27QkKCnIv79q1Ky6Xi127dmEymTh8+DA333zzRWNo166d+3lQUBChoaEcPXoUgL/85S/cfffdbN68md69exMfH0+XLl1KdawicmUpQRKRCisoKKjAKa+yEhAQUKx6VqvV47XJZMLlcgFwyy23sG/fPj766COSkpK4+eabuf/++3nmmWfKPF4RKVu6BklEKq1vvvmmwOuWLVsC0LJlS7Zu3Up6erp7+ddff43ZbKZ58+aEhITQqFEj1qxZc1kx1KpVi2HDhvHmm28yd+5cFi1adFnbE5ErQz1IIlJhZWdnk5KS4lHm5+fnvhB6+fLldOzYkW7duvHWW2+xYcMGXnnlFQDuu+8+pk6dyrBhw5g2bRrHjh1j7NixDBkyhIiICACmTZvGn//8Z2rXrs0tt9zC2bNn+frrrxk7dmyx4psyZQodOnSgdevWZGdn88EHH7gTNBHxbUqQRKTCSkxMJCoqyqOsefPm7Ny5E8gbYbZ06VL++te/EhUVxX/+8x9atWoFQGBgIJ988gnjxo3j2muvJTAwkLvvvps5c+a4tzVs2DCysrJ49tlneeihh6hZsyb33HNPsePz9/dn4sSJ7N27l4CAAK6//nqWLl1aBkcuIuXNZBiG4e0gRETKmslk4v333yc+Pt7boYhIBaRrkEREREQuoARJRERE5AK6BklEKiVdPSAil0M9SCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIX+H/Bv1kU0tRRTgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.plot(tr_loss_his_non_sc_en, label=\"Training loss\")\n", + "plt.plot(val_loss_his_non_sc_en, label=\"Validation loss\")\n", + "plt.ylabel(\"Loss\")\n", + "plt.xlabel(\"Epochs\")\n", + "plt.title(\"Non-SCF training: MSE energy loss\")\n", + "plt.grid()\n", + "plt.legend()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Self-consistent training using the energy only\n", + "\n", + "Training can also be performed in self consistent mode. Solids are presently supported in the linear mixing code: `gd.diff_simple_scf_loop`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "sc_en_train_recipe = (\n", + " gd.mse_energy_loss, \n", + " [None, gd.diff_simple_scf_loop(functional, cycles=5), [gd_sol_tr], [E_tr], True]\n", + ")\n", + "sc_en_validate_recipe = (\n", + " gd.mse_energy_loss, \n", + " [None, gd.diff_simple_scf_loop(functional, cycles=5), [gd_sol_val], [E_val], True]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Training epoch: 50%|█████ | 5/10 [04:05<03:57, 47.47s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "At epoch 5 training loss = 0.00016916189677703596, validation loss = 0.0001707407536255283\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Training epoch: 100%|██████████| 10/10 [07:59<00:00, 47.91s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "At epoch 10 training loss = 0.00017956670686227404, validation loss = 0.00017311377171407244\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "# Begin training\n", + "tr_loss_his_sc_en, val_loss_his_sc_en = train_neural_functional(sc_en_train_recipe, sc_en_validate_recipe)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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mMOVnJzMF198weTJky/7uV3IMAxuv/12Vq9ezfDhw2nfvj2ff/4548aN4/Dhw+7v/E8//cStt95K27ZtmTZtGjabjb179/Ltt9+623rttdd46KGHuOeeexgzZgyZmZn8+OOPrFu3rsCkWARDRIpsxYoVhsViMSwWixETE2M8+uijxueff25kZ2d71Pv73/9uAMamTZuK1O7ChQsNoMDX5fTr18+oX79+vvLVq1cbgNGoUSMjPT3dY1tmZqbhdDo9yvbt22fYbDZj2rRpHmWAsXDhQnfZkCFDDMCjnmEYxjXXXGN06NDBowwwJk+e7H4/efJkAzD+9Kc/edS78847jerVq7vfb9iwwQCMsWPHetQbOnRovjbzjtOjR498n8HF8j7n9evXG/PmzTNCQkLcn03//v2NG2+80TAMw6hfv77Rr18/937p6elGs2bNDMCoX7++MXToUOP11183UlJS8h0j7xwLejVr1uyS8e3fv9+wWCzG008/7VG+detWw8/Pz6O8R48eBmC8/fbb7rKsrCwjIiLCuPvuu91l//73vw2z2Wx8/fXXHm0uWLDAAIxvv/3WXQYYZrPZ+Omnnzzqjh492jCZTB7f599++82oVq2aARj79u0zDMMwnE6nUadOHWPgwIEe+8+ePdswmUzGL7/8csnzHzJkiMd3eenSpQZgPPXUUx717rnnHsNkMhl79+41DMMwnn/+eQMwjh8/Xmjbd9xxh9GqVatLHl/kQrrEJlIMvXr1Iikpidtvv50tW7bw7LPPEhsbS+3atVm2bJm7XmpqKgAhISHFan/+/PkkJiZ6vK7UkCFDCAgI8Ciz2WzueUhOp5PffvvNfVli48aNRWr3L3/5i8f76667jl9++aXE+/7222/uzy3vss7f/vY3j3oXToK/kGEYRR49yjNgwAAyMjL45JNPOHv2LJ988kmhIwkBAQGsW7eOcePGAbmr4YYPH05kZCSjR4/Od6kK4MMPP8zXlwsXLrxkTB999BEul4sBAwZw4sQJ9ysiIoLo6GhWr17tUT84OJg//vGP7vf+/v507tzZox+WLFlCixYtaN68uUebN910E0C+Nnv06EHLli09yhISEoiJiaF9+/busmrVqnH//fd71DObzdx///0sW7aMs2fPusvfffddunbtmm8BwuUsX74ci8XCQw895FH+8MMPYxgGn332GfD7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gOnTp1+FCK+OS32vivr7W5fYfEx0rWDWGxpBEhGR0nfgwAFWrFhBjx49yMrKYt68eezbt4/77rvP26H5HF1i8zFNawWzx6id++b4LtAAn4iIlBKz2cybb75Jp06d6NatG1u3bmXlypW0aNHC26H5HI0g+ZjoWkEcMMJxGBasjjQ48ytUqevtsEREpAKoW7duvhVoUjCNIPmY6sE2bH4W9hkRuQXHdcNIERGRq00Jkg+KDOSCy2w7vBuMiIhIJaQEyQdFBBjs1URtERERr1GC5IMiAg12u/ISJF1iExERudqUIPmgyABDK9lERES8SAmSD4oIhP1GBDmGGbJS4exRb4ckIiJSqShB8kHBVggJyl3uD2gekohIBXTDDTcwduxY9/sGDRowZ86cS+5jMplYunTpFR+7tNq5lClTptC+ffsyPUZZUoLko6JrBbHH0DwkERFfc9ttt9GnT58Ct3399deYTCZ+/PHHYre7fv16Ro4ceaXheSgsSTl69Ci33HJLqR6rolGC5KOiPe6orREkERFfMXz4cBITE/n111/zbVu4cCEdO3akbdu2xW63Zs2aBAYGlkaIlxUREYHNZrsqxyqvlCD5qCa1gtnjumCitoiI+IRbb72VmjVr8uabb3qUnzt3jiVLljB8+HB+++03Bg0aRO3atQkMDKRNmzb85z//uWS7F19i27NnD9dffz12u52WLVuSmJiYb5/HHnuMpk2bEhgYSKNGjZg0aRIOhwOAN998k6lTp7JlyxZMJhMmk8kd88WX2LZu3cpNN91EQEAA1atXZ+TIkZw7d869fejQocTFxTFz5kwiIyOpXr06Dz74oPtYReFyuZg2bRp16tTBZrPRvn17EhIS3Nuzs7MZNWoUkZGR2O126tevz4wZMwAwDIMpU6ZQr149bDYbUVFRPPTQQ0U+dknoUSM+qml4MIvzRpCO7chdyWYyeTcoEZGrwTDAkX71j2sNLNK/s35+fgwePJg333yTJ598EtP5fZYsWYLT6WTQoEGcO3eODh068NhjjxEaGsqnn37KAw88QOPGjencufNlj+FyubjrrrsIDw9n3bp1nDlzxmO+Up6QkBDefPNNoqKi2Lp1KyNGjMBqtTJx4kQGDhzItm3bSEhIYOXKlQCEhYXlayMtLY3Y2FhiYmJYv349x44d489//jOjRo3ySAJXr15NZGQkq1ev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UmkdPnyYP/7xj1SvXp2AgADatGnDDz/84O2wKi2n08nEiRNp2LAhAQEBNG7cmOnTp1/2eWNSOCVIPmTx4sXEx8czefJkNm7cSLt27YiNjeXYsWPeDq3S+fLLL3nwwQf57rvvSExMxOFw0Lt3b9LS0rwdWqW3fv16XnnlFdq2bevtUCqtU6dO0a1bN6xWK5999hnbt29n1qxZVK1a1duhVVrPPPMML7/8MvPmzWPHjh0888wzPPvss7z44oveDq3c0jJ/H9KlSxc6derEvHnzgNznvdWtW5fRo0fz+OOPezm6yu348ePUqlWLL7/8kuuvv97b4VRa586d49prr+Wll17iqaeeon379syZM8fbYVU6jz/+ON9++y1ff/21t0OR82699VbCw8N5/fXX3WV33303AQEBvPPOO16MrPzSCJKPyM7OZsOGDfTs2dNdZjab6dmzJ0lJSV6MTADOnDkDQLVq1bwcSeX24IMP0q9fP4+/J3L1LVu2jI4dO9K/f39q1arFNddcw2uvvebtsCq1rl27smrVKnbv3g3Ali1b+Oabb7jlllu8HFn5pYfV+ogTJ07gdDoJDw/3KA8PD2fnzp1eikogdyRv7NixdOvWjdatW3s7nErrvffeY+PGjaxfv97boVR6v/zyCy+//DLx8fE88cQTrF+/noceegh/f3+GDBni7fAqpccff5zU1FSaN2+OxWLB6XTy9NNPc//993s7tHJLCZLIZTz44INs27aNb775xtuhVFqHDh1izJgxJCYmYrfbvR1OpedyuejYsSP/+Mc/ALjmmmvYtm0bCxYsUILkJe+//z7vvvsuixYtolWrVmzevJmxY8cSFRWlPikhJUg+okaNGlgsFlJSUjzKU1JSiIiI8FJUMmrUKD755BO++uor6tSp4+1wKq0NGzZw7Ngxrr32WneZ0+nkq6++Yt68eWRlZWGxWLwYYeUSGRlJy5YtPcpatGjBhx9+6KWIZNy4cTz++OPce++9ALRp04YDBw4wY8YMJUglpDlIPsLf358OHTqwatUqd5nL5WLVqlXExMR4MbLKyTAMRo0axccff8wXX3xBw4YNvR1SpXbzzTezdetWNm/e7H517NiR+++/n82bNys5usq6deuW77YXu3fvpn79+l6KSNLT0zGbPX+lWywWXC6XlyIq/zSC5EPi4+MZMmQIHTt2pHPnzsyZM4e0tDSGDRvm7dAqnQcffJBFixbx3//+l5CQEJKTkwEICwsjICDAy9FVPiEhIfnmfwUFBVG9enXNC/OCv//973Tt2pV//OMfDBgwgO+//55XX32VV1991duhVVq33XYbTz/9NPXq1aNVq1Zs2rSJ2bNn86c//cnboZVbWubvY+bNm8dzzz1HcnIy7du3Z+7cuXTp0sXbYVU6JpOpwPKFCxcydOjQqxuMFOiGG27QMn8v+uSTTxg/fjx79uyhYcOGxMfHM2LECG+HVWmdPXuWiRMn8vHHH3Ps2DGioqIYNGgQkyZNwt/f39vhlUtKkEREREQuojlIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiUkImk4mlS5d6OwwRKQNKkESkXBo6dCgmkynfq0+fPt4OTUQqAD2LTUTKrT59+rBw4UKPMpvN5qVoRKQi0QiSiJRbNpuNiIgIj1fVqlWB3MtfL7/8MrfccgsBAQE0atSIDz74wGP/rVu3ctNNNxEQEED16tUZOXIk586d86jzxhtv0KpVK2w2G5GRkYwaNcpj+4kTJ7jzzjsJDAwkOjqaZcuWubedOnWK+++/n5o1axIQEEB0dHS+hE5EfJMSJBGpsCZOnMjdd9/Nli1buP/++7n33nvZsWMHAGlpacTGxlK1alXWr1/PkiVLWLlypUcC9PLLL/Pggw8ycuRItm7dyrJly2jSpInHMaZOncqAAQP48ccf6du3L/fffz8nT550H3/79u189tln7Nixg5dffpkaNWpcvQ9ARErOEBEph4YMGWJYLBYjKCjI4/X0008bhmEYgPGXv/zFY58uXboYf/3rXw3DMIxXX33VqFq1qnHu3Dn39k8//dQwm81GcnKyYRiGERUVZTz55JOFxgAYEyZMcL8/d+6cARifffaZYRiGcdtttxnDhg0rnRMWkatKc5BEpNy68cYbefnllz3KqlWr5v5zTEyMx7aYmBg2b94MwI4dO2jXrh1BQUHu7d26dcPlcrFr1y5MJhNHjhzh5ptvvmQMbdu2df85KCiI0NBQjh07BsBf//pX7r77bjZu3Ejv3r2Ji4uja9euJTpXEbm6lCCJSLkVFBSU75JXaQkICChSPavV6vHeZDLhcrkAuOWWWzhw4ADLly8nMTGRm2++mQcffJCZM2eWerwiUro0B0lEKqzvvvsu3/sWLVoA0KJFC7Zs2UJaWpp7+7fffovZbKZZs2aEhITQoEEDVq1adUUx1KxZkyFDhvDOO+8wZ84cXn311StqT0SuDo0giUi5lZWVRXJyskeZn5+feyL0kiVL6NixI927d+fdd9/l+++/5/XXXwfg/vvvZ/LkyQwZMoQpU6Zw/PhxRo8ezQMPPEB4eDgAU6ZM4S9/+Qu1atXilltu4ezZs3z77beMHj26SPFNmjSJDh060KpVK7Kysvjkk0/cCZqI+DYlSCJSbiUkJBAZGelR1qxZM3bu3AnkrjB77733+Nvf/kZkZCT/+c9/aNmyJQCBgYF8/vnnjBkzhk6dOhEYGMjdd9/N7Nmz3W0NGTKEzMxMnn/+eR555BFq1KjBPffcU+T4/P39GT9+PPv37ycgIIDrrruO9957rxTOXETKmskwDMPbQYiIlDaTycTHH39MXFyct0MRkXJIc5BERERELqIESUREROQimoMkIhWSZg+IyJXQCJKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRf4ftkgqIWPHjGcAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.plot(tr_loss_his_sc_en, label=\"Training loss\")\n", + "plt.plot(val_loss_his_sc_en, label=\"Validation loss\")\n", + "plt.ylabel(\"Loss\")\n", + "plt.xlabel(\"Epochs\")\n", + "plt.title(\"SCF training: MSE energy loss\")\n", + "plt.grid()\n", + "plt.legend()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "nan_check", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/intermediate_notebooks/periodic_systems_04.ipynb b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb similarity index 99% rename from examples/intermediate_notebooks/periodic_systems_04.ipynb rename to examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb index 1f47403..99b9f27 100644 --- a/examples/intermediate_notebooks/periodic_systems_04.ipynb +++ b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb @@ -6,9 +6,9 @@ "source": [ "# Periodic systems in Grad DFT\n", "\n", - "In this tutorial, you will learn how to train a simple neural functional for solids. Presently, we only support periodic calculations where Brillouin Zone (BZ) samping is performed at the $\\Gamma$-point. This converges the electronic structure only at the large supercell limit. We won't work with large supercells in this tutorial, so for accurate results, please consider this.\n", + "In this tutorial, you will learn how to train a simple neural functional for solids. Birllouin Zone (BZ) samping is performed at the $\\Gamma$-point. This converges the electronic structure only at the large supercell limit. We won't work with large supercells in this tutorial, so for accurate results, please consider this.\n", "\n", - "Full BZ sampling will be coming soon.\n", + "Full BZ sampling is discussed in `~examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb`,\n", "\n", "## Perform solid-state calculations with PySCF\n", "\n", @@ -495,13 +495,6 @@ "plt.grid()\n", "plt.legend()" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "and that's all there is! Remember, full BZ sampling is coming soon!" - ] } ], "metadata": { From 27d817c4ae9117b37617c32d46d77acb711e9fa6 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 22 Nov 2023 22:46:13 -0500 Subject: [PATCH 31/36] non xc energy test for solid hydrogen --- .github/workflows/install_and_test.yml | 1 + .../integration/solids/test_non_xc_energy.py | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 tests/integration/solids/test_non_xc_energy.py diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index c257b39..1fa5dbe 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -42,5 +42,6 @@ jobs: pytest -v tests/integration/molecules/test_predict_B88.py pytest -v tests/integration/molecules/test_training.py pytest -v tests/integration/solids/test_training.py + pytest -v tests/integration/solids/test_non_xc_energy.py diff --git a/tests/integration/solids/test_non_xc_energy.py b/tests/integration/solids/test_non_xc_energy.py new file mode 100644 index 0000000..4dff83e --- /dev/null +++ b/tests/integration/solids/test_non_xc_energy.py @@ -0,0 +1,111 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""The goal of this module is to test that the implementation of the total +energy is correct in Grad-DFT (for solids) ignoring the exchange and correlation functional. +We do so by comparing the energy volume curve of [ficticious] solid Hydrogren to the energy +calculated by PySCF. +""" + +from grad_dft import solid_from_pyscf + +import numpy as np + +from pyscf.pbc import gto, dft + +from jax import config + +import pytest + +config.update("jax_enable_x64", True) + +# Bond lengths in Angstroms. Taken from https://cccbdb.nist.gov/diatomicexpbondx.asp. +# This is for the molecule obviously, but we will use it as the solid lattice constant. +H2_EXP_BOND_LENGTH = 1.3984 + +SCF_ITERS = 200 +NUM_POINTS_CURVE = 10 +LAT_PARAM_FRAC_CHANGE = 0.1 +ERR_TOL = 1e-8 +KPTS = [2, 1, 1] + +H2_LAT_VECS = [ + np.array( + [ + [p, 0.0, 0.0], + [0.0, p, 0.0], + [0.0, 0.0, p] + ] + ) for p in np.linspace( + 2 * (1 - LAT_PARAM_FRAC_CHANGE) * H2_EXP_BOND_LENGTH, + 2 * (1 + LAT_PARAM_FRAC_CHANGE) * H2_EXP_BOND_LENGTH, + NUM_POINTS_CURVE, + ) +] + +H2_GEOMS = [ + """ + H 0.0 0.0 0.0 + H %.5f 0.0 0.0 + """ + % (bl) + for bl in np.linspace( + (1 - LAT_PARAM_FRAC_CHANGE) * H2_EXP_BOND_LENGTH, + (1 + LAT_PARAM_FRAC_CHANGE) * H2_EXP_BOND_LENGTH, + NUM_POINTS_CURVE, + ) +] + +H2_TRAJ = [ + gto.M( + a = lat_vec, + atom=geom, + basis="sto-3g", + ) + for geom, lat_vec in zip(H2_GEOMS, H2_LAT_VECS) +] + + + +def solid_and_energies(geom) -> tuple[float, float]: + r"""Calculate the total energy of crystal geometry with PySCF and Grad-DFT with no XC component in the electronic energy + + Args: + geom (gto.M): The periodicic gaussian orbital object from PySCF. Contains atomic positions, basis set and lattice vectors + Returns: + tuple[float, float]: the energy predicts by PySCF and Grad-DFT + """ + kmf = dft.KRKS(geom, kpts=geom.make_kpts(KPTS)) + kmf.xc = "0.00*LDA" # quick way of having no XC energy in PySCF + E_pyscf = kmf.kernel(max_cycle=SCF_ITERS) + sol = solid_from_pyscf(kmf) + E_gdft = sol.nonXC() + return E_pyscf, E_gdft + + +@pytest.mark.parametrize( + "geom", + H2_TRAJ, +) +def test_diatomic_molecule_energy(geom) -> None: + """Compare the total energies as a function of solid lattice parameter predicted by PySCF and Grad-DFT with no XC component in the electronic energy + + Args: + geom (gto.M): The periodicic gaussian orbital object from PySCF. Contains atomic positions, basis set and lattice vectors + """ + E_pyscf, E_gdft = solid_and_energies(geom) + tot_energy_error = np.abs(E_pyscf - E_gdft) + assert ( + tot_energy_error < ERR_TOL + ), f"Total energy difference exceeds threshold: {tot_energy_error}" From dafd90bf2e16ba18cc2c9e618107687a4094fbf2 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 22 Nov 2023 23:16:50 -0500 Subject: [PATCH 32/36] LDA and GGA functionals now tested for Solids --- .github/workflows/install_and_test.yml | 1 + .../solids/test_functional_implementations.py | 146 ++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 tests/integration/solids/test_functional_implementations.py diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index 1fa5dbe..37c0c22 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -43,5 +43,6 @@ jobs: pytest -v tests/integration/molecules/test_training.py pytest -v tests/integration/solids/test_training.py pytest -v tests/integration/solids/test_non_xc_energy.py + pytest -v tests/integration/solids/test_functional_implementations.py diff --git a/tests/integration/solids/test_functional_implementations.py b/tests/integration/solids/test_functional_implementations.py new file mode 100644 index 0000000..8d26662 --- /dev/null +++ b/tests/integration/solids/test_functional_implementations.py @@ -0,0 +1,146 @@ +# Copyright 2023 Xanadu Quantum Technologies Inc. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from flax.core import freeze +from jax import numpy as jnp +import pytest +from grad_dft import ( + solid_from_pyscf, + energy_predictor, # A class, needs to be instanciated! + B88, LSDA, VWN, PW92 +) +from grad_dft.utils.types import Hartree2kcalmol +import numpy as np + + +# This file aims to test, given some electronic density, whether our +# implementation of popular functionals closely matches libxc (pyscf default). + +# These tests are specifically for solids. We test only LDAs and GGGas here. + +# again, this only works on startup! +from jax import config +config.update("jax_enable_x64", True) + +# First we define a molecule: +from pyscf.pbc import gto, dft + +PARAMS = freeze({"params": {}}) +DIFF_TOL = 1e-3 # in KCal/Mol so is quite small +KPTS = [2, 1, 1] + +# Look at ficticious solid Hydrogen and Lithium + +# Bond lengths in Angstroms. Taken from https://cccbdb.nist.gov/diatomicexpbondx.asp. +# This is for the molecule obviously, but we will use it as the solid lattice constant. +H2_EXP_BOND_LENGTH = 1.3984 +LI2_EXP_BOND_LENGTH = 5.0512 + +LAT_VEC_H = 2 * np.array( + [ + [H2_EXP_BOND_LENGTH, 0.0, 0.0], + [0.0, H2_EXP_BOND_LENGTH, 0.0], + [0.0, 0.0, H2_EXP_BOND_LENGTH] + ] +) + +LAT_VEC_LI = 2 * np.array( + [ + [LI2_EXP_BOND_LENGTH, 0.0, 0.0], + [0.0, LI2_EXP_BOND_LENGTH, 0.0], + [0.0, 0.0, LI2_EXP_BOND_LENGTH] + ] +) + +GEOM_H = "H 0.0 0.0 0.0; H %.5f 0.0 0.0" % (H2_EXP_BOND_LENGTH) +GEOM_LI = "H 0.0 0.0 0.0; H %.5f 0.0 0.0" % (H2_EXP_BOND_LENGTH) + +sols = [ + gto.M( + a = LAT_VEC_H, + atom=GEOM_H, + basis="sto-3g", + ), + gto.M( + a = LAT_VEC_LI, + atom=GEOM_LI, + basis="sto-3g", + ) +] + +#### LSDA #### +@pytest.mark.parametrize("sol", sols) +def test_lda(sol): + kmf = dft.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf.xc = "LDA" # LDA is the same as LDA_X. + ground_truth_energy = kmf.kernel() + + gd_sol = solid_from_pyscf(kmf) + compute_energy = energy_predictor(LSDA) + predicted_e, fock = compute_energy(PARAMS, gd_sol) + + lsdadiff = (ground_truth_energy - predicted_e) * Hartree2kcalmol + + assert not jnp.isnan(fock).any() + assert jnp.allclose(lsdadiff, 0, atol=DIFF_TOL) + +##### B88 #### +@pytest.mark.parametrize("sol", sols) +def test_b88(sol): + kmf = dft.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf.xc = "B88" + ground_truth_energy = kmf.kernel() + + gd_sol = solid_from_pyscf(kmf) + compute_energy = energy_predictor(B88) + predicted_e, fock = compute_energy(PARAMS, gd_sol) + + b88diff = (ground_truth_energy - predicted_e) * Hartree2kcalmol + + assert not jnp.isnan(fock).any() + assert jnp.allclose(b88diff, 0, atol=DIFF_TOL) + + +##### VWN #### +@pytest.mark.parametrize("sol", sols) +def test_vwn(sol): + kmf = dft.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf.xc = "LDA_C_VWN" + ground_truth_energy = kmf.kernel() + + gd_sol = solid_from_pyscf(kmf) + compute_energy = energy_predictor(VWN) + predicted_e, fock = compute_energy(PARAMS, gd_sol) + + vwndiff = (ground_truth_energy - predicted_e) * Hartree2kcalmol + + assert not jnp.isnan(fock).any() + assert jnp.allclose(vwndiff, 0, atol=DIFF_TOL) + + +#### PW92 #### +@pytest.mark.parametrize("sol", sols) +def test_pw92(sol): + kmf = dft.KRKS(sol, kpts=sol.make_kpts(KPTS)) + kmf.xc = "LDA_C_PW" + ground_truth_energy = kmf.kernel() + + gd_sol = solid_from_pyscf(kmf) + compute_energy = energy_predictor(PW92) + predicted_e, fock = compute_energy(PARAMS, gd_sol) + + pw92diff = (ground_truth_energy - predicted_e) * Hartree2kcalmol + + assert not jnp.isnan(fock).any() + assert jnp.allclose(pw92diff, 0, atol=DIFF_TOL) From 9821531dbe6361acbf6596b7e571e0586d970d77 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 6 Dec 2023 16:31:14 -0500 Subject: [PATCH 33/36] perhaps tf bug with linux is because pytest versions aren't consistent. --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6b84e25..edc0361 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ tensorflow-hub>=0.14.0 typeguard==2.13.3 typing_extensions>=4.8.0 jaxtyping -pytest +pytest>=7.4.3 + From b533a7cf3f7ee54ff90f4cf3f98cc668136a7b5c Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 6 Dec 2023 16:39:24 -0500 Subject: [PATCH 34/36] restric tensorflow verion --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index edc0361..a236acd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ jaxlib>=0.4.14 pyscf>=2.3.0 attrs>=23.1.0 flax>=0.7.2 -tensorflow>=2.13.0 +tensorflow>=2.13.0,<=2.14.0 tensorflow-hub>=0.14.0 typeguard==2.13.3 typing_extensions>=4.8.0 From 9e08c52aac74159001cb528004254ca361d035f8 Mon Sep 17 00:00:00 2001 From: Jack Baker Date: Wed, 6 Dec 2023 18:49:14 -0500 Subject: [PATCH 35/36] Changes to notebooks --- .../periodic_systems_bz_sampling_05.ipynb | 134 ++++++++++-------- ...periodic_systems_gamma_point_only_04.ipynb | 8 +- 2 files changed, 82 insertions(+), 60 deletions(-) diff --git a/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb index e22aa0e..0d38a17 100644 --- a/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb +++ b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb @@ -14,7 +14,7 @@ "\n", "(1) A DFT starting point to prime Grad DFT. We'll use the PBE functional.\n", "\n", - "(2) Accurate training and validation data. We'll use the periodic MP2 solver implemented in PySCF.\n", + "(2) Accurate training and validation data. We'll use the periodic CCSD solver implemented in PySCF.\n", "\n", "Our calculations will be run using Sodium Chloride (NaCl) in the rock salt structure.\n", "\n", @@ -36,7 +36,7 @@ } ], "source": [ - "from pyscf.pbc import gto, scf, mp\n", + "from pyscf.pbc import gto, scf, mp, cc\n", "import numpy as np" ] }, @@ -53,24 +53,7 @@ "cell_type": "code", "execution_count": 2, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING!\n", - " Very diffused basis functions are found in the basis set. They may lead to severe\n", - " linear dependence and numerical instability. You can set cell.exp_to_discard=0.1\n", - " to remove the diffused Gaussians whose exponents are less than 0.1.\n", - "\n", - "WARNING!\n", - " Very diffused basis functions are found in the basis set. They may lead to severe\n", - " linear dependence and numerical instability. You can set cell.exp_to_discard=0.1\n", - " to remove the diffused Gaussians whose exponents are less than 0.1.\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "# Training geometry: pristine NaCl\n", "\n", @@ -87,7 +70,7 @@ " a = lat_vec,\n", " atom = \"\"\"Na 0.0 0.0 0.0\n", " Cl %.5f %.5f %.5f\"\"\" % (param, param, param),\n", - " basis = '631g*',\n", + " basis = 'sto-3g',\n", ")\n", "cell_tr.exp_to_discard=0.1\n", "\n", @@ -104,8 +87,8 @@ "cell_val = gto.M(\n", " a = lat_vec_strain,\n", " atom = \"\"\"Na 0.0 0.0 0.0 \n", - " Cl %.5f %.5f %.5f\"\"\" % (param_strain, param_strain, param_strain), # Na atom was displaced slightly.\n", - " basis = '631g*'\n", + " Cl %.5f %.5f %.5f\"\"\" % (param_strain, param_strain, param_strain),\n", + " basis = 'sto-3g'\n", ")\n", "cell_val.exp_to_discard=0.1" ] @@ -126,20 +109,61 @@ "name": "stdout", "output_type": "stream", "text": [ - "converged SCF energy = -622.178071472529\n", - "converged SCF energy = -622.168799570356\n" + "\n", + "WARN: HOMO 0.133342844043 == LUMO 0.133342844043\n", + "\n", + "\n", + "WARN: HOMO 0.129696509843 == LUMO 0.129696796322\n", + "\n", + "\n", + "WARN: HOMO 0.123485666222 == LUMO 0.12353379514\n", + "\n", + "\n", + "WARN: HOMO 0.122470531599 == LUMO 0.122549652121\n", + "\n", + "\n", + "WARN: HOMO 0.121977358086 == LUMO 0.121984607601\n", + "\n", + "\n", + "WARN: HOMO 0.127197661889 == LUMO 0.127213548187\n", + "\n", + "\n", + "WARN: HOMO 0.12742779891 == LUMO 0.127575039567\n", + "\n", + "SCF not converged.\n", + "SCF energy = -613.999832362389\n", + "\n", + "WARN: HOMO 0.136411628811 == LUMO 0.136411628812\n", + "\n", + "\n", + "WARN: HOMO 0.113400603597 == LUMO 0.113620213077\n", + "\n", + "\n", + "WARN: HOMO 0.114842685494 == LUMO 0.115091645752\n", + "\n", + "\n", + "WARN: HOMO 0.179108001182 == LUMO 0.179217499383\n", + "\n", + "\n", + "WARN: HOMO 0.180326657467 == LUMO 0.180385178642\n", + "\n", + "\n", + "WARN: HOMO 0.180259244142 == LUMO 0.180281025243\n", + "\n", + "SCF not converged.\n", + "SCF energy = -613.984244474623\n" ] } ], "source": [ "# Run training DFT starting point\n", - "kmf_tr = scf.KRKS(cell_tr, kpts=cell_tr.make_kpts([2,1,1])).density_fit()\n", + "kmf_tr = scf.KRKS(cell_tr, kpts=cell_tr.make_kpts([2,2,2])).density_fit()\n", "kmf_tr.xc = \"PBE\"\n", "kmf_tr.max_cycle = 10\n", "kmf_tr = kmf_tr.run()\n", "\n", "# Run validation DFT starting point\n", - "kmf_val = scf.KRKS(cell_val, kpts=cell_val.make_kpts([2,1,1])).density_fit()\n", + "kmf_val = scf.KRKS(cell_val, kpts=cell_val.make_kpts([2,2,2])).density_fit()\n", "kmf_val.xc = \"PBE\"\n", "kmf_val.max_cycle = 10\n", "kmf_val = kmf_val.run()" @@ -149,7 +173,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we can perform the MP2 calculations which will be used for truth values in training." + "Now we can perform the CCSD calculations which will be used for truth values in training." ] }, { @@ -161,32 +185,30 @@ "name": "stdout", "output_type": "stream", "text": [ - "converged SCF energy = -621.379366154699\n", - "E(KMP2) = -621.513466780104 E_corr = -0.134100625404806\n", - "E(SCS-KMP2) = -621.509253400475 E_corr = -0.129887245775369\n", - "converged SCF energy = -621.368407929544\n", - "E(KMP2) = -621.502082008919 E_corr = -0.133674079374634\n", - "E(SCS-KMP2) = -621.497876632087 E_corr = -0.129468702543138\n" + "converged SCF energy = -614.443314677292\n", + "E(RCCSD) = -614.4825393595152 E_corr = -0.03922468222342814\n", + "converged SCF energy = -614.434597523732\n", + "E(RCCSD) = -614.4738196894283 E_corr = -0.03922216569629878\n" ] } ], "source": [ - "# Make one training data-point and one validation using MP2\n", + "# Make one training data-point and one validation using CCSD\n", "\n", "# Training\n", - "khf_tr = scf.KRHF(cell_tr, kpts=cell_tr.make_kpts([2,1,1])).density_fit()\n", + "khf_tr = scf.KRHF(cell_tr, kpts=cell_tr.make_kpts([2,2,2])).density_fit()\n", "khf_tr = khf_tr.run()\n", - "mp2_tr = mp.KRMP2(khf_tr)\n", - "mp2_tr = mp2_tr.run()\n", - "E_tr = mp2_tr.e_tot\n", + "ccsd_tr = cc.KCCSD(khf_tr)\n", + "ccsd_tr = ccsd_tr.run()\n", + "E_tr = ccsd_tr.e_tot\n", "\n", "\n", "# Validation\n", - "khf_val = scf.KRHF(cell_val, kpts=cell_val.make_kpts([2,1,1])).density_fit()\n", + "khf_val = scf.KRHF(cell_val, kpts=cell_val.make_kpts([2,2,2])).density_fit()\n", "khf_val = khf_val.run()\n", - "mp2_val = mp.KRMP2(khf_val)\n", - "mp2_val = mp2_val.run()\n", - "E_val = mp2_val.e_tot\n" + "ccsd_val = cc.KCCSD(khf_val)\n", + "ccsd_val = ccsd_val.run()\n", + "E_val = ccsd_val.e_tot\n" ] }, { @@ -207,7 +229,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/var/folders/k8/81tnbcsx5lv94kjrw7pj513r0000gq/T/ipykernel_87611/2351384841.py:1: DeprecationWarning: Accessing jax.config via the jax.config submodule is deprecated.\n", + "/var/folders/k8/81tnbcsx5lv94kjrw7pj513r0000gq/T/ipykernel_57191/2351384841.py:1: DeprecationWarning: Accessing jax.config via the jax.config submodule is deprecated.\n", " from jax.config import config\n" ] }, @@ -387,28 +409,28 @@ "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 50%|█████ | 5/10 [00:37<00:34, 6.95s/it]" + "Training epoch: 50%|█████ | 5/10 [00:45<00:41, 8.39s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 5 training loss = 0.0001737845401721004, validation loss = 0.0001757714747113059\n" + "At epoch 5 training loss = 0.00021681116222285106, validation loss = 0.00022159278002315468\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 100%|██████████| 10/10 [01:10<00:00, 7.01s/it]" + "Training epoch: 100%|██████████| 10/10 [01:24<00:00, 8.41s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 10 training loss = 0.00018310176622873998, validation loss = 0.00018106695140976598\n" + "At epoch 10 training loss = 3.611193058348861e-07, validation loss = 1.789025202725588e-07\n" ] }, { @@ -439,7 +461,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -448,7 +470,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB2h0lEQVR4nO3deXhTVf7H8XeSpkn3srZl3yo7VEGwgIIKFMGlLmw6bMPAb2YEYao4ouzoMC4gIijiKOooA+LCMC6VgrhSAUEQFFCUHVp2Cl3T5P7+KI2GttCWlqTt5/U8eZqce+6935uTNt+ee889JsMwDERERETEzeztAERERER8jRIkERERkQsoQRIRERG5gBIkERERkQsoQRIRERG5gBIkERERkQsoQRIRERG5gBIkERERkQsoQRIRERG5gBIkEbki9u7di8lk4rXXXivV+iaTiWnTppVpTFJ5DR8+nEaNGnk7DKnAlCBJpfbaa69hMpmw2+0cOnSowPIePXrQpk0bL0SWZ9u2bdxzzz00bNgQu91O3bp16dWrF88//3yBuk6nk8WLF9OjRw+qV6+OzWajUaNGjBgxgm+//dZdL/+YC3s88sgjF41nyZIlzJ07t6wPs1L6/fv81VdfFVhuGAb169fHZDJx6623eiw7d+4cU6dOpU2bNgQFBVGjRg1iYmIYN24chw8fdtebNm1akW1pMplISUkp9+MUqar8vB2AyJWQnZ3NP//5z0ITD29Zt24dN954Iw0aNGDUqFFERkZy4MABvvnmG5577jnGjh3rrpuZmcldd91FYmIiN9xwA48++ijVq1dn7969vP3227z++uvs37+fevXqudeZMWMGjRs39tjnpZLBJUuWsH37dsaPH1+mxwrQsGFDMjMzsVqtpVo/MzMTPz/f+5Nlt9tZsmQJ3bp18yj//PPPOXjwIDabzaPc4XBwww03sHPnToYNG8bYsWM5d+4cP/zwA0uWLOHOO++kTp06Huu8+OKLBAcHF9h3eHh4mR+PiOTxvb82IuUgJiaGl19+mYkTJxb48vGWJ554grCwMDZu3Fjgi+7o0aMerydMmEBiYiLPPvtsgeRl6tSpPPvsswW2f8stt9CxY8eyDtstKysLf39/zObidUTn9+SV1uWsW5769u3L8uXLmTdvnkcCt2TJEjp06MDx48c96q9YsYLvvvuOt956i3vvvddjWVZWFjk5OQX2cc8991CzZs3yOYArxOVykZOT47PtKHIhnWKTKuHRRx/F6XTyz3/+85J1c3NzmTlzJk2bNnWfxnr00UfJzs72qNeoUSNuvfVWvvrqKzp16oTdbqdJkya88cYbxYrpl19+oXXr1oX2AtSuXdv9/ODBg7z00kv06tWr0J4di8XCQw895NF7VBo9evTgww8/ZN++fe5TOPnXcHz22WeYTCaWLl3KpEmTqFu3LoGBgaSlpXHy5Ekeeugh2rZtS3BwMKGhodxyyy1s3brVY/uFXYM0fPhwgoODOXToEPHx8QQHB1OrVi0eeughnE6nx/oXXoOUf/pp9+7dDB8+nPDwcMLCwhgxYgQZGRke62ZmZvLAAw9Qs2ZNQkJCuP322zl06FCh1zXt3LmT/fv3F/t9Gzx4MCdOnCApKcldlpOTwzvvvFMgAYK8dgfo2rVrgWV2u53Q0NBi77s43nzzTTp06EBAQADVq1dn0KBBHDhwwKNO/qnmH3/8kRtvvJHAwEDq1q3LU089VWB72dnZTJ06lWbNmmGz2ahfvz4PP/xwgd8Pk8nEmDFjeOutt2jdujU2m43ExEQAvv/+e7p3705AQAD16tXj8ccfZ/HixZhMJvbu3QvAsGHDqFmzJg6Ho0AMvXv3pnnz5iV+L9LT03nwwQepX78+NpuN5s2b88wzz2AYhke9pKQkunXrRnh4OMHBwTRv3pxHH33Uo87zzz9P69atCQwMpFq1anTs2JElS5aUOCbxXepBkiqhcePGDB06lJdffplHHnnkor1If/rTn3j99de55557ePDBB1m/fj2zZs1ix44dvP/++x51d+/ezT333MPIkSMZNmwYr776KsOHD6dDhw60bt36ojE1bNiQ5ORktm/fftFTXx9//DG5ubkMGTKkRMd85syZAr0XF+uFeOyxxzhz5gwHDx5090hdeFpn5syZ+Pv789BDD5GdnY2/vz8//vgjK1asoH///jRu3JjU1FReeuklunfvzo8//njJHjun00lcXBydO3fmmWeeYfXq1cyePZumTZvyl7/85ZLHOWDAABo3bsysWbPYvHkz//rXv6hduzZPPvmku87w4cN5++23GTJkCNdddx2ff/45/fr1K3R7LVu2pHv37nz22WeX3DfkJcqxsbH85z//4ZZbbgHy2uzMmTMMGjSIefPmedRv2LAhAG+88QaTJk3CZDJdch8nT54sUObn53fJU2xPPPEEkydPZsCAAfzpT3/i2LFjPP/889xwww189913HuufOnWKPn36cNdddzFgwADeeecd/v73v9O2bVv3cblcLm6//Xa++uorRo8eTcuWLdm2bRvPPvssP/30EytWrPDY/6effsrbb7/NmDFjqFmzJo0aNeLQoUPceOONmEwmJk6cSFBQEP/6178KnIocMmQIb7zxBp988onHNVwpKSl8+umnTJ069ZLv2+8ZhsHtt9/O2rVrGTlyJDExMXzyySdMmDCBQ4cOuT/zP/zwA7feeivt2rVjxowZ2Gw2du/ezddff+3e1ssvv8wDDzzAPffcw7hx48jKyuL7779n/fr1hSbFUkEZIpXY4sWLDcDYuHGj8csvvxh+fn7GAw884F7evXt3o3Xr1u7XW7ZsMQDjT3/6k8d2HnroIQMwPv30U3dZw4YNDcD44osv3GVHjx41bDab8eCDD14ytlWrVhkWi8WwWCxGbGys8fDDDxuffPKJkZOT41Hvb3/7mwEY3333XYmOubDHpfTr189o2LBhgfK1a9cagNGkSRMjIyPDY1lWVpbhdDo9yvbs2WPYbDZjxowZHmWAsXjxYnfZsGHDDMCjnmEYxtVXX2106NDBowwwpk6d6n49depUAzD++Mc/etS78847jRo1arhfb9q0yQCM8ePHe9QbPnx4gW3m76d79+4F3oML/f6zNX/+fCMkJMT93vTv39+48cYbDcPI+5z069fPvV5GRobRvHlzAzAaNmxoDB8+3HjllVeM1NTUAvvIP8bCHs2bN79ofHv37jUsFovxxBNPeJRv27bN8PPz8yjv3r27ARhvvPGGuyw7O9uIjIw07r77bnfZv//9b8NsNhtffvmlxzYXLlxoAMbXX3/tLgMMs9ls/PDDDx51x44da5hMJo/P84kTJ4zq1asbgLFnzx7DMAzD6XQa9erVMwYOHOix/pw5cwyTyWT8+uuvFz3+YcOGeXyWV6xYYQDG448/7lHvnnvuMUwmk7F7927DMAzj2WefNQDj2LFjRW77jjvu8Pi7IZWTTrFJldGkSROGDBnCokWLOHLkSKF1PvroIwASEhI8yh988EEAPvzwQ4/yVq1acf3117tf16pVi+bNm/Prr79eMp5evXqRnJzM7bffztatW3nqqaeIi4ujbt26rFy50l0vLS0NgJCQkGIc5W8WLFhAUlKSx+NyDRs2jICAAI8ym83mvg7J6XRy4sQJ92mJzZs3F2u7f/7znz1eX3/99cV6D4ta98SJE+73Lf+0zl//+lePer+/CP73DMModu9RvgEDBpCZmckHH3zA2bNn+eCDD4rsSQgICGD9+vVMmDAByBsNN3LkSKKiohg7dmyBU1UA7777boG2XLx48UVjeu+993C5XAwYMIDjx4+7H5GRkURHR7N27VqP+sHBwfzhD39wv/b396dTp04e7bB8+XJatmxJixYtPLZ50003ARTYZvfu3WnVqpVHWWJiIrGxscTExLjLqlevzn333edRz2w2c99997Fy5UrOnj3rLn/rrbfo0qVLgQEIl/LRRx9hsVh44IEHPMoffPBBDMPg448/Bn678P2///0vLper0G2Fh4dz8OBBNm7cWKIYpGJRgiRVyqRJk8jNzS3yWqR9+/ZhNptp1qyZR3lkZCTh4eHs27fPo7xBgwYFtlGtWjVOnToF5CUMKSkpHo/fX4R77bXX8t5773Hq1Ck2bNjAxIkTOXv2LPfccw8//vgjgPualN9/SRRHp06d6Nmzp8fjchX2peRyuXj22WeJjo7GZrNRs2ZNatWqxffff8+ZM2cuuU273U6tWrU8yn7/Hl7KhW1QrVo1APf6+W16YewXtvHlqFWrFj179mTJkiW89957OJ1O7rnnniLrh4WF8dRTT7F371727t3LK6+8QvPmzZk/fz4zZ84sUP+GG24o0JaxsbEXjennn3/GMAyio6OpVauWx2PHjh0FBgLUq1evwOm+C9vh559/5ocffiiwvauuugooOLigsM/Lvn37Cn3vCysbOnQomZmZ7lPbu3btYtOmTSU+3Zy/3zp16hT4R6Nly5bu5QADBw6ka9eu/OlPfyIiIoJBgwbx9ttveyRLf//73wkODqZTp05ER0dz//33e5yCk8pB1yBJldKkSRP+8Ic/sGjRooveE6g414VA3gXShTHOX/R54MCBAl8Sa9eupUePHh5l/v7+XHvttVx77bVcddVVjBgxguXLlzN16lRatGgB5N0z6ff/dXvDhb1HAP/4xz+YPHkyf/zjH5k5cybVq1fHbDYzfvz4Iv8D/72i3sPiulQbXCn33nsvo0aNIiUlhVtuuaXYQ/AbNmzIH//4R+68806aNGnCW2+9xeOPP37Z8bhcLkwmEx9//HGh79GF15cV5310uVy0bduWOXPmFFq3fv36Hq8L+7yURKtWrejQoQNvvvkmQ4cO5c0338Tf358BAwZc1nYvJiAggC+++IK1a9fy4YcfkpiYyLJly7jppptYtWoVFouFli1bsmvXLj744AMSExN59913eeGFF5gyZQrTp08vt9jkylKCJFXOpEmTePPNNz0u4s3XsGFDXC4XP//8s/s/S4DU1FROnz7tvsC2uCIjIwuc2mrfvv1F18kfmp9/GvCWW27BYrHw5ptvluo/55IobmL4e++88w433ngjr7zyikf56dOnfWJoen6b7tmzh+joaHf57t27y3Q/d955J//3f//HN998w7Jly0q8frVq1WjatCnbt28vk3iaNm2KYRg0btzY3cNTFtvcunUrN998c6k+K5DXHoW990W1x9ChQ0lISODIkSMsWbKEfv36uXsJS7rf1atXc/bsWY9epJ07d7qX5zObzdx8883cfPPNzJkzh3/84x889thjrF271t0TGxQUxMCBAxk4cCA5OTncddddPPHEE0ycOFG3MqgkdIpNqpymTZvyhz/8gZdeeqnAnYj79u0LUOBu0vn/MRc18qkodru9wKmR/D/ua9euLbSXI/86qPxhzPXr12fUqFGsWrWq0BtdulwuZs+ezcGDB0sUW2GCgoKKdVrs9ywWS4HjWL58eaF3LveGuLg4AF544QWP8qJuGlrSYf75goODefHFF5k2bRq33XZbkfW2bt1aYHQh5J3i+fHHH0s1fL0wd911FxaLhenTpxdoH8MwOHHiRIm3OWDAAA4dOsTLL79cYFlmZibp6emX3EZcXBzJycls2bLFXXby5EneeuutQusPHjwYk8nEuHHj+PXXXz2ukyqJvn374nQ6mT9/vkf5s88+i8lkco/UK2zEYH7Pbf71YRe+d/7+/rRq1QrDMAq9LYFUTOpBkirpscce49///je7du3yGI7fvn17hg0bxqJFizh9+jTdu3dnw4YNvP7668THx3PjjTeWWQxjx44lIyODO++8kxYtWpCTk8O6detYtmyZewqRfLNnz+aXX37hgQce4L333uPWW2+lWrVq7N+/n+XLl7Nz504GDRp02TF16NCBZcuWkZCQwLXXXktwcPBFv+wBbr31VmbMmMGIESPo0qUL27Zt46233qJJkyaXHU9Z6NChA3fffTdz587lxIkT7mH+P/30E1Cw16ykw/x/b9iwYZesk5SUxNSpU7n99tu57rrrCA4O5tdff+XVV18lOzu70Pnm3nnnnULvpN2rVy8iIiIK3U/Tpk15/PHHmThxInv37iU+Pp6QkBD27NnD+++/z+jRo3nooYdKdHxDhgzh7bff5s9//jNr166la9euOJ1Odu7cydtvv80nn3xyyZuTPvzww7z55pv06tWLsWPHuof5N2jQgJMnTxZoj1q1atGnTx+WL19OeHh4if9JyXfbbbdx44038thjj7F3717at2/PqlWr+O9//8v48eNp2rQpkHcH+i+++IJ+/frRsGFDjh49ygsvvEC9evXcd0vv3bs3kZGRdO3alYiICHbs2MH8+fPp169fiQdTiA/zzuA5kSvj90OxL5Q/xPzC4boOh8OYPn260bhxY8NqtRr169c3Jk6caGRlZXnUu3D4dr7u3bsXa5j4xx9/bPzxj380WrRoYQQHBxv+/v5Gs2bNjLFjxxY65Ds3N9f417/+ZVx//fVGWFiYYbVajYYNGxojRozwGDJ9sWO+lHPnzhn33nuvER4e7h6Gbhi/DfNfvnx5gXWysrKMBx980IiKijICAgKMrl27GsnJyQXeh6KG+QcFBRXYZv7w9t+jiGH+Fw7Hzj/+/OHihmEY6enpxv33329Ur17dCA4ONuLj441du3YZgPHPf/6zwH5KOsz/Yi78nPz666/GlClTjOuuu86oXbu24efnZ9SqVcvo16+fx20kfn+MRT3Wrl17yTjfffddo1u3bkZQUJARFBRktGjRwrj//vuNXbt2uetceLuLfBcOlTcMw8jJyTGefPJJo3Xr1obNZjOqVatmdOjQwZg+fbpx5swZdz3AuP/++wuN6bvvvjOuv/56w2azGfXq1TNmzZplzJs3zwCMlJSUAvXffvttAzBGjx59yeO9WOxnz541/va3vxl16tQxrFarER0dbTz99NOGy+Vy11mzZo1xxx13GHXq1DH8/f2NOnXqGIMHDzZ++uknd52XXnrJuOGGG4waNWoYNpvNaNq0qTFhwgSP45eKz2QYV/hKRhERH7Blyxauvvpq3nzzzQJDzOXKGz9+PC+99BLnzp0rcMH4f//7X+Lj4/niiy88bqshUp50DZKIVHqZmZkFyubOnYvZbOaGG27wQkRV24XtceLECf7973/TrVu3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XfFHed55+uuvv2b48OHceeedtG3blsjIyEtOql7WwsLCiIiIYOPGje4yp9PJ5s2bS7Sdli1b8vXXX3uUff3117Rq1cr9OiAggNtuu4158+bx2WefkZyczLZt24C86WV69uzJU089xffff8/evXv59NNPL+PIyod6kHyMJSCUFGoQyQmO/LKV+nXrejskERG5TNHR0bz33nvcdtttmEwmJk+efNGeoPIyduxYZs2aRbNmzWjRogXPP/88p06dKlFyOGHCBAYMGMDVV19Nz549+d///sd7773nHpX32muv4XQ66dy5M4GBgbz55psEBATQsGFDPvjgA3799VduuOEGqlWrxkcffYTL5aJ58+bldcilph4kH3TEUgeA9IPbvRyJiIiUhTlz5lCtWjW6dOnCbbfdRlxcHNdcc80Vj+Pvf/87gwcPZujQocTGxhIcHExcXFyJ5sGLj4/nueee45lnnqF169a89NJLLF68mB49egAQHh7Oyy+/TNeuXWnXrh2rV6/mf//7HzVq1CA8PJz33nuPm266iZYtW7Jw4UL+85//0Lp163I64tIzGVf65GQlkZaWRlhYGGfOnCnzyWq/mDOEmzM/5vNq99B93Ctltm0pHYfDwUcffUTfvn0195cPUHv4lsttj6ysLPbs2UPjxo01WW0ZcLlcpKWlERoaWqy52FwuFy1btmTAgAHMnDnzCkR4ZVzsc1Xc72+dYvNBGQF1IBNCzv3i7VBERKQS2bdvH6tWraJ79+5kZ2czf/589uzZw7333uvt0HyOTrH5IFdI3nVHdXP24nKpg09ERMqG2Wzmtdde49prr6Vr165s27aN1atX07JlS2+H5nPUg+SDzKF5CVKE6RT7U47QoE4dL0ckIiKVQf369QuMQJPCqQfJB7n8AjhmqglA6u6tXo5GRESk6lGC5KOOBeTdCfXcwW1ejkRERKTqUYLko7LCmwFgPv6TlyMRERGpepQg+Si/iLwL5kLO7vZyJCIiIlWPEiQfFd6gDQB1cvZpJJuIiMgVpgTJR9VqnDeDc6TpJIdSUrwcjYiISNWiBMlH+QWF/zaS7Zct3g1GRETKXI8ePRg/frz7daNGjZg7d+5F1zGZTKxYseKy911W27mYadOmERMTU677KE9KkHzY8fyRbAd+8HIkIiKS77bbbqNPnz6FLvvyyy8xmUx8//33Jd7uxo0b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Fx07duQf//gHAFdffTXbt29n4cKFSpC85O233+att95iyZIltG7dmi1btjB+/Hjq1KmjNiklJUg+ombNmlgsFlJTUz3KU1NTiYyM9FJUMmbMGD744AO++OIL6tWr5+1wqqxNmzZx9OhRrrnmGneZ0+nkiy++YP78+WRnZ2OxWLwYYdUSFRVFq1atPMpatmzJu+++66WIZMKECTzyyCMMGjQIgLZt27Jv3z5mzZqlBKmUdA2Sj/D396dDhw6sWbPGXeZyuVizZg2xsbFejKxqMgyDMWPG8P777/Ppp5/SuHFjb4dUpd18881s27aNLVu2uB8dO3bkvvvuY8uWLUqOrrCuXbsWuO3FTz/9RMOGDb0UkWRkZGA2e36lWywWXC6XlyKq+NSD5EMSEhIYNmwYHTt2pFOnTsydO5f09HRGjBjh7dCqnPvvv58lS5bw3//+l5CQEFJSUgAICwsjICDAy9FVPSEhIQWu/woKCqJGjRq6LswL/va3v9GlSxf+8Y9/MGDAADZs2MCiRYtYtGiRt0Orsm677TaeeOIJGjRoQOvWrfnuu++YM2cOf/zjH70dWoWlYf4+Zv78+Tz99NOkpKQQExPDvHnz6Ny5s7fDqnJMJlOh5YsXL2b48OFXNhgpVI8ePTTM34s++OADJk6cyM8//0zjxo1JSEhg1KhR3g6ryjp79iyTJ0/m/fff5+jRo9SpU4fBgwczZcoU/P39vR1ehaQESUREROQCugZJRERE5AJKkEREREQuoARJRERE5AJKkEREREQuoARJRERE5AJKkEREREQuoARJRERE5AJKkERESslkMrFixQpvhyEi5UAJkohUSMOHD8dkMhV49OnTx9uhiUgloLnYRKTC6tOnD4sXL/Yos9lsXopGRCoT9SCJSIVls9mIjIz0eFSrVg3IO/314osvcssttxAQEECTJk145513PNbftm0bN910EwEBAdSoUYPRo0dz7tw5jzqvvvoqrVu3xmazERUVxZgxYzyWHz9+nDvvvJPAwECio6NZuXKle9mpU6e47777qFWrFgEBAURHRxdI6ETENylBEpFKa/Lkydx9991s3bqV++67j0GDBrFjxw4A0tPTiYuLo1q1amzcuJHly5ezevVqjwToxRdf5P7772f06NFs27aNlStX0qxZM499TJ8+nQEDBvD999/Tt29f7rvvPk6ePOne/48//sjHH3/Mjh07ePHFF6lZs+aVewNEpPQMEZEKaNiwYYbFYjGCgoI8Hk888YRhGIYBGH/+85891uncubPxl7/8xTAMw1i0aJFRrVo149y5c+7lH374oWE2m42UlBTDMAyjTp06xmOPPVZkDIAxadIk9+tz584ZgPHxxx8bhmEYt912mzFixIiyOWARuaJ0DZKIVFg33ngjL774okdZ9erV3c9jY2M9lsXGxrJlyxYAduzYQfv27QkKCnIv79q1Ky6Xi127dmEymTh8+DA333zzRWNo166d+3lQUBChoaEcPXoUgL/85S/cfffdbN68md69exMfH0+XLl1KdawicmUpQRKRCisoKKjAKa+yEhAQUKx6VqvV47XJZMLlcgFwyy23sG/fPj766COSkpK4+eabuf/++3nmmWfKPF4RKVu6BklEKq1vvvmmwOuWLVsC0LJlS7Zu3Up6erp7+ddff43ZbKZ58+aEhITQqFEj1qxZc1kx1KpVi2HDhvHmm28yd+5cFi1adFnbE5ErQz1IIlJhZWdnk5KS4lHm5+fnvhB6+fLldOzYkW7duvHWW2+xYcMGXnnlFQDuu+8+pk6dyrBhw5g2bRrHjh1j7NixDBkyhIiICACmTZvGn//8Z2rXrs0tt9zC2bNn+frrrxk7dmyx4psyZQodOnSgdevWZGdn88EHH7gTNBHxbUqQRKTCSkxMJCoqyqOsefPm7Ny5E8gbYbZ06VL++te/EhUVxX/+8x9atWoFQGBgIJ988gnjxo3j2muvJTAwkLvvvps5c+a4tzVs2DCysrJ49tlneeihh6hZsyb33HNPsePz9/dn4sSJ7N27l4CAAK6//nqWLl1aBkcuIuXNZBiG4e0gRETKmslk4v333yc+Pt7boYhIBaRrkEREREQuoARJRERE5AK6BklEKiVdPSAil0M9SCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIXUIIkIiIicgElSCIiIiIX+H/Bv1kU0tRRTgAAAABJRU5ErkJggg==", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAABxCklEQVR4nO3dd3wUdf7H8dfsJtn0hARICITQIr1IFVCBkyZYQCliocjB71SwoJ6i0k+xIioK6inoCQdi4ThFJCA2iIAgClJE6SWhE0jd7M7vj5A9lwQIIcmkvJ+Pxz7Y/c53vvOZ+S7sh5nvfMcwTdNERERERDxsVgcgIiIiUtooQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRKRErF7924Mw2DOnDmFWt8wDCZOnFikMUn5NXToUGrVqmV1GFKGKUGScm3OnDkYhoG/vz8HDhzIs7xz5840adLEgshybNq0iX79+hEXF4e/vz/Vq1enW7duvPbaa3nqulwuZs+eTefOnYmIiMDhcFCrVi2GDRvGjz/+6KmXu8/5vR5//PELxjNv3jymT59e1LtZLv35OH///fd5lpumSWxsLIZhcMMNN3gtO3PmDBMmTKBJkyYEBQURGRlJixYteOCBBzh48KCn3sSJE8/bl4ZhkJSUVOz7KVJR+VgdgEhJyMzM5Nlnn8038bDK6tWr6dKlCzVr1mTEiBFER0ezb98+fvjhB1555RVGjx7tqZuens4tt9zC0qVLufbaa3niiSeIiIhg9+7dfPjhh7z33nvs3buXGjVqeNaZPHkytWvX9trmxZLBefPmsXnzZh588MEi3VeAuLg40tPT8fX1LdT66enp+PiUvn+y/P39mTdvHldffbVX+TfffMP+/ftxOBxe5U6nk2uvvZZt27YxZMgQRo8ezZkzZ/j111+ZN28effv2JSYmxmudmTNnEhwcnGfb4eHhRb4/IpKj9P1rI1IMWrRowdtvv83YsWPz/PhY5emnnyYsLIx169bl+aE7fPiw1+dHH32UpUuX8vLLL+dJXiZMmMDLL7+cp/3rr7+e1q1bF3XYHhkZGfj5+WGzFexEdO6ZvMK6nHWLU69evVi4cCGvvvqqVwI3b948WrVqxdGjR73qL1q0iJ9++om5c+dy++23ey3LyMggKysrzzb69etH5cqVi2cHSojb7SYrK6vU9qPIuXSJTSqEJ554ApfLxbPPPnvRutnZ2UyZMoW6det6LmM98cQTZGZmetWrVasWN9xwA99//z1t27bF39+fOnXq8P777xcopj/++IPGjRvnexagatWqnvf79+/nzTffpFu3bvme2bHb7TzyyCNeZ48Ko3Pnznz++efs2bPHcwkndwzH119/jWEYzJ8/n6eeeorq1asTGBhISkoKx48f55FHHqFp06YEBwcTGhrK9ddfz88//+zVfn5jkIYOHUpwcDAHDhygT58+BAcHU6VKFR555BFcLpfX+ueOQcq9/PT7778zdOhQwsPDCQsLY9iwYaSlpXmtm56ezv3330/lypUJCQnhpptu4sCBA/mOa9q2bRt79+4t8HEbNGgQx44dIyEhwVOWlZXFRx99lCcBgpx+B+jYsWOeZf7+/oSGhhZ42wXxwQcf0KpVKwICAoiIiOC2225j3759XnVyLzVv2bKFLl26EBgYSPXq1Xn++efztJeZmcmECROoV68eDoeD2NhY/v73v+f5+2EYBqNGjWLu3Lk0btwYh8PB0qVLAfjll1/o1KkTAQEB1KhRg3/84x/Mnj0bwzDYvXs3AEOGDKFy5co4nc48MXTv3p369etf8rFITU3l4YcfJjY2FofDQf369XnxxRcxTdOrXkJCAldffTXh4eEEBwdTv359nnjiCa86r732Go0bNyYwMJBKlSrRunVr5s2bd8kxSemlM0hSIdSuXZvBgwfz9ttv8/jjj1/wLNJf//pX3nvvPfr168fDDz/MmjVrmDp1Klu3buXTTz/1qvv777/Tr18/hg8fzpAhQ3j33XcZOnQorVq1onHjxheMKS4ujsTERDZv3nzBS19ffPEF2dnZ3HXXXZe0z6dOncpz9uJCZyGefPJJTp06xf79+z1npM69rDNlyhT8/Px45JFHyMzMxM/Pjy1btrBo0SL69+9P7dq1SU5O5s0336RTp05s2bLlomfsXC4XPXr0oF27drz44ossX76cl156ibp163LPPfdcdD8HDBhA7dq1mTp1Khs2bOCf//wnVatW5bnnnvPUGTp0KB9++CF33XUXV111Fd988w29e/fOt72GDRvSqVMnvv7664tuG3IS5fbt2/Pvf/+b66+/Hsjps1OnTnHbbbfx6quvetWPi4sD4P333+epp57CMIyLbuP48eN5ynx8fC56ie3pp59m3LhxDBgwgL/+9a8cOXKE1157jWuvvZaffvrJa/0TJ07Qs2dPbrnlFgYMGMBHH33EY489RtOmTT375Xa7uemmm/j+++8ZOXIkDRs2ZNOmTbz88sv89ttvLFq0yGv7X331FR9++CGjRo2icuXK1KpViwMHDtClSxcMw2Ds2LEEBQXxz3/+M8+lyLvuuov333+fL7/80msMV1JSEl999RUTJky46HH7M9M0uemmm1i5ciXDhw+nRYsWfPnllzz66KMcOHDA853/9ddfueGGG2jWrBmTJ0/G4XDw+++/s2rVKk9bb7/9Nvfffz/9+vXjgQceICMjg19++YU1a9bkmxRLGWWKlGOzZ882AXPdunXmH3/8Yfr4+Jj333+/Z3mnTp3Mxo0bez5v3LjRBMy//vWvXu088sgjJmB+9dVXnrK4uDgTML/99ltP2eHDh02Hw2E+/PDDF41t2bJlpt1uN+12u9m+fXvz73//u/nll1+aWVlZXvUeeughEzB/+umnS9rn/F4X07t3bzMuLi5P+cqVK03ArFOnjpmWlua1LCMjw3S5XF5lu3btMh0Ohzl58mSvMsCcPXu2p2zIkCEm4FXPNE3zyiuvNFu1auVVBpgTJkzwfJ4wYYIJmHfffbdXvb59+5qRkZGez+vXrzcB88EHH/SqN3To0Dxt5m6nU6dOeY7Buf783ZoxY4YZEhLiOTb9+/c3u3TpYppmzvekd+/envXS0tLM+vXrm4AZFxdnDh061HznnXfM5OTkPNvI3cf8XvXr179gfLt37zbtdrv59NNPe5Vv2rTJ9PHx8Srv1KmTCZjvv/++pywzM9OMjo42b731Vk/Zv/71L9Nms5nfffedV5uzZs0yAXPVqlWeMsC02Wzmr7/+6lV39OjRpmEYXt/nY8eOmRERESZg7tq1yzRN03S5XGaNGjXMgQMHeq0/bdo00zAMc+fOnRfc/yFDhnh9lxctWmQC5j/+8Q+vev369TMNwzB///130zRN8+WXXzYB88iRI+dt++abb/b6d0PKJ11ikwqjTp063HXXXbz11lscOnQo3zpLliwBYMyYMV7lDz/8MACff/65V3mjRo245pprPJ+rVKlC/fr12blz50Xj6datG4mJidx00038/PPPPP/88/To0YPq1auzePFiT72UlBQAQkJCCrCX//P666+TkJDg9bpcQ4YMISAgwKvM4XB4xiG5XC6OHTvmuSyxYcOGArX7t7/9zevzNddcU6BjeL51jx075jluuZd17r33Xq96fx4E/2emaRb47FGuAQMGkJ6ezmeffcbp06f57LPPznsmISAggDVr1vDoo48COXfDDR8+nGrVqjF69Og8l6oAPv744zx9OXv27AvG9Mknn+B2uxkwYABHjx71vKKjo4mPj2flypVe9YODg7nzzjs9n/38/Gjbtq1XPyxcuJCGDRvSoEEDrzb/8pe/AORps1OnTjRq1MirbOnSpbRv354WLVp4yiIiIrjjjju86tlsNu644w4WL17M6dOnPeVz586lQ4cOeW5AuJglS5Zgt9u5//77vcoffvhhTNPkiy++AP438P0///kPbrc737bCw8PZv38/69atu6QYpGxRgiQVylNPPUV2dvZ5xyLt2bMHm81GvXr1vMqjo6MJDw9nz549XuU1a9bM00alSpU4ceIEkJMwJCUleb3+PAi3TZs2fPLJJ5w4cYK1a9cyduxYTp8+Tb9+/diyZQuAZ0zKn38kCqJt27Z07drV63W58vtRcrvdvPzyy8THx+NwOKhcuTJVqlThl19+4dSpUxdt09/fnypVqniV/fkYXsy5fVCpUiUAz/q5fXpu7Of28eWoUqUKXbt2Zd68eXzyySe4XC769et33vphYWE8//zz7N69m927d/POO+9Qv359ZsyYwZQpU/LUv/baa/P0Zfv27S8Y044dOzBNk/j4eKpUqeL12rp1a54bAWrUqJHnct+5/bBjxw5+/fXXPO1dccUVQN6bC/L7vuzZsyffY59f2eDBg0lPT/dc2t6+fTvr16+/5MvNuduNiYnJ8x+Nhg0bepYDDBw4kI4dO/LXv/6VqKgobrvtNj788EOvZOmxxx4jODiYtm3bEh8fz3333ed1CU7KB41BkgqlTp063Hnnnbz11lsXnBOoIONCIGeAdH7Ms4M+9+3bl+dHYuXKlXTu3NmrzM/PjzZt2tCmTRuuuOIKhg0bxsKFC5kwYQINGjQAcuZM+vP/uq1w7tkjgGeeeYZx48Zx9913M2XKFCIiIrDZbDz44IPn/R/4n53vGBbUxfqgpNx+++2MGDGCpKQkrr/++gLfgh8XF8fdd99N3759qVOnDnPnzuUf//jHZcfjdrsxDIMvvvgi32N07viyghxHt9tN06ZNmTZtWr51Y2NjvT7n9325FI0aNaJVq1Z88MEHDB48mA8++AA/Pz8GDBhwWe1eSEBAAN9++y0rV67k888/Z+nSpSxYsIC//OUvLFu2DLvdTsOGDdm+fTufffYZS5cu5eOPP+aNN95g/PjxTJo0qdhik5KlBEkqnKeeeooPPvjAaxBvrri4ONxuNzt27PD8zxIgOTmZkydPegbYFlR0dHSeS1vNmze/4Dq5t+bnXga8/vrrsdvtfPDBB4X6n/OlKGhi+GcfffQRXbp04Z133vEqP3nyZKm4NT23T3ft2kV8fLyn/Pfffy/S7fTt25f/+7//44cffmDBggWXvH6lSpWoW7cumzdvLpJ46tati2ma1K5d23OGpyja/Pnnn7nuuusK9V2BnP7I79ifrz8GDx7MmDFjOHToEPPmzaN3796es4SXut3ly5dz+vRpr7NI27Zt8yzPZbPZuO6667juuuuYNm0azzzzDE8++SQrV670nIkNCgpi4MCBDBw4kKysLG655Raefvppxo4dq6kMygldYpMKp27dutx55528+eabeWYi7tWrF0Ce2aRz/8d8vjufzsff3z/PpZHcf9xXrlyZ71mO3HFQubcxx8bGMmLECJYtW5bvRJdut5uXXnqJ/fv3X1Js+QkKCirQZbE/s9vtefZj4cKF+c5cboUePXoA8MYbb3iVn2/S0Eu9zT9XcHAwM2fOZOLEidx4443nrffzzz/nubsQci7xbNmypVC3r+fnlltuwW63M2nSpDz9Y5omx44du+Q2BwwYwIEDB3j77bfzLEtPTyc1NfWibfTo0YPExEQ2btzoKTt+/Dhz587Nt/6gQYMwDIMHHniAnTt3eo2TuhS9evXC5XIxY8YMr/KXX34ZwzA8d+rld8dg7pnb3PFh5x47Pz8/GjVqhGma+U5LIGWTziBJhfTkk0/yr3/9i+3bt3vdjt+8eXOGDBnCW2+9xcmTJ+nUqRNr167lvffeo0+fPnTp0qXIYhg9ejRpaWn07duXBg0akJWVxerVq1mwYIHnESK5XnrpJf744w/uv/9+PvnkE2644QYqVarE3r17WbhwIdu2beO222677JhatWrFggULGDNmDG3atCE4OPiCP/YAN9xwA5MnT2bYsGF06NCBTZs2MXfuXOrUqXPZ8RSFVq1aceuttzJ9+nSOHTvmuc3/t99+A/KeNbvU2/z/bMiQIRetk5CQwIQJE7jpppu46qqrCA4OZufOnbz77rtkZmbm+7y5jz76KN+ZtLt160ZUVFS+26lbty7/+Mc/GDt2LLt376ZPnz6EhISwa9cuPv30U0aOHMkjjzxySft311138eGHH/K3v/2NlStX0rFjR1wuF9u2bePDDz/kyy+/vOjkpH//+9/54IMP6NatG6NHj/bc5l+zZk2OHz+epz+qVKlCz549WbhwIeHh4Zf8n5RcN954I126dOHJJ59k9+7dNG/enGXLlvGf//yHBx98kLp16wI5M9B/++239O7dm7i4OA4fPswbb7xBjRo1PLOld+/enejoaDp27EhUVBRbt25lxowZ9O7d+5JvppBSzJqb50RKxp9vxT5X7i3m596u63Q6zUmTJpm1a9c2fX19zdjYWHPs2LFmRkaGV71zb9/O1alTpwLdJv7FF1+Yd999t9mgQQMzODjY9PPzM+vVq2eOHj0631u+s7OzzX/+85/mNddcY4aFhZm+vr5mXFycOWzYMK9bpi+0zxdz5swZ8/bbbzfDw8M9t6Gb5v9u81+4cGGedTIyMsyHH37YrFatmhkQEGB27NjRTExMzHMcznebf1BQUJ42c29v/zPOc5v/ubdj5+5/7u3ipmmaqamp5n333WdGRESYwcHBZp8+fczt27ebgPnss8/m2c6l3uZ/Ied+T3bu3GmOHz/evOqqq8yqVauaPj4+ZpUqVczevXt7TSPx530832vlypUXjfPjjz82r776ajMoKMgMCgoyGzRoYN53333m9u3bPXXOne4i17m3ypumaWZlZZnPPfec2bhxY9PhcJiVKlUyW7VqZU6aNMk8deqUpx5g3nffffnG9NNPP5nXXHON6XA4zBo1aphTp041X331VRMwk5KS8tT/8MMPTcAcOXLkRff3QrGfPn3afOihh8yYmBjT19fXjI+PN1944QXT7XZ76qxYscK8+eabzZiYGNPPz8+MiYkxBw0aZP7222+eOm+++aZ57bXXmpGRkabD4TDr1q1rPvroo177L2WfYZolPJJRRKQU2LhxI1deeSUffPBBnlvMpeQ9+OCDvPnmm5w5cybPgPH//Oc/9OnTh2+//dZrWg2R4qQxSCJS7qWnp+cpmz59OjabjWuvvdaCiCq2c/vj2LFj/Otf/+Lqq6/O9266t99+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1atXM3fuXObMmVOU8UkJSo3MGahtaKC2iIhUcIVKkJxOJw6HA4Dly5dz0003AdCgQQOvh8tK2eKomTOjdmTKVosjERERsVahEqTGjRsza9YsvvvuOxISEujZsycABw8eJDIyskgDlJIT07AdAFGuJNypJyyORkRExDqFSpCee+453nzzTTp37sygQYNo3rw5AIsXL/ZcepOyp06N6uw1qwKQtF0DtUVEpOLyKcxKnTt35ujRo6SkpFCpUiVP+ciRIwkMDCyy4KRk+dht7PO/gpqZhznxx4/EtLze6pBEREQsUagzSOnp6WRmZnqSoz179jB9+nS2b99O1apVizRAKVmpEY0BMA5ttDYQERERCxUqQbr55pt5//33ATh58iTt2rXjpZdeok+fPsycObNIA5SS5RebM1C70ikN1BYRkYqrUAnShg0buOaaawD46KOPiIqKYs+ePbz//vu8+uqrRRqglKzoBlcBUM11ADP9pLXBiIiIWKRQCVJaWhohISEALFu2jFtuuQWbzcZVV13Fnj17ijRAKVl1atZkv1kZgOQdP1ocjYiIiDUKlSDVq1ePRYsWsW/fPr788ku6d+8OwOHDhwkNDS3SAKVk+fnY2OeIB+D4jrUWRyMiImKNQiVI48eP55FHHqFWrVq0bduW9u3bAzlnk6688soiDVBK3umInBm13Qc1o7aIiFRMhbrNv1+/flx99dUcOnTIMwcSwHXXXUffvn2LLDixhm+NKyEJKp361epQRERELFGoBAkgOjqa6Oho9u/fD0CNGjU0SWQ5EX1FO/gRqmXvx8w8jeEIsTokERGRElWoS2xut5vJkycTFhZGXFwccXFxhIeHM2XKFNxud1HHKCWsTp3aJJkR2DA5rIHaIiJSARXqDNKTTz7JO++8w7PPPkvHjh0B+P7775k4cSIZGRk8/fTTRRqklCyHj53dfvFEO9dwfMdaopp0sTokERGRElWoBOm9997jn//8JzfddJOnrFmzZlSvXp17771XCVI5cLpSYzi8BtfBjVaHIiIiUuIKdYnt+PHjNGjQIE95gwYNOH78+GUHJdaz18i5GzHs5BaLIxERESl5hUqQmjdvzowZM/KUz5gxg2bNml12UGK9qle0AyDGuRczK9XiaEREREpWoS6xPf/88/Tu3Zvly5d75kBKTExk3759LFmypEgDFGvUq1uPw2Y4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NatDK7N0m38p0q5dO9q0acOMGTOAnOe9xcbGMnr0aB5//HGLo6vYjhw5QtWqVfnmm2+49tprrQ6nwjpz5gwtW7bkjTfe4B//+ActWrRg+vTpVodV4Tz++OOsWrWK7777zupQ5KwbbriBqKgo3nnnHU/ZrbfeSkBAAB988IGFkZVdOoNUSmRlZbF+/Xq6du3qKbPZbHTt2pXExEQLIxOAU6dOARAREWFxJBXbfffdR+/evb3+nkjJW7x4Ma1bt6Z///5UrVqVK6+8krffftvqsCq0Dh06sGLFCn777TcAfv75Z77//nuuv/56iyMru/Sw2lLi6NGjuFwuoqKivMqjoqLYtm2bRVEJ5JzJe/DBB+nYsSNNmjSxOpwKa/78+WzYsIF169ZZHUqFt3PnTmbOnMmYMWN44oknWLduHffffz9+fn4MGTLE6vAqpMcff5yUlBQaNGiA3W7H5XLx9NNPc8cdd1gdWpmlBEnkIu677z42b97M999/b3UoFda+fft44IEHSEhIwN/f3+pwKjy3203r1q155plnALjyyivZvHkzs2bNUoJkkQ8//JC5c+cyb948GjduzMaNG3nwwQeJiYlRnxSSEqRSonLlytjtdpKTk73Kk5OTiY6OtigqGTVqFJ999hnffvstNWrUsDqcCmv9+vUcPnyYli1bespcLhfffvstM2bMIDMzE7vdbmGEFUu1atVo1KiRV1nDhg35+OOPLYpIHn30UR5//HFuu+02AJo2bcqePXuYOnWqEqRC0hikUsLPz49WrVqxYsUKT5nb7WbFihW0b9/ewsgqJtM0GTVqFJ9++ilfffUVtWvXtjqkCu26665j06ZNbNy40fNq3bo1d9xxBxs3blRyVMI6duyYZ9qL3377jbi4OIsikrS0NGw27590u92O2+22KKKyT2eQSpExY8YwZMgQWrduTdu2bZk+fTqpqakMGzbM6tAqnPvuu4958+bxn//8h5CQEJKSkgAICwsjICDA4ugqnpCQkDzjv4KCgoiMjNS4MAs89NBDdOjQgWeeeYYBAwawdu1a3nrrLd566y2rQ6uwbrzxRp5++mlq1qxJ48aN+emnn5g2bRp333231aGVWbrNv5SZMWMGL7zwAklJSbRo0YJXX32Vdu3aWR1WhWMYRr7ls2fPZujQoSUbjOSrc+fOus3fQp999hljx45lx44d1K5dmzFjxjBixAirw6qwTp8+zbhx4/j00085fPgwMTExDBo0iPHjx+Pn52d1eGWSEiQRERGRc2gMkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiBSSYRgsWrTI6jBEpBgoQRKRMmno0KEYhpHn1bNnT6tDE5FyQM9iE5Eyq2fPnsyePdurzOFwWBSNiJQnOoMkImWWw+EgOjra61WpUiUg5/LXzJkzuf766wkICKBOnTp89NFHXutv2rSJv/zlLwQEBBAZGcnIkSM5c+aMV513332Xxo0b43A4qFatGqNGjfJafvToUfr27UtgYCDx8fEsXrzYs+zEiRPccccdVKlShYCAAOLj4/MkdCJSOilBEpFya9y4cdx66638/PPP3HHHHdx2221s3boVgNTUVHr06EGlSpVYt24dCxcuZPny5V4J0MyZM7nvvvsYOXIkmzZtYvHixdSrV89rG5MmTWLAgAH88ssv9OrVizvuuIPjx497tr9lyxa++OILtm7dysyZM6lcuXLJHQARKTxTRKQMGjJkiGm3282goCCv19NPP22apmkC5t/+9jevddq1a2fec889pmma5ltvvWVWqlTJPHPmjGf5559/btpsNjMpKck0TdOMiYkxn3zyyfPGAJhPPfWU5/OZM2dMwPziiy9M0zTNG2+80Rw2bFjR7LCIlCiNQRKRMqtLly7MnDnTqywiIsLzvn379l7L2rdvz8aNGwHYunUrzZs3JygoyLO8Y8eOuN1utm/fjmEYHDx4kOuuu+6CMTRr1szzPigoiNDQUA4fPgzAPffcw6233sqGDRvo3r07ffr0oUOHDoXaVxEpWUqQRKTMCgoKynPJq6gEBAQUqJ6vr6/XZ8MwcLvdAFx//fXs2bOHJUuWkJCQwHXXXcd9993Hiy++WOTxikjR0hgkESm3fvjhhzyfGzZsCEDDhg35+eefSU1N9SxftWoVNpuN+vXrExISQq1atVixYsVlxVClShWGDBnCBx98wPTp03nrrbcuqz0RKRk6gyQiZVZmZiZJSUleZT4+Pp6B0AsXLqR169ZcffXVzJ07l7Vr1/LOO+8AcMcddzBhwgSGDBnCxIkTOXLkCKNHj+auu+4iKioKgIkTJ/K3v/2NqlWrcv3113P69GlWrVrF6NGjCxTf+PHjadWqFY0bNyYzM5PPPvvMk6CJSOmmBElEyqylS5dSrVo1r7L69euzbds2IOcOs/nz53PvvfdSrVo1/v3vf9OoUSMAAgMD+fLLL3nggQdo06YNgYGB3HrrrUybNs3T1pAhQ8jIyODll1/mkUceoXLlyvTr16/A8fn5+TF27Fh2795NQEAA11xzDfPnzy+CPReR4maYpmlaHYSISFEzDINPP/2UPn36WB2KiJRBGoMkIiIicg4lSCIiIiLn0BgkESmXNHpARC6HziCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInOP/AelQk1YrSjIxAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -503,28 +525,28 @@ "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 50%|█████ | 5/10 [04:05<03:57, 47.47s/it]" + "Training epoch: 50%|█████ | 5/10 [04:17<04:11, 50.36s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 5 training loss = 0.00016916189677703596, validation loss = 0.0001707407536255283\n" + "At epoch 5 training loss = 0.0001228379673192498, validation loss = 0.00012489799656530793\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 100%|██████████| 10/10 [07:59<00:00, 47.91s/it]" + "Training epoch: 100%|██████████| 10/10 [08:26<00:00, 50.68s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 10 training loss = 0.00017956670686227404, validation loss = 0.00017311377171407244\n" + "At epoch 10 training loss = 0.00016523082156208446, validation loss = 0.00016298455128254218\n" ] }, { @@ -548,7 +570,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 13, @@ -557,7 +579,7 @@ }, { "data": { - "image/png": "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mMOVnJzMF198weTJky/7uV3IMAxuv/12Vq9ezfDhw2nfvj2ff/4548aN4/Dhw+7v/E8//cStt95K27ZtmTZtGjabjb179/Ltt9+623rttdd46KGHuOeeexgzZgyZmZn8+OOPrFu3rsCkWARDRIpsxYoVhsViMSwWixETE2M8+uijxueff25kZ2d71Pv73/9uAMamTZuK1O7ChQsNoMDX5fTr18+oX79+vvLVq1cbgNGoUSMjPT3dY1tmZqbhdDo9yvbt22fYbDZj2rRpHmWAsXDhQnfZkCFDDMCjnmEYxjXXXGN06NDBowwwJk+e7H4/efJkAzD+9Kc/edS78847jerVq7vfb9iwwQCMsWPHetQbOnRovjbzjtOjR498n8HF8j7n9evXG/PmzTNCQkLcn03//v2NG2+80TAMw6hfv77Rr18/937p6elGs2bNDMCoX7++MXToUOP11183UlJS8h0j7xwLejVr1uyS8e3fv9+wWCzG008/7VG+detWw8/Pz6O8R48eBmC8/fbb7rKsrCwjIiLCuPvuu91l//73vw2z2Wx8/fXXHm0uWLDAAIxvv/3WXQYYZrPZ+Omnnzzqjh492jCZTB7f599++82oVq2aARj79u0zDMMwnE6nUadOHWPgwIEe+8+ePdswmUzGL7/8csnzHzJkiMd3eenSpQZgPPXUUx717rnnHsNkMhl79+41DMMwnn/+eQMwjh8/Xmjbd9xxh9GqVatLHl/kQrrEJlIMvXr1Iikpidtvv50tW7bw7LPPEhsbS+3atVm2bJm7XmpqKgAhISHFan/+/PkkJiZ6vK7UkCFDCAgI8Ciz2WzueUhOp5PffvvNfVli48aNRWr3L3/5i8f76667jl9++aXE+/7222/uzy3vss7f/vY3j3oXToK/kGEYRR49yjNgwAAyMjL45JNPOHv2LJ988kmhIwkBAQGsW7eOcePGAbmr4YYPH05kZCSjR4/Od6kK4MMPP8zXlwsXLrxkTB999BEul4sBAwZw4sQJ9ysiIoLo6GhWr17tUT84OJg//vGP7vf+/v507tzZox+WLFlCixYtaN68uUebN910E0C+Nnv06EHLli09yhISEoiJiaF9+/busmrVqnH//fd71DObzdx///0sW7aMs2fPusvfffddunbtmm8BwuUsX74ci8XCQw895FH+8MMPYxgGn332GfD7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gOnTp1+FCK+OS32vivr7W5fYfEx0rWDWGxpBEhGR0nfgwAFWrFhBjx49yMrKYt68eezbt4/77rvP26H5HF1i8zFNawWzx6id++b4LtAAn4iIlBKz2cybb75Jp06d6NatG1u3bmXlypW0aNHC26H5HI0g+ZjoWkEcMMJxGBasjjQ48ytUqevtsEREpAKoW7duvhVoUjCNIPmY6sE2bH4W9hkRuQXHdcNIERGRq00Jkg+KDOSCy2w7vBuMiIhIJaQEyQdFBBjs1URtERERr1GC5IMiAg12u/ISJF1iExERudqUIPmgyABDK9lERES8SAmSD4oIhP1GBDmGGbJS4exRb4ckIiJSqShB8kHBVggJyl3uD2gekohIBXTDDTcwduxY9/sGDRowZ86cS+5jMplYunTpFR+7tNq5lClTptC+ffsyPUZZUoLko6JrBbHH0DwkERFfc9ttt9GnT58Ct3399deYTCZ+/PHHYre7fv16Ro4ceaXheSgsSTl69Ci33HJLqR6rolGC5KOiPe6orREkERFfMXz4cBITE/n111/zbVu4cCEdO3akbdu2xW63Zs2aBAYGlkaIlxUREYHNZrsqxyqvlCD5qCa1gtnjumCitoiI+IRbb72VmjVr8uabb3qUnzt3jiVLljB8+HB+++03Bg0aRO3atQkMDKRNmzb85z//uWS7F19i27NnD9dffz12u52WLVuSmJiYb5/HHnuMpk2bEhgYSKNGjZg0aRIOhwOAN998k6lTp7JlyxZMJhMmk8kd88WX2LZu3cpNN91EQEAA1atXZ+TIkZw7d869fejQocTFxTFz5kwiIyOpXr06Dz74oPtYReFyuZg2bRp16tTBZrPRvn17EhIS3Nuzs7MZNWoUkZGR2O126tevz4wZMwAwDIMpU6ZQr149bDYbUVFRPPTQQ0U+dknoUSM+qml4MIvzRpCO7chdyWYyeTcoEZGrwTDAkX71j2sNLNK/s35+fgwePJg333yTJ598EtP5fZYsWYLT6WTQoEGcO3eODh068NhjjxEaGsqnn37KAw88QOPGjencufNlj+FyubjrrrsIDw9n3bp1nDlzxmO+Up6QkBDefPNNoqKi2Lp1KyNGjMBqtTJx4kQGDhzItm3bSEhIYOXKlQCEhYXlayMtLY3Y2FhiYmJYv349x44d489//jOjRo3ySAJXr15NZGQkq1evZu/evQwcOJD27dszYsSIy54PwAsvvMCsWbN45ZVXuOaaa3jjjTe4/fbb+emnn4iOjmbu3LksW7aM999/n3r16nHo0CEOHToEwIcffsjzzz/Pe++9R6tWrUhOTmbLli1FOm5JKUHyUdG1gvnZiMJpmLBknoZzxyAk3NthiYiUPUc6/CPq6h/3iSPgH1Skqn/605947rnn+PLLL7nhhhuA3Mtrd999N2FhYYSFhfHII4+4648ePZrPP/+c999/v0gJ0sqVK9m5cyeff/45UVG5n8U//vGPfPOGJkyY4P5zgwYNePjhh1m0aBETJ04kICCA4OBg/Pz8iIiIKPRYixYtIjMzk7fffpugoNzznzdvHrfddhvPPPMM4eG5v3uqVq3KvHnzsFgsNG/enH79+rFq1aoiJ0gzZ87kscce49577wXgmWeeYfXq1cyZM4f58+dz8OBBoqOj6d69OyaTifr167v3PXjwIBEREfTs2ROr1Uq9evWK9DleCV1i81FhAVbCQkI4aNTKLdA8JBERn9G8eXO6du3KG2+8AcDevXv5+uuvGT58OABOp5Pp06fTpk0bqlWrRnBwMJ9//jkHDx4sUvs7duygbt267uQIICYmJl+9xYsX061bNyIiIggODmbixIkFzo263LHatWvnTo4AunXrhsvlYteu36d4tGrVCovF4n4fGRnJsWPHinSM1NRUjhw5Qrdu3TzKu3Xrxo4duY/UGjp0KJs3b6ZZs2Y89NBDrFixwl2vf//+ZGRk0KhRI0aMGMHHH39MTk5Osc6zuDSC5MOahoew90AdGpKSOw+pUQ9vhyQiUvasgbmjOd44bjEMHz6c0aNHM3/+fBYuXEjjxo3p0SP33+nnnnuOF154gTlz5tCmTRuCgoIYO3Ys2dnZpRZuUlIS999/P1OnTiU2NpawsDD+85//MGvWrFI7xoWsVqvHe5PJhMvlKrX2r732Wvbt28dnn33GypUrGTBgAD179uSDDz6gbt267Nq1i5UrV5KYmMjf/vY39wjexXGVFo0g+bDocK1kE5FKyGTKvdR1tV/FnOc5YMAAzGYzixYt4u233+ZPf/qTez7St99+yx133MEf//hH2rVrR6NGjdi9e3eR227RogWHDh3i6NHfbxT83XffedRZu3Yt9evX58knn6Rjx45ER0dz4MABjzr+/v44nc7LHmvLli2kpaW5y7799lvMZjPNmjUrcsyXEhoaSlRUFN9++61H+bfffkvLli096g0cOJDXXnuNxYsX8+GHH3Ly5EkAAgICuO2225g7dy5r1qwhKSmJrVu3lkp8BdEIkg9rGh7C91rJJiLik4KDgxk4cCDjx48nNTWVoUOHurdFR0fzwQcfsHbtWqpWrcrs2bNJSUnxSAYupWfPnjRt2pQhQ4bw3HPPkZqaypNPPulRJzo6moMHD/Lee+/RqVMnPv3003w3f2zQoAH79u1j8+bN1KlTh5CQkHzL+++//34mT57MkCFDmDJlCsePH2f06NE88MAD7vlHpWHcuHFMnjyZxo0b0759exYuXMjmzZt59913AZg9ezaRkZFcc801mM1mlixZQkREBFWqVOHNN9/E6XTSpUsXAgMDeeeddwgICPCYp1TaNILkw5pqBElExKcNHz6cU6dOERsb6zFfaMKECVx77bXExsZyww03EBERQVxcXJHbNZvNfPzxx2RkZNC5c2f+/Oc/8/TTT3vUuf322/n73//OqFGjaN++PWvXrvWYtA1w991306dPH2688UZq1qxZ4K0GAgMD+fzzzzl58iSdOnXinnvu4eabb2bevHnF+zAu46GHHiI+Pp6HH36YNm3akJCQwLJly4iOjgZyV+Q9++yzdOzYkU6dOrF//36WL1+O2WymSpUqvPbaa3Tr1o22bduycuVK/ve//1G9evVSjfFCJsPQk1BLIjU1lbCwMM6cOUNoaGiptetwOFi+fDl9+/YlPQf+MHUZO+x/yt047mcIqlFqx5KiubBPyupatxSd+sO3XGl/ZGZmsm/fPho2bIjdbi+DCCsXl8tFamoqoaGhmM2VdwzkUt+rov7+rryfXjkQFmAlLLQKh1w1cwt0mU1EROSqUILk4zwnau/wbjAiIiKVhBIkH9c0POSCBEkjSCIiIleDEiQflztRu07uG03UFhERuSqUIPm4puEhemitiFR4Wi8kpak0vk9KkHxcdHgIe/MusZ1LgfST3g1IRKQU5a18S0/3wsNppcLK+z5dyUpX3SjSxwXb/KhSpRqHM6pT2/QbnNgN9f7g7bBEREqFxWKhSpUq7md6BQYGuu9GLcXncrnIzs4mMzOzUi7zNwyD9PR0jh07RpUqVTyeHVdcSpDKgejwYPb+Upvalt9y5yEpQRKRCiTvSfNFffCpFM4wDDIyMggICKjUiWaVKlXc36uSUoJUDjQND2HPz7XpwY+ahyQiFY7JZCIyMpJatWrhcDi8HU655nA4+Oqrr7j++usr7Y1UrVbrFY0c5VGCVA5E1wrmB61kE5EKzmKxlMovtsrMYrGQk5OD3W6vtAlSaal8FyjLIY+VbMeUIImIiJQ1rydI8+fPp0GDBtjtdrp06cL3339/yfpLliyhefPm2O122rRpw/Llyz22f/TRR/Tu3Zvq1atjMpnYvHmzx/aTJ08yevRomjVrRkBAAPXq1eOhhx7izJkzpX1qpaZJreDfV7KdPQKZvhuriIhIReDVBGnx4sXEx8czefJkNm7cSLt27YiNjS10ot7atWsZNGgQw4cPZ9OmTcTFxREXF8e2bdvcddLS0ujevTvPPPNMgW0cOXKEI0eOMHPmTLZt28abb75JQkICw4cPL5NzLA1BNj9Cq9Yg2aiaW3B8t3cDEhERqeC8Ogdp9uzZjBgxgmHDhgGwYMECPv30U9544w0ef/zxfPVfeOEF+vTpw7hx4wCYPn06iYmJzJs3jwULFgDwwAMPALB///4Cj9m6dWs+/PBD9/vGjRvz9NNP88c//pGcnBz8/HxzWlbeRO0Iy6nceUh1O3k7JBERkQrLa9lAdnY2GzZsYPz48e4ys9lMz549SUpKKnCfpKQk4uPjPcpiY2NZunTpFcVy5swZQkNDL5kcZWVlkZWV5X6fmpoK5K4YKM1VF3ltXdxm4xqB7N1bm+vYhjNlOy6t9LhqCusT8Q71h29Rf/gW9cflFfWz8VqCdOLECZxOJ+Hh4R7l4eHh7NxZ8ETk5OTkAusnJydfURzTp09n5MiRl6w3Y8YMpk6dmq98xYoVBAYGlvj4hUlMTPR4n37c5H4m24kd3/Bd9vKCdpMydHGfiHepP3yL+sO3qD8KV9S7tvvm9aSrJDU1lX79+tGyZUumTJlyybrjx4/3GL1KTU2lbt269O7dm9DQ0FKLyeFwkJiYSK9evTyWaNY7nMo/XtkDQC3TKfr27Vtqx5RLK6xPxDvUH75F/eFb1B+Xl3cF6HK8liDVqFEDi8VCSkqKR3lKSkqhd7+MiIgoVv1LOXv2LH369CEkJISPP/74sl8km82GzWbLV261WsvkS3hxu82jqrCX3JVspjOHsLqywBZc6seVwpVVX0vJqD98i/rDt6g/ClfUz8Vrq9j8/f3p0KEDq1atcpe5XC5WrVpFTExMgfvExMR41IfcYcTC6hcmNTWV3r174+/vz7Jly7Db7cU/gasswN9CaLVwjhvnR6tOaCWbiIhIWfHqJbb4+HiGDBlCx44d6dy5M3PmzCEtLc29qm3w4MHUrl2bGTNmADBmzBh69OjBrFmz6NevH++99x4//PADr776qrvNkydPcvDgQY4cOQLArl25j+aIiIggIiLCnRylp6fzzjvvkJqa6h5uq1mzpk/fxTW6Vgh7U+tQ07I9dyVb7Wu9HZKIiEiF5NUEaeDAgRw/fpxJkyaRnJxM+/btSUhIcE/EPnjwoMfTiLt27cqiRYuYMGECTzzxBNHR0SxdupTWrVu76yxbtsydYAHce++9AEyePJkpU6awceNG1q1bB0CTJk084tm3bx8NGjQoq9O9Yk3Dg9mzpzYxbNcjR0RERMqQ1ydpjxo1ilGjRhW4bc2aNfnK+vfvT//+/Qttb+jQoQwdOrTQ7TfccAOGYRQ3TJ/QNDyEDXl31NZDa0VERMqM1x81IkUXHR7sXupvaARJRESkzChBKkca1wzm57wRpFMHILto93IQERGR4lGCVI7YrRaCq0Vy0gjGhAG/7fF2SCIiIhWSEqRyJjo8xH2ZTfOQREREyoYSpHKmaXgIe115E7U1D0lERKQsKEEqZ3Inamslm4iISFlSglTONA0PcSdIxrEdXo5GRESkYlKCVM40qhnEL5yfg3RqHzgyvRuQiIhIBaQEqZyx+VkIrFabVCMQk+GC3/Z6OyQREZEKRwlSOdQ0IpTd7pVsmqgtIiJS2pQglUPR4SHscWmitoiISFlRglQONQ0PZq+hpf4iIiJlRQlSOeSxkk0jSCIiIqVOCVI51KB6EPuom/vm5M+Qk+3dgERERCoYJUjlkL+fGXv1upwz7JhcOXDyF2+HJCIiUqEoQSqnmkaEah6SiIhIGVGCVE5FhwdfsJJNCZKIiEhpUoJUTl04UVsJkoiISOlSglRONQ0Pdt8sUivZRERESpcSpHKqfvUgDpjOr2Q7sQecOd4NSEREpAJRglROWS1m7DXqk27YMLkcuQ+uFRERkVKhBKkcaxIRxl4jKveN5iGJiIiUGiVI5VjTWsGaqC0iIlIGlCCVY9HhIex15U7U1kNrRURESo8SpHKsaXjwBc9k0wiSiIhIaVGCVI7Vrx7EfnPuSjbj+B5wOb0ckYiISMWgBKkcs5hN2Go0JNOwYnZmwqn93g5JRESkQlCCVM41iQjjZ/dKNs1DEhERKQ1KkMo5PXJERESk9ClBKueiawWzRyvZRERESpUSpHKuaXgIe7WSTUREpFQpQSrn6lYL5KAlbyXbLnC5vByRiIhI+acEqZyzmE1YazYm27BgzsmAM4e8HZKIiEi5pwSpAmgSXoVftJJNRESk1ChBqgCiL5iHxPEd3g1GRESkAlCCVAE0DQ9mjysvQdIIkoiIyJVSglQBNA0PYbeRu9TfOKaVbCIiIlfK6wnS/PnzadCgAXa7nS5duvD9999fsv6SJUto3rw5drudNm3asHz5co/tH330Eb1796Z69eqYTCY2b96cr43MzEwefPBBqlevTnBwMHfffTcpKSmleVpXVe0qARyy1APOL/U3DC9HJCIiUr55NUFavHgx8fHxTJ48mY0bN9KuXTtiY2M5duxYgfXXrl3LoEGDGD58OJs2bSIuLo64uDi2bdvmrpOWlkb37t155plnCj3u3//+d/73v/+xZMkSvvzyS44cOcJdd91V6ud3tZjNJvxrNcZhWDA70iD1sLdDEhERKde8miDNnj2bESNGMGzYMFq2bMmCBQsIDAzkjTfeKLD+Cy+8QJ8+fRg3bhwtWrRg+vTpXHvttcybN89d54EHHmDSpEn07NmzwDbOnDnD66+/zuzZs7npppvo0KEDCxcuZO3atXz33Xdlcp5XQ8Pwauw3InLf6IaRIiIiV8RrCVJ2djYbNmzwSGTMZjM9e/YkKSmpwH2SkpLyJT6xsbGF1i/Ihg0bcDgcHu00b96cevXqFasdX9M0PPiCZ7JporaIiMiV8PPWgU+cOIHT6SQ8PNyjPDw8nJ07Cx4BSU5OLrB+cnJykY+bnJyMv78/VapUKVY7WVlZZGVlud+npqYC4HA4cDgcRT7+5eS1Vdw2G9UIYPv5BMmVsh1nKcZU2ZW0T6RsqD98i/rDt6g/Lq+on43XEqTyZsaMGUydOjVf+YoVKwgMDCz14yUmJhar/sks2Ht+qf+p3ev4xrT8MntIcRW3T6RsqT98i/rDt6g/Cpeenl6kel5LkGrUqIHFYsm3eiwlJYWIiIgC94mIiChW/cLayM7O5vTp0x6jSJdrZ/z48cTHx7vfp6amUrduXXr37k1oaGiRj385DoeDxMREevXqhdVqLfJ+hmGwbFvuCFiVnGT63nILmEylFldlVtI+kbKh/vAt6g/fov64vLwrQJfjtQTJ39+fDh06sGrVKuLi4gBwuVysWrWKUaNGFbhPTEwMq1atYuzYse6yxMREYmJiinzcDh06YLVaWbVqFXfffTcAu3bt4uDBg5dsx2azYbPZ8pVbrdYy+RKWpF2/Wk1xHjdhyT6LJfM3CI0s9bgqs7LqaykZ9YdvUX/4FvVH4Yr6uXj1Elt8fDxDhgyhY8eOdO7cmTlz5pCWlsawYcMAGDx4MLVr12bGjBkAjBkzhh49ejBr1iz69evHe++9xw8//MCrr77qbvPkyZMcPHiQI0eOALnJD+SOHEVERBAWFsbw4cOJj4+nWrVqhIaGMnr0aGJiYvjDH/5wlT+B0tUwohr7j0XQ2HQ0dyWbEiQREZES8WqCNHDgQI4fP86kSZNITk6mffv2JCQkuCdiHzx4ELP594V2Xbt2ZdGiRUyYMIEnnniC6Oholi5dSuvWrd11li1b5k6wAO69914AJk+ezJQpUwB4/vnnMZvN3H333WRlZREbG8tLL710Fc64bDU9/0y2xhzNXcnW+EZvhyQiIlIueX2S9qhRowq9pLZmzZp8Zf3796d///6Ftjd06FCGDh16yWPa7Xbmz5/P/PnzixOqz4sOD2GrUZtYftC9kERERK6A1x81IqXnwofWuvRMNhERkRJTglSBRITaOWKtD4BxbIeeySYiIlJCSpAqEJPJhKVWNC7DhCXrNKSd8HZIIiIi5ZISpAqmQURNDhk1c99oHpKIiEiJKEGqYKLDQy54JpsSJBERkZJQglTBNA0PZq9RJ/eNEiQREZESUYJUwTQND2G3VrKJiIhcESVIFUytEBtH/HNXsilBEhERKRklSBWMyWTCWqsZAH4ZJyDtNy9HJCIiUv4oQaqA6kbW4lejRu6bE7u8G4yIiEg5pASpAmpa6/c7amuitoiISPEpQaqAmoaHsMe9kk0jSCIiIsWlBKkCuvBeSM5jO7wcjYiISPmjBKkCqhHsT0reSrYUJUgiIiLFpQSpAjKZTJhqNQfAmn4MMk55OSIREZHyRQlSBVU3MpwjRrXcN8d3ezcYERGRckYJUgXVNDyEvVrJJiIiUiJKkCqo6FpaySYiIlJSSpAqqKbhwVrJJiIiUkJKkCqo6sE2jtkaAOBM0SU2ERGR4lCCVIGZzz+TzT/tCGSmejkaERGR8kMJUgVWOzKKY0aV3Dcn9ng1FhERkfJECVIFFh0ecsEz2TQPSUREpKiUIFVgTS945IiW+ouIiBSdEqQKLHclW+5S/xxN1BYRESkyJUgVWJVAf47bGwDg1DPZREREikwJUgWX90w227lfITvNy9GIiIiUD0qQKrjIyDqcMEJz35zQM9lERESKQglSBdc0PIS97onaeuSIiIhIUShBquCahgdfsNRfE7VFRESKQglSBRd9wVJ/R7ImaouIiBSFEqQKLizAyomAhoBWsomIiBSVEqRKwJy3ku3sQXBkeDkaERER36cEqRIIj6zHKSMYE4aeySYiIlIESpAqgaYRFz5yRCvZRERELkcJUiUQHR7CXq1kExERKTIlSJVAdK3g31eyaaK2iIjIZSlBqgRC7FZOBuauZMvRUn8REZHL8nqCNH/+fBo0aIDdbqdLly58//33l6y/ZMkSmjdvjt1up02bNixfvtxju2EYTJo0icjISAICAujZsyd79nhOTN69ezd33HEHNWrUIDQ0lO7du7N69epSPzdfYqrZAgDb2QOQk+XlaERERHybVxOkxYsXEx8fz+TJk9m4cSPt2rUjNjaWY8eOFVh/7dq1DBo0iOHDh7Np0ybi4uKIi4tj27Zt7jrPPvssc+fOZcGCBaxbt46goCBiY2PJzMx017n11lvJycnhiy++YMOGDbRr145bb72V5OTkMj9nb6kZVZ9UIwCz4YTffvZ2OCIiIj7NqwnS7NmzGTFiBMOGDaNly5YsWLCAwMBA3njjjQLrv/DCC/Tp04dx48bRokULpk+fzrXXXsu8efOA3NGjOXPmMGHCBO644w7atm3L22+/zZEjR1i6dCkAJ06cYM+ePTz++OO0bduW6Oho/vnPf5Kenu6RaFU00RGhFzyTTZfZRERELsXPWwfOzs5mw4YNjB8/3l1mNpvp2bMnSUlJBe6TlJREfHy8R1lsbKw7+dm3bx/Jycn07NnTvT0sLIwuXbqQlJTEvffeS/Xq1WnWrBlvv/021157LTabjVdeeYVatWrRoUOHQuPNysoiK+v3S1OpqakAOBwOHA5Hsc+/MHltlWabAI2qB7DHVYdrzXtxJm/H1ez2Um2/IiurPpGSUX/4FvWHb1F/XF5RPxuvJUgnTpzA6XQSHh7uUR4eHs7OnQUvRU9OTi6wft6lsbyfl6pjMplYuXIlcXFxhISEYDabqVWrFgkJCVStWrXQeGfMmMHUqVPzla9YsYLAwMDLnG3xJSYmlmp7WU7YfX4E6fCPX7IprW2ptl8ZlHafyJVRf/gW9YdvUX8ULj09vUj1vJYgeYthGDz44IPUqlWLr7/+moCAAP71r39x2223sX79eiIjIwvcb/z48R6jV6mpqdStW5fevXsTGhpaavE5HA4SExPp1asXVqu11NoFeGzHbnBADdMp+vbtW6ptV2Rl2SdSfOoP36L+8C3qj8vLuwJ0OV5LkGrUqIHFYiElJcWjPCUlhYiIiAL3iYiIuGT9vJ8pKSkeiU5KSgrt27cH4IsvvuCTTz7h1KlT7sTmpZdeIjExkbfeeovHH3+8wGPbbDZsNlu+cqvVWiZfwrJo11SrBRwGe+p+zGbAor88xVFWfS0lo/7wLeoP36L+KFxRPxevTdL29/enQ4cOrFq1yl3mcrlYtWoVMTExBe4TExPjUR9yhxHz6jds2JCIiAiPOqmpqaxbt85dJ29ozWz2PHWz2YzL5bryE/NhNWo34pxhx2zkwMlfvB2OiIiIz/LqKrb4+Hhee+013nrrLXbs2MFf//pX0tLSGDZsGACDBw/2mMQ9ZswYEhISmDVrFjt37mTKlCn88MMPjBo1CsidXzR27Fieeuopli1bxtatWxk8eDBRUVHExcUBuUlW1apVGTJkCFu2bGH37t2MGzeOffv20a9fv6v+GVxNTcND2WtE5b7RI0dEREQK5dU5SAMHDuT48eNMmjSJ5ORk2rdvT0JCgnuS9cGDBz1Gerp27cqiRYuYMGECTzzxBNHR0SxdupTWrVu76zz66KOkpaUxcuRITp8+Tffu3UlISMButwO5l/YSEhJ48sknuemmm3A4HLRq1Yr//ve/tGvX7up+AFdZ0/AQdhl1aM8vemitiIjIJXh9kvaoUaPcI0AXW7NmTb6y/v37079//0LbM5lMTJs2jWnTphVap2PHjnz++efFjrW8a1IrmE/Pr2TLOrqd/DOqREREBHzgUSNy9QT4WzgV1AiAnOTtXo5GRETEdylBqmRMNZsBYD/zCzhzvByNiIiIb1KCVMlUrR1NhuGPxXDAqf3eDkdERMQnKUGqZJpGaCWbiIjI5ShBqmSia4Wwx6gDgKEESUREpEBKkCqZJrWC+fmClWwiIiKSnxKkSsZutXDavZJNI0giIiIFUYJUGdVqDoD9zF5wOb0cjIiIiO8pUYJ06NAhfv31V/f777//nrFjx/Lqq6+WWmBSdqrVjibLsOLnyoLTB70djoiIiM8pUYJ03333sXr1agCSk5Pp1asX33//PU8++eQl72AtvqFJRBV+MSJz32iitoiISD4lSpC2bdtG586dAXj//fdp3bo1a9eu5d133+XNN98szfikDDQND2HP+YnaxjElSCIiIhcrUYLkcDiw2XKf5LVy5Upuv/12AJo3b87Ro0dLLzopE41qBrH3/FL/TK1kExERyadECVKrVq1YsGABX3/9NYmJifTp0weAI0eOUL169VINUEqfzc/CmeDGAOQk7/ByNCIiIr6nRAnSM888wyuvvMINN9zAoEGDaNeuHQDLli1zX3oTH1fzwpVsLi8HIyIi4lv8SrLTDTfcwIkTJ0hNTaVq1aru8pEjRxIYGFhqwUnZqVq7KdkHLfg7MyD1V6hSz9shiYiI+IwSjSBlZGSQlZXlTo4OHDjAnDlz2LVrF7Vq1SrVAKVsNI6syj73SrZd3g1GRETEx5QoQbrjjjt4++23ATh9+jRdunRh1qxZxMXF8fLLL5dqgFI2PFeyaR6SiIjIhUqUIG3cuJHrrrsOgA8++IDw8HAOHDjA22+/zdy5c0s1QCkbDWsE8Qu5K9kyjmglm4iIyIVKlCClp6cTEhICwIoVK7jrrrswm8384Q9/4MCBA6UaoJQNfz/zBSvZlCCJiIhcqEQJUpMmTVi6dCmHDh3i888/p3fv3gAcO3aM0NDQUg1QylDNZgDYT+8Fw/ByMCIiIr6jRAnSpEmTeOSRR2jQoAGdO3cmJiYGyB1Nuuaaa0o1QCk7obVbkGOY8XemQeoRb4cjIiLiM0q0zP+ee+6he/fuHD161H0PJICbb76ZO++8s9SCk7IVHVWN/UYETUxHcp/JFlbb2yGJiIj4hBIlSAARERFERETw66+/AlCnTh3dJLKcaRoezB6jNk04gnF8J6YmN3s7JBEREZ9QoktsLpeLadOmERYWRv369alfvz5VqlRh+vTpuHRX5nKjfvXfV7KlHf7Jy9GIiIj4jhKNID355JO8/vrr/POf/6Rbt24AfPPNN0yZMoXMzEyefvrpUg1SyobVYiY1uDFkQE7yTm+HIyIi4jNKlCC99dZb/Otf/+L22293l7Vt25batWvzt7/9TQlSeVKrGRwA++k9uSvZTCZvRyQiIuJ1JbrEdvLkSZo3b56vvHnz5pw8efKKg5KrJ7R2C5yGCXtOKpw75u1wREREfEKJEqR27doxb968fOXz5s2jbdu2VxyUXD2No2pw0Dj//LzjuswmIiICJbzE9uyzz9KvXz9WrlzpvgdSUlIShw4dYvny5aUaoJSt6PAQ9hp1aEgKrmM7MDfq4e2QREREvK5EI0g9evRg9+7d3HnnnZw+fZrTp09z11138dNPP/Hvf/+7tGOUMlS/WiA/n1/Jlq6VbCIiIsAV3AcpKioq32TsLVu28Prrr/Pqq69ecWBydfhZzKSGNIZ0cCTv8HY4IiIiPqFEI0hSwdTMnXBvP73Hy4GIiIj4BiVIQmidlrgMEwGO05B2wtvhiIiIeJ0SJKFRVE1+NWrkvtFKNhERkeLNQbrrrrsuuf306dNXEot4SdPwEPYYdajHcVzHdmJu0N3bIYmIiHhVsRKksLCwy24fPHjwFQUkV1/daoGsNNUBNnHu0DZC9cxhERGp5IqVIC1cuLCs4hAvsphNnA1pDGngSNFKNhEREc1BklznV7IFnNJKNhEREa8nSPPnz6dBgwbY7Xa6dOnC999/f8n6S5YsoXnz5tjtdtq0aZPvzt2GYTBp0iQiIyMJCAigZ8+e7NmT/5f+p59+SpcuXQgICKBq1arExcWV5mmVO8F1WgIQ6PgN0vU8PRERqdy8miAtXryY+Ph4Jk+ezMaNG2nXrh2xsbEcO1bwQ1PXrl3LoEGDGD58OJs2bSIuLo64uDi2bdvmrvPss88yd+5cFixYwLp16wgKCiI2NpbMzEx3nQ8//JAHHniAYcOGsWXLFr799lvuu+++Mj9fX9YwKuKClWy7vBuMiIiIl3k1QZo9ezYjRoxg2LBhtGzZkgULFhAYGMgbb7xRYP0XXniBPn36MG7cOFq0aMH06dO59tpr3Q/ONQyDOXPmMGHCBO644w7atm3L22+/zZEjR1i6dCkAOTk5jBkzhueee46//OUvNG3alJYtWzJgwICrddo+qWl4CHtdtQFwHdNSfxERqdxK/KiRK5Wdnc2GDRsYP368u8xsNtOzZ0+SkpIK3CcpKYn4+HiPstjYWHfys2/fPpKTk+nZs6d7e1hYGF26dCEpKYl7772XjRs3cvjwYcxmM9dccw3Jycm0b9+e5557jtatWxcab1ZWFllZWe73qampADgcDhwOR7HPvzB5bZVmm0URHuzHKlMdbmALZw78SHD7q3t8X+atPpGCqT98i/rDt6g/Lq+on43XEqQTJ07gdDoJDw/3KA8PD2fnzoJHMJKTkwusn5yc7N6eV1ZYnV9++QWAKVOmMHv2bBo0aMCsWbO44YYb2L17N9WqVSvw2DNmzGDq1Kn5ylesWEFgYODlTrfYEhMTS73Ny0mxRIEBJ/d+z1cXze0S7/SJFE794VvUH75F/VG49PT0ItXzWoLkLS6XC4Ann3ySu+++G8i9fUGdOnVYsmQJ//d//1fgfuPHj/cYvUpNTaVu3br07t2b0NDQUovP4XCQmJhIr169sFqtpdZuUew7mQoHoJbrGH379r2qx/Zl3uwTyU/94VvUH75F/XF5eVeALsdrCVKNGjWwWCykpKR4lKekpBAREVHgPhEREZesn/czJSWFyMhIjzrt27cHcJe3bNnSvd1ms9GoUSMOHjxYaLw2mw2bzZav3Gq1lsmXsKzavZTQum3gAIRkHwNnOtgvfWPQysYbfSKFU3/4FvWHb1F/FK6on4vXJmn7+/vToUMHVq1a5S5zuVysWrWKmJiYAveJiYnxqA+5w4h59Rs2bEhERIRHndTUVNatW+eu06FDB2w2G7t2/b5Sy+FwsH//furXr19q51ceNawTRbJRNffN8d3eDUZERMSLvHqJLT4+niFDhtCxY0c6d+7MnDlzSEtLY9iwYQAMHjyY2rVrM2PGDADGjBlDjx49mDVrFv369eO9997jhx9+4NVXXwXAZDIxduxYnnrqKaKjo2nYsCETJ04kKirKfZ+j0NBQ/vKXvzB58mTq1q1L/fr1ee655wDo37//1f8QfEh0eDB7XLWJsJwiJ2U7fnU7eTskERERr/BqgjRw4ECOHz/OpEmT3KvJEhIS3JOsDx48iNn8+yBX165dWbRoERMmTOCJJ54gOjqapUuXeqw+e/TRR0lLS2PkyJGcPn2a7t27k5CQgN1ud9d57rnn8PPz44EHHiAjI4MuXbrwxRdfULVq1at38j6odpUAVpvrch3bOHtoG1U7ejsiERER7/D6JO1Ro0YxatSoAretWbMmX1n//v0vOdJjMpmYNm0a06ZNK7SO1Wpl5syZzJw5s9jxVmQmk4nUkCZwDhzJeiabiIhUXl5/1Ij4mBrNALCf1jPZRESk8lKCJB5C6rYCIDQrGbLOejkaERER71CCJB7q1anDceP88v4TWskmIiKVkxIk8dA0PIQ955/JlpOsZ7KJiEjlpARJPESG2TlgrgtA6qGtXo5GRETEO5QgiYfclWyNAa1kExGRyksJkuRXozkAtlOagyQiIpWTEiTJJ8i9ku0oZKd5ORoREZGrTwmS5FOvbn1+M0IwY8AJ3Q9JREQqHyVIkk+ziBD2Grkr2RwpmockIiKVjxIkyadWiM29ku3MAa1kExGRykcJkuRjMpk4q5VsIiJSiSlBkgIZeSvZ9Ew2ERGphJQgSYGCz69kq5J5GByZXo5GRETk6lKCJAWqW7chZ4xAzLjgt73eDkdEROSqUoIkBYqOCGGPUQeA7OTtXo5GRETk6lKCJAWqGWzjoFayiYhIJaUESQqU+0y2JoBWsomISOWjBEkKZdRsBoDtlFayiYhI5aIESQoVXKc1AFUyD0JOtpejERERuXqUIEmhatdrxFkjAAsuOPmzt8MRERG5apQgSaGaRYS6n8mWdVQr2UREpPJQgiSFqh5s46AldyXbaa1kExGRSkQJklxS3jPZsrWSTUREKhElSHJJRo3clWz2U7u9HImIiMjVowRJLino/Eq2qhkHwenwcjQiIiJXhxIkuaTa9aNJM2z4kQMn93k7HBERkatCCZJcUtOIMPdKtsyjP3k5GhERkatDCZJcUtUgfw5Z6gFwar9WsomISOWgBEku62xII0DPZBMRkcpDCZJcllGjOQC203omm4iIVA5KkOSyguq0AqBa+n5wOb0bjIiIyFWgBEkuK6pBMzINK1YccGq/t8MREREpc0qQ5LKaRlThZyMKgIwjWskmIiIVnxIkuaywQCuH/PJWsv3o5WhERETKnhIkKZLUkCaAnskmIiKVgxIkKZK8Z7LZTmklm4iIVHw+kSDNnz+fBg0aYLfb6dKlC99///0l6y9ZsoTmzZtjt9tp06YNy5cv99huGAaTJk0iMjKSgIAAevbsyZ49Bf9iz8rKon379phMJjZv3lxap1ThBNc+v5ItYz+4XN4NRkREpIx5PUFavHgx8fHxTJ48mY0bN9KuXTtiY2M5duxYgfXXrl3LoEGDGD58OJs2bSIuLo64uDi2bdvmrvPss88yd+5cFixYwLp16wgKCiI2NpbMzMx87T366KNERUWV2flVFBENW5Bl+GEzsuDMQW+HIyIiUqa8niDNnj2bESNGMGzYMFq2bMmCBQsIDAzkjTfeKLD+Cy+8QJ8+fRg3bhwtWrRg+vTpXHvttcybNw/IHT2aM2cOEyZM4I477qBt27a8/fbbHDlyhKVLl3q09dlnn7FixQpmzpxZ1qdZ7kVHVuEXIxKAtMNaySYiIhWbVxOk7OxsNmzYQM+ePd1lZrOZnj17kpSUVOA+SUlJHvUBYmNj3fX37dtHcnKyR52wsDC6dOni0WZKSgojRozg3//+N4GBgaV5WhVSqN3Kr1rJJiIilYSfNw9+4sQJnE4n4eHhHuXh4eHs3LmzwH2Sk5MLrJ+cnOzenldWWB3DMBg6dCh/+ctf6NixI/v3779srFlZWWRlZbnfp6amAuBwOHA4HJfdv6jy2irNNktLanAjSP2WrCPbfTK+suLLfVIZqT98i/rDt6g/Lq+on41XEyRvefHFFzl79izjx48v8j4zZsxg6tSp+cpXrFhRJiNQiYmJpd7mlTrqrAqAKWVbvonxlYEv9kllpv7wLeoP36L+KFx6enqR6nk1QapRowYWi4WUlBSP8pSUFCIiIgrcJyIi4pL1836mpKQQGRnpUad9+/YAfPHFFyQlJWGz2Tza6dixI/fffz9vvfVWvuOOHz+e+Ph49/vU1FTq1q1L7969CQ0NLeIZX57D4SAxMZFevXphtVpLrd3S8HlQMHwzlyjXEerecguYTN4O6arw5T6pjNQfvkX94VvUH5eXdwXocryaIPn7+9OhQwdWrVpFXFwcAC6Xi1WrVjFq1KgC94mJiWHVqlWMHTvWXZaYmEhMTAwADRs2JCIiglWrVrkTotTUVNatW8df//pXAObOnctTTz3l3v/IkSPExsayePFiunTpUuBxbTZbvoQKwGq1lsmXsKzavRK1m7TB8bUFO5mQngJV6no7pKvKF/ukMlN/+Bb1h29RfxSuqJ+L1y+xxcfHM2TIEDp27Ejnzp2ZM2cOaWlpDBs2DIDBgwdTu3ZtZsyYAcCYMWPo0aMHs2bNol+/frz33nv88MMPvPrqqwCYTCbGjh3LU089RXR0NA0bNmTixIlERUW5k7B69ep5xBAcHAxA48aNqVOnzlU68/InOrIa+4wImpoOk/brTwRVsgRJREQqD68nSAMHDuT48eNMmjSJ5ORk2rdvT0JCgnuS9cGDBzGbf19s17VrVxYtWsSECRN44okniI6OZunSpbRu3dpd59FHHyUtLY2RI0dy+vRpunfvTkJCAna7/aqfX0USbPPjV796NHUd5rcDPxLUuo+3QxIRESkTXk+QAEaNGlXoJbU1a9bkK+vfvz/9+/cvtD2TycS0adOYNm1akY7foEEDDMMoUt3K7mxIYziTRPbR7d4ORUREpMx4/UaRUr7kPZPNX89kExGRCkwJkhRLYJ3cS5nV0/eBRt1ERKSCUoIkxRLZqBVOw0SQkQZnk70djoiISJlQgiTF0jiyOvuN3HtNpR7a6uVoREREyoYSJCmWQH8/Dltzb5NwUs9kExGRCkoJkhRbanBjAK1kExGRCksJkhSbq0ZzQCvZRESk4lKCJMUWVKclADXSf9FKNhERqZCUIEmxRTRqi8swEWycg7Tj3g5HRESk1ClBkmJrFFmDg9QC4MxBrWQTEZGKRwmSFFuAv4XDfrkr2X7TSjYREamAlCBJieStZMs6opVsIiJS8ShBkhIxauY+k812areXIxERESl9SpCkRIJqtwKgesY+L0ciIiJS+pQgSYnUatQOgDDXGYxzWskmIiIVixIkKZGGUTU5ZNQE4PTBbV6ORkREpHQpQZISsVsvWMm2T0v9RUSkYlGCJCXmXsmWrJVsIiJSsShBkhJz1dBKNhERqZiUIEmJBdbJXclWLV0r2UREpGJRgiQlFtG4LQDVXCcx0k95ORoREZHSowRJSqx+VARHjWoAnNyvidoiIlJxKEGSErP5WTjsVx+A3/Zv8XI0IiIipUcJklyRMyHnV7Id3eHlSEREREqPEiS5Iq7quSvZ/LWSTUREKhAlSHJFgs6vZKuulWwiIlKBKEGSKxJ+fiVbDdcJjMwzXo5GRESkdChBkitSr3ZtUowqABzfp2eyiYhIxaAESa6I1WLWSjYREalwlCDJFUsNaQRA9lE9k01ERCoGJUhyxdwr2U5qJZuIiFQMSpDkigXW1jPZRESkYlGCJFesVpP2AIS7juHKPOvdYEREREqBEiS5YvVq1+GEEQbAsX16JpuIiJR/SpDkivlZzBy21gPg5P4fvRyNiIjIlVOCJKUiNVjPZBMRkYpDCZKUCleNpgBYtZJNREQqACVIUiq0kk1ERCoSn0iQ5s+fT4MGDbDb7XTp0oXvv//+kvWXLFlC8+bNsdvttGnThuXLl3tsNwyDSZMmERkZSUBAAD179mTPnj3u7fv372f48OE0bNiQgIAAGjduzOTJk8nOzi6T86sMajVuD0CEMxlXVrp3gxEREblCXk+QFi9eTHx8PJMnT2bjxo20a9eO2NhYjh07VmD9tWvXMmjQIIYPH86mTZuIi4sjLi6Obdt+fw7Ys88+y9y5c1mwYAHr1q0jKCiI2NhYMjMzAdi5cycul4tXXnmFn376ieeff54FCxbwxBNPXJVzrojq1K7HKSMYs8kgWSvZRESknPN6gjR79mxGjBjBsGHDaNmyJQsWLCAwMJA33nijwPovvPACffr0Ydy4cbRo0YLp06dz7bXXMm/ePCB39GjOnDlMmDCBO+64g7Zt2/L2229z5MgRli5dCkCfPn1YuHAhvXv3plGjRtx+++088sgjfPTRR1frtCscywUr2X7bp5VsIiJSvvl58+DZ2dls2LCB8ePHu8vMZjM9e/YkKSmpwH2SkpKIj4/3KIuNjXUnP/v27SM5OZmePXu6t4eFhdGlSxeSkpK49957C2z3zJkzVKtWrdBYs7KyyMrKcr9PTU0FwOFw4HA4Ln2ixZDXVmm2ebWcDmoMZ7aTeXhbuYy/MOW5Tyoi9YdvUX/4FvXH5RX1s/FqgnTixAmcTifh4eEe5eHh4ezcubPAfZKTkwusn5yc7N6eV1ZYnYvt3buXF198kZkzZxYa64wZM5g6dWq+8hUrVhAYGFjofiWVmJhY6m2WtWxn7s0iXUe35psXVhGUxz6pyNQfvkX94VvUH4VLTy/aPFmvJki+4PDhw/Tp04f+/fszYsSIQuuNHz/eY+QqNTWVunXr0rt3b0JDQ0stHofDQWJiIr169cJqtZZau1fD5i+z4Zt3qG0kc23fvt4Op9SU5z6piNQfvkX94VvUH5eXdwXocryaINWoUQOLxUJKSopHeUpKChEREQXuExERccn6eT9TUlKIjIz0qNO+fXuP/Y4cOcKNN95I165defXVVy8Zq81mw2az5Su3Wq1l8iUsq3bLUmT0tfANRDqPgOHE4m/3dkilqjz2SUWm/vAt6g/fov4oXFE/F69O0vb396dDhw6sWrXKXeZyuVi1ahUxMTEF7hMTE+NRH3KHEvPqN2zYkIiICI86qamprFu3zqPNw4cPc8MNN9ChQwcWLlyI2ez1+erlXlSdhqQagVhMBkd/2Xb5HURERHyU1y+xxcfHM2TIEDp27Ejnzp2ZM2cOaWlpDBs2DIDBgwdTu3ZtZsyYAcCYMWPo0aMHs2bNol+/frz33nv88MMP7hEgk8nE2LFjeeqpp4iOjqZhw4ZMnDiRqKgo4uLigN+To/r16zNz5kyOHz/ujqewkSu5PPP5lWyhOTv5bf+P1Gne0dshiYiIlIjXE6SBAwdy/PhxJk2aRHJyMu3btychIcE9yfrgwYMeoztdu3Zl0aJFTJgwgSeeeILo6GiWLl1K69at3XUeffRR0tLSGDlyJKdPn6Z79+4kJCRgt+de8klMTGTv3r3s3buXOnXqeMRjGMZVOOuK60xwYzi9k6wj270dioiISIl5PUECGDVqFKNGjSpw25o1a/KV9e/fn/79+xfanslkYtq0aUybNq3A7UOHDmXo0KElCVUuw1W9GZz+VM9kExGRck0Tb6RUBdZpCUC19F+8HImIiEjJKUGSUlWrUXsAopxHyMnO9G4wIiIiJaQESUpVRJ3GpBl2rCYnh3/RPCQRESmflCBJqTJf8Ey2k/u2eDkaERGRklGCJKXuTHBjADKP7vByJCIiIiWjBElKnbN6UwCsp7SSTUREyiclSFLqAmu3AqBamlayiYhI+aQESUpdrcbtAKjjPIzDke3laERERIpPCZKUuvC60WQY/vibcjj8i+YhiYhI+aMESUqdyWzhyPmVbId3fu/laERERIpPCZKUiTNVcu+ofc3GJ0l4dTxnzqV7OSIREZGiU4IkZSJ64NP8HNCWQFMWfY68xImZnflq5X/1MGARESkXlCBJmQipWY/Gj37F3q7PctoUSmMOcf03g/ny2f78cuCAt8MTERG5JCVIUnZMJpr0/j8C/76JnyLvBOCGjESqvRHDirf/SWa2w8sBioiIFEwJkpQ5/9AatPq/N0np/wkHrY2oYkqj9y8z2PvPrqxPWuPt8ERERPJRgiRXTXir66j7+PfsaDeeNOy0du3m2oQ4vnh+GMnHjnk7PBERETclSHJVmSxWWtz5OKZR69le9WYsJoObznyEeX5nvvjgZXJynN4OUURERAmSeEdgjXq0HPMRB/u+wxFLFLVMp7hp2+Ns+efNbPtxo7fDExGRSk4JknhVvc63EfHYRrZG/40srHTI2UT0h71Z+dJYTqemejs8ERGppJQgideZ/QNoc/8M0od/za7gzthMDnoeW8jZ2Z34+rP3dO8kERG56pQgic+oWrcFzR5ewZ4e8zhhqkZdkrlu3f/x3TO38svPu70dnoiIVCJKkMS3mExE3/gAYeM28WOd+3AaJmIyv6HW29exauFkMjKzvB2hiIhUAkqQxCdZA6vQ9s8vc+L+Fey1tSTYlMnNB+bw6zOdWf9VgrfDExGRCk4Jkvi08KadafLYt2zv+BRnCCba2E+nLwby1axBHD162NvhiYhIBaUESXyf2UzLW0djHbOBH2veCsD1Z5djX9CF1e/NwpGT4+UARUSkolGCJOVGYNUI2j74LgfjPuKgXwOqms5y485p7JrRnW2b1no7PBERqUCUIEm5U6/9zdR9fD1bWjxMOnZaO3fQfGk/vpz3f5w8ddLb4YmISAWgBEnKJZOfP+0GTiL7/75jW2gP/Ewuepx4j+wXOvLNsjdwOV3eDlFERMoxJUhSrlWJbEjr+GXs6fkGR83hRPAb3Tf+nU3P9Obn3Vu9HZ6IiJRTSpCkQojufjc1H93IpgZ/xmFY6JC9ntrv3siXr40jLS3N2+GJiEg5owRJKgw/ezDXDJ3FySFfsjPgGuwmBz0Ov8qJmZ34ftXHemSJiIgUmRIkqXDCG7Wh+aOr+SlmNr9RlfrGYTp/PZR1M+/k8KF93g5PRETKASVIUjGZTLSKHU5g/CY2RvTHaZj4Q9pqQv8Vw1fvPEV2tsPbEYqIiA9TgiQVWkBoVa79y7840v9T9lqbEmLK4Pq9z7H/n13Y+v0X3g5PRER8lBIkqRTqtu5G48eT2NRmImcJpKnrZ1p9ehffvjCY306keDs8ERHxMUqQpNIwWfy45u5HMB78gU1VYzGbDLqd+i/M68Taj+bp3kkiIuLm5+0ARK620Jq1uWbM++xZtxzb549Sz3WIrj8+ybYd72GPe54mrTp5O0QBcObgzE4jM/0cmenncGSmkZWZRlZaKjkn9pL88yZCQqtjDw7DFhiCyc/m7YhFrphhGGQ6XKRlZZNx7hwZaafJSk8lO/0s2RlnyUlPxZl5FldWGkb2OchOw5R9DrMjHUtOGn456dTISmfDTy+ByYyBCcNkxiDvzybAnFt2fjseP3PLMZkwOP/zfDmm399z/n1ee5hNHnVyf16434XlFo86ntstmEwmDHNuWdsuvalTt55X+kIJklRa0V36knPNTfzw/tO02rOA1o6tON6P5ZvI+2j/x38QHBzq7RB9kzMHw5FOVkYa2RnnyMo4R3ZGGtmZaeRkpZOTmU5OdhqurHRc2ekY2ekYjnRwZGDKyX2ZczKxODPwc2bi58zE6srE38jCamRhM7Kwk4UVJxYg6PzrQk0B3vMsy8aPdALINAWQZQ4gyxJIjiWQHL8gcvyCMPyDMKzBYAvGbAvGbA/BLyAEa0Ao1oAQbEGh2IPCCAgOIyAoFJM1IPcfbJFLyM5xkZ6VTdq5s2Smp5KZlkp2WirZGWdxZp7FkXkOIzMV43xCY8pOw+RIxy8nDb+cNKzODKyuDGyuDAJc6QSQSSCZ1DBlXWFgpXN+3ra15sLKnSDNnz+f5557juTkZNq1a8eLL75I586dC62/ZMkSJk6cyP79+4mOjuaZZ56hb9++7u2GYTB58mRee+01Tp8+Tbdu3Xj55ZeJjo521zl58iSjR4/mf//7H2azmbvvvpsXXniB4ODgMj1X8S1+/nY6/nE6xw8+wJ7FY2ibtpbuyf/myMwEdsZMpUPv+7wd4qW5XODMwuXIJDsrk+ysDHKyMnE4MsnJysCZnUlOdiZORyYuRybOrHSc2enu5IXziUte8mJx5iUvmfi5chMXqysLfyMLm5GJnWys5GAC7OdfZX6KhokM/MnERrbJn2yTDYsrm0AyCSITmyl3RaI/OfhzFoyz4CT3dQVyDDPppgAyTXYyzYFkmwNxWAJx+AXi9AvGZQ3E8A8G/yBMtpDchMsejF9AKP6BYfgHhRBwQcJltgUr4fIiwzDIcjhJz8ggIy2VrIxzZKal4sg4l5vcZ6TizErDmXkOI+scnB+dMTvSsDjSsTjTsOak438+mbEbGdiNTILIoIopiyqlEWQBXw8XJjKwk2EKINsckPs99AsgxxKI0xqEyxqEYQ3C5B8MtiCwBnLocDL169fL/boZrtx/J3CB4cJwGWA4wbjwpyvfyzAMTB5lF9TDdX6b574mw3AfJ2+7yfj92CaM3/fjfH3DhSmvvfPbTe7tLsKq1iiNT7ZEvJ4gLV68mPj4eBYsWECXLl2YM2cOsbGx7Nq1i1q1auWrv3btWgYNGsSMGTO49dZbWbRoEXFxcWzcuJHWrVsD8OyzzzJ37lzeeustGjZsyMSJE4mNjWX79u3Y7bn/pN9///0cPXqUxMREHA4Hw4YNY+TIkSxatOiqnr/4hpr1mlJz3Gds++I/1Ph6IlHGcaKS/sbGzf+m2t2zPOo6nS53MpKdnZ6bkGRlkOPIxJmdhfP8n12OTFyOrPM/MzFysjBysiDvpzMbU04mJmc2Jmc2ZmdW7k9XNpa8l5GNnysbP8OBn5GN1XDgZzjwJxt/HFjPZwFmrl7CcqF0w0Ym/mSabGRhI9tsI8dkw2G2k2PJfTktAbj8AjD8AsAaAH4B4B+A2RqA2RaE2T8QP1sQfvZArLYgrPYg/AODsAUEYw8IJiAgkECrhaDzyYXD4WD58uX07dsXs8WP1IwMMs6lknHuDJlpZ8hOT8WRkUrO+f/BuzLPYmSlQfZZzI68X3hpWJ3pWJ3p2Fzp2F0ZBBgZBJJJ4Pn/ufuZXISSRqiRBs7fchOuK7g7hMswkW6y5yZcpkCyzQE4LAE4zf7kWOy4zP64LDYMPzuGxZb7efnZMFntmKwBmKx2zNYALOc/O4stAD9/O1Z7EFZbAFZbIFZbAP4BQdjsgVis9nKZkLlcBumZuUlMZtpZstLPkZ1xFkfGWRwZ58jJOocrK+38Jab03EtMjtxRGcv5JN/PmYG/MwN/IwN/VyZ2I5MAsgggi2qmK8ycL3TRx+vERAa5SXWWOeB8Hwfi8AvC5ReI0xoI1rykOgizPQSLPRg/ewj+AaFYA0Ownx/JtAeFYrEFY7YGEGQy5RtFLYzD4WDf8uU069sXq9VaeudaCZkML99euEuXLnTq1Il58+YB4HK5qFu3LqNHj+bxxx/PV3/gwIGkpaXxySefuMv+8Ic/0L59exYsWIBhGERFRfHwww/zyCOPAHDmzBnCw8N58803uffee9mxYwctW7Zk/fr1dOzYEYCEhAT69u3Lr7/+SlRU1GXjTk1NJSwsjDNnzhAaWnqXYi78x19fbu/ITEvlx0UTuObXd7CanGQbfpwlEH8c+OPAZsrxdoiFyjSsZPP7y2HKe/njNFlzExeznRyLDafFjssSgGG9IHmxBmLyD8TsH4DFPxCLLQg/exB+tiD8A4Lwt+cmLv4BgQQEBGH398NqubprPcry74jLZZCZnU2aO+FKJTvtDNkZqeRknMOZkTv/w8hOg6yzmBzn53440rA6cy+X+DvTz48upBNo5I5ymU3e+Wc207DmjrrhT7bJH4fJH4fZRo7JH6fZlvs9MNtwWewYFv/cRNZiAz87WO2Y/Gzu5MziH4jZasdiy03S/PwDsdoDMFn8WbcuiXatWuDKTseRmUZOZm4iY2Sl48rKHYnBkY45Jx2TIwNLTvr5BDUz9/KSkZk7QmlkEUgm1tJMYgqRjR+Z2Mky2cky290Ja95lWcMaiMsa9PsIoS04N5kJCMm9JBsYin9gKPagUAKCQ7HaQ3L/Dnk5KdXvkMsr6u9vr44gZWdns2HDBsaPH+8uM5vN9OzZk6SkpAL3SUpKIj4+3qMsNjaWpUuXArBv3z6Sk5Pp2bOne3tYWBhdunQhKSmJe++9l6SkJKpUqeJOjgB69uyJ2Wxm3bp13HnnnfmOm5WVRVbW79eEU1NTgdwvo8NRejcdzGurNNuU4rH4B3DN0Fkc3vNH0pfG0zJ7K9VJLbR+lmEl2+SHAyvZ+JNzPinJMeX+2Wn2J8fsj8vkj9NixWW24TL75/5CstjAkvtn/Ozg5w8WGyarDZOfDbOfDbPVnvuLyd+OxWrHYrVh8bfjZ7XjZ7Pnjh742/H3t+HvZ8FuMRFwtf6RdjlxuMr+l9mFyvrviNVipkpYFaqEVbnitgzDIN3hJC39HBnnTpOVfpastDO5oyHpqbiyM3A5sjAc6edHFzPBkYnJmYkpJwuzMxOzMxuLMxOzKws/V9b5EcVsrK4srDjwN7LwNxzYyMZOtkcyZjc5sOMA0sAg91UGizUbAPxSCg1d9LV1GBYyzo+6ZZvsZF+QyOSNTLqsgRh+gRj+QZj8c0ckzXmJvT3k/IhkyPnEPoSAoFAstkBMFisBQEAphA3nBxdzvP+fJ/0OubyifjZeTZBOnDiB0+kkPDzcozw8PJydO3cWuE9ycnKB9ZOTk93b88ouVefiy3d+fn5Uq1bNXediM2bMYOrUqfnKV6xYQWBgYGGnWGKJiYml3qYUn9HiEbafPYphuDCZ/cBixWS2YrJYMZv9wOyHyVyGyUjeXJpMyJ11WUFmXpaC8v93JCT3ZSX3VQpcLgOn04nL6cBwZoPLgZGTjeFy5F7SdeaAKxuTy4HZlY3J6cDscmA2sjG7HFgMBxaX4/yl3dzLun5GbupvNXKwGtlYyU3GrOeTMhvZuDCTgZ1Mk41MbGSZbGSbbGSb7DhMttxRK7ONHLM/Tosdp9mGYbHhMtsw/HL/k4CfHZPFhtlqw2zJ/Q8ClhL+ijKAjPMvss6/TpTOh1xOlP+/H2UnPT29SPW8PgepvBg/frzHyFVqaip169ald+/epX6JLTExkV69eml41EeoT3yL+sO3OBwOvjjfH1XVH16nvx+Xl3cF6HK8miDVqFEDi8VCSornnYxTUlKIiIgocJ+IiIhL1s/7mZKSQmRkpEed9u3bu+scO3bMo42cnBxOnjxZ6HFtNhs2W/77rFit1jL5EpZVu1Jy6hPfov7wLeoP36L+KFxRPxev3knb39+fDh06sGrVKneZy+Vi1apVxMTEFLhPTEyMR33IHUrMq9+wYUMiIiI86qSmprJu3Tp3nZiYGE6fPs2GDRvcdb744gtcLhddunQptfMTERGR8snrl9ji4+MZMmQIHTt2pHPnzsyZM4e0tDSGDRsGwODBg6lduzYzZswAYMyYMfTo0YNZs2bRr18/3nvvPX744QdeffVVAEwmE2PHjuWpp54iOjravcw/KiqKuLg4AFq0aEGfPn0YMWIECxYswOFwMGrUKO69994irWATERGRis3rCdLAgQM5fvw4kyZNIjk5mfbt25OQkOCeZH3w4EHM5t8Hurp27cqiRYuYMGECTzzxBNHR0SxdutR9DySARx99lLS0NEaOHMnp06fp3r07CQkJ7nsgAbz77ruMGjWKm2++2X2jyLlz5169ExcRERGf5fUECWDUqFGMGjWqwG1r1qzJV9a/f3/69+9faHsmk4lp06Yxbdq0QutUq1ZNN4UUERGRAnl1DpKIiIiIL1KCJCIiInIRJUgiIiIiF1GCJCIiInIRJUgiIiIiF1GCJCIiInIRJUgiIiIiF1GCJCIiInIRJUgiIiIiF/GJO2mXR4ZhALkPwi1NDoeD9PR0UlNT9SRmH6E+8S3qD9+i/vAt6o/Ly/u9nfd7vDBKkEro7NmzANStW9fLkYiIiEhxnT17lrCwsEK3m4zLpVBSIJfLxZEjRwgJCcFkMpVau6mpqdStW5dDhw4RGhpaau1KyalPfIv6w7eoP3yL+uPyDMPg7NmzREVFYTYXPtNII0glZDabqVOnTpm1Hxoaqi+3j1Gf+Bb1h29Rf/gW9celXWrkKI8maYuIiIhcRAmSiIiIyEWUIPkYm83G5MmTsdls3g5FzlOf+Bb1h29Rf/gW9Ufp0SRtERERkYtoBElERETkIkqQRERERC6iBElERETkIkqQRERERC6iBMnHzJ8/nwYNGmC32+nSpQvff/+9t0OqlGbMmEGnTp0ICQmhVq1axMXFsWvXLm+HJef985//xGQyMXbsWG+HUmkdPnyYP/7xj1SvXp2AgADatGnDDz/84O2wKi2n08nEiRNp2LAhAQEBNG7cmOnTp1/2eWNSOCVIPmTx4sXEx8czefJkNm7cSLt27YiNjeXYsWPeDq3S+fLLL3nwwQf57rvvSExMxOFw0Lt3b9LS0rwdWqW3fv16XnnlFdq2bevtUCqtU6dO0a1bN6xWK5999hnbt29n1qxZVK1a1duhVVrPPPMML7/8MvPmzWPHjh0888wzPPvss7z44oveDq3c0jJ/H9KlSxc6derEvHnzgNznvdWtW5fRo0fz+OOPezm6yu348ePUqlWLL7/8kuuvv97b4VRa586d49prr+Wll17iqaeeon379syZM8fbYVU6jz/+ON9++y1ff/21t0OR82699VbCw8N5/fXX3WV33303AQEBvPPOO16MrPzSCJKPyM7OZsOGDfTs2dNdZjab6dmzJ0lJSV6MTADOnDkDQLVq1bwcSeX24IMP0q9fP4+/J3L1LVu2jI4dO9K/f39q1arFNddcw2uvvebtsCq1rl27smrVKnbv3g3Ali1b+Oabb7jlllu8HFn5pYfV+ogTJ07gdDoJDw/3KA8PD2fnzp1eikogdyRv7NixdOvWjdatW3s7nErrvffeY+PGjaxfv97boVR6v/zyCy+//DLx8fE88cQTrF+/noceegh/f3+GDBni7fAqpccff5zU1FSaN2+OxWLB6XTy9NNPc//993s7tHJLCZLIZTz44INs27aNb775xtuhVFqHDh1izJgxJCYmYrfbvR1OpedyuejYsSP/+Mc/ALjmmmvYtm0bCxYsUILkJe+//z7vvvsuixYtolWrVmzevJmxY8cSFRWlPikhJUg+okaNGlgsFlJSUjzKU1JSiIiI8FJUMmrUKD755BO++uor6tSp4+1wKq0NGzZw7Ngxrr32WneZ0+nkq6++Yt68eWRlZWGxWLwYYeUSGRlJy5YtPcpatGjBhx9+6KWIZNy4cTz++OPce++9ALRp04YDBw4wY8YMJUglpDlIPsLf358OHTqwatUqd5nL5WLVqlXExMR4MbLKyTAMRo0axccff8wXX3xBw4YNvR1SpXbzzTezdetWNm/e7H517NiR+++/n82bNys5usq6deuW77YXu3fvpn79+l6KSNLT0zGbPX+lWywWXC6XlyIq/zSC5EPi4+MZMmQIHTt2pHPnzsyZM4e0tDSGDRvm7dAqnQcffJBFixbx3//+l5CQEJKTkwEICwsjICDAy9FVPiEhIfnmfwUFBVG9enXNC/OCv//973Tt2pV//OMfDBgwgO+//55XX32VV1991duhVVq33XYbTz/9NPXq1aNVq1Zs2rSJ2bNn86c//cnboZVbWubvY+bNm8dzzz1HcnIy7du3Z+7cuXTp0sXbYVU6JpOpwPKFCxcydOjQqxuMFOiGG27QMn8v+uSTTxg/fjx79uyhYcOGxMfHM2LECG+HVWmdPXuWiRMn8vHHH3Ps2DGioqIYNGgQkyZNwt/f39vhlUtKkEREREQuojlIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiIiJyESVIIiIiIhdRgiQiUkImk4mlS5d6OwwRKQNKkESkXBo6dCgmkynfq0+fPt4OTUQqAD2LTUTKrT59+rBw4UKPMpvN5qVoRKQi0QiSiJRbNpuNiIgIj1fVqlWB3MtfL7/8MrfccgsBAQE0atSIDz74wGP/rVu3ctNNNxEQEED16tUZOXIk586d86jzxhtv0KpVK2w2G5GRkYwaNcpj+4kTJ7jzzjsJDAwkOjqaZcuWubedOnWK+++/n5o1axIQEEB0dHS+hE5EfJMSJBGpsCZOnMjdd9/Nli1buP/++7n33nvZsWMHAGlpacTGxlK1alXWr1/PkiVLWLlypUcC9PLLL/Pggw8ycuRItm7dyrJly2jSpInHMaZOncqAAQP48ccf6du3L/fffz8nT550H3/79u189tln7Nixg5dffpkaNWpcvQ9ARErOEBEph4YMGWJYLBYjKCjI4/X0008bhmEYgPGXv/zFY58uXboYf/3rXw3DMIxXX33VqFq1qnHu3Dn39k8//dQwm81GcnKyYRiGERUVZTz55JOFxgAYEyZMcL8/d+6cARifffaZYRiGcdtttxnDhg0rnRMWkatKc5BEpNy68cYbefnllz3KqlWr5v5zTEyMx7aYmBg2b94MwI4dO2jXrh1BQUHu7d26dcPlcrFr1y5MJhNHjhzh5ptvvmQMbdu2df85KCiI0NBQjh07BsBf//pX7r77bjZu3Ejv3r2Ji4uja9euJTpXEbm6lCCJSLkVFBSU75JXaQkICChSPavV6vHeZDLhcrkAuOWWWzhw4ADLly8nMTGRm2++mQcffJCZM2eWerwiUro0B0lEKqzvvvsu3/sWLVoA0KJFC7Zs2UJaWpp7+7fffovZbKZZs2aEhITQoEEDVq1adUUx1KxZkyFDhvDOO+8wZ84cXn311StqT0SuDo0giUi5lZWVRXJyskeZn5+feyL0kiVL6NixI927d+fdd9/l+++/5/XXXwfg/vvvZ/LkyQwZMoQpU6Zw/PhxRo8ezQMPPEB4eDgAU6ZM4S9/+Qu1atXilltu4ezZs3z77beMHj26SPFNmjSJDh060KpVK7Kysvjkk0/cCZqI+DYlSCJSbiUkJBAZGelR1qxZM3bu3AnkrjB77733+Nvf/kZkZCT/+c9/aNmyJQCBgYF8/vnnjBkzhk6dOhEYGMjdd9/N7Nmz3W0NGTKEzMxMnn/+eR555BFq1KjBPffcU+T4/P39GT9+PPv37ycgIIDrrruO9957rxTOXETKmskwDMPbQYiIlDaTycTHH39MXFyct0MRkXJIc5BERERELqIESUREROQimoMkIhWSZg+IyJXQCJKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRZQgiYiIiFxECZKIiIjIRf4ftkgqIWPHjGcAAAAASUVORK5CYII=", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB2/UlEQVR4nO3dd3wUdf7H8dfsZrObHmoKvUmHKAhSFAsQBEssiOhJOQ5+eoJgTjxRBEQ9TgVERMWKesqBWDhOMRIQzzuJjSYoIEovCSBCSN/szu+PwOqSAAkkzCZ5Px+PPMLOfuc7n9nv6r4zM98dwzRNExERERHxsVldgIiIiEigUUASEREROYkCkoiIiMhJFJBERERETqKAJCIiInISBSQRERGRkyggiYiIiJxEAUlERETkJApIIiIiIidRQBKRU9qxYweGYfD666+f1fqGYTBlypRyrUmqrmHDhtG4cWOryxABFJBEymzDhg3cfPPNNGrUCJfLRb169ejTpw/PPvtssbYej4d58+Zx+eWXU7NmTZxOJ40bN2b48OF8++23vnavv/46hmGU+PPAAw+ctp758+cza9as8t7NKun3r/P//ve/Ys+bpkmDBg0wDINrrrnG77msrCwmT55Mu3btCAsLo1atWiQkJDB27Fj27dvnazdlypRTjqVhGKSnp1f4forIuQuyugCRymTVqlVcccUVNGzYkJEjRxIbG8vu3bv58ssveeaZZxgzZoyvbW5uLjfeeCMpKSlcdtllPPjgg9SsWZMdO3bwzjvv8MYbb7Br1y7q16/vW2fq1Kk0adLEb5vt2rU7bU3z589n48aNjBs3rlz3FaBRo0bk5ubicDjOav3c3FyCggLvfzMul4v58+fTs2dPv+X/+c9/2LNnD06n02+52+3msssuY/PmzQwdOpQxY8aQlZXF999/z/z587nhhhuIj4/3W+eFF14gPDy82Lajo6PLfX9EpPwF3v+5RALY448/TlRUFN98802xD7oDBw74PR4/fjwpKSk8/fTTxcLL5MmTefrpp4v1f/XVV9O5c+fyLtsnLy+P4OBgbLbSHTw2DAOXy3XW2zuXdStS//79WbRoEbNnz/YLcPPnz6dTp04cOnTIr/3ixYtZu3Ytb7/9Nrfddpvfc3l5eRQUFBTbxs0330zt2rUrZgfOE6/XS0FBQcCOo0hF0ik2kTL4+eefadu2bYlHAerWrev79549e3jxxRfp06dPiUd27HY79913n9/Ro7Nx+eWX89FHH7Fz507fKZwT13B89tlnGIbBggULmDhxIvXq1SM0NJTMzEwOHz7MfffdR/v27QkPDycyMpKrr76a9evX+/Vf0jVIw4YNIzw8nL1795KUlER4eDh16tThvvvuw+Px+K1/8jVIJ04//fTTTwwbNozo6GiioqIYPnw4OTk5fuvm5uZyzz33ULt2bSIiIrjuuuvYu3dvidc1bd68mV27dpX6dRs8eDC//PILqampvmUFBQW8++67xQIQFI07QI8ePYo953K5iIyMLPW2S+Ott96iU6dOhISEULNmTW699VZ2797t1+byyy+nXbt2/PDDD1xxxRWEhoZSr149nnzyyWL95efnM3nyZJo3b47T6aRBgwbcf//95Ofn+7UzDIPRo0fz9ttv07ZtW5xOJykpKQB899139OrVi5CQEOrXr89jjz3GvHnzMAyDHTt2ADB06FBq166N2+0uVkPfvn1p2bJlmV+L7Oxs/vKXv9CgQQOcTictW7Zk+vTpmKbp1y41NZWePXsSHR1NeHg4LVu25MEHH/Rr8+yzz9K2bVtCQ0OpUaMGnTt3Zv78+WWuSaoHHUESKYNGjRqRlpbGxo0bT3vq6+OPP6awsJA77rijTP0fPXq02NGL0x2FeOihhzh69Ch79uzxHZE6+bTOo48+SnBwMPfddx/5+fkEBwfzww8/sHjxYgYOHEiTJk3IyMjgxRdfpFevXvzwww/FThedzOPxkJiYSNeuXZk+fTrLly9nxowZNGvWjLvuuuuM+3nLLbfQpEkTpk2bxpo1a3jllVeoW7cuTzzxhK/NsGHDeOedd7jjjju45JJL+M9//sOAAQNK7K9169b06tWLzz777IzbBmjcuDHdunXjn//8J1dffTVQNGZHjx7l1ltvZfbs2X7tGzVqBMCbb77JxIkTMQzjjNs4fPhwsWVBQUFnPMX2+OOP8/DDD3PLLbfwpz/9iYMHD/Lss89y2WWXsXbtWr/1f/31V/r168eNN97ILbfcwrvvvstf//pX2rdv79svr9fLddddx//+9z9GjRpF69at2bBhA08//TQ//vgjixcv9tv+p59+yjvvvMPo0aOpXbs2jRs3Zu/evVxxxRUYhsGECRMICwvjlVdeKXYq8o477uDNN9/kk08+8buGKz09nU8//ZTJkyef8XX7PdM0ue6661i5ciUjRowgISGBTz75hPHjx7N3717fe/7777/nmmuuoUOHDkydOhWn08lPP/3EF1984evr5Zdf5p577uHmm29m7Nix5OXl8d133/HVV1+VGIpFMEWk1JYtW2ba7XbTbreb3bp1M++//37zk08+MQsKCvza3XvvvSZgrl27tlT9zps3zwRK/DmTAQMGmI0aNSq2fOXKlSZgNm3a1MzJyfF7Li8vz/R4PH7Ltm/fbjqdTnPq1Kl+ywBz3rx5vmVDhw41Ab92pmmaF154odmpUye/ZYA5efJk3+PJkyebgPnHP/7Rr90NN9xg1qpVy/d49erVJmCOGzfOr92wYcOK9XliO7169Sr2GpzsxOv8zTffmHPmzDEjIiJ8r83AgQPNK664wjRN02zUqJE5YMAA33o5OTlmy5YtTcBs1KiROWzYMPPVV181MzIyim3jxD6W9NOyZcvT1rdjxw7Tbrebjz/+uN/yDRs2mEFBQX7Le/XqZQLmm2++6VuWn59vxsbGmjfddJNv2T/+8Q/TZrOZ//3vf/36nDt3rgmYX3zxhW8ZYNpsNvP777/3aztmzBjTMAy/9/Mvv/xi1qxZ0wTM7du3m6Zpmh6Px6xfv745aNAgv/VnzpxpGoZhbtu27bT7P3ToUL/38uLFi03AfOyxx/za3XzzzaZhGOZPP/1kmqZpPv300yZgHjx48JR9X3/99Wbbtm1Pu32R39MpNpEy6NOnD2lpaVx33XWsX7+eJ598ksTEROrVq8eSJUt87TIzMwGIiIgoU//PPfccqampfj/naujQoYSEhPgtczqdvuuQPB4Pv/zyi++0xJo1a0rV75133un3+NJLL2Xbtm1nve4vv/zie91OnNb585//7Nfu9xfB/55pmqU+enTCLbfcQm5uLh9++CHHjh3jww8/POWRhJCQEL766ivGjx8PFM2GGzFiBHFxcYwZM6bYqSqA9957r9hYzps377Q1vf/++3i9Xm655RYOHTrk+4mNjaVFixasXLnSr314eDh/+MMffI+Dg4Pp0qWL3zgsWrSI1q1b06pVK78+r7zySoBiffbq1Ys2bdr4LUtJSaFbt24kJCT4ltWsWZPbb7/dr53NZuP2229nyZIlHDt2zLf87bffpnv37sUmIJzJ0qVLsdvt3HPPPX7L//KXv2CaJh9//DHw24Xv//rXv/B6vSX2FR0dzZ49e/jmm2/KVINUXzrFJlJGF198Me+//z4FBQWsX7+eDz74gKeffpqbb76ZdevW0aZNG981Kb//kCiNLl26lPtF2iV9KHm9Xp555hmef/55tm/f7nftUK1atc7Yp8vlok6dOn7LatSowa+//lqqmho2bFhsXSg6ZRQZGcnOnTux2WzFam/evHmp+i+NOnXq0Lt3b+bPn09OTg4ej4ebb775lO2joqJ48sknefLJJ9m5cycrVqxg+vTpzJkzh6ioKB577DG/9pdddlmZL9LeunUrpmnSokWLEp8/eTZh/fr1i53uq1GjBt99951fn5s2bSo2XiecPLmgpPfLzp076datW7HlJY3HkCFDeOKJJ/jggw8YMmQIW7ZsYfXq1cydO7fE7Z/Ozp07iY+PL/aHRuvWrX3PAwwaNIhXXnmFP/3pTzzwwANcddVV3Hjjjdx8882+PwT++te/snz5crp06ULz5s3p27cvt912W4nXlYmAApLIWQsODubiiy/m4osv5oILLmD48OEsWrSIyZMn06pVK6DoO5N+/1e3FU4+egTwt7/9jYcffpg//vGPPProo9SsWRObzca4ceNO+Rf479nt9nOq6VTrmyddeFvRbrvtNkaOHEl6ejpXX311qafgN2rUiD/+8Y/ccMMNNG3alLfffrtYQDobXq8XwzD4+OOPS3yNTr6+rDSvo9frpX379sycObPEtg0aNPB7XNL7pSzatGlDp06deOuttxgyZAhvvfUWwcHB3HLLLefU7+mEhITw+eefs3LlSj766CNSUlJYuHAhV155JcuWLcNut9O6dWu2bNnChx9+SEpKCu+99x7PP/88kyZN4pFHHqmw2qTyUkASKQcnjvrs378fKJqub7fbeeutt8p8oXZZleaC4ZO9++67XHHFFbz66qt+y48cORIQU9MbNWqE1+tl+/btfkdTfvrpp3Ldzg033MD//d//8eWXX7Jw4cIyr1+jRg2aNWvGxo0by6WeZs2aYZomTZo04YILLii3PtevX89VV111Vu8VKBqPkl77U43HkCFDSE5OZv/+/cyfP58BAwb4jhKWdbvLly/n2LFjfkeRNm/e7Hv+BJvNxlVXXcVVV13FzJkz+dvf/sZDDz3EypUr6d27NwBhYWEMGjSIQYMGUVBQwI033sjjjz/OhAkT9FUGUoyuQRIpg5UrV5Z4lGPp0qUAvmnMDRo0YOTIkSxbtqzEb9j2er3MmDGDPXv2nHNNYWFhHD16tEzr2O32YvuxaNEi9u7de871lIfExEQAnn/+eb/lJb2WUPZp/ieEh4fzwgsvMGXKFK699tpTtlu/fn2x2YVQdIrnhx9+OKvp6yW58cYbsdvtPPLII8XGxzRNfvnllzL3ecstt7B3715efvnlYs/l5uaSnZ19xj4SExNJS0tj3bp1vmWHDx/m7bffLrH94MGDMQyDsWPHsm3bNr/rpMqif//+eDwe5syZ47f86aefxjAM30y9kmYMnjhye+L6sJNfu+DgYNq0aYNpmiV+LYGIjiCJlMGYMWPIycnhhhtuoFWrVhQUFLBq1SoWLlzou4XICTNmzODnn3/mnnvu4f333+eaa66hRo0a7Nq1i0WLFrF582ZuvfXWc66pU6dOLFy4kOTkZC6++GLCw8NP+2EPcM011zB16lSGDx9O9+7d2bBhA2+//TZNmzY953rKQ6dOnbjpppuYNWsWv/zyi2+a/48//ggUP2pW1mn+vzd06NAztklNTWXy5Mlcd911XHLJJYSHh7Nt2zZee+018vPzS7zf3LvvvlviN2n36dOHmJiYErfTrFkzHnvsMSZMmMCOHTtISkoiIiKC7du388EHHzBq1Cjuu+++Mu3fHXfcwTvvvMOdd97JypUr6dGjBx6Ph82bN/POO+/wySefnPG6t/vvv5+33nqLPn36MGbMGN80/4YNG3L48OFi41GnTh369evHokWLiI6OPuXXM5zJtddeyxVXXMFDDz3Ejh076NixI8uWLeNf//oX48aNo1mzZkDRN9B//vnnDBgwgEaNGnHgwAGef/556tev7/u29L59+xIbG0uPHj2IiYlh06ZNzJkzhwEDBpR5MoVUExbNnhOplD7++GPzj3/8o9mqVSszPDzcDA4ONps3b26OGTOmxCnfhYWF5iuvvGJeeumlZlRUlOlwOMxGjRqZw4cP95sy/fvp52WVlZVl3nbbbWZ0dLRvGrpp/jbNf9GiRcXWycvLM//yl7+YcXFxZkhIiNmjRw8zLS3N7NWrl990+VNN8w8LCyvW54np7b/HKab5nzwd+8T+n5gubpqmmZ2dbd59991mzZo1zfDwcDMpKcncsmWLCZh///vfi22nrNP8T+fkaf7btm0zJ02aZF5yySVm3bp1zaCgILNOnTrmgAEDzE8//bTE1+FUPytXrjxjne+9957Zs2dPMywszAwLCzNbtWpl3n333eaWLVt8bXr16lXitPWTp8qbpmkWFBSYTzzxhNm2bVvT6XSaNWrUMDt16mQ+8sgj5tGjR33tAPPuu+8usaa1a9eal156qel0Os369eub06ZNM2fPnm0CZnp6erH277zzjgmYo0aNOuP+nq72Y8eOmffee68ZHx9vOhwOs0WLFuZTTz1ler1eX5sVK1aY119/vRkfH28GBweb8fHx5uDBg80ff/zR1+bFF180L7vsMrNWrVqm0+k0mzVrZo4fP95v/0V+zzDN83xVpIjIWVq3bh0XXnghb731VrEp5nL+jRs3jhdffJGsrKxiF4z/61//Iikpic8//5xLL73UogpFzp6uQRKRgJSbm1ts2axZs7DZbFx22WUWVFS9nTwev/zyC//4xz/o2bNnibPpXn75ZZo2bVrshsAilYWuQRKRgPTkk0+yevVqrrjiCoKCgvj444/5+OOPGTVqVLGp6VLxunXrxuWXX07r1q3JyMjg1VdfJTMzk4cfftiv3YIFC/juu+/46KOPeOaZZ8565pyI1XSKTUQCUmpqKo888gg//PADWVlZNGzYkDvuuIOHHnqIoCD9bXe+Pfjgg7z77rvs2bMHwzC46KKLmDx5sm8K/QmGYRAeHs6gQYOYO3euxkoqLQUkERERkZPoGiQRERGRkyggiYiIiJxEJ4fPktfrZd++fUREROgiRBERkUrCNE2OHTtGfHy872bGJVFAOkv79u3TTBoREZFKavfu3dSvX/+UzysgnaUTX02/e/duIiMjy61ft9vNsmXL6Nu3Lw6Ho9z6lbOnMQksGo/AovEILBqPM8vMzKRBgwZnvMWMAtJZOnFaLTIystwDUmhoKJGRkXpzBwiNSWDReAQWjUdg0XiU3pkuj9FF2iIiIiInUUASEREROYkCkoiIiMhJdA2SiIgEBI/Hg9vttrqMSs3tdhMUFEReXh4ej8fqcizhcDhKvIFyWSkgiYiIpUzTJD09nSNHjlhdSqVnmiaxsbHs3r27Wn9HX3R0NLGxsef0GiggiYiIpU6Eo7p16xIaGlqtP9jPldfrJSsri/Dw8NN+CWJVZZomOTk5HDhwAIC4uLiz7ksBSURELOPxeHzhqFatWlaXU+l5vV4KCgpwuVzVMiABhISEAHDgwAHq1q171qfbquerJyIiAeHENUehoaEWVyJVyYn307lc06aAJCIiltNpNSlP5fF+UkASEREROYkCkoiISABo3Lgxs2bNKnX7zz77DMMwKnz23+uvv050dHSFbiMQKSCJiIiUgWEYp/2ZMmXKWfX7zTffMGrUqFK37969O/v37ycqKuqstienp1lsAcbt8bI/B47lFVJTNxoUEQk4+/fv9/174cKFTJo0iS1btviWhYeH+/5tmiYej4egoDN/3NapU6dMdQQHBxMbG1umdaT0dAQpwAx6+Wv+vj6Ir7YftroUEREpQWxsrO8nKioKwzB8jzdv3kxERAQff/wxnTp1wul08r///Y+ff/6Z66+/npiYGMLDw7n44otZvny5X78nn2IzDINXXnmFG264gdDQUFq0aMGSJUt8z598iu3111+nZs2arFixgrZt2xIeHk6/fv38Al1hYSH33HMP0dHR1KpVi7/+9a8MHTqUpKSkMr0GL7zwAs2aNSM4OJiWLVvyj3/8w/ecaZpMmTKFhg0b4nQ6iY+P55577vE9//zzz9OiRQtcLhcxMTHcfPPNZdr2+aKAFGD+4p1HavB4srd+bnUpIiKWME2TnILC8/5jmma57cMDDzzA3//+dzZt2kSHDh3Iysqif//+rFixgrVr19KvXz+uvfZadu3addp+HnnkEW655Ra+++47+vfvz+23387hw6f+AzonJ4c5c+bwxhtv8Pnnn7Nr1y7uu+8+3/NPPPEEb7/9NvPmzeOLL74gMzOTxYsXl2nfPvjgA8aOHctf/vIXNm7cyP/93/8xfPhwVq5cCcB7773H008/zYsvvsjWrVtZvHgx7du3B+Dbb7/lnnvuYerUqWzZsoWUlBQuu+yyMm3/fNEptgDT0DhIU9te1qZ/b3UpIiKWyHV7aDPpk/O+3R+mJhIaXD4fi1OnTqVPnz6+xzVr1qRjx46+x48++igffPABS5YsYfTo0afsZ9iwYQwePBiAv/3tb8yePZuvv/6afv36ldje7XYzc+ZMOnbsiM1mY/To0UydOtX3/LPPPsuECRO44YYbAJgzZw5Lly4t075Nnz6dYcOG8ec//xmA5ORkvvzyS6ZPn84VV1zBrl27iI2NpXfv3jgcDho2bEiXLl0A2LVrF2FhYVxzzTVERETQqFEjLrzwwjJt/3zREaRAU6cVAGFHt1pciIiInK3OnTv7Pc7KyuK+++6jdevWREdHEx4ezqZNm854BKlDhw6+f4eFhREZGem7jUZJQkNDadKkie9xXFycr/3Ro0fJyMjwhRUAu91Op06dyrRvmzZtokePHn7LevTowaZNmwAYOHAgubm5NG3alJEjR/LBBx9QWFgIQJ8+fWjUqBFNmzbljjvu4O233yYnJ6dM2z9fdAQpwIQ3aAdbICZvO26PF4ddGVZEqpcQh50fpiZast3yEhYW5vf4vvvuIzU1lenTp9O8eXNCQkK4+eabKSgoOG0/jpMm6xiGgdfrLVP78jx1WBoNGjRgy5YtLF++nNTUVP785z/z1FNP8Z///IeIiAjWrFnDZ599xrJly5g0aRJTpkzhm2++CbivEtCnb4CJblT018IFxm52HsqyuBoRkfPPMAxCg4PO+09Ffpv3F198wbBhw7jhhhto3749sbGx7Nixo8K2V5KoqChiYmL45ptvfMs8Hg9r1qwpUz+tW7fmiy++8Fv2xRdf0KZNG9/jkJAQrr32WmbPns1nn31GWloaGzZsACAoKIjevXvz5JNP8t1337Fjxw4+/fTTc9iziqEjSAHGqN2CQmxEGjl8s/1nmscE5rlZEREpvRYtWvD+++9z7bXXYhgGDz/88GmPBFWUMWPGMG3aNJo3b06rVq149tln+fXXX8sUDsePH88tt9zChRdeSO/evfn3v//N+++/75uV9/rrr+PxeOjatSuhoaG89dZbhISE0KhRIz788EO2bdvGZZddRo0aNVi6dCler5eWLVtW1C6fNR1BCjRBTtJtRd9rcWTXdxYXIyIi5WHmzJnUqFGD7t27c+2115KYmMhFF1103uv461//yuDBgxkyZAjdunUjPDycxMREXC5XqftISkrimWeeYfr06bRt25YXX3yRefPmcfnllwMQHR3Nyy+/TI8ePejQoQPLly/n3//+N7Vq1SI6Opr333+fK6+8ktatWzN37lz++c9/0rZt2wra47NnmOf75GQVkZmZSVRUFEePHiUyMrLc+nW73Wyc3p8L87/m3Vp3cvOYJ8qtbzk7brebpUuX0r9//2Ln9+X803gElnMdj7y8PLZv306TJk3K9CEtJfN6vWRmZhIZGYnNduZjIF6vl9atW3PLLbfw6KOPnocKz4/Tva9K+/mtU2wBKCukPuR/TfjR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dIoxLS0Nm81G69atsdlsvou8T671RD8l+f3z0dHRxMfHk5aWxhVXXOFrs2rVKrp06eLrIzo6msGDBzN48GAGDhxIv379OHLkCDVr1iQsLIzrr7+e66+/ntGjR9OqVSu+//57LrroohL3zTCMEt+XpX2fWnqKLTk5maFDh9K5c2e6dOnCrFmzyM7OZvjw4QAMGTKEevXq+a5iHzt2LL169WLGjBkMGDCABQsW8O233/LSSy/5+jx8+DC7du1i3759AGzZUjRFPjY21u/nZA0bNqRJkyYVvctlFhLfHnYsoEbWz1aXIiIivxMeHs6gQYOYMGECmZmZDBs2zPdcixYtePfdd1m1ahU1atRg5syZZGRk0KZNm1L13bt3by644AKGDh3KU089RWZmJg899JBfmxYtWrBr1y4WLFjAxRdfzEcffVRs0lLjxo3Zvn0769ato379+kRERBT7Y//2229n8uTJDB06lClTpnDw4EHGjBnDHXfcUey633Mxfvx4Jk+eTLNmzUhISGDevHmsW7eOt99+Gyia2R4XF8eFF16IzWZj0aJFxMbGEh0dzeuvv47H46Fr166Ehoby1ltvERISQqNGFXfpiaXT/AcNGsT06dOZNGkSCQkJrFu3jpSUFN+A7Nq1i/379/vad+/enfnz5/PSSy/RsWNH3n33XRYvXky7du18bZYsWcKFF17IgAEDgKKEf+GFFzJ37tzzu3PlpHbTBACamLs4lJV/+sYiInJejRgxgl9//ZXExETfxdQAEydO5KKLLiIxMZHLL7+c2NhY39mS0rDZbHzwwQfk5ubSpUsX/vSnP/H444/7tbnuuuu49957GT16NAkJCaxatcrvaBIUXT7Sr18/rrjiCurUqVPiVw2EhobyySefcPjwYS6++GJuvvlmrrrqKr+v0CkP99xzD8nJyfzlL3+hffv2pKSksGTJElq0aAEUzch78skn6dy5MxdffDE7duxg6dKlviNQL7/8Mj169KBDhw4sX76cf//739SqVatca/w9wzxxolHKJDMzk6ioKI4ePVru1yAtXbqU/v37Fx0GzDkMTxYd2frqlnV0bRN4R7mqumJjIpbSeASWcx2PvLw8tm/fTpMmTYpdKyJl5/V6yczMJDIy8pSnvqqD072vSvv5XX1fvcoitCZH7EUJ+eB23XJERETkfFBAqgSOhDcHIH+fblor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J59gQowCdv28yepyRERELKGAJP5sdtKDGwLw687vLC5GRETEGgpIUsyxyBYAeNI1k01ERKonBSQpxohpA0DIkR8trkRERMQaCkhSTETDDgDE5G3DNE2LqxERETn/LA9Izz33HI0bN8blctG1a1e+/vrr07ZftGgRrVq1wuVy0b59e5YuXer3vGmaTJo0ibi4OEJCQujduzdbtxa/bcZHH31E165dCQkJoUaNGiQlJZXnblVqMc2LZrI1Nvdx4Mgxi6sRERE5/ywNSAsXLiQ5OZnJkyezZs0aOnbsSGJiIgcOHCix/apVqxg8eDAjRoxg7dq1JCUlkZSUxMaNG31tnnzySWbPns3cuXP56quvCAsLIzExkby8PF+b9957jzvuuIPhw4ezfv16vvjiC2677bYK39/KwlmzIdmE4DA87N66wepyREREzjtLA9LMmTMZOXIkw4cPp02bNsydO5fQ0FBee+21Ets/88wz9OvXj/Hjx9O6dWseffRRLrroIubMmQMUHT2aNWsWEydO5Prrr6dDhw68+eab7Nu3j8WLFwNQWFjI2LFjeeqpp7jzzju54IILaNOmDbfccsv52u3AZxhkuJoAkLlLM9lERKT6sSwgFRQUsHr1anr37v1bMTYbvXv3Ji0trcR10tLS/NoDJCYm+tpv376d9PR0vzZRUVF07drV12bNmjXs3bsXm83GhRdeSFxcHFdffbXfUSiB7KiimWzeDH0XkoiIVD9BVm340KFDeDweYmJi/JbHxMSwefPmEtdJT08vsX16errv+RPLTtVm27ZtAEyZMoWZM2fSuHFjZsyYweWXX86PP/5IzZo1S9x2fn4++fn5vseZmZkAuN1u3G53qfa5NE70VZ59npU6rSDjX4Qd/dH6WiwWMGMigMYj0Gg8AovG48xK+9pYFpCs4vV6AXjooYe46aabAJg3bx7169dn0aJF/N///V+J602bNo1HHnmk2PJly5YRGhpa7nWmpqaWe59lYT8K7YHY/O18+NFSbIal5QQEq8dE/Gk8AovGI7BoPE4tJ6d0t9GyLCDVrl0bu91ORkaG3/KMjAxiY2NLXCc2Nva07U/8zsjIIC4uzq9NQkICgG95mzZtfM87nU6aNm3Krl27TlnvhAkTSE5O9j3OzMykQYMG9O3bl8jIyDPtbqm53W5SU1Pp06cPDoej3Potq8LMi+DZJ2hEBnS5hPp1Sj6yVh0EyphIEY1HYNF4BBaNx5mdOAN0JpYFpODgYDp16sSKFSt8U+y9Xi8rVqxg9OjRJa7TrVs3VqxYwbhx43zLUlNT6datGwBNmjQhNjaWFStW+AJRZmYmX331FXfddRcAnTp1wul0smXLFnr27AkUvaF27NhBo0aNTlmv0+nE6XQWW+5wOCrkTVhR/ZZ6+zXrc8SIJJpMDm7/nibxV1pWS6CwekzEn8YjsGg8AovG49RK+7pYeootOTmZoUOH0rlzZ7p06cKsWbPIzs5m+PDhAAwZMoR69eoxbdo0AMaOHUuvXr2YMWMGAwYMYMGCBXz77be89NJLABiGwbhx43jsscdo0aIFTZo04eGHHyY+Pt4XwiIjI7nzzjuZPHkyDRo0oFGjRjz11FMADBw48Py/CIHKMDjoakJ07nqO7f4OUEASEZHqw9KANGjQIA4ePMikSZNIT08nISGBlJQU30XWu3btwmb7baJd9+7dmT9/PhMnTuTBBx+kRYsWLF68mHbt2vna3H///WRnZzNq1CiOHDlCz549SUlJweVy+do89dRTBAUFcccdd5Cbm0vXrl359NNPqVGjxvnb+Uogt0ZLyF0PB0q+aF5ERKSqsvwi7dGjR5/ylNpnn31WbNnAgQNPe6THMAymTp3K1KlTT9nG4XAwffp0pk+fXuZ6qxNHbFvYBxGZxb+JXEREpCqz/FYjErhqNukIQD33Dgo9XourEREROX8UkOSU6jRNAKCecYhd6RmnbywiIlKFKCDJKdnCanDIVguAAz+ttbgaERGR80cBSU7rUGgzALJ261YsIiJSfSggyWkV1LgAAPsh3ZNNRESqDwUkOa3g+LYARB372eJKREREzh8FJDmt2scv1G5QuIP8Qo+1xYiIiJwnCkhyWrUadwCgjnGUXbtPfa86ERGRqkQBSU7LcIaTbj9+E+Cf1llbjIiIyHmigCRndDisOQD5ezWTTUREqgcFJDkjd62WAAT9onuyiYhI9aCAJGcUUq/oZsA1sjWTTUREqgcFJDmjOs0SAGjk2UlufqG1xYiIiJwHCkhyRjUatKUQG1FGDjt26CiSiIhUfQpIcmZBTtKD6gNwaJvuySYiIlWfApKUypHwoplsBfs0k01ERKo+BSQpFU/tVgAEH95icSUiIiIVTwFJSiWsftFMtto5ugZJRESqPgUkKZWY5hcC0Mi7h8zcfIurERERqVgKSFIqEXEXkI+DUCOfnT/rCyNFRKRqU0CS0rEHke5oCMCv29dZW4uIiEgFU0CSUsuMbAGAe//3FlciIiJSsRSQpNTMOq0BCPlVM9lERKRqU0CSUgtv0B6AOrnbLK5ERESkYikgSanFtTg+k83cy+HMbIurERERqTgKSFJqIbUbk4OLYMPDrp/0jdoiIlJ1KSBJ6dls7Hc2BuDozvXW1iIiIlKBFJCkTLIjLwDAk/6DxZWIiIhUHAUkKRMjpg0AoUd+tLgSERGRiqOAJGUS2bADALH52zBN0+JqREREKoYCkpRJzPGZbA3MdA4cPmJtMSIiIhVEAUnKxBUdRyYR2A2TPVt1obaIiFRNCkhSNoZBuqsJAMd2bbC4GBERkYqhgCRllhNdNJPNPKCZbCIiUjUFREB67rnnaNy4MS6Xi65du/L111+ftv2iRYto1aoVLpeL9u3bs3TpUr/nTdNk0qRJxMXFERISQu/evdm6dWuJfeXn55OQkIBhGKxbt668dqlKC4ptC0B4ZsmvqYiISGVneUBauHAhycnJTJ48mTVr1tCxY0cSExM5cOBAie1XrVrF4MGDGTFiBGvXriUpKYmkpCQ2bvztm52ffPJJZs+ezdy5c/nqq68ICwsjMTGRvLy8Yv3df//9xMfHV9j+VUXRjYtmssXn78Dr1Uw2ERGpeiwPSDNnzmTkyJEMHz6cNm3aMHfuXEJDQ3nttddKbP/MM8/Qr18/xo8fT+vWrXn00Ue56KKLmDNnDlB09GjWrFlMnDiR66+/ng4dOvDmm2+yb98+Fi9e7NfXxx9/zLJly5g+fXpF72aVEtO8aCZbPeMg+zJKDrIiIiKVmaUBqaCggNWrV9O7d2/fMpvNRu/evUlLSytxnbS0NL/2AImJib7227dvJz093a9NVFQUXbt29eszIyODkSNH8o9//IPQ0NDy3K0qzxFei0NGTQD2/7TO2mJEREQqQJCVGz906BAej4eYmBi/5TExMWzevLnEddLT00tsn56e7nv+xLJTtTFNk2HDhnHnnXfSuXNnduzYccZa8/Pzyc/P9z3OzMwEwO1243a7z7h+aZ3oqzz7rAgHQ5pQO+cwx3atx+2+0upyKlRlGZPqQuMRWDQegUXjcWalfW0sDUhWefbZZzl27BgTJkwo9TrTpk3jkUceKbZ82bJlFXIEKjU1tdz7LE/hZh1aAzk7Vhe7SL6qCvQxqW40HoFF4xFYNB6nlpOTU6p2lgak2rVrY7fbycjI8FuekZFBbGxsievExsaetv2J3xkZGcTFxfm1SUhIAODTTz8lLS0Np9Pp10/nzp25/fbbeeONN4ptd8KECSQnJ/seZ2Zm0qBBA/r27UtkZGQp9/jM3G43qamp9OnTB4fDUW79lrfNxk5Yk0K8mU77/v2tLqdCVZYxqS40HoFF4xFYNB5nduIM0JlYGpCCg4Pp1KkTK1asICkpCQCv18uKFSsYPXp0iet069aNFStWMG7cON+y1NRUunXrBkCTJk2IjY1lxYoVvkCUmZnJV199xV133QXA7Nmzeeyxx3zr79u3j8TERBYuXEjXrl1L3K7T6SwWqAAcDkeFvAkrqt/yUqdZJ1gD9d07sNmDsNsMq0uqcIE+JtWNxiOwaDwCi8bj1Er7ulh+ii05OZmhQ4fSuXNnunTpwqxZs8jOzmb48OEADBkyhHr16jFt2jQAxo4dS69evZgxYwYDBgxgwYIFfPvtt7z00ksAGIbBuHHjeOyxx2jRogVNmjTh4YcfJj4+3hfCGjZs6FdDeHg4AM2aNaN+/frnac8rt7rNiqb61zWOsGPPbhqf9JqKiIhUZpYHpEGDBnHw4EEmTZpEeno6CQkJpKSk+C6y3rVrFzbbb5Ptunfvzvz585k4cSIPPvggLVq0YPHixbRr187X5v777yc7O5tRo0Zx5MgRevbsSUpKCi6X67zvX1Vlc0WQbosh1ptBxs9rFZBERKRKsTwgAYwePfqUp9Q+++yzYssGDhzIwIEDT9mfYRhMnTqVqVOnlmr7jRs3xjT1hYdldTi0GbFZGeTs3ghcb3U5IiIi5cbyL4qUyiu/VksA7L+U/JUMIiIilZUCkpw1Z3zRPdmis36yuBIREZHypYAkZ61Os6JbjjQs3EmB22NxNSIiIuVHAUnOWu1GbSk0bUQb2ezatc3qckRERMqNApKcNcMRQnpQPQAO/rzO2mJERETKkQKSnJNfw5sBkLd3g8WViIiIlB8FJDknnuMz2Ry/bLG4EhERkfKjgCTnJKReewBq5vxscSUiIiLlRwFJzknd5kUz2Rp5dpGb77a4GhERkfKhgCTnpEb9VhQQRJiRz85t+sJIERGpGhSQ5NzYg9gXVHQftsPb1llbi4iISDlRQJJzdjSiOQAF+7+3uBIREZHyoYAk58xbpzUAzsOaySYiIlWDApKcs7AG7QConatv0xYRkapBAUnOWWyziwBo6N3DsZxci6sRERE5dwpIcs4iY5uSgwunUcjOrRutLkdEROScKSDJubPZ2B/cCIAjO9ZbXIyIiMi5U0CScnEssgUAhemaySYiIpWfApKUj7ptAAg98qPFhYiIiJw7BSQpFxENOwBQVzPZRESkClBAknIR1zwBgPpmOoePZlpbjIiIyDlSQJJyEVqrPpmEE2R42bP1O6vLEREROScKSFI+DIN0ZxMAju7UTDYREancFJCk3GRFXwCAN+MHiysRERE5NwpIUm7sMUUz2cKPbrW4EhERkXOjgCTlJqpR0Uy22PxtmKZpcTUiIiJnTwFJyk1s8wsBqMdBDv1y2OJqREREzp4CkpQbV1QdfjFqALBn61qLqxERETl7CkhSrg64mgJwbJem+ouISOWlgCTlKvf4TDbjwCaLKxERETl7CkhSroLi2gIQkamZbCIiUnkpIEm5qtGkaCZbfMEOvF7NZBMRkcpJAUnKVWyzBADqGr+yf/9ea4sRERE5SwpIUq4coVFkGHUByPh5nbXFiIiInKWACEjPPfccjRs3xuVy0bVrV77++uvTtl+0aBGtWrXC5XLRvn17li5d6ve8aZpMmjSJuLg4QkJC6N27N1u3/nZNzI4dOxgxYgRNmjQhJCSEZs2aMXnyZAoKCipk/6qbg6FFM9mydm+0uBIREZGzY3lAWrhwIcnJyUyePJk1a9bQsWNHEhMTOXDgQIntV61axeDBgxkxYgRr164lKSmJpKQkNm787cP4ySefZPbs2cydO5evvvqKsLAwEhMTycvLA2Dz5s14vV5efPFFvv/+e55++mnmzp3Lgw8+eF72uarLr9kSANshzWQTEZHKyfKANHPmTEaOHMnw4cNp06YNc+fOJTQ0lNdee63E9s888wz9+vVj/PjxtG7dmkcffZSLLrqIOXPmAEVHj2bNmsXEiRO5/vrr6dChA2+++Sb79u1j8eLFAPTr14958+bRt29fmjZtynXXXcd9993H+++/f752u0oLPj6TLerYTxZXIiIicnaCrNx4QUEBq1evZsKECb5lNpuN3r17k5aWVuI6aWlpJCcn+y1LTEz0hZ/t27eTnp5O7969fc9HRUXRtWtX0tLSuPXWW0vs9+jRo9SsWfOUtebn55Ofn+97nJmZCYDb7cbtdp9+R8vgRF/l2ef5FtWoPXwN9d07yMvLx263PIefk6owJlWJxiOwaDwCi8bjzEr72lgakA4dOoTH4yEmJsZveUxMDJs3by5xnfT09BLbp6en+54/sexUbU72008/8eyzzzJ9+vRT1jpt2jQeeeSRYsuXLVtGaGjoKdc7W6mpqeXe53njKaCeaVDDyOKtdxcQERFtdUXlolKPSRWk8QgsGo/AovE4tZycnFK1szQgBYK9e/fSr18/Bg4cyMiRI0/ZbsKECX5HrjIzM2nQoAF9+/YlMjKy3Opxu92kpqbSp08fHA5HufV7vu3fOIX63j00q+Oi85X9rS7nnFSVMakqNB6BReMRWDQeZ3biDNCZWBqQateujd1uJyMjw295RkYGsbGxJa4TGxt72vYnfmdkZBAXF+fXJiEhwW+9ffv2ccUVV9C9e3deeuml09bqdDpxOp3Fljscjgp5E1ZUv+fLkYjm1D+6h+C0Wayt15Eu7VpZXdI5q+xjUtVoPAKLxiOwaDxOrbSvi6UXhwQHB9OpUydWrFjhW+b1elmxYgXdunUrcZ1u3br5tYeiQ4kn2jdp0oTY2Fi/NpmZmXz11Vd+fe7du5fLL7+cTp06MW/ePGy2yn2dTKCp1+8v5OKiEz/QYNHVfLDkA0xT36wtIiKVg+WpIDk5mZdffpk33niDTZs2cdddd5Gdnc3w4cMBGDJkiN9F3GPHjiUlJYUZM2awefNmpkyZwrfffsvo0aMBMAyDcePG8dhjj7FkyRI2bNjAkCFDiI+PJykpCfgtHDVs2JDp06dz8OBB0tPTT3mNkpRdjdaXYRv1KRnBDYkzDjNg9QgWPj+Z7DxdOCgiIoHP8muQBg0axMGDB5k0aRLp6ekkJCSQkpLiu8h6165dfkd3unfvzvz585k4cSIPPvggLVq0YPHixbRr187X5v777yc7O5tRo0Zx5MgRevbsSUpKCi6XCyg64vTTTz/x008/Ub9+fb96dJSj/Djj21I3+Qt2zvsjjTJSufXgMyyfsZ7mf3yFxnF1rC5PRETklAxTieCsZGZmEhUVxdGjR8v9Iu2lS5fSv3//qnP+2DTZvfRJ4r75O0F42WI24lD/V+jRtYvVlZVKlRyTSkzjEVg0HoFF43Fmpf38tvwUm1QDhkGDAX/l2MD3+NVWg5bGTtovvZ7FC17G61U+FxGRwKOAJOdNjbZXEjbmC3aFtSfSyCFp8318NOsujmblWV2aiIiIHwUkOa+Ca9Sj4b2f8lOTPwBwbeY/2TqzL1u377C2MBERkd9RQJLzLyiY5kOfY/cVz5KLk87e9YS9fiWfr0yxujIRERFAAUks1KDXEAqGL2d/UH3ijV/o+tntLH3tMQoLPVaXJiIi1ZwCklgqqlEH6v5lFVtqXI7TKKT/rqf4YsYtHPr1V6tLExGRakwBSSxnD4mi5T2L2dxuPB7ToFfucg7Pvpwfvl9vdWkiIlJNKSBJYDAMWt08kfSkBRw2orjA3EG9d67m8w//YXVlIiJSDSkgSUCpd2E/gv/8P35ytiHKyOayb0fz6fP3kF9QYHVpIiJSjSggScAJr9OQpvd9xnfxtwBw5YE3+OGpRNLT91pcmYiIVBcKSBKQbA4nHUa9zA/dppOLkwvdazDnXsaGr1daXZqIiFQDCkgS0NokjuTI4I/Za4sjjkNc8NHN/G/hdEyv1+rSRESkClNAkoAX17ITNcel8V14D5xGIT03PcpXz9xObnaW1aWJiEgVpYAklUJIZA3aJ/+bb5vfg8c0uOToUvbOvJS92zZbXZqIiFRBCkhSaRg2O53/8Cg/9n2Tw0TS3LON8Dev5LuV71hdmoiIVDEKSFLptO5xHe4/rWRLUEuiyKbdZ6P4+rX78BYWWl2aiIhUEQpIUinF1G9O4/s+48taN2AzTLrsepnvZ/Qj89cDVpcmIiJVgAKSVFpOVyiXjHmdLzv+jVwzmPa535A9uwe7Nq6yujQREankFJCk0rvkhrvZdeMS9hBLnHmAmEXXsWHJs1aXJSIilZgCklQJLTt2I2T0f1ntvASn4ab9momse24InoJcq0sTEZFKSAFJqoxatevScfxHrKz3f3hMg4SD/2LnU5dydN9PVpcmIiKVjAKSVClBQUFcMfJJvur5CofNCJq6t8JLvdjx5b+sLk1ERCoRBSSpkrr3uZnDf0hlk60FUWTR8OOhfP/Ph0C3KBERkVJQQJIqq3mL1sTf+xkrw6/BZpi03TKHLbMGUHDssNWliYhIgFNAkiotKiKcXslv8UmLyeSZDlpmruLXWd04/NM3VpcmIiIBTAFJqjybzSDx9mTWJy5ij1mXGE86oW/1Z8fyF60uTUREApQCklQbXbtfgWfkZ3wZ1BkXBTT+3/38+MofMd15VpcmIiIBRgFJqpVG9evR/r6P+XetP+I1DS7Y8x67Z/Yi79BOq0sTEZEAooAk1U6YK5hrRs8kJeFZfjXDaZi7mfznenJw3VKrSxMRkQChgCTVkmEY9L/hDrbdsJTvaUaUmUmtxbex44NH9FUAIiKigCTVW6eEjkSPXkGKMxEbJo3Xz2THc9dj5v5qdWkiImIhBSSp9urVrsHl9/2ThfEPkG86aPzL5xya2Y2cXeusLk1ERCwSZHUBIoHA5bBzy8gH+HhZAu1XjaGBez/5r/XhwFVPUuOSP1hdnohUc16vSZ67kNzcHPJysyjIzaIgNwd3Xvbxnxy8Bdm4c7PI3rmdtCV7sDuCMQw7hj0IwxaEYQ/CZrNj2B0YNhs2uwPb8edsQXYMmwO73X58uR1b0PHfJ5YHObAHBWG3B2EPchT9ttuw2wzshoHdZmAYhtUvVblRQBI5zjAM+idezbomqez+53C6m2upu2Icu7alUSuoGeyvB2E1IDgcgsOKfqrQ/wxEpOxM06TA4yUvN5+83Czyj/8U5GZTmJ9NYV7Rb09+Dt6CHMyCHLzuXHDnYLhzMQpzsRXmYS/Mxe7JI8ibh+P4T7CZj/P4j4t8Qigg1DBLV9iGit3vEzymgQcbbuzkYcODDS92CrHhxYbHsBf9xo75u8dew44XO17DjmmceGzDNILwGjZMw45p2IlKnMAFCT3Pz86cJCAC0nPPPcdTTz1Feno6HTt25Nlnn6VLly6nbL9o0SIefvhhduzYQYsWLXjiiSfo37+/73nTNJk8eTIvv/wyR44coUePHrzwwgu0aNHC1+bw4cOMGTOGf//739hsNm666SaeeeYZwsPDK3RfJfAlXNCEA/cu5Z2XxnPzsbdpuH0hDQG2/s2vnReDfCOEAnsIBbZQ3EFheIJC8TjC8AaFYQaHgzMcmzMMwxmJPSQCR0g4jpAogkMjCQ6NIDg0EsMZcTxwhYPNbsk+VyhPIYX5WeTlZJGfc/zDIy8bd14WhXnZePKzKczPwZufjVmQg+nOgYJcjMKiDxCbJxd7YS5Bv/vwaF1osv37v1Noc+G1B+OxufAGOTHtTrxBLrA7weGCIBc2RwiGw4XhCMEe7MLuCMHuDCEoOJQgVwiO4BCCXWE4XCEEO0NxukKxBYdUzbGoptyFHnJycsnNOUpe9jHyczIpyMnCnZuJOy8LT14W3vwszPxsTHeuL7j4wosnlyDv8fefJ59gM88vuLgoIMrwEFVRO1DC32Fu7OTjJN9wUmA4KbC5KLQ5cdtc5BZ4cAU7iuKKWYhherGZnqLfeLCZx3/w+n7b8WAzT0SZ44+P/7Zz6lBmN0zseABP6fbFPOn3GWzIPFi6hhXA8oC0cOFCkpOTmTt3Ll27dmXWrFkkJiayZcsW6tatW6z9qlWrGDx4MNOmTeOaa65h/vz5JCUlsWbNGtq1awfAk08+yezZs3njjTdo0qQJDz/8MImJifzwww+4XC4Abr/9dvbv309qaiput5vhw4czatQo5s+ff173XwJT3chQbrj3WebPv4gLtr5ELY4SauQTRi7h5GEzTGyYhJg5hBTmAL9AwblvNw8nebYQ8m2h5NtCKbSH+IKX1xGOeSJIOcOxOSOwucIJckUSFBpBcEgEztAogsOjCAmLxBESCXbHabdnegpx52UX/eWbfYz8vGwKcrNw52Xj+f1fvvnZmO6iv36L/vLNwSjMw1aYW/ThcfwDxOHNJ9ib6/vL10U+wRQSBIQf/yk35fB6n47btJNvBFNAMG4jmALDSaEtmEIjmEKbE48tGI/dhdfuxGt3YdqDIciFGVQUzIxgF0bQb8HMFhyK3eHyhTOHKwS7w0WQIxi7w0FQkJMgRzBBwU4cDif2oOCikFaNjlKapkluXh45WZnkZR8lPyeLgtxMCnKOUZh7jMK8bLz5x46H6SwoyMHmzsZWmFMUogtzcHhzCPbk4jTzcJm5hJh5hJBfMQGmhKHxmAZ5hpN8fgsu7uPBxWMPwWN34QkKwbS7MB0h4AjFcIRgOEKwOUOxBYdhd4YS5ArD4QwjyBVGcEgYzpDw4z9h2IJDcdgdOCj+35Tb7Wbp0qX0798fh+P0//2XmmmC1wOmB7yFmN5CPIWFFBYW4vW68RR6MD1uCj2FmIWFeDyFeI//eAqPt/cUYno9eD1uvB4P5vHn8Rb9Nr2FeD0n+vdgegsxPR4aNOtYPvtwFgzTNEuZ4ypG165dufjii5kzZw4AXq+XBg0aMGbMGB544IFi7QcNGkR2djYffvihb9kll1xCQkICc+fOxTRN4uPj+ctf/sJ9990HwNGjR4mJieH111/n1ltvZdOmTbRp04ZvvvmGzp07A5CSkkL//v3Zs2cP8fHxZ6w7MzOTqKgojh49SmRkZHm8FEAFvbnlnBzKzOFfH6fSpfulFHgNcvMLycvNwp2TiTv3GIV5x/DmHcObfwzys6AgC1tBNjZ3NvbCbByebIIKc3B6c3B6c3GZuYSauYQZeYRR9OMwSvnXVxnl4yAXF7lGCPk2F0Fm4W/hxczHabgrZLsl8ZoGuQSTi8v3V2++4cJtc+G2u4o+OI5/gHgdIRAUgukIK/rwCA7FFhyKzRkGQU5+2vojTRvEY3oKMN15mO7com9EL8zDKMwHTy62wnwMTz52Tz42bz5Bvp8CHGbRT7CZj8N046QAJwUEV9A4nC2vaVCInULDjhsHHuy4jSA8BOH5/e/jP15bEKYRhMfm+O23LQjTcGDaHZg2B9iCisKcLQjswWBzYNiLlhl2Bza7A4KCMYIc2OzBGEHB2O0ObI7gomtTgoKxO4KxBwVjdzgxDRtfpq2iY7tWePJzKczNxJ2fjTf3tyBjFuRgc2dhc+dgK8whqDDXF2SCvbm4zDxCzFxCyKvwMcjDQS4h5BkuCmwhFNhCcNtDKAwKxWMPwRsUUhRcgkLg+HvPCA7FHhyK3RmK3RlGkDMMR0gYwa4wnK5wgkPDcIVG4HCGFf1RYmGo1WfImZX289vSI0gFBQWsXr2aCRMm+JbZbDZ69+5NWlpaieukpaWRnJzstywxMZHFixcDsH37dtLT0+ndu7fv+aioKLp27UpaWhq33noraWlpREdH+8IRQO/evbHZbHz11VfccMMNxbabn59Pfn6+73FmZiZQ9GZ0u8vvQ+ZEX+XZp5yb0CCo7YJmtVy/+x9O9Dn1Wejxkuv2kFXg4UB+Ibm5uRTkZuLOOUZBbiaevCw8eccw87Mw849BQRaGu+hDxu4uClwOTw7BnpyiDxhvDiEU/bUcTp4v+Dhx48RNtHms+BHw3/0//ER4yTt+yD7fcFFgOH3hpfD4X7/eIFfRB0hQCKYj9PgHSBi24BBswaEEOcOKPkBcoQSHhBPsCiP4+F++Ia4Qgh12gs/xw8PtdpORm0pC7z7l+gFQ6PFypMBNfn4u7rxc3PnZFOTnUpifS2FBDp78XDwFeXjceXgKco4Hs7yTglketsI8DE8+Nk8+dm9RQAvyFmA3C3B4833BLJgCHGYhRTGnEAeF2E+6vsRmmARTSDCFwPH//5TxFMX50Bhg+zl2ctLbosAMItdwkWe4yDNOBBkXhfbQojATFIoZFHr8qGoYRnA4dmcoNlc4DlcEjpCIovdeaCTO0AhcYZEEh4RhtwWV/9HM49wmUFhYAT2XoQZ9hpxRaV8bSwPSoUOH8Hg8xMTE+C2PiYlh8+bNJa6Tnp5eYvv09HTf8yeWna7NyafvgoKCqFmzpq/NyaZNm8YjjzxSbPmyZcsIDQ091S6etdTU1HLvU87N+R+TCHBGgDOu1GuYJnhMKCgsxCzMx3TnQmEeHD+aYtqDwFZ0VMCwO7EFBWMEObHbHcdnoJxDuR4gB8gpBDKP/1Qca/4bcRb9GFEQTNFPOfGa4PF6MT0nTjF4wPzdv72FRac5vIVgejC9XgyzaJnhLcQwi9obpgfb8cfGice+61AKsXk92Cg8fh1KIXaz6LH9+HUpQcf/baew6PqTE8vwFIW4449/C3YeCrGTi7MozFAUsE8cJXTbXL7rYzw2Z9ERQtvx05JBzqLrxYKcRacjg5zYjv827Gf58VRw/CezADh8/Kf60WfIqeXk5JSqneXXIFUWEyZM8DtylZmZSYMGDejbt2+5n2JLTU2lT5/y/etYzp7GJLBoPAKL2+1m5fHxqKnxsJz++zizE2eAzsTSgFS7dm3sdjsZGRl+yzMyMoiNjS1xndjY2NO2P/E7IyODuLg4vzYJCQm+NgcOHPDro7CwkMOHD59yu06nE6fTWWy5w+GokDdhRfUrZ09jElg0HoFF4xFYNB6nVtrXxdJv0g4ODqZTp06sWLHCt8zr9bJixQq6detW4jrdunXzaw9FhxJPtG/SpAmxsbF+bTIzM/nqq698bbp168aRI0dYvXq1r82nn36K1+ula9eu5bZ/IiIiUjlZfootOTmZoUOH0rlzZ7p06cKsWbPIzs5m+PDhAAwZMoR69eoxbdo0AMaOHUuvXr2YMWMGAwYMYMGCBXz77be89NJLQNGX/Y0bN47HHnuMFi1a+Kb5x8fHk5SUBEDr1q3p168fI0eOZO7cubjdbkaPHs2tt95aqhlsIiIiUrVZHpAGDRrEwYMHmTRpEunp6SQkJJCSkuK7yHrXrl3YbL8d6OrevTvz589n4sSJPPjgg7Ro0YLFixf7vgMJ4P777yc7O5tRo0Zx5MgRevbsSUpKiu87kADefvttRo8ezVVXXeX7osjZs2efvx0XERGRgGV5QAIYPXo0o0ePLvG5zz77rNiygQMHMnDgwFP2ZxgGU6dOZerUqadsU7NmTX0ppIiIiJTI0muQRERERAKRApKIiIjISRSQRERERE6igCQiIiJyEgUkERERkZMoIImIiIicRAFJRERE5CQKSCIiIiInUUASEREROUlAfJN2ZWSaJlB0I9zy5Ha7ycnJITMzU3diDhAak8Ci8QgsGo/AovE4sxOf2yc+x09FAeksHTt2DIAGDRpYXImIiIiU1bFjx4iKijrl84Z5pgglJfJ6vezbt4+IiAgMwyi3fjMzM2nQoAG7d+8mMjKy3PqVs6cxCSwaj8Ci8QgsGo8zM02TY8eOER8fj8126iuNdATpLNlsNurXr19h/UdGRurNHWA0JoFF4xFYNB6BReNxeqc7cnSCLtIWEREROYkCkoiIiMhJFJACjNPpZPLkyTidTqtLkeM0JoFF4xFYNB6BReNRfnSRtoiIiMhJdARJRERE5CQKSCIiIiInUUASEREROYkCkoiIiMhJFJACzHPPPUfjxo1xuVx07dqVr7/+2uqSqqVp06Zx8cUXExERQd26dUlKSmLLli1WlyXH/f3vf8cwDMaNG2d1KdXW3r17+cMf/kCtWrUICQmhffv2fPvtt1aXVW15PB4efvhhmjRpQkhICM2aNePRRx894/3G5NQUkALIwoULSU5OZvLkyaxZs4aOHTuSmJjIgQMHrC6t2vnPf/7D3XffzZdffklqaiput5u+ffuSnZ1tdWnV3jfffMOLL75Ihw4drC6l2vr111/p0aMHDoeDjz/+mB9++IEZM2ZQo0YNq0urtp544gleeOEF5syZw6ZNm3jiiSd48sknefbZZ60urdLSNP8A0rVrVy6++GLmzJkDFN3vrUGDBowZM4YHHnjA4uqqt4MHD1K3bl3+85//cNlll1ldTrWVlZXFRRddxPPPP89jjz1GQkICs2bNsrqsaueBBx7giy++4L///a/Vpchx11xzDTExMbz66qu+ZTfddBMhISG89dZbFlZWeekIUoAoKChg9erV9O7d27fMZrPRu3dv0tLSLKxMAI4ePQpAzZo1La6kerv77rsZMGCA338ncv4tWbKEzp07M3DgQOrWrcuFF17Iyy+/bHVZ1Vr37t1ZsWIFP/74IwDr16/nf//7H1dffbXFlVVeulltgDh06BAej4eYmBi/5TExMWzevNmiqgSKjuSNGzeOHj160K5dO6vL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", "text/plain": [ "
" ] diff --git a/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb index 99b9f27..dc19519 100644 --- a/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb +++ b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb @@ -6,19 +6,19 @@ "source": [ "# Periodic systems in Grad DFT\n", "\n", - "In this tutorial, you will learn how to train a simple neural functional for solids. Birllouin Zone (BZ) samping is performed at the $\\Gamma$-point. This converges the electronic structure only at the large supercell limit. We won't work with large supercells in this tutorial, so for accurate results, please consider this.\n", + "In this tutorial, you will learn how to train a simple neural functional for solids. First Brillouin Zone (1BZ) samping is performed at the $\\Gamma$-point. This converges the electronic structure only at the large supercell limit. We won't work with large supercells in this tutorial, so for accurate results, please consider this.\n", "\n", - "Full BZ sampling is discussed in `~examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb`,\n", + "Full 1BZ sampling is discussed in `~examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb`,\n", "\n", "## Perform solid-state calculations with PySCF\n", "\n", - "PySCF implements DFT and some wavefunction methods in periodic boundary conditions with integration over the first BZ. To begin, we need:\n", + "PySCF implements DFT and some wavefunction methods in periodic boundary conditions with integration over the 1BZ. To begin, we need:\n", "\n", "(1) A DFT starting point to prime Grad DFT. Let's use the LDA.\n", "\n", "(2) Accurate training and validation data. We'll use the periodic Coupled Cluster Singles and Doubles (CCSD) implemented in PySCF\n", "\n", - "Our calculations will be run using carbon in the diamond structure." + "Our calculations will be run using Carbon in the diamond structure." ] }, { From 0174903e59fa5c8b2219de9d3608043cb1d7416d Mon Sep 17 00:00:00 2001 From: PabloAMC Date: Fri, 8 Dec 2023 13:50:01 +0100 Subject: [PATCH 36/36] Adding colab badges --- .../periodic_systems_bz_sampling_05.ipynb | 105 ++++++++++-------- ...periodic_systems_gamma_point_only_04.ipynb | 17 +++ 2 files changed, 73 insertions(+), 49 deletions(-) diff --git a/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb index 0d38a17..060c590 100644 --- a/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb +++ b/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb @@ -1,5 +1,22 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/XanaduAI/GradDFT/blob/main/examples/intermediate_notebooks/periodic_systems_bz_sampling_05.ipynb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# In colab run\n", + "# !pip install git+https://github.com/XanaduAI/GradDFT.git" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -30,7 +47,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/pyscf/dft/libxc.py:771: UserWarning: Since PySCF-2.3, B3LYP (and B3P86) are changed to the VWN-RPA variant, corresponding to the original definition by Stephens et al. (issue 1480) and the same as the B3LYP functional in Gaussian. To restore the VWN5 definition, you can put the setting \"B3LYP_WITH_VWN5 = True\" in pyscf_conf.py\n", + "/Users/pablo.casares/miniforge3/envs/graddft/lib/python3.10/site-packages/pyscf/dft/libxc.py:772: UserWarning: Since PySCF-2.3, B3LYP (and B3P86) are changed to the VWN-RPA variant, the same to the B3LYP functional in Gaussian and ORCA (issue 1480). To restore the VWN5 definition, you can put the setting \"B3LYP_WITH_VWN5 = True\" in pyscf_conf.py\n", " warnings.warn('Since PySCF-2.3, B3LYP (and B3P86) are changed to the VWN-RPA variant, '\n" ] } @@ -105,6 +122,13 @@ "execution_count": 3, "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " does not have attributes nlcgrids nlc\n" + ] + }, { "name": "stdout", "output_type": "stream", @@ -113,45 +137,45 @@ "WARN: HOMO 0.133342844043 == LUMO 0.133342844043\n", "\n", "\n", - "WARN: HOMO 0.129696509843 == LUMO 0.129696796322\n", + "WARN: HOMO 0.129696510302 == LUMO 0.129696796143\n", "\n", "\n", - "WARN: HOMO 0.123485666222 == LUMO 0.12353379514\n", + "WARN: HOMO 0.123485609714 == LUMO 0.123533794981\n", "\n", "\n", - "WARN: HOMO 0.122470531599 == LUMO 0.122549652121\n", + "WARN: HOMO 0.122470342913 == LUMO 0.122549417589\n", "\n", "\n", - "WARN: HOMO 0.121977358086 == LUMO 0.121984607601\n", + "WARN: HOMO 0.121977200489 == LUMO 0.121984450283\n", "\n", "\n", - "WARN: HOMO 0.127197661889 == LUMO 0.127213548187\n", + "WARN: HOMO 0.127199590342 == LUMO 0.127215372837\n", "\n", "\n", - "WARN: HOMO 0.12742779891 == LUMO 0.127575039567\n", + "WARN: HOMO 0.127429516524 == LUMO 0.127576695046\n", "\n", "SCF not converged.\n", - "SCF energy = -613.999832362389\n", + "SCF energy = -613.999831522497\n", "\n", "WARN: HOMO 0.136411628811 == LUMO 0.136411628812\n", "\n", "\n", - "WARN: HOMO 0.113400603597 == LUMO 0.113620213077\n", + "WARN: HOMO 0.113400677255 == LUMO 0.113620213224\n", "\n", "\n", - "WARN: HOMO 0.114842685494 == LUMO 0.115091645752\n", + "WARN: HOMO 0.114848903144 == LUMO 0.115097636252\n", "\n", "\n", - "WARN: HOMO 0.179108001182 == LUMO 0.179217499383\n", + "WARN: HOMO 0.178814138743 == LUMO 0.17892358234\n", "\n", "\n", - "WARN: HOMO 0.180326657467 == LUMO 0.180385178642\n", + "WARN: HOMO 0.180008068011 == LUMO 0.180066156279\n", "\n", "\n", - "WARN: HOMO 0.180259244142 == LUMO 0.180281025243\n", + "WARN: HOMO 0.179951129106 == LUMO 0.179972904236\n", "\n", "SCF not converged.\n", - "SCF energy = -613.984244474623\n" + "SCF energy = -613.984277821783\n" ] } ], @@ -185,10 +209,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "converged SCF energy = -614.443314677292\n", - "E(RCCSD) = -614.4825393595152 E_corr = -0.03922468222342814\n", - "converged SCF energy = -614.434597523732\n", - "E(RCCSD) = -614.4738196894283 E_corr = -0.03922216569629878\n" + "converged SCF energy = -614.443314677291\n", + "E(RCCSD) = -614.4825393595149 E_corr = -0.03922468222342719\n", + "converged SCF energy = -614.434597523731\n", + "E(RCCSD) = -614.4738196894269 E_corr = -0.03922216569629406\n" ] } ], @@ -225,28 +249,11 @@ "execution_count": 5, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/k8/81tnbcsx5lv94kjrw7pj513r0000gq/T/ipykernel_57191/2351384841.py:1: DeprecationWarning: Accessing jax.config via the jax.config submodule is deprecated.\n", - " from jax.config import config\n" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ - "WARNING:tensorflow:From /Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/tensorflow/python/compat/v2_compat.py:108: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n", - "Instructions for updating:\n", - "non-resource variables are not supported in the long term\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING:tensorflow:From /Users/jack.baker/miniconda3/envs/gdft/lib/python3.10/site-packages/tensorflow/python/compat/v2_compat.py:108: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n", + "WARNING:tensorflow:From /Users/pablo.casares/miniforge3/envs/graddft/lib/python3.10/site-packages/tensorflow/python/compat/v2_compat.py:107: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n", "Instructions for updating:\n", "non-resource variables are not supported in the long term\n" ] @@ -409,28 +416,28 @@ "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 50%|█████ | 5/10 [00:45<00:41, 8.39s/it]" + "Training epoch: 50%|█████ | 5/10 [01:11<01:08, 13.70s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 5 training loss = 0.00021681116222285106, validation loss = 0.00022159278002315468\n" + "At epoch 5 training loss = 0.00021681184278852755, validation loss = 0.00022157386004632528\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 100%|██████████| 10/10 [01:24<00:00, 8.41s/it]" + "Training epoch: 100%|██████████| 10/10 [02:17<00:00, 13.78s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 10 training loss = 3.611193058348861e-07, validation loss = 1.789025202725588e-07\n" + "At epoch 10 training loss = 3.611312949052283e-07, validation loss = 1.7956748122185697e-07\n" ] }, { @@ -461,7 +468,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -470,7 +477,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAABxCklEQVR4nO3dd3wUdf7H8dfsJtn0hARICITQIr1IFVCBkyZYQCliocjB71SwoJ6i0k+xIioK6inoCQdi4ThFJCA2iIAgClJE6SWhE0jd7M7vj5A9lwQIIcmkvJ+Pxz7Y/c53vvOZ+S7sh5nvfMcwTdNERERERDxsVgcgIiIiUtooQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRIRERE5hxIkERERkXMoQRKRErF7924Mw2DOnDmFWt8wDCZOnFikMUn5NXToUGrVqmV1GFKGKUGScm3OnDkYhoG/vz8HDhzIs7xz5840adLEgshybNq0iX79+hEXF4e/vz/Vq1enW7duvPbaa3nqulwuZs+eTefOnYmIiMDhcFCrVi2GDRvGjz/+6KmXu8/5vR5//PELxjNv3jymT59e1LtZLv35OH///fd5lpumSWxsLIZhcMMNN3gtO3PmDBMmTKBJkyYEBQURGRlJixYteOCBBzh48KCn3sSJE8/bl4ZhkJSUVOz7KVJR+VgdgEhJyMzM5Nlnn8038bDK6tWr6dKlCzVr1mTEiBFER0ezb98+fvjhB1555RVGjx7tqZuens4tt9zC0qVLufbaa3niiSeIiIhg9+7dfPjhh7z33nvs3buXGjVqeNaZPHkytWvX9trmxZLBefPmsXnzZh588MEi3VeAuLg40tPT8fX1LdT66enp+PiUvn+y/P39mTdvHldffbVX+TfffMP+/ftxOBxe5U6nk2uvvZZt27YxZMgQRo8ezZkzZ/j111+ZN28effv2JSYmxmudmTNnEhwcnGfb4eHhRb4/IpKj9P1rI1IMWrRowdtvv83YsWPz/PhY5emnnyYsLIx169bl+aE7fPiw1+dHH32UpUuX8vLLL+dJXiZMmMDLL7+cp/3rr7+e1q1bF3XYHhkZGfj5+WGzFexEdO6ZvMK6nHWLU69evVi4cCGvvvqqVwI3b948WrVqxdGjR73qL1q0iJ9++om5c+dy++23ey3LyMggKysrzzb69etH5cqVi2cHSojb7SYrK6vU9qPIuXSJTSqEJ554ApfLxbPPPnvRutnZ2UyZMoW6det6LmM98cQTZGZmetWrVasWN9xwA99//z1t27bF39+fOnXq8P777xcopj/++IPGjRvnexagatWqnvf79+/nzTffpFu3bvme2bHb7TzyyCNeZ48Ko3Pnznz++efs2bPHcwkndwzH119/jWEYzJ8/n6eeeorq1asTGBhISkoKx48f55FHHqFp06YEBwcTGhrK9ddfz88//+zVfn5jkIYOHUpwcDAHDhygT58+BAcHU6VKFR555BFcLpfX+ueOQcq9/PT7778zdOhQwsPDCQsLY9iwYaSlpXmtm56ezv3330/lypUJCQnhpptu4sCBA/mOa9q2bRt79+4t8HEbNGgQx44dIyEhwVOWlZXFRx99lCcBgpx+B+jYsWOeZf7+/oSGhhZ42wXxwQcf0KpVKwICAoiIiOC2225j3759XnVyLzVv2bKFLl26EBgYSPXq1Xn++efztJeZmcmECROoV68eDoeD2NhY/v73v+f5+2EYBqNGjWLu3Lk0btwYh8PB0qVLAfjll1/o1KkTAQEB1KhRg3/84x/Mnj0bwzDYvXs3AEOGDKFy5co4nc48MXTv3p369etf8rFITU3l4YcfJjY2FofDQf369XnxxRcxTdOrXkJCAldffTXh4eEEBwdTv359nnjiCa86r732Go0bNyYwMJBKlSrRunVr5s2bd8kxSemlM0hSIdSuXZvBgwfz9ttv8/jjj1/wLNJf//pX3nvvPfr168fDDz/MmjVrmDp1Klu3buXTTz/1qvv777/Tr18/hg8fzpAhQ3j33XcZOnQorVq1onHjxheMKS4ujsTERDZv3nzBS19ffPEF2dnZ3HXXXZe0z6dOncpz9uJCZyGefPJJTp06xf79+z1npM69rDNlyhT8/Px45JFHyMzMxM/Pjy1btrBo0SL69+9P7dq1SU5O5s0336RTp05s2bLlomfsXC4XPXr0oF27drz44ossX76cl156ibp163LPPfdcdD8HDBhA7dq1mTp1Khs2bOCf//wnVatW5bnnnvPUGTp0KB9++CF33XUXV111Fd988w29e/fOt72GDRvSqVMnvv7664tuG3IS5fbt2/Pvf/+b66+/Hsjps1OnTnHbbbfx6quvetWPi4sD4P333+epp57CMIyLbuP48eN5ynx8fC56ie3pp59m3LhxDBgwgL/+9a8cOXKE1157jWuvvZaffvrJa/0TJ07Qs2dPbrnlFgYMGMBHH33EY489RtOmTT375Xa7uemmm/j+++8ZOXIkDRs2ZNOmTbz88sv89ttvLFq0yGv7X331FR9++CGjRo2icuXK1KpViwMHDtClSxcMw2Ds2LEEBQXxz3/+M8+lyLvuuov333+fL7/80msMV1JSEl999RUTJky46HH7M9M0uemmm1i5ciXDhw+nRYsWfPnllzz66KMcOHDA853/9ddfueGGG2jWrBmTJ0/G4XDw+++/s2rVKk9bb7/9Nvfffz/9+vXjgQceICMjg19++YU1a9bkmxRLGWWKlGOzZ882AXPdunXmH3/8Yfr4+Jj333+/Z3mnTp3Mxo0bez5v3LjRBMy//vWvXu088sgjJmB+9dVXnrK4uDgTML/99ltP2eHDh02Hw2E+/PDDF41t2bJlpt1uN+12u9m+fXvz73//u/nll1+aWVlZXvUeeughEzB/+umnS9rn/F4X07t3bzMuLi5P+cqVK03ArFOnjpmWlua1LCMjw3S5XF5lu3btMh0Ohzl58mSvMsCcPXu2p2zIkCEm4FXPNE3zyiuvNFu1auVVBpgTJkzwfJ4wYYIJmHfffbdXvb59+5qRkZGez+vXrzcB88EHH/SqN3To0Dxt5m6nU6dOeY7Buf783ZoxY4YZEhLiOTb9+/c3u3TpYppmzvekd+/envXS0tLM+vXrm4AZFxdnDh061HznnXfM5OTkPNvI3cf8XvXr179gfLt37zbtdrv59NNPe5Vv2rTJ9PHx8Srv1KmTCZjvv/++pywzM9OMjo42b731Vk/Zv/71L9Nms5nfffedV5uzZs0yAXPVqlWeMsC02Wzmr7/+6lV39OjRpmEYXt/nY8eOmRERESZg7tq1yzRN03S5XGaNGjXMgQMHeq0/bdo00zAMc+fOnRfc/yFDhnh9lxctWmQC5j/+8Q+vev369TMNwzB///130zRN8+WXXzYB88iRI+dt++abb/b6d0PKJ11ikwqjTp063HXXXbz11lscOnQo3zpLliwBYMyYMV7lDz/8MACff/65V3mjRo245pprPJ+rVKlC/fr12blz50Xj6datG4mJidx00038/PPPPP/88/To0YPq1auzePFiT72UlBQAQkJCCrCX//P666+TkJDg9bpcQ4YMISAgwKvM4XB4xiG5XC6OHTvmuSyxYcOGArX7t7/9zevzNddcU6BjeL51jx075jluuZd17r33Xq96fx4E/2emaRb47FGuAQMGkJ6ezmeffcbp06f57LPPznsmISAggDVr1vDoo48COXfDDR8+nGrVqjF69Og8l6oAPv744zx9OXv27AvG9Mknn+B2uxkwYABHjx71vKKjo4mPj2flypVe9YODg7nzzjs9n/38/Gjbtq1XPyxcuJCGDRvSoEEDrzb/8pe/AORps1OnTjRq1MirbOnSpbRv354WLVp4yiIiIrjjjju86tlsNu644w4WL17M6dOnPeVz586lQ4cOeW5AuJglS5Zgt9u5//77vcoffvhhTNPkiy++AP438P0///kPbrc737bCw8PZv38/69atu6QYpGxRgiQVylNPPUV2dvZ5xyLt2bMHm81GvXr1vMqjo6MJDw9nz549XuU1a9bM00alSpU4ceIEkJMwJCUleb3+PAi3TZs2fPLJJ5w4cYK1a9cyduxYTp8+Tb9+/diyZQuAZ0zKn38kCqJt27Z07drV63W58vtRcrvdvPzyy8THx+NwOKhcuTJVqlThl19+4dSpUxdt09/fnypVqniV/fkYXsy5fVCpUiUAz/q5fXpu7Of28eWoUqUKXbt2Zd68eXzyySe4XC769et33vphYWE8//zz7N69m927d/POO+9Qv359ZsyYwZQpU/LUv/baa/P0Zfv27S8Y044dOzBNk/j4eKpUqeL12rp1a54bAWrUqJHnct+5/bBjxw5+/fXXPO1dccUVQN6bC/L7vuzZsyffY59f2eDBg0lPT/dc2t6+fTvr16+/5MvNuduNiYnJ8x+Nhg0bepYDDBw4kI4dO/LXv/6VqKgobrvtNj788EOvZOmxxx4jODiYtm3bEh8fz3333ed1CU7KB41BkgqlTp063Hnnnbz11lsXnBOoIONCIGeAdH7Ms4M+9+3bl+dHYuXKlXTu3NmrzM/PjzZt2tCmTRuuuOIKhg0bxsKFC5kwYQINGjQAcuZM+vP/uq1w7tkjgGeeeYZx48Zx9913M2XKFCIiIrDZbDz44IPn/R/4n53vGBbUxfqgpNx+++2MGDGCpKQkrr/++gLfgh8XF8fdd99N3759qVOnDnPnzuUf//jHZcfjdrsxDIMvvvgi32N07viyghxHt9tN06ZNmTZtWr51Y2NjvT7n9325FI0aNaJVq1Z88MEHDB48mA8++AA/Pz8GDBhwWe1eSEBAAN9++y0rV67k888/Z+nSpSxYsIC//OUvLFu2DLvdTsOGDdm+fTufffYZS5cu5eOPP+aNN95g/PjxTJo0qdhik5KlBEkqnKeeeooPPvjAaxBvrri4ONxuNzt27PD8zxIgOTmZkydPegbYFlR0dHSeS1vNmze/4Dq5t+bnXga8/vrrsdvtfPDBB4X6n/OlKGhi+GcfffQRXbp04Z133vEqP3nyZKm4NT23T3ft2kV8fLyn/Pfffy/S7fTt25f/+7//44cffmDBggWXvH6lSpWoW7cumzdvLpJ46tati2ma1K5d23OGpyja/Pnnn7nuuusK9V2BnP7I79ifrz8GDx7MmDFjOHToEPPmzaN3796es4SXut3ly5dz+vRpr7NI27Zt8yzPZbPZuO6667juuuuYNm0azzzzDE8++SQrV670nIkNCgpi4MCBDBw4kKysLG655Raefvppxo4dq6kMygldYpMKp27dutx55528+eabeWYi7tWrF0Ce2aRz/8d8vjufzsff3z/PpZHcf9xXrlyZ71mO3HFQubcxx8bGMmLECJYtW5bvRJdut5uXXnqJ/fv3X1Js+QkKCirQZbE/s9vtefZj4cKF+c5cboUePXoA8MYbb3iVn2/S0Eu9zT9XcHAwM2fOZOLEidx4443nrffzzz/nubsQci7xbNmypVC3r+fnlltuwW63M2nSpDz9Y5omx44du+Q2BwwYwIEDB3j77bfzLEtPTyc1NfWibfTo0YPExEQ2btzoKTt+/Dhz587Nt/6gQYMwDIMHHniAnTt3eo2TuhS9evXC5XIxY8YMr/KXX34ZwzA8d+rld8dg7pnb3PFh5x47Pz8/GjVqhGma+U5LIGWTziBJhfTkk0/yr3/9i+3bt3vdjt+8eXOGDBnCW2+9xcmTJ+nUqRNr167lvffeo0+fPnTp0qXIYhg9ejRpaWn07duXBg0akJWVxerVq1mwYIHnESK5XnrpJf744w/uv/9+PvnkE2644QYqVarE3r17WbhwIdu2beO222677JhatWrFggULGDNmDG3atCE4OPiCP/YAN9xwA5MnT2bYsGF06NCBTZs2MXfuXOrUqXPZ8RSFVq1aceuttzJ9+nSOHTvmuc3/t99+A/KeNbvU2/z/bMiQIRetk5CQwIQJE7jpppu46qqrCA4OZufOnbz77rtkZmbm+7y5jz76KN+ZtLt160ZUVFS+26lbty7/+Mc/GDt2LLt376ZPnz6EhISwa9cuPv30U0aOHMkjjzxySft311138eGHH/K3v/2NlStX0rFjR1wuF9u2bePDDz/kyy+/vOjkpH//+9/54IMP6NatG6NHj/bc5l+zZk2OHz+epz+qVKlCz549WbhwIeHh4Zf8n5RcN954I126dOHJJ59k9+7dNG/enGXLlvGf//yHBx98kLp16wI5M9B/++239O7dm7i4OA4fPswbb7xBjRo1PLOld+/enejoaDp27EhUVBRbt25lxowZ9O7d+5JvppBSzJqb50RKxp9vxT5X7i3m596u63Q6zUmTJpm1a9c2fX19zdjYWHPs2LFmRkaGV71zb9/O1alTpwLdJv7FF1+Yd999t9mgQQMzODjY9PPzM+vVq2eOHj0631u+s7OzzX/+85/mNddcY4aFhZm+vr5mXFycOWzYMK9bpi+0zxdz5swZ8/bbbzfDw8M9t6Gb5v9u81+4cGGedTIyMsyHH37YrFatmhkQEGB27NjRTExMzHMcznebf1BQUJ42c29v/zPOc5v/ubdj5+5/7u3ipmmaqamp5n333WdGRESYwcHBZp8+fczt27ebgPnss8/m2c6l3uZ/Ied+T3bu3GmOHz/evOqqq8yqVauaPj4+ZpUqVczevXt7TSPx530832vlypUXjfPjjz82r776ajMoKMgMCgoyGzRoYN53333m9u3bPXXOne4i17m3ypumaWZlZZnPPfec2bhxY9PhcJiVKlUyW7VqZU6aNMk8deqUpx5g3nffffnG9NNPP5nXXHON6XA4zBo1aphTp041X331VRMwk5KS8tT/8MMPTcAcOXLkRff3QrGfPn3afOihh8yYmBjT19fXjI+PN1944QXT7XZ76qxYscK8+eabzZiYGNPPz8+MiYkxBw0aZP7222+eOm+++aZ57bXXmpGRkabD4TDr1q1rPvroo177L2WfYZolPJJRRKQU2LhxI1deeSUffPBBnlvMpeQ9+OCDvPnmm5w5cybPgPH//Oc/9OnTh2+//dZrWg2R4qQxSCJS7qWnp+cpmz59OjabjWuvvdaCiCq2c/vj2LFj/Otf/+Lqq6/O9266t99+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1atXM3fuXObMmVOU8UkJSo3MGahtaKC2iIhUcIVKkJxOJw6HA4Dly5dz0003AdCgQQOvh8tK2eKomTOjdmTKVosjERERsVahEqTGjRsza9YsvvvuOxISEujZsycABw8eJDIyskgDlJIT07AdAFGuJNypJyyORkRExDqFSpCee+453nzzTTp37sygQYNo3rw5AIsXL/ZcepOyp06N6uw1qwKQtF0DtUVEpOLyKcxKnTt35ujRo6SkpFCpUiVP+ciRIwkMDCyy4KRk+dht7PO/gpqZhznxx4/EtLze6pBEREQsUagzSOnp6WRmZnqSoz179jB9+nS2b99O1apVizRAKVmpEY0BMA5ttDYQERERCxUqQbr55pt5//33ATh58iTt2rXjpZdeok+fPsycObNIA5SS5RebM1C70ikN1BYRkYqrUAnShg0buOaaawD46KOPiIqKYs+ePbz//vu8+uqrRRqglKzoBlcBUM11ADP9pLXBiIiIWKRQCVJaWhohISEALFu2jFtuuQWbzcZVV13Fnj17ijRAKVl1atZkv1kZgOQdP1ocjYiIiDUKlSDVq1ePRYsWsW/fPr788ku6d+8OwOHDhwkNDS3SAKVk+fnY2OeIB+D4jrUWRyMiImKNQiVI48eP55FHHqFWrVq0bduW9u3bAzlnk6688soiDVBK3umInBm13Qc1o7aIiFRMhbrNv1+/flx99dUcOnTIMwcSwHXXXUffvn2LLDixhm+NKyEJKp361epQRERELFGoBAkgOjqa6Oho9u/fD0CNGjU0SWQ5EX1FO/gRqmXvx8w8jeEIsTokERGRElWoS2xut5vJkycTFhZGXFwccXFxhIeHM2XKFNxud1HHKCWsTp3aJJkR2DA5rIHaIiJSARXqDNKTTz7JO++8w7PPPkvHjh0B+P7775k4cSIZGRk8/fTTRRqklCyHj53dfvFEO9dwfMdaopp0sTokERGRElWoBOm9997jn//8JzfddJOnrFmzZlSvXp17771XCVI5cLpSYzi8BtfBjVaHIiIiUuIKdYnt+PHjNGjQIE95gwYNOH78+GUHJdaz18i5GzHs5BaLIxERESl5hUqQmjdvzowZM/KUz5gxg2bNml12UGK9qle0AyDGuRczK9XiaEREREpWoS6xPf/88/Tu3Zvly5d75kBKTExk3759LFmypEgDFGvUq1uPw2Y4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NatDK7N0m38p0q5dO9q0acOMGTOAnOe9xcbGMnr0aB5//HGLo6vYjhw5QtWqVfnmm2+49tprrQ6nwjpz5gwtW7bkjTfe4B//+ActWrRg+vTpVodV4Tz++OOsWrWK7777zupQ5KwbbriBqKgo3nnnHU/ZrbfeSkBAAB988IGFkZVdOoNUSmRlZbF+/Xq6du3qKbPZbHTt2pXExEQLIxOAU6dOARAREWFxJBXbfffdR+/evb3+nkjJW7x4Ma1bt6Z///5UrVqVK6+8krffftvqsCq0Dh06sGLFCn777TcAfv75Z77//nuuv/56iyMru/Sw2lLi6NGjuFwuoqKivMqjoqLYtm2bRVEJ5JzJe/DBB+nYsSNNmjSxOpwKa/78+WzYsIF169ZZHUqFt3PnTmbOnMmYMWN44oknWLduHffffz9+fn4MGTLE6vAqpMcff5yUlBQaNGiA3W7H5XLx9NNPc8cdd1gdWpmlBEnkIu677z42b97M999/b3UoFda+fft44IEHSEhIwN/f3+pwKjy3203r1q155plnALjyyivZvHkzs2bNUoJkkQ8//JC5c+cyb948GjduzMaNG3nwwQeJiYlRnxSSEqRSonLlytjtdpKTk73Kk5OTiY6OtigqGTVqFJ999hnffvstNWrUsDqcCmv9+vUcPnyYli1bespcLhfffvstM2bMIDMzE7vdbmGEFUu1atVo1KiRV1nDhg35+OOPLYpIHn30UR5//HFuu+02AJo2bcqePXuYOnWqEqRC0hikUsLPz49WrVqxYsUKT5nb7WbFihW0b9/ewsgqJtM0GTVqFJ9++ilfffUVtWvXtjqkCu26665j06ZNbNy40fNq3bo1d9xxBxs3blRyVMI6duyYZ9qL3377jbi4OIsikrS0NGw27590u92O2+22KKKyT2eQSpExY8YwZMgQWrduTdu2bZk+fTqpqakMGzbM6tAqnPvuu4958+bxn//8h5CQEJKSkgAICwsjICDA4ugqnpCQkDzjv4KCgoiMjNS4MAs89NBDdOjQgWeeeYYBAwawdu1a3nrrLd566y2rQ6uwbrzxRp5++mlq1qxJ48aN+emnn5g2bRp333231aGVWbrNv5SZMWMGL7zwAklJSbRo0YJXX32Vdu3aWR1WhWMYRr7ls2fPZujQoSUbjOSrc+fOus3fQp999hljx45lx44d1K5dmzFjxjBixAirw6qwTp8+zbhx4/j00085fPgwMTExDBo0iPHjx+Pn52d1eGWSEiQRERGRc2gMkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiBSSYRgsWrTI6jBEpBgoQRKRMmno0KEYhpHn1bNnT6tDE5FyQM9iE5Eyq2fPnsyePdurzOFwWBSNiJQnOoMkImWWw+EgOjra61WpUiUg5/LXzJkzuf766wkICKBOnTp89NFHXutv2rSJv/zlLwQEBBAZGcnIkSM5c+aMV513332Xxo0b43A4qFatGqNGjfJafvToUfr27UtgYCDx8fEsXrzYs+zEiRPccccdVKlShYCAAOLj4/MkdCJSOilBEpFya9y4cdx66638/PPP3HHHHdx2221s3boVgNTUVHr06EGlSpVYt24dCxcuZPny5V4J0MyZM7nvvvsYOXIkmzZtYvHixdSrV89rG5MmTWLAgAH88ssv9OrVizvuuIPjx497tr9lyxa++OILtm7dysyZM6lcuXLJHQARKTxTRKQMGjJkiGm3282goCCv19NPP22apmkC5t/+9jevddq1a2fec889pmma5ltvvWVWqlTJPHPmjGf5559/btpsNjMpKck0TdOMiYkxn3zyyfPGAJhPPfWU5/OZM2dMwPziiy9M0zTNG2+80Rw2bFjR7LCIlCiNQRKRMqtLly7MnDnTqywiIsLzvn379l7L2rdvz8aNGwHYunUrzZs3JygoyLO8Y8eOuN1utm/fjmEYHDx4kOuuu+6CMTRr1szzPigoiNDQUA4fPgzAPffcw6233sqGDRvo3r07ffr0oUOHDoXaVxEpWUqQRKTMCgoKynPJq6gEBAQUqJ6vr6/XZ8MwcLvdAFx//fXs2bOHJUuWkJCQwHXXXcd9993Hiy++WOTxikjR0hgkESm3fvjhhzyfGzZsCEDDhg35+eefSU1N9SxftWoVNpuN+vXrExISQq1atVixYsVlxVClShWGDBnCBx98wPTp03nrrbcuqz0RKRk6gyQiZVZmZiZJSUleZT4+Pp6B0AsXLqR169ZcffXVzJ07l7Vr1/LOO+8AcMcddzBhwgSGDBnCxIkTOXLkCKNHj+auu+4iKioKgIkTJ/K3v/2NqlWrcv3113P69GlWrVrF6NGjCxTf+PHjadWqFY0bNyYzM5PPPvvMk6CJSOmmBElEyqylS5dSrVo1r7L69euzbds2IOcOs/nz53PvvfdSrVo1/v3vf9OoUSMAAgMD+fLLL3nggQdo06YNgYGB3HrrrUybNs3T1pAhQ8jIyODll1/mkUceoXLlyvTr16/A8fn5+TF27Fh2795NQEAA11xzDfPnzy+CPReR4maYpmlaHYSISFEzDINPP/2UPn36WB2KiJRBGoMkIiIicg4lSCIiIiLn0BgkESmXNHpARC6HziCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInEMJkoiIiMg5lCCJiIiInOP/AelQk1YrSjIxAAAAAElFTkSuQmCC", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABxCklEQVR4nO3dd3wUdf7H8dfsJtn0hFASAiG0SC9SRVTgpAkWkCYWihz87hRQsaLSz8OKqCiop6AnHIiF4xSRgKgnRKooSBGVDgk9gdTN7vz+CNlzSYAQkkzK+/l47IPd73znO5+Z78J+mPnOdwzTNE1ERERExMNmdQAiIiIipY0SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROY8SJBEpEXv37sUwDObNm1eo9Q3DYPLkyUUak5Rfw4YNo3bt2laHIWWYEiQp1+bNm4dhGPj7+3Po0KE8yzt37kzTpk0tiCzH1q1b6d+/P7Gxsfj7+1OjRg26devGa6+9lqeuy+Vi7ty5dO7cmYiICBwOB7Vr12b48OFs3LjRUy93n/N7PfHEExeNZ8GCBcycObOod7Nc+uNx/u677/IsN02TmJgYDMPg5ptv9lp29uxZJk2aRNOmTQkKCqJy5cq0bNmSBx54gMOHD3vqTZ48+YJ9aRgGiYmJxb6fIhWVj9UBiJSEzMxMnn322XwTD6usXbuWLl26UKtWLUaOHElUVBQHDhzg+++/55VXXmHMmDGeuunp6dx+++0sX76cG264gSeffJKIiAj27t3Lhx9+yHvvvcf+/fupWbOmZ52pU6dSp04dr21eKhlcsGAB27Zt48EHHyzSfQWIjY0lPT0dX1/fQq2fnp6Oj0/p+yfL39+fBQsWcN1113mVf/PNNxw8eBCHw+FV7nQ6ueGGG9i5cydDhw5lzJgxnD17lp9//pkFCxbQt29foqOjvdaZPXs2wcHBebYdHh5e5PsjIjlK3782IsWgZcuWvP3224wfPz7Pj49VnnnmGcLCwtiwYUOeH7qjR496fX700UdZvnw5L7/8cp7kZdKkSbz88st52r/pppto06ZNUYftkZGRgZ+fHzZbwU5E557JK6wrWbc49erVi8WLF/Pqq696JXALFiygdevWHD9+3Kv+kiVL+OGHH5g/fz533nmn17KMjAyysrLybKN///5UqVKleHaghLjdbrKyskptP4qcT5fYpEJ48skncblcPPvss5esm52dzbRp06hXr57nMtaTTz5JZmamV73atWtz8803891339GuXTv8/f2pW7cu77//foFi+u2332jSpEm+ZwGqVavmeX/w4EHefPNNunXrlu+ZHbvdziOPPOJ19qgwOnfuzOeff86+ffs8l3Byx3B8/fXXGIbBwoULefrpp6lRowaBgYGkpKRw8uRJHnnkEZo1a0ZwcDChoaHcdNNN/Pjjj17t5zcGadiwYQQHB3Po0CH69OlDcHAwVatW5ZFHHsHlcnmtf/4YpNzLT7/++ivDhg0jPDycsLAwhg8fTlpamte66enpjB07lipVqhASEsKtt97KoUOH8h3XtHPnTvbv31/g4zZ48GBOnDhBfHy8pywrK4uPPvooTwIEOf0O0LFjxzzL/P39CQ0NLfC2C+KDDz6gdevWBAQEEBERwR133MGBAwe86uReat6+fTtdunQhMDCQGjVq8Pzzz+dpLzMzk0mTJlG/fn0cDgcxMTE89thjef5+GIbB6NGjmT9/Pk2aNMHhcLB8+XIAfvrpJzp16kRAQAA1a9bkb3/7G3PnzsUwDPbu3QvA0KFDqVKlCk6nM08M3bt3p0GDBpd9LFJTU3n44YeJiYnB4XDQoEEDXnzxRUzT9KoXHx/PddddR3h4OMHBwTRo0IAnn3zSq85rr71GkyZNCAwMpFKlSrRp04YFCxZcdkxSeukMklQIderUYciQIbz99ts88cQTFz2L9Oc//5n33nuP/v378/DDD7Nu3TqmT5/Ojh07+PTTT73q/vrrr/Tv358RI0YwdOhQ3n33XYYNG0br1q1p0qTJRWOKjY0lISGBbdu2XfTS1xdffEF2djb33HPPZe1zcnJynrMXFzsL8dRTT5GcnMzBgwc9Z6TOv6wzbdo0/Pz8eOSRR8jMzMTPz4/t27ezZMkSBgwYQJ06dUhKSuLNN9+kU6dObN++/ZJn7FwuFz169KB9+/a8+OKLrFy5kpdeeol69erx17/+9ZL7OXDgQOrUqcP06dPZvHkz//jHP6hWrRrPPfecp86wYcP48MMPueeee7jmmmv45ptv6N27d77tNWrUiE6dOvH1119fctuQkyh36NCBf/3rX9x0001ATp8lJydzxx138Oqrr3rVj42NBeD999/n6aefxjCMS27j5MmTecp8fHwueYntmWeeYcKECQwcOJA///nPHDt2jNdee40bbriBH374wWv9U6dO0bNnT26//XYGDhzIRx99xOOPP06zZs08++V2u7n11lv57rvvGDVqFI0aNWLr1q28/PLL/PLLLyxZssRr+1999RUffvgho0ePpkqVKtSuXZtDhw7RpUsXDMNg/PjxBAUF8Y9//CPPpch77rmH999/ny+//NJrDFdiYiJfffUVkyZNuuRx+yPTNLn11ltZvXo1I0aMoGXLlnz55Zc8+uijHDp0yPOd//nnn7n55ptp3rw5U6dOxeFw8Ouvv7JmzRpPW2+//TZjx46lf//+PPDAA2RkZPDTTz+xbt26fJNiKaNMkXJs7ty5JmBu2LDB/O2330wfHx9z7NixnuWdOnUymzRp4vm8ZcsWEzD//Oc/e7XzyCOPmID51VdfecpiY2NNwPz22289ZUePHjUdDof58MMPXzK2FStWmHa73bTb7WaHDh3Mxx57zPzyyy/NrKwsr3oPPfSQCZg//PDDZe1zfq9L6d27txkbG5unfPXq1SZg1q1b10xLS/NalpGRYbpcLq+yPXv2mA6Hw5w6dapXGWDOnTvXUzZ06FAT8KpnmqZ59dVXm61bt/YqA8xJkyZ5Pk+aNMkEzHvvvderXt++fc3KlSt7Pm/atMkEzAcffNCr3rBhw/K0mbudTp065TkG5/vjd2vWrFlmSEiI59gMGDDA7NKli2maOd+T3r17e9ZLS0szGzRoYAJmbGysOWzYMPOdd94xk5KS8mwjdx/zezVo0OCi8e3du9e02+3mM88841W+detW08fHx6u8U6dOJmC+//77nrLMzEwzKirK7Nevn6fsn//8p2mz2cz//ve/Xm3OmTPHBMw1a9Z4ygDTZrOZP//8s1fdMWPGmIZheH2fT5w4YUZERJiAuWfPHtM0TdPlcpk1a9Y0Bw0a5LX+jBkzTMMwzN9///2i+z906FCv7/KSJUtMwPzb3/7mVa9///6mYRjmr7/+apqmab788ssmYB47duyCbd92221e/25I+aRLbFJh1K1bl3vuuYe33nqLI0eO5Ftn2bJlAIwbN86r/OGHHwbg888/9ypv3Lgx119/vedz1apVadCgAb///vsl4+nWrRsJCQnceuut/Pjjjzz//PP06NGDGjVqsHTpUk+9lJQUAEJCQgqwl//z+uuvEx8f7/W6UkOHDiUgIMCrzOFweMYhuVwuTpw44bkssXnz5gK1+5e//MXr8/XXX1+gY3ihdU+cOOE5brmXde677z6ven8cBP9HpmkW+OxRroEDB5Kens5nn33GmTNn+Oyzzy54JiEgIIB169bx6KOPAjl3w40YMYLq1aszZsyYPJeqAD7++OM8fTl37tyLxvTJJ5/gdrsZOHAgx48f97yioqKIi4tj9erVXvWDg4O5++67PZ/9/Pxo166dVz8sXryYRo0a0bBhQ682//SnPwHkabNTp040btzYq2z58uV06NCBli1besoiIiK46667vOrZbDbuuusuli5dypkzZzzl8+fP59prr81zA8KlLFu2DLvdztixY73KH374YUzT5IsvvgD+N/D93//+N263O9+2wsPDOXjwIBs2bLisGKRsUYIkFcrTTz9Ndnb2Bcci7du3D5vNRv369b3Ko6KiCA8PZ9++fV7ltWrVytNGpUqVOHXqFJCTMCQmJnq9/jgIt23btnzyySecOnWK9evXM378eM6cOUP//v3Zvn07gGdMyh9/JAqiXbt2dO3a1et1pfL7UXK73bz88svExcXhcDioUqUKVatW5aeffiI5OfmSbfr7+1O1alWvsj8ew0s5vw8qVaoE4Fk/t0/Pj/38Pr4SVatWpWvXrixYsIBPPvkEl8tF//79L1g/LCyM559/nr1797J3717eeecdGjRowKxZs5g2bVqe+jfccEOevuzQocNFY9q9ezemaRIXF0fVqlW9Xjt27MhzI0DNmjXzXO47vx92797Nzz//nKe9q666Csh7c0F+35d9+/ble+zzKxsyZAjp6emeS9u7du1i06ZNl325OXe70dHRef6j0ahRI89ygEGDBtGxY0f+/Oc/ExkZyR133MGHH37olSw9/vjjBAcH065dO+Li4rj//vu9LsFJ+aAxSFKh1K1bl7vvvpu33nrronMCFWRcCOQMkM6PeW7Q54EDB/L8SKxevZrOnTt7lfn5+dG2bVvatm3LVVddxfDhw1m8eDGTJk2iYcOGQM6cSX/8X7cVzj97BPD3v/+dCRMmcO+99zJt2jQiIiKw2Ww8+OCDF/wf+B9d6BgW1KX6oKTceeedjBw5ksTERG666aYC34IfGxvLvffeS9++falbty7z58/nb3/72xXH43a7MQyDL774It9jdP74soIcR7fbTbNmzZgxY0a+dWNiYrw+5/d9uRyNGzemdevWfPDBBwwZMoQPPvgAPz8/Bg4ceEXtXkxAQADffvstq1ev5vPPP2f58uUsWrSIP/3pT6xYsQK73U6jRo3YtWsXn332GcuXL+fjjz/mjTfeYOLEiUyZMqXYYpOSpQRJKpynn36aDz74wGsQb67Y2Fjcbje7d+/2/M8SICkpidOnT3sG2BZUVFRUnktbLVq0uOg6ubfm514GvOmmm7Db7XzwwQeF+p/z5ShoYvhHH330EV26dOGdd97xKj99+nSpuDU9t0/37NlDXFycp/zXX38t0u307duX//u//+P7779n0aJFl71+pUqVqFevHtu2bSuSeOrVq4dpmtSpU8dzhqco2vzxxx+58cYbC/VdgZz+yO/YX6g/hgwZwrhx4zhy5AgLFiygd+/enrOEl7vdlStXcubMGa+zSDt37vQsz2Wz2bjxxhu58cYbmTFjBn//+9956qmnWL16tedMbFBQEIMGDWLQoEFkZWVx++2388wzzzB+/HhNZVBO6BKbVDj16tXj7rvv5s0338wzE3GvXr0A8swmnfs/5gvd+XQh/v7+eS6N5P7jvnr16nzPcuSOg8q9jTkmJoaRI0eyYsWKfCe6dLvdvPTSSxw8ePCyYstPUFBQgS6L/ZHdbs+zH4sXL8535nIr9OjRA4A33njDq/xCk4Ze7m3+uYKDg5k9ezaTJ0/mlltuuWC9H3/8Mc/dhZBziWf79u2Fun09P7fffjt2u50pU6bk6R/TNDlx4sRltzlw4EAOHTrE22+/nWdZeno6qampl2yjR48eJCQksGXLFk/ZyZMnmT9/fr71Bw8ejGEYPPDAA/z+++9e46QuR69evXC5XMyaNcur/OWXX8YwDM+devndMZh75jZ3fNj5x87Pz4/GjRtjmma+0xJI2aQzSFIhPfXUU/zzn/9k165dXrfjt2jRgqFDh/LWW29x+vRpOnXqxPr163nvvffo06cPXbp0KbIYxowZQ1paGn379qVhw4ZkZWWxdu1aFi1a5HmESK6XXnqJ3377jbFjx/LJJ59w8803U6lSJfbv38/ixYvZuXMnd9xxxxXH1Lp1axYtWsS4ceNo27YtwcHBF/2xB7j55puZOnUqw4cP59prr2Xr1q3Mnz+funXrXnE8RaF169b069ePmTNncuLECc9t/r/88guQ96zZ5d7m/0dDhw69ZJ34+HgmTZrErbfeyjXXXENwcDC///477777LpmZmfk+b+6jjz7Kdybtbt26ERkZme926tWrx9/+9jfGjx/P3r176dOnDyEhIezZs4dPP/2UUaNG8cgjj1zW/t1zzz18+OGH/OUvf2H16tV07NgRl8vFzp07+fDDD/nyyy8vOTnpY489xgcffEC3bt0YM2aM5zb/WrVqcfLkyTz9UbVqVXr27MnixYsJDw+/7P+k5Lrlllvo0qULTz31FHv37qVFixasWLGCf//73zz44IPUq1cPyJmB/ttvv6V3797ExsZy9OhR3njjDWrWrOmZLb179+5ERUXRsWNHIiMj2bFjB7NmzaJ3796XfTOFlGLW3DwnUjL+eCv2+XJvMT//dl2n02lOmTLFrFOnjunr62vGxMSY48ePNzMyMrzqnX/7dq5OnToV6DbxL774wrz33nvNhg0bmsHBwaafn59Zv359c8yYMfne8p2dnW3+4x//MK+//nozLCzM9PX1NWNjY83hw4d73TJ9sX2+lLNnz5p33nmnGR4e7rkN3TT/d5v/4sWL86yTkZFhPvzww2b16tXNgIAAs2PHjmZCQkKe43Ch2/yDgoLytJl7e/sfcYHb/M+/HTt3/3NvFzdN00xNTTXvv/9+MyIiwgwODjb79Olj7tq1ywTMZ599Ns92Lvc2/4s5/3vy+++/mxMnTjSvueYas1q1aqaPj49ZtWpVs3fv3l7TSPxxHy/0Wr169SXj/Pjjj83rrrvODAoKMoOCgsyGDRua999/v7lr1y5PnfOnu8h1/q3ypmmaWVlZ5nPPPWc2adLEdDgcZqVKlczWrVubU6ZMMZOTkz31APP+++/PN6YffvjBvP76602Hw2HWrFnTnD59uvnqq6+agJmYmJin/ocffmgC5qhRoy65vxeL/cyZM+ZDDz1kRkdHm76+vmZcXJz5wgsvmG6321Nn1apV5m233WZGR0ebfn5+ZnR0tDl48GDzl19+8dR58803zRtuuMGsXLmy6XA4zHr16pmPPvqo1/5L2WeYZgmPZBQRKQW2bNnC1VdfzQcffJDnFnMpeQ8++CBvvvkmZ8+ezTNg/N///jd9+vTh22+/9ZpWQ6Q4aQySiJR76enpecpmzpyJzWbjhhtusCCiiu38/jhx4gT//Oc/ue666/K9m+7tt9+mbt26eR4ILFKcNAZJRMq9559/nk2bNtGlSxd8fHz44osv+OKLLxg1alSeW9Ol+HXo0IHOnTvTqFEjkpKSeOedd0hJSWHChAle9RYuXMhPP/3E559/ziuvvFLoO+dECkOX2ESk3IuPj2fKlCls376ds2fPUqtWLe655x6eeuopfHz0/8SS9uSTT/LRRx9x8OBBDMOgVatWTJo0Kc9kpoZhEBwczKBBg5gzZ476SkqUEiQRERGR82gMkoiIiMh5lCCJiIiInEcXdAvJ7XZz+PBhQkJCNHBQRESkjDBNkzNnzhAdHY3NduHzREqQCunw4cO6+0VERKSMOnDgADVr1rzgciVIhZQ7nfyBAwcIDQ0tsnadTicrVqyge/fu+Pr6Flm7Unjqk9JF/VG6qD9KF/XHpaWkpBATE3PJx8IoQSqk3MtqoaGhRZ4gBQYGEhoaqi93KaE+KV3UH6WL+qN0UX8U3KWGx2iQtoiIiMh5lCCJiIiInEcJkoiIiMh5NAZJRERKBZfLhdPptDqMMs3pdOLj40NGRgYul8vqcCzh6+ub70OPL5cSJBERsZRpmiQmJnL69GmrQynzTNMkKiqKAwcOVOg5+sLDw4mKirqiY6AESURELJWbHFWrVo3AwMAK/cN+pdxuN2fPniU4OPiikyCWV6ZpkpaWxtGjRwGoXr16odtSgiQiIpZxuVye5Khy5cpWh1Pmud1usrKy8Pf3r5AJEkBAQAAAR48epVq1aoW+3FYxj56IiJQKuWOOAgMDLY5EypPc79OVjGlTgiQiIpbTZTUpSkXxfVKCJCIiInIeJUgiIiKlQO3atZk5c2aB63/99dcYhlHsd//NmzeP8PDwYt1GaaQESURE5DIYhnHR1+TJkwvV7oYNGxg1alSB61977bUcOXKEsLCwQm1PLk53sZU27mxC0g9A5hnwjbA6GhEROc+RI0c87xctWsTEiRPZtWuXpyw4ONjz3jRNXC4XPj6X/rmtWrXqZcXh5+dHVFTUZa0jBaczSKWM7d0e/GnnU6Tv/tbqUEREJB9RUVGeV1hYGIZheD7v3LmTkJAQvvjiC1q3bo3D4eC7777jt99+47bbbiMyMpLg4GDatm3LypUrvdo9/xKbYRj84x//oG/fvgQGBhIXF8fSpUs9y8+/xDZv3jwiIiJYtWoVTZo0ITg4mJ49e3oldNnZ2YwdO5bw8HAqV67M448/ztChQ+nTp89lHYPZs2dTr149/Pz8aNCgAf/85z89y0zTZPLkydSqVQuHw0F0dDRjx471LH/jjTeIi4vD39+fyMhI+vfvf1nbLilKkEqZr07mzAOStGudxZGIiFjDNE3SsrJL/GWaZpHtwxNPPMGzzz7Ljh07aN68OWfPnqVXr16sWrWKH374gZ49e3LLLbewf//+i7YzZcoUBg4cyE8//USvXr246667OHny5AXrp6WlMWvWLN577z2+/fZb9u/fzyOPPOJZ/txzzzF//nzmzp3LmjVrSElJYcmSJZe1b59++ikPPPAADz/8MNu2beP//u//GD58OKtXrwbg448/5uWXX+bNN99k9+7dLFmyhGbNmgGwceNGxo4dy9SpU9m1axfLly/nhhtuuKztlxRdYitlzkY0gaSvMJJ+sjoUERFLpDtdNJ74ZYlvd/vUHgT6Fc3P4tSpU+nWrZvnc0REBC1atPB8njZtGp9++ilLly5l9OjRF2xn2LBhDB48GIC///3vvPrqq6xfv56ePXvmW9/pdDJjxgxatGiBzWZj9OjRTJ061bP8tddeY/z48fTt2xeAWbNmsWzZssvatxdffJFhw4Zx3333ATBu3Di+//57XnzxRbp06cL+/fuJioqia9eu+Pr6UqtWLdq1awfA/v37CQoK4uabbyYkJITY2Fiuvvrqy9p+SdEZpFLGt2bOF6Vyyg6LIxERkcJq06aN1+ezZ8/yyCOP0KhRI8LDwwkODmbHjh2XPIPUvHlzz/ugoCBCQ0M9j9HIT2BgIHXq1PF8rl69uqd+cnIySUlJnmQFwG6307p168vatx07dtCxY0evso4dO7JjR87v1oABA0hPT6du3bqMHDmSTz/9lOzsbAC6detGbGwsdevW5Z577mH+/PmkpaVd1vZLis4glTKRca1xbzSo5DoBZ5IgJNLqkERESlSAr53tU3tYst2iEhQU5PX5kUceIT4+nhdffJH69esTEBBA//79ycrKumg7vr6+Xp8Nw8Dtdl9W/aK8dFgQMTEx7Nq1i5UrVxIfH899993HCy+8wDfffENISAibN2/m66+/ZsWKFUycOJHJkyezYcOGUjeVgM4glTINYqL4zcx5uN6p3zZYHI2ISMkzDINAP58SfxXnbN5r1qxh2LBh9O3bl2bNmhEVFcXevXuLbXv5CQsLIzIykg0b/vfb4nK52Lx582W106hRI9asWeNVtmbNGho3buz5HBAQwC233MKrr77K119/TUJCAlu3bgXAx8eHrl278vzzz/PTTz+xd+9evvrqqyvYs+KhM0ilTICfnd9sdYjjMCd/3UClljdbHZKIiFyhuLg4PvnkE2655RYMw2DChAkXPRNUXMaMGcP06dOpX78+DRs25LXXXuPUqVOXlRw++uijDBw4kKuvvpquXbvyn//8h08++cRzV968efNwuVy0b9+ewMBAPvjgAwICAoiNjeWzzz7j999/54YbbqBSpUosW7YMt9tNgwYNimuXC00JUimU6FcbstZgHt5idSgiIlIEZsyYwb333su1115LlSpVePzxx0lJSSnxOB5//HESExMZMmQIdrudUaNG0aNHj8t64n2fPn145ZVXePHFF3nggQeoU6cOc+fOpXPnzgCEh4fz7LPPMm7cOFwuF82aNeM///kPlStXJjw8nE8++YTJkyeTkZFBXFwc//rXv2jSpEkx7fEVMEuBWbNmmbGxsabD4TDbtWtnrlu37qL1P/zwQ7NBgwamw+EwmzZtan7++eeeZVlZWeZjjz1mNm3a1AwMDDSrV69u3nPPPeahQ4e82oiNjTUBr9f06dMLHHNycrIJmMnJyZe3s5eQlZVlvvbKs6Y5KdQ8PrV+kbYthZOVlWUuWbLEzMrKsjoUMdUfpc2V9kd6erq5fft2Mz09vYgjq5hcLpd56tQp0+VyFbj+VVddZT799NPFHFnJutj3qqC/35aPQVq0aBHjxo1j0qRJbN68mRYtWtCjR48LjtJfu3YtgwcPZsSIEfzwww/06dOHPn36sG3bNiBnDojNmzczYcIENm/ezCeffMKuXbu49dZb87Q1depUjhw54nmNGTOmWPe1wMJiAajsOgqpJywORkREyot9+/bx9ttv88svv7B161b++te/smfPHu68806rQyt1LE+QZsyYwciRIxk+fDiNGzdmzpw5BAYG8u677+Zb/5VXXqFnz548+uijNGrUiGnTptGqVStmzZoF5AxCi4+PZ+DAgTRo0IBrrrmGWbNmsWnTpjy3U4aEhHjNiHr+XQdWqRYSwB53zvTxp3/XQG0RESkaNpuNefPm0bZtWzp27MjWrVtZuXIljRo1sjq0UsfSMUhZWVls2rSJ8ePHe8psNhtdu3YlISEh33USEhIYN26c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XniBb775hs6dOwM5l9f69etHWFgYYWFhPPLII576Y8aM4csvv+TDDz8sUIK0cuVKdu7cyZdffkl0dM6x+Pvf/55n3NDTTz/teV+7dm0efvhhFixYwIQJEwgICCA4ONjzOJcLWbBgARkZGbz//vueh7bPmjWLW265heeee85zV3mlSpWYNWsWdrudhg0b0rt3b1atWlXgBOnFF1/k8ccf54477gDgueeeY/Xq1cycOZPXX3+d/fv3ExcXx3XXXYdhGMTGxnrW3b9/P1FRUXTt2hVfX19q1apVoON4JXSJrZSrcm6gdrWsA5B59hK1RUSkJDRs2JBrr72Wd999F4Bff/2V//73v4wYMQLImSF82rRpNGvWjIiICIKDg/nyyy/Zv39/gdrfsWMHMTExnuQIyHcC5UWLFtGxY0eioqIIDg5mwoQJ+Y6NutS2WrRo4UmOADp27Ijb7WbXrl2esiZNmng9+LV69eocPXq0QNtISUnh8OHDdOzY0au8Y8eO7NixA8i5jLdlyxYaNGjA2LFjWbFihafegAEDSE9Pp27duowcOZJPP/00zzPWiprOIJVyDerV44gZQXXjJGf3/0Bw3PVWhyQiUrx8A3PO5lix3cswYsQIxowZw+uvv87cuXOpV68enTp1AuCFF17glVdeYebMmTRr1oygoCAefPDBIn0gb0JCAnfddRdTpkyhR48ehIWF8a9//YuXXnqpyLbxR+c/osMwDM+jTYpCq1at2LNnD1988QUrV65k4MCBdO3alY8++oiYmBh27drFypUriY+P57777vOcwSuuRw7pDFIpVynIj9/s9QA4umudxdGIiJQAw8i51FXSr8t8uOvAgQOx2WwsWLCA999/n3vvvdczHmnNmjXcdttt3H333bRo0YK6devyyy+/FLjtRo0aceDAAY4cOeIpO3/+vrVr1xIbG8tTTz1FmzZtiIuLY9++fV51/Pz8cLlcl9zWjz/+SGpqqqdszZo12Gy2fJ9NWhihoaFER0ezZs0ar/I1a9bQuHFjr3qDBg3i7bffZtGiRXz88cecPHkSgICAAG655RZeffVVvv76axISEti6dWuRxJcfnUEqA06FNYZTGzRQW0SkFAkODmbQoEGMHz+elJQUhg0b5lkWFxfHRx99xNq1a6lUqRIzZswgKSnJKxm4mK5du3LVVVcxdOhQXnjhBVJSUnjq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paWlFaieZQmSlUaNGuV536xZM6pXr86NN97Ib7/9Rr169fJdZ/z48V5nr1JSUoiJiaF79+5FennO6XQSHx9Pt27d8PX1LbJ2L+S7Xz6gcdo+YgLSadirV7Fvrywq6T6Ri1N/lC7qj9JF/XFpuVeALsWyBKlKlSrY7XaSkpK8ypOSkoiKisp3naioqMuqX1Dt27cH4Ndff71gguRwOHA4HHnKfX19i+VLWFztni+ranPYtwK/Y1v1l+kSSqpPpGDUH6WL+qN0UX9cWEGPi2WDtP38/GjdujWrVq3ylLndblatWkWHDh3yXadDhw5e9SHnNOKF6hdU7lQA1atXv6J2yqLA2udm1D6rgdoiIiK5LL3ENm7cOIYOHUqbNm1o164dM2fOJDU1leHDhwMwZMgQatSowfTp0wF44IEH6NSpEy+99BK9e/dm4cKFbNy4kbfeesvT5smTJ9m/fz+HDx8GYNeuXQCeu9V+++03FixYQK9evahcuTI//fQTDz30EDfccAPNmzcv4SNgvZhG7cj+2kY4p3GePoRvpZpWhyQiImI5S2/zHzRoEC+++CITJ06kZcuWbNmyheXLl3sGYu/fv58jR4546l977bUsWLCAt956ixYtWvDRRx+xZMkSmjZt6qmzdOlSrr76anr37g3AHXfcwdVXX82cOXOAnDNXK1eupHv37jRs2JCHH36Yfv368Z///KcE97z0qFWtMnuoAUDiznUWRyMiIlI6WD5Ie/To0YwePTrfZV9//XWesgEDBjBgwIALtjds2DCGDRt2weUxMTF88803lxtmuWWzGRwKbEBc+gFSft8AHfpZHZKIiIjlLH/UiFgvo0rOpUV70k8WRyIiIlI6KEESgmq3AqDq2fznnxIREalolCAJ0Q3b4zYNKrtPkJ185NIriIiIlHNKkIQ61auyh2gAknZpoLaIiIgSJMkZqB3QAIDTv220OBoRERHrKUESANKr5EyVYEv80eJIRERErKcESQDwj82ZUbvKGQ3UFhERUYIkANRo2A6Aqu6juM4etzgaERERaxUqQTpw4AAHDx70fF6/fj0PPvig1yM/pGypU6M6e8ycZ9El7vze4mhERESsVagE6c4772T16tUAJCYm0q1bN9avX89TTz3F1KlTizRAKRl2m8Eh/6sAOP3bBoujERERsVahEqRt27bRrl3OJZkPP/yQpk2bsnbtWubPn8+8efOKMj4pQamVcwZqGxqoLSIiFVyhEiSn04nD4QBg5cqV3HrrrQA0bNjQ6+GyUrY4auXMqF05ZYfFkYiIiFirUAlSkyZNmDNnDv/973+Jj4+nZ8+eABw+fJjKlSsXaYBScqIbtQcg0pWIO/WUxdGIiIhYp1AJ0nPPPcebb75J586dGTx4MC1atABg6dKlnktvUvbUrVmD/WY1ABJ3aaC2iIhUXD6FWalz584cP36clJQUKlWq5CkfNWoUgYGBRRaclCwfu40D/ldRK/Mop37bSHSrm6wOSURExBKFOoOUnp5OZmamJznat28fM2fOZNeuXVSrVq1IA5SSlRrRBADjyBZrAxEREbFQoRKk2267jffffx+A06dP0759e1566SX69OnD7NmzizRAKVl+MTkDtSsla6C2iIhUXIVKkDZv3sz1118PwEcffURkZCT79u3j/fff59VXXy3SAKVkRTW8BoDqrkOY6aetDUZERMQihUqQ0tLSCAkJAWDFihXcfvvt2Gw2rrnmGvbt21ekAUrJqlurFgfNKgAk7d5ocTQiIiLWKFSCVL9+fZYsWcKBAwf48ssv6d69OwBHjx4lNDS0SAOUkuXnY+OAIw6Ak7vXWxyNiIiINQqVIE2cOJFHHnmE2rVr065dOzp06ADknE26+uqrizRAKXlnInJm1HYf1ozaIiJSMRXqNv/+/ftz3XXXceTIEc8cSAA33ngjffv2LbLgxBq+Na+GRKiU/LPVoYiIiFiiUAkSQFRUFFFRURw8eBCAmjVrapLIciLqqvawEapnH8TMPIPhCLE6JBERkRJVqEtsbrebqVOnEhYWRmxsLLGxsYSHhzNt2jTcbndRxyglrG7dOiSaEdgwOaqB2iIiUgEV6gzSU089xTvvvMOzzz5Lx44dAfjuu++YPHkyGRkZPPPMM0UapJQsh4+dvX5xRDnXcWL3eiKbdrE6JBERkRJVqATpvffe4x//+Ae33nqrp6x58+bUqFGD++67TwlSOXCmUhM4ug734S1WhyIiIlLiCnWJ7eTJkzRs2DBPecOGDTl58uQVByXWs9fMuRsx7PR2iyMREREpeYVKkFq0aMGsWbPylM+aNYvmzZtfcVBivWpXtQcg2rkfMyvV4mhERERKVqEusT3//PP07t2blStXeuZASkhI4MCBAyxbtqxIAxRr1K9Xn6NmONWM0xz77QeqNrrO6pBERERKTKHOIHXq1IlffvmFvn37cvr0aU6fPs3tt9/Ozz//zD//+c+ijlEs4O9rZ69vfQCO/bLO4mhERERKVqHnQYqOjs4zGPvHH3/knXfe4a233rriwMR6yZWawLGNuA/9YHUoIiIiJapQZ5CkYrDXaAlA6CnNqC0iIhWLEiS5oCpxuQO192E60y2ORkREpOQoQZILiqvfgBNmCD64OLlni9XhiIiIlJjLGoN0++23X3T56dOnryQWKWUCHD5s861P5ewfOLprPZWv6mB1SCIiIiXishKksLCwSy4fMmTIFQUkpUtyWGM48QPZBzdbHYqIiEiJuawEae7cucUVh5RSthpXw4n5hJzSjNoiIlJxaAySXFTluHYARGf9DtlZFkcjIiJSMpQgyUXVj2vMaTMIP7I5ufdHq8MREREpEUqQ5KKC/H35zaceAEd3aUZtERGpGJQgySWdDmsCQNZBzagtIiIVgxIkuSQjugUAISe3WRyJiIhIyVCCJJdUqf65gdqZv4HLaXE0IiIixU8JklxS/QZNSTEDcODk9P6tVocjIiJS7JQgySWFBDg8A7UTd2qgtoiIlH9KkKRAToU2BiDrgAZqi4hI+acESQrErJ4zUDvopC6xiYhI+acESQokol5bAGpk/Apul8XRiIiIFC8lSFIgdRu15Kzpjz9ZpBz82epwREREipUSJCmQsEAHv9vrAHBkhwZqi4hI+aYESQrs+LmB2pn7N1kciYiISPFSgiQFZkblDNQOPKlLbCIiUr4pQZICq3RuoHZ0+i/gdlscjYiISPFRgiQFVqdhS9JNPwLJ4MzhnVaHIyIiUmwsT5Bef/11ateujb+/P+3bt2f9+vUXrb948WIaNmyIv78/zZo1Y9myZV7LP/nkE7p3707lypUxDIMtW7bkaSMjI4P777+fypUrExwcTL9+/UhKSirK3SqXKoUE8mvuQO2d31scjYiISPGxNEFatGgR48aNY9KkSWzevJkWLVrQo0cPjh49mm/9tWvXMnjwYEaMGMEPP/xAnz596NOnD9u2/e8p86mpqVx33XU899xzF9zuQw89xH/+8x8WL17MN998w+HDh7n99tuLfP/KoxPBDQFI37fZ4khERESKj6UJ0owZMxg5ciTDhw+ncePGzJkzh8DAQN59991867/yyiv07NmTRx99lEaNGjFt2jRatWrFrFmzPHXuueceJk6cSNeuXfNtIzk5mXfeeYcZM2bwpz/9idatWzN37lzWrl3L99/rrMiluKq3BCDwuGbUFhGR8svHqg1nZWWxadMmxo8f7ymz2Wx07dqVhISEfNdJSEhg3LhxXmU9evRgyZIlBd7upk2bcDqdXglUw4YNqVWrFgkJCVxzzTX5rpeZmUlmZqbnc0pKCgBOpxOn01ng7V9KbltF2WZRCom9GnZB9fRfcGZlgmH5VdpiV9r7pKJRf5Qu6o/SRf1xaQU9NpYlSMePH8flchEZGelVHhkZyc6d+Q8ATkxMzLd+YmJigbebmJiIn58f4eHhl9XO9OnTmTJlSp7yFStWEBgYWODtF1R8fHyRt1kUUrOyaWH6Emyk8flH75EdFHnplcqJ0tonFZX6o3RRf5Qu6o8LS0tLK1A9yxKksmb8+PFeZ69SUlKIiYmhe/fuhIaGFtl2nE4n8fHxdOvWDV9f3yJrtyjt3v53Gpu/Uq+aL/U69bI6nGJXFvqkIlF/lC7qj9JF/XFpuVeALsWyBKlKlSrY7fY8d48lJSURFRWV7zpRUVGXVf9CbWRlZXH69Gmvs0iXasfhcOBwOPKU+/r6FsuXsLjaLQpHgxvR+MyvZB7Ygq/vcKvDKTGluU8qIvVH6aL+KF3UHxdW0ONi2QASPz8/WrduzapVqzxlbrebVatW0aFDh3zX6dChg1d9yDmNeKH6+WndujW+vr5e7ezatYv9+/dfVjsVmSuyOQD+xzRQW0REyidLL7GNGzeOoUOH0qZNG9q1a8fMmTNJTU1l+PCcsxJDhgyhRo0aTJ8+HYAHHniATp068dJLL9G7d28WLlzIxo0beeuttzxtnjx5kv3793P48GEgJ/mBnDNHUVFRhIWFMWLECMaNG0dERAShoaGMGTOGDh06XHCAtngLrdsWfoXqabvANMEwrA5JRESkSFmaIA0aNIhjx44xceJEEhMTadmyJcuXL/cMxN6/fz822/9Ocl177bUsWLCAp59+mieffJK4uDiWLFlC06ZNPXWWLl3qSbAA7rjjDgAmTZrE5MmTAXj55Zex2Wz069ePzMxMevTowRtvvFECe1w+xDZqRdaXdkKNs6Qd3UNgZF2rQxIRESlSlg/SHj16NKNHj8532ddff52nbMCAAQwYMOCC7Q0bNoxhw4ZddJv+/v68/vrrvP7665cTqpxTrVIYO22xNDR/5/COBOorQRIRkXKm/E9iI8XiaFADAFL3bbI4EhERkaKnBEkKxVmtBQCOoxqoLSIi5Y8SJCmUkDqtAYjKHagtIiJSjihBkkKJbdKObNNGuJlMxon9VocjIiJSpJQgSaFUqxTG70YMAAe36yG/IiJSvihBkkIxDIOkoIYApO7daHE0IiIiRUsJkhRaVrVmAPhqoLaIiJQzSpCk0ILqtAEgKnWnxZGIiIgULSVIUmixjdrhMg0izFNknDxkdTgiIiJFRgmSFFpUlQj2GDUBOLxDA7VFRKT8UIIkhWYYBomBOTNqn9mjgdoiIlJ+KEGSK5KZO1A76SeLIxERESk6SpDkigTF5syoXVUDtUVEpBxRgiRXpGaj9rhNg6ru42QmJ1odjoiISJFQgiRXpEZkVfYZ1QE4vH2dxdGIiIgUDSVIckUMw+BwQM5A7ZQ9GyyORkREpGgoQZIrllk1Z6C2XQO1RUSknFCCJFcsIHeg9pkdFkciIiJSNJQgyRWr0ag9AJHuozjPHLc4GhERkSunBEmuWEz1KPYRBcChHQkWRyMiInLllCDJFTMMg8P+VwGQ/Ltm1BYRkbJPCZIUifTcgdqJGqgtIiJlnxIkKRL+MVcDUDlFA7VFRKTsU4IkRSK60TUAVHcfITv1lMXRiIiIXBklSFIkatWoyUGzKgCHd2pGbRERKduUIEmRsNkMDp6bUfvUr+stjkZEROTKKEGSIpNWuQkANg3UFhGRMk4JkhQZ/1o5M2pHpGy3OBIREZErowRJikxUw5wZtWu4DuFKT7Y4GhERkcJTgiRFJjYmliNmZQAO79Q4JBERKbuUIEmRsdsMDpybUfvkrxssjkZERKTwlCBJkTob0RQA48iPFkciIiJSeEqQpEg5zs2oXUkDtUVEpAxTgiRFKrJhzoza0c4DuDPOWhyNiIhI4ShBkiJVO7YOR81K2A2Tw79oHJKIiJRNSpCkSPnYbexzxAFwcrfuZBMRkbJJCZIUubMROTNqmxqoLSIiZZQSJClyvjVbARB++meLIxERESkcJUhS5KpddW5Gbed+3JlpFkcjIiJy+ZQgSZGrU7c+x80wfAw3ibs3WR2OiIjIZVOCJEXO18fOPr/6AJz94WOLoxEREbl8SpCkWByMuRWAq36by/Fv37E4GhERkcujBEmKRddBo/kwYCAA4V89QvJPyyyOSEREpOCUIEmxCHL40OWvr/GFvTM+uHF8Moz0vZo4UkREygYlSFJsqob603DUPBJojj+ZZL3fH+ex36wOS0RE5JKUIEmxqhNZiaB7/sV2szZh7tOcfvsWzLPHrA5LRETkopQgSbFrXq8mJ/vM54BZlapZh0iccxtkpVodloiIyAUpQZIScd3VTfmp0zucMoOpfvZnDr59B7iyrQ5LREQkX0qQpMT0/lMn4lu8QobpS81j33Lgg7+CaVodloiISB5KkKREDejbj8W1J+MyDWL2fMihf0+xOiQREZE8lCBJiTIMg8FD7mNBlbEA1NjyMklfv2VxVCIiIt6UIEmJ87Hb6P9/k1gcOAiAyl8/zqktn1kclYiIyP8oQRJLBPjZufG+1/jSpws+uAlYci9n96yzOiwRERFACZJYKCLYQeP/e4+1Rkv8ycT1zwFkHt1tdVgiIiKlI0F6/fXXqV27Nv7+/rRv357169dftP7ixYtp2LAh/v7+NGvWjGXLvJ/zZZomEydOpHr16gQEBNC1a1d27/b+4a1duzaGYXi9nn322SLfN7m4mKphhA9ZwM9mHcLcyaS8fSvuM0etDktERCo4yxOkRYsWMW7cOCZNmsTmzZtp0aIFPXr04OjR/H8k165dy+DBgxkxYgQ//PADffr0oU+fPmzbts1T5/nnn+fVV19lzpw5rFu3jqCgIHr06EFGRoZXW1OnTuXIkSOe15gxY4p1XyV/jevU4Ey/BTkTSToPayJJERGxnOUJ0owZMxg5ciTDhw+ncePGzJkzh8DAQN59991867/yyiv07NmTRx99lEaNGjFt2jRatWrFrFmzgJyzRzNnzuTpp5/mtttuo3nz5rz//vscPnyYJUuWeLUVEhJCVFSU5xUUFFTcuysXcE3zxuy4cS4nzWCiU7dz4M2BmkhSREQs42PlxrOysti0aRPjx4/3lNlsNrp27UpCQkK+6yQkJDBu3Divsh49eniSnz179pCYmEjXrl09y8PCwmjfvj0JCQnccccdnvJnn32WadOmUatWLe68804eeughfHzyPySZmZlkZmZ6PqekpADgdDpxOp2Xt+MXkdtWUbZZVnTpcA1LTrzKzVv+QsyJ79j73khq3P0mGIalcVXkPimN1B+li/qjdFF/XFpBj42lCdLx48dxuVxERkZ6lUdGRrJz585810lMTMy3fmJiomd5btmF6gCMHTuWVq1aERERwdq1axk/fjxHjhxhxowZ+W53+vTpTJmSd1LDFStWEBgYeIk9vXzx8fFF3mZZ4Gv4MDv4fh44O5Pa+z9h7Rsmx+r0tTosoOL2SWml/ihd1B+li/rjwtLS0gpUz9IEyUp/PAvVvHlz/Pz8+L//+z+mT5+Ow+HIU3/8+PFe66SkpBATE0P37t0JDQ0tsricTifx8fF069YNX1/fImu3LHG5b+Jfb5vcfXwm157+lENB7ajWaaRl8ahPShf1R+mi/ihd1B+XlnsF6FIsTZCqVKmC3W4nKSnJqzwpKYmoqKh814mKirpo/dw/k5KSqF69uledli1bXjCW9u3bk52dzd69e2nQoEGe5Q6HI9/EydfXt1i+hMXVblngC/T/v4l8PDOJfqn/IvK7p0iOqEHlVrdZG1cF7pPSSP1Ruqg/Shf1x4UV9LhYOkjbz8+P1q1bs2rVKk+Z2+1m1apVdOjQId91OnTo4FUfck4l5tavU6cOUVFRXnVSUlJYt27dBdsE2LJlCzabjWrVql3JLkkR8fe10/W+V/nS90Z8cBO09M+c+TX/cWkiIiJFzfJLbOPGjWPo0KG0adOGdu3aMXPmTFJTUxk+fDgAQ4YMoUaNGkyfPh2ABx54gE6dOvHSSy/Ru3dvFi5cyMaNG3nrrZzneRmGwYMPPsjf/vY34uLiqFOnDhMmTCA6Opo+ffoAOQO9161bR5cuXQgJCSEhIYGHHnqIu+++m0qVKllyHCSvsCA/mv1lHgmzbqGDuYWs+QPJ/MsqHJFXWR2aiIiUc5YnSIMGDeLYsWNMnDiRxMREWrZsyfLlyz2DrPfv34/N9r8TXddeey0LFizg6aef5sknnyQuLo4lS5bQtGlTT53HHnuM1NRURo0axenTp7nuuutYvnw5/v7+QM7lsoULFzJ58mQyMzOpU6cODz30UJ6748R60ZVDOXPvQn5+pxdNzN859vatRIz9Bnto5KVXFhERKSTDNE3T6iDKopSUFMLCwkhOTi7yQdrLli2jV69eun78Bxu37SRy8S3EGEc5FNiQ6AdWYjhCSmTb6pPSRf1Ruqg/Shf1x6UV9Pfb8okiRQqiTdOG/Np9HifNYGqk7WT/m4PApXk+RESkeChBkjKjS8eOfNfuDdJNP2JPrmHve6NAJ0BFRKQYKEGSMuXW3rfxn6uewWUa1N7/Cfs+ftrqkEREpBxSgiRlTv/BI1kclTOgPnbbLA6tfMPiiEREpLxRgiRljs1m0HfkU3wScicAUd89xbGNS6wNSkREyhUlSFImOXzsdLvvFVb4dcWOm5DPRpK8WxNJiohI0VCCJGVWSIAfLf46jwRbK/zJggUDST+S/0OORURELocSJCnTIiuFUG3Ev/iZuoSZKZx95zaykxOtDktERMo4JUhS5tWrEYVz0EL2m9Womp1I4pxbMTPPWB2WiIiUYUqQpFxo2agB+276JyfMEGqm72LfnAGaSFJERApNCZKUG9dfcw3rO8whzXRQ+1QCv787QhNJiohIoShBknLlpp43s7zR33GZBnUP/Zs9i5+0OiQRESmDlCBJudN30Ag+iX4EgDrb32D/ilkWRyQiImWNEiQpdwzDoM+fn+TT0HsAqLF2AonrP7E4KhERKUuUIEm55Gu30f2+l1nh6I4dN+HL/o+Tu/5rdVgiIlJGKEGScivI35er/zqXBHtr/MnCvvBOUg9rIkkREbk0JUhSrlUNDyb6z4vYRn3CzBRS37kNZ/IRq8MSEZFSTgmSlHux1avCnYvYZ0ZSzZVI4uxbMTNSrA5LRERKMSVIUiE0vao+R26ezwkzlJiMX9g7u78mkhQRkQtSgiQVxjVt2/LDdW+SZjqok7yO394ZrokkRUQkX0qQpELp2q0XK5s+R7Zpo97h//DboiesDklEREohJUhS4dzSfxj/jnkMgHo757B3+asWRyQiIqWNEiSpcAzD4Lbhj/Pv8KEAxHw/kcPfL7Y4KhERKU2UIEmF5GO30f2vM4j374Edk8rL7+PEDk0kKSIiOZQgSYUV4PChzf3zSLC3wUEWvh8O5uyh7VaHJSIipYASJKnQKoUEEjNqEduMOELNM6S924fMU4esDktERCymBEkqvJqRVbDftYh9ZhTVXEkcnXMb7nRNJCkiUpEpQRIBGtWvx7HbFuRMJJm5mz2z+0N2ltVhiYiIRZQgiZzTplVrtnZ6mzTTQb2Udez+xzBNJCkiUkEpQRL5g85/6snXLV4g27QRl/g5v/zrMatDEhERCyhBEjnPTX2H8HlszgzbV/3yFnu/1ESSIiIVjRIkkfMYhsHNwx7jPxHDAai3YRpVds8n68jPFkcmIiIlRQmSSD7sNoNuf3mR+MBe2AyTjme/JOjdThx4/hoOxL+BmX7a6hBFRKQYKUESuQB/Px86jH2fTxu8wFdmG5ymnZi0HcSsGU/mc3HsnnMnydu/Arfb6lBFRKSI+VgdgEhpFuzvy839h/PZ55Gsr12PY2s+oOnRpdQ3DhGX+Dl8+DnHfKqT3HAQsX8agW9ELatDFhGRIqAESaQAbAa0a9IA35bPkpw2lS++/RJjywd0TP+GqtlHqLptJu5tr/BbWHsC2w2levt+4OOwOmwRESkkJUgilyks0I+bet4CPW/hlwNJfPXVB9TY8zFt+Jl6yd9D/PekrHyMI7VuocafRhIc28rqkEVE5DIpQRK5AlfFRHLV0Idxuh7i240bSU54jzanllGdk4TuWwBzF3DQEUdW8zup3XkYtqAIq0MWEZECUIIkUgR87TZuaN8O2rfjaHIqy776mKCfF9LB+T01M3fDhilkbXiGPVW6EHHdvVRt3gNsdqvDFhGRC1CCJFLEqoUF0avvEMw+97B19+/s+/o9rjq0hAbGPhocj4cl8Rz/T1VO1O9P7RtH4qhWz+qQRUTkPEqQRIqJYRg0v6oeza+aSnrmRL5a+xXZG9+n/dlVVHEdo8qu2bBrNr8Ft8an9T3U6jgIwy/Q6rBFRAQlSCIlIsDhw5+6dIcu3Tlw9CTfrVxA1V8/pI3rJ+qd3QTfbOLsN09xoMZNVO88kvD67cEwrA5bRKTCUoIkUsJiqkUQc+do3O772fTjTxxbM5fmxz6jpnGMRoc+gvkfcci3Dmcb30HdG+/FN7Sa1SGLiFQ4SpBELGKzGbS9ugVcPZPktOeIX/1vfH+azzUZa6jh3AM/Tif7x+fZWel6QjoMp0brm8Guv7IiIiVB/9qKlAJhgQ669R4IvQeye99Bdq+aR+z+T2jCbzQ89TUs+5qTyyM4UrsvsV1HEhzdyOqQRUTKNSVIIqVMXGxN4u59GqfrSdZ8/y1p696ndfKXRLhPEvH7O/DWO/we0Ax3y7up2+kubP4hVocsIlLuKEESKaV87TY6duwMHTtz9HQK8SsXErpzEW2cm6ibvhUSHictYRJ7IrtT9YYRVGvcSQO7RUSKiBIkkTKgWngo3fqPwjRH8vPOnRz8Zi6NjvybWCORJklLYfFSjvjU5ORVA6nX9c/4R9SwOmQRkTJNCZJIGWIYBk0bNaJpo+dJz/w73/73c8zN/6Rt6rdUzz5I9e0zyN4+kx2hHfBvO5TaHfpi+PhZHbaISJmjBEmkjApw+HBD19ug620cTDzKdyvfI+q3j2hu7qRRyhpYtYbTXz3K/phbifnTSCrVbmF1yCIiZYYSJJFyoGZUNWre/Shu9yNs2rye02vfpfmJL6hKMuH7/wnz/snvjoacDW8IAREYQRH4BEXgCKlCQFhVgsKrEhxeLedhunZfq3dHRMRySpBEyhGbzaB1m/bQpj3JZ9JYvfpDArb9izaZ66mbuROSdl6yjVQCOGsLJc0nlEzfcJx+Ybj9K0FgBLbACHyDK+MIrUJgWFWCKlUlKKwahn8Y2GwlsIciIiVDCZJIORUWEkiXW4fBrcP49fff2Lv2Y4yziRgZp/HLOo3DeZrA7DMEu1MI4wyhpGEzTIJIJ8idDllJkAWkXnpbLmycNYI4awsl3SeMLN8wsh3huP0jILAS9qDK+IZUxj+kMoHh1QipVA3/0CoYfkG6805ESiUlSCIVQP269ahf97ELLs/MdnE8NYOU0ydIO3WUtJRjOFNO4Ew9gZl2EiP9JPZziZV/djKBrhSC3WcI5wxBRiZ23ISZZwhznQHXIcgEzl46rix8OGOEkmoPJcMnlCy/cLId4Zj+lTACI7AHV8YvuDL+YVUICqtGcEQ17AFhYLrB5QRcYLrAdGO6szFdblxuFy5XNqbbjdvtwu3KxnS7ct5nu3CbrpzPuXVcLtzubDhXP2dZzp+mmbMcM6dtt+kCtwvTfW57phvT/b8y3C5M89z7c9sx3G5PmXGuDNN97uUCk/99xjz33vR8Nrw+5743MfhfueFZ9w/lf1g3Txkmxh/KDdwYucv/+N50Y/yhXQPvcuNcO81dJge3TcVl88Nt+Ob8affFbfPDtPnhtjvA7odp9wMfP7A7wMcPm92B4evA8HFgO/en3deBzdcfHz8HPr7+2Pz88fHzx9fXgY/DHz8/f3wdAdh9HTnt2H2VZEuxKBUJ0uuvv84LL7xAYmIiLVq04LXXXqNdu3YXrL948WImTJjA3r17iYuL47nnnqNXr16e5aZpMmnSJN5++21Onz5Nx44dmT17NnFxcZ46J0+eZMyYMfznP//BZrPRr18/XnnlFYKDg4t1X0VKI4ePnWphQVQLC4LYWgVeL8PpIjHlLGdOHSX19DEyU46ReeYkrtTjOYlVxil8Mk/jyErGP/s0Qa4zhJg5iZWf4cKPbCqbJ6mcfRKygYyCbfc2gC3eZca5lw3QKCoLOK3bdCa+ZOODE1+chi/ZnpcfLpvvH5I2P9y2c4mb3ZGTsOUmbnY/DF9/DN8ADN8AbH7+2PwCsfsGYHcE4OsIzHn557wc/kE4AoKx+wWAj0NJWjlkeYK0aNEixo0bx5w5c2jfvj0zZ86kR48e7Nq1i2rV8j6kc+3atQwePJjp06dz8803s2DBAvr06cPmzZtp2rQpAM8//zyvvvoq7733HnXq1GHChAn06NGD7du34+/vD8Bdd93FkSNHiI+Px+l0Mnz4cEaNGsWCBQtKdP9FyjJ/XztRlcOIqhwGxF2yPuT8ByYtM5tjyac5e+ooacnHyDxznKwzJ3CnnoC0kxgZp/HNPIXDmYx/dgrB7hRCzTOEkYrNMC+5DbeZc77DhQ3z3J9/fO8+72UaueX2nHMoxrlybF7vzdz3xrkX//uMcW793PeGDdOwAwamYfesg/G/OnjWNcAwMDlXfu5zTh3jD/Vzy+3nMsKcNjx1c9c9145hy2nT+EObhqeeLaeqYf/D+gaGzY6R24bNlvPe+F8bhu3cuuS073Kb7P5lJ/ViY8CdjTs7EzM7C9OZiZmdCa5McGVhZOf8iSsLmzsLW+6fbid2d857H9OJ/dzL13Tic+5PX5z44cSPbHzJxtdwefW3AycOnED6uTNyBf4KFwm3aZBl+JKFH1mGH1mGA6fhR7bNQbbNn2y7A5fNgdvHH7fdPyc58/EH3wAMX3/wCcDml/Oy+wVg8wvExxGAj19OYubjCMQvIAiHfyB+/kH4+gdi2P2UlBUzwzTNEv4qeWvfvj1t27Zl1qxZALjdbmJiYhgzZgxPPPFEnvqDBg0iNTWVzz77zFN2zTXX0LJlS+bMmYNpmkRHR/Pwww/zyCOPAJCcnExkZCTz5s3jjjvuYMeOHTRu3JgNGzbQpk0bAJYvX06vXr04ePAg0dHRl4w7JSWFsLAwkpOTCQ0NLYpDAYDT6WTZsmX06tULX1/9P7g0UJ+UDm63yZn0TE4eT+K7//6X62+4Hj9HADabDZvNjmH3wW63Y7f5YNgN7IaBzTCw2fjDe/2gFLWS+vthmiZOl0mWy01WlhNnVkbOKzPnz+ysDFzOTFx//DM7E9OZkZO0OTNxZ2dhujIhOxOys8CVieHKwsjOwnDnvLe7MrG7M7C7MvFxZ+JrZuLrzsTPzMKPTBxmFn448ScLH8NdbPt7KS7TINNwkHkuKXMafjgNB06bHxnZBj5+DkzD53+JumHDbfjAuc+mYcO02c8ty/nTtNnPJcx2sNkwDZ9zSfK5ZTYfjNw65z5j2DHsOYm/YfPBsNvByPnTsPnk/N089/fTsOW0Z7P5YLPbwe7jeW/YfLDZc9/bsdt9sdntVKpWA/+AoCI9dgX9/bb0DFJWVhabNm1i/PjxnjKbzUbXrl1JSEjId52EhATGjRvnVdajRw+WLFkCwJ49e0hMTKRr166e5WFhYbRv356EhATuuOMOEhISCA8P9yRHAF27dsVms7Fu3Tr69u2bZ7uZmZlkZmZ6PqekpAA5/zg4nUV3bjm3raJsU66M+qT0CPSz41u1KqEhIVSrUvUSP8jnTiXkDKHBBbhcF6kuhVKSfz8MwGEDh78P+AcD1gyJcLlN0rLdZGRmkJmRhjMjFWdGOs7MNJyZabiy0nFlpuFyZuDKSsfMSsfMTgdnBjjTITsDIzsDmysDW3YmNnfmuYQsIycpc2fha2biZ2biRxYOMwsHWThwes6g2g2TQDIIJMP7rFnudzwzv8jLni03vE2T6/P+Jl+Jgn5XLU2Qjh8/jsvlIjIy0qs8MjKSnTvzvx05MTEx3/qJiYme5bllF6tz/uU7Hx8fIiIiPHXON336dKZMmZKnfMWKFQQGBl5oFwstPj6+yNuUK6M+KV3UH6WL+uN8fjkvIxQc5LyugGlCttvE5crG7crCzHZinrtkiSsL3NkYrixwZ2G4s88N0HefG3Sf+96VMzjfU55zw4DNM1Df5Rmkb+DGdu6z7Vx927m2DDP34rTLs67tXH0buXVNbKYbO67/LceN/Y/vzy3/wwVtfP5wEdyOm527f2PfmWVF0SEeaWlpBapn+RiksmL8+PFeZ65SUlKIiYmhe/fuRX6JLT4+nm7duulyTimhPild1B+li/qjdClv/dGvGNrMvQJ0KZYmSFWqVMFut5OUlORVnpSURFRUVL7rREVFXbR+7p9JSUlUr17dq07Lli09dY4ePerVRnZ2NidPnrzgdh0OBw5H3v8C+Pr6FsuXsLjalcJTn5Qu6o/SRf1Ruqg/Lqygx8XSqW/9/Pxo3bo1q1at8pS53W5WrVpFhw4d8l2nQ4cOXvUh59Rubv06deoQFRXlVSclJYV169Z56nTo0IHTp0+zadMmT52vvvoKt9tN+/bti2z/REREpGyy/BLbuHHjGDp0KG3atKFdu3bMnDmT1NRUhg8fDsCQIUOoUaMG06dPB+CBBx6gU6dOvPTSS/Tu3ZuFCxeyceNG3nrrLSDnaecPPvggf/vb34iLi/Pc5h8dHU2fPn0AaNSoET179mTkyJHMmTMHp9PJ6NGjueOOOwp0B5uIiIiUb5YnSIMGDeLYsWNMnDiRxMREWrZsyfLlyz2DrPfv34/tD894uvbaa1mwYAFPP/00Tz75JHFxcSxZssQzBxLAY489RmpqKqNGjeL06dNcd911LF++3DMHEsD8+fMZPXo0N954o2eiyFdffbXkdlxERERKLcsTJIDRo0czevTofJd9/fXXecoGDBjAgAEDLtieYRhMnTqVqVOnXrBORESEJoUUERGRfOnx2yIiIiLnUYIkIiIich4lSCIiIiLnUYIkIiIich4lSCIiIiLnUYIkIiIich4lSCIiIiLnUYIkIiIich4lSCIiIiLnKRUzaZdFpmkCOQ/CLUpOp5O0tDRSUlL0JOZSQn1Suqg/Shf1R+mi/ri03N/t3N/xC1GCVEhnzpwBICYmxuJIRERE5HKdOXOGsLCwCy43zEulUJIvt9vN4cOHCQkJwTCMIms3JSWFmJgYDhw4QGhoaJG1K4WnPild1B+li/qjdFF/XJppmpw5c4bo6GhstguPNNIZpEKy2WzUrFmz2NoPDQ3Vl7uUUZ+ULuqP0kX9UbqoPy7uYmeOcmmQtoiIiMh5lCCJiIiInEcJUinjcDiYNGkSDofD6lDkHPVJ6aL+KF3UH6WL+qPoaJC2iIiIyHl0BklERETkPEqQRERERM6jBElERETkPEqQRERERM6jBKmUef3116lduzb+/v60b9+e9evXWx1ShTR9+nTatm1LSEgI1apVo0+fPuzatcvqsOScZ599FsMwePDBB60OpcI6dOgQd999N5UrVyYgIIBmzZqxceNGq8OqsFwuFxMmTKBOnToEBARQr149pk2bdsnnjcmFKUEqRRYtWsS4ceOYNGkSmzdvpkWLFvTo0YOjR49aHVqF880333D//ffz/fffEx8fj9PppHv37qSmplodWoW3YcMG3nzzTZo3b251KBXWqVOn6NixI76+vnzxxRds376dl156iUqVKlkdWoX13HPPMXv2bGbNmsWOHTt47rnneP7553nttdesDq3M0m3+pUj79u1p27Yts2bNAnKe9xYTE8OYMWN44oknLI6uYjt27BjVqlXjm2++4YYbbrA6nArr7NmztGrVijfeeIO//e1vtGzZkpkzZ1odVoXzxBNPsGbNGv773/9aHYqcc/PNNxMZGck777zjKevXrx8BAQF88MEHFkZWdukMUimRlZXFpk2b6Nq1q6fMZrPRtWtXEhISLIxMAJKTkwGIiIiwOJKK7f7776d3795ef0+k5C1dupQ2bdowYMAAqlWrxtVXX83bb79tdVgV2rXXXsuqVav45ZdfAPjxxx/57rvvuOmmmyyOrOzSw2pLiePHj+NyuYiMjPQqj4yMZOfOnRZFJZBzJu/BBx+kY8eONG3a1OpwKqyFCxeyefNmNmzYYHUoFd7vv//O7NmzGTduHE8++SQbNmxg7Nix+Pn5MXToUKvDq5CeeOIJUlJSaNiwIXa7HZfLxTPPPMNdd91ldWhllhIkkUu4//772bZtG999953VoVRYBw4c4IEHHiA+Ph5/f3+rw6nw3G43bdq04e9//zsAV199Ndu2bWPOnDlKkCzy4YcfMn/+fBYsWECTJk3YsmULDz74INHR0eqTQlKCVEpUqVIFu91OUlKSV3lSUhJRUVEWRSWjR4/ms88+49tvv6VmzZpWh1Nhbdq0iaNHj9KqVStPmcvl4ttvv2XWrFlkZmZit9stjLBiqV69Oo0bN/Yqa9SoER9//LFFEcmjjz7KE088wR133AFAs2bN2LdvH9OnT1eCVEgag1RK+Pn50bp1a1atWuUpc7vdrFq1ig4dOlgYWcVkmiajR4/m008/5auvvqJOnTpWh1Sh3XjjjWzdupUtW7Z4Xm3atOGuu+5iy5YtSo5KWMeOHfNMe/HLL78QGxtrUUSSlpaGzeb9k26323G73RZFVPbpDFIpMm7cOIYOHUqbNm1o164dM2fOJDU1leHDh1sdWoVz//33s2DBAv79738TEhJCYmIiAGFhYQQEBFgcXcUTEhKSZ/xXUFAQlStX1rgwCzz00ENce+21/P3vf2fgwIGsX7+et956i7feesvq0CqsW265hWeeeYZatWrRpEkTfvjhB2bMmMG9995rdWhllm7zL2VmzZrFCy+8QGJiIi1btuTVV1+lffv2VodV4RiGkW/53LlzGTZsWMkGI/nq3LmzbvO30Geffcb48ePZvXs3derUYdy4cYwcOdLqsCqsM2fOMGHCBD799FOOHj1KdHQ0gwcPZuLEifj5+VkdXpmkBElERETkPBqDJCIiInIeJUgiIiIi51GCJCIiInIeJUgiIiIi51GCJCIiInIeJUgiIiIi51GCJCIiInIeJUgiIoVkGAZLliyxOgwRKQZKkESkTBo2bBiGYeR59ezZ0+rQRKQc0LPYRKTM6tmzJ3PnzvUqczgcFkUjIuWJziCJSJnlcDiIioryelWqVAnIufw1e/ZsbrrpJgICAqhbty4fffSR1/pbt27lT3/6EwEBAVSuXJlRo0Zx9uxZrzrvvvsuTZo0weFwUL16dUaPHu21/Pjx4/Tt25fAwEDi4uJYunSpZ9mpU6e46667qFq1KgEBAcTFxeVJ6ESkdFKCJCLl1oQJE+jXrx8//vgjd911F3fccQc7duwAIDU1lR49elCpUiU2bNjA4sWLWblypVcCNHv2bO6//35GjRrF1q1bWbp0KfXr1/faxpQpUxg4cCA//fQTvXr14q677uLkyZOe7W/fvp0vvviCHTt2MHv2bKpUqVJyB0BECs8UESmDhg4datrtdjMoKMjr9cwzz5imaZqA+Ze//MVrnfbt25t//etfTdM0zbfeesusVKmSefbsWc/yzz//3LTZbGZiYqJpmqYZHR1tPvXUUxeMATCffvppz+ezZ8+agPnFF1+Ypmmat9xyizl8+PCi2WERKVEagyQiZVaXLl2YPXu2V1lERITnfYcOHbyWdejQgS1btgCwY8cOWrRoQVBQkGd5x44dcbvd7Nq1C8MwOHz4MDfeeONFY2jevLnnfVBQEKGhoRw9ehSAv/71r/Tr14/NmzfTvXt3+vTpw7XXXluofRWRkqUESUTKrKCgoDyXvIpKQEBAger5+vp6fTYMA7fbDcBNN93Evn37WLZsGfHx8dx4443cf//9vPjii0Uer4gULY1BEpFy6/vvv8/zuVGjRgA0atSIH3/8kdTUVM/yNWvWYLPZaNCgASEhIdSuXZtVq1ZdUQxVq1Zl6NChfPDBB8ycOZO33nrritoTkZKhM0giUmZlZmaSmJjoVebj4+MZCL148WLatGnDddddx/z581m/fj3vvPMOAHfddReTJk1i6NChTJ48mWPHjjFmzBjuueceIiMjAZg8eTJ/+ctfqFatGjfddBNnzpxhzZo1jBkzpkDxTZw4kdatW9OkSRMyMzP57LPPPAmaiJRuSpBEpMxavnw51atX9ypr0KABO3fuBHLuMFu4cCH33Xcf1atX51//+heNGzcGIDAwkC+//JIHHniAtm3bEhgYSL9+/ZgxY4anraFDh5KRkcHLL7/MI488QpUqVejfv3+B4/Pz82P8+PHs3buXgIAArr/+ehYuXFgEey4ixc0wTdO0OggRkaJmGAaffvopffr0sToUESmDNAZJRERE5DxKkERERETOozFIIlIuafSAiFwJnUESEREROY8SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROY8SJBEREZHzKEESEREROc//AwbqiZkAp0StAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -525,28 +532,28 @@ "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 50%|█████ | 5/10 [04:17<04:11, 50.36s/it]" + "Training epoch: 50%|█████ | 5/10 [10:38<10:36, 127.31s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 5 training loss = 0.0001228379673192498, validation loss = 0.00012489799656530793\n" + "At epoch 5 training loss = 0.00012283809515136498, validation loss = 0.00012489890222459223\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Training epoch: 100%|██████████| 10/10 [08:26<00:00, 50.68s/it]" + "Training epoch: 100%|██████████| 10/10 [21:38<00:00, 129.80s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "At epoch 10 training loss = 0.00016523082156208446, validation loss = 0.00016298455128254218\n" + "At epoch 10 training loss = 0.00016523055544214686, validation loss = 0.00016298261790833693\n" ] }, { @@ -570,7 +577,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 13, @@ -579,7 +586,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkgAAAHHCAYAAABEEKc/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/SrBM8AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB2/UlEQVR4nO3dd3wUdf7H8dfsZrObHmoKvUmHKAhSFAsQBEssiOhJOQ5+eoJgTjxRBEQ9TgVERMWKesqBWDhOMRIQzzuJjSYoIEovCSBCSN/szu+PwOqSAAkkzCZ5Px+PPMLOfuc7n9nv6r4zM98dwzRNExERERHxsVldgIiIiEigUUASEREROYkCkoiIiMhJFJBERERETqKAJCIiInISBSQRERGRkyggiYiIiJxEAUlERETkJApIIiIiIidRQBKRU9qxYweGYfD666+f1fqGYTBlypRyrUmqrmHDhtG4cWOryxABFJBEymzDhg3cfPPNNGrUCJfLRb169ejTpw/PPvtssbYej4d58+Zx+eWXU7NmTZxOJ40bN2b48OF8++23vnavv/46hmGU+PPAAw+ctp758+cza9as8t7NKun3r/P//ve/Ys+bpkmDBg0wDINrrrnG77msrCwmT55Mu3btCAsLo1atWiQkJDB27Fj27dvnazdlypRTjqVhGKSnp1f4forIuQuyugCRymTVqlVcccUVNGzYkJEjRxIbG8vu3bv58ssveeaZZxgzZoyvbW5uLjfeeCMpKSlcdtllPPjgg9SsWZMdO3bwzjvv8MYbb7Br1y7q16/vW2fq1Kk0adLEb5vt2rU7bU3z589n48aNjBs3rlz3FaBRo0bk5ubicDjOav3c3FyCggLvfzMul4v58+fTs2dPv+X/+c9/2LNnD06n02+52+3msssuY/PmzQwdOpQxY8aQlZXF999/z/z587nhhhuIj4/3W+eFF14gPDy82Lajo6PLfX9EpPwF3v+5RALY448/TlRUFN98802xD7oDBw74PR4/fjwpKSk8/fTTxcLL5MmTefrpp4v1f/XVV9O5c+fyLtsnLy+P4OBgbLbSHTw2DAOXy3XW2zuXdStS//79WbRoEbNnz/YLcPPnz6dTp04cOnTIr/3ixYtZu3Ytb7/9Nrfddpvfc3l5eRQUFBTbxs0330zt2rUrZgfOE6/XS0FBQcCOo0hF0ik2kTL4+eefadu2bYlHAerWrev79549e3jxxRfp06dPiUd27HY79913n9/Ro7Nx+eWX89FHH7Fz507fKZwT13B89tlnGIbBggULmDhxIvXq1SM0NJTMzEwOHz7MfffdR/v27QkPDycyMpKrr76a9evX+/Vf0jVIw4YNIzw8nL1795KUlER4eDh16tThvvvuw+Px+K1/8jVIJ04//fTTTwwbNozo6GiioqIYPnw4OTk5fuvm5uZyzz33ULt2bSIiIrjuuuvYu3dvidc1bd68mV27dpX6dRs8eDC//PILqampvmUFBQW8++67xQIQFI07QI8ePYo953K5iIyMLPW2S+Ott96iU6dOhISEULNmTW699VZ2797t1+byyy+nXbt2/PDDD1xxxRWEhoZSr149nnzyyWL95efnM3nyZJo3b47T6aRBgwbcf//95Ofn+7UzDIPRo0fz9ttv07ZtW5xOJykpKQB899139OrVi5CQEOrXr89jjz3GvHnzMAyDHTt2ADB06FBq166N2+0uVkPfvn1p2bJlmV+L7Oxs/vKXv9CgQQOcTictW7Zk+vTpmKbp1y41NZWePXsSHR1NeHg4LVu25MEHH/Rr8+yzz9K2bVtCQ0OpUaMGnTt3Zv78+WWuSaoHHUESKYNGjRqRlpbGxo0bT3vq6+OPP6awsJA77rijTP0fPXq02NGL0x2FeOihhzh69Ch79uzxHZE6+bTOo48+SnBwMPfddx/5+fkEBwfzww8/sHjxYgYOHEiTJk3IyMjgxRdfpFevXvzwww/FThedzOPxkJiYSNeuXZk+fTrLly9nxowZNGvWjLvuuuuM+3nLLbfQpEkTpk2bxpo1a3jllVeoW7cuTzzxhK/NsGHDeOedd7jjjju45JJL+M9//sOAAQNK7K9169b06tWLzz777IzbBmjcuDHdunXjn//8J1dffTVQNGZHjx7l1ltvZfbs2X7tGzVqBMCbb77JxIkTMQzjjNs4fPhwsWVBQUFnPMX2+OOP8/DDD3PLLbfwpz/9iYMHD/Lss89y2WWXsXbtWr/1f/31V/r168eNN97ILbfcwrvvvstf//pX2rdv79svr9fLddddx//+9z9GjRpF69at2bBhA08//TQ//vgjixcv9tv+p59+yjvvvMPo0aOpXbs2jRs3Zu/evVxxxRUYhsGECRMICwvjlVdeKXYq8o477uDNN9/kk08+8buGKz09nU8//ZTJkyef8XX7PdM0ue6661i5ciUjRowgISGBTz75hPHjx7N3717fe/7777/nmmuuoUOHDkydOhWn08lPP/3EF1984evr5Zdf5p577uHmm29m7Nix5OXl8d133/HVV1+VGIpFMEWk1JYtW2ba7XbTbreb3bp1M++//37zk08+MQsKCvza3XvvvSZgrl27tlT9zps3zwRK/DmTAQMGmI0aNSq2fOXKlSZgNm3a1MzJyfF7Li8vz/R4PH7Ltm/fbjqdTnPq1Kl+ywBz3rx5vmVDhw41Ab92pmmaF154odmpUye/ZYA5efJk3+PJkyebgPnHP/7Rr90NN9xg1qpVy/d49erVJmCOGzfOr92wYcOK9XliO7169Sr2GpzsxOv8zTffmHPmzDEjIiJ8r83AgQPNK664wjRN02zUqJE5YMAA33o5OTlmy5YtTcBs1KiROWzYMPPVV181MzIyim3jxD6W9NOyZcvT1rdjxw7Tbrebjz/+uN/yDRs2mEFBQX7Le/XqZQLmm2++6VuWn59vxsbGmjfddJNv2T/+8Q/TZrOZ//3vf/36nDt3rgmYX3zxhW8ZYNpsNvP777/3aztmzBjTMAy/9/Mvv/xi1qxZ0wTM7du3m6Zpmh6Px6xfv745aNAgv/VnzpxpGoZhbtu27bT7P3ToUL/38uLFi03AfOyxx/za3XzzzaZhGOZPP/1kmqZpPv300yZgHjx48JR9X3/99Wbbtm1Pu32R39MpNpEy6NOnD2lpaVx33XWsX7+eJ598ksTEROrVq8eSJUt87TIzMwGIiIgoU//PPfccqampfj/naujQoYSEhPgtczqdvuuQPB4Pv/zyi++0xJo1a0rV75133un3+NJLL2Xbtm1nve4vv/zie91OnNb585//7Nfu9xfB/55pmqU+enTCLbfcQm5uLh9++CHHjh3jww8/POWRhJCQEL766ivGjx8PFM2GGzFiBHFxcYwZM6bYqSqA9957r9hYzps377Q1vf/++3i9Xm655RYOHTrk+4mNjaVFixasXLnSr314eDh/+MMffI+Dg4Pp0qWL3zgsWrSI1q1b06pVK78+r7zySoBiffbq1Ys2bdr4LUtJSaFbt24kJCT4ltWsWZPbb7/dr53NZuP2229nyZIlHDt2zLf87bffpnv37sUmIJzJ0qVLsdvt3HPPPX7L//KXv2CaJh9//DHw24Xv//rXv/B6vSX2FR0dzZ49e/jmm2/KVINUXzrFJlJGF198Me+//z4FBQWsX7+eDz74gKeffpqbb76ZdevW0aZNG981Kb//kCiNLl26lPtF2iV9KHm9Xp555hmef/55tm/f7nftUK1atc7Yp8vlok6dOn7LatSowa+//lqqmho2bFhsXSg6ZRQZGcnOnTux2WzFam/evHmp+i+NOnXq0Lt3b+bPn09OTg4ej4ebb775lO2joqJ48sknefLJJ9m5cycrVqxg+vTpzJkzh6ioKB577DG/9pdddlmZL9LeunUrpmnSokWLEp8/eTZh/fr1i53uq1GjBt99951fn5s2bSo2XiecPLmgpPfLzp076datW7HlJY3HkCFDeOKJJ/jggw8YMmQIW7ZsYfXq1cydO7fE7Z/Ozp07iY+PL/aHRuvWrX3PAwwaNIhXXnmFP/3pTzzwwANcddVV3Hjjjdx8882+PwT++te/snz5crp06ULz5s3p27cvt912W4nXlYmAApLIWQsODubiiy/m4osv5oILLmD48OEsWrSIyZMn06pVK6DoO5N+/1e3FU4+egTwt7/9jYcffpg//vGPPProo9SsWRObzca4ceNO+Rf479nt9nOq6VTrmyddeFvRbrvtNkaOHEl6ejpXX311qafgN2rUiD/+8Y/ccMMNNG3alLfffrtYQDobXq8XwzD4+OOPS3yNTr6+rDSvo9frpX379sycObPEtg0aNPB7XNL7pSzatGlDp06deOuttxgyZAhvvfUWwcHB3HLLLefU7+mEhITw+eefs3LlSj766CNSUlJYuHAhV155JcuWLcNut9O6dWu2bNnChx9+SEpKCu+99x7PP/88kyZN4pFHHqmw2qTyUkASKQcnjvrs378fKJqub7fbeeutt8p8oXZZleaC4ZO9++67XHHFFbz66qt+y48cORIQU9MbNWqE1+tl+/btfkdTfvrpp3Ldzg033MD//d//8eWXX7Jw4cIyr1+jRg2aNWvGxo0by6WeZs2aYZomTZo04YILLii3PtevX89VV111Vu8VKBqPkl77U43HkCFDSE5OZv/+/cyfP58BAwb4jhKWdbvLly/n2LFjfkeRNm/e7Hv+BJvNxlVXXcVVV13FzJkz+dvf/sZDDz3EypUr6d27NwBhYWEMGjSIQYMGUVBQwI033sjjjz/OhAkT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EaRAU6cVAGFHt1pciIiInK3OnTv7Pc7KyuK+++6jdevWREdHEx4ezqZNm854BKlDhw6+f4eFhREZGem7jUZJQkNDadKkie9xXFycr/3Ro0fJyMjwhRUAu91Op06dyrRvmzZtokePHn7LevTowaZNmwAYOHAgubm5NG3alJEjR/LBBx9QWFgIQJ8+fWjUqBFNmzbljjvu4O233yYnJ6dM2z9fdAQpwIQ3aAdbICZvO26PF4ddGVZEqpcQh50fpiZast3yEhYW5vf4vvvuIzU1lenTp9O8eXNCQkK4+eabKSgoOG0/jpMm6xiGgdfrLVP78jx1WBoNGjRgy5YtLF++nNTUVP785z/z1FNP8Z///IeIiAjWrFnDZ599xrJly5g0aRJTpkzhm2++CbivEtCnb4CJblT018IFxm52HsqyuBoRkfPPMAxCg4PO+09Ffpv3F198wbBhw7jhhhto3749sbGx7Nixo8K2V5KoqChiYmL45ptvfMs8Hg9r1qwpUz+tW7fmiy++8Fv2xRdf0KZNG9/jkJAQrr32WmbPns1nn31GWloaGzZsACAoKIjevXvz5JNP8t1337Fjxw4+/fTTc9iziqEjSAHGqN2CQmxEGjl8s/1nmscE5rlZEREpvRYtWvD+++9z7bXXYhgGDz/88GmPBFWUMWPGMG3aNJo3b06rVq149tln+fXXX8sUDsePH88tt9zChRdeSO/evfn3v//N+++/75uV9/rrr+PxeOjatSuhoaG89dZbhISE0KhRIz788EO2bdvGZZddRo0aNVi6dCler5eWLVtW1C6fNR1BCjRBTtJtRd9rcWTXdxYXIyIi5WHmzJnUqFGD7t27c+2115KYmMhFF1103uv461//yuDBgxkyZAjdunUjPDycxMREXC5XqftISkrimWeeYfr06bRt25YXX3yRefPmcfnllwMQHR3Nyy+/TI8ePejQoQPLly/n3//+N7Vq1SI6Opr333+fK6+8ktatWzN37lz++c9/0rZt2wra47NnmOf75GQVkZmZSVRUFEePHiUyMrLc+nW73Wyc3p8L87/m3Vp3cvOYJ8qtbzk7brebpUuX0r9//2Ln9+X803gElnMdj7y8PLZv306TJk3K9CEtJfN6vWRmZhIZGYnNduZjIF6vl9atW3PLLbfw6KOPnocKz4/Tva9K+/mtU2wBKCukPuR/TfjR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dIoxLS0Nm81G69atsdlsvou8T671RD8l+f3z0dHRxMfHk5aWxhVXXOFrs2rVKrp06eLrIzo6msGDBzN48GAGDhxIv379OHLkCDVr1iQsLIzrr7+e66+/ntGjR9OqVSu+//57LrroohL3zTCMEt+XpX2fWnqKLTk5maFDh9K5c2e6dOnCrFmzyM7OZvjw4QAMGTKEevXq+a5iHzt2LL169WLGjBkMGDCABQsW8O233/LSSy/5+jx8+DC7du1i3759AGzZUjRFPjY21u/nZA0bNqRJkyYVvctlFhLfHnYsoEbWz1aXIiIivxMeHs6gQYOYMGECmZmZDBs2zPdcixYtePfdd1m1ahU1atRg5syZZGRk0KZNm1L13bt3by644AKGDh3KU089RWZmJg899JBfmxYtWrBr1y4WLFjAxRdfzEcffVRs0lLjxo3Zvn0769ato379+kRERBT7Y//2229n8uTJDB06lClTpnDw4EHGjBnDHXfcUey633Mxfvx4Jk+eTLNmzUhISGDevHmsW7eOt99+Gyia2R4XF8eFF16IzWZj0aJFxMbGEh0dzeuvv47H46Fr166Ehoby1ltvERISQqNGFXfpiaXT/AcNGsT06dOZNGkSCQkJrFu3jpSUFN+A7Nq1i/379/vad+/enfnz5/PSSy/RsWNH3n33XRYvXky7du18bZYsWcKFF17IgAEDgKKEf+GFFzJ37tzzu3PlpHbTBACamLs4lJV/+sYiInJejRgxgl9//ZXExETfxdQAEydO5KKLLiIxMZHLL7+c2NhY39mS0rDZbHzwwQfk5ubSpUsX/vSnP/H444/7tbnuuuu49957GT16NAkJCaxatcrvaBIUXT7Sr18/rrjiCurUqVPiVw2EhobyySefcPjwYS6++GJuvvlmrrrqKr+v0CkP99xzD8nJyfzlL3+hffv2pKSksGTJElq0aAEUzch78skn6dy5MxdffDE7duxg6dKlviNQL7/8Mj169KBDhw4sX76cf//739SqVatca/w9wzxxolHKJDMzk6ioKI4ePVru1yAtXbqU/v37Fx0GzDkMTxYd2frqlnV0bRN4R7mqumJjIpbSeASWcx2PvLw8tm/fTpMmTYpdKyJl5/V6yczMJDIy8pSnvqqD072vSvv5XX1fvcoitCZH7EUJ+eB23XJERETkfFBAqgSOhDcHIH+fblor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J59gQowCdv28yepyRERELKGAJP5sdtKDGwLw687vLC5GRETEGgpIUsyxyBYAeNI1k01ERKonBSQpxohpA0DIkR8trkRERMQaCkhSTETDDgDE5G3DNE2LqxERETn/LA9Izz33HI0bN8blctG1a1e+/vrr07ZftGgRrVq1wuVy0b59e5YuXer3vGmaTJo0ibi4OEJCQujduzdbtxa/bcZHH31E165dCQkJoUaNGiQlJZXnblVqMc2LZrI1Nvdx4Mgxi6sRERE5/ywNSAsXLiQ5OZnJkyezZs0aOnbsSGJiIgcOHCix/apVqxg8eDAjRoxg7dq1JCUlkZSUxMaNG31tnnzySWbPns3cuXP56quvCAsLIzExkby8PF+b9957jzvuuIPhw4ezfv16vvjiC2677bYK39/KwlmzIdmE4DA87N66wepyREREzjtLA9LMmTMZOXIkw4cPp02bNsydO5fQ0FBee+21Ets/88wz9OvXj/Hjx9O6dWseffRRLrroIubMmQMUHT2aNWsWEydO5Prrr6dDhw68+eab7Nu3j8WLFwNQWFjI2LFjeeqpp7jzzju54IILaNOmDbfccsv52u3AZxhkuJoAkLlLM9lERKT6sSwgFRQUsHr1anr37v1bMTYbvXv3Ji0trcR10tLS/NoDJCYm+tpv376d9PR0vzZRUVF07drV12bNmjXs3bsXm83GhRdeSFxcHFdffbXfUSiB7KiimWzeDH0XkoiIVD9BVm340KFDeDweYmJi/JbHxMSwefPmEtdJT08vsX16errv+RPLTtVm27ZtAEyZMoWZM2fSuHFjZsyYweWXX86PP/5IzZo1S9x2fn4++fn5vseZmZkAuN1u3G53qfa5NE70VZ59npU6rSDjX4Qd/dH6WiwWMGMigMYj0Gg8AovG48xK+9pYFpCs4vV6AXjooYe46aabAJg3bx7169dn0aJF/N///V+J602bNo1HHnmk2PJly5YRGhpa7nWmpqaWe59lYT8K7YHY/O18+NFSbIal5QQEq8dE/Gk8AovGI7BoPE4tJ6d0t9GyLCDVrl0bu91ORkaG3/KMjAxiY2NLXCc2Nva07U/8zsjIIC4uzq9NQkICgG95mzZtfM87nU6aNm3Krl27TlnvhAkTSE5O9j3OzMykQYMG9O3bl8jIyDPtbqm53W5SU1Pp06cPDoej3Potq8LMi+DZJ2hEBnS5hPp1Sj6yVh0EyphIEY1HYNF4BBaNx5mdOAN0JpYFpODgYDp16sSKFSt8U+y9Xi8rVqxg9OjRJa7TrVs3VqxYwbhx43zLUlNT6datGwBNmjQhNjaWFStW+AJRZmYmX331FXfddRcAnTp1wul0smXLFnr27AkUvaF27NhBo0aNTlmv0+nE6XQWW+5wOCrkTVhR/ZZ6+zXrc8SIJJpMDm7/nibxV1pWS6CwekzEn8YjsGg8AovG49RK+7pYeootOTmZoUOH0rlzZ7p06cKsWbPIzs5m+PDhAAwZMoR69eoxbdo0AMaOHUuvXr2YMWMGAwYMYMGCBXz77be89NJLABiGwbhx43jsscdo0aIFTZo04eGHHyY+Pt4XwiIjI7nzzjuZPHkyDRo0oFGjRjz11FMADBw48Py/CIHKMDjoakJ07nqO7f4OUEASEZHqw9KANGjQIA4ePMikSZNIT08nISGBlJQU30XWu3btwmb7baJd9+7dmT9/PhMnTuTBBx+kRYsWLF68mHbt2vna3H///WRnZzNq1CiOHDlCz549SUlJweVy+do89dRTBAUFcccdd5Cbm0vXrl359NNPqVGjxvnb+Uogt0ZLyF0PB0q+aF5ERKSqsvwi7dGjR5/ylNpnn31WbNnAgQNPe6THMAymTp3K1KlTT9nG4XAwffp0pk+fXuZ6qxNHbFvYBxGZxb+JXEREpCqz/FYjErhqNukIQD33Dgo9XourEREROX8UkOSU6jRNAKCecYhd6RmnbywiIlKFKCDJKdnCanDIVguAAz+ttbgaERGR80cBSU7rUGgzALJ261YsIiJSfSggyWkV1LgAAPsh3ZNNRESqDwUkOa3g+LYARB372eJKREREzh8FJDmt2scv1G5QuIP8Qo+1xYiIiJwnCkhyWrUadwCgjnGUXbtPfa86ERGRqkQBSU7LcIaTbj9+E+Cf1llbjIiIyHmigCRndDisOQD5ezWTTUREqgcFJDkjd62WAAT9onuyiYhI9aCAJGcUUq/oZsA1sjWTTUREqgcFJDmjOs0SAGjk2UlufqG1xYiIiJwHCkhyRjUatKUQG1FGDjt26CiSiIhUfQpIcmZBTtKD6gNwaJvuySYiIlWfApKUypHwoplsBfs0k01ERKo+BSQpFU/tVgAEH95icSUiIiIVTwFJSiWsftFMtto5ugZJRESqPgUkKZWY5hcC0Mi7h8zcfIurERERqVgKSFIqEXEXkI+DUCOfnT/rCyNFRKRqU0CS0rEHke5oCMCv29dZW4uIiEgFU0CSUsuMbAGAe//3FlciIiJSsRSQpNTMOq0BCPlVM9lERKRqU0CSUgtv0B6AOrnbLK5ERESkYikgSanFtTg+k83cy+HMbIurERERqTgKSFJqIbUbk4OLYMPDrp/0jdoiIlJ1KSBJ6dls7Hc2BuDozvXW1iIiIlKBFJCkTLIjLwDAk/6DxZWIiIhUHAUkKRMjpg0AoUd+tLgSERGRiqOAJGUS2bADALH52zBN0+JqREREKoYCkpRJzPGZbA3MdA4cPmJtMSIiIhVEAUnKxBUdRyYR2A2TPVt1obaIiFRNCkhSNoZBuqsJAMd2bbC4GBERkYqhgCRllhNdNJPNPKCZbCIiUjUFREB67rnnaNy4MS6Xi65du/L111+ftv2iRYto1aoVLpeL9u3bs3TpUr/nTdNk0qRJxMXFERISQu/evdm6dWuJfeXn55OQkIBhGKxbt668dqlKC4ptC0B4ZsmvqYiISGVneUBauHAhycnJTJ48mTVr1tCxY0cSExM5cOBAie1XrVrF4MGDGTFiBGvXriUpKYmkpCQ2bvztm52ffPJJZs+ezdy5c/nqq68ICwsjMTGRvLy8Yv3df//9xMfHV9j+VUXRjYtmssXn78Dr1Uw2ERGpeiwPSDNnzmTkyJEMHz6cNm3aMHfuXEJDQ3nttddKbP/MM8/Qr18/xo8fT+vWrXn00Ue56KKLmDNnDlB09GjWrFlMnDiR66+/ng4dOvDmm2+yb98+Fi9e7NfXxx9/zLJly5g+fXpF72aVEtO8aCZbPeMg+zJKDrIiIiKVmaUBqaCggNWrV9O7d2/fMpvNRu/evUlLSytxnbS0NL/2AImJib7227dvJz093a9NVFQUXbt29eszIyODkSNH8o9//IPQ0NDy3K0qzxFei0NGTQD2/7TO2mJEREQqQJCVGz906BAej4eYmBi/5TExMWzevLnEddLT00tsn56e7nv+xLJTtTFNk2HDhnHnnXfSuXNnduzYccZa8/Pzyc/P9z3OzMwEwO1243a7z7h+aZ3oqzz7rAgHQ5pQO+cwx3atx+2+0upyKlRlGZPqQuMRWDQegUXjcWalfW0sDUhWefbZZzl27BgTJkwo9TrTpk3jkUceKbZ82bJlFXIEKjU1tdz7LE/hZh1aAzk7Vhe7SL6qCvQxqW40HoFF4xFYNB6nlpOTU6p2lgak2rVrY7fbycjI8FuekZFBbGxsievExsaetv2J3xkZGcTFxfm1SUhIAODTTz8lLS0Np9Pp10/nzp25/fbbeeONN4ptd8KECSQnJ/seZ2Zm0qBBA/r27UtkZGQp9/jM3G43qamp9OnTB4fDUW79lrfNxk5Yk0K8mU77/v2tLqdCVZYxqS40HoFF4xFYNB5nduIM0JlYGpCCg4Pp1KkTK1asICkpCQCv18uKFSsYPXp0iet069aNFStWMG7cON+y1NRUunXrBkCTJk2IjY1lxYoVvkCUmZnJV199xV133QXA7Nmzeeyxx3zr79u3j8TERBYuXEjXrl1L3K7T6SwWqAAcDkeFvAkrqt/yUqdZJ1gD9d07sNmDsNsMq0uqcIE+JtWNxiOwaDwCi8bj1Er7ulh+ii05OZmhQ4fSuXNnunTpwqxZs8jOzmb48OEADBkyhHr16jFt2jQAxo4dS69evZgxYwYDBgxgwYIFfPvtt7z00ksAGIbBuHHjeOyxx2jRogVNmjTh4YcfJj4+3hfCGjZs6FdDeHg4AM2aNaN+/frnac8rt7rNiqb61zWOsGPPbhqf9JqKiIhUZpYHpEGDBnHw4EEmTZpEeno6CQkJpKSk+C6y3rVrFzbbb5Ptunfvzvz585k4cSIPPvggLVq0YPHixbRr187X5v777yc7O5tRo0Zx5MgRevbsSUpKCi6X67zvX1Vlc0WQbosh1ptBxs9rFZBERKRKsTwgAYwePfqUp9Q+++yzYssGDhzIwIEDT9mfYRhMnTqVqVOnlmr7jRs3xjT1hYdldTi0GbFZGeTs3ghcb3U5IiIi5cbyL4qUyiu/VksA7L+U/JUMIiIilZUCkpw1Z3zRPdmis36yuBIREZHypYAkZ61Os6JbjjQs3EmB22NxNSIiIuVHAUnOWu1GbSk0bUQb2ezatc3qckRERMqNApKcNcMRQnpQPQAO/rzO2mJERETKkQKSnJNfw5sBkLd3g8WViIiIlB8FJDknnuMz2Ry/bLG4EhERkfKjgCTnJKReewBq5vxscSUiIiLlRwFJzknd5kUz2Rp5dpGb77a4GhERkfKhgCTnpEb9VhQQRJiRz85t+sJIERGpGhSQ5NzYg9gXVHQftsPb1llbi4iISDlRQJJzdjSiOQAF+7+3uBIREZHyoYAk58xbpzUAzsOaySYiIlWDApKcs7AG7QConatv0xYRkapBAUnOWWyziwBo6N3DsZxci6sRERE5dwpIcs4iY5uSgwunUcjOrRutLkdEROScKSDJubPZ2B/cCIAjO9ZbXIyIiMi5U0CScnEssgUAhemaySYiIpWfApKUj7ptAAg98qPFhYiIiJw7BSQpFxENOwBQVzPZRESkClBAknIR1zwBgPpmOoePZlpbjIiIyDlSQJJyEVqrPpmEE2R42bP1O6vLEREROScKSFI+DIN0ZxMAju7UTDYREancFJCk3GRFXwCAN+MHiysRERE5NwpIUm7sMUUz2cKPbrW4EhERkXOjgCTlJqpR0Uy22PxtmKZpcTUiIiJnTwFJyk1s8wsBqMdBDv1y2OJqREREzp4CkpQbV1QdfjFqALBn61qLqxERETl7CkhSrg64mgJwbJem+ouISOWlgCTlKvf4TDbjwCaLKxERETl7CkhSroLi2gIQkamZbCIiUnkpIEm5qtGkaCZbfMEOvF7NZBMRkcpJAUnKVWyzBADqGr+yf/9ea4sRERE5SwpIUq4coVFkGHUByPh5nbXFiIiInKWACEjPPfccjRs3xuVy0bVrV77++uvTtl+0aBGtWrXC5XLRvn17li5d6ve8aZpMmjSJuLg4QkJC6N27N1u3/nZNzI4dOxgxYgRNmjQhJCSEZs2aMXnyZAoKCipk/6qbg6FFM9mydm+0uBIREZGzY3lAWrhwIcnJyUyePJk1a9bQsWNHEhMTOXDgQIntV61axeDBgxkxYgRr164lKSmJpKQkNm787cP4ySefZPbs2cydO5evvvqKsLAwEhMTycvLA2Dz5s14vV5efPFFvv/+e55++mnmzp3Lgw8+eF72uarLr9kSANshzWQTEZHKyfKANHPmTEaOHMnw4cNp06YNc+fOJTQ0lNdee63E9s888wz9+vVj/PjxtG7dmkcffZSLLrqIOXPmAEVHj2bNmsXEiRO5/vrr6dChA2+++Sb79u1j8eLFAPTr14958+bRt29fmjZtynXXXcd9993H+++/f752u0oLPj6TLerYTxZXIiIicnaCrNx4QUEBq1evZsKECb5lNpuN3r17k5aWVuI6aWlpJCcn+y1LTEz0hZ/t27eTnp5O7969fc9HRUXRtWtX0tLSuPXWW0vs9+jRo9SsWfOUtebn55Ofn+97nJmZCYDb7cbtdp9+R8vgRF/l2ef5FtWoPXwN9d07yMvLx263PIefk6owJlWJxiOwaDwCi8bjzEr72lgakA4dOoTH4yEmJsZveUxMDJs3by5xnfT09BLbp6en+54/sexUbU72008/8eyzzzJ9+vRT1jpt2jQeeeSRYsuXLVtGaGjoKdc7W6mpqeXe53njKaCeaVDDyOKtdxcQERFtdUXlolKPSRWk8QgsGo/AovE4tZycnFK1szQgBYK9e/fSr18/Bg4cyMiRI0/ZbsKECX5HrjIzM2nQoAF9+/YlMjKy3Opxu92kpqbSp08fHA5HufV7vu3fOIX63j00q+Oi85X9rS7nnFSVMakqNB6BReMRWDQeZ3biDNCZWBqQateujd1uJyMjw295RkYGsbGxJa4TGxt72vYnfmdkZBAXF+fXJiEhwW+9ffv2ccUVV9C9e3deeuml09bqdDpxOp3Fljscjgp5E1ZUv+fLkYjm1D+6h+C0Wayt15Eu7VpZXdI5q+xjUtVoPAKLxiOwaDxOrbSvi6UXhwQHB9OpUydWrFjhW+b1elmxYgXdunUrcZ1u3br5tYeiQ4kn2jdp0oTY2Fi/NpmZmXz11Vd+fe7du5fLL7+cTp06MW/ePGy2yn2dTKCp1+8v5OKiEz/QYNHVfLDkA0xT36wtIiKVg+WpIDk5mZdffpk33niDTZs2cdddd5Gdnc3w4cMBGDJkiN9F3GPHjiUlJYUZM2awefNmpkyZwrfffsvo0aMBMAyDcePG8dhjj7FkyRI2bNjAkCFDiI+PJykpCfgtHDVs2JDp06dz8OBB0tPTT3mNkpRdjdaXYRv1KRnBDYkzDjNg9QgWPj+Z7DxdOCgiIoHP8muQBg0axMGDB5k0aRLp6ekkJCSQkpLiu8h6165dfkd3unfvzvz585k4cSIPPvggLVq0YPHixbRr187X5v777yc7O5tRo0Zx5MgRevbsSUpKCi6XCyg64vTTTz/x008/Ub9+fb96dJSj/Djj21I3+Qt2zvsjjTJSufXgMyyfsZ7mf3yFxnF1rC5PRETklAxTieCsZGZmEhUVxdGjR8v9Iu2lS5fSv3//qnP+2DTZvfRJ4r75O0F42WI24lD/V+jRtYvVlZVKlRyTSkzjEVg0HoFF43Fmpf38tvwUm1QDhkGDAX/l2MD3+NVWg5bGTtovvZ7FC17G61U+FxGRwKOAJOdNjbZXEjbmC3aFtSfSyCFp8318NOsujmblWV2aiIiIHwUkOa+Ca9Sj4b2f8lOTPwBwbeY/2TqzL1u377C2MBERkd9RQJLzLyiY5kOfY/cVz5KLk87e9YS9fiWfr0yxujIRERFAAUks1KDXEAqGL2d/UH3ijV/o+tntLH3tMQoLPVaXJiIi1ZwCklgqqlEH6v5lFVtqXI7TKKT/rqf4YsYtHPr1V6tLExGRakwBSSxnD4mi5T2L2dxuPB7ToFfucg7Pvpwfvl9vdWkiIlJNKSBJYDAMWt08kfSkBRw2orjA3EG9d67m8w//YXVlIiJSDSkgSUCpd2E/gv/8P35ytiHKyOayb0fz6fP3kF9QYHVpIiJSjSggScAJr9OQpvd9xnfxtwBw5YE3+OGpRNLT91pcmYiIVBcKSBKQbA4nHUa9zA/dppOLkwvdazDnXsaGr1daXZqIiFQDCkgS0NokjuTI4I/Za4sjjkNc8NHN/G/hdEyv1+rSRESkClNAkoAX17ITNcel8V14D5xGIT03PcpXz9xObnaW1aWJiEgVpYAklUJIZA3aJ/+bb5vfg8c0uOToUvbOvJS92zZbXZqIiFRBCkhSaRg2O53/8Cg/9n2Tw0TS3LON8Dev5LuV71hdmoiIVDEKSFLptO5xHe4/rWRLUEuiyKbdZ6P4+rX78BYWWl2aiIhUEQpIUinF1G9O4/s+48taN2AzTLrsepnvZ/Qj89cDVpcmIiJVgAKSVFpOVyiXjHmdLzv+jVwzmPa535A9uwe7Nq6yujQREankFJCk0rvkhrvZdeMS9hBLnHmAmEXXsWHJs1aXJSIilZgCklQJLTt2I2T0f1ntvASn4ab9momse24InoJcq0sTEZFKSAFJqoxatevScfxHrKz3f3hMg4SD/2LnU5dydN9PVpcmIiKVjAKSVClBQUFcMfJJvur5CofNCJq6t8JLvdjx5b+sLk1ERCoRBSSpkrr3uZnDf0hlk60FUWTR8OOhfP/Ph0C3KBERkVJQQJIqq3mL1sTf+xkrw6/BZpi03TKHLbMGUHDssNWliYhIgFNAkiotKiKcXslv8UmLyeSZDlpmruLXWd04/NM3VpcmIiIBTAFJqjybzSDx9mTWJy5ij1mXGE86oW/1Z8fyF60uTUREApQCklQbXbtfgWfkZ3wZ1BkXBTT+3/38+MofMd15VpcmIiIBRgFJqpVG9evR/r6P+XetP+I1DS7Y8x67Z/Yi79BOq0sTEZEAooAk1U6YK5hrRs8kJeFZfjXDaZi7mfznenJw3VKrSxMRkQChgCTVkmEY9L/hDrbdsJTvaUaUmUmtxbex44NH9FUAIiKigCTVW6eEjkSPXkGKMxEbJo3Xz2THc9dj5v5qdWkiImIhBSSp9urVrsHl9/2ThfEPkG86aPzL5xya2Y2cXeusLk1ERCwSZHUBIoHA5bBzy8gH+HhZAu1XjaGBez/5r/XhwFVPUuOSP1hdnohUc16vSZ67kNzcHPJysyjIzaIgNwd3Xvbxnxy8Bdm4c7PI3rmdtCV7sDuCMQw7hj0IwxaEYQ/CZrNj2B0YNhs2uwPb8edsQXYMmwO73X58uR1b0PHfJ5YHObAHBWG3B2EPchT9ttuw2wzshoHdZmAYhtUvVblRQBI5zjAM+idezbomqez+53C6m2upu2Icu7alUSuoGeyvB2E1IDgcgsOKfqrQ/wxEpOxM06TA4yUvN5+83Czyj/8U5GZTmJ9NYV7Rb09+Dt6CHMyCHLzuXHDnYLhzMQpzsRXmYS/Mxe7JI8ibh+P4T7CZj/P4j4t8Qigg1DBLV9iGit3vEzymgQcbbuzkYcODDS92CrHhxYbHsBf9xo75u8dew44XO17DjmmceGzDNILwGjZMw45p2IlKnMAFCT3Pz86cJCAC0nPPPcdTTz1Feno6HTt25Nlnn6VLly6nbL9o0SIefvhhduzYQYsWLXjiiSfo37+/73nTNJk8eTIvv/wyR44coUePHrzwwgu0aNHC1+bw4cOMGTOGf//739hsNm666SaeeeYZwsPDK3RfJfAlXNCEA/cu5Z2XxnPzsbdpuH0hDQG2/s2vnReDfCOEAnsIBbZQ3EFheIJC8TjC8AaFYQaHgzMcmzMMwxmJPSQCR0g4jpAogkMjCQ6NIDg0EsMZcTxwhYPNbsk+VyhPIYX5WeTlZJGfc/zDIy8bd14WhXnZePKzKczPwZufjVmQg+nOgYJcjMKiDxCbJxd7YS5Bv/vwaF1osv37v1Noc+G1B+OxufAGOTHtTrxBLrA7weGCIBc2RwiGw4XhCMEe7MLuCMHuDCEoOJQgVwiO4BCCXWE4XCEEO0NxukKxBYdUzbGoptyFHnJycsnNOUpe9jHyczIpyMnCnZuJOy8LT14W3vwszPxsTHeuL7j4wosnlyDv8fefJ59gM88vuLgoIMrwEFVRO1DC32Fu7OTjJN9wUmA4KbC5KLQ5cdtc5BZ4cAU7iuKKWYhherGZnqLfeLCZx3/w+n7b8WAzT0SZ44+P/7Zz6lBmN0zseABP6fbFPOn3GWzIPFi6hhXA8oC0cOFCkpOTmTt3Ll27dmXWrFkkJiayZcsW6tatW6z9qlWrGDx4MNOmTeOaa65h/vz5JCUlsWbNGtq1awfAk08+yezZs3njjTdo0qQJDz/8MImJifzwww+4XC4Abr/9dvbv309qaiput5vhw4czatQo5s+ff173XwJT3chQbrj3WebPv4gLtr5ELY4SauQTRi7h5GEzTGyYhJg5hBTmAL9AwblvNw8nebYQ8m2h5NtCKbSH+IKX1xGOeSJIOcOxOSOwucIJckUSFBpBcEgEztAogsOjCAmLxBESCXbHabdnegpx52UX/eWbfYz8vGwKcrNw52Xj+f1fvvnZmO6iv36L/vLNwSjMw1aYW/ThcfwDxOHNJ9ib6/vL10U+wRQSBIQf/yk35fB6n47btJNvBFNAMG4jmALDSaEtmEIjmEKbE48tGI/dhdfuxGt3YdqDIciFGVQUzIxgF0bQb8HMFhyK3eHyhTOHKwS7w0WQIxi7w0FQkJMgRzBBwU4cDif2oOCikFaNjlKapkluXh45WZnkZR8lPyeLgtxMCnKOUZh7jMK8bLz5x46H6SwoyMHmzsZWmFMUogtzcHhzCPbk4jTzcJm5hJh5hJBfMQGmhKHxmAZ5hpN8fgsu7uPBxWMPwWN34QkKwbS7MB0h4AjFcIRgOEKwOUOxBYdhd4YS5ArD4QwjyBVGcEgYzpDw4z9h2IJDcdgdOCj+35Tb7Wbp0qX0798fh+P0//2XmmmC1wOmB7yFmN5CPIWFFBYW4vW68RR6MD1uCj2FmIWFeDyFeI//eAqPt/cUYno9eD1uvB4P5vHn8Rb9Nr2FeD0n+vdgegsxPR4aNOtYPvtwFgzTNEuZ4ypG165dufjii5kzZw4AXq+XBg0aMGbMGB544IFi7QcNGkR2djYffvihb9kll1xCQkICc+fOxTRN4uPj+ctf/sJ9990HwNGjR4mJieH111/n1ltvZdOmTbRp04ZvvvmGzp07A5CSkkL//v3Zs2cP8fHxZ6w7MzOTqKgojh49SmRkZHm8FEAFvbnlnBzKzOFfH6fSpfulFHgNcvMLycvNwp2TiTv3GIV5x/DmHcObfwzys6AgC1tBNjZ3NvbCbByebIIKc3B6c3B6c3GZuYSauYQZeYRR9OMwSvnXVxnl4yAXF7lGCPk2F0Fm4W/hxczHabgrZLsl8ZoGuQSTi8v3V2++4cJtc+G2u4o+OI5/gHgdIRAUgukIK/rwCA7FFhyKzRkGQU5+2vojTRvEY3oKMN15mO7com9EL8zDKMwHTy62wnwMTz52Tz42bz5Bvp8CHGbRT7CZj8N046QAJwUEV9A4nC2vaVCInULDjhsHHuy4jSA8BOH5/e/jP15bEKYRhMfm+O23LQjTcGDaHZg2B9iCisKcLQjswWBzYNiLlhl2Bza7A4KCMYIc2OzBGEHB2O0ObI7gomtTgoKxO4KxBwVjdzgxDRtfpq2iY7tWePJzKczNxJ2fjTf3tyBjFuRgc2dhc+dgK8whqDDXF2SCvbm4zDxCzFxCyKvwMcjDQS4h5BkuCmwhFNhCcNtDKAwKxWMPwRsUUhRcgkLg+HvPCA7FHhyK3RmK3RlGkDMMR0gYwa4wnK5wgkPDcIVG4HCGFf1RYmGo1WfImZX289vSI0gFBQWsXr2aCRMm+JbZbDZ69+5NWlpaieukpaWRnJzstywxMZHFixcDsH37dtLT0+ndu7fv+aioKLp27UpaWhq33noraWlpREdH+8IRQO/evbHZbHz11VfccMMNxbabn59Pfn6+73FmZiZQ9GZ0u8vvQ+ZEX+XZp5yb0CCo7YJmtVy/+x9O9Dn1Wejxkuv2kFXg4UB+Ibm5uRTkZuLOOUZBbiaevCw8eccw87Mw849BQRaGu+hDxu4uClwOTw7BnpyiDxhvDiEU/bUcTp4v+Dhx48RNtHms+BHw3/0//ER4yTt+yD7fcFFgOH3hpfD4X7/eIFfRB0hQCKYj9PgHSBi24BBswaEEOcOKPkBcoQSHhBPsCiP4+F++Ia4Qgh12gs/xw8PtdpORm0pC7z7l+gFQ6PFypMBNfn4u7rxc3PnZFOTnUpifS2FBDp78XDwFeXjceXgKco4Hs7yTglketsI8DE8+Nk8+dm9RQAvyFmA3C3B4833BLJgCHGYhRTGnEAeF2E+6vsRmmARTSDCFwPH//5TxFMX50Bhg+zl2ctLbosAMItdwkWe4yDNOBBkXhfbQojATFIoZFHr8qGoYRnA4dmcoNlc4DlcEjpCIovdeaCTO0AhcYZEEh4RhtwWV/9HM49wmUFhYAT2XoQZ9hpxRaV8bSwPSoUOH8Hg8xMTE+C2PiYlh8+bNJa6Tnp5eYvv09HTf8yeWna7NyafvgoKCqFmzpq/NyaZNm8YjjzxSbPmyZcsIDQ091S6etdTU1HLvU87N+R+TCHBGgDOu1GuYJnhMKCgsxCzMx3TnQmEeHD+aYtqDwFZ0VMCwO7EFBWMEObHbHcdnoJxDuR4gB8gpBDKP/1Qca/4bcRb9GFEQTNFPOfGa4PF6MT0nTjF4wPzdv72FRac5vIVgejC9XgyzaJnhLcQwi9obpgfb8cfGice+61AKsXk92Cg8fh1KIXaz6LH9+HUpQcf/baew6PqTE8vwFIW4449/C3YeCrGTi7MozFAUsE8cJXTbXL7rYzw2Z9ERQtvx05JBzqLrxYKcRacjg5zYjv827Gf58VRw/CezADh8/Kf60WfIqeXk5JSqneXXIFUWEyZM8DtylZmZSYMGDejbt2+5n2JLTU2lT5/y/etYzp7GJLBoPAKL2+1m5fHxqKnxsJz++zizE2eAzsTSgFS7dm3sdjsZGRl+yzMyMoiNjS1xndjY2NO2P/E7IyODuLg4vzYJCQm+NgcOHPDro7CwkMOHD59yu06nE6fTWWy5w+GokDdhRfUrZ09jElg0HoFF4xFYNB6nVtrXxdJv0g4ODqZTp06sWLHCt8zr9bJixQq6detW4jrdunXzaw9FhxJPtG/SpAmxsbF+bTIzM/nqq698bbp168aRI0dYvXq1r82nn36K1+ula9eu5bZ/IiIiUjlZfootOTmZoUOH0rlzZ7p06cKsWbPIzs5m+PDhAAwZMoR69eoxbdo0AMaOHUuvXr2YMWMGAwYMYMGCBXz77be89NJLQNGX/Y0bN47HHnuMFi1a+Kb5x8fHk5SUBEDr1q3p168fI0eOZO7cubjdbkaPHs2tt95aqhlsIiIiUrVZHpAGDRrEwYMHmTRpEunp6SQkJJCSkuK7yHrXrl3YbL8d6OrevTvz589n4sSJPPjgg7Ro0YLFixf7vgMJ4P777yc7O5tRo0Zx5MgRevbsSUpKiu87kADefvttRo8ezVVXXeX7osjZs2efvx0XERGRgGV5QAIYPXo0o0ePLvG5zz77rNiygQMHMnDgwFP2ZxgGU6dOZerUqadsU7NmTX0ppIiIiJTI0muQRERERAKRApKIiIjISRSQRERERE6igCQiIiJyEgUkERERkZMoIImIiIicRAFJRERE5CQKSCIiIiInUUASEREROUlAfJN2ZWSaJlB0I9zy5Ha7ycnJITMzU3diDhAak8Ci8QgsGo/AovE4sxOf2yc+x09FAeksHTt2DIAGDRpYXImIiIiU1bFjx4iKijrl84Z5pgglJfJ6vezbt4+IiAgMwyi3fjMzM2nQoAG7d+8mMjKy3PqVs6cxCSwaj8Ci8QgsGo8zM02TY8eOER8fj8126iuNdATpLNlsNurXr19h/UdGRurNHWA0JoFF4xFYNB6BReNxeqc7cnSCLtIWEREROYkCkoiIiMhJFJACjNPpZPLkyTidTqtLkeM0JoFF4xFYNB6BReNRfnSRtoiIiMhJdARJRERE5CQKSCIiIiInUUASEREROYkCkoiIiMhJFJACzHPPPUfjxo1xuVx07dqVr7/+2uqSqqVp06Zx8cUXExERQd26dUlKSmLLli1WlyXH/f3vf8cwDMaNG2d1KdXW3r17+cMf/kCtWrUICQmhffv2fPvtt1aXVW15PB4efvhhmjRpQkhICM2aNePRRx894/3G5NQUkALIwoULSU5OZvLkyaxZs4aOHTuSmJjIgQMHrC6t2vnPf/7D3XffzZdffklqaiput5u+ffuSnZ1tdWnV3jfffMOLL75Ihw4drC6l2vr111/p0aMHDoeDjz/+mB9++IEZM2ZQo0YNq0urtp544gleeOEF5syZw6ZNm3jiiSd48sknefbZZ60urdLSNP8A0rVrVy6++GLmzJkDFN3vrUGDBowZM4YHHnjA4uqqt4MHD1K3bl3+85//cNlll1ldTrWVlZXFRRddxPPPP89jjz1GQkICs2bNsrqsaueBBx7giy++4L///a/Vpchx11xzDTExMbz66qu+ZTfddBMhISG89dZbFlZWeekIUoAoKChg9erV9O7d27fMZrPRu3dv0tLSLKxMAI4ePQpAzZo1La6kerv77rsZMGCA338ncv4tWbKEzp07M3DgQOrWrcuFF17Iyy+/bHVZ1Vr37t1ZsWIFP/74IwDr16/nf//7H1dffbXFlVVeulltgDh06BAej4eYmBi/5TExMWzevNmiqgSKjuSNGzeOHj160K5dO6vL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", + "image/png": "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TzYvueQSs27dumZQUJBZp04dc+DAgeann35a4utwqp+VK1eesc733nvP7NWrlxkWFmaGhYWZrVu3Nu+++25zy5Ytvja9e/cucdr6yVPlTdM0CwoKzCeeeMJs166d6XQ6zRo1apidO3c2H3nkEfPo0aO+doB59913l1jT2rVrzUsvvdR0Op1mgwYNzOnTp5tz5swxATM9Pb1Y+3feeccEzNGjR59xf09X+7Fjx8x7773XjIuLMx0Oh9myZUvzqaeeMr1er69Namqqef3115txcXFmcHCwGRcXZw4ZMsT88ccffW1efPFF87LLLjNr1aplOp1Os3nz5uaECRP89l/k9wzTPM9XRYqInKV169Zx4YUX8tZbbxWbYi7n3/jx43nxxRfJysoqdsH4v/71LxITE/n888+59NJLLapQ5OzpGiQRCUi5ubnFls2ePRubzcZll11mQUXV28nj8csvv/CPf/yDXr16lTib7uWXX6ZZs2bFbggsUlnoGiQRCUhPPvkkq1ev5oorriAoKIiPP/6Yjz/+mNGjRxebmi4Vr3v37lx++eW0adOGjIwMXn31VTIzM3n44Yf92i1cuJDvvvuOjz76iGeeeeasZ86JWE2n2EQkIKWkpPDII4/www8/kJWVRaNGjbjjjjt46KGHCArS33bn24MPPsi7777Lnj17MAyDiy66iClTpvim0J9gGAbh4eEMHjyYefPmaayk0lJAEhERETmJrkESEREROYkCkoiIiMhJdHL4LHm9Xvbt20dERIQuQhQREakkTNPk2LFjxMXF+W5mXBIFpLO0b98+zaQRERGppHbv3k2DBg1O+bwC0lk68dX0u3fvJjIystz6dbvdLF++nH79+uFwOMqtXzl7GpPAovEILBqPwKLxOLPMzEwaNmx4xlvMKCCdpROn1SIjI8s9IIWGhhIZGak3d4DQmAQWjUdg0XgEFo1H6Z3p8hhdpC0iIiJyEgUkERERkZMoIImIiIicRNcgiYhIQPB4PLjdbqvLqNTcbjdBQUHk5eXh8XisLscSDoejxBsol5UCkoiIWMo0TdLT0zly5IjVpVR6pmkSGxvL7t27q/V39EVHRxMbG3tOr4ECkoiIWOpEOKpbty6hoaHV+oP9XHm9XrKysggPDz/tlyBWVaZpkpOTw4EDBwCoV6/eWfelgCQiIpbxeDy+cFSrVi2ry6n0vF4vBQUFuFyuahmQAEJCQgA4cOAAdevWPevTbdXz1RMRkYBw4pqj0NBQiyuRquTE++lcrmlTQBIREcvptJqUp/J4PykgiYiIiJxEAUlERCQANGnShNmzZ5e6/WeffYZhGBU+++/1118nOjq6QrcRiBSQREREysAwjNP+TJ069az6/eabbxg9enSp2/fo0YP9+/cTFRV1VtuT09MstgDj9njZnwPH8gqpqRsNiogEnP379/v+vWjRIiZPnsyWLVt8y8LDw33/Nk0Tj8dDUNCZP27r1KlTpjqCg4OJjY0t0zpSejqCFGAGv/w1f18fxFfbD1tdioiIlCA2Ntb3ExUVhWEYvsebN28mIiKCjz/+mM6dO+N0Ovnf//7Hzz//zPXXX09MTAzh4eFcfPHFrFixwq/fk0+xGYbBK6+8wg033EBoaCgtW7Zk6dKlvudPPsX2+uuvU7NmTVJTU2nXrh3h4eH079/fL9AVFhZyzz33EB0dTa1atfjrX//KsGHDSExMLNNr8MILL9C8eXOCg4Np1aoV//jHP3zPmabJ1KlTadSoEU6nk7i4OO655x7f888//zwtW7bE5XIRExPDzTffXKZtny8KSAHmL975pARPIHvr51aXIiJiCdM0ySkoPO8/pmmW2z488MAD/P3vf2fTpk107NiRrKwsBgwYQGpqKmvXrqV///5ce+217Nq167T9PPLII9xyyy189913DBgwgNtvv53Dh0/9B3ROTg5z587ljTfe4PPPP2fXrl3cd999vuefeOIJ3n77bebPn88XX3xBZmYmS5YsKdO+ffDBB4wbN46//OUvbNy4kf/7v/9jxIgRrFy5EoD33nuPp59+mhdffJGtW7eyZMkSOnToAMC3337LPffcw7Rp09iyZQvJyclcdtllZdr++aJTbAGmkXGQZra9rE3/3upSREQskev20HbyJ+d9uz9MSyA0uHw+FqdNm0bfvn19j2vWrEmnTp18jx999FE++OADli5dypgxY07Zz/DhwxkyZAgAf/vb35gzZw5ff/01/fv3L7G92+1m1qxZdOrUCZvNxpgxY5g2bZrv+WeffZaJEydyww03ADB37lyWLVtWpn2bMWMGw4cP589//jMASUlJfPnll8yYMYMrrriCXbt2ERsbS58+fXA4HDRq1IiuXbsCsGvXLsLCwrjmmmuIiIigcePGXHjhhWXa/vmi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BjFo0KBT9mcYBtOmTWPatGmnbFOzZk19KaSIiIiUyNJrkEREREQCkQKSiIiIyEkUkEREREROooAkIiIichIFJBEREZGTKCCJiIiInEQBSUREROQkCkgiIiIiJ1FAEhERETlJQHyTdmVkmiZQdCPc8uR2u8nJySEzM1N3Yg4QGpPAovEILBqPwKLxOLMTn9snPsdPRQHpLB07dgyAhg0bWlyJiIiIlNWxY8eIioo65fOGeaYIJSXyer3s27ePiIgIDMMot34zMzNp2LAhu3fvJjIystz6lbOnMQksGo/AovEILBqPMzNNk2PHjhEXF4fNduorjXQE6SzZbDYaNGhQYf1HRkbqzR1gNCaBReMRWDQegUXjcXqnO3J0gi7SFhERETmJApKIiIjISRSQAozT6WTKlCk4nU6rS5HjNCaBReMRWDQegUXjUX50kbaIiIjISXQESUREROQkCkgiIiIiJ1FAEhERETmJApKIiIjISRSQAsxzzz1HkyZNcLlcdOvWja+//trqkqql6dOnc/HFFxMREUHdunVJTExky5YtVpclx/3973/HMAzGjx9vdSnV1t69e/nDH/5ArVq1CAkJoUOHDnz77bdWl1VteTweHn74YZo2bUpISAjNmzfn0UcfPeP9xuTUFJACyKJFi0hKSmLKlCmsWbOGTp06kZCQwIEDB6wurdr5z3/+w913382XX35JSkoKbrebfv36kZ2dbXVp1d4333zDiy++SMeOHa0updr69ddf6dmzJw6Hg48//pgffviBmTNnUqNGDatLq7aeeOIJXnjhBebOncumTZt44oknePLJJ3n22WetLq3S0jT/ANKtWzcuvvhi5s6dCxTd761hw4aMHTuWBx54wOLqqreDBw9St25d/vOf/3DZZZdZXU61lZWVxUUXXcTzzz/PY489Rnx8PLNnz7a6rGrngQce4IsvvuC///2v1aXIcddccw0xMTG8+uqrvmU33XQTISEhvPXWWxZWVnnpCFKAKCgoYPXq1fTp08e3zGaz0adPH9LS0iysTACOHj0KQM2aNS2upHq7++67GThwoN9/J3L+LV26lC5dujBo0CDq1q3LhRdeyMsvv2x1WdVajx49SE1N5ccffwRg/fr1/O9//+Pqq6+2uLLKSzerDRCHDh3C4/EQExPjtzwmJobNmzdbVJVA0ZG88ePH07NnT9q3b291OdXWwoULWbNmDd98843VpVR727Zt44UXXiApKYkHH3yQb775hnvuuYfg4GCGDRtmdXnV0gMPPEBmZiatW7fGbrfj8Xh4/PHHuf32260urdJSQBI5g7vvvpuNGzfyv//9z+pSqq3du3czbtw4UlJScLlcVpdT7Xm9Xrp06cLf/vY3AC688EI2btzIvHnzFJAs8s477/D222+zYMEC2rVrx7p16xg/fjxxcXEak7OkgBQgateujd1uJyMjw295RkYGsbGxFlUlY8aM4cMPP+Tzzz+nQYMGVpdTba1evZoDBw5w0UUX+ZZ5PB4+//xz5s6dS35+Pna73cIKq5d69erRtm1bv2Vt2rThvffes6gimTBhAg888AC33norAB06dGDnzp1Mnz5dAeks6RqkABEcHEznzp1JTU31LfN6vaSmptK9e3cLK6ueTNNkzJgxfPDBB3z66ac0bdrU6pKqtauuuooNGzawbt0630+XLl24/fbbWbduncLRedazZ89iX3vx448/0rhxY4sqkpycHGw2/490u92O1+u1qKLKT0eQAkhSUhLDhg2jS5cudO3aldmzZ5Odnc2IESOsLq3aufvuu1mwYAH/+te/iIiIID09HYCoqChCQkIsrq76iYiIKHb9V1hYGLVq1dJ1YRa499576dGjB3/729+45ZZb+Prrr3nppZd46aWXrC6t2rr22mt5/PHHadSoEe3atWPt2rXMmjWLP/7xj1aXVmlpmn+AmTt3Lk899RTp6enEx8czZ84cunXrZnVZ1Y5hGCUunz9/PsOHDz+/xUiJLr/8ck3zt9CHH37IxIkT2bp1K02bNiUpKYlRo0ZZXVa1dezYMR5++GE++OADDhw4QFxcHEOGDGHy5MkEBwdbXV6lpIAkIiIichJdgyQiIiJyEgUkERERkZMoIImIiIicRAFJRERE5CQKSCIiIiInUUASEREROYkCkoiIiMhJFJBERM6SYRgsWbLE6jJEpAIoIIlIpTR8+HAMwyj2079/f6tLE5EqQPdiE5FKq3///syfP99vmdPptKgaEalKdARJRCotp9NJbGys30+NGjWAotNfL7zwAldffTUhISE0a9aMd99912/9DRs2cOWVVxISEkKtWrUYPXo0WVlZfm1ee+012rVrh9PppF69eowZM8bv+UOHDnHDDTcQGhpKy5YtWbp0qe+5X3/9ldtvv506deoQEhJCy5YtiwU6EQlMCkgiUmU9/PDD3HTTTaxfv57bb7+dW2+9lU2bNgGQnZ1NQkICNWrU4JtvvmHx4sWsWLHCLwC98MIL3H333YwePZoNGzawdOlSWrRo4beNRx55hFtuuYXvvvuOAQMGcPvtt3P48GHf9n/44Qc+/vhjNm3axAsvvEDt2rXP3wsgImfPFBGphIYNG2ba7XYzLCzM7+fxxx83TdM0AfPOO+/0W6dbt27mXXfdZZqmab700ktmjRo1zKysLN/zH330kWmz2cz09HTTNE0zLi7OfOihh05ZA2BOmjTJ9zgrK8sEzI8//tg0TdO89tprzREjRpTPDovIeaVrkESk0rriiit44YUX/JbVrFnT9+/u3bv7Pde9e3fWrVsHwKZNm+jUqRNhYWG+53v27InX62XLli0YhsG+ffu46qqrTltDx44dff8OCwsjMjKSAwcOAHDXXXdx0003sWbNGvr160diYiI9evQ4q30VkfNLAUlEKq2wsLBip7zKS0hISKnaORwOv8eGYeD1egG4+uqr2blzJ8uWLSMlJYWrrrqKu+++mxkzZpR7vSJSvnQNkohUWV9++WWxx23atAGgTZs2rF+/nuzsbN/zX3zxBTabjVatWhEREUGTJk1ITU09pxrq1KnDsGHDeOutt5g9ezYvvfTSOfUnIueHjiCJSKWVn59Penq637KgoCDfhdCLFy+mS5cu9OrVi7fffpuvv/6aV199FYDbb7+dKVOmMGzYMKZOncrBgwcZO3Ysd9xxBzExMQBMnTqVO++8k7p163L11Vdz7NgxvvjiC8aOHVuq+iZPnkznzp1p164d+fn5fPjhh76AJiKBTQFJRCqt5ORk6tWr57esVatWbN68GSiaYbZw4UL+/Oc/U69ePf75z3/Stm1bAEJDQ/nkk08YN24cF198MaGhodx0003MmjXL19ewYcPIy8vj6aef5r777qN27drcfPPNpa4vODiYiRMnsmPHDkJCQrj00ktZuHBhOey5iFQ0wzRN0+oiRETKm2EYfPDBByQmJlpdiohUQroGSUREROQkCkgiIiIiJ9E1SCJSJenqARE5FzqCJCIiInISBSQRERGRkyggiYiIiJxEAUlERETkJApIIiIiIidRQBIRERE5iQKSiIiIyEkUkEREREROooAkIiIicpL/B0dTASBdQWdvAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -617,7 +624,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb index dc19519..2a9cdf1 100644 --- a/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb +++ b/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb @@ -1,5 +1,22 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/XanaduAI/GradDFT/blob/main/examples/intermediate_notebooks/periodic_systems_gamma_point_only_04.ipynb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# In colab run\n", + "# !pip install git+https://github.com/XanaduAI/GradDFT.git" + ] + }, { "cell_type": "markdown", "metadata": {},