Commit 734a9868 authored by Dmitry Yu. Naumov's avatar Dmitry Yu. Naumov
Browse files

Merge branch 'ChemicalBC' into 'master'

[CL] Solution dependent Dirichlet boundary condition

See merge request !3085
parents f2d152d1 b514b165
Pipeline #1448 passed with stages
in 118 minutes and 8 seconds
......@@ -62,6 +62,13 @@ public:
// A hook added for solution dependent dirichlet
}
virtual void postTimestep(const double /*t*/,
std::vector<GlobalVector*> const& /*x*/,
int const /*process_id*/)
{
// A hook added for solution dependent dirichlet
}
virtual ~BoundaryCondition() = default;
};
......
......@@ -63,6 +63,15 @@ public:
}
}
void postTimestep(const double t, std::vector<GlobalVector*> const& x,
int const process_id)
{
for (auto const& bc_ptr : _boundary_conditions)
{
bc_ptr->postTimestep(t, x, process_id);
}
}
private:
mutable std::vector<NumLib::IndexValueVector<GlobalIndexType>> _dirichlet_bcs;
std::vector<std::unique_ptr<BoundaryCondition>> _boundary_conditions;
......
......@@ -21,6 +21,7 @@
#include "PhaseFieldIrreversibleDamageOracleBoundaryCondition.h"
#include "PrimaryVariableConstraintDirichletBoundaryCondition.h"
#include "RobinBoundaryCondition.h"
#include "SolutionDependentDirichletBoundaryCondition.h"
#include "VariableDependentNeumannBoundaryCondition.h"
#include "BaseLib/TimeInterval.h"
......@@ -114,6 +115,12 @@ std::unique_ptr<BoundaryCondition> createBoundaryCondition(
config.config, config.boundary_mesh, dof_table, variable_id,
*config.component_id, parameters);
}
if (type == "SolutionDependentDirichlet")
{
return ProcessLib::createSolutionDependentDirichletBoundaryCondition(
config.config, config.boundary_mesh, dof_table, variable_id,
*config.component_id, parameters);
}
if (type == "HCNonAdvectiveFreeComponentFlowBoundary")
{
return createHCNonAdvectiveFreeComponentFlowBoundaryCondition(
......
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "SolutionDependentDirichletBoundaryCondition.h"
#include <memory>
#include <vector>
#include "BaseLib/ConfigTree.h"
#include "BaseLib/Logging.h"
#include "DirichletBoundaryConditionAuxiliaryFunctions.h"
#include "MeshLib/Mesh.h"
#include "NumLib/DOF/LocalToGlobalIndexMap.h"
#include "ParameterLib/Utils.h"
namespace ProcessLib
{
SolutionDependentDirichletBoundaryCondition::
SolutionDependentDirichletBoundaryCondition(
ParameterLib::Parameter<double> const& parameter,
MeshLib::Mesh const& bc_mesh,
NumLib::LocalToGlobalIndexMap const& dof_table_bulk,
int const variable_id, int const component_id)
: _bc_mesh(bc_mesh), _variable_id(variable_id), _component_id(component_id)
{
checkParametersOfDirichletBoundaryCondition(_bc_mesh, dof_table_bulk,
_variable_id, _component_id);
std::vector<MeshLib::Node*> const& bc_nodes = bc_mesh.getNodes();
MeshLib::MeshSubset bc_mesh_subset(_bc_mesh, bc_nodes);
// Create local DOF table from the BC mesh subset for the given variable
// and component id.
_dof_table_boundary.reset(dof_table_bulk.deriveBoundaryConstrainedMap(
variable_id, {component_id}, std::move(bc_mesh_subset)));
std::string const property_name = "solution_dependent_bc";
if (bc_mesh.getProperties().existsPropertyVector<double>(property_name))
{
OGS_FATAL(
"Found mesh property '{:s}' which is the built-in property of the "
"class SolutionDependentDirichletBoundaryCondition.",
property_name);
}
auto& solution_dependent_bc = *MeshLib::getOrCreateMeshProperty<double>(
const_cast<MeshLib::Mesh&>(bc_mesh), property_name,
MeshLib::MeshItemType::Node, 1);
solution_dependent_bc.resize(bc_mesh.getNumberOfNodes());
ParameterLib::SpatialPosition pos;
auto const& nodes = bc_mesh.getNodes();
for (std::size_t i = 0; i < solution_dependent_bc.size(); ++i)
{
auto const id = nodes[i]->getID();
pos.setNodeID(id);
solution_dependent_bc[i] = parameter(0, pos)[0];
}
_parameter = std::make_unique<ParameterLib::MeshNodeParameter<double>>(
property_name, bc_mesh, solution_dependent_bc);
}
void SolutionDependentDirichletBoundaryCondition::getEssentialBCValues(
double const t, GlobalVector const& x,
NumLib::IndexValueVector<GlobalIndexType>& bc_values) const
{
getEssentialBCValuesLocal(*_parameter, _bc_mesh, _bc_mesh.getNodes(),
*_dof_table_boundary, _variable_id, _component_id,
t, x, bc_values);
}
void SolutionDependentDirichletBoundaryCondition::postTimestep(
double const /*t*/, std::vector<GlobalVector*> const& x,
int const process_id)
{
auto& solution_dependent_bc =
*const_cast<MeshLib::Properties&>(_bc_mesh.getProperties())
.getPropertyVector<double>("solution_dependent_bc");
auto const& nodes = _bc_mesh.getNodes();
for (std::size_t i = 0; i < solution_dependent_bc.size(); ++i)
{
auto const id = nodes[i]->getID();
auto const global_index = _dof_table_boundary->getGlobalIndex(
{_bc_mesh.getID(), MeshLib::MeshItemType::Node, id}, _variable_id,
_component_id);
assert(global_index >= 0);
solution_dependent_bc[i] = x[process_id]->get(global_index);
}
}
std::unique_ptr<SolutionDependentDirichletBoundaryCondition>
createSolutionDependentDirichletBoundaryCondition(
BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh,
NumLib::LocalToGlobalIndexMap const& dof_table_bulk, int const variable_id,
int const component_id,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters)
{
DBUG(
"Constructing SolutionDependentDirichletBoundaryCondition from "
"config.");
//! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__type}
config.checkConfigParameter("type", "SolutionDependentDirichlet");
auto& initial_value_parameter = ParameterLib::findParameter<double>(
//! \ogs_file_param{prj__process_variables__process_variable__boundary_conditions__boundary_condition__SolutionDependentDirichlet__initial_value_parameter}
config.getConfigParameter<std::string>("initial_value_parameter"),
parameters, 1, &bc_mesh);
// In case of partitioned mesh the boundary could be empty, i.e. there is no
// boundary condition.
#ifdef USE_PETSC
// This can be extracted to createBoundaryCondition() but then the config
// parameters are not read and will cause an error.
// TODO (naumov): Add a function to ConfigTree for skipping the tags of the
// subtree and move the code up in createBoundaryCondition().
if (bc_mesh.getDimension() == 0 && bc_mesh.getNumberOfNodes() == 0 &&
bc_mesh.getNumberOfElements() == 0)
{
return nullptr;
}
#endif // USE_PETSC
return std::make_unique<SolutionDependentDirichletBoundaryCondition>(
initial_value_parameter, bc_mesh, dof_table_bulk, variable_id,
component_id);
}
} // namespace ProcessLib
/**
* \file
* \copyright
* Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include "BoundaryCondition.h"
#include "ParameterLib/MeshNodeParameter.h"
namespace ProcessLib
{
/// The SolutionDependentDirichletBoundaryCondition belongs to the
/// Dirichlet-type boundary condition.
///
/// This class is a special category of Dirichlet boundary condition,
/// applied in the situation where the value assigned for the boundary condition
/// is dependent on the process solution of the last time step. This particular
/// boundary condition is widely used in the reactive transport problems and has
/// the potential to be used in other processes.
class SolutionDependentDirichletBoundaryCondition final
: public BoundaryCondition
{
public:
SolutionDependentDirichletBoundaryCondition(
ParameterLib::Parameter<double> const& parameter,
MeshLib::Mesh const& bc_mesh,
NumLib::LocalToGlobalIndexMap const& dof_table_bulk,
int const variable_id, int const component_id);
void getEssentialBCValues(
double const t, GlobalVector const& x,
NumLib::IndexValueVector<GlobalIndexType>& bc_values) const override;
/// Renchao: The original idea to place the update of the boundary condition
/// value at the preTimestep stage. The update could be achieved within the
/// class function "Process::preTimestep". Whereas, I find it not doable to
/// implement in this way. The class function "Process::preTimestep" is
/// called in a row by the functions "preTimestepForAllProcesses" and
/// "TimeLoop::outputSolutions". These two functions are called when
/// initializing and subsequently looping over the "TimeLoop". Actually, it
/// is not intended to make the boundary condition value updated in the
/// first loop. Instead, the update is intended to start from the second
/// loop. For these two reasons, I think it more proper to do the
/// implementation at the postTimestep stage.
void postTimestep(double const /*t*/,
std::vector<GlobalVector*> const& x,
int const process_id) override;
private:
MeshLib::Mesh const& _bc_mesh;
int const _variable_id;
int const _component_id;
std::unique_ptr<NumLib::LocalToGlobalIndexMap const> _dof_table_boundary;
std::unique_ptr<ParameterLib::MeshNodeParameter<double>> _parameter;
};
std::unique_ptr<SolutionDependentDirichletBoundaryCondition>
createSolutionDependentDirichletBoundaryCondition(
BaseLib::ConfigTree const& config, MeshLib::Mesh const& bc_mesh,
NumLib::LocalToGlobalIndexMap const& dof_table_bulk, int const variable_id,
int const component_id,
std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const&
parameters);
} // namespace ProcessLib
......@@ -384,6 +384,8 @@ void Process::postTimestep(std::vector<GlobalVector*> const& x, const double t,
for (auto* const solution : x)
MathLib::LinAlg::setLocalAccessibleVector(*solution);
postTimestepConcreteProcess(x, t, delta_t, process_id);
_boundary_conditions[process_id].postTimestep(t, x, process_id);
}
void Process::postNonLinearSolver(GlobalVector const& x, const double t,
......
......@@ -438,8 +438,8 @@
<boundary_conditions>
<boundary_condition>
<mesh>1d_isofrac_upstream</mesh>
<type>Dirichlet</type>
<parameter>c_Synthetica</parameter>
<type>SolutionDependentDirichlet</type>
<initial_value_parameter>c_Synthetica</initial_value_parameter>
</boundary_condition>
</boundary_conditions>
</process_variable>
......
<?xml version="1.0"?>
<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64" compressor="vtkZLibDataCompressor">
<UnstructuredGrid>
<FieldData>
<DataArray type="Int8" Name="OGS_VERSION" NumberOfTuples="19" format="appended" RangeMin="45" RangeMax="103" offset="0" />
<DataArray type="Float64" Name="Productc" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="60" />
<DataArray type="Float64" Name="Productd" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="140" />
<DataArray type="Float64" Name="Producte" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="220" />
<DataArray type="Float64" Name="pe" NumberOfTuples="400" format="appended" RangeMin="4" RangeMax="4" offset="300" />
<DataArray type="Int8" Name="OGS_VERSION" NumberOfTuples="41" format="appended" RangeMin="45" RangeMax="121" offset="0" />
<DataArray type="Float64" Name="Productc" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="112" />
<DataArray type="Float64" Name="Productd" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="212" />
<DataArray type="Float64" Name="Producte" NumberOfTuples="400" format="appended" RangeMin="1e-06" RangeMax="1e-06" offset="312" />
<DataArray type="Float64" Name="pe" NumberOfTuples="400" format="appended" RangeMin="4" RangeMax="4" offset="412" />
</FieldData>
<Piece NumberOfPoints="201" NumberOfCells="200" >
<PointData>
<DataArray type="Float64" Name="H" format="appended" RangeMin="1e-07" RangeMax="1e-07" offset="372" />
<DataArray type="Float64" Name="Synthetica" format="appended" RangeMin="0" RangeMax="0" offset="436" />
<DataArray type="Float64" Name="Syntheticb" format="appended" RangeMin="0" RangeMax="0" offset="488" />
<DataArray type="Float64" Name="darcy_velocity" format="appended" RangeMin="0" RangeMax="0" offset="540" />
<DataArray type="Float64" Name="pressure" format="appended" RangeMin="1" RangeMax="1" offset="592" />
<DataArray type="Float64" Name="H" format="appended" RangeMin="1e-07" RangeMax="1e-07" offset="504" />
<DataArray type="Float64" Name="Synthetica" format="appended" RangeMin="0" RangeMax="0" offset="588" />
<DataArray type="Float64" Name="Syntheticb" format="appended" RangeMin="0" RangeMax="0" offset="660" />
<DataArray type="Float64" Name="darcy_velocity" format="appended" RangeMin="0" RangeMax="0" offset="732" />
<DataArray type="Float64" Name="pressure" format="appended" RangeMin="1" RangeMax="1" offset="804" />
</PointData>
<CellData>
<DataArray type="Int32" Name="MaterialIDs" format="appended" RangeMin="0" RangeMax="0" offset="652" />
<DataArray type="Int32" Name="MaterialIDs" format="appended" RangeMin="0" RangeMax="0" offset="884" />
</CellData>
<Points>
<DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0" RangeMax="0.5" offset="700" />
<DataArray type="Float64" Name="Points" NumberOfComponents="3" format="appended" RangeMin="0" RangeMax="0.5" offset="952" />
</Points>
<Cells>
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="2284" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="2812" />
<DataArray type="UInt8" Name="types" format="appended" RangeMin="" RangeMax="" offset="3304" />
<DataArray type="Int64" Name="connectivity" format="appended" RangeMin="" RangeMax="" offset="2556" />
<DataArray type="Int64" Name="offsets" format="appended" RangeMin="" RangeMax="" offset="3104" />
<DataArray type="UInt8" Name="types" format="appended" RangeMin="" RangeMax="" offset="3616" />
</Cells>
</Piece>
</UnstructuredGrid>
<AppendedData encoding="base64">
_AQAAAACAAAATAAAAGwAAAA==eF4z0zPWM9K1sNRNNzCyTDFLM7AwBQApcwRiAQAAAACAAACADAAAKQAAAA==eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAACAAACADAAAKQAAAA==eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAACAAACADAAAKQAAAA==eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAACAAACADAAAIwAAAA==eF7txTENAAAIA7BJQBL+VS2I4GufJmc2tm3btv18ARw0fQE=AQAAAACAAABIBgAAHgAAAA==eF7zWL9n1qfrVXYeo/QoPUqP0qP0KE0GDQDk38XsAQAAAACAAABIBgAAFQAAAA==eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAACAAABIBgAAFQAAAA==eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAACAAABIBgAAFQAAAA==eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAACAAABIBgAAGwAAAA==eF5jYACBD/YMo/QoPUqP0qP0KE0GDQBOJu3oAQAAAACAAAAgAwAAEAAAAA==eF5jYBgFo2AU4AIAAyAAAQ==AQAAAACAAADYEgAAkAQAAA==eF591n1MVXUcx3GjWEANnWKbOZmLaIBJaMRyhdUGSrCk66Cn6x+wgTMzlEayoJwubmoTFC1M0iKvChRXRYwHA6V7CcQgkJAHH9CLw26iM61buQr7fe6fvbfOn6+xe875ft+/MyZN+r/r0jP/lYafHYvdBVnwXp/nwa+MFI1bGtfBJ3x/XwTPytplrs3wHN/vlMAvz2kMtY2XwjM9+v2P4F/ts6+JD9oJ92bovrvgybO2Or0Ru+HTzup5PoPXpMQHDdor4CVRes4v4NWBj5vLDu/0Pf8+uKcjYtlW5354QKXeqxIe+YG5raUKnpSt162Gv54QcnCx+0v4pjDNoQZe5Wded40D/r5b8zkID2+9Y65D7GSJ5nYY/nlLgXmgWnjco5onvavcawZ0hD345lwH/yPfjG2QXnxF8z8KfzjdvFbo1/BjLu2Fnjp/ubnq4WMV2lcDvHCy27wwfeo67bGR879mNYuhx1u13yZ4T+eAufEx+KontXe6X6V5Xds38E+mq4dmeHRRl7nobbcCTSct8NcyzZhDjsNv9Kgfum2hue2yE/CZDnVFHyrW3FrhYYnqjZ7zt+ZJb6pTh9/C73lDc6anPqQ+6eXDmr+TPWxTt/SYJO2FXnhnvunZBW+v177oU3LUOd0arj22wQ+cV//0mzu0X/rTKToX38E3+r4P9L4mvS59Vq56aIeviNA5otddVCf0iTKdrw540hL1Q9/hr3NHH2lWV/S5eerqJDxvjrqiu0bVFT2oXF11wtMt6opuD1BX9PET6uoUfEG+uqKvj1ZX9J4xdfU9/ME96oqenaau6IfvU1dd8L+c6oq+qEBd0bfNU1fd8HMefU/oj1SoK3ruy+rqB3hzsLqi39uuruhL31NXPfA9seqKHnPtklkw/bZdXdGt0ZpbL3z4Q/VGf+cnzZM+I0Ed0psqNGb6K/+oT/rvr2r+p+Fl9eqWHjdN550+sFo909d2aV/0ByLVOb3epj32wdNH1T/du1D7pX/8qc4F/Yk/tXf6mTSdF/rbterhR/j0YP2/QT+6Up3Q0zp0vui3wvRdom9fr3NHj72gruj9C9RVP/ytMnVFn/qruqLXpqoruqVGXdFvBpj1euml2erqDHyeU13RT4eqK3puobqiTxlSV/RDseqK/mKpuhqA/3JdXdFLktUVPaZSXdF779a/b/TVGeqKHtyirgbhjhnqiv7CWnVFv96nrujFj6kr+twtui2926Ou6G8mqqsh+P171RW9ZkJd0ZOt6op+tUFd0beEqCt6VK66Goaf6lZX9JVR6ooeuFFd0asvqyv688+qK/r4bnV1Fr75trqiR76kruidR9QVfcVkdUUPWKWu6FUn1dU5eFK4uqJ7Nqgr+qYRdUWPeEpd0dt3qit69m/qiu5vUVfn4fsd6oqeGGRet4A+tlxd0W0udUUPn62u6G3vqqsL8KxhdUX3i1NX9L3b1RU94Ya6oo+mqCt6UZW6GoGH+ZvbxtNdmeqKnnlcXdHvmqmu6PZ8dUV/rl9dXYS7Y9QVfUOxuqLPvqqu6K2L1BU9w/eZpP8LT5QzDQ==AQAAAACAAACADAAAeQEAAA==eF5dxcciEAAAAFBKQ0u0l5BoaGhPMiuitKi0NZREe6uUJu1op6G0pL33+iwHnd67vICAZi24JQdxK27NbbgtB3M7bs8duCN34hDuzKEcxl24K3fj7tyDe3Iv7s19uC/343DuzxEcyVE8gKN5IMdwLA/iwTyEh3IcD+PhPIJHcjyP4tE8hsfyOB7PE3giT+LJPIWncgIn8jRO4mRO4VRO43SezjN4JmdwJs/iLM7m2TyHc3guz+P5vIAXci7n8SJezEs4n5fyMl7OK3glr+LVXMBreC2v4/VcyBt4IxfxJi7mzVzCpbyFt/I23s47eCfv4t28h/fyPt7PB7iMD/IhPszlfISPcgUf4+N8gk/yKT7NlVzFZ/gsn+PzfIEv8iW+zNVcw1f4Kl/j63yDb/Itvs21fIfv8j2+z3X8gB9yPT/ix/yEn/IzbuDn3Mgv+CW/4tf8ht/yO37PH/gjf+LP/IW/8jf+zj/4J//i3/yH//I/Dvx/E2V5nQg=AQAAAACAAABABgAAXwEAAA==eF4txVFEHAAAANBKkpzkJEmSJMlJkiRJkiRJkiQnSXKSJEmSJEmSJEmSZGYmmUmSJEmSJEkyMzOTzCRJkmT20Xs/LybqXazjHO8EB5zoJAed7BSnOs3pznCms5ztHOc6zyHnu8CFLnKxS1zqMpe7wpWucrVrXOs617vBjW5ys1vc6rDb3O4Od7rLEXe7x73uc78HPOghD3vEox7zuCc86SlPe8aznvO8F7zoJS97xate8wd/9Cd/9ro3/MVfvektb3vHu97zvg986CMf+8SnPvO5L3zpK1/7m7/7h3/6l3/7xrf+47++870f/OgnP/vFr37zP0dFvxfjWMc53gkOONFJDjrZKU51mtOd4UxnOds5znWeQ853gQtd5GKXuNRlLneFK13late41nWud4Mb3eRmt7jVYbe53R3udJcj7naPe93nfg940EMe9ohHPeZxT3jSU572jGc95/9sSVRSAQAAAACAAADIAAAADAAAAA==eF5jZh4eAADsVAJZ
_AQAAAAAAAAAAgAAAAAAAACkAAAAAAAAAMQAAAAAAAAA=eF4z0zPWM9I1MjXTTU8yTrVMTkxOstRLySwqqdQzMjAyMLA0MDM0MTAxMgQA4c8Kkg==AQAAAAAAAAAAgAAAAAAAAIAMAAAAAAAAKQAAAAAAAAA=eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAAAAAAAAgAAAAAAAAIAMAAAAAAAAKQAAAAAAAAA=eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAAAAAAAAgAAAAAAAAIAMAAAAAAAAKQAAAAAAAAA=eF7rfbt1wfdjG+x6R+lRepQepUfpUXqUHqVH6VF6lB6laUwDABEbjxk=AQAAAAAAAAAAgAAAAAAAAIAMAAAAAAAAIwAAAAAAAAA=eF7txTENAAAIA7BJQBL+VS2I4GufJmc2tm3btv18ARw0fQE=AQAAAAAAAAAAgAAAAAAAAEgGAAAAAAAAHgAAAAAAAAA=eF7zWL9n1qfrVXYeo/QoPUqP0qP0KE0GDQDk38XsAQAAAAAAAAAAgAAAAAAAAEgGAAAAAAAAFQAAAAAAAAA=eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAAAAAAAAgAAAAAAAAEgGAAAAAAAAFQAAAAAAAAA=eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAAAAAAAAgAAAAAAAAEgGAAAAAAAAFQAAAAAAAAA=eF5jYBgFo2AUjIJRMArIBwAGSAABAQAAAAAAAAAAgAAAAAAAAEgGAAAAAAAAGwAAAAAAAAA=eF5jYACBD/YMo/QoPUqP0qP0KE0GDQBOJu3oAQAAAAAAAAAAgAAAAAAAACADAAAAAAAAEAAAAAAAAAA=eF5jYBgFo2AU4AIAAyAAAQ==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eF5jZh4eAADsVAJZ
</AppendedData>
</VTKFile>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment