From 376f1a5a3bd1dad8da0f85981b29c8b2b19b686f Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Tue, 5 Apr 2016 14:15:09 -0400 Subject: [PATCH] add GridOut::write_mesh_per_processor_as_vtu Writes vtu with values "level", "subdomain", "lvl_subdomain", and "proc_writing". Also combines these into a .pvtu file. The motivation for this function is to visually debug geometric multigrid for parallel computations. Added entry in changes.h --- doc/doxygen/images/write_mesh_vtu_active.png | Bin 0 -> 1184 bytes doc/doxygen/images/write_mesh_vtu_levels.png | Bin 0 -> 1473 bytes doc/news/changes.h | 8 + include/deal.II/grid/grid_out.h | 34 +++ source/grid/grid_out.cc | 102 +++++++ source/grid/grid_out.inst.in | 15 +- tests/grid/grid_out_per_processor_vtu_01.cc | 92 ++++++ ...d_out_per_processor_vtu_01.mpirun=3.output | 278 ++++++++++++++++++ 8 files changed, 527 insertions(+), 2 deletions(-) create mode 100644 doc/doxygen/images/write_mesh_vtu_active.png create mode 100644 doc/doxygen/images/write_mesh_vtu_levels.png create mode 100644 tests/grid/grid_out_per_processor_vtu_01.cc create mode 100644 tests/grid/grid_out_per_processor_vtu_01.mpirun=3.output diff --git a/doc/doxygen/images/write_mesh_vtu_active.png b/doc/doxygen/images/write_mesh_vtu_active.png new file mode 100644 index 0000000000000000000000000000000000000000..13528f75f0dc58d7a26be6e8cb69ac6c52b7b401 GIT binary patch literal 1184 zcmeAS@N?(olHy`uVBq!ia0y~yU@`)-mvS%x$&*11cYqXUfk$L90|U1(2s1Lwnj--e zWH0gbb!C6R!Xv7!z9z8oFaraNy{C&~NX4zUcYU)SI|wvfeC62A#Zj|0FWxud#9EW? zHJdn>oep~ad~fYeTQAT14|=^^c;BVO-d;98-m7?G?v&m|x3?S)`@1oBai3iEuN#ZM zTRi*vX8zpl|36~(FaG~x{ffKw)1TZgdGq6=xz^`$&%ETK#k-ChZ%#h`+5LZT8bhD+ zG=>SPAe6!hLXk{Bl^h>(SmWFF+I3h8&9oA-9<%W#{j<=;1bp56P%NNsw<`D)wW z>CbQ3+g*SE!v2@`FQ6^E^|EWxlF)m0CA zyj)5}^HO7PZ_^H))t$3AN969ZCt*`BLHu*P?z8ZnhwIb-zlr$`wEE>@i1(kzK2x5) zeu`O+s$2e*6(9dxtUJQ|zyZlWXg)=91hUM%Fr`(iH|%fJ_r3q?#oT+R&*e_L>2~+5 zh#+%(nEjg<9W#RUSD(Mrb$$QYyd8m^rN3^j2z>l=aevIdC;tzBdTh2T`A&ZYgG`4G zqk=aB5S$) z`4vZG1B1X~u~1-aYjouGZEwA%K2y5A;(XqfYwi)xoM$R2J(~EVMb&U$kF}N3v;}cgg(QI-dnj+B8o(zdk4`Yi9epBPUYD?mFvzCO7^YwomPNrFF;aS?#g> zwO91sryh4J3`Gux{(sMaasMS|w>-=5I}fAnm;d{5J+)77>D-E$yUnxKoy^@5C~jT# z!=8e809vQBlRuK}?7W||&zl;@dTri)J7(r(z2daRMYlPkQ(jKoJzY*Y?Rekv{yJM@ z{)we;YktJ-OTQcb?D?Yz8diKWt2^S1!7o9tJJLp#5KQYVvXO)uOXOWS1=8d@|5N zf3{3qpV0mGdp2eJpY8n3dj8hw_&l?cFnv#ca@sb4Fn_&O1n*V%je4k+0Qmg2V{tFA1)w{QKqGn}h~ z@&p}`j1-UvIIDJiYuvfV;*L2*Q}!xZrUx@@?||5c>Q-3T|Bdch;PKx*`n~o4$CDQO z`y?#CZ68y0zxHp}dHwyaSDy+_4C?Mz;kVxS3!9H&roe-}hk=F7*-P;C1^WXh)qQ;G zT28ZHE_>nocBV>hze%RS=EUQoSC{XosYp9_BHy6>UIQ!$k%JM<(1Sf~_Ft9-z2p?0 zEdMYmY3a0%j*5^!e85i_GNDgBH0nV6tWGbE)Thc$}d(^wP? zBqllMZ`)L9`9*EMRpUkWdj}Vq1087j{q0w7_Z=az_Y#tlzrGO@M5Ix;4?&3#*=UD^ z0)ypVx#|8jPm(9O**7h7Odu5Mb)Dy%bB`)Z|M|bye4VkbVBpvL=fZcbkH7e4_x)4< zi##)Dm&FK9yyQNA=bRrz`v}F0@T`U6Y?#v*OcdF8?$77vd#0Y%&YiqJ*=NlOAwj|Z zvigSf*YE!|W*$#XI(q-Et`aauA>}+|PeUy`!vRaocx{K|-UeH57Z;n^|0L%v<~_T^ z=S{5U^Ec}y3%WT#MF5IB5jI`ekKxkq>a*lG|NAk&_S#p&kJ87EoI3WD$T-LAMo5~0 zg%ECUp(Retqz2N8X;X2elG3A00o9(JYc^2=^t-#`!!PC{xWt~$(698H1 B4Icmi literal 0 HcmV?d00001 diff --git a/doc/news/changes.h b/doc/news/changes.h index 0965897dc0..68767f7749 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -253,6 +253,14 @@ inconvenience this causes. (Daniel Shapero, 2016/04/19) +
  • New: added function GridOut::write_mesh_per_processor_as_vtu. This allows + the visualization of a parallel finite element mesh that can be seperated into each + processor's owned and ghost cells. It also allows for the visualization of each level + of a multilevel mesh. +
    + (Conrad Clevenger, 2016/04/28) +
  • +
  • Improved: The parallel loops in the deal.II Vector class for vector-vector operations have been revised for performance. This includes adjusting the minimum parallel grain size to 4096 vector entries and using an diff --git a/include/deal.II/grid/grid_out.h b/include/deal.II/grid/grid_out.h index 93b91ddf91..bb9c89dc32 100644 --- a/include/deal.II/grid/grid_out.h +++ b/include/deal.II/grid/grid_out.h @@ -1079,6 +1079,40 @@ public: void write_vtu (const Triangulation &tria, std::ostream &out) const; + /** + * Write triangulation in VTU format for each processor, and add a .pvtu file for + * visualization in Visit or Paraview that describes the collection of VTU files + * as all part of the same simulation. The output is in the form + * filename_without_extension.proc000*.vtu where * is 0,1,...,n_proc-1 and + * filename_without_extension.pvtu. The input view_levels can be + * set as true to view each level of a multilevel method. The input + * include_artificial can be set as true to view the artificial cells for + * each processor. Each .vtu and .pvtu file will have the attributes subdomain, + * level_subdomain, level, and proc_writing. The level value can be used to seperate the + * image into the view of the grid on each level of a multilevel method and the + * proc_writing value can be used to seperate the image into each processor's owned and + * ghost cells. + * This is accomplished by applying the "warp by scalar" filter in paraview + * to each of the values. After opening the .pvtu file of a mesh where the input + * view_levels is set to true, select the "warp by scalar" + * filter. For the "Scalars" input select proc_writing and for the "Normal" input + * enter in 1 0 0, then click Apply. Next select the "warp by scalar" filter again. For the + * "Scalars" input select level and for the "Normal" input enter in 0 1 0, + * then click Apply. This will give you the following image. + * @image html write_mesh_vtu_levels.png + * If the view_levels remains at false, thereby only giving the mesh for the active + * level, it is enough to seperate the image into the views written by different processors. + * This is shown in the following image where the include_artificial input is set as true. + * @image html write_mesh_vtu_active.png + * Note: Depending on the size of the mesh you may need to increase the "Scale Factor" input + * so that each piece does not overlap. + */ + template + void write_mesh_per_processor_as_vtu (const Triangulation &tria, + const std::string &filename_without_extension, + const bool view_levels=false, + const bool include_artificial=false) const; + /** * Write grid to @p out according to the given data format. This function * simply calls the appropriate write_* function. diff --git a/source/grid/grid_out.cc b/source/grid/grid_out.cc index 324b6ea29c..f1d6f9b789 100644 --- a/source/grid/grid_out.cc +++ b/source/grid/grid_out.cc @@ -19,11 +19,14 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -2526,6 +2529,105 @@ void GridOut::write_vtu (const Triangulation &tria, +template +void GridOut::write_mesh_per_processor_as_vtu (const Triangulation &tria, + const std::string &filename_without_extension, + const bool view_levels, + const bool include_artificial) const +{ + std::vector > patches; + const unsigned int n_datasets=4; + std::vector data_names; + data_names.push_back("level"); + data_names.push_back("subdomain"); + data_names.push_back("level_subdomain"); + data_names.push_back("proc_writing"); + + const unsigned int n_q_points = GeometryInfo::vertices_per_cell; + + typename Triangulation::cell_iterator cell, endc; + for (cell=tria.begin(), endc=tria.end(); + cell != endc; ++cell) + { + if (!include_artificial && cell->level_subdomain_id() == + numbers::artificial_subdomain_id) + continue; + if (!view_levels && cell->has_children()) + continue; + + DataOutBase::Patch patch; + patch.data.reinit(n_datasets, n_q_points); + patch.points_are_available = false; + + for (unsigned int vertex=0; vertexvertex(vertex); + patch.data(0,vertex) = cell->level(); + if (!cell->has_children()) + patch.data(1,vertex) = + (double)static_cast(cell->subdomain_id()); + else + patch.data(1,vertex) = -1.0; + patch.data(2,vertex) = + (double)static_cast(cell->level_subdomain_id()); + patch.data(3,vertex) = tria.locally_owned_subdomain(); + } + + for (unsigned int f=0; f::faces_per_cell; ++f) + patch.neighbors[f] = numbers::invalid_unsigned_int; + patches.push_back(patch); + } + + const std::string new_file = (filename_without_extension + ".proc" + + Utilities::int_to_string (tria.locally_owned_subdomain(), 4) + + ".vtu"); + std::ofstream out(new_file.c_str()); + std::vector > vector_data_ranges; + DataOutBase::VtkFlags flags; + DataOutBase::write_vtu (patches, + data_names, + vector_data_ranges, + flags, + out); + //create .pvtu record + if (tria.locally_owned_subdomain() == 0) + { + std::vector filenames; + + //.pvtu needs to reference the files without a relative path because it will be written + //in the same directory. For this, remove any paths from filename. + std::size_t pos = filename_without_extension.find_last_of('/'); + if (pos == std::string::npos) + pos = 0; + else + pos += 1; + for (unsigned int i=0; i > data_out; + data_out.attach_triangulation (tria); + + //We need a dummy vector with the names of the data values in the .vtu files + //in order that the .pvtu contains reference these values + Vector dummy_vector (tria.n_active_cells()); + data_out.add_data_vector (dummy_vector, "level"); + data_out.add_data_vector (dummy_vector, "subdomain"); + data_out.add_data_vector (dummy_vector, "level_subdomain"); + data_out.add_data_vector (dummy_vector, "proc_writing"); + + data_out.build_patches (); + + data_out.write_pvtu_record (pvtu_master, filenames); + } +} + + + unsigned int GridOut::n_boundary_faces (const Triangulation<1> &) const { return 0; diff --git a/source/grid/grid_out.inst.in b/source/grid/grid_out.inst.in index 420ba1d870..c36139e9d2 100644 --- a/source/grid/grid_out.inst.in +++ b/source/grid/grid_out.inst.in @@ -53,8 +53,13 @@ for (deal_II_dimension : DIMENSIONS) std::ostream&) const; template void GridOut::write_vtu (const Triangulation&, - std::ostream&) const; - + std::ostream&) const; + template void GridOut::write_mesh_per_processor_as_vtu + (const Triangulation&, + const std::string&, + const bool, + const bool) const; + template void GridOut::write (const Triangulation &, std::ostream &, const OutputFormat, @@ -83,6 +88,12 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : SPACE_DIMENSIONS template void GridOut::write_vtu (const Triangulation&, std::ostream&) const; + template void GridOut::write_mesh_per_processor_as_vtu + (const Triangulation&, + const std::string&, + const bool, + const bool) const; + template void GridOut::write (const Triangulation &, diff --git a/tests/grid/grid_out_per_processor_vtu_01.cc b/tests/grid/grid_out_per_processor_vtu_01.cc new file mode 100644 index 0000000000..5a505b0952 --- /dev/null +++ b/tests/grid/grid_out_per_processor_vtu_01.cc @@ -0,0 +1,92 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2009 - 2016 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + + + +// check GriOut::write_mesh_per_processor_as_vtu() + +#include "../tests.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +template +void output(const parallel::distributed::Triangulation &tr, + const std::string &filename, + const bool view_levels, + const bool include_artificial) +{ + GridOut out; + out.write_mesh_per_processor_as_vtu(tr, filename, view_levels, include_artificial); + + // copy the .pvtu and .vtu files + // into the logstream + int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD); + if (myid==0) + { + cat_file((std::string(filename) + ".pvtu").c_str()); + cat_file((std::string(filename) + ".proc0000.vtu").c_str()); + } + else if (myid==1) + cat_file((std::string(filename) + ".proc0001.vtu").c_str()); + else if (myid==2) + cat_file((std::string(filename) + ".proc0002.vtu").c_str()); + else + AssertThrow(false, ExcNotImplemented()); +} + +template +void test() +{ + unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD); + if (myid == 0) + deallog << "hyper_cube" << std::endl; + + parallel::distributed::Triangulation tr(MPI_COMM_WORLD, + Triangulation::limit_level_difference_at_vertices, + parallel::distributed::Triangulation::construct_multigrid_hierarchy); + GridGenerator::hyper_cube(tr); + tr.refine_global(3); + DoFHandler dofh(tr); + + output(tr, "file1", false, true); + output(tr, "file2", true, false); +} + + +int main(int argc, char *argv[]) +{ + Utilities::MPI::MPI_InitFinalize mpi_initialization (argc, argv, 1); + + MPILogInitAll init; + + deallog.push("2d"); + test<2>(); + deallog.pop(); +} diff --git a/tests/grid/grid_out_per_processor_vtu_01.mpirun=3.output b/tests/grid/grid_out_per_processor_vtu_01.mpirun=3.output new file mode 100644 index 0000000000..30fb43b736 --- /dev/null +++ b/tests/grid/grid_out_per_processor_vtu_01.mpirun=3.output @@ -0,0 +1,278 @@ + +DEAL:0:2d::hyper_cube + + + + + + + + + + + + + + + + + + + + + + + + +AQAAAGASAABgEgAAbAEAAA==eNqlWDGuQzEI6824eo7AyMiQgSFDjtAp0v9RHYNge65rLEJ5pJ/P3wj59/hR+Y2f2IC/kzou77wb8G/8fN/ltz8H/AD8rM8gfORzN/0gnQ1wFENqn59nhN+h8tYd4NyH9Pyg/Ien0vODdJTgdxjxfec1gt/hJO8AfZutgxG+Ar5Kzw/ScXnXO9sPqK6Hb81+QDoq7/PM+kHnP+SNZ/0gHSV4th9QXiN4th+QjhfrYITvgO9NP0jHCX7HJH1z/+4mwe8IkneA91p2DkzCV8BX6flBOkHwOxap2513EZztZ0xnF+uwCF8BX6XnB+ns4hyYhG+Ab81+QDpRnAOT8B3wvelnkr3am/2A8i6CZ/sB6exiHRbhO+B7088q3neq+wCa64c/m/sA0lF5v0+yftDcHfLGs36G1O7L1X0A5TWCZ/cBpOPFOhjhB+BH048V7+nVeYjyToJn5yHSiWIdJuEH4EfTz0z/H/IFub2Npg== + + + + + +AQAAABADAAAQAwAAPgEAAA==eNoNwwdXiAEAAMBPJVRm9iikZFdGJSuzorI32aPIXmVTMkIkI0KECNmJrP6Yu/cuCIKgg6GGGGZHOxluZ7sYaYRRdrW73exhT6PtZW/72M++9neAgxzoYIcYa4xDHWacwx1hvCNNMNFRjnG0Yx3nBMebZLITTXGSk011immmm+FUpzndmc5wlpnOcbZznecC55tltgvNcZG55pvnYpe4zKUud4WrXOlq17jOta53gwVudJOb3eoWt7ndne5wl7ststA97nWfxe73gIc86GGPeMyjHveEpZZ40lOe8bRnPecFz3vRMi9ZboWXveoVr1npDa970ypve8tq73jXGu9531of+NBHPrbOJz71mfU+t8GXvvCVjb7xtU2+9b3vbPaDn/zoZ7/4za+2+N0ftvrTNn/7yz/+td1//gef8Eqn + + +AQAAAMQAAADEAAAAcwAAAA==eNoNwxEXwmAAAMAPgiAIgiAYBEEQBEEQBINgEAyCYBAEQTAYBMEgCIIgCAZBEARBEOyHdffeNUIITVu27di1Z2TfgUNHjp04debc2IWJS1NXrs3cuHXn3tzCg0dLT569ePXm3cqHT1++/fj1Z+0fFp8TJQ== + + +AQAAADEAAAAxAAAADAAAAA==eNrj5CQRAAArQgG6 + + + + +AQAAACAGAAAgBgAAGwAAAA==eNpjYAADB4ZBTXOM0qP0KD1Kj9J0pgGhvDaB + +AQAAACAGAAAgBgAAMQAAAA==eNpjYACDAwyDmx4Fo2AAwQd7/DSh9Etr/ZTStHY/pTSt/TfY7WdwIEDTLPwBSdZmWQ== + +AQAAACAGAAAgBgAAMQAAAA==eNpjYACDAwyDmx4Fo2AAwQd7/DSh9Etr/ZTStHY/pTSt/TfY7WdwIEDTLPwBSdZmWQ== + +AQAAACAGAAAgBgAAFQAAAA==eNpjYBgFo2AUjIJRMAowAQAGIAAB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +AQAAAKARAACgEQAASwEAAA==eNqtVjsSBSEI25vl6h6BkpLCwmKLPcKrbHwTPoN2xmzIALI+j7c+PKXzvY++28tQO997hmf9M50Pvl7WD4tv8PGsH6ZTzb+gdr73DM/Wl+kYfL2sHxZf4ONZP4I7/bkC32fcFeDZ/mc6XzEPK+Ab4Rt6ftal+yuo1WfzV7MfmI4FeDafTGfB75dzDdTO957h2fnDdAS+XtYPiz/g41k/A3fmpwa+z7ga4Nn5zHSsmAcN+EL4gp4fvfR/GajVZ/O12Q9MR+DXM+uH1X/Ax7N+Bu78fzXImxK+NvuB6VgxDxrwjfCt6UcvvU9m0DfnvZsBnn3/MJ1VnAMz4AvhC3p+5qX32xvk7Yz7Fn1GfCF8aeaT9e0M8Gw+mc4q3qMZ8I3wrZlP5vO9NM/Zvdz82ZznTEcCPDsPmY4GeHYeMh0L8Gw/MJ35h/8AciNj+g== + + + + + +AQAAAPACAADwAgAAMgEAAA==eNoNwwdXDgAAAMAvSipbA9krUdlKSZnZMlIqpBAiyiqjRMosM4RoWaGyEn/O3XsXCAQCQQ51iMGGGOowhxtmhOGOcKSjHeUYxzrecUYaZYzRTnCisU5yslOc5lSnO8NZznS2c4xzrvOMd4HzTTDRhSa5yMUudYnLXG6yK0xxpWmmusp0M1xtpmtc51rXu8EsN7rJzW51i9vc7k53mO0u97jbveaY6z7z3G+B+RZ6wEMetMjDlljsEY9a6jGPe8IyT3rK056x3LNWeM5Kz3vBS160ymqveNmrXrPWGq9b501vWO8tG23wtne8513v+8Bmm3zoI5/42Kc+87ktvvClr2z1tW98a5vvbLfTDrvs9oPv/egne/zsF7/a6zf77PeH3/3pLwf87R8H/edf/wOe8USr + + +AQAAALwAAAC8AAAAbwAAAA==eNoNwxEXwmAAAMAPgiAIgiAIBkEQBIMgCIJgMBgEwSAIBkEwGARBEATBIAiCYBAE/bjdvXedEELXnn0HDh05NnLi1JlzYxcuXbl2Y2Jq5taduXsPFh49WVp59uLVm3cf1j59+fZj49eff1uAeBGh + + +AQAAAC8AAAAvAAAADAAAAA==eNrj5CQJAAAn1wGo + + + + +AQAAAOAFAADgBQAAHgAAAA==eNpjYCAGfLAfWJrBYZSmJc0xSo/So/QwpAFNQ0DR + +AQAAAOAFAADgBQAAIgAAAA==eNpjYACBD/sZRukRTI+CUTCQ4IP9KE0JzeCAiwYAjdmcGQ== + +AQAAAOAFAADgBQAAKAAAAA==eNpjYKAH+GCPn2ZwIEAPckDIfwNND/XwHQXDGwz2/DN08zcABbROwQ== + +AQAAAOAFAADgBQAAFAAAAA==eNpjYBgFo2AUjIJRMBwBAAXgAAE= + + + + + + + + + + + + + +AQAAAMAVAADAFQAAqgEAAA==eNqlmDGSxSAMQ3MzX50jUFK6oKCg4AhbUSy7D5mxmz/R18gaxzFOvu8W1b6n//f1iQ/7/btjAb6vF/CXxXw2u/su9j+f8DNc5D11HPBXP1TnJvCoH9Jxu9f7xIu93Z/Nb0EdqgPpVLvfz6gfuv+b70k/pFMFHu0HytsEHu0H0vHHOjTBd+B70g/puMDP6KJvzueuC/yMIfIWmKvROdAFvwK/Ws5PF+cI4WdMUbcz7xT4GUvkLXB+ReswBb8Cv1rOD+msxznQBb8BvyX7gXTG4xzogu/A96Qf0hkCj/YD5Z0Cj/YD6azHOkzBd+B70g/pLLvP++g+QHN983tyHyCdavfzJOqH5m6xOx71QzpV4NF9gPI2gUf3AdLxxzo0wR/AH0k/pON2P2+j/UDn6ubPZD+QTrX7eR71Q+d/sTse9VPEe+5K9gPlbQKP9gPp+GMdmuAv4K+kH9JxgUf3AXruusCj+wDpjMc50AV/AH8k/XTxXWgk9wHKOwUe3QdIZz3WYQr+AP5I+pmP3+te+4Geuy7waD+QznicA13wF/BX0g/p/P0u+gPINeP8 + + + + + +AQAAAKADAACgAwAAbgEAAA==eNoNwwN3FgAAAMAvm1vLtm1sGYuLW9aytYxlrsWFLbfslm1by/wb3b13gUAgkMZ0pjW9GcxkRjObxWxmNbs5zGVOc5vHIPMabD7zG2IBC1rYQhaxqMUtZglLWtpSlrGs5S1nBSta2UpWsarVrWYNa1rbWtaxrvWtZwMb2thGNrGpoTYzzOa2tIWtbG1b29jO9obbwY52soud7Wo3uxthD3va2172MdK+RtnP/g50gIMc7FCHOMzhjjDakY5yjKMd6zgnON6JTnKKk53qNGc43RhnOttZznGu853nAhca6yIXu8RlLnW5K1zlSle7xnWuNc71bjDejW5yi5vdaoLb3eYOd5pkorvc7V73uM/9HvSAyR7yiIc96jFPeNyTnvKMpz3rOVM87wUvetlLXvGq173mDW9621ve8a73vecDH/rYRz7xqc995gtf+tpXvvGt733nBz+a6ic/+8VvfvW7P/zlT3/7x3/+9T8SCWit + + +AQAAAOgAAADoAAAAhAAAAA==eNoNw6ESAVEAAMAXBEEQBEEQBEEQBEEQBEEQBEEQBEEQBOGCIAiCIAiCIAiCIAiCIAiCIAiCIPgMuzMbCyHETZg0ZdqMWXPmLVi0ZNmKVWvWbdi0ZduOXXv2HTh05NjIiVNnzl24dOXajVt37j149OTZi1dv3n349OXbj19//gFcIBq9 + + +AQAAADoAAAA6AAAADAAAAA==eNrj5CQXAAA8YQIL + + + + +AQAAAEAHAABABwAAHQAAAA==eNpjYAADBwaKaI5RepQepUfpUXqUHlE0ABj2QQE= + +AQAAAEAHAABABwAANQAAAA==eNpjYACDAwyDmyYEaG0+pfbTGgyw/R/sR+lReuTSDA40pgnl76FuP6XlN63Nx0kDAIRbqqE= + +AQAAAEAHAABABwAANQAAAA==eNpjYACDAwyDmyYEaG0+pfbTGgyw/R/sR+lReuTSDA40pgnl76FuP6XlN63Nx0kDAIRbqqE= + +AQAAAEAHAABABwAAHQAAAA==eNpjYACBD/YMo/QoPUqP0qP0KD1KE00DAEonEqg= + + + + + + + + + + + + +AQAAAOAWAADgFgAAqQEAAA==eNqtlzG27iAIhP+dsXWXQElpQUFh4RJu82zyzjhwMF3Il3FCIJjf73Zs+ZWun3N23zmm1K6fcxTP+kc6W+56WT9o/Sn3eNYP0kH5V6nl//AK1lVyH9NB66vc41k/Km/qJ4jv77pB4tn6RDq7mIcg/AT8lJ6feNRfKrX3c/ho1gPSmXJ/n1k/6P0r6d+sH5U3358geQvAR7MekM4u5iEIvwH/jdu/8wF0BuCr30/7xI+uJftlyD1uoE4sqYP6qPq8BtadRZ9GeORzNv1Y8XvixfnioK6iWIdOeAW8Ss+PP5qPi+Ttu+4i8ez8RTq7mIdFeAW8Ss/PerR/cMIb4K1ZD0gnin3qhEd9Opt+/NH+apG8GeCtWQ9IZxfzsAg/AT+bftaj/ecgvAPem/MU6ajc50nWD/ruDrnHs36GvNmfG8mbA96b8xrpzGIejPAB+Gj6sUf/L0Nq8/nwq1kPSEflPs+zftD8H3KPZ/0MefN/ZyRvC/CrWQ9IZxbzYIRH/1m7Oa9RXziJZ+c10olinzrhA/DRnKfI5yLx7DxFOvvR86I69P/ifwI48yA= + + + + + +AQAAANADAADQAwAAewEAAA==eNoNwwN3FgAAAMAv23Zr2bZrLdu2bWMLa9m2bdu2bbv+QHfvXSAQCEQxmlGNbgxjGdPYxjGecY1vAhOZ0MQmMZlJTW4KU5nS1KYxnWlNbwYzmdHMBhlsFrOazRxmN6e5zGNu85rPAua3oIUsYmGLWswSFrekpSxjactazgqWt6KVrGJlqxpiqNWsbg1rWdPa1rGeda1vAxvZ0MY2sZlNbW4LW9nS1raxnW1tbwc72dHOdrGbXe1uD3vZ0972sZ997e8ABznQwQ5xmEMd7ghHOdLRjnGcYx3vBMMNc6KTnOJkI5zqNCOd7gxnOdPZznGec53vAhe50MUucZlLXe4KV7nS1a5xnWtd7wY3udHNbnGbW93uDne5093ucZ973e8BD3nQwx7xmEc97glPedLTnvGcZz3vBS950cte8ZpXve4Nb3nT297xnne97wMf+dDHPvGZT33uC1/50te+8Z1vfe8HP/nRz37xm1/97g9/+dPf/vGff/0P0ulzzw== + + +AQAAAPQAAAD0AAAAiQAAAA==eNoNw6ESQQEAALAXBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQBEEQfIDtbqEgCMJGjBozbsKkKdNmzJozb8GiJctWrFqzbsOmLdt27Nqz78ChI8dOnDpz7sKlK9du3Lpz78GjJ89evHrz7sOnL99+/PrzD7NrHY0= + + +AQAAAD0AAAA9AAAADAAAAA==eNrj5KQAAABCuAIm + + + + +AQAAAKAHAACgBwAAIgAAAA==eNpjYCAGfLAfWJrBYZQeyjTHKD1Kj9Kj9ChNIg0AU5ZQMQ== + +AQAAAKAHAACgBwAAJQAAAA==eNpjYACBD/sZRulRmmb0KMAPPtiP0qP0yKUZHEZp7DQAAc/6lQ== + +AQAAAKAHAACgBwAALQAAAA==eNpjYKAH+GCPn2ZwIEAPMCDk/sFOEwxfWtOjYFinr1F6lB7S5dOgpQEhaaDF + +AQAAAKAHAACgBwAAHQAAAA==eNpjYACBD/YMo/QoPUqP0qP0KD1KDxoaANQSINw= + + + + + + + + + + + + + + +AQAAAGASAABgEgAAXAEAAA==eNqlljGywzAIRH0zXf0fwSWlChUUKjhCKjf687QwqMv6ZdkhmOh5bucdT+n595n088xx9z2/N8fdL5uH6n/cHLmcLnzPui7084Soe/rEqPXBBG/AW9JniroGvDXz0O9oQs/mMTEnM9mHJfpmwFvSx0VdA96aeagPS+jZPOTjQj/7sEXfDHhL+oSoa8BbMw/1YQs9m4d8Ytz35an/CX4Bv5I+tAfI5wW9mof2+sd7Mw/5vELP7kOqa0LP7kPymcU+mOAdeG/mIZ857v/n2Xk437OT3815IJ8X9Goeur98fDTzkM8r9Ow8UF0TenYeyGcW+2CCD+CjmYd8ptCz9wF675bQs/cB8vHiHliCd+C9mYd8XOjZ+wDV3ULP3gfIJ4p92IJ34L2Zh3yiuAeW4DfwuzkP5OPFPbAEH8BHMw/5uNCz80B1t9Cz80A+UezDFnwAH8085BP/9B+M/6Hc + + + + + +AQAAABADAAAQAwAAPgEAAA==eNoNwwdXiAEAAMBPJVRm9iikZFdGJSuzorI32aPIXmVTMkIkI0KECNmJrP6Yu/cuCIKgg6GGGGZHOxluZ7sYaYRRdrW73exhT6PtZW/72M++9neAgxzoYIcYa4xDHWacwx1hvCNNMNFRjnG0Yx3nBMebZLITTXGSk011immmm+FUpzndmc5wlpnOcbZznecC55tltgvNcZG55pvnYpe4zKUud4WrXOlq17jOta53gwVudJOb3eoWt7ndne5wl7ststA97nWfxe73gIc86GGPeMyjHveEpZZ40lOe8bRnPecFz3vRMi9ZboWXveoVr1npDa970ypve8tq73jXGu9531of+NBHPrbOJz71mfU+t8GXvvCVjb7xtU2+9b3vbPaDn/zoZ7/4za+2+N0ftvrTNn/7yz/+td1//gef8Eqn + + +AQAAAMQAAADEAAAAcwAAAA==eNoNwxEXwmAAAMAPgiAIgiAYBEEQBEEQBINgEAyCYBAEQTAYBMEgCIIgCAZBEARBEOyHdffeNUIITVu27di1Z2TfgUNHjp04debc2IWJS1NXrs3cuHXn3tzCg0dLT569ePXm3cqHT1++/fj1Z+0fFp8TJQ== + + +AQAAADEAAAAxAAAADAAAAA==eNrj5CQRAAArQgG6 + + + + +AQAAACAGAAAgBgAAGwAAAA==eNpjYAADB4ZBTXOM0qP0KD1Kj9J0pgGhvDaB + +AQAAACAGAAAgBgAALAAAAA==eNpjYACDAwwjmyYEKDT/gz1l9FC3n1L30dp/tLafYv0Oo/QoPRA0AEm6eVk= + +AQAAACAGAAAgBgAALAAAAA==eNpjYACDAwwjmyYEKDT/gz1l9FC3n1L30dp/tLafYv0Oo/QoPRA0AEm6eVk= + +AQAAACAGAAAgBgAAGQAAAA==eNpjYAADB4ZRepQepUfpUXqURqIBi9sxAQ== + + + + + + + + + + + + +AQAAAKARAACgEQAARwEAAA==eNqtljESxDAIA/Mzf/2e4NIlBQUFBU+4ykU8owgGp8nE2ROKjhA/z9cR4ynd39fsd/uQUbu/r9F61j/SifGtl/WD6sv4Xs/6QToo/zne51NnAr6a/6ljpK4AXpI6Qep2/99JeAO8NfNEOgLWq35Qf07SP1k/c9zpfyO5GeCt2Q9IJ4o5GOED8NH0Y8X5sMb7fPpcgK/Oh1NHSV0BvCR1jNStzp9Tx0ldAbwkdYLUzfbzb7yf+3xPFfDZeVLthwXqStHnIjzyaU0/qzgHqnlu3gHvl/ju/F/kuRzw3swT6Ugxh0V4NCej6Wdd+j4qee8U8Nqch0jHiu+REt4Ab00/emn/4CQ3Bbw25znSiWIOTngDvDX9+KX9lRLeAe/NfkA6VpwDSvgAfDT96KX9p5PcHPDe7AekE8UcnPAB+Gj68fT+/A9ohZjI + + + + + +AQAAAPACAADwAgAAMgEAAA==eNoNwwdXDgAAAMAvSipbA9krUdlKSZnZMlIqpBAiyiqjRMosM4RoWaGyEn/O3XsXCAQCQQ51iMGGGOowhxtmhOGOcKSjHeUYxzrecUYaZYzRTnCisU5yslOc5lSnO8NZznS2c4xzrvOMd4HzTTDRhSa5yMUudYnLXG6yK0xxpWmmusp0M1xtpmtc51rXu8EsN7rJzW51i9vc7k53mO0u97jbveaY6z7z3G+B+RZ6wEMetMjDlljsEY9a6jGPe8IyT3rK056x3LNWeM5Kz3vBS160ymqveNmrXrPWGq9b501vWO8tG23wtne8513v+8Bmm3zoI5/42Kc+87ktvvClr2z1tW98a5vvbLfTDrvs9oPv/egne/zsF7/a6zf77PeH3/3pLwf87R8H/edf/wOe8USr + + +AQAAALwAAAC8AAAAbwAAAA==eNoNwxEXwmAAAMAPgiAIgiAIBkEQBIMgCIJgMBgEwSAIBkEwGARBEATBIAiCYBAE/bjdvXedEELXnn0HDh05NnLi1JlzYxcuXbl2Y2Jq5taduXsPFh49WVp59uLVm3cf1j59+fZj49eff1uAeBGh + + +AQAAAC8AAAAvAAAADAAAAA==eNrj5CQJAAAn1wGo + + + + +AQAAAOAFAADgBQAAHgAAAA==eNpjYCAGfLAfWJrBYZSmJc0xSo/So/QwpAFNQ0DR + +AQAAAOAFAADgBQAAIgAAAA==eNpjYACBD/sZRukRTBMCH+xHaUpoBodRepQeCBoAveCvGQ== + +AQAAAOAFAADgBQAAKAAAAA==eNpjYKAH+GCPn2ZwIEBTaP5A0wT9N9D0EA/f0fgfpUdpbDQAAW5lwQ== + +AQAAAOAFAADgBQAAGAAAAA==eNpjYAADB4ZRepQepUfpUXpY0QCQ5y8B + + + + + + -- 2.39.5