From c23b3dfdfdf678d2e524e9bbaf045f0e02aaa94e Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 21 Aug 2023 20:09:34 -0700 Subject: [PATCH 01/30] Initializing git lfs --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1bccc1f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.h5 filter=lfs diff=lfs merge=lfs -text From 433c20b0f8cc145401f6268d065d100ff494af58 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 21 Aug 2023 20:09:52 -0700 Subject: [PATCH 02/30] Adding .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6b72f03 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# File generated by Pkg, the package manager, based on a corresponding Project.toml +# It records a fixed state of all packages used by the project. As such, it should not be +# committed for packages, but should be committed for applications that require a static +# environment. +Manifest.toml From 7b49edfb28fb43397bdbefc119e0870976a31930 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 21 Aug 2023 20:10:39 -0700 Subject: [PATCH 03/30] First attempt on simple interpolation using KDTree search. --- Project.toml | 12 ++++++++++++ samples/edge_profiles.h5 | 3 +++ src/GGDUtils.jl | 29 +++++++++++++++++++++++++++++ test/runtests.jl | 25 +++++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 Project.toml create mode 100644 samples/edge_profiles.h5 create mode 100644 src/GGDUtils.jl create mode 100644 test/runtests.jl diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..94faade --- /dev/null +++ b/Project.toml @@ -0,0 +1,12 @@ +name = "GGDUtils" +uuid = "b7b5e640-9b39-4803-84eb-376048795def" +authors = ["Anchal Gupta "] +version = "0.1.0" + +[deps] +NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" +OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" +SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/samples/edge_profiles.h5 b/samples/edge_profiles.h5 new file mode 100644 index 0000000..0a3bd10 --- /dev/null +++ b/samples/edge_profiles.h5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b75ef7d6f0354fa51c4c41066e72bd50df12858dc4f30582317d50d1fedf258 +size 168176600 diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl new file mode 100644 index 0000000..aa5c07b --- /dev/null +++ b/src/GGDUtils.jl @@ -0,0 +1,29 @@ +module GGDUtils + +import NearestNeighbors: KDTree, knn +import SOLPS2IMAS: path_to_obj +import StaticArrays: SVector +import Statistics: mean + +export interp + +function interp(ids, path_to_data, path_to_opd) + prop = path_to_obj(ids, path_to_data) + grid_nodes = path_to_obj(ids, path_to_opd)[1].object + grid_faces = path_to_obj(ids, path_to_opd)[3].object + grid_faces = [cell for cell in grid_faces if length(cell.nodes) == 4] + grid_centers = [SVector{2}(mean([grid_nodes[node].geometry for node in cell.nodes])) for cell in grid_faces] + kdtree = KDTree(grid_centers; leafsize=10) + function get_interp_val(x, y) + nearest_indices, distances = knn(kdtree, Array([x, y]), 4) + v1, v2, v3, v4 = [prop[ii] for ii in nearest_indices] + d1, d2, d3, d4 = distances + return ((v1 * d2 * d3 * d4 + d1 * v2 * d3 * d4 + + d1 * d2 * v3 * d4 + d1 * d2 * d3 * v4) + / (d2 * d3 * d4 + d1 * d3 * d4 + + d1 * d2 * d4 + d1 * d2 * d3)) + end + return get_interp_val +end + +end # module GGDUtils diff --git a/test/runtests.jl b/test/runtests.jl new file mode 100644 index 0000000..0f7b1c5 --- /dev/null +++ b/test/runtests.jl @@ -0,0 +1,25 @@ +import GGDUtils: interp +import OMAS: h5i2imas +import Statistics: mean +using Test + +function test_interp() + ids = h5i2imas("$(@__DIR__)/../samples/edge_profiles.h5") + path_to_data = ["edge_profiles", "ggd", 1, "electrons", "density", 1, "values"] + path_to_opd = ["edge_profiles", "grid_ggd", 1, "space", 1, "objects_per_dimension"] + get_electron_density = interp(ids, path_to_data, path_to_opd) + chosen_index = 555 + nodes = ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[3].object[chosen_index].nodes + nodes_coords = [ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[1].object[node].geometry for node in nodes] + cell_center = mean(nodes_coords) + grid_val = ids.edge_profiles.ggd[1].electrons.density[1].values[chosen_index] + searched_val = get_electron_density(cell_center...) + println("Grid Value: ", grid_val) + println("Searched Value: ", searched_val) + @assert(grid_val == searched_val) + return true +end + +@testset "GGDUtils" begin + @test test_interp() +end \ No newline at end of file From d69cd572f87470dc185d0a943e87908b7ff2ceaf Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Wed, 23 Aug 2023 13:20:24 -0700 Subject: [PATCH 04/30] Overloaded interp to allow storing common kdtree One instance of interp now takes property object and kdtree object as inputs to generate interpolation function. kdtree can be created for a space using get_kdtree function and can be used for several properties on the same space. See test_interp function for example of how this case is used. Eventually, we should make an option of storing a kdtree in space object in IMAS data structure. --- Project.toml | 1 - src/GGDUtils.jl | 26 ++++++++++++++++++-------- test/runtests.jl | 31 +++++++++++++++++++++++++++---- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/Project.toml b/Project.toml index 94faade..17fdb6e 100644 --- a/Project.toml +++ b/Project.toml @@ -6,7 +6,6 @@ version = "0.1.0" [deps] NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" -SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index aa5c07b..a799281 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -1,29 +1,39 @@ module GGDUtils import NearestNeighbors: KDTree, knn -import SOLPS2IMAS: path_to_obj import StaticArrays: SVector import Statistics: mean export interp +export get_kdtree -function interp(ids, path_to_data, path_to_opd) - prop = path_to_obj(ids, path_to_data) - grid_nodes = path_to_obj(ids, path_to_opd)[1].object - grid_faces = path_to_obj(ids, path_to_opd)[3].object + +function get_kdtree(objects_per_dimension) + grid_nodes = objects_per_dimension[1].object + grid_faces = objects_per_dimension[3].object grid_faces = [cell for cell in grid_faces if length(cell.nodes) == 4] grid_centers = [SVector{2}(mean([grid_nodes[node].geometry for node in cell.nodes])) for cell in grid_faces] - kdtree = KDTree(grid_centers; leafsize=10) + return KDTree(grid_centers; leafsize=10) +end + + +function interp(prop, kdtree::KDTree) function get_interp_val(x, y) nearest_indices, distances = knn(kdtree, Array([x, y]), 4) v1, v2, v3, v4 = [prop[ii] for ii in nearest_indices] d1, d2, d3, d4 = distances return ((v1 * d2 * d3 * d4 + d1 * v2 * d3 * d4 + d1 * d2 * v3 * d4 + d1 * d2 * d3 * v4) - / (d2 * d3 * d4 + d1 * d3 * d4 - + d1 * d2 * d4 + d1 * d2 * d3)) + / + (d2 * d3 * d4 + d1 * d3 * d4 + + d1 * d2 * d4 + d1 * d2 * d3)) end return get_interp_val end + +function interp(prop, objects_per_dimension) + return interp(prop, get_kdtree(objects_per_dimension)) +end + end # module GGDUtils diff --git a/test/runtests.jl b/test/runtests.jl index 0f7b1c5..9ac64c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,22 +1,45 @@ -import GGDUtils: interp +import GGDUtils: interp, get_kdtree import OMAS: h5i2imas import Statistics: mean using Test function test_interp() ids = h5i2imas("$(@__DIR__)/../samples/edge_profiles.h5") - path_to_data = ["edge_profiles", "ggd", 1, "electrons", "density", 1, "values"] - path_to_opd = ["edge_profiles", "grid_ggd", 1, "space", 1, "objects_per_dimension"] - get_electron_density = interp(ids, path_to_data, path_to_opd) + electron_density = ids.edge_profiles.ggd[1].electrons.density[1].values + objects_per_dimension = ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension + # path_to_data = ["edge_profiles", "ggd", 1, "electrons", "density", 1, "values"] + # path_to_opd = ["edge_profiles", "grid_ggd", 1, "space", 1, "objects_per_dimension"] + get_electron_density = interp(electron_density, objects_per_dimension) chosen_index = 555 nodes = ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[3].object[chosen_index].nodes nodes_coords = [ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[1].object[node].geometry for node in nodes] cell_center = mean(nodes_coords) grid_val = ids.edge_profiles.ggd[1].electrons.density[1].values[chosen_index] searched_val = get_electron_density(cell_center...) + println("Electron density at: ", cell_center) println("Grid Value: ", grid_val) println("Searched Value: ", searched_val) @assert(grid_val == searched_val) + + # Use the same kdtree to interpolate other quantities + kdtree = get_kdtree(objects_per_dimension) + get_electron_temperature = interp(ids.edge_profiles.ggd[1].electrons.temperature[1].values, kdtree) + get_ion_density = interp(ids.edge_profiles.ggd[1].ion[1].density[1].values, kdtree) + + grid_val = ids.edge_profiles.ggd[1].electrons.temperature[1].values[chosen_index] + searched_val = get_electron_temperature(cell_center...) + println("Electron temperature at: ", cell_center) + println("Grid Value: ", grid_val) + println("Searched Value: ", searched_val) + @assert(grid_val == searched_val) + + grid_val = ids.edge_profiles.ggd[1].ion[1].density[1].values[chosen_index] + searched_val = get_ion_density(cell_center...) + println("First Ion density at: ", cell_center) + println("Grid Value: ", grid_val) + println("Searched Value: ", searched_val) + @assert(grid_val == searched_val) + return true end From 551958b28979b329215955b5c76b49bd441ecba4 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Thu, 7 Sep 2023 12:54:14 -0700 Subject: [PATCH 05/30] stop tracking samples/edge_profiles.h5 --- .gitattributes | 1 - samples/edge_profiles.h5 | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 .gitattributes delete mode 100644 samples/edge_profiles.h5 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 1bccc1f..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.h5 filter=lfs diff=lfs merge=lfs -text diff --git a/samples/edge_profiles.h5 b/samples/edge_profiles.h5 deleted file mode 100644 index 0a3bd10..0000000 --- a/samples/edge_profiles.h5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3b75ef7d6f0354fa51c4c41066e72bd50df12858dc4f30582317d50d1fedf258 -size 168176600 From eb84a4415a76842d6e1398796503bb381f8662b6 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Thu, 7 Sep 2023 12:56:28 -0700 Subject: [PATCH 06/30] Adding edge_profiles.h5 through dvc, stopped using lfs now. --- .dvc/.gitignore | 3 +++ .dvc/config | 0 .dvcignore | 3 +++ samples/.gitignore | 1 + samples/edge_profiles.h5.dvc | 12 ++++++++++++ 5 files changed, 19 insertions(+) create mode 100644 .dvc/.gitignore create mode 100644 .dvc/config create mode 100644 .dvcignore create mode 100644 samples/.gitignore create mode 100644 samples/edge_profiles.h5.dvc diff --git a/.dvc/.gitignore b/.dvc/.gitignore new file mode 100644 index 0000000..528f30c --- /dev/null +++ b/.dvc/.gitignore @@ -0,0 +1,3 @@ +/config.local +/tmp +/cache diff --git a/.dvc/config b/.dvc/config new file mode 100644 index 0000000..e69de29 diff --git a/.dvcignore b/.dvcignore new file mode 100644 index 0000000..5197305 --- /dev/null +++ b/.dvcignore @@ -0,0 +1,3 @@ +# Add patterns of files dvc should ignore, which could improve +# the performance. Learn more at +# https://dvc.org/doc/user-guide/dvcignore diff --git a/samples/.gitignore b/samples/.gitignore new file mode 100644 index 0000000..8214b75 --- /dev/null +++ b/samples/.gitignore @@ -0,0 +1 @@ +/edge_profiles.h5 diff --git a/samples/edge_profiles.h5.dvc b/samples/edge_profiles.h5.dvc new file mode 100644 index 0000000..b09e182 --- /dev/null +++ b/samples/edge_profiles.h5.dvc @@ -0,0 +1,12 @@ +md5: ba8bc1d923f00971c24d51267d9416de +frozen: true +deps: +- path: ITER_Lore_2296_00000/IMAS/edge_profiles.h5 + repo: + url: git@github.com:ProjectTorreyPines/TestSamples.git + rev_lock: 5cb261ee0410759c4d6fd9a18fef421bd954aff1 +outs: +- md5: c3d60ce69e9d3a9b9ec621e9276858e0 + size: 168176600 + hash: md5 + path: edge_profiles.h5 From 7131e1de75ec7184495852317fcf789912d15e4e Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 12 Sep 2023 20:09:06 -0700 Subject: [PATCH 07/30] Added project_prop_on_subset as a slicing function project_prop_on_subset can be used to project values of any property like dd.edge_profiles.ggd[1].electrons.density onto another subset. Desired subset, if not present, can be generated using functions available in SOLPS2IMAS. This requried function call change of interp. It makes more sense to give it a property object rather than just the values. --- Project.toml | 1 + samples/.gitignore | 3 + samples/b2fgmtry.dvc | 12 +++ samples/b2mn.dat.dvc | 12 +++ samples/b2time.nc.dvc | 12 +++ samples/b2time_red.nc | Bin 0 -> 168048 bytes samples/gridspacedesc.yml | 196 ++++++++++++++++++++++++++++++++++++++ src/GGDUtils.jl | 64 +++++++++++-- test/runtests.jl | 44 +++++++-- 9 files changed, 327 insertions(+), 17 deletions(-) create mode 100644 samples/b2fgmtry.dvc create mode 100644 samples/b2mn.dat.dvc create mode 100644 samples/b2time.nc.dvc create mode 100644 samples/b2time_red.nc create mode 100644 samples/gridspacedesc.yml diff --git a/Project.toml b/Project.toml index 17fdb6e..94faade 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.1.0" [deps] NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" +SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/samples/.gitignore b/samples/.gitignore index 8214b75..023a568 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -1 +1,4 @@ /edge_profiles.h5 +/b2time.nc +/b2mn.dat +/b2fgmtry diff --git a/samples/b2fgmtry.dvc b/samples/b2fgmtry.dvc new file mode 100644 index 0000000..ea287f0 --- /dev/null +++ b/samples/b2fgmtry.dvc @@ -0,0 +1,12 @@ +md5: 26c488e90a669ef2909a6fbe873b38d0 +frozen: true +deps: +- path: ITER_Lore_2296_00000/baserun/b2fgmtry + repo: + url: git@github.com:ProjectTorreyPines/TestSamples.git + rev_lock: dc2da57d329888998e008f766e620ee914541d2f +outs: +- md5: 6589953daeef49b21744d159af970cbb + size: 2908856 + hash: md5 + path: b2fgmtry diff --git a/samples/b2mn.dat.dvc b/samples/b2mn.dat.dvc new file mode 100644 index 0000000..866c609 --- /dev/null +++ b/samples/b2mn.dat.dvc @@ -0,0 +1,12 @@ +md5: c408a3f9242593adab848e2899868371 +frozen: true +deps: +- path: ITER_Lore_2296_00000/run_restart/b2mn.dat + repo: + url: git@github.com:ProjectTorreyPines/TestSamples.git + rev_lock: dc2da57d329888998e008f766e620ee914541d2f +outs: +- md5: 26c5edd33fed9bff73cda8db17c591db + size: 1560 + hash: md5 + path: b2mn.dat diff --git a/samples/b2time.nc.dvc b/samples/b2time.nc.dvc new file mode 100644 index 0000000..aec5055 --- /dev/null +++ b/samples/b2time.nc.dvc @@ -0,0 +1,12 @@ +md5: ca5c76dfa367c27a421168b198c3346d +frozen: true +deps: +- path: ITER_Lore_2296_00000/run_restart/b2time.nc + repo: + url: git@github.com:ProjectTorreyPines/TestSamples.git + rev_lock: dc2da57d329888998e008f766e620ee914541d2f +outs: +- md5: 850542d59a6796eca1e22a64162af2de + size: 201992 + hash: md5 + path: b2time.nc diff --git a/samples/b2time_red.nc b/samples/b2time_red.nc new file mode 100644 index 0000000000000000000000000000000000000000..91cd47f17298ae399e934ba1722cbd08e325f6fc GIT binary patch literal 168048 zcma&O2{c#V_y2FmJZ7j2p-It1Dw=38yv&k{dxm|lR2rp}G)ht`l!}x@DWo|xk2Ii3 z8Z?kd8JcGe`fcye`}1GF|8K4D`u$#OJv`4jci(gO-Fu(&y6W{Z&e>I7?msVely(&6 zF8*hL{?m^7r)`NpJIsv=o{jq7_WXa_igTl8v>UaLV_W)fTVd{$_NH9>{0egy{L@yz zpUQI=M9h~W{^_gY&khkY=1fJ^_-EulKib=xNQb#o2Zf+2B5KHgeZ}TKFC{sJz*?L> z6MIV2BJ4ui9mH4rb=vLQ^}jDAy!1Lb1rm(|O4FwNzt{%1`=>N*_Wz4*=%#;c(TDcH z;OoCWwEOT}! z|AXD8_WS?GE@Z|cZ2nL4ZE_Ck&><$Ue$V?Lql!sEeLa5#*}JR`a<@4WH0@nW&}L`< zpgWVD1)al^;Jvt$klsp#k8j9Zj+8ABL|Q?e-KOg612i=cTnaYA?Vdr zUBNv3k1#DGQ8;ezKs4sm5G|LZlnVz(UIDM`mR(4s$ z_|`6>`For2{#J(YwKY^&F|bmYQ&lL$4VWQpTB{-K>>MiO**zD|T~ZTXb*Lp~9p(_y zuP@p4>pl6}b0Sr43ZRAs6RGLf^VDkM3fg=9Givihq$8vH(qUg;QtR{g!BaZ~NksyX z1qkLqI}=%rU|h9D1nXEEW23zi!TZ$4+SiUk2LIc4Kn+ANcG{Q|ZLH6K6l?FFIor?Q z_AmLUyOAvju8n`LwFGqs(tdr+u{K965H;}BYCujRm{TpRZ7uXyD+j4Z-k}YyA?+S? zoZ2HgYep%}_%n)TEDoa=yOz+u)~3wBVkFa_`;N&?QKgS78fpHpD!M7+C!MblL??Kp z(2;)(>ENMXXpeCv)Ue)xD!r&9EgS4e^Uf-=_lrn!gbCzgfj_ygG@Z1JE2Z+4{ix== zL$rtdVd^s?m#!{~r}>8rX#M#Fru3`-GiEchZ;E8y zgS^1w#}8xWbQk>WF#|wI}LFR1MUp$RFe}vH^LCBq9Tlm5A=Ye$=2QAZrjq!~80c57WEs~)kARdzhXF3(G289PH+Y`7v@l;^~zt#@N? zSD!HlKONR5vp?%PA%*EjOkj$CU(%K_D)dX4K7HOtlRoL^!{qG!SjXWnn0drdHn6CU zx&H}dY~v^vKDLx?7*)n{2PU&Brxy0ZxQy$|4shdw<-C*G2CnBZlN;-H*% z$;cyQ8xp{c!*6lxl2q!nE?2&UYw6o?lQ=&< zU_>?_oY9$&_R!(<)KnferG&5BR>HGRJmqJy{Q12;a{PYQY<_R;Dw z{8`u>UY&?_y*(1?0v@SLQPKBQtf%d!sIO6b|7UDF+NDK+$Br3D8iF;s18aXL!|`X> zc1O&xjk(()kBad~!#Jkl+DV&mx#Os|$^+Cn8 zw0#n?5V1t?`l-AB^$+u~-4pHF{maF%1pf5sZvG>1f%#Az7++7L59JpH}j);VIxYxL2j6GJN-aws;j6iC! zk9F#~56{P(xc|m6eN@bi`*Wmy&L?<%%$saI>U`8isA1^KY-|@}8|y@N0?!M@HiN{$ zgJA8ur4Tb>JFGP;CoU<@@OFx*Sun%Uhb%GGN zl|Z+afbY4};41cl5zek)!wSJhqY&bop2E5qU)Y+x3Nk;vhrHEY;MgroC?GmeG~)`K z>b)DT97u$x3%9@*b9Yf;znQ4Kdbg<9^NJ{cB~_F++66y{TZl^X(?ydT+r*w5_kw%v zJaB*B1n$qm!To70(i_~LtOxhUL5LfUTY!6&Ik;E9K|+vA;9j!@$92HHE(vugo__~P zMmmA}3m2R-1GNN?pF@6vdwm(|2;?HR(Y~%D+6>3`By1aFI}p!ppXWEWpQBpibp!<4 z&kiB=c+JbG`sm*#JpKXuMrivBuOp(}HqoMCsHo+-4!#BZ!C#x}qDFJChNPYo;j@nzxcs&_^TI1Jq3pT1>*zpm_umfg;~T);5AVmfC%F4yY<(_( zyVqt^Lp**S+�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

`L7(IoDrOV`-XA&bq{RiOyQJr zayho_SP9td*>5{v_6V;~0CKy^&q4XkwSHgtFF2JPzfXKu|mz2Ac5$z@Ydy3~MTe zapy8&s(~kXmyLyB8%>CH8wNX?PD6?P0=Tf!8m`zJgVXYUaMEHjl=RDnvidZrIGhY+ zSp!jeWD>_3rG=H;Msmx?%|bo~7V=(Yh zox|H}Q3B^O=Ol+8Tg>~7qJQ~jam%k!+>P7CoNfHL{oMY`*ORCHxz*-2{(slx^<4Ou z!}Ar^a56dnad^K|$m_K5IcGViiPOv(43(oM!1-laaJg{bya%b-PfZ`*&#F)gK-`m<#tGnZs?@8n|+2KU5yChNDY6VE@lvkTb#*($1SfdXO4i zDmu>fY1`q+CIQ;+)6aZUqJa?lBbtl!~cD??nO zZ;l}=!V%tbE!I+93{H)~Rc<3N{80-^ckpq4hdhV(0okuPZk(Yg&6>|`56(lBZs+&4 zgZp#`e-3t3p)^OztrJRjkK^_jN_Vz#__O`b?&585mp_O5YB%@yu6Ayxa{G^R&U8)@ zKSvz5eBX{YJbj###nZgbbJV!C;ymSL$mZ8i;+8*K+58#F;^o`U^Y7sGoOOwR*2?qq zI>85rR%zxIS(9Gqm*ThgPb4aRXnkYy*zOP39kQ`%q=f4Fo)V@);g$ zD#en*dMqt;z;pX{<5AK7~ITKJCWQ5Y$t2w;Q2KPp($lKjqKc438aqdWd%uJr<&-lVn zzRmp}>dxW&=fC8i>7jH1ws6spjbje$G|A9K0WzbCj25Hi!59!702vyq(W_z|*{5f*g203x3QAp6{~I_qc=5 zJ>>wtREfp5Sy6(5ZGS;Ex?IqFq9|zpxh`l~&JlWF4deQ>qu3rG#dehd{OI9@&FfFkn;+A`)BRD}m$&_X3sBl85~b?TxJ5o! ze-6LKVU+gdR)x27dHx(I^7`n(^Y=K%%QFO}a;CgYkND@j-j&DlV}5XZOGrEQg0B;I zMsQsHNpMRH6okW;!lL5C!fJmq_$V(F{M=Rx{^xfJ zzO!}-d<|Q{;rLi#%*JWL2#>vjRoO-%G4ZaDhMP{WT_qguXckWN{VAL_FA~mNyC$58nIxP(>L!$4>ktahcnZ0{YJ|go0)&3XvE{^M2H+DnM2qpAf&Gmt+xZZCC*8;}<l(eom= zbvo$zgzGZjuSCyIu7&E&eXMX7CF-6i>Bs%U*YcK_aXWyZWN0f&#tlb_9ru;}YLra; zi4t3`ts0+$lHuIH2Bkb-6F-(~{{GaXXA{>SKH)mGhg{!zd;ogx`i7qAoORcDS?tj> zGzmTZN1~^62YL!wJY9*N3%PzUD}(3XDcY!63O{`FgiANZ3%4HR2=9ka6MkleiE>)| zLT3@ug83gYqjk@ac$Zg^yuVz zhFQEGZo6=wE#vK;xA{Z79k!+M=axU;gLb2I{B@MtpGB!FA7iKRK6VW6bBwh3GoFo- zPi`o=6^fG6-BD7k%G>)|-WJE8#Nh(hI?d$T9qN$p?Xr^l|4hb(3O||Vs;{(B>Y2-3- zMC*QWocj!MQu|ub-mZ^0QGJLw+Dch8jo&Jot|Hf6DkrjxNuvLyPSM{`U-TWlN0cUnh|_9sh?5Mbi^E*?#6Id@gb$NFg;u?> zqDpIsXp(&srF`u6*ExuRjR`2@^V(&8h=F_!z(9v03~)_Af8(C$XVHK&t`*dkp{EOvBN3>L?hD*- zdK6#pD}}GycwGnGdX}MUtP#5EccIIdTy#0w3tetpL)Ttf=-MX=UGIEAHzPHirf!bY z75SRFt#i?1TrY>Bs?9LrLE(Gh+<)OhgF1-4<Kt+0bZc>9^$>CL{1u}8fNtVsGk0<7gPo%9o{wUX!2xk`)(~;|UTtyt6e}@w z_&{-HXTIoXDu{<&bHqaz8^w!!9l(nZ?uk_szl$X%1H}DzoWw0Hd17pMhq(S>y%^>j zCN9t~6@|0~qW1+5$Hy3pT2T*#$7$xmK5|5el1K!%o!9UekI7S4dk7Di37ERX2&0@U zaJhE?&i{QDgM3dT_P>O(`e^j8uSVY=?fky9(Yx&zdVSa9x+OXEQW}KPx5rTWh>u<8 z_;|?ml9JNxypQ^W?uXvuwD(HrHlzVvg5KfO*94u`4dQds%W;a?S#%hyj`n*tqrIUg z+M8U($uI7r{eWb&Pk)5=*Jh)`f5UOgu`lSfVkA0eYH%#KGIl`V(tAxk5>P59NwW5WMwm8XWx9IlcizwCIA^K*x zh=FP?;+#?WVnkA?m~u8+%raRj?s}Rg?y24?=2-6%H_dq~Zdx5Bw!ZlxzAJt`t7m~Y zOW|{l_+Q%@@mYcvH!^KqP%>S@c85bp=4f@keb>{ znDr!77&rKqpnb>yJCrK$(z}ybXfzdfx@cgkZY##*x#8+sYrZB;1kS15f@oujfmhPe zucr$7Y-Z>srlX{CGkPZQm=BLy(Ibw>ZQ$>N9&?>}8|LvLdULI+MFLJs8o}46EJ0_n z5S{Fw;*_Bq_&Q+9IO*aFoH%hY+F6z11Pgl{pS&B#E6&341FoU%eHR?B_Y21#Q^WB; z;?d4y6;8B1gOi=~(V^NKrC6JFBWW_C!X7LO)OU%Anr4mCC1;%7u{cO6*Xsc z32$;!g$tT>LjI>tAw6-a5T4&Guz;0+|z*U!sK>0S ze=vFW4~)JTiYwbzVd$w)ob_}al8h3Z8N&6I!=|CfqBl5g3}2t`qdYp>o8VN%1a$H- zM8|KX=vd>2j>RqLxJnVH{MJQ>w`$waH5+i11j53O%J!;$-@;piPMT-#=do%umEvz#U9Z`dAS&DeNkLn*da!Ixh>9-+a?CN zMT_mLcwV0 zIHAw^=|cDL>-es?5bw78^R=u#;^B+2m@UL(a%df{_dSdAd)pu#6Now2~`EOJBZz z6_1x;5pxHJ^?rmyD?8B4;Q*R$mq(L9JT}YeGBnQIh(?vG(eT3(G@Sn(4Z3X6P$3Qt z%IeYJzbk0CcoG_}b48*!M#^QxA{a&3g z$0$^Y+QNj*a&1E1F9qS)iuFRpW^JKz-fSVW9}zNVj}W9g^90FpQz6p4L5Q)_5F%Dz z78duSf`7qcVG`UCOpQtf^?q0Jk4_N2Oi9EWZx3Qc?QJ}md;)iPea4iS;TZMF4;R(& z@AWDCU0`Y$PN}lRQDd^vJm)@|G*+VVjt6LHZ;biDQ& zzuk@4Pst9oBTk~$cNf&6KB$>vi+#^B)ObD@)sHq{pVSkm_W2{KHJYN@f_JET@H48k zE1}9*ipqr|Dm!ez-p|Hi@9q7tH>hK8_5gd2TZ_G?^X^-*+_U84{`v%vpNfWqE ztv9N?8j7lo3$ag+1XSn$GidyMfSP}nqt3)1Xz=bUnt#?o8~q5J+ISKDGMsUqy$-JT zvcSY;i!if)C+1e>a?Grnr~b+S(Jpq96V?^2Wc7e)wzpZv1#x9*e7n zV(|}Mti0lkm7BA%V@)ppsmc|)4Z4KCdhWtc^V;#*Oc85g4VK@_!Thjv%v^Q{6SV4Z z^_giHRPzdFZ1TmaN*mCoaRr(izd-|?0@P|>j2fr9VGp7XzdtO1@A6CGOZ#5v?6(#^ z54Zvykr$z3+B^8vc?UYwUEtFgDSRv&2_LFu_L^i zeFa|pnFlXJe#5JukD*y^FEkshgJwNXXdY+?&4DYRdG8x&eq0I7-}*!I*LZl-tq|S} z`Ur2j--qUN;n4hI8Z=)sf#yY5pqcSCvI3VubB;YUPk#ij2>R9NUjG{Hs;A(HoG)l>8H?KCuBd$U7s`Da1m8#kygBC%jkYu4 z$=;rDb#fD&nYs!p*1m%>D*;O9n?k8?6qM#CaZTA${yXAwD4%QwWw#WdY>^U_zB~>m zpR9uub6TOqaR3|>jzV#1EEMfigCizAp)f-pj_iK~N7Vx1cu##eep?15F%(YFJUF@J zB$USR-zJ0kIr}t0`J5Oi&kTVIl{P4U-y6!)x}f|)e<(k}_Yd0%W&55&*)Xn!8@T{V zM@Znr+5J%R%NUMNOM{~t42m86;Kbj@aQdEnQdyLF(!q1 zdEG{$7LPe(`11pr-B^Ma?wiqKq8FO4Dd7FwVH}V&7d6+MMWvsP*sb<6bm*Rj7oZ6D zX2n5`#yhC${t1p3#=#+j?~vzU0l9uNA=7#|Br9%(_`BK=XP^zS`>i4Nek{b9--mdm z9}pkv3i0PNA^yl_h+ldN;`@w&xGB9M*5n*)RIP^SGpivgqYp$W$3dk2ZHU-=8KRu4 zAf~oI#8x*#+}=2T4rNH#&b}8{dZ-doSIa|c zg9xbw<&f%`1u1n^kRl#~l$gJe96Aj)>F?&6w_>iHlR&)B6o}*Zmw09=q%_w-+LLnF zYWe}Pqqo5BuZLkj*PazF9u6f%hu~CYE>x#IhHK`7;m)M}@Z@O*G)Q{D;|fK%lX4EO zyljJ$FZ;s&RbL>=UIU_r^n|#6w;^^k*YUl`hq8$~p?Y&BTz{hgbxY4f-NzKTfsJrE zyamoA@-`SN2ZbNgA@Af(*fDY&Y_{=%O=IqJ-5$dFFNYy)!B+^SV`1JST_8qV!NY$J zIA53pP7|(z84FNN?AYh9n1T60kfzlBW*i8ijGOfY?i3<3SxD5W2zr)P1T$r(~2l#lu z25FEgctjY3d$bBjUep*tb2}Jp25Ta!di!83dN>dqZ===y9LpDId zy=#zSk`L)sLm-v=caz0!h}k+6R>~;?h8KdTl?ej}Q|61n|yt@Lwqf$skv7*^~~Gf87CF|9dd1 z`&Y2o?geJU=E9JT=fOaJIcTa@ftt=~P~rMZmFdo)(ohJhStX!$!WH`D{eMioc|29$ z_s5UOOfn`CAxTkYQiN+NDXHAO*52o6pjo5lB1NfC8cZoNlQa?yR4Pp*k>*jO<}~-) z@6Yf1dpv%BJRfVHd-vIA-*wKp1M9V4eQB?_Fxo3*673~@Ks6saQB6Zls{Z>3RkzQi zYC7CkZE7-A9h^&5{^U|sx8GD_dmh!60M+Yxjp~`6p?X^^ss7Pw+NWSX?R#CB8dvP5 zCT=fi|IqKW|EpkXdTTQ^(-o+h&Q@yHu20QUZd0>~zo==QF*WsiOigvpP?N`|)cDz7 zYV06O4V`_ceq15d_gF>^hRRX{4GpUI_#M@EkEMNXbyMS>Nwoj|0BSMFiCWE>PltF2 z)b8d}>X>+tx_xGJ#6o52JjH?9ZfK^K0nXIu^IrbC#!&fj2l0We1wPn01~1KCiWjfw z;Jf6v_-{r%Rc>vgTGskh-?E7ss#Z|L=l^J5%SfvKXCl>E`Ih#Y+LNj!jHXJx$4~|C zPbquC1OE(a$FG%Vv1@S|z6y}yOGi_DRPY*`UhKxp7s~MBr|)!jgG4Sawtn z4;GKXiiat9C^Zi&kMF?Bw>enZGz<^l+lYrxRQ%5quF}jE54kqrA;SARRB;bA{+ey{ z@Iajr?)UwL`=&KuPC^y#9k3NMOOr5tf)4K9T8?`L4aH2^N0=RZ2y+(w#{KGxaerD8 z?$a^F>>+8m``I>33mA=CmA_#8_zH|wj>n}s>$yi*H~KdwVZgNGXqr=wX5+ljZTw*L zZR?96TKjM!ACD+m;IxB-F-oo&XRWBhS@sn;%fc9E_5++zaS*3VlrW;}F$y*^2ug^P zXC-0iq8%9W$s0p31t;3}N56g}(CgYs9IbdBeO!*9--v}6=Z1K25{np zrxz*%A>&P=YxsI}{H>Ud40+KaiyYAe^8d18Pp z!GJT*FeK&#a>GQNwe%@Qk9vUf?{C7Hqa{dkC*Z`O_c&_ZR2<%G9uCvAMVtNG(7bL6 zYA6_?MrAhKe)$$|^BR&*g*V_|>3dYz9)pUTHls4J!(J}k*gJnb>QqlgU28Yg>&sB@ z;9S%_{R8#VH*jyUSk&fvG_8VfsL}in)s}>!O1D0$%Iw8n*5gsJC;{d3qflX22`YX# zgev)cQGM)F?B(x;y~~nO=dKCrt-XNyhc=?Y6%XvQE)Vkw-t`wtc+e3M{(5Kqd1c5&^+RU(e-l%IVI=%gs)sMaC3rc;02PK zABL*u`f#qN8&th7fnyuC!HM*fP_uCXoaNq4=O4d>%Mst<+TBsmoOumeRqUZHzZcxu zv;^)3PlkKz`@#Jyqv7G10(kPs1Uly$!P}-*_ZyZtMxIL;TE1~L- z1*mdxASxcQ;A>0ogumw&!^c+{@Z#nm=qT$Ct=X2);k*x;LyO?n8aKFUw;itfxj^G? zb+~Y#4$jMPEz$B8Xbis&H*N;Q?O{LQ;+;IWZoV1Lypn-KrJtd2++HZyx&-#uSHqUx zzaZ)OBk+b-;B8?7W1=R(_)q~@j5o~rmkaZHe}SQcSlRCz#I#7bA5=8N4p4*m zJ9i+l?g(r-VFM|-mXOw04|X**LHZ;U$TTm4tcD}7ciJGxc{d35zn%>T&i8|&KMGKO z@hKen-2fN-i=fro7}}TYg6pYHaB)R%XsEV@%ZUnb^=maWSr$M`VozvQvVqpxAZRlb zpe;rY+E!FS`{Gz=i?@c>h)d9NYz#E7HGv!1+n`Y~3C^pphSM|U;8@lGD2=p+iiNkJ zu-*=eZ{LM-u6;UCKN9lyj)B~hdtkrU1=t&03EApxkTv@|WN{5rR{JZ+vE2;2bauj? zhM$n0J{YzKmqEh28Lx<^}k`%eRYt;j)yTxT`(c38z#>?2V}z{U`ZPw zqWc<5Ut$7LZbdNr)=P-)UI)u06xJQR1RGXGzz#(N$kEvX`z3~uk)a7YyX#?R^;X!U z=nNUJd?1^>g?-%PZ~vTLkSlWx@~rA0Z|!!-OZ*52ru~4t>#>mQUkv-c#6S*v0ogB2 zA${*?*y+3xQYJ}Y(>Vu-Pjlzj(PLO|r3CA^U)5TlL$Lb!L|A@a3zn4cfyHbnEPT)i z3;H0;AKM6Xvi8BO!51KE&kGRmPvwguRsgwU2IGcB!|10rFrrs344XXwjKc}^{r8!) z8eJf*y0=N|`&@Es?E`XiMH6WZ+Ofj#5QnNN&v^3@4)`~~2dc_-G9!fH*zrO%|~t`jLO3nV2bt)wXAH}_C`LJH0jl3#Ox z6fRFE#lLFF$+kLDnRb~Rz1U1@A{xj!@BZY<2H<{TzU1BkJM!#wE_vJcCi!&hHuxUQ1XynX|Bv%Qa>^2XgId7byahZ( zuAlO;2FLs|7+T&91NS_D0RyLk$(S@Ssyqk=-*v!XU>N8N1)zU_CFoQv0qv`8pfk<^ zwEY^O*Y9zl!Qc1Q`Te21Ybx~IGZN%`-37TXr^&AdUGm=c5xM`}oZOrpM{3u2k(%k+ zWWiB468-Zzi5}OBEPNMB7T3Na3vU*a`NwvU=%)f%_g=#*{`D)4}?PU_#8Ky&A8ix>mbmYIN=C@(5RXmTWR!0@@$4EvyyWi_ZzX%;LoX5E^>M_vs)k55a8EVk zeZ==c6p_rIPb3M`h~J+u!jvzNP@g6;p^7`}@{XdfRkriZ9`V*3Tj-LbD z=Oq2LHrX4qm*hqjlKkq^q4+#wg-2|2&*6*+g?gVg&( zk-DE#NPYBTayGw!fwO$rP^~GeO8qrErI)aFbG@Gav1QN9eN<=MIj;PP`CF=W9iKdDV z(NZ@e+HR+aZoLCBNIOCd3-=HsH3woey+1KN6;6!(ev^I%5@MnsN&3&|BsQ@Y#L7pH z*uqBQa#A4P5p&46eknxS8cSxZ`bHKk@gOUgt|hU5?~@H%_LD?$14*)(LAKtyMN-v$ z$k{ zzfO=3BR`Q(W4WfUHjaGhH-&uWK2o3M2apf(r^#CnchZ@&f;=udK{^sXlcwN912B` zBPnX3WJ~ifvRS>IY_L2?;;vefHQ6oPk1T~mPPj%$h7Xz0?oB)r8i~j5+0vTVOj^^D zDXq`9k)8`ql-6gwlb*{NA#G@hls2lWNv|lLm0oLWmo{5^OI!c^m3Fv?OCMGnOP>|| zk-mO5L;Atyqx9?4Bx&~n1?l(u%F>@MO446%he`iw?jSvTnh_;k?w|HYO8V-ICzdiE zWLW+#;^B0R_|F?kCM-Nh2=}OqNd8VD^P0)*@W*7{*aal|_&l;`+!nH|nrjB6LrKEa z(`2*abdup8L5j<>NoDy*a%92}a(uonsU4tA&P{A4jR!uFW^XNW`^pc}vGgaompzx< zfA)YpuwF#&7p^4t5)8?m0wr?mTNJrbaEV-c+)d859wEna%eg<@6_PbekEA*LBU_YR z$%gey$@-@Y$@*2UB=+$cvhJHFS>5|GS$?UGEE)Zt-=}9tH}vWusuCtiM}2Jb0yaxR-@AV5X&%z!K@K z_<7O=T|K2MJwHif2RcX-^?jvV&%c%K*fvGF=RmA9r}?(DK$tHrcejupsg0GMeAYu+ z=inf{U@j-Uq@5#eyw@zf+7K{Y-8Qiy${5zL4uR zk>uKp8KhAfLoSFK7Ee;;=1@xPKZ- zyauTd@0;(4&(gQVTibz*`s7dCH+K^!KTR^UauXSlZbGaJUlFpg2U&mOBS}fVN_LsK za}Qd|wdB1?>5bpyXul*^Y{KAsk-68K}k4n;H2l9duP+ZA#u>nI=QwhBZRP(M!(%XKB4-?j zaHO0moN&%$&IC>Q%lm9RNmup@F`@eH!!J`M~zt`^j zfBcv0|8f`hfARmH@BecCU%vm#@qanzb-DjLC;#R2zx{kTP8?o?_`e+gcP>YA{u}?l zKL7uG|91}lyAE_YeaQy(IC8M8irhCJ1hVq6{CD#qh}4=5ai`5;>AXHb_?je6$7(>k zQ;ob4BgmPTi%G8Q0g_bmnJg|SCQ^?o;-}z5>=TrUc5oEYRr(=aJJw#hCN)U9`#`a@ zXpy(Hdh{OYb=7X^`>_#3d;BBfY?eu44h4|X8DZp^(*w|HE&-RUzTmg{E=cm?z)wFE zro%s2*trZMf4W12$6^+2$X~nRN)FGt;ZzRKo8f22ZDB>mZOHIG2FDtIz>Pyu@H0*Wjfc!a z+o%wt z4+fDFGc?Hwv(@CTdNlc#N1hMhM*oD5Ti63_LMJ#i?(l2W&mIR>DOX( zylaR)pE}TQ(_|d`wGbI?!l?#nNLL=l@TkvhY}E_SGY>EImWaQ}@e?!!~Hjx&g}kK@nbb;wl_oZ*}pjwxpmXBKB6C!6!%oL1qqjV2hk zu^CgjS6QLMVyxYng^#Yc;FqX1*tI(V+axh~Vy_49XiHTsz6;IQ2} zIKV9z4NMwP?Zy}Q7rYMsr3`|vmVe>1?sw`1iG)gisREdaF&`Du78t( z848#2)P)j!HAtVT5d~_zt&^Isa-Nu~J4(nXW#+vgyng?)? zkWwDKdF1mS(9F5Qw|nw9EO;I)>^Tmc zLXJKsog>e&;OO#x-JEF7Zw}9&xjBc|f19iF<9z2)hev)c2PAX&z5~KI{JI!0kwZC` zI0?L;5l5T1%c=9B2I_rn3>~j`oJMu0&~;`uG*#vsP4}KdcXEB%re(==QOhVgdE;}+ zOA@IAUmw`&=22>7*hn>B*3zDhUif>wGQJL~$JVQlu|=|(%3h79a!2-2ox(NLY+xH5 z+LA#>jHshytb8b`|3>EqZKbg*cuh7b0LuliJOnR?5h(2A|MW1E87d^(=%f{eG9+&d?iSvuYy;i6qr#EjW^BBZw;gqm3j6X&XvoXRr z-tNcYwQ;m-@ahEw4FBLes661e9KOX89Hgt3F1OML%E9_u(NygioF&7u5Q zCwL6xk^8)$z}d~2!{NSO@PkJ_KJxJ}g!7E|UCiSNCTDBJWcg=|Oh^s)IMZVKv(lOQ zqOZ(4@(CMcqQ*@6m^1ZiU-~m~B40bZoIWbnqU}*0^lD%WJrmhTkEFk#MP<8bj!PF! zE4fe8PPo%sj=yQk!(96E(G>b?A!9vfH8aiLvdqBbEbEsP#w^<{*>Iir%(rq06O|XR zCFw3KHnV}nUtG*K4vb_QCX}-cryjB`H&3!mu6N9xko=j~ls# z&n20+yLda7$3otZj~ls)?Nf_oJ2zRdO`8kZ)&_HyZTN!~-0jJV_gJu^<_#?GRs>6v z4`cDKC$VLHKC;Dych~}**({QKKXB7zHqMmS!YSx6m*V+s82^m1>+_f;te0U4Q@BUO zu~wG#QHK>a{bGlQ$+7DBeOZmxH+E`&2)p=NhTYG8!rrIzdbi{=g8Yttf}&B7pfti> zkiXbRko&PsQ0;sqn3dcSY&{qY45(&-{vjMY7U);Y8O#DDlUSf{C+E-q`?&Xa-jDlW z_;YWT|6PoeC)AL zSYQx8R&W9f9P^Kl_mYpZi1UiK6ZzPi`5gGR`j?7d)L>Jz0?EtVCDhV-1VDXxMIetmw#tR^R}{My`Bl$X*NRd=Tn4!M>h%9H@yY> zGZzHc-pd8|09#?i=yqX5ew^Stf1ME8X(@=6eTArNHp09+3BrQmS;G9h3?Z_?SfHf~ zh51@kNR6=&@(Qh4Ko3h!6DNiR$oeqVaN=Kp6M3y^ut{C_NF0dm(kye?Vp zAq!C0&SNMGP>*5(^0!!k@<|q;dXC2lEI?xbZ+GxGgKHDCIi?(56R!S>1!$(T05!(j zd_1Mwyj{-%dOEWJ#Z^3VErYxxpF3bPr&gqE) z)%h(1pO6Y;FKP=R*Q11x`+-8xcMHLL;!?qF;6Y(%j=W&?Y=|)E%`YKIKT}9DaTE3k zkwWf~Q9`l83Zc}-Stza>DHPm3Ddb-tA(W&V3YBO62-USRLapv}p|;yYsC^nPob2&e zIP}k6D5!ZWRC=Be9>RazXE&V&;1Ue_Nt|@Yf`0<#r%YdN3Voq zzxNAOAM}N4=~SV5Mv`#MVZTt`FkQ&se@{3t%~dGr(N`#Ud?}Q2%>Y1X#A1ATLjuFDY+kJ)ixtoN0Hm8NovDuscapdFo-oqp^hnVjdt|fUil=BXJE7a< zkMMre8R4V8pYUVLQc?EvGO6ru0L!EjcRMTpTD4Eh!LfF1Lz}Y)$qJtWs*fPOd^&rN!W8H z@#48R*~omq66RY!k@?0cGGCt~{21rCkIxI{vwJ1;5p$W3K_&B1nZtZ!7BKINsm#0T zHuK&ynd8gn7tFjPk1}sK!@NfqGjFb~_E!7Dymc#?_X1?zpALzha<_yJs~v<(wOlXt z^{UvT^RlR(3Jb;yqh4d+%`m-X_fHUA%%VkWkJDnG=x9-PZ9(9hFhFO3x#~q z=Gj@%uBuBM-WDa=PiPR`bk~W23YDU?;G`I7=qk?1nJmtcY!atFEfvR^FA{_ClUS77 zDHeGZiD!pbiD$FQ#Hy6b;z7M7Vve?pxTU~UTycAwI44v^WH$cdq+^<*zs>;Baimo2 zdw9L@L&s96J+C2bFR>A3>vs!I*N?DQclNS#r<2+KLq04qHJru#ILl^v&tam=J0`8u zWntXAXZ*@5EI5UK_p4WDfql!E|J4BI_t=~HjlID9WWO-U8-9(yn#Uwh`TIoPMdtha z6!STBoQ?j)y{4SC*{B6U%%j?ijqrZN+@4=%u4#{$3-^9>u2E*rR;kRXbQg0v*oQgI zu3%0%n#@^Mg*khSVJ=g`nX7y`bE|M?BPwm!C{riqJur#+&r4<@&-vO5B`$0^|4p`g zO9-nndCwYeXbWZ)dIDa)CM5qD!*$h(LYJq9sENwrfI)WRu#^j;+kls%XWckavSx=k zVP3H~yL_z}e{#N<{B*3ibMItvxBnn*VN)S9eSolb*Gpl%NwZ)R zG)+){qr_gw*R$HIdF(*lI=1VQ5lie!XRC*AX7iqmWYe4k1_Rfzu(H1_B+QnLDdFE; zy!mHo|9a-T;SlqIaOQp7nR(Cq$GrJUhTe0Mxo)pN^Y)m-MlZU^JRfJ`-M9$%VW;BFL3QuA2#a6L?*Gl&O(Aa7+aIVmR|K>TNDeEG&Lsp`bjwnuCHb{(pwN^}* z?iNdBGR0#XM~Wu~REh`QbH3P%TlbiVTQl#7`&>fBJ^6x|&=fBUwg<&Q^PEMQ!TW^k zc4|U-doN+vNU5;?tdS69_fiEDhVJ9D-XZaOHEOmD- z+nBMItvGXq%~>&#iA(F)l!nV}e7-CT+RwF<>vyox&qi?zD`Xzqw3vHWf96(qkn5-l znCs=I%(c*fx#q58uIrJx_J6}%225d23(qo#IfJ=hO$)P=aE~wNe#~Z7C$nx-XM?!@ z-D>(&HgLf}X4%0#t)%Oiw1y3|!bc@Iq9o^2>CmXP>dkHJJbdg<{(#~GWR0)c=A_e0!>4Ib3 zQXvF7ggF-V!iIT+gk6Vvd^-jTMT8l8CZ;_z& zbf?fG%$vP)HDI^*UuN}kDXhZj4a+__fNlNMo5i_AusI`6GHDn05N-2j67G@ZxvCd) zUzow1twm-Z^N86EEnq{+da%J6glo>0GpoDH*uX!QY~XA)Hc;&mvuxPREa%N&ma;vV z#f&-3+^LJ1UB1dpBa&EubDGgzNl$C<(2iA?`t2h*Q+lt@!pa2V^H7B9#Q?k#AjHweb< zrv=;b&jlZ!8-jFCs1W_iS6HvrBy27MVcUVZ!ZrgNfjs>nK(Et+g_?(8o~tW_nEw$b z`FRTCyJH1Ey-dNW{+2LcsE?J=lqnU96z$1KYFaAWQngy}ge- zWOF*XK6mIC=Kn!t?hdoq@QS6(JjIO}Tl`>s_KxQ1zV z>|~mzrA&i4G4-=8Ox@)vQ>!xJdb1Hsm9H72@>rFrsC;C~PG^{sQ7BV1p38dXNm^W+#2#v-%ew*rm@G z*tK~N*mb3C?2^_UR#Vf-HvV>G3GR&T2^q-t9O=gzCq%N_va?zHfDG1pP?=pT8OrMB z`miHIWm#_f3bvzhF54KL$Cf(eG4a_H7UCx|FaCYje&7&hIbVqxzMsN+{ZVI1Ev2mI z3`)PLext8rjp_3&uKOC3N}s51r;lTE=wpvn^szt3>Ii)tb&x(P8%rN~?WYgJ^5}zw zMfASxQ+ju|EWJ~*ing7}qqpt!=&j%e+QR>S)^a7Bwr&olx33PSZNq(O+wASME$1F> zmpMS&r%$Hs$5zw!=f1T4!wh;yZZo|z%#PksZ>Q}SUeWeiB1%(+Jz>$zw! z>)EpxvsC@XESA4zP$>nsxL@M3!AsfVi%M+HobxQgs*p`o+{%2Htz=FWU$}+} zneob4*8AiirnGtq{dedZ{m^R=eWIs8TmFrwjitHt^09DQbuyeD+`{x@n1gE-k4@qa|b4)8bDHXz|Q?S~SC!7IY`m{F~7<@0SJ5g)F*% zGNn0xH_@Cu5p>_R?KCgYnC4FnqXpANS|~A~MI)Ee;z$QtvdNv6E|;feLy~FP7EfAs zejP0z{fU-aY0cqq*) zUO;n4E6_qEZCZYNCOurLMXPSw)3ez!^sMo`{d^7#IRgpe!dPqyp4yR>K2DEN_7CjppPk&}7Go?8O ztXE|}rsHkTbW#s6?QsrF@70n!!L3a)qNYgeY&`oR$UH2x5u2^SCW7>Ra3^k+6da2W8Z>{Kxst~$z%XhlU zZ9ZMqCyTDkPoOIvEv3r?C({^X4Z8UIRl0C)ZyIfvN$0y$IyX~?&h<>7(Voxf5`QJS zJZwH)DGZ~l?fcWUD?MqfrX`JAC`;F8KBVz+#&m;*3*8V|LO1-KMK`K&ZQO%jbR*Xo zZq)Xo8&3728%7(@_|`-k|Na79fA$gQVLH`2gGQ`fN4LG<<6Nqzg}cjX#hlIbNL&E-%lkwt z?@DReoyWAmv?tA}{!aIp#nF_@$#k>YUb;RpiLP8bn=bIxqBA=EDZEOgljSPuq#;+R z|JCEvJ*o$Ftn5wgZxmDea!MVT19fz>p-$8Dsq=hq>SEnVUEE(#7v-_kc|<358q-7_ zw&YTK_j`2M?AO$8=vHdG-IESIbC%i~&7;FDld03EXzI2pkh&jGryhL*=*X8tsMmQqXeZJ}u0LBst-8hUjz9g}pE`p(FpBe#sF z&c;vZFz4fRutO@fsB5GB=dYoCwZ2jP)rnN!ek9dAe3mNwSwLlPzoas!c2JpTI#jk` zCY4*m*DuU^K;<{3Q3dXysNlYaDtLdU@{LJUUgbKK`(Z`p93N9z%M>aTH<8Lr;+|PP z=cr8Xd)nhwDOH-kjjCE)r>fkOQOz=es`K}4&52*A)?#0(9c)f@nx|3S=Soy>l^4}# zJ*fVEYpQ=>7d0UFse%4Js^4Kw_5B#tJJ*-$C7Dv)i9f0K6d&3`m2{HBi;e z1yuFt5URSdjjC8msfy_Ys%GU*HHtf_)*2bAD?zINHisG+ms6AA-*f;2I-#6lg-T7Fe<%Pu`&Hh z@p{|{Y_7J#7MzBy(F?HcehJ=b9Ez>dL3qRQA~xtw!P=MK@L1 zpR0qR^PXVn4>Me{PzB>AT4U1iAaw zH=AT)%DV@+r+5)&K7EbpJ6GZ!ODU%7mttnrG|c{Pfcsp2VXpC1%o~@42NWh?exKf$ zKVA#-M>J!B-Eu5YOvn78iFjaH8|H1-!n_^3asRCST=$lNSyF%8qiKw3Gr4Ejlf9Vw z@;at$3c_vNPb%ruW!$Xbgqx@Q#4V{?aa-1UOtGuQ)YW#FdaV&tyr1IMS$8neF9qXc zC*sOU+BiE^2dD2SM``sz9D8#C4!2*4!&6w_+0+9) zU-w7P_9*n^etcdsdN{h*T=c&E1tq_w7g)c=$VHTx;JC+bVUp}T7jNo0J<#Mh)!Y`I?KLB5BJ{~ zup@x`gtg<8eU>5?R0(%^7LZu_tsAgS*8iFROKkJJ<{V$_z>3itRF@bxv z1RjLZ-PH_)JO2#t=X;6`vA+_pUkFYix+UtT`&?|unM*N!w zXkiZF-f9qLc@0AK!ePRMI}jS30z!!DG>8W z5!Uo|hS<#~Vf}qA*svi5Hhv!od?gszRJj$BrcZ~hufieq@Cn!z;0#&pF_cbIhH9Ca zP#awX$L?}JuecgGY^V#zmWxnrQVX@hU^tU}8R~TIL)}v^IOk9Z=d$DB+=-=de)l&x zcf1+uuKj?sf&OsX<0{m8t%MV@5213$CnyU@<=0go$dsvvy(@!ZclL5fcl`#L;$hf6 zxd-eRwFy%DJcAVO!?tboTG$$J3AQ@+hppA^u=TDvB(saK@#Q>7{Q3np^)!dr{>dj}uYnLtmyZ=kv;jeFqif!>+3pcnVZQmbqMb4h19p70gY6l`kh-u1QWWOEwoO&AIZ+li?z{kT zDuZE}r#s9$zaHjfKZPhGIfxjV3&P=4V5$899FIddzdonr$-rc;0h*MX3}Gv*A#~?2 z7$0>Ef;X0fUyv5~^za5x=K)~fIvK1+T7qfWanOIW7J7!?gPv0-k)oAaq$so}DLK+f zijT&V!j6X||KTQ5WIK$M1`Q@9`-YOThjU5g1~+mdQis&k&meW90(_ ztiDP9ENch3Bbv~2L?>da#`Ue8HZh=8|3__vLJ`K>Zdj{$;BSG<$F8P~B$@|6% z@_IJcswm}>MmuZLs4#`BNaY?Z$3?QNuz@UH=tUN*TqMy&OSw+Uo2(FTlO=bJ$cmlU z$f`$E$+~(~62CZuY_!oL3DN6G;+zvCA>azx@Gy>SNS7n==iZa`o#AAI^JkJ^!Todc zr<1Lpj**lVon#kPB-#B=kpn?eQhIMWIkME7oNU%1bw|y}r2*dLn!w0S?+$YN>k4vr zTq$|v)j~RL&B@24q2zD50w~me;NDtez$8ZmvjQbB`5FcNHtIwF5G62Itb>8=FJW*f zgQ47u&~DHt80Ovu!z=HDy=fxYd)b16vIf{+YlLC1>%gwI4Te7Y2R4r7Fi>MKm>nI* zJ*WDBuGADXFWdrE_YCOy_Xocg@<49SPLON95AuB`f!rW7kn6h`dbnAD?9o>8m+Nf4 zce#--KU&GV!Pm))oL}T&#~X5g%>(Wyw}4#wAxEn7ACn574qmH1h-6+FOx)`XiM#o6 z;#MwCMl|PphnB1*$2|kd8CO}-c#-RLqBf8> zp0ec6i8Nn4=T?BSrbAsn>opM%!l zi_n|<-D#ca51L==L8D#<)SefE%J89}aKH}aG>S-f;d1ge=PY@ta+=)z_LVekh#)PN z?&PMbF=_d-h1?2ACpX`HCbv|~$*rNGq>0j8R464xWhkU*o+OdZ zvxjpCWr}19r9nj~Lo!4mL(-g#88cI+43$D5QKrn(`}AA?cdd85%lfQm?|r82+56sm zZg+pr_x7z0xMrRPmzu8OI^>^lD(?@JwyuLBIS#p#2EyLCd9Wiv22yL)VeQ=-SQ=Cc zOKt5(?B?mpG0d)V}2YUQPPZOPips_~-G>^Q5o_VuDDzJTAb%Aw!_w!rfqbq%RCT-3kuB zzJTlGso-zo2cQ!PGwsS@!ORX=o^}CZ9lyaE`(BW|*96w1hAXx1Fr=H$g58$q;E=Kc z6s+F|7j`GXo!fn&W@{WgIBE?w0b}6_tcS*co$zvIS7?2RK5Nlg@X1^TI{N*EFAu`t z>#RWd8vh!;2B<(sRtG#ql+1c!0?>k*BGkb6N94m$RMeH(Hivp57YzU+f7|MtOVtsAg` zHA71EW?1va4x%?2!o06LL9{yvZZ8_at*}9O>^DMqJjgQQ2+56vu)i~4LEqD`TyFuyZ%K!g8`hBaeLCzliG=*OQ=s(GLnw>e0_C|k z;WX(27v}tct0}wSw$6OGTUZYdvfjhPbbEO8y$d{^s|Sx=EZ|XEDb)Ct!`<|Ia64-Q zT${NT&Of{kCuaSGf_bwbr=$>e%?XC|KNhfY2kPaDeIU^_7ZSS%K@tyvr19R6JoGLk z75s(x+m9joN)tpcc?`?7=Rib7D9pVy4W@mO0Vo^-Qyiv%&*Nek_tFwZ#(aVyiN(E)=c%BpeI7DxBPGB~%;?5YD-s70zq?6wd$g6D|(BCRA?jCR7~{5$-(> z7M{EB7d{Sd0aPZWI4OG>Dw=KK z!r*Ig$?hRkE_?))H}s%#ULjlxcZBng)8Wj8F>s>qE-2A9fFpXJAe-KU^c6LbTyF?* ztB*rCzSgCx`5>XrVA}X|Ach_Ry7LDFuPBG$0hti^XbbqE#>;)$bZ|Pm0!CiG0yf3V zVZcRAFjJfY_$MsTeL5dBD$PJGRD!M(6F|n3RIr?| zUa$*y66{Zp6r8V?3+}_73jsY-1dy>1LJZV}Ia8E{CD}iO)$`vq=)X_{(6 zy3!nByS}Bc({+K6=^7&J-YhRN8|S%`4g`Jm9WUrzYCkQ=%GH`sF5*$A?8jkmmfMY-L zbusoS6uiuU-0H!we}XOS{1OdmXYWG7qZpW9)gMI96)^Gi2yo3?0(9dl z`xD&+=h8C4^S7el-;^!DvOmHMvpgYuxV5lsm9h}KE?!6+(;=)aY!y;QHVGRZoE1`a zLWNC6Ey517oaOFg!j6dN+H5 ziOUZ#KCc433OvAI*9p+MW(gX-CxOx?bLbJ438TxCVEXQTu%ed-#2Y_?FsXVbjDNZZMiz915m_%_*tAHnd3_Fsm~4lE2kM}|(>CZ`LqM;I zfZDw*kXMcqzIv4jEt{f+hcE63Rdy?d^L7)2W9Fv9k>3Y|{Y|HZ9Ueb~4R(&g{PiWm z{N?x;uh}6}KTJOw-1oxO;E`91f_-|83Z9ucJ9ynZt>B|eynkFZA&xIow zZG?ue(V+5Z88thv0hUNLR!O z@j!6xa-`?~>UJ2%Bb~=|mTiy$2(Fio?DxO2DMsvbq$biG=>q1*BY^cB3>kl3pR-#bJCgf&OH6U`R>eh zXP#Y@A$U6bg^m zcM#QAa>QM=jLi0&MkLKAWcG&dI1DZ(E`VnB`|1* z9~g}Z68?D*=u#*vOv>Iac*GS5D`X>t)R?b>%V0r7={t^E8yG|a6Sv8kwFONO7KSlkPu|*|6(A< zNeDx{5C_Bu!TbxjPXE8-FrNa>R{`_f*%txlZ|60GJNt>-{=2R|mJN~4es^B8^LjcY zF!eN9ZTFn)>=;H$H*}Ck(+^SAjbmtU%>&d>WgP8RJc2aiJ^#6=C1g*W3HqShlIgeo zh}-aeWJqN+G0px=bY__lrN4^sdD0{J=DYy1T{|EPpO0{H=wqn6e-Sz&2a|4&PQ*~_ zBpKe&L1rj-BPoxwNr~kO@>&=~HQEBH1^%uw%)E^bPgA19c5^!ZN_RTWGlq_>(WDMt zA8{|U>&RUMb8Ge+Nk!Ho1j$82D<2@$>(0?vKY@{#5rbmA0y_-Tn-t9V2;g) zBiRVPXPF;Ca7@iNA`_7r2+m*g$p{{2hVM=0IKTh9{$VWRoHaX%pq9bx64KeHTgYOh zvuzhrgy8G(zdl7$*8wl-v0^37ZhkyZ7_YdF$sSII!=%Jh0`r> z-qKi?n{?LIt8~KE3Dn_)A+;Q}j2bEJpc;nfs6yym@_zk2@^;5-(()*tyqiL4R}~qm zmFG$Obl*U2lq#s}!IzZm8An$%-=bUefEG({X>EieQ(SwKX?+f5hS@Pp@6!cl;3Ug> z-5bkHCcI##9!Htc=F{A>HW=~do=-kvWEgSn>yyJsI#P`kBB)n*f?9;yF^C>wjZ8sy zBT2{_-2(d&21dppjO+qcMt*r~hi0f=?(~u_!>J@6k z5nKyWI~mbLdf~O3FfPW}f;_{rEyjNs;}Lr--)AP?&TQ}|eKsnl8=Khin$5{jWJz`- z*{0VsSejo0OIWVPLLa_h-jj^j$St1CYI-v3^ShF1TjFn?Cmu67vl!YTeWJ}C`|){} zz38oZTj^i-9QvmcpDns%2kT`M#VkC$nO&h5bJ;$h1?tPQkgmVkisUOS^#Ege&bL@) zW(B)nQo(9pzhjSW-myncwd_f41#8q-WUWC{*z4NI+;b)7dZh#RTrnNN`idb4>Oi7U z|ABrBo-3TNT!AqRd5#p|{ze$ja?e#hSjPOWY{fF}yUGlSMm8XKxo7lfjF{KxRTxo! z5{>y=g=4eo03K6@@gT;ph#P`_4=Zt>6(tx^W3r+c@kLf5fSkvEe8Sir*@W02c#W0V z*A<+-S)9+>tW((AiN5UD9&fI4XCODy?8EzQTg>~;AIuFs&3U&IuIvl@!(KLxXZ3BA z-N!W!*Js+XGwN4a;q8O$z^r7ptMoV9S`(x%z^5AtRF!=PC4pv1|!oD93S=0cFdE;1uU;d zeGZOCk0r=2Z1Y57k?Y)36Z5R;g`jRnV-H5Wmc|yO9k2Tw>xLM|B6wVPoaeYc)3duH zMv7pYD!#7N@Y<>mF@8jJu#DrYJ{8NB7~OGyoGWVM_?Ff_JSE`^U%m7lU*kEJZ~f`P zv++6T2XCqH1Gn$<>^wET`N3`;|6(m)EVqC!_;rxavm4E4x)*bBxPWV}efhZcfqVpx zt+nPJZY@8BCvIusiCq`-O^)w*=Eev7&{S()JX($)e>a|=+$Y1&e7EA4@BHPp_h<38 zH>dgES=U9mjF+OkWs}&&FI$v3*pvS`|5;QVBPZ(rs1nV3#B-1ID(gnMksM>M&| zW_RwfX%f;M3BmnZ0!acUV#dEGj{$d%=y)_g2fyZyI!#=D>4&n8% z4{5R37t~E{8HR0raX-BNHe3t2Wrk?-b(5$zy_|p1AIg7wWs9ndeu+KbUlsKhhl+Zu z-iTVW1X0EGIsfb6#@{Wp18w5`N|Yl0{#y%R&bREYED zO%dn!)ez^ny%48g*Aija4>9yjoVZ@KyO?SxLra}v!;eQ>Y%KPkkH*!)x5b z$O9o*pM!N%+^&aZPwt^rgXP=YLo*VOyNPioo)>ehuE;%=c*F{-DVxI&kT zOC7I>^X%`4Z1!Gpf`*DXVb)?X(EOq}$#$jamoi3l&8iYdkH{2<*v$|JDCCF(tn|f{ zJX zh-cbfizia9iG^$Xi3k05iiJ@*V!iotN$!L@cb}`m-IosM?u);1_XSN@Z{Y4>5!`*& z3hq9WW8H?k^T*tMkuP@-@59|A?&7|vM_aU(yT{jY_vPEUd(1y9pW^Oun%sS@KX*?` zLj4%()wZApZEG`X+^%5Rh`Vp{L!DU_g1WR6)Ua*3hsV6f{U37oXnO>8XK~o4#rPcm zrFf07Ros0xo@*v**k+q?_fYI7$Mek{gZ)dzKHTE&E3rS(0peGi*W#)BgT(ZoH^f~r zhr~jaRIxmwOgzA8t7omRS0e5T194QRo zZvWF za^jDhSHzDCu8N<{?ux(Dv!pJIXGjWhXC!&wrMTZX@spRY*wiM8%_F=eyOaARyQ)W$ z&;039VDdC+QsYW#f)bV7uFsN2$$yfD95IpxYb=t6>}iv%JwGEclGS`?$;^J8WVHB{ zq?X=I{5E@z`1ebZWID}HBK2Rmi;*jLc^AN4{q4AGR)6mLtAV@CTF%|>J>l+_YqHt-a8{b#~mueEd6m@w|T(3QK+isP<> zDR(tK#9jW$AZpy@y)1XBLeHa1CEVo*mQzvBwsj_=Dv9FJJuezCf&Q ztrweg1Hmh_UMrCtTUB$M^QlF7kl$vDAG>ecOsWU3V@S+=0(T(+}he`$c^ zP_tbc0du9n!*)ofYMUif}x}N~NUYd(tWcK?)r+M4GCw zTk_ACAx#KGjoP!%l3P@YG`80$Y3LUl$z-;+q>^x*ronEM8Yai0p#eJ1*H?{6Qt z_aT4Oz#r${ruaScxI6b6D$hMPFXtZ33%G|p&ihms?smP7yFSiCKd)1K{7*AJUIn#g zUd`Nj!(8sHdVxC~oX?$B6>}&1+1x4M4tHADz@5^jb7zlo?wt0IkBdZY5M7H}#gE)I zPno-GqTcuz=U)9*aG&03-1mVA_il+0Ka6`MUd%Wzmff@xt5wq_xpDI(txI>LKKCa} z1Em1TR{xANtYDKgLjA8aV&G-Tage^`r>HEk(LJTGk29qCrz50!bM8qYIn|PXP@v@R zGgQjem?IrN7AT!xSSej_87Q4RbWAFgZcEwcS4tZ{S4gY7-;@@90BNRvhs5gqrHMsl zlGFDFssH5!NulM9c-2~6%=nluE-W_{9ZEI$yEh~G&++C0QY~B#Ql10MZY-oMYHhaUSp!T=MlVbWX9YRb@ralc#k-IF!w+| zSq~o>?yj_(Qm@{#Wtw&$9OQ!vnO3J6^ifzFg#j9~XV$SL5;+o`mF(`4i zXnoF8?BSx#TYjnVv-j)xK@T~;9q&QbnI-U;{Y`u!x8O6+DRMMo;ZvRDc|a?AvyRo^ z-nIC>;`lzi*Z7Eje(K!K_YikekhtrI(cJY9YFuSdn|$dZ>R1i=_@z2HH*fH<*(Q9< znsI!TUsrBF`xR;cZ}Q~7o;i;jd+{;5UsxX(VZE7X=*+dHKdQ{p_))g<1X`LTGRQr!_ z32*1g_@IbYS1xl>#)cYL;rk0~9& z$8_t-N1yn|N2gOhdVLWeJ?jh~Ejy5p>N1$y&xqwCHYxI9r`5Ubkr#aEbOUaU_c?oi{JA08=9i(+~;E7 zRu|FH;;$$)tq`Mhvc-*(qqw*9qj>z{Yw^CVf%q+FlGL*vKlehPOWvzZB=T&8B+0** zT<;y1T*VXOn|Ti6o3*Zz@*77KV z9jn9b8^>`Me3pX$uR&bgvYST@f56v2`Na41JI9O874ggFFL>R~Lf*0dr`YvJtf)IF zRwLKF9urGi1Wu>5);nv6gP`~#mrmR#C>N+iTlTyimTt7i>q7LiuOK3MEluS z#90>q#Cdx)#Ly|BqVOw0bax#r4q+e~>^(1b4G!Y(UGDOl!;kp+WwyMauIHK!7F@IYL9Q`d2{mi>ya)d4j=AdY2V6a4D_6Uc$5p?jbCre?uKW(Y&oVb~ z<$Lm6d6_Hk7Qc}zrK<6+7fwR23^%U0_{fp~)t>Arb z_UD5}?BJu`hjJhMTMliX$QPtuRkP6 z99PxUiRXTJ$r77nl-l>?CDi!R`<3Hy_@1#-TfWx=?8%|YE-d?bJJOaQygpP zVZa*3>9B?rj91pOhSyyYHP-MsfHfLNu!g^Stl>1nHYL_@cO7epoW&Y=Dr=ZBjx}t( zgXf4~Pto7%sc$K(Hyz1pi}tfxx$Epj&TRI6mL~h2KY@2ym%>%ftmj(MyLhkfZ@ER6 zP;RqsKOfTzzxR4y;sGPeI8pHCvla#M`N8pg;iq=K@Z%~zzYpGc+4SN*CPUGWuY>D^ z_vQ|#6}W@&lSl6B!{htx=SeCXd2+A)Jkfd!k4012B`Ih4OzjpvxwkTR8JEt7Iifc7 z(nW4qZozv*;yme+#Qw+~V{L!)S!0(ytfpHDyMLgFT_~?*$7O%9lBuq&$l@O>j2OZS zXN_Qm=Z3JNm=ac0VZ@3<`mmzk0jy{rwwc^#h2~`}ztVvnJ=UEadH0FsGHZ5t?tONs zmlr$u=odST`jfn|)+`@yI`ZS^viy>MtYCr%E1Wcl715=vc+_52+_aySj5xqbLTgyb z>tU?q24^J;(UT3m!%A{?vl5daR=m576lkh!mE7y%^wm~ zrZEOFHimQ?+RCBH33FSRFZozEq2ZLq{}IGCxqGl} zn^W1YUt8JUO4K0kmsnw=8Y}PcVdskd*yZYb?Dl#&_Hc6$d$?{1dr&c$-6~CF7k>X> zMQ?Vqy}Fm#svo^rOn^Fzzdnj3$jxI17FM&;NyhA)Mg+U+af#iiUchcnZedqXHn5BR zKC@HHrm>QgV=Q-s49gxljb&Wl%TjNKpm$gei@UXzEzj3u^Bu$3EEhL6{*8<&28IXC`b&YH?>?7Vx- z(aVR8&V0j0t*vIGjEb2B=JDwo^EUd)e6x?$FvS5~n8-KMbqcg$Iz zfx!A4ILq83`>-k9Em+9xE-YLtpDoEXW6Sq#U{NKyZ1I=TY=LDOn{`Wt@e#&sN<04l z;?^@anP}!X?++Vs(uNJSGiL*i$1(HKBbeFL7tAQ{Ez{Vwn5nLx%9L*vFy(bcOhwm# zsobB-RNEq$+M_Q_{jxDrKRA%7-w0&t^S&^(JGYqXi&mx@xSpv*^kT~YZZnl`c-$Z@ zrt*rh9)=&7c9}fWn^DhnwKp>z&8JLfS3J|B?#y6j3^N)O#(L%HvfiiuG2`(gnTc%; zGl|@aJY%NgH#5^N*mma!Gw}>$#*a2I<1-If?`-@{>dZuDG(3ap&zi|}zWrjlT7#LM z@l>Y!uNZZFy_l|#4>Rbpi}mt6$V^_fGqWiCU8dzT8}w-j8(Q^(4evjbjha=@Mz5aB zMjS*Pqpm6IKfD*~J?tpcn9#r!o|Mw(w*~s_=S_M`a}>Rmx1WAIYsh4m07=M(>3Eq18J+(rSY+TD1&lRazsh-Wx=#|M=5;Yyhou*h*hnucWOJlj+NnA@uq7 zZ2ElNK-z4+guZrBrEk7v(RVYy(ssGNw7q^A{SdN-ez*`sKOC!}pUmXx$BrrVqp36f z5MV>!7n{=eYjkN_#a`NKt4CW3U1{@j#C<`sfJS zSn!)R-C0dv{~bc#4Yi}~Y#;sb>lf|V+C;w{dqF=JR?_xG*|d3=1+A?D^Dz-O>H%!H4H){)w-&eA_j8X3I)iaWI^o`?!*x z4eLuQG|lL#Kk4*DMgT3lwT6}$ETDyISu}5+4?Pr~PSMVQX4fmxtm0dAk8UH~!gtb* zs6E{9!a++_vj~3cB z&|>Qr-8X0Lr16StLz*#ADuo`NI zoV!rhKhD&D+bi+LA^|H{WzE0Dq|FQxa zs3=E+$T%uYO{JvYK*~(c;TK9uMT?(Q>T-lmlP#swi8h^a{tpfPJf6O=p zD``sp8M;yV2~9k7jIQ1|mqx4l($#iuH1^1H8gEli6CTW=Yf3)T#9qxb$u{R%T81Xo%hII&cWGi;DP2>uohEjPrU`@fX>83fy4r6Wjnc57ixx%DMFVEgh)^dw zPwGlT`>&<6)|O6ouA!4+s%YSBKMHy4Y1k$Yy2O1OU6C}Nu7DSGiOF;tx;vUqvnioI z|JteJqii~+tby9E8cc_7nM?JrMN$1S)C$@EAnl14seJYYsyxV?s;~V(dvx)k8hyg3 z?!|JdZ!?b?PC82sAEL%>eKqZ+QcI1tKBBz}pHibr3us@YsbH6~E1 zG2epfs_dicy&b7C>H$^0R#NrwG^#P<7uA|Di|QVnO$`S+nU`-s z`)S>#W=2}n{P1sTG4DDZ@Ou>FB#$57wbs2ALlPRDB6 zQ6~onI&SJE>as0}x(~Of9%-i3b6^_vI$lJ*u8Pzv@+b8^eVTgDwxwQ5c%Itp)P3U{ z>UJa^HGJjNaia@$DBVi!#%-m8Y7bM(>Os`(?h)G0NT4QWoc20#mFkvtr9GpLQmrUu zsw?_a{miq}csQYb=d@Atj+4}4Qw=rM_MyEG^`YHeoT$=*HrnmYKdQKGF_rOhA@$nx zN!{6{I3L^Igz9-e<2y)Zm9J!YEnOyNaNGfR;Qdu;VROg40%2kKS1-)zJ(n5T` z^3yHk_K>UOUif43X#Y1--`Jl#=PSs|oEGwCNIQ9_`j)i6drUt1xscBt>f~EuGx;5} zoys0T551#|DzC_(dir+MtjdX6bV2Rj_zK!n`5*0$n!z3;?5RfHWZH90KGi<@f$E%| zLUpYkQ$5E)R4?ox{#mkt>W{rb^-gc1x(T?QoS<4)LTS&PfwV_%GgURPqDo!-sjTfN z^3`xLX^Ff{UOazEUVm>U4NmIhh3p5?m}o(sOgu#%Wj-PIx@(a;>bm59%og(S%tTWE zw~f5am_#17o+ZzeMv{BK{mG@X*T~76!Q|x8f8?0ECD~K9on-ZXPNwhqN~RBwAhUJL z$sErlvUH0FS$(IPtX?^XM7ixJaczDiwji4%I$M$C>Dgp`?On2=;3evfO36mgeI#X$ zAzAC+L6WBQBZ=nnWX?3DVzVtac z@nsS@YqWrrrQJjyzkQ@+fIcZIvLg8#<49g(2{}?7PV%gGk-YRPq);}59B?ishtF7( zBPqj3PM#LososTb>ybk?RMn6rJ%*FT#iqn^mN~JsZXxD%wWQy_HZow|FEUWkmspH@ zL@b`Ak%3>fk-@PuiOmKxGCb%T8I`$xhiopB+-ZNw(Ic}-LGPZV;QSs^WG9fKvbm(_K`bdz^diOEJ4lh*PEvs0 zefipUB=3GGIpq6{?A!2#?4C25Y;$fPX=Mk{6)0mz(XB@~z|CwaNP9u`y@s=d- zJxr3K-ASTpI7xUnh{V5%B5~q~Akg)=*BYO#hN0%A<+h!1-jvr4PiRV!A(J@EydkdIgNT>+ z7ZRX5fPnrqGUIpySv|p&q&#aT>)XzeHPc^^n1F?3rP+ECU3!qj+9;9uNtZ~XY$Zt= zS3#2Mg2~$67s%QqKeBeyZnAE6DOnfgOV;+fNRo$4CW$Y9kTub}NZjnlWaYU2WYNSG zB=p~RGUMwWLd>g(=vzyIQExhV#Rn2(T}%S@{3a7UClbH6?}$&5J@M@DA|C#yiM!)$ z;`*SFjK5?{oTg?HhaJAe?&mCGwTh8G;f=)jN&zwSNF}Nt~%8x{^1yR3p5V|TcI>Mz_nt_%<6*TPft-tcPHXn23!1Af@% z5}B{xhESRNO`ydQa<52+G+#XkY*1XFMWXxXO=?B?yWyn1kxsSgH6)|Ve`Nk*qq$}TZ|^cX8&Z^d|)G_?Jj^#3W<=GxE0dMY+>`b z1#s}yR@j*_1u{Qhfc>U-;7Ir|D1Mp=CtGg9g@|Cd?rNp~_lAbbY49R; zAH0fcfw!$o;8Vq4`2BSbkc@#-x ztBc{E>ks%1VOs7_m|nC1 zLXsaq$o$nX!_*x@;vPeY8HbQ_{t!~#7iP|PhSgy;u&{LwEDd{){x)YJY2`cE=(PvZ z(er6nRR`Mr3UH`x6dcVhhhmG9Q1(p=PW0OWr}saCbEuuWTzeL()_KEYZxI?}kHOE% z?xbt(dZOHA0#UqlgUCNJAc}ouNVk!<@wKW*df2v+p3#J8`-Kpl9q)=AFa#aefxfB&3y*1S9!zpu+7jo zZW}zkI0@=4Ucr-{C*iT(I(U?G6SZ+(aL;ESRIk1UH;1Rem9{9j_=v;#YJ4wndz#JUfH2tcraxqc zi;z`r0y!1wa5S(xlufx0C+3`l+aJ5avsa$*@?$$REkUjFZ#Q_Y69{cB0q|u>3j9uJ zBeDz3NtgNVM7}hGC}ignh4<5lLTxrtSQkL#y^DzK?|Ja|Eq*Rdxd9(-&cVw&ec{O& zE4Y37F;uR)3upbb;k57r$_x{r^!`sMZqb6`x~ota%b}q6Z^$dEgxul7;6T?Qu)l8* zWIw+JyF2E>u758fLv|8u*-;K@SKdI%kO{D+t0}Ckx&n)o%>e8)0HzAUlZ+q2lQVyX zhARm|qk+B9z+MQA`yU8RLtTYe^Q(l{8?%MChB`v~yAeW%Q?Bs+S*q~&<57?c{sIb( z!$GNP0;m*+g6ijVP&?`g>MLBJ`zkHa@RI?(g5F?|XAJ!k%VEf%uP}O36?m>qg(-a> z!8DU*n2SDnOLQ7x6>1_^UrdL%(MutIoG-*T&VV%@e<4}1H>`iJ4qN01Y%~7`xm^#! z=`ksA>2M=dUJHe*dRlNRR}mgenhEu*zeBU(KWHs*hxa|u=d>saJ_n}5=c+{bJZlJi z3V81$b)F3=bY2himCK@iS}yAt6E@Vk2~6h4~(c7`Pth%-jjm`yl{HeIX!r6nF<-hVl7k z;5f7&3}12q2CeA=M%Prp=*n%uC-{@#Ge;C=KC%^7g!~i|&6|aF*8W239TQ5pI2dDb%R82=yxV!ZW^1Xeyd5yh8ov8ygMb zokxby5my2-bCW@}cTdp!F&@m`{RW#ir(x`j2jKO5Gz7L#pt2e;Z4HANS=Jy${h|a ztAvcjC9u9M8~`b{5V|j zPei|#=)1^MNi?AG4wO2MV|#+ZwM)Jzv0DSRidqanHab%Axc-bLgV`fkiYpmtg-Tj z3D5|ZGM1ox{WCRGUue@MjyA_1}$bhWN=ip!SY+~+NO9s4LL3Gv_z!#Z6P%(2a zq&*u0xX=Vf1WpAVA2aAupC`0Wm?%8{9xGft^+L!zHbpov;D*pmd43r1Wexu>1raOvHZpPg0$yP&+Y|#o8qdNj*GKT+R|K4zHxN$mTL!c6ULd@D z4s7n72nUv4f@AY0!nGIMp{2Z*baMzK{obD>zNVYWn(nhmzMK*gUlkpd(U!MRtLfOMW?8iMDpTZL>!L?j8BiQt_7Z$AgT zUK^G>&x`Z9_7_GijIS}`KD9VLbvUnU|6(*l1Y{`IpOPo4ZB+Kt4{CbB`MJ@e}-&By2LrKc^W%VM%<;I>%mByU8AoF7e%KklNM7ISG=-2>!DMJZ{% z=s<4Z7~NFZK~A>Dlk-uUihi^Nb>*PW=roN%2 z@=xi*lP2_i_rLV(xfitM)lOP72A{V$H;z8&D4{o-vgw6hdfeAC84FqKomywsl#W9 z`&yzW+W_=X8z6_}cStyv(VxvS9&ti&4X))V#2T4^pf{RD9r6Y_hV{;V-9pgg&a(3w z<_P-LSyDun-t4i4wpM>+3bTutu7@@oHbKOP*$!YUzP@Iw6MC`mZg<#3hxu$o?0RN? zBZ~DhKFYNFE@mowCa^A!Z)wNd!L;eF61^Y1fL45eNzXP7ruD%G=u^Ws`nxifDbH$S z+83v@KD}?T!8$E$5D#_a;TU^zInH=tM{|=u7sW9(^ygbJ$B&f0=Ca( z4?ED$nH{K?W&3S8_l;SHpf5%=uI-I}jr2h9|B6}z-{^%%5#oaTXdv5>K%@j2!+lp* zVqAvN7#WRV4pyUI-RdO>jz?@?jCmO6V|2!dcx;;i5>uAh<40;FRXRL1w_AMp{+e+C%13OmS=*!9vXR|A-m$8-? zHoR-KI@j?|;CcgUd5@p=T;@w2dujTdJ&Zlh?wcjDs;WR%Iop|?7&o0Ao!E`-y)cty z3}|5~8Wt?2{Tn+Sc$A%b--X>dahbhnX6*CEL0mTXEmtb4;A%3KT(gdG!!So~l^w!e zx0!Jv$byF)n82q`)#ar5Cl7cU!~KdU^C`Fed5F$s9;WKgeedCXxx1YE-uaE7|6g?} zl89h#s&8Z4F78{k4fk-J;@ay}tYd!e<9OVAjxh+yN7`_kBk~o&bJSq2 z9=Ibn5FEn?&A307Yw(=+aGdU|WBh@bAUIxkajxIPIe$kP%d!|PFiyj`4*QgeRcvJ<;d3 zX9||raz9OT?x&B(X@0|Vd_+1B^byr7=6<^0aoZ^L0qyiC&EbBA4C`^oeXOH*uiiD> z_b}Egv5a1$I_TT0Rm%OeeXuNx*Z4nNy>~p9U;O{yAQdT+M2PH}glw|+Ca*J|=W0_) zJ4!SaMNvsZO4_NkNW;6mhe|`5Dm0XaX#JjjKA+z|-#_lR=Q-Cn*X3O2^}4R><@q=d zY*Xbvwrzvw@Da=CdD^!(meEtU_i8NT@m0{vw4WSqpMdoZLa}xxv}Y}Y$G308tN!yu zC+DA{=XV{Un$sfGQksRzwHVQ}tpa|>xxu^C3d{$*3h!4hg~k(|;e~Y?)OPO#S5++F zUrK}Wz=4V7~fT_rMoGx;IV*d@_4WW*zNHT;vU__6B z&|&={)CT*^))PYQv2Uzq;&xsLZtw5}LY?N}@_GmzaTWJVfl#*x5b7C)u^B?Wv7HeD zLVXG#)bAIB`eUxX|0}HHHSv3n>+yI#*q@%*hdybz&o&74=z|ga(IpStLoK8|;4!ex zq1dLK8=ePVFWVbf$L*|fx&0_SNAyy5{0^b6=mG1bAhKK2#d!Vo!hOGq@ZKCKXmgyH z^s+_F`s^uEk9UaK<}PB&s6|59z7>($S4G6{0uhI~%5ksyikR@(B6vQC5l#leZrem* zbuvv@dpV2DUz%dsWb_DAelE6-4-h+Abj7Y0RP21aQEX2*B}z2cid}s@#G!5~qOxzg zIQd;soJ7yMN^(XVb{`~mKb|g%_hpG)^OlO5`px1eUk{D zqW?jtNeqMiSchteh#%xHgM36B|X9Q-?ULN5$^4`C`|0d2v8(qc}Wyo+y8kEXr2@6}!&$7De}V ziGp3PMS;J$_~2nL-e>ogx^{Gy6yNTXl>MlrBvwd0bkZfce_mj-^rbF)#!Ct@`BIO; zX_BJ#8L6k*3aQ)O=Tc|mQ1O{x6VFsEMU!Evq}JgmdD@MD5Y&-|RO3Cex)MUFuwFhL zLJr|~=0PP~)&U`P7Wf^B_rYK2b*#_}Kf8EMjE-X8dt)DO#J?BEV89>j-~C85gpOK? zeTyE*W4l7=%z+S^+5djP-NOYy$B8t?DR(;#F+JeK=G$d1kU-F*f^nhr{~AI6D} zGhf8TZa>BC1DC`H`zG zJyQ4PMoA%KsnoT!O#G<*E1GqEMDtS($+qH-G;DBRDJbHp6x9(UMIHGhg@(P7eD51b zE;A2Fwtu2-%I_ry4lsmg2a78V_N^ydjJ)gs@`Nl~j*{um@)$tR)%3 zzRicQ-wqJg_7T0m(jcrh2EtDMg0P)#5VmwBgiUXOu*3uii;jgbbNuf3F&{!tW8cok z>t&Dk)i+xpq|6SVFYwy>;Cs;z0|RqIc)ke)Co4g4coGEr z>zC%wM897$!5#lGFY!4QnVl^aXy9i0sxkJ(qLJv8$ z{gTPfg_7~4F_Pi*<&yryv62ydkgPsGm4#CmnKRf z8>}VI4IYw}l7^(xUL#t^c!&@AyQJRJE=WfD3nBc(Nf_ymKNzd10GZPSBsC9+)+Uf~ zXNZ?NV5FlS#CgU+tVSZlB%Xrki#;Jal0#JMSBNU=15r#9q7)ZGuH93BaQ<{l7a-~+*m`0TQACxmG?K=?Clh)gnp==^esopTVPrzS~# z2AGO^HDhsJ-#|R?>L>Mzl$Qqgijjui+ao!vjFsFk{**knn4_PUo#g%-$LQ}ODfVo= zH1_36DLJ!Inwd0Kno*oDCBD~{Vs4IunG09SG$3)gDLs} z`hwS(Ko~LcIe5-_0Uj^Tf`?=e9^+SmhoK^Ph^^r9Fcm!eYQYE}^aaFu1-!3s1>Y}t zeO4CWbL1O{N*V}slrkiKwueR8MNnMY4CfzwhZlWs3&$WLQp77!Qr0G3_+&_G`eD-0 z;HQ#T_DU(#exejL7Nn7zZbw)wr?e$-gjD?Ux3o#2M#|p* zQ(ED-Qu;uc^nPjLs2=X_qq?ErT1VSu=~Zombl&T>v^l{@npf3NioLBUIWJ3-2Fc{5 z?(&nw%Wn3fV(MCvN7jmQx4sHTqe(*ja|N`n)_@By;$d%{5^Q>T3386w!eSrP!01@R z6fzFR5A6nGOE{2Wx)3+x4n%i;3=uU0A>17Ab?q-8G!Vb%+cF@e_TTd}J_A>0LdazN zon>Vn1b#)G`|mvTvm>axe1}@A{owIb2iz@pg6q~};F5O-oL6iBr}ya3HEt+4%_{&W z`;*|5Rs+uchl2Cy7;veo2G{L#!2LACzOM(L!=?~;!x29}r-8f~0~6B|VZnyqkhe-7 ziob9;fbYMrwk#HXCr%PByt6>p8nGees`xJ>Q#5N0k$Pr$N`stUOZE?LOF@4gN#iFp zOPL8wD!DO6s@jwyUEAy`-8-5u-EHhFRaK};Rk}G+S;%2&|Cn3SrGUTE>Ce}tJ;_t0 z95PUfIp!*9+`cP5Yimq`lpaI_% zFSvh$vT=S;h|e4=Eu3Ld)_9n+_z+B{dtprW2b>5f7vi+CA>xS}gz7AWz?bN6yJl=3^CV(As&Ch`m+ZNaW;n`pU;AgaSRL{wF+$A3&GAq z9vn*Tz*%`FxSvN2^7_FLTKE=ZQ`2E0&hwM8BNeg}zCwZTO*kAf0BSXr;g6fDP@j5P z3~A05p+A$*OZY#Lg}%c@smkK$*!kj?9eR$g-6Sb{XiJtuE2T*MPM=Y9Tv}Y?CS^ux zNHeCXNYhs+OTE0prC!swNrq-hl0lWXq;UwJRW{!j51bE+{Yz3s4(i^f9&i&8N1Da( zgjQi-hN*9KRgIkga2O4f&Jh2z$S$T$T?9C8R*?JIq?C2z7NDq$7eEv z^I`0qfm&4!aKGXXE>_pUamsOUu%KW!dld|`Fb7*l9~fG|V5s?4uz55J{rs?>S`=W2 zdrz=x?GKjIjliO>KA62w0n>3YV7xX141c@=gSiknp+;=pRdeXxD12~Nht@VjX$ zgiUq>HvJDI{nr3XHq3zn<&&@{4EGAqW5!X^W;@2O0jv=}cg6z>q1^+$=VR?T9orj;OBI|TWgD>C!?h^*bwV(ED< z=1!tQYV9O^cB=^U)k5^^y&e6jYoW=tC)_E$3#aZj!oE+sP-K+@t9x~aB?JG18Iw&w zY>Y!6Nhk2RFc0kNc7er1)GDWlmP>9&K(WZ zv}&0D2mQCUL4U1AP+zzc`kl`LwPrU^QyvVePuf7G`Ua>B_XQQFFz9n`KlHw>4ayA) zpsZQ~y;6rmFNIK0D((qNQCmQ%e;z2Qp9aO27*LX11WKmgLCF}`kLv_sST-Oz5ZTXZQg5DFHRqWgRFa$H#`ItQ$WQ(H9P z)YY+Y(PBSboaG09b{C0m>UTxAdR-ysTL3=~-h;+1jc^w~h_B_qF$o$n>lYX$9mj%-jrCtn?@^PTf&>dGSEv730Kc+TIZzT+)W5+Ne5ZmQ5g3$AEvF>hV+lIu-GmW zmhRjSnQp^iNzosemtqYQl+g!qwj-F;&V@+n1w?gT2g|E2LB8}13LGv%LF*D&t9uo4 zdv1nIG8Iy9bilZhLl8CiB#f{w2U~~hVAQ(}27KHNz3(|dx4k|2Z)=?E$!q|BiGEwp z7wzRY@|E~m{}g`8G>4xkO5v6J_VCKtzjyz(fz$;2M#Cra`6%i9xqmG2E+WjLLmxb&P?^%;!6%Pr<765M#@>n2_~ zJ)T!Cp2RD%^Z0QyYkq8g7k=b}6EFXCke6>vPtH zSX+L_X&e8Nrpv!Pd;r=df5B|{O|WT51Uvh`VAt;_YR_Z9;`wtJyrTm&SL;9@cNgdu zw4Zm}CA?YjIInZ=%5Q32=VvGP;>Xcnsq9i$zB8+Z@0i!f3ttrSRm6s8*WcmGTh{XB zA(#2`37z=zeMLNLi9XMIp~SQ8ym+>L0?%sB;aMw9`SJ^neA&T4JhS8qUrHnR5{D~% z@u^I{=zcf8XuUCC;#AKwKdJELwLf@PtR>GnH=1Yf9?4fUX!0CKIi4H)A75o#$5$Qe z##hTn@YNgV@zq;i^VO5W`0AQtSoY(qeOI9$nKNGn{rIY^WjuHGex75~jjx#ar@RhAmJTK`sU$e`Q7fyfAx6H8PrE6C4eVyg`;dC!vHMWYMGtJ}Ivu^Rb z@ymJL)o}j$nGt_;U@3o1l6bxETV6BZ3qNz;hL%{b^Hr^SeATb#{Fotn zt+g5QJ1TMf(Pl0FJ%!7}4^MJGWx&Pk_JRoWo5BR>52lcGu z!Ad`Q@bwcs_*FO$uGHf}Uz&N4S|ksMtmFPFv$?O60r&nrl6#NR4xbD6AG$OrOx+lhRn%2FQVevL=&GvSe*5|8y<%;Pl^xy)}A zXO~9u(JeE0;u|ME?cjEvl32wTI6me}+CzDE23}+Tb$rdw1it>|N?xG$mgh&C^6XVR z`NFfWd6L>)E^GVtKb~+yJwy1Ag54pVZZMw^V#H^Uo6Q#_>G36VI`gF+Ry@QAZ@`VamU3hC$27imi5o9><;Ia$arr846spLLhTP+Z zii`MQ-HBX(qc+z)w}orR+jH&pMqH=ah3ovf$+cf~<2rK&a=q!U+)%EGo2vV9D<@Ar zw37jM*szwn7!-3)t2x}S|27`bX)*VTPU*spG`+adXvPQoJ?FYVMscl!#k{|( z9#{3-#g$K7<2~!Aa|L$=-nI8e_WP4yKL*CK?@K$g4{hJslM{jLUf~E z{YJBUMf+IovpDw9LykR4_`x21=wOev?Ac>&4fbfIK6|)$2YYZXiPb(xVYS=6*n`n# z>_Ox!_DJg~d*N8Z-o^aKT8bvK_l_N`Y4mH>^iq?(-=D==-i=_b)ynLfa}E3cDvPyU z9?06mN3iyNM_K!pIqawM2G)UIRqY*HS-Vjr`!Qdi{Rnu^zNao`tqptGXJX1em~Lc^ z(R10`rxmQx$AP__YRX<$tY)vxjcaj^& zJHPj0e;Z3!$JS@;)6Ey`&3AY9^uK=W)-_93tU?`B00=CUml?wgUCCjk4RLH&DQ;K!m+jkhknNvg$o4G9Tu~AkME4`S;ycTYPoK|{U1NHapt4h_)crt z_${7nf;MW>$|G4qomPE~EOFwpF%d#J`<*27y{&WV*x);f^KCEY1r>C;)LJgL^Y$nUPv6p4p^kd7X zw6W#Ixh(T!He13P*`jL;S;pMCEOnwYOC9IIQYuy0jQqYVsot24v8rKY*Z>xf9&)nb zeoT6JlO^Ybv-#RKY+5m~l==YadtVex2>-|}isojcT>g!f9jqYts*Kso&RM)`tKfPvy(W}j%SdAG* z4rB%y&za$5V`eaBHq#GxXS%OnvVq4hGEK{mOk>SErm<-b(}~h&YX3Db6`Opfs-eZy zvZt{A2@jd3;|->rQN{+Da_2Q$*Y&y06EGLtLUnd#CV%&ck=v(QmyRvu2w zX4Y#q?4Bocw98@s5Y6IdKV`D(gIH)u4D*R7U?ZA+nfF>n=GS>83y^8Ep!W_e#PcHy zc^1yXMryDy$YEg$Ml9U9gN48Z6*^x|ka zdfmpKUSHLRUORQ2-aL~eIKeZvg;$wbiBgS*iOEt0nB?4<2(>*z0sR@TY86YJ`9n{_*MiS@irSby}IGa!eU z(XwJT&~X7%8#|Dxs*h)?zuq#n@<67(3CGF7hit&%u}o9@6VuXJ!?awMGA)~tOsj=5 zt&v}uX5W!aqkb0aZ|}tV{b*vUU*0q2=tr!lnGfq4>`psohtLn^!SrqF8v1^J27S5H zn7#>cp|4(g)B0Hnw60(qtsQJi?+whQ56v#qx>JSprPo9HuFE1?cg~nLWJJ^2GI@IO zjX6De{t7*r)V$=#p#ZbV<`}x-hnw zE;BZvOTVPi>`!4d#~ZavSNGEVBvrb0+h4k-k0D(h6-jdyR?!t7HEH(6`7}GYA6;Sk zm#z(dL07IjO|$R2(42nH>FU>a={h52x?ye_E&8HOOQP!NPFHuj2WRuzKYj*1usxX` zI%z=C>wE}rgpSxxsP^rHKAY@++Vjim=mYw3aF)+RdSk3=okS!~My5>|< zuT>e;-?xYcU`~~9>@4c3*iJpG*HE{hYt*f$8Fh=Xq3+Kn)6lDDsm~l$>h;`}`d!*c zLkD)HF(Gl3&KX3<40u8lPwk>p$6lbb?p4#d(+ANEg*v)W?iXFOM2jx*noBdY^l4VP z3C-2`OxL7T(89lG=$;KbX=Q46dZIO#9!y+LcdhrOJHVChJfKSV=-#3G_)K~reJ?#& zt3eNqs-fk_is<119rW-ZD|*BxfF9nFOUt_~r3Y6}q-D=O(EW>@=&p~!bi2WKTGVlt z7M$`!kHkMTF9rSAHkQ&=GXrUE_6eGE>jhmgcMVC#UB z9VUOr>yqDc<)lNgnfx|JP1=_)v{U93+U0mIm7jT!cJFFUd#Vbm6uW~erOl&CJ=W45 z*G;Ix&m^jF_y$$b3Zx3%JJIg+5AB`iM|;Z|pf0NxJ+ktt+R+xOIj4*c8jZRmg^r$agRJ4K4FWNQEi``bY#O5(MWc?#(};1$X_##Z4PLE7123$i{y$bxKf_|`y?;FQIG{$Io=&HB zzV6igogvkKidsCK^;9dngetv1PJ1c7Al2bBNp;RFa;9G_IhFFARPB!=l}itjs#Egh zzx`v$Y1u4t*4~Pow=^LaXJ02*ZuKWu8;_7{Q!kL~L08Gu*dgSy{b_QkCY4;=@`GGR zLa(}c3(3_fN6Ay!SyHnnkKDhYL+VfDkT*vP$*1l~q&;^Q?Y#UuYCY!A9V~egpUy1WKc$0e2F<5BGmlV%gg&SZGod!+)zr7)CXI`JPvf^8q~UIVXka%x z8nDuq2Jcd!;r@9vTH`t$IU8q%5q;)d>N#C$~sDZMN?VqA{zJE zfX3)aXuX~)RkJD$fuSnuc$@cd}`v|OpVZ2 z((uGzYH(GB>QDMZ2TkQvC-w!^a{fg%#!sRBKJ}&jI-Q}tJA7%6Ee^Dkh$COu>?Kd0 zT_W|S!DMx!Hp%O9h^+q7pX6V5Bx}1bCHWm0Wc919BrkUt$-nPP@;`hhYbx=-Ir~jW zfrc+xKXegU|JIlkE(;{<&xevi^OdAPGk_GFEFuNIy-2}~v!qaI3n|r)GtiPY#!5Y_)}PX{l$MvdkeQ?qVAspaDJ)TYZ2 zI<#UfwQYCBSspd0-705lcW?}~?}cU5r`bBA)-UrbwN^``7M^#gaY_o+dx&H3zdYJc z&4>2&s-h}48fmZF8B}>}ELFU8jw(i$(;lV!se(x`?bdZRmAmLoyDHzNogG`q->F~7 z&yZ>4hkXqBTp%MKA6Sz{c}w!lqK({N_#e44c^x?`bt4C_z9EOy{t)nAL~!z2!agk_ z&{RpJdPO3krfJld?__kqSu(~}my9z_BNO6)Bqnzzi5JF^$;#(R(kMqVW!`BrW!YVl zoTx{pJf>vI;sGSttezyh7n7+SR%Gd;EHZ!W7_!h-fn?tQLUN+2$y(V3vMKjCDH*Cv zcHa@GLrNt_f?`Ro)U8A-g|N`JdIo$TTgC``9bcV>qnk8y(0~0Yw>SeOnU~E zQ>A!8d$?3ng&ALH_gmYkV%uKYJKdP7-Yus6{xs75hn`W57xHw#TT7~GlTJ0w4pU9F zGCII`8da|uNYze!qAD*|Q01@BXpeb5R4)1m`E@9ce9^NbA0oGs<^wk5wb}&oaxW*( zzwaf_hJPVX<`J#MoPCc^pwc@a1*leSOO^u zT#S0J-=rj|hU~bYME2IUk;5>QRCUiIr;Q!S-I40#bt(48)L_y$D3!du9!cK)T0>eN zZzmm*b7-f{(X{K~N-AH-X}1d*RAIwts&G%0D(ppkE2#WeT%TJ*JAIu`e%gN|UtM%a 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

(`HbX%0A*_&qupFciV5KdwcTqSIb=j6UG7wKh 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 Knfd;IKK}<|$k{vq literal 0 HcmV?d00001 diff --git a/samples/gridspacedesc.yml b/samples/gridspacedesc.yml new file mode 100644 index 0000000..0c82f2a --- /dev/null +++ b/samples/gridspacedesc.yml @@ -0,0 +1,196 @@ +identifier: # grid_ggd[#].Identifier properties + name: Sven + index: 1 + description: This is a grid +space: + 1: # space_number + identifier: # grid_ggd[it].space[#].identifier properties + name: linear + index: 1 + description: Linear + geometry_type: # grid_dd[#].space[#].geometry_type properties + name: "standard" + index: 0 # 0: standard, 1:Fourier, >1: Fourier with periodicity + description: "trying to hold a b2/solps mesh here" # Verbose descripition of space + coordinates_type: [4, 3] # r, z +grid_subset: + 1: + dimension: 0 + identifier: + name: nodes + index: 1 + description: All nodes (0D) belonging to the associated spaces, implicit declaration (no need to replicate the grid elements in the grid_subset structure). + 2: + dimension: 1 + identifier: + name: faces + index: 2 + description: All faces (1D) belonging to the associated spaces, implicit declaration (no need to replicate the grid elements in the grid_subset structure) + 3: + dimension: 1 + identifier: + name: x_aligned_faces + index: 3 + description: All x-aligned (polidally aligned) faces + 4: + dimension: 1 + identifier: + name: y_aligned_faces + index: 4 + description: All y-aligned (radially aligned) faces + 5: + dimension: 2 + identifier: + name: cells + index: 5 + description: All cells (2D) belonging to the associated spaces, implicit declaration (no need to replicate the grid elements in the grid_subset structure) + 6: + dimension: 0 + identifier: + name: x_points + index: 6 + description: Nodes defining magnetic X-points (poloidal field nulls) + 7: + dimension: 1 + identifier: + name: core_cut + index: 7 + description: Y-aligned faces (edges) inside the separatrix connecting to the active X-point + 8: + dimension: 1 + identifier: + name: PFR_cut + index: 8 + description: Y-aligned faces (edges) inside the private flux region connecting to the active X-point + 9: + dimension: 1 + identifier: + name: outer_throat + index: 9 + description: Y-aligned faces in the outer SOL connecting to the active X-point + 10: + dimension: 1 + identifier: + name: inner_throat + index: 10 + description: Y-aligned faces in the inner SOL connecting to the active X-point + 11: + dimension: 1 + identifier: + name: outer_midplane + index: 11 + description: Y-aligned faces connecting to the node closest to the outer midplane on the separatrix + 12: + dimension: 1 + identifier: + name: inner_midplane + index: 12 + description: Y-aligned faces connecting to the node closest to the inner midplane on the separatrix + 13: + dimension: 1 + identifier: + name: outer_target + index: 13 + description: Y-aligned faces defining the outer divertor target + 14: + dimension: 1 + identifier: + name: inner_target + index: 14 + description: Y-aligned faces defining the inner divertor target + 15: + dimension: 1 + identifier: + name: core_boundary + index: 15 + description: Innermost X-aligned faces + 16: + dimension: 1 + identifier: + name: separatrix + index: 16 + description: X-aligned faces defining the active separatrix + 17: + dimension: 1 + identifier: + name: main_chamber_wall + index: 17 + description: X-aligned faces defining the main chamber wall outside of the divertor regions + 18: + dimension: 1 + identifier: + name: outer_baffle + index: 18 + description: X-aligned faces defining the chamber wall of the outer active divertor region + 19: + dimension: 1 + identifier: + name: inner_baffle + index: 19 + description: X-aligned faces defining the chamber wall of the inner active divertor region + 20: + dimension: 1 + identifier: + name: outer_PFR_wall + index: 20 + description: X-aligned faces defining the private flux region wall of the outer active divertor region + 21: + dimension: 1 + identifier: + name: inner_PFR_wall + index: 21 + description: X-aligned faces defining the private flux region wall of the inner active divertor region + 22: + dimension: 2 + identifier: + name: core + index: 22 + description: Cells (2D) inside the active separatrix in the same lobe as the magnetic axis + 23: + dimension: 2 + identifier: + name: sol + index: 23 + description: Cells (2D) outside the active separatrix and outside the divertor regions + 24: + dimension: 2 + identifier: + name: outer_divertor + index: 24 + description: Cells (2D) defining the (primary, if there are 2 X-points) outer divertor region + 25: + dimension: 2 + identifier: + name: inner_divertor + index: 25 + description: Cells (2D) defining the (primary, if there are 2 X-points) inner divertor region + 26: + dimension: 1 + identifier: + name: core_sol + index: 26 + description: X-aligned faces defining the part of the active separatrix separating core and SOL + 27: + dimension: 0 + identifier: + name: outer_mid_plane_separatrix + index: 101 + description: Point on the active separatrix at the outer mid-plane + 28: + dimension: 0 + identifier: + name: inner_mid_plane_separatrix + index: 102 + description: Point on the active separatrix at the inner mid-plane + 29: + dimension: 0 + identifier: + name: outer_target_separatrix + index: 103 + description: Point on the active separatrix at the outer active divertor target plate + 30: + dimension: 0 + identifier: + name: inner_target_separatrix + index: 104 + description: Point on the active separatrix at the inner active divertor target plate diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index a799281..d178c0e 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -3,14 +3,17 @@ module GGDUtils import NearestNeighbors: KDTree, knn import StaticArrays: SVector import Statistics: mean +import OMAS +import SOLPS2IMAS: get_subset_space export interp export get_kdtree +export project_prop_on_subset! -function get_kdtree(objects_per_dimension) - grid_nodes = objects_per_dimension[1].object - grid_faces = objects_per_dimension[3].object +function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) + grid_nodes = space.objects_per_dimension[1].object + grid_faces = space.objects_per_dimension[3].object grid_faces = [cell for cell in grid_faces if length(cell.nodes) == 4] grid_centers = [SVector{2}(mean([grid_nodes[node].geometry for node in cell.nodes])) for cell in grid_faces] return KDTree(grid_centers; leafsize=10) @@ -18,9 +21,9 @@ end function interp(prop, kdtree::KDTree) - function get_interp_val(x, y) + function get_interp_val(x::Number, y::Number) nearest_indices, distances = knn(kdtree, Array([x, y]), 4) - v1, v2, v3, v4 = [prop[ii] for ii in nearest_indices] + v1, v2, v3, v4 = [prop.values[ii] for ii in nearest_indices] d1, d2, d3, d4 = distances return ((v1 * d2 * d3 * d4 + d1 * v2 * d3 * d4 + d1 * d2 * v3 * d4 + d1 * d2 * d3 * v4) @@ -28,12 +31,59 @@ function interp(prop, kdtree::KDTree) (d2 * d3 * d4 + d1 * d3 * d4 + d1 * d2 * d4 + d1 * d2 * d3)) end + function get_interp_val(x::Vector{Float64}, y::Vector{Float64}) + if length(x) != length(y) + error("Length of the two axes are not equal") + else + return [get_interp_val(x[ii], y[ii]) for ii in eachindex(x)] + end + end + function get_interp_val(xy::Vector{Tuple{Float64, Float64}}) + return [get_interp_val(xy[ii]...) for ii in eachindex(xy)] + end return get_interp_val end -function interp(prop, objects_per_dimension) - return interp(prop, get_kdtree(objects_per_dimension)) +function interp(prop, space::OMAS.edge_profiles__grid_ggd___space) + return interp(prop, get_kdtree(space)) +end + + +function project_prop_on_subset!(prop, from_subset, to_subset; + space::OMAS.edge_profiles__grid_ggd___space) + from_prop = nothing + for p in prop + if p.grid_subset_index == from_subset.identifier.index + from_prop = p + break + end + end + if isnothing(from_prop) + println("from_subset not represented in the property yet") + return false + end + + if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension + resize!(prop, length(prop) + 1) + to_prop = prop[end] + to_prop.grid_index = from_prop.grid_index + to_prop.grid_subset_index = to_subset.identifier.index + from_subset_element_inds = [ele.index for ele in from_subset.element] + filtered_values = [from_prop[ele.index] for ele in to_subset.element if ele.index ∈ from_subset_element_inds] + resize!(to_prop.values, length(filtered_values)) + to_prop.values = filtered_values + elseif from_subset.element[1].object[1].dimension > to_subset.element[1].object[1].dimension + resize!(prop, length(prop) + 1) + to_prop = prop[end] + to_prop.grid_index = from_prop.grid_index + to_prop.grid_subset_index = to_subset.identifier.index + resize!(to_prop.values, length(to_subset.element)) + prop_interp = interp(from_prop, space) + grid_nodes = space.objects_per_dimension[1].object + to_subset_space = get_subset_space(space, to_subset.element) + to_prop.values = prop_interp([Tuple(mean([grid_nodes[node].geometry for node in obj.nodes])) for obj in to_subset_space]) + end end end # module GGDUtils diff --git a/test/runtests.jl b/test/runtests.jl index 9ac64c0..0ab2a8e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,18 +1,19 @@ -import GGDUtils: interp, get_kdtree +import GGDUtils: interp, get_kdtree, project_prop_on_subset! import OMAS: h5i2imas import Statistics: mean +import SOLPS2IMAS: solps2imas, get_grid_subset_with_index using Test function test_interp() ids = h5i2imas("$(@__DIR__)/../samples/edge_profiles.h5") - electron_density = ids.edge_profiles.ggd[1].electrons.density[1].values - objects_per_dimension = ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension + electron_density = ids.edge_profiles.ggd[1].electrons.density[1] + space = ids.edge_profiles.grid_ggd[1].space[1] # path_to_data = ["edge_profiles", "ggd", 1, "electrons", "density", 1, "values"] # path_to_opd = ["edge_profiles", "grid_ggd", 1, "space", 1, "objects_per_dimension"] - get_electron_density = interp(electron_density, objects_per_dimension) + get_electron_density = interp(electron_density, space) chosen_index = 555 - nodes = ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[3].object[chosen_index].nodes - nodes_coords = [ids.edge_profiles.grid_ggd[1].space[1].objects_per_dimension[1].object[node].geometry for node in nodes] + nodes = space.objects_per_dimension[3].object[chosen_index].nodes + nodes_coords = [space.objects_per_dimension[1].object[node].geometry for node in nodes] cell_center = mean(nodes_coords) grid_val = ids.edge_profiles.ggd[1].electrons.density[1].values[chosen_index] searched_val = get_electron_density(cell_center...) @@ -22,9 +23,9 @@ function test_interp() @assert(grid_val == searched_val) # Use the same kdtree to interpolate other quantities - kdtree = get_kdtree(objects_per_dimension) - get_electron_temperature = interp(ids.edge_profiles.ggd[1].electrons.temperature[1].values, kdtree) - get_ion_density = interp(ids.edge_profiles.ggd[1].ion[1].density[1].values, kdtree) + kdtree = get_kdtree(space) + get_electron_temperature = interp(ids.edge_profiles.ggd[1].electrons.temperature[1], kdtree) + get_ion_density = interp(ids.edge_profiles.ggd[1].ion[1].density[1], kdtree) grid_val = ids.edge_profiles.ggd[1].electrons.temperature[1].values[chosen_index] searched_val = get_electron_temperature(cell_center...) @@ -39,10 +40,33 @@ function test_interp() println("Grid Value: ", grid_val) println("Searched Value: ", searched_val) @assert(grid_val == searched_val) - + + chosen_index = 553:557 + grid_val = ids.edge_profiles.ggd[1].ion[1].density[1].values[chosen_index] + chosen_nodes = [space.objects_per_dimension[3].object[ii].nodes for ii in chosen_index] + cell_centers = [Tuple(mean([space.objects_per_dimension[1].object[node].geometry for node in nodes])) for nodes in chosen_nodes] + searched_val = get_ion_density(cell_centers) + return true +end + + +function test_project_prop_on_subset() + b2gmtry = "$(@__DIR__)/../samples/b2fgmtry" + b2output = "$(@__DIR__)/../samples/b2time_red.nc" + gsdesc = "$(@__DIR__)/../samples/gridspacedesc.yml" + b2mn = "$(@__DIR__)/../samples/b2mn.dat" + dd = solps2imas(b2gmtry, b2output, gsdesc, b2mn) + space = dd.edge_profiles.grid_ggd[1].space[1] + prop = dd.edge_profiles.ggd[1].electrons.density + from_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 5) # All cells + to_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 16) # separatix + # Cheating: need to fix solps2imas, prop did not get correct grid_subset_index + prop[5].grid_subset_index = 5 + project_prop_on_subset!(prop, from_subset, to_subset; space) return true end @testset "GGDUtils" begin @test test_interp() + @test test_project_prop_on_subset() end \ No newline at end of file From 79e79a90d986f0c22745100967a8638a2ca5906c Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Wed, 13 Sep 2023 15:48:29 -0700 Subject: [PATCH 08/30] project_prop_on_subset no returns grid centers project_prop_on_subset! now returns a tuple of two objects, first is an array of tuples representing (r,z) coordinates where the values are computed and the second is an array of the property values. The return tuple is different if projection is done within same subset dimensions. In this case, space keyword is not required. The first element in the return tuple is an array of indices of the subset objects where the value is defined. Second element is the same, the property values that were just computed and stored. For utility, get_subset_centers function has been added to quickly get an array of tuples representing (r, z) coordinates of the cell centers or the edge centers of the subset. --- src/GGDUtils.jl | 119 ++++++++++++++++++++++++++++++++++++++++------- test/runtests.jl | 13 +++++- 2 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index d178c0e..fdd9c71 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -50,8 +50,86 @@ function interp(prop, space::OMAS.edge_profiles__grid_ggd___space) end -function project_prop_on_subset!(prop, from_subset, to_subset; +""" + get_subset_centers(space::OMAS.edge_profiles__grid_ggd___space, + subset::OMAS.edge_profiles__grid_ggd___grid_subset) + +Returns an array of tuples corresponding to (r,z) coordinates of the center of +cells or the center of edges in the subset space. +""" +function get_subset_centers(space::OMAS.edge_profiles__grid_ggd___space, + subset::OMAS.edge_profiles__grid_ggd___grid_subset) + subset_space = get_subset_space(space, subset.element) + grid_nodes = space.objects_per_dimension[1].object + return [Tuple(mean([grid_nodes[node].geometry for node in obj.nodes])) for obj in subset_space] +end + + +""" + project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset; + space::OMAS.edge_profiles__grid_ggd___space) + +This function can be used to add another instance on a property vector representing the value +in a new subset that can be taken as a projection from an existing larger subset. +Arguments: +prop: A property like electrons.density that is a vector of objects with fields coefficients, + grid_index, grid_subset_index, and values. The different instances in the vector correspond + to different grid_subset for which the property is provided. +from_subset: grid_subset object which is already represented in the property instance. grid subset + with index 5 is populated in electrons.density already if the values for all cells are + present. +to_subset: grid_subset which is either a smaller part of from_subset (core, sol, idr, odr) but has + same dimensions as from_subset + OR + is smaller in dimension that goes through the from_subset (core_boundary, separatix etc.) +space: (optional) space object in grid_ggd is required only when from_subset is higher dimensional + than to_subset. +Returns: +NOTE: This function ends in ! which means it updates prop argument in place. But for the additional +utility, this function also returns a tuple +to_subset_centers, to_prop.values (when from_subset dimension is greater than to_subset dimension) +to_subset_ele_obj_inds, to_prop.values (when from_subset dimension is same as to_subset dimension) +Descriptions: +to_subset_centers: center of cells or center of edges of the to_subset where property values are + defined and stored +to_subset_ele_obj_inds: Indices of the elements of to_subset where property values are deined and + stored +to_prop.values: The projected values of the properties added to prop object in a new instance +""" +function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset; space::OMAS.edge_profiles__grid_ggd___space) + if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension + return project_prop_on_subset!(prop, from_subset, to_subset) + elseif from_subset.element[1].object[1].dimension > to_subset.element[1].object[1].dimension + from_prop = nothing + for p in prop + if p.grid_subset_index == from_subset.identifier.index + from_prop = p + break + end + end + if isnothing(from_prop) + println("from_subset not represented in the property yet") + end + to_subset_centers = get_subset_centers(space, to_subset) + resize!(prop, length(prop) + 1) + to_prop = prop[end] + to_prop.grid_index = from_prop.grid_index + to_prop.grid_subset_index = to_subset.identifier.index + resize!(to_prop.values, length(to_subset.element)) + prop_interp = interp(from_prop, space) + to_prop.values = prop_interp(to_subset_centers) + return to_subset_centers, to_prop.values + else + println("to_subset is higher dimensional than from_subset") + end +end + + +function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset) from_prop = nothing for p in prop if p.grid_subset_index == from_subset.identifier.index @@ -61,28 +139,35 @@ function project_prop_on_subset!(prop, from_subset, to_subset; end if isnothing(from_prop) println("from_subset not represented in the property yet") - return false end - if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension resize!(prop, length(prop) + 1) to_prop = prop[end] to_prop.grid_index = from_prop.grid_index to_prop.grid_subset_index = to_subset.identifier.index - from_subset_element_inds = [ele.index for ele in from_subset.element] - filtered_values = [from_prop[ele.index] for ele in to_subset.element if ele.index ∈ from_subset_element_inds] - resize!(to_prop.values, length(filtered_values)) - to_prop.values = filtered_values - elseif from_subset.element[1].object[1].dimension > to_subset.element[1].object[1].dimension - resize!(prop, length(prop) + 1) - to_prop = prop[end] - to_prop.grid_index = from_prop.grid_index - to_prop.grid_subset_index = to_subset.identifier.index - resize!(to_prop.values, length(to_subset.element)) - prop_interp = interp(from_prop, space) - grid_nodes = space.objects_per_dimension[1].object - to_subset_space = get_subset_space(space, to_subset.element) - to_prop.values = prop_interp([Tuple(mean([grid_nodes[node].geometry for node in obj.nodes])) for obj in to_subset_space]) + from_subset_ele_obj_inds = [ele.object[1].index for ele in from_subset.element] + to_subset_ele_obj_inds = [ele.object[1].index for ele in to_subset.element] + if to_subset_ele_obj_inds ⊆ from_subset_ele_obj_inds + from_ele_inds = [] + for to_ele_obj_ind in to_subset_ele_obj_inds + for (from_ele_ind, from_ele_obj_ind) in enumerate(from_subset_ele_obj_inds) + if from_ele_obj_ind == to_ele_obj_ind + append!(from_ele_inds, from_ele_ind) + end + end + end + filtered_values = [from_prop.values[from_ele_ind] for from_ele_ind in from_ele_inds] + resize!(to_prop.values, length(filtered_values)) + to_prop.values = filtered_values + return to_subset_ele_obj_inds, to_prop.values + else + error("to_subset does not lie entirely inside from_subset. Projection not possible.") + end + else + error("Dimensions of from_subset and to_subset do not match. Provide keyword ", + "argument space if you want to project to a smaller dimension as space ", + "information is required for that. Use\n", + "project_prop_on_subset!(prop, from_subset, to_subset; space=space)") end end diff --git a/test/runtests.jl b/test/runtests.jl index 0ab2a8e..7039138 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -62,7 +62,18 @@ function test_project_prop_on_subset() to_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 16) # separatix # Cheating: need to fix solps2imas, prop did not get correct grid_subset_index prop[5].grid_subset_index = 5 - project_prop_on_subset!(prop, from_subset, to_subset; space) + separatix_centers, values_at_separatix = project_prop_on_subset!(prop, from_subset, to_subset; space) + # println("Projected to separatix:") + # for ii in eachindex(separatix_centers) + # println(separatix_centers[ii], ": ", values_at_separatix[ii]) + # end + + subset_core = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 22) # core + core_element_inds, values_at_core = project_prop_on_subset!(prop, from_subset, subset_core) + # println("Project to core:") + # for ii in eachindex(core_element_inds) + # println("Element index: ", core_element_inds[ii], " has value : ", values_at_core[ii]) + # end return true end From 0388734d7b08694e3c9b3a500a496892486d9676 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 18 Sep 2023 17:06:21 -0700 Subject: [PATCH 09/30] Added 2D Visualization of grid_ggd as a recipe * plot(space) would overlay the whole grid_ggd defined in the space with label as space.identifier.name * plot(space, subset) will plot any edges of the subset or if it is a collection of nodes, scatter plot of those nodes with label same as subset.identifier.name * All attributes can be passed to these methods. * Identified some issues with SOLPS2IMAS which will be fixed. --- Project.toml | 1 + src/GGDUtils.jl | 4 +++ src/recipes.jl | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/recipes.jl diff --git a/Project.toml b/Project.toml index 94faade..5614f03 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.1.0" [deps] NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index fdd9c71..403f0c0 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -5,12 +5,16 @@ import StaticArrays: SVector import Statistics: mean import OMAS import SOLPS2IMAS: get_subset_space +using RecipesBase export interp export get_kdtree export project_prop_on_subset! +include("recipes.jl") + + function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) grid_nodes = space.objects_per_dimension[1].object grid_faces = space.objects_per_dimension[3].object diff --git a/src/recipes.jl b/src/recipes.jl new file mode 100644 index 0000000..cee710a --- /dev/null +++ b/src/recipes.jl @@ -0,0 +1,92 @@ +@recipe function f(space::OMAS.edge_profiles__grid_ggd___space) + nodes = space.objects_per_dimension[1].object + edges = space.objects_per_dimension[2].object + legend --> false + linewidth --> 0.2 + linecolor --> :black + size --> [600, 900] + xaxis --> "R [m]" + yaxis --> "Z [m]" + label_assigned = false + for edge in edges + if 0 ∉ edge.nodes + @series begin + seriestype := :path + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := space.identifier.name + end + label_assigned = true + else + label := "" + end + [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + end + end + end +end + + +@recipe function f( + space::OMAS.edge_profiles__grid_ggd___space, + subset::OMAS.edge_profiles__grid_ggd___grid_subset, +) + nodes = space.objects_per_dimension[1].object + edges = space.objects_per_dimension[2].object + cells = space.objects_per_dimension[3].object + legend --> false + linewidth --> 0.2 + linecolor --> :black + size --> [600, 900] + xaxis --> "R [m]" + yaxis --> "Z [m]" + subset_edge_inds = [] + label_assigned = false + if subset.element[1].object[1].dimension == 2 + for ele in subset.element + for bnd_ind in cells[ele.object[1].index].boundary + union!(subset_edge_inds, bnd_ind) + end + end + elseif subset.element[1].object[1].dimension == 1 + subset_edge_inds = [ele.object[1].index for ele in subset.element] + elseif subset.element[1].object[1].dimension == 0 + for ele in subset.element + @series begin + seriestype := :scatter + marker --> (:circle, 5) + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := subset.identifier.name + end + label_assigned = true + else + label := "" + end + ([nodes[ele.object[1].index].geometry[1]], [nodes[ele.object[1].index].geometry[2]]) + end + end + end + for edge in edges[subset_edge_inds] + if 0 ∉ edge.nodes + @series begin + seriestype := :path + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := subset.identifier.name + end + label_assigned = true + else + label := "" + end + [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + end + end + end +end \ No newline at end of file From 4b864b380553f3e0a3175c9ec3472d74b732acec Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 18 Sep 2023 18:24:08 -0700 Subject: [PATCH 10/30] Distinguishing the two function calls better. --- src/GGDUtils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index fdd9c71..fe2fa9a 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -98,7 +98,7 @@ to_subset_ele_obj_inds: Indices of the elements of to_subset where property valu to_prop.values: The projected values of the properties added to prop object in a new instance """ function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - to_subset::OMAS.edge_profiles__grid_ggd___grid_subset; + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset, space::OMAS.edge_profiles__grid_ggd___space) if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension return project_prop_on_subset!(prop, from_subset, to_subset) From 1328de70172d3c28ad718d6f7fde604f29b0f988 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 18 Sep 2023 17:06:21 -0700 Subject: [PATCH 11/30] Added 2D Visualization of grid_ggd as a recipe * plot(space) would overlay the whole grid_ggd defined in the space with label as space.identifier.name * plot(space, subset) will plot any edges of the subset or if it is a collection of nodes, scatter plot of those nodes with label same as subset.identifier.name * All attributes can be passed to these methods. * Identified some issues with SOLPS2IMAS which will be fixed. --- Project.toml | 1 + src/GGDUtils.jl | 4 +++ src/recipes.jl | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/recipes.jl diff --git a/Project.toml b/Project.toml index 94faade..5614f03 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ version = "0.1.0" [deps] NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" +RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index fe2fa9a..a0972cc 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -5,12 +5,16 @@ import StaticArrays: SVector import Statistics: mean import OMAS import SOLPS2IMAS: get_subset_space +using RecipesBase export interp export get_kdtree export project_prop_on_subset! +include("recipes.jl") + + function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) grid_nodes = space.objects_per_dimension[1].object grid_faces = space.objects_per_dimension[3].object diff --git a/src/recipes.jl b/src/recipes.jl new file mode 100644 index 0000000..cee710a --- /dev/null +++ b/src/recipes.jl @@ -0,0 +1,92 @@ +@recipe function f(space::OMAS.edge_profiles__grid_ggd___space) + nodes = space.objects_per_dimension[1].object + edges = space.objects_per_dimension[2].object + legend --> false + linewidth --> 0.2 + linecolor --> :black + size --> [600, 900] + xaxis --> "R [m]" + yaxis --> "Z [m]" + label_assigned = false + for edge in edges + if 0 ∉ edge.nodes + @series begin + seriestype := :path + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := space.identifier.name + end + label_assigned = true + else + label := "" + end + [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + end + end + end +end + + +@recipe function f( + space::OMAS.edge_profiles__grid_ggd___space, + subset::OMAS.edge_profiles__grid_ggd___grid_subset, +) + nodes = space.objects_per_dimension[1].object + edges = space.objects_per_dimension[2].object + cells = space.objects_per_dimension[3].object + legend --> false + linewidth --> 0.2 + linecolor --> :black + size --> [600, 900] + xaxis --> "R [m]" + yaxis --> "Z [m]" + subset_edge_inds = [] + label_assigned = false + if subset.element[1].object[1].dimension == 2 + for ele in subset.element + for bnd_ind in cells[ele.object[1].index].boundary + union!(subset_edge_inds, bnd_ind) + end + end + elseif subset.element[1].object[1].dimension == 1 + subset_edge_inds = [ele.object[1].index for ele in subset.element] + elseif subset.element[1].object[1].dimension == 0 + for ele in subset.element + @series begin + seriestype := :scatter + marker --> (:circle, 5) + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := subset.identifier.name + end + label_assigned = true + else + label := "" + end + ([nodes[ele.object[1].index].geometry[1]], [nodes[ele.object[1].index].geometry[2]]) + end + end + end + for edge in edges[subset_edge_inds] + if 0 ∉ edge.nodes + @series begin + seriestype := :path + if !label_assigned + if :label ∈ keys(plotattributes) + label := plotattributes[:label] + else + label := subset.identifier.name + end + label_assigned = true + else + label := "" + end + [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + end + end + end +end \ No newline at end of file From 68a8a4207c89fcfcdbd5f186f1c973fa20796635 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 15:49:34 -0700 Subject: [PATCH 12/30] Added 2D visualization of 2D quantities * Added a heatmap like visualization of 2D quantities * plot(grid_ggd, prop) would do this. * Example plot(grid_ggd, dd.edge_profiles.ggd[1].electrons.density[5]) * Colorbar label is set from property type name by default. This can be changed by user in plot command with colorbar_title argument. * Color scheme can be changed by providing any color scheme symbol name supported by ColorSchemes.jl as seriescolor argument. --- Project.toml | 1 + src/GGDUtils.jl | 3 +- src/recipes.jl | 85 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 5614f03..3609a45 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Anchal Gupta "] version = "0.1.0" [deps] +ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce" OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index a0972cc..5c0f4ef 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -4,8 +4,9 @@ import NearestNeighbors: KDTree, knn import StaticArrays: SVector import Statistics: mean import OMAS -import SOLPS2IMAS: get_subset_space +import SOLPS2IMAS: get_subset_space, get_grid_subset_with_index using RecipesBase +import ColorSchemes export interp export get_kdtree diff --git a/src/recipes.jl b/src/recipes.jl index cee710a..c682cad 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -5,8 +5,8 @@ linewidth --> 0.2 linecolor --> :black size --> [600, 900] - xaxis --> "R [m]" - yaxis --> "Z [m]" + xaxis --> "R / m" + yaxis --> "Z / m" label_assigned = false for edge in edges if 0 ∉ edge.nodes @@ -40,8 +40,8 @@ end linewidth --> 0.2 linecolor --> :black size --> [600, 900] - xaxis --> "R [m]" - yaxis --> "Z [m]" + xaxis --> "R / m" + yaxis --> "Z / m" subset_edge_inds = [] label_assigned = false if subset.element[1].object[1].dimension == 2 @@ -89,4 +89,81 @@ end end end end +end + + +@recipe function f(grid_ggd::OMAS.edge_profiles__grid_ggd, prop::OMAS.IDSvectorElement) + subset = get_grid_subset_with_index(grid_ggd, prop.grid_subset_index) + space = grid_ggd.space[subset.element[1].object[1].space] + nodes = space.objects_per_dimension[1].object + # edges = space.objects_per_dimension[2].object + cells = space.objects_per_dimension[3].object + legend --> false + size --> [600, 900] + xaxis --> "R / m" + yaxis --> "Z / m" + layout := @layout [a{0.95w} b] + if subset.element[1].object[1].dimension == 2 + if :seriescolor in keys(plotattributes) + color_scheme = plotattributes[:seriescolor] + else + color_scheme = :inferno + end + color_grad = getproperty(ColorSchemes, color_scheme) + val_min = minimum(prop.values) + val_max = maximum(prop.values) + function get_color(prop_value) + return color_grad[(log10(prop_value / val_min) / log10(val_max / val_min))] + end + + if :colorbar_title in keys(plotattributes) + prop_name = plotattributes[:colorbar_title] + else + prop_name = join(split(split(string(typeof(prop)), "___")[end], "__"), " ") + end + + # Make a mock heatmap to get the colorbar in a side pane + @series begin + subplot := 2 + seriestype := :heatmap + clims := (val_min, val_max) + framestyle := :none + color := color_scheme + colorbar := true + colorbar_scale := :log10 + colorbar_formatter := :scientific + colorbar_title := prop_name + lims := (-1, 0) + rand(2, 2) + end + + # Actual plot is plotted as different cell shapes filled with color values based on + # property value + for (ele, prop_value) in zip(subset.element, prop.values) + cell = cells[ele.object[1].index] + @series begin + subplot := 1 + seriestype := :shape + linecolor := get_color(prop_value) + fillcolor := get_color(prop_value) + [Tuple(nodes[cell.nodes[ii]].geometry) for ii in [1, 2, 4, 3]] + end + end + end +end + + +@recipe function f(grid_ggd_arr::Vector{OMAS.edge_profiles__grid_ggd}, prop::OMAS.IDSvectorElement) + found = false + for grid_ggd in grid_ggd_arr + if grid_ggd.identifier.index == prop.grid_index + @series begin + return grid_ggd, prop + end + found = true + end + end + if !found + error("Provided property belongs to a grid_index tha is not present in provided grid_ggd array") + end end \ No newline at end of file From a8b9f0029632134d8bc73d102b6c12b72e87add7 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 16:00:30 -0700 Subject: [PATCH 13/30] Ensure no labels are created for individual shapes --- src/recipes.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/recipes.jl b/src/recipes.jl index c682cad..ba9a24e 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -146,6 +146,7 @@ end seriestype := :shape linecolor := get_color(prop_value) fillcolor := get_color(prop_value) + label := "" [Tuple(nodes[cell.nodes[ii]].geometry) for ii in [1, 2, 4, 3]] end end From 75133739fe5e33d2dacda21bfeb50fba3ed44cb9 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 16:02:45 -0700 Subject: [PATCH 14/30] Minimum Working Exmaples added for plotting. --- examples/Project.toml | 11 +++ examples/plotting.ipynb | 171 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 examples/Project.toml create mode 100644 examples/plotting.ipynb diff --git a/examples/Project.toml b/examples/Project.toml new file mode 100644 index 0000000..1cd060b --- /dev/null +++ b/examples/Project.toml @@ -0,0 +1,11 @@ +name = "GGDUtils_examples" +authors = ["Anchal Gupta "] +version = "0.1.0" + +[deps] +GGDUtils = "b7b5e640-9b39-4803-84eb-376048795def" +GR = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +OMAS = "91cfaa06-6526-4804-8666-b540b3feef2f" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +SOLPS2IMAS = "09becab6-0636-4c23-a92a-2b3723265c31" diff --git a/examples/plotting.ipynb b/examples/plotting.ipynb new file mode 100644 index 0000000..3ebd5f6 --- /dev/null +++ b/examples/plotting.ipynb @@ -0,0 +1,171 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plotting examples using GGDUtils\n", + " \n", + " For running this notebook, you need to install package IJulia in your home environment (that is messy, but that is the only way I know right now). So in your terminal:\n", + " ```\n", + " % julia\n", + " julia > ]\n", + " (@v1.9 pkg) pkg> add IJulia\n", + " ```\n", + "\n", + " After this, Julia kernel would appear in your jupyter notebooks as an option. This also works for julia notebooks directly opened on VSCode. Select the Julia kernel to run this notebook." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "using Pkg\n", + "Pkg.activate(\"./\")\n", + "Pkg.add(url=\"git@github.com:ProjectTorreyPines/OMAS.jl.git\")\n", + "Pkg.add(url=\"git@github.com:ProjectTorreyPines/SOLPS2IMAS.jl.git\", rev=\"dev\")\n", + "Pkg.add(path=\"../\")\n", + "Pkg.add(PackageSpec(name=\"GR\", version=\"0.72.9\"))\n", + "Pkg.pin(\"GR\")\n", + "Pkg.add(\"Plots\")\n", + "Pkg.add(\"LaTeXStrings\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "using SOLPS2IMAS\n", + "using GGDUtils\n", + "using Plots\n", + "using LaTeXStrings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "b2gmtry = \"../samples/b2fgmtry\"\n", + "b2output = \"../samples/b2time_red.nc\"\n", + "gsdesc = \"../samples/gridspacedesc.yml\"\n", + "b2mn = \"../samples/b2mn.dat\"\n", + "dd = solps2imas(b2gmtry, b2output, gsdesc, b2mn)\n", + "grid_ggd = dd.edge_profiles.grid_ggd[1]\n", + "space = grid_ggd.space[1]\n", + "dd.edge_profiles.ggd[1].electrons.density[5].grid_subset_index = 5 # This is a bug in SOLPS2IMAS to be fixed" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotting grid and subsets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Choose backend\n", + "gr() # Fast and can save pdf\n", + "# plotlyjs() # Use for interactive plot, can only save png\n", + "\n", + "plot(space) # Simply plot the grid described in space, all common arguments to plot can be given here\n", + "\n", + "# You can overlay any subset by giving a second argument\n", + "# Labels \n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 6), markercolor=:chocolate1)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 7), linecolor=:red, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 8), linecolor=:darkred, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 9), linecolor=:limegreen, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 10), linecolor=:darkgreen, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 11), linecolor=:cyan, linewidth=2)\n", + "# plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 12), linecolor=:teal, linewidth=1)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 13), linecolor=:royalblue1, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 14), linecolor=:navyblue, linewidth=2)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 15), linecolor=:fuchsia, linewidth=2, linestyle=:dash)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 16), linecolor=:purple4, linewidth=2, linestyle=:dash)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 101), markershape=:rect, markercolor=:royalblue1)\n", + "# plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 102), markershape=:rect, markercolor=:maroon)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 103), markershape=:diamond, markercolor=:fuchsia)\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 104), markershape=:diamond, markercolor=:purple4)\n", + "\n", + "# Legend is supressed unless asked for specifically\n", + "plot!(legend=true)\n", + "# Default labels are subset.identifier.name but can be changed by providing a label argument" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotting 2D quantities as heatmaps" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Choose backend\n", + "gr() # Fast and can save pdf\n", + "# plotlyjs() # Use for interactive plot, can only save png\n", + "\n", + "plot(dd.edge_profiles.grid_ggd, dd.edge_profiles.ggd[1].electrons.density[5], colorbar_title=\"Electrons density / \" * L\"m^{-3}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### You can overlap any grid on top of a quantity" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Choose backend\n", + "gr() # Fast and can save pdf\n", + "# plotlyjs() # Use for interactive plot, can only save png\n", + "\n", + "plot(dd.edge_profiles.grid_ggd, dd.edge_profiles.ggd[1].electrons.density[5]) # Note default label in colorbar\n", + "plot!(space, SOLPS2IMAS.get_grid_subset_with_index(grid_ggd, 16), linecolor=:red, linewidth=2, linestyle=:solid, label=\"Separatix\", legend=true)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.9.2", + "language": "julia", + "name": "julia-1.9" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.9.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 46aaf7105ced24116129a2398e89254cc9f97ddf Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 17:59:35 -0700 Subject: [PATCH 15/30] Adding format configuration. This is how it will look. --- .JuliaFormatter.toml | 27 ++++++++ src/GGDUtils.jl | 144 ++++++++++++++++++++++++++----------------- src/recipes.jl | 44 +++++++------ 3 files changed, 139 insertions(+), 76 deletions(-) create mode 100644 .JuliaFormatter.toml diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..4d331ff --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1,27 @@ +align_assignment = true +align_conditional = true +align_matrix = true +align_pair_arrow = true +align_struct_field = true +always_for_in = true +always_use_return = true +annotate_untyped_fields_with_any = false +conditional_to_if = true +for_in_replacement = "∈" +format_docstrings = true +import_to_using = true +indent = 4 +indent_submodule = true +join_lines_based_on_source = true +long_to_short_function_def = true +margin = 88 +normalize_line_endings = "unix" +pipe_to_function_call = true +remove_extra_newlines = false +separate_kwargs_with_semicolon = true +surround_whereop_typeparameters = true +trailing_comma = false +whitespace_in_kwargs = false +whitespace_ops_in_indices = false +whitespace_typedefs = true +yas_style_nesting = true \ No newline at end of file diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index 5c0f4ef..90fd15c 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -3,10 +3,10 @@ module GGDUtils import NearestNeighbors: KDTree, knn import StaticArrays: SVector import Statistics: mean -import OMAS +using OMAS: OMAS import SOLPS2IMAS: get_subset_space, get_grid_subset_with_index using RecipesBase -import ColorSchemes +using ColorSchemes: ColorSchemes export interp export get_kdtree @@ -19,8 +19,11 @@ include("recipes.jl") function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) grid_nodes = space.objects_per_dimension[1].object grid_faces = space.objects_per_dimension[3].object - grid_faces = [cell for cell in grid_faces if length(cell.nodes) == 4] - grid_centers = [SVector{2}(mean([grid_nodes[node].geometry for node in cell.nodes])) for cell in grid_faces] + grid_faces = [cell for cell ∈ grid_faces if length(cell.nodes) == 4] + grid_centers = [ + SVector{2}(mean([grid_nodes[node].geometry for node ∈ cell.nodes])) for + cell ∈ grid_faces + ] return KDTree(grid_centers; leafsize=10) end @@ -28,23 +31,27 @@ end function interp(prop, kdtree::KDTree) function get_interp_val(x::Number, y::Number) nearest_indices, distances = knn(kdtree, Array([x, y]), 4) - v1, v2, v3, v4 = [prop.values[ii] for ii in nearest_indices] + v1, v2, v3, v4 = [prop.values[ii] for ii ∈ nearest_indices] d1, d2, d3, d4 = distances - return ((v1 * d2 * d3 * d4 + d1 * v2 * d3 * d4 - + d1 * d2 * v3 * d4 + d1 * d2 * d3 * v4) - / - (d2 * d3 * d4 + d1 * d3 * d4 - + d1 * d2 * d4 + d1 * d2 * d3)) + return ( + ( + v1 * d2 * d3 * d4 + d1 * v2 * d3 * d4 + + d1 * d2 * v3 * d4 + d1 * d2 * d3 * v4 + ) + / + (d2 * d3 * d4 + d1 * d3 * d4 + + d1 * d2 * d4 + d1 * d2 * d3) + ) end function get_interp_val(x::Vector{Float64}, y::Vector{Float64}) if length(x) != length(y) error("Length of the two axes are not equal") else - return [get_interp_val(x[ii], y[ii]) for ii in eachindex(x)] + return [get_interp_val(x[ii], y[ii]) for ii ∈ eachindex(x)] end end function get_interp_val(xy::Vector{Tuple{Float64, Float64}}) - return [get_interp_val(xy[ii]...) for ii in eachindex(xy)] + return [get_interp_val(xy[ii]...) for ii ∈ eachindex(xy)] end return get_interp_val end @@ -66,50 +73,65 @@ function get_subset_centers(space::OMAS.edge_profiles__grid_ggd___space, subset::OMAS.edge_profiles__grid_ggd___grid_subset) subset_space = get_subset_space(space, subset.element) grid_nodes = space.objects_per_dimension[1].object - return [Tuple(mean([grid_nodes[node].geometry for node in obj.nodes])) for obj in subset_space] + return [ + Tuple(mean([grid_nodes[node].geometry for node ∈ obj.nodes])) for + obj ∈ subset_space + ] end +#! format: off """ - project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - to_subset::OMAS.edge_profiles__grid_ggd___grid_subset; - space::OMAS.edge_profiles__grid_ggd___space) + project_prop_on_subset!(prop, + from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + space::OMAS.edge_profiles__grid_ggd___space) -This function can be used to add another instance on a property vector representing the value -in a new subset that can be taken as a projection from an existing larger subset. +This function can be used to add another instance on a property vector representing the +value in a new subset that can be taken as a projection from an existing larger subset. Arguments: -prop: A property like electrons.density that is a vector of objects with fields coefficients, - grid_index, grid_subset_index, and values. The different instances in the vector correspond - to different grid_subset for which the property is provided. -from_subset: grid_subset object which is already represented in the property instance. grid subset - with index 5 is populated in electrons.density already if the values for all cells are - present. -to_subset: grid_subset which is either a smaller part of from_subset (core, sol, idr, odr) but has - same dimensions as from_subset +prop: A property like electrons.density that is a vector of objects with fields + coefficients, grid_index, grid_subset_index, and values. The different instances + in the vector correspond to different grid_subset for which the property is + provided. +from_subset: grid_subset object which is already represented in the property instance. + grid subset with index 5 is populated in electrons.density already if the + values for all cells are present. +to_subset: grid_subset which is either a smaller part of from_subset (core, sol, idr, + odr) but has same dimensions as from_subset OR - is smaller in dimension that goes through the from_subset (core_boundary, separatix etc.) -space: (optional) space object in grid_ggd is required only when from_subset is higher dimensional - than to_subset. + is smaller in dimension that goes through the from_subset (core_boundary, + separatix etc.) +space: (optional) space object in grid_ggd is required only when from_subset is + higher dimensional than to_subset. Returns: -NOTE: This function ends in ! which means it updates prop argument in place. But for the additional -utility, this function also returns a tuple -to_subset_centers, to_prop.values (when from_subset dimension is greater than to_subset dimension) -to_subset_ele_obj_inds, to_prop.values (when from_subset dimension is same as to_subset dimension) +NOTE: This function ends in ! which means it updates prop argument in place. But for +the additional utility, this function also returns a tuple +(to_subset_centers, to_prop.values) when from_subset dimension is greater than + to_subset dimension +OR +(to_subset_ele_obj_inds, to_prop.values) when from_subset dimension is same as + to_subset dimension) Descriptions: -to_subset_centers: center of cells or center of edges of the to_subset where property values are - defined and stored -to_subset_ele_obj_inds: Indices of the elements of to_subset where property values are deined and - stored -to_prop.values: The projected values of the properties added to prop object in a new instance +to_subset_centers: center of cells or center of edges of the to_subset where property + values are defined and stored +to_subset_ele_obj_inds: Indices of the elements of to_subset where property values are + defined and stored +to_prop.values: The projected values of the properties added to prop object in a new + instance """ -function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - to_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - space::OMAS.edge_profiles__grid_ggd___space) - if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension +#! format: on +function project_prop_on_subset!(prop, + from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + space::OMAS.edge_profiles__grid_ggd___space) + if from_subset.element[1].object[1].dimension == + to_subset.element[1].object[1].dimension return project_prop_on_subset!(prop, from_subset, to_subset) - elseif from_subset.element[1].object[1].dimension > to_subset.element[1].object[1].dimension + elseif from_subset.element[1].object[1].dimension > + to_subset.element[1].object[1].dimension from_prop = nothing - for p in prop + for p ∈ prop if p.grid_subset_index == from_subset.identifier.index from_prop = p break @@ -133,10 +155,11 @@ function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd end -function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - to_subset::OMAS.edge_profiles__grid_ggd___grid_subset) +function project_prop_on_subset!(prop, + from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset) from_prop = nothing - for p in prop + for p ∈ prop if p.grid_subset_index == from_subset.identifier.index from_prop = p break @@ -145,34 +168,39 @@ function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd if isnothing(from_prop) println("from_subset not represented in the property yet") end - if from_subset.element[1].object[1].dimension == to_subset.element[1].object[1].dimension + if from_subset.element[1].object[1].dimension == + to_subset.element[1].object[1].dimension resize!(prop, length(prop) + 1) to_prop = prop[end] to_prop.grid_index = from_prop.grid_index to_prop.grid_subset_index = to_subset.identifier.index - from_subset_ele_obj_inds = [ele.object[1].index for ele in from_subset.element] - to_subset_ele_obj_inds = [ele.object[1].index for ele in to_subset.element] + from_subset_ele_obj_inds = [ele.object[1].index for ele ∈ from_subset.element] + to_subset_ele_obj_inds = [ele.object[1].index for ele ∈ to_subset.element] if to_subset_ele_obj_inds ⊆ from_subset_ele_obj_inds from_ele_inds = [] - for to_ele_obj_ind in to_subset_ele_obj_inds - for (from_ele_ind, from_ele_obj_ind) in enumerate(from_subset_ele_obj_inds) + for to_ele_obj_ind ∈ to_subset_ele_obj_inds + for (from_ele_ind, from_ele_obj_ind) ∈ + enumerate(from_subset_ele_obj_inds) if from_ele_obj_ind == to_ele_obj_ind append!(from_ele_inds, from_ele_ind) end end end - filtered_values = [from_prop.values[from_ele_ind] for from_ele_ind in from_ele_inds] - resize!(to_prop.values, length(filtered_values)) + filtered_values = + [from_prop.values[from_ele_ind] for from_ele_ind ∈ from_ele_inds] + resize!(to_prop.values, length(filtered_values)) to_prop.values = filtered_values return to_subset_ele_obj_inds, to_prop.values else - error("to_subset does not lie entirely inside from_subset. Projection not possible.") + error("to_subset does not lie entirely inside from_subset. Projection ", + "not possible." + ) end else error("Dimensions of from_subset and to_subset do not match. Provide keyword ", - "argument space if you want to project to a smaller dimension as space ", - "information is required for that. Use\n", - "project_prop_on_subset!(prop, from_subset, to_subset; space=space)") + "argument space if you want to project to a smaller dimension as space ", + "information is required for that. Use\n", + "project_prop_on_subset!(prop, from_subset, to_subset; space=space)") end end diff --git a/src/recipes.jl b/src/recipes.jl index ba9a24e..db5e18a 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -8,7 +8,7 @@ xaxis --> "R / m" yaxis --> "Z / m" label_assigned = false - for edge in edges + for edge ∈ edges if 0 ∉ edge.nodes @series begin seriestype := :path @@ -22,7 +22,7 @@ else label := "" end - [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + [Tuple(nodes[edge.nodes[ii]].geometry) for ii ∈ [1, 2]] end end end @@ -31,7 +31,7 @@ end @recipe function f( space::OMAS.edge_profiles__grid_ggd___space, - subset::OMAS.edge_profiles__grid_ggd___grid_subset, + subset::OMAS.edge_profiles__grid_ggd___grid_subset ) nodes = space.objects_per_dimension[1].object edges = space.objects_per_dimension[2].object @@ -45,15 +45,15 @@ end subset_edge_inds = [] label_assigned = false if subset.element[1].object[1].dimension == 2 - for ele in subset.element - for bnd_ind in cells[ele.object[1].index].boundary + for ele ∈ subset.element + for bnd_ind ∈ cells[ele.object[1].index].boundary union!(subset_edge_inds, bnd_ind) end end elseif subset.element[1].object[1].dimension == 1 - subset_edge_inds = [ele.object[1].index for ele in subset.element] + subset_edge_inds = [ele.object[1].index for ele ∈ subset.element] elseif subset.element[1].object[1].dimension == 0 - for ele in subset.element + for ele ∈ subset.element @series begin seriestype := :scatter marker --> (:circle, 5) @@ -67,11 +67,14 @@ end else label := "" end - ([nodes[ele.object[1].index].geometry[1]], [nodes[ele.object[1].index].geometry[2]]) + ( + [nodes[ele.object[1].index].geometry[1]], + [nodes[ele.object[1].index].geometry[2]] + ) end end end - for edge in edges[subset_edge_inds] + for edge ∈ edges[subset_edge_inds] if 0 ∉ edge.nodes @series begin seriestype := :path @@ -85,7 +88,7 @@ end else label := "" end - [Tuple(nodes[edge.nodes[ii]].geometry) for ii in [1, 2]] + [Tuple(nodes[edge.nodes[ii]].geometry) for ii ∈ [1, 2]] end end end @@ -113,7 +116,7 @@ end val_min = minimum(prop.values) val_max = maximum(prop.values) function get_color(prop_value) - return color_grad[(log10(prop_value / val_min) / log10(val_max / val_min))] + return color_grad[(log10(prop_value / val_min)/log10(val_max / val_min))] end if :colorbar_title in keys(plotattributes) @@ -137,9 +140,9 @@ end rand(2, 2) end - # Actual plot is plotted as different cell shapes filled with color values based on - # property value - for (ele, prop_value) in zip(subset.element, prop.values) + # Actual plot is plotted as different cell shapes filled with color values + # based on property value + for (ele, prop_value) ∈ zip(subset.element, prop.values) cell = cells[ele.object[1].index] @series begin subplot := 1 @@ -147,16 +150,19 @@ end linecolor := get_color(prop_value) fillcolor := get_color(prop_value) label := "" - [Tuple(nodes[cell.nodes[ii]].geometry) for ii in [1, 2, 4, 3]] + [Tuple(nodes[cell.nodes[ii]].geometry) for ii ∈ [1, 2, 4, 3]] end end end end -@recipe function f(grid_ggd_arr::Vector{OMAS.edge_profiles__grid_ggd}, prop::OMAS.IDSvectorElement) +@recipe function f( + grid_ggd_arr::Vector{OMAS.edge_profiles__grid_ggd}, + prop::OMAS.IDSvectorElement +) found = false - for grid_ggd in grid_ggd_arr + for grid_ggd ∈ grid_ggd_arr if grid_ggd.identifier.index == prop.grid_index @series begin return grid_ggd, prop @@ -165,6 +171,8 @@ end end end if !found - error("Provided property belongs to a grid_index tha is not present in provided grid_ggd array") + error("Provided property belongs to a grid_index tha is not present in ", + "provided grid_ggd array" + ) end end \ No newline at end of file From 5e0192856b857c90b48a4e4a64dd63502ed276dd Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 18:32:03 -0700 Subject: [PATCH 16/30] Trying Format Check in CI --- .github/workflows/format_check.yml | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/format_check.yml diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml new file mode 100644 index 0000000..76305a0 --- /dev/null +++ b/.github/workflows/format_check.yml @@ -0,0 +1,36 @@ +name: Format Check + +on: + push: + branches: ["master", "dev"] + pull_request: + branches: ["master", "dev"] +jobs: + check: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1.9.3] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - uses: actions/checkout@v1 + - name: Install JuliaFormatter and format + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter"))' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + - name: Format check + run: | + julia -e ' + out = Cmd(`git diff --name-only`) |> read |> String + if out == "" + exit(0) + else + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) + end' From 04f0a664a15715ae399b3358f10de13f28d85249 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 18:33:19 -0700 Subject: [PATCH 17/30] Adding format branch for action testing. --- .github/workflows/format_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index 76305a0..4e46a44 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -2,7 +2,7 @@ name: Format Check on: push: - branches: ["master", "dev"] + branches: ["master", "dev", "format"] pull_request: branches: ["master", "dev"] jobs: From adcac0148c8e08c4517f7fff35a9504b9eeccdec Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 18:44:36 -0700 Subject: [PATCH 18/30] Formatted using config file. --- test/runtests.jl | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 7039138..76970b6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,12 +8,11 @@ function test_interp() ids = h5i2imas("$(@__DIR__)/../samples/edge_profiles.h5") electron_density = ids.edge_profiles.ggd[1].electrons.density[1] space = ids.edge_profiles.grid_ggd[1].space[1] - # path_to_data = ["edge_profiles", "ggd", 1, "electrons", "density", 1, "values"] - # path_to_opd = ["edge_profiles", "grid_ggd", 1, "space", 1, "objects_per_dimension"] get_electron_density = interp(electron_density, space) chosen_index = 555 nodes = space.objects_per_dimension[3].object[chosen_index].nodes - nodes_coords = [space.objects_per_dimension[1].object[node].geometry for node in nodes] + nodes_coords = + [space.objects_per_dimension[1].object[node].geometry for node ∈ nodes] cell_center = mean(nodes_coords) grid_val = ids.edge_profiles.ggd[1].electrons.density[1].values[chosen_index] searched_val = get_electron_density(cell_center...) @@ -24,7 +23,8 @@ function test_interp() # Use the same kdtree to interpolate other quantities kdtree = get_kdtree(space) - get_electron_temperature = interp(ids.edge_profiles.ggd[1].electrons.temperature[1], kdtree) + get_electron_temperature = + interp(ids.edge_profiles.ggd[1].electrons.temperature[1], kdtree) get_ion_density = interp(ids.edge_profiles.ggd[1].ion[1].density[1], kdtree) grid_val = ids.edge_profiles.ggd[1].electrons.temperature[1].values[chosen_index] @@ -43,8 +43,15 @@ function test_interp() chosen_index = 553:557 grid_val = ids.edge_profiles.ggd[1].ion[1].density[1].values[chosen_index] - chosen_nodes = [space.objects_per_dimension[3].object[ii].nodes for ii in chosen_index] - cell_centers = [Tuple(mean([space.objects_per_dimension[1].object[node].geometry for node in nodes])) for nodes in chosen_nodes] + chosen_nodes = + [space.objects_per_dimension[3].object[ii].nodes for ii ∈ chosen_index] + cell_centers = [ + Tuple( + mean([ + space.objects_per_dimension[1].object[node].geometry for node ∈ nodes + ]) + ) for nodes ∈ chosen_nodes + ] searched_val = get_ion_density(cell_centers) return true end @@ -58,21 +65,30 @@ function test_project_prop_on_subset() dd = solps2imas(b2gmtry, b2output, gsdesc, b2mn) space = dd.edge_profiles.grid_ggd[1].space[1] prop = dd.edge_profiles.ggd[1].electrons.density - from_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 5) # All cells - to_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 16) # separatix + # All cells + from_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 5) + # separatix + to_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 16) # Cheating: need to fix solps2imas, prop did not get correct grid_subset_index prop[5].grid_subset_index = 5 - separatix_centers, values_at_separatix = project_prop_on_subset!(prop, from_subset, to_subset; space) + separatix_centers, values_at_separatix = + project_prop_on_subset!(prop, from_subset, to_subset; space) # println("Projected to separatix:") - # for ii in eachindex(separatix_centers) + # for ii ∈ eachindex(separatix_centers) # println(separatix_centers[ii], ": ", values_at_separatix[ii]) # end - subset_core = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 22) # core - core_element_inds, values_at_core = project_prop_on_subset!(prop, from_subset, subset_core) + subset_core = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 22) + core_element_inds, values_at_core = + project_prop_on_subset!(prop, from_subset, subset_core) # println("Project to core:") - # for ii in eachindex(core_element_inds) - # println("Element index: ", core_element_inds[ii], " has value : ", values_at_core[ii]) + # for ii ∈ eachindex(core_element_inds) + # println( + # "Element index: ", + # core_element_inds[ii], + # " has value : ", + # values_at_core[ii] + # ) # end return true end From 5079befcc38f353116caaa12cf00ec46733f698d Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 18:51:19 -0700 Subject: [PATCH 19/30] Newline at end of file is required VScode formatter on my machine missed this but the Github Actions did not. When I ran teh formatter using julia, it indeed was failing due to the newline at the end of the file. On this commit, the workflow should pass. --- src/recipes.jl | 2 +- test/runtests.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index db5e18a..3d4f081 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -175,4 +175,4 @@ end "provided grid_ggd array" ) end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 76970b6..3bb7909 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -96,4 +96,4 @@ end @testset "GGDUtils" begin @test test_interp() @test test_project_prop_on_subset() -end \ No newline at end of file +end From e485283d2b04f1db198460b8df3923d96a0eb888 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Tue, 19 Sep 2023 19:00:52 -0700 Subject: [PATCH 20/30] Added Format Check status badge --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5d33011..af5e098 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # GGDUtils + +![Format Check](https://github.com/ProjectTorreyPines/GGDUtils.jl/actions/workflows/format_check.yml/badge.svg) + Package holding utilities for Generalized Grid Description (GGD) objects in IMAS datastructure. Primary goals are interpolation and core profile extrapolation. From 077d7471d1f6075f998936a76c7b1ee336011fbe Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Wed, 20 Sep 2023 10:33:36 -0700 Subject: [PATCH 21/30] Using dangling commas: trailing_comma = true --- .JuliaFormatter.toml | 2 +- src/GGDUtils.jl | 2 +- src/recipes.jl | 8 ++++---- test/runtests.jl | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 4d331ff..c436b82 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -20,7 +20,7 @@ pipe_to_function_call = true remove_extra_newlines = false separate_kwargs_with_semicolon = true surround_whereop_typeparameters = true -trailing_comma = false +trailing_comma = true whitespace_in_kwargs = false whitespace_ops_in_indices = false whitespace_typedefs = true diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index 90fd15c..606913d 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -193,7 +193,7 @@ function project_prop_on_subset!(prop, return to_subset_ele_obj_inds, to_prop.values else error("to_subset does not lie entirely inside from_subset. Projection ", - "not possible." + "not possible.", ) end else diff --git a/src/recipes.jl b/src/recipes.jl index 3d4f081..72a109d 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -31,7 +31,7 @@ end @recipe function f( space::OMAS.edge_profiles__grid_ggd___space, - subset::OMAS.edge_profiles__grid_ggd___grid_subset + subset::OMAS.edge_profiles__grid_ggd___grid_subset, ) nodes = space.objects_per_dimension[1].object edges = space.objects_per_dimension[2].object @@ -69,7 +69,7 @@ end end ( [nodes[ele.object[1].index].geometry[1]], - [nodes[ele.object[1].index].geometry[2]] + [nodes[ele.object[1].index].geometry[2]], ) end end @@ -159,7 +159,7 @@ end @recipe function f( grid_ggd_arr::Vector{OMAS.edge_profiles__grid_ggd}, - prop::OMAS.IDSvectorElement + prop::OMAS.IDSvectorElement, ) found = false for grid_ggd ∈ grid_ggd_arr @@ -172,7 +172,7 @@ end end if !found error("Provided property belongs to a grid_index tha is not present in ", - "provided grid_ggd array" + "provided grid_ggd array", ) end end diff --git a/test/runtests.jl b/test/runtests.jl index 3bb7909..c08b031 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -49,7 +49,7 @@ function test_interp() Tuple( mean([ space.objects_per_dimension[1].object[node].geometry for node ∈ nodes - ]) + ]), ) for nodes ∈ chosen_nodes ] searched_val = get_ion_density(cell_centers) From 0c7036cc83f26ad1ad05ed42f301b64ecb59a47b Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Wed, 20 Sep 2023 10:45:27 -0700 Subject: [PATCH 22/30] remove_extra_newlines=true --- .JuliaFormatter.toml | 4 ++-- src/GGDUtils.jl | 7 ------- src/recipes.jl | 3 --- test/runtests.jl | 1 - 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index c436b82..aa7f0eb 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -17,11 +17,11 @@ long_to_short_function_def = true margin = 88 normalize_line_endings = "unix" pipe_to_function_call = true -remove_extra_newlines = false +remove_extra_newlines = true separate_kwargs_with_semicolon = true surround_whereop_typeparameters = true trailing_comma = true whitespace_in_kwargs = false whitespace_ops_in_indices = false whitespace_typedefs = true -yas_style_nesting = true \ No newline at end of file +yas_style_nesting = true diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index 606913d..c5c65e1 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -12,10 +12,8 @@ export interp export get_kdtree export project_prop_on_subset! - include("recipes.jl") - function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) grid_nodes = space.objects_per_dimension[1].object grid_faces = space.objects_per_dimension[3].object @@ -27,7 +25,6 @@ function get_kdtree(space::OMAS.edge_profiles__grid_ggd___space) return KDTree(grid_centers; leafsize=10) end - function interp(prop, kdtree::KDTree) function get_interp_val(x::Number, y::Number) nearest_indices, distances = knn(kdtree, Array([x, y]), 4) @@ -56,12 +53,10 @@ function interp(prop, kdtree::KDTree) return get_interp_val end - function interp(prop, space::OMAS.edge_profiles__grid_ggd___space) return interp(prop, get_kdtree(space)) end - """ get_subset_centers(space::OMAS.edge_profiles__grid_ggd___space, subset::OMAS.edge_profiles__grid_ggd___grid_subset) @@ -79,7 +74,6 @@ function get_subset_centers(space::OMAS.edge_profiles__grid_ggd___space, ] end - #! format: off """ project_prop_on_subset!(prop, @@ -154,7 +148,6 @@ function project_prop_on_subset!(prop, end end - function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, to_subset::OMAS.edge_profiles__grid_ggd___grid_subset) diff --git a/src/recipes.jl b/src/recipes.jl index 72a109d..3a7726a 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -28,7 +28,6 @@ end end - @recipe function f( space::OMAS.edge_profiles__grid_ggd___space, subset::OMAS.edge_profiles__grid_ggd___grid_subset, @@ -94,7 +93,6 @@ end end end - @recipe function f(grid_ggd::OMAS.edge_profiles__grid_ggd, prop::OMAS.IDSvectorElement) subset = get_grid_subset_with_index(grid_ggd, prop.grid_subset_index) space = grid_ggd.space[subset.element[1].object[1].space] @@ -156,7 +154,6 @@ end end end - @recipe function f( grid_ggd_arr::Vector{OMAS.edge_profiles__grid_ggd}, prop::OMAS.IDSvectorElement, diff --git a/test/runtests.jl b/test/runtests.jl index c08b031..df7be0e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -56,7 +56,6 @@ function test_interp() return true end - function test_project_prop_on_subset() b2gmtry = "$(@__DIR__)/../samples/b2fgmtry" b2output = "$(@__DIR__)/../samples/b2time_red.nc" From 2f7bb53a008523ff202ecd752ca5bc1c39649711 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 22 Sep 2023 12:20:34 -0700 Subject: [PATCH 23/30] Updated .dvc connections to point to new repo name SOLPSTestSamples --- samples/b2fgmtry.dvc | 6 +++--- samples/b2mn.dat.dvc | 6 +++--- samples/b2time.nc.dvc | 6 +++--- samples/edge_profiles.h5.dvc | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/samples/b2fgmtry.dvc b/samples/b2fgmtry.dvc index ea287f0..a92eca2 100644 --- a/samples/b2fgmtry.dvc +++ b/samples/b2fgmtry.dvc @@ -1,10 +1,10 @@ -md5: 26c488e90a669ef2909a6fbe873b38d0 +md5: bf96c041599ce04799130f3e0dd34d3f frozen: true deps: - path: ITER_Lore_2296_00000/baserun/b2fgmtry repo: - url: git@github.com:ProjectTorreyPines/TestSamples.git - rev_lock: dc2da57d329888998e008f766e620ee914541d2f + url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git + rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: - md5: 6589953daeef49b21744d159af970cbb size: 2908856 diff --git a/samples/b2mn.dat.dvc b/samples/b2mn.dat.dvc index 866c609..30100fe 100644 --- a/samples/b2mn.dat.dvc +++ b/samples/b2mn.dat.dvc @@ -1,10 +1,10 @@ -md5: c408a3f9242593adab848e2899868371 +md5: 604582a3258f12bb4d2711a15479e2c0 frozen: true deps: - path: ITER_Lore_2296_00000/run_restart/b2mn.dat repo: - url: git@github.com:ProjectTorreyPines/TestSamples.git - rev_lock: dc2da57d329888998e008f766e620ee914541d2f + url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git + rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: - md5: 26c5edd33fed9bff73cda8db17c591db size: 1560 diff --git a/samples/b2time.nc.dvc b/samples/b2time.nc.dvc index aec5055..9ed9f84 100644 --- a/samples/b2time.nc.dvc +++ b/samples/b2time.nc.dvc @@ -1,10 +1,10 @@ -md5: ca5c76dfa367c27a421168b198c3346d +md5: 3a4769e64de6be6527579e6490d332f3 frozen: true deps: - path: ITER_Lore_2296_00000/run_restart/b2time.nc repo: - url: git@github.com:ProjectTorreyPines/TestSamples.git - rev_lock: dc2da57d329888998e008f766e620ee914541d2f + url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git + rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: - md5: 850542d59a6796eca1e22a64162af2de size: 201992 diff --git a/samples/edge_profiles.h5.dvc b/samples/edge_profiles.h5.dvc index b09e182..02b22ec 100644 --- a/samples/edge_profiles.h5.dvc +++ b/samples/edge_profiles.h5.dvc @@ -1,10 +1,10 @@ -md5: ba8bc1d923f00971c24d51267d9416de +md5: fd276c67d8a16214d1e230b6dd6c32c4 frozen: true deps: - path: ITER_Lore_2296_00000/IMAS/edge_profiles.h5 repo: - url: git@github.com:ProjectTorreyPines/TestSamples.git - rev_lock: 5cb261ee0410759c4d6fd9a18fef421bd954aff1 + url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git + rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: - md5: c3d60ce69e9d3a9b9ec621e9276858e0 size: 168176600 From 1270f93146f905cb439c4fee680f3ecfb8f0781d Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 22 Sep 2023 15:08:27 -0700 Subject: [PATCH 24/30] Removing hack needed for a bug in SOLPS2IMAS. --- test/runtests.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index df7be0e..5f9ccb7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -68,10 +68,8 @@ function test_project_prop_on_subset() from_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 5) # separatix to_subset = get_grid_subset_with_index(dd.edge_profiles.grid_ggd[1], 16) - # Cheating: need to fix solps2imas, prop did not get correct grid_subset_index - prop[5].grid_subset_index = 5 separatix_centers, values_at_separatix = - project_prop_on_subset!(prop, from_subset, to_subset; space) + project_prop_on_subset!(prop, from_subset, to_subset, space) # println("Projected to separatix:") # for ii ∈ eachindex(separatix_centers) # println(separatix_centers[ii], ": ", values_at_separatix[ii]) From 9480064bd788ea475a51edcb8630f223a5d76588 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 22 Sep 2023 15:14:19 -0700 Subject: [PATCH 25/30] Using correct time dependent SOLPS run samples --- samples/b2mn.dat.dvc | 8 ++++---- samples/b2time.nc.dvc | 9 +++++---- test/runtests.jl | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/samples/b2mn.dat.dvc b/samples/b2mn.dat.dvc index 30100fe..018dfbc 100644 --- a/samples/b2mn.dat.dvc +++ b/samples/b2mn.dat.dvc @@ -1,12 +1,12 @@ -md5: 604582a3258f12bb4d2711a15479e2c0 +md5: ab8eafd069e624c2e00e6156be881d4a frozen: true deps: -- path: ITER_Lore_2296_00000/run_restart/b2mn.dat +- path: ITER_Lore_2296_00000/run_time_dep_EIRENE_jdl_to_ss_cont_sine2_2d_output/b2mn.dat repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: -- md5: 26c5edd33fed9bff73cda8db17c591db - size: 1560 +- md5: 1af9d167996ea1a420f49e0d89c98e6d + size: 13925 hash: md5 path: b2mn.dat diff --git a/samples/b2time.nc.dvc b/samples/b2time.nc.dvc index 9ed9f84..5139eeb 100644 --- a/samples/b2time.nc.dvc +++ b/samples/b2time.nc.dvc @@ -1,12 +1,13 @@ -md5: 3a4769e64de6be6527579e6490d332f3 +md5: 14431f8773812c851d7dc95befad39d5 frozen: true deps: -- path: ITER_Lore_2296_00000/run_restart/b2time.nc +- path: + ITER_Lore_2296_00000/run_time_dep_EIRENE_jdl_to_ss_cont_sine2_2d_output/b2time.nc repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 outs: -- md5: 850542d59a6796eca1e22a64162af2de - size: 201992 +- md5: 778b3bb62b82f493c785373d872f6a1f + size: 13630424 hash: md5 path: b2time.nc diff --git a/test/runtests.jl b/test/runtests.jl index 5f9ccb7..b397f42 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -58,7 +58,7 @@ end function test_project_prop_on_subset() b2gmtry = "$(@__DIR__)/../samples/b2fgmtry" - b2output = "$(@__DIR__)/../samples/b2time_red.nc" + b2output = "$(@__DIR__)/../samples/b2time.nc" gsdesc = "$(@__DIR__)/../samples/gridspacedesc.yml" b2mn = "$(@__DIR__)/../samples/b2mn.dat" dd = solps2imas(b2gmtry, b2output, gsdesc, b2mn) From dea75179f168c1a75a6265d14c18967a0c83e1d5 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 22 Sep 2023 15:29:59 -0700 Subject: [PATCH 26/30] dvc path updates --- samples/b2fgmtry.dvc | 4 ++-- samples/b2mn.dat.dvc | 4 ++-- samples/b2time.nc.dvc | 4 ++-- samples/edge_profiles.h5.dvc | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/samples/b2fgmtry.dvc b/samples/b2fgmtry.dvc index a92eca2..0701492 100644 --- a/samples/b2fgmtry.dvc +++ b/samples/b2fgmtry.dvc @@ -1,10 +1,10 @@ -md5: bf96c041599ce04799130f3e0dd34d3f +md5: bcf05d7d7b6d91ef1025c0dc018c4bbf frozen: true deps: - path: ITER_Lore_2296_00000/baserun/b2fgmtry repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git - rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 + rev_lock: df499f1275428ec06175c48dc4af6ecbd5ec6117 outs: - md5: 6589953daeef49b21744d159af970cbb size: 2908856 diff --git a/samples/b2mn.dat.dvc b/samples/b2mn.dat.dvc index 018dfbc..e13ac93 100644 --- a/samples/b2mn.dat.dvc +++ b/samples/b2mn.dat.dvc @@ -1,10 +1,10 @@ -md5: ab8eafd069e624c2e00e6156be881d4a +md5: c0c920771883f03bc0abe98425b38d5e frozen: true deps: - path: ITER_Lore_2296_00000/run_time_dep_EIRENE_jdl_to_ss_cont_sine2_2d_output/b2mn.dat repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git - rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 + rev_lock: df499f1275428ec06175c48dc4af6ecbd5ec6117 outs: - md5: 1af9d167996ea1a420f49e0d89c98e6d size: 13925 diff --git a/samples/b2time.nc.dvc b/samples/b2time.nc.dvc index 5139eeb..b4a7624 100644 --- a/samples/b2time.nc.dvc +++ b/samples/b2time.nc.dvc @@ -1,11 +1,11 @@ -md5: 14431f8773812c851d7dc95befad39d5 +md5: b94876ee58c5d62734d4ee32c28bb0da frozen: true deps: - path: ITER_Lore_2296_00000/run_time_dep_EIRENE_jdl_to_ss_cont_sine2_2d_output/b2time.nc repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git - rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 + rev_lock: df499f1275428ec06175c48dc4af6ecbd5ec6117 outs: - md5: 778b3bb62b82f493c785373d872f6a1f size: 13630424 diff --git a/samples/edge_profiles.h5.dvc b/samples/edge_profiles.h5.dvc index 02b22ec..4af263a 100644 --- a/samples/edge_profiles.h5.dvc +++ b/samples/edge_profiles.h5.dvc @@ -1,10 +1,10 @@ -md5: fd276c67d8a16214d1e230b6dd6c32c4 +md5: 583339f63b0b4d2aa3f7f7a659a5b07c frozen: true deps: - path: ITER_Lore_2296_00000/IMAS/edge_profiles.h5 repo: url: git@github.com:ProjectTorreyPines/SOLPSTestSamples.git - rev_lock: 35fd24298a4118eec6491dcd17d4e0ec97823e83 + rev_lock: df499f1275428ec06175c48dc4af6ecbd5ec6117 outs: - md5: c3d60ce69e9d3a9b9ec621e9276858e0 size: 168176600 From 701c33e7588bb1371fde487e8e38dd841edd3223 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 29 Sep 2023 16:25:12 -0700 Subject: [PATCH 27/30] Overloading \in for finding point in subset --- src/GGDUtils.jl | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index c5c65e1..955c4a9 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -197,4 +197,57 @@ function project_prop_on_subset!(prop, end end +function Base.:∈( + point::Tuple{Float64, Float64}, + subset_of_space::Tuple{ + OMAS.edge_profiles__grid_ggd___grid_subset, + OMAS.edge_profiles__grid_ggd___space, + }, +) + r, z = point + subset, space = subset_of_space + dim = subset.element[1].object[1].dimension + nodes = space.objects_per_dimension[1].object + edges = space.objects_per_dimension[2].object + if dim == 2 + subset_bnd = OMAS.edge_profiles__grid_ggd___grid_subset() + subset_bnd.element = SOLPS2IMAS.get_subset_boundary(space, subset) + elseif dim == 1 + subset_bnd = subset + elseif dim == 0 + for ele ∈ subset.element + node = nodes[ele.object[1].index] + if node.geometry[1] == r && node.geometry[2] == z + return true + end + end + return false + else + error("Dimension ", dim, " is not supported yet.") + end + count = 0 + for ele ∈ subset_bnd.element + edge = edges[ele.object[1].index] + edge_z_at_r = line_between([nodes[node].geometry for node ∈ edge.nodes]...)(r) + edge_ends = + mapreduce(permutedims, vcat, [nodes[node].geometry for node ∈ edge.nodes]) + if maximum(edge_ends[:, 1]) >= r >= minimum(edge_ends[:, 1]) + if z < edge_z_at_r + count += 1 + end + end + end + if count % 2 == 1 + return true + else + return false + end +end + +function line_between(fp::Vector{Float64}, sp::Vector{Float64}) + slope = (sp[2] - fp[2]) / (sp[1] - fp[1]) + intercept = fp[2] - slope * fp[1] + return (x::Float64) -> slope * x + intercept +end + end # module GGDUtils From a44a3ac085f3db4cd25747efd0bb1bd77640d5f3 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Fri, 29 Sep 2023 18:11:23 -0700 Subject: [PATCH 28/30] Adding get_prop_with_grid_subset_index --- src/GGDUtils.jl | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index 955c4a9..fe62693 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -11,6 +11,8 @@ using ColorSchemes: ColorSchemes export interp export get_kdtree export project_prop_on_subset! +export get_subset_centers +export get_prop_with_grid_subset_index include("recipes.jl") @@ -150,14 +152,9 @@ end function project_prop_on_subset!(prop, from_subset::OMAS.edge_profiles__grid_ggd___grid_subset, - to_subset::OMAS.edge_profiles__grid_ggd___grid_subset) - from_prop = nothing - for p ∈ prop - if p.grid_subset_index == from_subset.identifier.index - from_prop = p - break - end - end + to_subset::OMAS.edge_profiles__grid_ggd___grid_subset, +) + from_prop = get_prop_with_grid_subset_index(prop, from_subset.identifier.index) if isnothing(from_prop) println("from_subset not represented in the property yet") end @@ -250,4 +247,12 @@ function line_between(fp::Vector{Float64}, sp::Vector{Float64}) return (x::Float64) -> slope * x + intercept end +function get_prop_with_grid_subset_index(prop, grid_subset_index::Int64) + for p ∈ prop + if p.grid_subset_index == grid_subset_index + return p + end + end + return nothing +end end # module GGDUtils From 919b1729947e8e440e4255fff2094e4095f1a411 Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 2 Oct 2023 16:13:24 -0700 Subject: [PATCH 29/30] Modified \in, documented better, added tests. --- src/GGDUtils.jl | 40 +++++++++++++++++++++++++++------------- test/runtests.jl | 20 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/GGDUtils.jl b/src/GGDUtils.jl index fe62693..f3a6552 100644 --- a/src/GGDUtils.jl +++ b/src/GGDUtils.jl @@ -4,7 +4,7 @@ import NearestNeighbors: KDTree, knn import StaticArrays: SVector import Statistics: mean using OMAS: OMAS -import SOLPS2IMAS: get_subset_space, get_grid_subset_with_index +import SOLPS2IMAS: get_subset_space, get_grid_subset_with_index, get_subset_boundary using RecipesBase using ColorSchemes: ColorSchemes @@ -194,6 +194,24 @@ function project_prop_on_subset!(prop, end end +""" + Base.:∈( + point::Tuple{Float64, Float64}, + subset_of_space::Tuple{ + OMAS.edge_profiles__grid_ggd___grid_subset, + OMAS.edge_profiles__grid_ggd___space, + }, + +) + +Overloading ∈ operator to check if a point is inside a subset of space. + +If the subset is 0-dimensional, all points are searched. If the subset is 1-dimensional, +it is checked if the point is within the enclosed area. It is assumed that a +1-dimensional subset used in such a context will form a closed area. If the subset is +2-dimensional, its boundary is calculated on the fly. If used multiple times, it is +recommended to calculate the boundary once and store it in a variable. +""" function Base.:∈( point::Tuple{Float64, Float64}, subset_of_space::Tuple{ @@ -208,7 +226,7 @@ function Base.:∈( edges = space.objects_per_dimension[2].object if dim == 2 subset_bnd = OMAS.edge_profiles__grid_ggd___grid_subset() - subset_bnd.element = SOLPS2IMAS.get_subset_boundary(space, subset) + subset_bnd.element = get_subset_boundary(space, subset) elseif dim == 1 subset_bnd = subset elseif dim == 0 @@ -222,18 +240,20 @@ function Base.:∈( else error("Dimension ", dim, " is not supported yet.") end + # Count number of times an upward going ray from (r,z) intersects the boundary count = 0 for ele ∈ subset_bnd.element edge = edges[ele.object[1].index] - edge_z_at_r = line_between([nodes[node].geometry for node ∈ edge.nodes]...)(r) - edge_ends = - mapreduce(permutedims, vcat, [nodes[node].geometry for node ∈ edge.nodes]) - if maximum(edge_ends[:, 1]) >= r >= minimum(edge_ends[:, 1]) - if z < edge_z_at_r + r_max = maximum([nodes[node].geometry[1] for node ∈ edge.nodes]) + r_min = minimum([nodes[node].geometry[1] for node ∈ edge.nodes]) + if r_min <= r < r_max + z_max = maximum([nodes[node].geometry[2] for node ∈ edge.nodes]) + if z < z_max count += 1 end end end + # If it is even, the point is outside the boundary if count % 2 == 1 return true else @@ -241,12 +261,6 @@ function Base.:∈( end end -function line_between(fp::Vector{Float64}, sp::Vector{Float64}) - slope = (sp[2] - fp[2]) / (sp[1] - fp[1]) - intercept = fp[2] - slope * fp[1] - return (x::Float64) -> slope * x + intercept -end - function get_prop_with_grid_subset_index(prop, grid_subset_index::Int64) for p ∈ prop if p.grid_subset_index == grid_subset_index diff --git a/test/runtests.jl b/test/runtests.jl index b397f42..57964e5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -94,3 +94,23 @@ end @test test_interp() @test test_project_prop_on_subset() end + +@testset "test ∈" begin + b2gmtry = "$(@__DIR__)/../samples/b2fgmtry" + b2output = "$(@__DIR__)/../samples/b2time.nc" + gsdesc = "$(@__DIR__)/../samples/gridspacedesc.yml" + b2mn = "$(@__DIR__)/../samples/b2mn.dat" + dd = solps2imas(b2gmtry, b2output, gsdesc, b2mn) + grid_ggd = dd.edge_profiles.grid_ggd[1] + space = grid_ggd.space[1] + subset_corebnd = get_grid_subset_with_index(grid_ggd, 15) + subset_sol = get_grid_subset_with_index(grid_ggd, 23) + subset_odr = get_grid_subset_with_index(grid_ggd, 24) + + @test (6.0, 0.0) ∈ (subset_corebnd, space) + @test (5.0, -2.5) ∉ (subset_corebnd, space) + @test (6.0, 4.0) ∈ (subset_sol, space) + @test (6.0, 3.0) ∉ (subset_sol, space) + @test (5.1, -3.7) ∈ (subset_odr, space) + @test (4.5, -3.7) ∉ (subset_odr, space) +end \ No newline at end of file From 80bbbb40ea71e8eb3332543dba077ec6386450ca Mon Sep 17 00:00:00 2001 From: Anchal Gupta Date: Mon, 2 Oct 2023 16:18:18 -0700 Subject: [PATCH 30/30] Adding newline to end of file. --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 57964e5..5a3fc22 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -113,4 +113,4 @@ end @test (6.0, 3.0) ∉ (subset_sol, space) @test (5.1, -3.7) ∈ (subset_odr, space) @test (4.5, -3.7) ∉ (subset_odr, space) -end \ No newline at end of file +end