From dfd9bc02caa0e69930f3c434bf84c78e036fc5e2 Mon Sep 17 00:00:00 2001 From: Siqi Ling <lsq0473@gmail.com> Date: Mon, 8 Jun 2015 12:30:44 +0000 Subject: [PATCH] merge parallel multimesh branch to the trunk --- AMDiS/src/AMDiS_fwd.h | 4 + AMDiS/src/Assembler.cc | 189 +- AMDiS/src/BoundaryObject.cc | 2 + AMDiS/src/CoarseningManager3d.cc | 3 +- AMDiS/src/CouplingIterationInterface.h | 2 +- AMDiS/src/CouplingProblemStat.h | 399 +- AMDiS/src/CouplingTimeInterface.h | 2 +- AMDiS/src/DOFMatrix.h | 10 + AMDiS/src/Debug.cc | 63 +- AMDiS/src/Debug.h | 6 + AMDiS/src/ElInfo2d.cc | 2 +- AMDiS/src/Element.cc | 8 +- AMDiS/src/Lagrange.cc | 1 - AMDiS/src/Mesh.cc | 71 +- AMDiS/src/Mesh.h | 5 + AMDiS/src/MeshStructure.cc | 34 +- AMDiS/src/MeshStructure.h | 14 +- AMDiS/src/ProblemStat.cc | 73 +- AMDiS/src/ProblemStat.h | 21 +- AMDiS/src/RefinementManager3d.cc | 22 +- AMDiS/src/RefinementManager3d.h | 5 +- AMDiS/src/StandardProblemIteration.h | 2 +- AMDiS/src/est/Estimator.cc | 12 +- AMDiS/src/est/ResidualEstimator.cc | 35 +- AMDiS/src/io/FileWriter.cc | 4 +- AMDiS/src/io/FileWriter.hh | 1 + AMDiS/src/io/detail/VtkWriter.cc | 21 +- AMDiS/src/io/detail/VtkWriter.h | 6 +- AMDiS/src/parallel/DofComm.cc | 61 +- AMDiS/src/parallel/DofComm.h | 20 +- AMDiS/src/parallel/ElementObjectDatabase.cc | 224 +- AMDiS/src/parallel/ElementObjectDatabase.h | 51 +- AMDiS/src/parallel/InteriorBoundary.cc | 35 +- AMDiS/src/parallel/InteriorBoundary.h | 15 + AMDiS/src/parallel/MatrixNnzStructure.cc | 20 +- AMDiS/src/parallel/MatrixNnzStructure.h | 4 + AMDiS/src/parallel/MeshDistributor.cc | 1216 +-- AMDiS/src/parallel/MeshDistributor.h | 135 +- AMDiS/src/parallel/MeshManipulation.cc | 14 +- AMDiS/src/parallel/MeshManipulation.h | 4 + .../src/parallel/ParallelCoarseSpaceSolver.cc | 11 +- AMDiS/src/parallel/ParallelDebug.cc | 338 +- AMDiS/src/parallel/ParallelDebug.h | 19 +- AMDiS/src/parallel/ParallelDofMapping.cc | 116 +- AMDiS/src/parallel/ParallelDofMapping.h | 111 +- AMDiS/src/parallel/ParallelProblemStat.cc | 13 +- AMDiS/src/parallel/ParallelSolver.cc | 6 +- AMDiS/src/parallel/ParallelTypes.h | 4 + AMDiS/src/parallel/PetscSolverFeti.cc | 12 +- AMDiS/src/parallel/PetscSolverGlobalMatrix.cc | 5 +- AMDiS/src/parallel/PetscSolverSchur.cc | 11 +- AMDiS/src/utility/to_string.hpp | 41 + extensions/ProblemStatMassConserve.h | 13 +- extensions/ProblemStatMassConserve_mm.h | 123 + extensions/Refinement.h | 26 +- extensions/Refinement_Level.h | 1 + .../base_problems/CouplingBaseProblem.h | 17 +- .../base_problems/CouplingBaseProblem2.h | 49 +- .../CouplingBaseProblem2_cxx11.h | 201 +- .../NavierStokes_TH_MultiPhase.hh | 1 + extensions/demo/multimesh/CMakeLists.txt | 33 + .../init/cahnHilliard_navierStokes.dat.2d | 126 + .../multimesh/init/dend002.dat.2d.m.bicg.2p | 138 + .../multimesh/init/heat.dat.2d.m_1015_1010 | 85 + .../demo/multimesh/init/heat.dat.2d.s_16_16 | 76 + .../demo/multimesh/macro/macro.square.2d | 47 + .../macro/macro.square.2d.666466.tmp | 236 + .../macro/macro.square.2d.685642.tmp | 236 + .../demo/multimesh/macro/macro_corner_1x1.2d | 24 + .../macro/macro_corner_1x1.2d.736102.tmp | 6708 +++++++++++++++++ .../macro/macro_corner_1x1.2d.801668.tmp | 6708 +++++++++++++++++ .../macro/macro_corner_1x1.2d.991261.tmp | 6708 +++++++++++++++++ extensions/demo/multimesh/src/Anisotropy.h | 175 + .../demo/multimesh/src/CahnHilliard_mm.h | 127 + .../demo/multimesh/src/CahnHilliard_mm.hh | 222 + .../demo/multimesh/src/MyProblemInstat.cc | 158 + .../demo/multimesh/src/MyProblemInstat.h | 96 + extensions/demo/multimesh/src/Refinement.cc | 184 + extensions/demo/multimesh/src/Refinement.h | 39 + .../src/cahnHilliard_navierStokes.cc | 187 + .../src/cahnHilliard_navierStokes_mm.cc | 186 + extensions/demo/multimesh/src/dendrites.cc | 234 + .../demo/multimesh/src/diffuseDomain.cc | 340 + .../init/cahnHilliard_navierStokes.dat.2d | 8 +- 84 files changed, 25635 insertions(+), 1380 deletions(-) create mode 100644 AMDiS/src/utility/to_string.hpp create mode 100644 extensions/ProblemStatMassConserve_mm.h create mode 100644 extensions/demo/multimesh/CMakeLists.txt create mode 100644 extensions/demo/multimesh/init/cahnHilliard_navierStokes.dat.2d create mode 100644 extensions/demo/multimesh/init/dend002.dat.2d.m.bicg.2p create mode 100644 extensions/demo/multimesh/init/heat.dat.2d.m_1015_1010 create mode 100644 extensions/demo/multimesh/init/heat.dat.2d.s_16_16 create mode 100644 extensions/demo/multimesh/macro/macro.square.2d create mode 100644 extensions/demo/multimesh/macro/macro.square.2d.666466.tmp create mode 100644 extensions/demo/multimesh/macro/macro.square.2d.685642.tmp create mode 100644 extensions/demo/multimesh/macro/macro_corner_1x1.2d create mode 100644 extensions/demo/multimesh/macro/macro_corner_1x1.2d.736102.tmp create mode 100644 extensions/demo/multimesh/macro/macro_corner_1x1.2d.801668.tmp create mode 100644 extensions/demo/multimesh/macro/macro_corner_1x1.2d.991261.tmp create mode 100644 extensions/demo/multimesh/src/Anisotropy.h create mode 100644 extensions/demo/multimesh/src/CahnHilliard_mm.h create mode 100644 extensions/demo/multimesh/src/CahnHilliard_mm.hh create mode 100644 extensions/demo/multimesh/src/MyProblemInstat.cc create mode 100644 extensions/demo/multimesh/src/MyProblemInstat.h create mode 100644 extensions/demo/multimesh/src/Refinement.cc create mode 100644 extensions/demo/multimesh/src/Refinement.h create mode 100644 extensions/demo/multimesh/src/cahnHilliard_navierStokes.cc create mode 100644 extensions/demo/multimesh/src/cahnHilliard_navierStokes_mm.cc create mode 100644 extensions/demo/multimesh/src/dendrites.cc create mode 100644 extensions/demo/multimesh/src/diffuseDomain.cc diff --git a/AMDiS/src/AMDiS_fwd.h b/AMDiS/src/AMDiS_fwd.h index ecbe2de4..3c030371 100644 --- a/AMDiS/src/AMDiS_fwd.h +++ b/AMDiS/src/AMDiS_fwd.h @@ -163,6 +163,10 @@ namespace AMDiS { template<typename T> class WorldVector; template<typename T> class WorldMatrix; template<typename T> class VectorOfFixVecs; + + namespace detail { + template <class P> class CouplingProblemStat; + } typedef mtl::dense2D<double> ElementMatrix; diff --git a/AMDiS/src/Assembler.cc b/AMDiS/src/Assembler.cc index b73de0b3..4e0941a7 100644 --- a/AMDiS/src/Assembler.cc +++ b/AMDiS/src/Assembler.cc @@ -53,7 +53,6 @@ namespace AMDiS { Assembler::~Assembler() {} - void Assembler::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& userMat, double factor) @@ -64,19 +63,22 @@ namespace AMDiS { Element *el = elInfo->getElement(); if (el != lastMatEl || !operat->isOptimized()) { - initElement(elInfo, elInfo); + initElement(elInfo); if (rememberElMat) set_to_zero(elementMatrix); lastMatEl = el; } else { + // Only possible in single mesh case when one operator + // is used more than twice? if (rememberElMat) { - userMat += factor * elementMatrix; + if (&userMat != &elementMatrix) + userMat += factor * elementMatrix; return; } } - + ElementMatrix& mat = rememberElMat ? elementMatrix : userMat; if (secondOrderAssembler) @@ -91,8 +93,7 @@ namespace AMDiS { if (rememberElMat && &userMat != &elementMatrix) userMat += factor * elementMatrix; } - - + void Assembler::calculateElementMatrix(const ElInfo *rowElInfo, const ElInfo *colElInfo, const ElInfo *smallElInfo, @@ -101,115 +102,68 @@ namespace AMDiS { ElementMatrix& userMat, double factor) { - if (remember && (factor != 1.0 || operat->uhOld)) - rememberElMat = true; - - Element *el = smallElInfo->getElement(); + Element *el = smallElInfo->getElement(); + // initElement and calculateElementMatrix always need to be + // recalculated since the smaller ElInfo can be different lastVecEl = lastMatEl = NULL; if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) initElement(smallElInfo, largeElInfo); - if (el != lastMatEl || !operat->isOptimized()) { - if (rememberElMat) - set_to_zero(elementMatrix); + if (el != lastMatEl || !operat->isOptimized()) lastMatEl = el; - } else { - if (rememberElMat) { + else { + ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n"); + if (&userMat != &elementMatrix) userMat += factor * elementMatrix; - return; - } + return; } - - ElementMatrix& mat = rememberElMat ? elementMatrix : userMat; - - if (secondOrderAssembler) { - // calculate element matrices always on smallest element - secondOrderAssembler->calculateElementMatrix(smallElInfo, mat); - // smallElInfo stores refinement-relation to largeElInfo - ElementMatrix &m = - smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); // muste be moved to next if-else block when generalized for multiple polynomial degrees - - if (!rowColFeSpaceEqual) { - if (smallElInfo == colElInfo) - tmpMat = m * mat; - else - tmpMat = mat * trans(m); - - mat = tmpMat; - } - } + // In multimesh case, elementMatrix is always be recalculated, because each time we + // need to do transformation here. + set_to_zero(elementMatrix); + + ElementMatrix& mat = elementMatrix; - if (firstOrderAssemblerGrdPsi) { + if (secondOrderAssembler) + secondOrderAssembler->calculateElementMatrix(smallElInfo, mat); + if (firstOrderAssemblerGrdPsi) firstOrderAssemblerGrdPsi->calculateElementMatrix(smallElInfo, mat); - - if (!rowColFeSpaceEqual) { - if (largeElInfo == rowElInfo) { - ElementMatrix &m = - smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - - tmpMat = m * mat; - } else { - ElementMatrix &m = - smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - - tmpMat = mat * trans(m); - } - - mat = tmpMat; - } - } - - if (firstOrderAssemblerGrdPhi) { + if (firstOrderAssemblerGrdPhi) firstOrderAssemblerGrdPhi->calculateElementMatrix(smallElInfo, mat); - - if (!rowColFeSpaceEqual) { - if (largeElInfo == colElInfo) { - ElementMatrix &m = - smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - - tmpMat = mat * trans(m); - } else { - ElementMatrix &m = - smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - - tmpMat = m * mat; - } - - mat = tmpMat; - } - } - - if (zeroOrderAssembler) { + if (zeroOrderAssembler) zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat); + + - if (!rowColFeSpaceEqual) { - ElementMatrix &m = - smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - - if (smallElInfo == colElInfo) - tmpMat = m * mat; - else - tmpMat = mat * trans(m); - - mat = tmpMat; - } - } + ElementMatrix &m = + smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); - if (rememberElMat && &userMat != &elementMatrix) - userMat += factor * elementMatrix; + if (!rowColFeSpaceEqual) { + if (smallElInfo == colElInfo) + tmpMat = m * mat; + else + tmpMat = mat * trans(m); + + mat = tmpMat; + } else if (smallElInfo == colElInfo) { + tmpMat = m * mat * trans(m); + mat = tmpMat; + } + + // This is for the call in matVecAssemble + if (&userMat != &elementMatrix) + userMat += factor * elementMatrix; } - void Assembler::calculateElementVector(const ElInfo *elInfo, ElementVector& userVec, double factor) { if (remember && factor != 1.0) rememberElVec = true; - + Element *el = elInfo->getElement(); if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) @@ -221,6 +175,8 @@ namespace AMDiS { lastVecEl = el; } else { + // Only possible in single mesh case when one operator + // is used more than twice at dof vector? if (rememberElVec) { userVec += factor * elementVector; return; @@ -246,7 +202,6 @@ namespace AMDiS { userVec += factor * elementVector; } - void Assembler::calculateElementVector(const ElInfo *mainElInfo, const ElInfo *auxElInfo, const ElInfo *smallElInfo, @@ -256,36 +211,33 @@ namespace AMDiS { { FUNCNAME("Assembler::calculateElementVector()"); - if (remember && factor != 1.0) - rememberElVec = true; - Element *el = mainElInfo->getElement(); + // initElement and calculateElementVector always need to be + // recalculated since the smaller ElInfo can be different + lastVecEl = lastMatEl = NULL; if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) initElement(smallElInfo, largeElInfo); - - if (el != lastVecEl || !operat->isOptimized()) { - if (rememberElVec) - set_to_zero(elementVector); - + + if (el != lastVecEl || !operat->isOptimized()) lastVecEl = el; - } else { - if (rememberElVec) { - userVec += factor * elementVector; - return; - } + else { + ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n"); + userVec += factor * elementVector; + return; } - ElementVector& vec = rememberElVec ? elementVector : userVec; + + set_to_zero(elementVector); + ElementVector& vec = elementVector; if (operat->uhOld && remember) { + if (smallElInfo->getLevel() == largeElInfo->getLevel()) matVecAssemble(auxElInfo, vec); - else + else matVecAssemble(mainElInfo, auxElInfo, smallElInfo, largeElInfo, vec); - if (rememberElVec) - userVec += factor * elementVector; - + userVec += factor * elementVector; return; } @@ -306,13 +258,12 @@ namespace AMDiS { } } - if (rememberElVec) - userVec += factor * elementVector; + userVec += factor * elementVector; } - void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector& vec) { + Element *el = elInfo->getElement(); ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ? nRow : nCol); @@ -323,7 +274,8 @@ namespace AMDiS { calculateElementMatrix(elInfo, elementMatrix); } - vec += elementMatrix*uhOldLoc; + + vec += elementMatrix * uhOldLoc; } @@ -331,7 +283,7 @@ namespace AMDiS { const ElInfo *smallElInfo, const ElInfo *largeElInfo, ElementVector& vec) { - FUNCNAME("Assembler::matVecAssemble()"); + FUNCNAME("Assembler::matVecAssemble()"); TEST_EXIT(rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts()) ("Works only for equal basis functions for different components!\n"); @@ -343,7 +295,7 @@ namespace AMDiS { usedEl = mainElInfo->getElement(); else ERROR("Mesh is incorrect.\n"); - + const BasisFunction *basFcts = rowFeSpace->getBasisFcts(); int nBasFcts = basFcts->getNumber(); ElementVector uhOldLoc(nBasFcts); @@ -353,10 +305,11 @@ namespace AMDiS { if (mainElInfo->getElement() != lastMatEl) { set_to_zero(elementMatrix); calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo, - rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix); + rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix); } vec += elementMatrix * uhOldLoc; + } @@ -472,4 +425,4 @@ namespace AMDiS { checkQuadratures(); } -} +} \ No newline at end of file diff --git a/AMDiS/src/BoundaryObject.cc b/AMDiS/src/BoundaryObject.cc index 6478af25..f7b4393b 100644 --- a/AMDiS/src/BoundaryObject.cc +++ b/AMDiS/src/BoundaryObject.cc @@ -56,6 +56,8 @@ namespace AMDiS { FUNCNAME("BoundaryObject::computeReverseMode()"); bool reverseMode = false; + + TEST_EXIT_DBG(obj0.el && obj1.el)("BoundaryObject without element pointer.\n"); switch (feSpace->getMesh()->getDim()) { case 2: diff --git a/AMDiS/src/CoarseningManager3d.cc b/AMDiS/src/CoarseningManager3d.cc index 85ce619c..4b56e6f8 100644 --- a/AMDiS/src/CoarseningManager3d.cc +++ b/AMDiS/src/CoarseningManager3d.cc @@ -99,7 +99,7 @@ namespace AMDiS { #if HAVE_PARALLEL_DOMAIN_AMDIS vector<FixRefinementPatch::EdgeInEl> refineEdges; - FixRefinementPatch::getOtherEl(stack, refineEdges); + FixRefinementPatch::getOtherEl(mesh, stack, refineEdges); // === If the refinement edge must be fixed, add also the other part of this === // === edge to the refinement patch. === @@ -110,6 +110,7 @@ namespace AMDiS { return; Element *otherEl = refineEdges[0].first; + TEST_EXIT_DBG(otherEl->getMesh() == mesh)("Something is wrong.\n"); TraverseStack stack2; ElInfo *elInfo2 = diff --git a/AMDiS/src/CouplingIterationInterface.h b/AMDiS/src/CouplingIterationInterface.h index b19eb44d..d65c608f 100644 --- a/AMDiS/src/CouplingIterationInterface.h +++ b/AMDiS/src/CouplingIterationInterface.h @@ -40,7 +40,7 @@ namespace AMDiS { * problem-list, that is filled by addProblem. Alternatively one can a access * each problem by an unique name. */ - class CouplingIterationInterface : public ProblemIterationInterface + class CouplingIterationInterface : public virtual ProblemIterationInterface { public: virtual ~CouplingIterationInterface() {} diff --git a/AMDiS/src/CouplingProblemStat.h b/AMDiS/src/CouplingProblemStat.h index 0c69f06f..c2b3d81f 100644 --- a/AMDiS/src/CouplingProblemStat.h +++ b/AMDiS/src/CouplingProblemStat.h @@ -31,7 +31,7 @@ #include "AMDiS_fwd.h" #include "ProblemStat.h" #include "Initfile.h" -#include <boost/lexical_cast.hpp> +#include "utility/to_string.hpp" namespace AMDiS { @@ -43,21 +43,26 @@ namespace AMDiS { * computations. */ template<typename ProblemStatType> - class CouplingProblemStat + class CouplingProblemStat : public ProblemStatSeq { + protected: + typedef ProblemStatSeq super; + + using super::nComponents; + using super::meshes; + using super::nMeshes; + using super::feSpaces; + using super::name; + using super::refinementManager; + using super::coarseningManager; + public: /// Constructor CouplingProblemStat(std::string name_) - : name(name_), - nComponents(0), - nMeshes(0), - refinementManager(NULL), - coarseningManager(NULL) + : super(name_), + dim(-1) {} - /// Destructor - virtual ~CouplingProblemStat() {} - /// add problem by number virtual void addProblem(ProblemStatType* prob) { @@ -71,112 +76,193 @@ namespace AMDiS { Flag adoptFlag = INIT_NOTHING) { FUNCNAME("CouplingProblemStat::initialize()"); - // create one refinement-/coarseningmanager for all problems - if (refinementManager != NULL && coarseningManager != NULL) { - WARNING("refinement-/coarseningmanager already created\n"); - } else { - if (!adoptProblem) - createRefCoarseManager(); - else { - refinementManager = adoptProblem->getRefinementManager(); - coarseningManager = adoptProblem->getCoarseningManager(); - } + super::initialize(initFlag - INIT_MESH); + + const Flag DEFAULT_INIT = (INIT_FE_SPACE | INIT_MESH | CREATE_MESH | INIT_SYSTEM | INIT_SOLVER | INIT_ESTIMATOR | INIT_MARKER | INIT_FILEWRITER); + for (size_t p = 0; p < problems.size(); ++p) { + problems[p]->initialize(initFlag - DEFAULT_INIT); } - - if (refinementManager == NULL || coarseningManager == NULL) - WARNING("no refinement-/coarseningmanager created\n"); - // create Meshes and FeSpaces + for (size_t i = 0; i < meshes.size(); i++) { + int globalRefinements = 0; + + // If AMDiS is compiled for parallel computations, the global refinements are + // ignored here. Later, each rank will add the global refinements to its + // private mesh. + #ifndef HAVE_PARALLEL_DOMAIN_AMDIS + Parameters::get(meshes[i]->getName() + "->global refinements", + globalRefinements); + #endif + bool initMesh = initFlag.isSet(INIT_MESH); + // Initialize the meshes if there is no serialization file. + if (initMesh && meshes[i] && !(meshes[i]->isInitialized())) { + meshes[i]->initialize(); + refinementManager->globalRefine(meshes[i], globalRefinements); + } + } + } + + + /// Used in \ref initialize(). + virtual void createMesh() override + { // all problems must have the same dimension (?) - int dim = 0; + dim = 0; Parameters::get(name + "->dim", dim); TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n", name.c_str()); - std::map<std::string, Mesh*> meshByName; + std::map<std::pair<std::string, int>, Mesh*> meshByName; // (name, refSet) --> Mesh* + typedef std::map<std::pair<std::string, int>, Mesh*>::iterator MeshIterator; + std::vector<std::set<Mesh*> > meshesForProblems(problems.size()); - std::map<std::pair<Mesh*, int>, FiniteElemSpace*> feSpaceMap; + for (size_t i = 0; i < problems.size(); ++i) { TEST_EXIT(problems[i])("problem[%d] does not exist!\n",i); - for (size_t j = 0; j < problems[i]->getNumComponents(); j++) { - // mesh - + + int nComponents = problems[i]->getNumComponents(); + + int nAddComponents = 0; + Parameters::get(problems[i]->getName() + "->additional components", nAddComponents); + + problems[i]->componentMeshes.resize(nComponents + nAddComponents); + + for (size_t j = 0; j < nComponents + nAddComponents; j++) { + // name of the mesh std::string meshName(""); Parameters::get(problems[i]->getName() + "->mesh", meshName); TEST_EXIT(meshName != "")("No mesh name specified for \"%s->mesh\"!\n", problems[i]->getName().c_str()); - - if (meshByName.find(meshName) == meshByName.end()) { + + // dimension of the mesh + int mesh_dim = 0; + Parameters::get(problems[i]->getName() + "->dim", mesh_dim); + TEST_EXIT(dim == mesh_dim)("Mesh-dimension must be the same for all problems!\n"); + + // refinement set (optional) + int refSet = 0; + Parameters::get(problems[i]->getName() + "->refinement set[" + to_string(j) + "]", refSet); + + // create a new Mesh only if not already created for other problem + Mesh* componentMesh; + MeshIterator meshIt = meshByName.find(std::make_pair(meshName, refSet)); + if (meshIt == meshByName.end()) { Mesh *newMesh = new Mesh(meshName, dim); - meshByName[meshName] = newMesh; meshes.push_back(newMesh); - meshesForProblems[i].insert(newMesh); + meshByName[std::make_pair(meshName, refSet)] = newMesh; + componentMesh = newMesh; nMeshes++; - } else - meshesForProblems[i].insert(meshByName[meshName]); + } else { + componentMesh = meshIt->second; + } + problems[i]->componentMeshes[j] = componentMesh; + } + + // copy unqiue set of meshes to problem[i]->meshes + std::set<Mesh*> uniqueMeshes; + for (size_t j = 0; j < problems[i]->componentMeshes.size(); ++j) + uniqueMeshes.insert(problems[i]->componentMeshes[j]); + problems[i]->meshes.clear(); + problems[i]->meshes.insert(problems[i]->meshes.begin(), uniqueMeshes.begin(), uniqueMeshes.end()); + } + } - problems[i]->setComponentMesh(j, meshByName[meshName]); + /// Used in \ref initialize(). + virtual void createFeSpace(DOFAdmin *admin) override + { + std::vector<std::set<FiniteElemSpace const*> > feSpacesForProblems(problems.size()); + std::map<std::pair<Mesh*, std::string>, FiniteElemSpace*> feSpaceMap; + + for (size_t p = 0; p < problems.size(); ++p) { + TEST_EXIT(problems[p])("problem[%d] does not exist!\n",p); + + int nComponents = problems[p]->getNumComponents(); + + int nAddComponents = 0; + Parameters::get(problems[p]->getName() + "->additional components", nAddComponents); + problems[p]->componentSpaces.resize(nComponents + nAddComponents, NULL); + problems[p]->traverseInfo.resize(nComponents); + + for (size_t i = 0; i < nComponents + nAddComponents; i++) { + + std::string componentString = "[" + to_string(i) + "]"; + + std::string feSpaceName = ""; + std::string initFileStr = problems[p]->getName() + "->feSpace" + componentString; + Parameters::get(initFileStr, feSpaceName); + + // synonym for "feSpace" + if (feSpaceName.size() == 0) { + initFileStr = problems[p]->getName() + "->finite element space" + componentString; + Parameters::get(initFileStr, feSpaceName); + } + + // for backward compatibility also accept the old syntax + if (feSpaceName.size() == 0) { + int degree = 1; + initFileStr = problems[p]->getName() + "->polynomial degree" + componentString; + Parameters::get(initFileStr, degree); + TEST_EXIT(degree > 0) + ("Poynomial degree in component %d must be larger than zero!\n", i); + + feSpaceName = "Lagrange" + to_string(degree); + } + + if (feSpaceName.size() == 0) + feSpaceName = "Lagrange1"; + + if (feSpaceMap[std::make_pair(problems[p]->componentMeshes[i], feSpaceName)] == NULL) { + BasisFunctionCreator *basisFctCreator = + dynamic_cast<BasisFunctionCreator*>(CreatorMap<BasisFunction>::getCreator(feSpaceName, initFileStr)); + TEST_EXIT(basisFctCreator) + ("No valid basisfunction type found in parameter \"%s\"\n", initFileStr.c_str()); + basisFctCreator->setDim(dim); - // feSpace - int degree = 1; - Parameters::get(problems[i]->getName() + "->polynomial degree[" + - boost::lexical_cast<std::string>(j) + "]", degree); - - if (feSpaceMap[std::pair<Mesh*, int>(meshByName[meshName], degree)] == NULL) { - std::stringstream s; - s << problems[i]->getName() << "->feSpace[" << j << "]"; - FiniteElemSpace *newFeSpace = - FiniteElemSpace::provideFeSpace(NULL, Lagrange::getLagrange(dim, degree), - meshByName[meshName], s.str()); - feSpaceMap[std::pair<Mesh*, int>(meshByName[meshName], degree)] = newFeSpace; + FiniteElemSpace::provideFeSpace(admin, basisFctCreator->create(), + problems[p]->componentMeshes[i], + "FeSpace" + componentString + " (" + feSpaceName + ")"); + + feSpaceMap[std::make_pair(problems[p]->componentMeshes[i], feSpaceName)] = newFeSpace; feSpaces.push_back(newFeSpace); } - - // problems[i]->setComponentSpace(j, feSpaceMap[std::pair<Mesh*, int>(meshByName[meshName], degree)]); + problems[p]->componentSpaces[i] = feSpaceMap[std::make_pair(problems[p]->componentMeshes[i], feSpaceName)]; + } + + // copy unqiue set of meshes to problem[p]->meshes + std::set<FiniteElemSpace const*> uniqueFeSpaces; + for (size_t i = 0; i < problems[p]->componentSpaces.size(); ++i) + uniqueFeSpaces.insert(problems[p]->componentSpaces[i]); + problems[p]->feSpaces.clear(); + problems[p]->feSpaces.insert(problems[p]->feSpaces.begin(), uniqueFeSpaces.begin(), uniqueFeSpaces.end()); + + // create traverseInfo + for (int i = 0; i < nComponents; i++) { + for (int j = 0; j < nComponents; j++) + problems[p]->traverseInfo.getMatrix(i, j).setFeSpace(problems[p]->componentSpaces[i], problems[p]->componentSpaces[j]); + + problems[p]->traverseInfo.getVector(i).setFeSpace(problems[p]->componentSpaces[i]); } } - for (size_t i = 0; i < problems.size(); i++) { - std::vector<Mesh*> problemMeshes(meshesForProblems[i].begin(), meshesForProblems[i].end()); - problems[i]->setMeshes(problemMeshes); - problems[i]->setRefinementManager(refinementManager); - problems[i]->setCoarseningManager(coarseningManager); - problems[i]->initialize(INIT_ALL - INIT_MESH); - } - + // create dof admin for vertex dofs if neccessary for (size_t i = 0; i < meshes.size(); i++) { - int globalRefinements = 0; - - // If AMDiS is compiled for parallel computations, the global refinements are - // ignored here. Later, each rank will add the global refinements to its - // private mesh. - #ifndef HAVE_PARALLEL_DOMAIN_AMDIS - Parameters::get(meshes[i]->getName() + "->global refinements", - globalRefinements); - #endif - - bool initMesh = initFlag.isSet(INIT_MESH); - - // Initialize the meshes if there is no serialization file. - if (initMesh && meshes[i] && !(meshes[i]->isInitialized())) { - meshes[i]->initialize(); - refinementManager->globalRefine(meshes[i], globalRefinements); + if (meshes[i]->getNumberOfDofs(VERTEX) == 0) { + DimVec<int> ln_dof(meshes[i]->getDim(), DEFAULT_VALUE, 0); + ln_dof[VERTEX] = 1; + meshes[i]->createDOFAdmin("vertex dofs", ln_dof); } } } - void createRefCoarseManager() + /// Used in \ref initialize(). + virtual void createRefCoarseManager() override { FUNCNAME("CouplingProblemStat::createRefCoarseManager()"); - - int dim = 0; - Parameters::get(name + "->dim", dim); - TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n", - name.c_str()); + assert( dim > 0); switch (dim) { case 1: @@ -194,20 +280,65 @@ namespace AMDiS { default: ERROR_EXIT("invalid dim!\n"); } + + for (size_t p = 0; p < problems.size(); p++) { + problems[p]->setRefinementManager(refinementManager); + problems[p]->setCoarseningManager(coarseningManager); + } + } + + /// Used in \ref initialize(). + virtual void createMatricesAndVectors() override + { + for (size_t p = 0; p < problems.size(); ++p) { + assert( problems[p] ); + problems[p]->createMatricesAndVectors(); + } + } + + /// Used in \ref initialize(). + virtual void createSolver() override + { + for (size_t p = 0; p < problems.size(); ++p) { + assert( problems[p] ); + problems[p]->createSolver(); + } } + /// Used in \ref initialize(). + virtual void createEstimator() override + { + for (size_t p = 0; p < problems.size(); ++p) { + assert( problems[p] ); + problems[p]->createEstimator(); + } + } + + /// Used in \ref initialize(). + virtual void createMarker() override + { + for (size_t p = 0; p < problems.size(); ++p) { + assert( problems[p] ); + problems[p]->createMarker(); + } + } + + /// Used in \ref initialize(). + virtual void createFileWriter() override + { + for (size_t p = 0; p < problems.size(); ++p) { + assert( problems[p] ); + problems[p]->createFileWriter(); + } + } + + /// Returns number of managed problems virtual int getNumProblems() { return problems.size(); } - /// Implementation of ProblemStatBase::getNumComponents() - virtual int getNumComponents() - { - return nComponents; - } - /** \brief * Returns the problem with the given number. If only one problem * is managed by this master problem, the number hasn't to be given. @@ -223,64 +354,48 @@ namespace AMDiS { return meshes[number]; } - /// Returns \ref meshes - inline std::vector<Mesh*> getMeshes() - { - return meshes; - } - - /// Returns \ref refinementManager. - inline RefinementManager* getRefinementManager(int comp = 0) - { - return refinementManager; - } - - /// Returns \ref refinementManager. - inline CoarseningManager* getCoarseningManager(int comp = 0) - { - return coarseningManager; - } - - /// Returns the name of the problem - inline virtual std::string getName() - { - return name; - } + using super::getNumComponents; + using super::getRefinementManager; + using super::getCoarseningManager; + using super::getName; protected: - /// Name of this problem. - std::string name; - - /// Number of problem components - int nComponents; - - /** \brief - * Number of problem meshes. If all components are defined on the same mesh, - * this number is 1. Otherwise, this variable is the number of different meshes - * within the problem. - */ - int nMeshes; - - /// FE spaces of this problem. - std::vector<FiniteElemSpace*> feSpaces; - - /// Meshes of this problem. - std::vector<Mesh*> meshes; - - /** \brief - * All actions of mesh refinement are performed by refinementManager. - * If new refinement algorithms should be realized, one has to override - * RefinementManager and give one instance of it to AdaptStationary. - */ - RefinementManager *refinementManager; - - /** \brief - * All actions of mesh coarsening are performed by coarseningManager. - * If new coarsening algorithms should be realized, one has to override - * CoarseningManager and give one instance of it to AdaptStationary. - */ - CoarseningManager *coarseningManager; +// /// Name of this problem. +// std::string name; +// +// /// Number of problem components +// int nComponents; + + /// unqiue mesh-dimension for all problems + int dim; + +// /** \brief +// * Number of problem meshes. If all components are defined on the same mesh, +// * this number is 1. Otherwise, this variable is the number of different meshes +// * within the problem. +// */ +// int nMeshes; + +// /// FE spaces of this problem. +// std::vector<FiniteElemSpace*> feSpaces; +// +// /// Meshes of this problem. +// std::vector<Mesh*> meshes; + +// /** \brief +// * All actions of mesh refinement are performed by refinementManager. +// * If new refinement algorithms should be realized, one has to override +// * RefinementManager and give one instance of it to AdaptStationary. +// */ +// RefinementManager *refinementManager; +// +// /** \brief +// * All actions of mesh coarsening are performed by coarseningManager. +// * If new coarsening algorithms should be realized, one has to override +// * CoarseningManager and give one instance of it to AdaptStationary. +// */ +// CoarseningManager *coarseningManager; std::vector<ProblemStatType*> problems; }; diff --git a/AMDiS/src/CouplingTimeInterface.h b/AMDiS/src/CouplingTimeInterface.h index fe3187d7..be62c3ea 100644 --- a/AMDiS/src/CouplingTimeInterface.h +++ b/AMDiS/src/CouplingTimeInterface.h @@ -36,7 +36,7 @@ namespace AMDiS { * * \brief */ - class CouplingTimeInterface : public ProblemTimeInterface + class CouplingTimeInterface : public virtual ProblemTimeInterface { public: void addTimeInterface(ProblemTimeInterface *interface) diff --git a/AMDiS/src/DOFMatrix.h b/AMDiS/src/DOFMatrix.h index f28f1f29..0a36a5a4 100644 --- a/AMDiS/src/DOFMatrix.h +++ b/AMDiS/src/DOFMatrix.h @@ -344,6 +344,16 @@ namespace AMDiS { { return nnzPerRow; } + + std::vector<DegreeOfFreedom>& getRowIndices() + { + return rowIndices; + } + + std::vector<DegreeOfFreedom>& getColIndices() + { + return colIndices; + } /// Writes the matrix to an output stream. void serialize(std::ostream &out); diff --git a/AMDiS/src/Debug.cc b/AMDiS/src/Debug.cc index 85f3bf1d..dd6ebc7f 100644 --- a/AMDiS/src/Debug.cc +++ b/AMDiS/src/Debug.cc @@ -71,7 +71,7 @@ namespace AMDiS { io::VtkWriter::writeFile(tmp, filename + lexical_cast<std::string>(myRank) + ".vtu", io::VtkWriter::ASCII, false, - false); + false); } } #endif @@ -751,8 +751,7 @@ namespace AMDiS { elInfo = stack.traverseNext(elInfo); } } - - + void testSortedDofs(Mesh *mesh, ElementIdxToDofs &elMap) { FUNCNAME("debug::dbgTestElementMap()"); @@ -797,6 +796,64 @@ namespace AMDiS { } + void createNodeCoords(Mesh *mesh, ElementIdxToCoords& coords) + { + TraverseStack stack; + ElInfo *elInfo = + stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS); + + while (elInfo) { + coords.insert(std::make_pair(elInfo->getElement()->getIndex(), elInfo->getCoords())); + + elInfo = stack.traverseNext(elInfo); + } + } + + void testNodeCoords(Mesh* mesh, ElementIdxToCoords& coords) + { + FUNCNAME("debug::testNodeCoords()"); + + int dim = mesh->getDim(); + + TraverseStack stack; + ElInfo *elInfo = + stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS); + + while (elInfo) { + Element *el = elInfo->getElement(); + + FixVec<WorldVector<double>, VERTEX> elCoords = elInfo->getCoords(); + + for (size_t i = 0; i < (size_t)(size(elCoords)); i++) + for (size_t j = 0; j < (size_t)(mesh->getDim()); j++) + if(elCoords[i][j] != coords[el->getIndex()][i][j]) { + + MSG("[DBG] Wrong coordnate on element = %d, vertex index = %d\n!", el->getIndex(), i); + + switch (dim) { + case 2: + std::cout << "[DBG]: one coord is: "; + std::cout << "(" << elCoords[i][0] << ", " << elCoords[i][1]<< ") "; + std::cout << "another is: "; + std::cout << "(" << coords[el->getIndex()][i][0] << ", " << coords[el->getIndex()][i][1] << ")\n"; + break; + case 3: + std::cout << "[DBG]: one coord is: "; + std::cout << "(" << elCoords[i][0] << ", " << elCoords[i][1]<< ", " << elCoords[i][2] << ") "; + std::cout << "another is: "; + std::cout << "(" << coords[el->getIndex()][i][0] << ", " << coords[el->getIndex()][i][1] + << ". " << coords[el->getIndex()][i][2] << ")\n"; + break; + default: + ERROR_EXIT("What is this?\n"); + } + ERROR_EXIT("Mesh vertex coords don't match!\n"); + } + + elInfo = stack.traverseNext(elInfo); + } + } + void sortDofs(const DegreeOfFreedom* dof0, const DegreeOfFreedom* dof1, const DegreeOfFreedom* dof2, diff --git a/AMDiS/src/Debug.h b/AMDiS/src/Debug.h index 51da6683..248c2f03 100644 --- a/AMDiS/src/Debug.h +++ b/AMDiS/src/Debug.h @@ -28,6 +28,7 @@ #include <set> #include "AMDiS_fwd.h" #include "Global.h" +#include "FixVec.h" namespace AMDiS { @@ -41,6 +42,7 @@ namespace AMDiS { }; typedef std::map<int, DofContainer> ElementIdxToDofs; + typedef std::map<int, FixVec<WorldVector<double>, VERTEX> > ElementIdxToCoords; #ifdef HAVE_PARALLEL_DOMAIN_AMDIS void writeLocalElementDofs(int rank, @@ -185,6 +187,10 @@ namespace AMDiS { void exportDofVectorByCoords(const DOFVector<double>* vec, std::string filename); + void createNodeCoords(Mesh *mesh, ElementIdxToCoords& coords); + + void testNodeCoords(Mesh* mesh, ElementIdxToCoords& coords); + /** \brief * Traverse a mesh and store for each element all its vertex DOFs in local sorted * order (by values). diff --git a/AMDiS/src/ElInfo2d.cc b/AMDiS/src/ElInfo2d.cc index 99b9ccf6..92054469 100644 --- a/AMDiS/src/ElInfo2d.cc +++ b/AMDiS/src/ElInfo2d.cc @@ -875,4 +875,4 @@ namespace AMDiS { { return getSubElemCoordsMat(degree); } -} +} \ No newline at end of file diff --git a/AMDiS/src/Element.cc b/AMDiS/src/Element.cc index ca37629e..a169d20c 100644 --- a/AMDiS/src/Element.cc +++ b/AMDiS/src/Element.cc @@ -67,6 +67,11 @@ namespace AMDiS { elementData->deleteDecorated(); delete elementData; } + +// if (dof) { +// delete [] dof; +// dof = NULL; +// } } @@ -146,7 +151,8 @@ namespace AMDiS { if (dof[j]) { if (deletedDOFs.count(dof[j]) == 0) { deletedDOFs[dof[j]] = true; - delete [] dof[j]; +// delete [] dof[j]; + mesh->freeDof(dof[j], position); } } j++; diff --git a/AMDiS/src/Lagrange.cc b/AMDiS/src/Lagrange.cc index 283c32be..e1d273bd 100644 --- a/AMDiS/src/Lagrange.cc +++ b/AMDiS/src/Lagrange.cc @@ -1963,7 +1963,6 @@ namespace AMDiS { RCNeighbourList* list, int n, BasisFunction* basFct) { - FUNCNAME_DBG("Lagrange::refineInter4_3d"); if (n < 1) return; diff --git a/AMDiS/src/Mesh.cc b/AMDiS/src/Mesh.cc index 31796081..41e7be70 100644 --- a/AMDiS/src/Mesh.cc +++ b/AMDiS/src/Mesh.cc @@ -89,6 +89,7 @@ namespace AMDiS { vector<DegreeOfFreedom> Mesh::dof_used; const int Mesh::MAX_DOF = 100; map<pair<DegreeOfFreedom, int>, DegreeOfFreedom*> Mesh::serializedDOFs; + std::set<string> Mesh::refinedMeshNames; Mesh::Mesh(string aName, int dimension) : name(aName), @@ -236,7 +237,7 @@ namespace AMDiS { // for the vector index the corresponding element is stored in. // 3. Get this element from macroElements, and set it as the i-th // neighbour for the current element. - if((*it)->getNeighbour(i)!=NULL) { + if ((*it)->getNeighbour(i)!=NULL) { macroElements[insertCounter]-> setNeighbour(i, macroElements[mapIndex[(*it)->getNeighbour(i)->getIndex()]]); } @@ -275,6 +276,50 @@ namespace AMDiS { me->setIndex(macroElements.size()); } + void Mesh::removeAllMacroElements() + { + // Delete all the dofs + Element::deletedDOFs.clear(); + for (deque<MacroElement*>::const_iterator it = macroElements.begin(); + it != macroElements.end(); ++it) { + (*it)->getElement()->deleteElementDOFs(); + } + Element::deletedDOFs.clear(); + + // Set all neighbors null + for (deque<MacroElement*>::const_iterator macroIt = macroElements.begin(); + macroIt != macroElements.end(); ++macroIt) { + + for (int i = 0; i < getGeo(NEIGH); i++) + (*macroIt)->setNeighbour(i, NULL); + + Element *mel = (*macroIt)->getElement(); + // Delete element hierarchie + if (!(mel->isLeaf())) { + delete mel->getChild(0); + delete mel->getChild(1); + + mel->child[0] = NULL; + mel->child[1] = NULL; + + mel->setElementData(elementDataPrototype->clone()); + } + } + + macroElements.clear(); + nLeaves = 0; + nElements = 0; + nVertices = 0; + + for (size_t i = 0; i < admin.size(); i++) + { + TEST_EXIT_DBG(admin[i]->getUsedSize() == admin[i]->getHoleCount()) + ("All macro elements has been removed. But not all dofs are cleaned. (UsedSize = %d, HoleCount = %d)\n", + admin[i]->getUsedSize(), admin[i]->getHoleCount()); + + admin[i]->reset(); + } + } void Mesh::removeMacroElements(std::set<MacroElement*>& delMacros, vector<const FiniteElemSpace*>& feSpaces) @@ -577,6 +622,7 @@ namespace AMDiS { return; delete [] ptrs; + ptrs = NULL; } @@ -1259,7 +1305,7 @@ namespace AMDiS { Parameters::get("parallel->repartitioning->strategy", strategy); - if(strategy && !preserveMacroFileInfo) { + if (strategy && !preserveMacroFileInfo) { MSG("Preserve macroFileInfo.\n"); preserveMacroFileInfo = true; } @@ -1410,7 +1456,7 @@ namespace AMDiS { RefinementManager *refManager; if (dim == 2) refManager = new RefinementManager2d(); - else if(dim == 3) + else if (dim == 3) refManager = new RefinementManager3d(); else { @@ -1439,15 +1485,20 @@ namespace AMDiS { // === We have refined the mesh, so reduce the number of global refinements. === - int globalRefinements = 0; - Parameters::get(name + "->global refinements", globalRefinements); + // This is avoid to minus parallel prerefinement multiple times + if (refinedMeshNames.count(name + "->global refinements") == 0) { + refinedMeshNames.insert(name + "->global refinements"); + + int globalRefinements = 0; + Parameters::get(name + "->global refinements", globalRefinements); - if (globalRefinements < nParallelPreRefinements) - globalRefinements = 0; - else - globalRefinements -= nParallelPreRefinements; + if (globalRefinements < nParallelPreRefinements) + globalRefinements = 0; + else + globalRefinements -= nParallelPreRefinements; - Parameters::set(name + "->global refinements", globalRefinements); + Parameters::set(name + "->global refinements", globalRefinements); + } // === Print a note to the screen that another mesh file will be used. === diff --git a/AMDiS/src/Mesh.h b/AMDiS/src/Mesh.h index 9df196c5..e40e79d1 100644 --- a/AMDiS/src/Mesh.h +++ b/AMDiS/src/Mesh.h @@ -405,6 +405,8 @@ namespace AMDiS { /// elements have no children. void removeMacroElements(std::set<MacroElement*>& macros, std::vector<const FiniteElemSpace*>& feSpaces); + + void removeAllMacroElements(); /// Frees the array of DOF pointers (see \ref createDofPtrs) void freeDofPtrs(DegreeOfFreedom **ptrs); @@ -494,6 +496,7 @@ namespace AMDiS { * @param[out] coords DOF vector that stores the coordinates to each DOF. */ void getDofIndexCoords(DOFVector<WorldVector<double> >& coords); + /** \brief * Traverse the mesh and get all DOFs in this mesh for a given FE space. @@ -817,6 +820,8 @@ namespace AMDiS { /// Used by check functions static std::vector<DegreeOfFreedom> dof_used; + + static std::set<std::string> refinedMeshNames; /// This map is used for serialization and deserialization of mesh elements. /// During the serialization process, all elements are visited and their diff --git a/AMDiS/src/MeshStructure.cc b/AMDiS/src/MeshStructure.cc index e5523539..b6b0b78f 100644 --- a/AMDiS/src/MeshStructure.cc +++ b/AMDiS/src/MeshStructure.cc @@ -90,12 +90,12 @@ namespace AMDiS { } - void MeshStructure::init(BoundaryObject &bound) + void MeshStructure::init(BoundaryObject &bound, Element* element) { FUNCNAME("MeshStructure::init()"); - Element *el = bound.el; - + Element* el = (element == NULL) ? bound.el : element; + TEST_EXIT_DBG(el)("No element!\n"); clear(); @@ -454,7 +454,8 @@ namespace AMDiS { void MeshStructure::getMeshStructureValues(int macroElIndex, const DOFVector<double>* vec, - std::vector<double>& values) + std::vector<double>& values, + bool withElIndex) { FUNCNAME_DBG("MeshStructure::getMeshStructureValues()"); @@ -465,10 +466,10 @@ namespace AMDiS { int nVertexPreDofs = feSpace->getAdmin()->getNumberOfPreDofs(VERTEX); bool feSpaceHasNonVertexDofs = (feSpace->getBasisFcts()->getDegree() > 1); values.clear(); -#if (DEBUG != 0) + // In debug mode we add the macro element index to the value code. - values.push_back(static_cast<double>(macroElIndex)); -#endif + if (withElIndex) + values.push_back(static_cast<double>(macroElIndex)); ElementDofIterator elDofIter(feSpace); TraverseStack stack; @@ -507,7 +508,8 @@ namespace AMDiS { void MeshStructure::setMeshStructureValues(int macroElIndex, DOFVector<double>* vec, - const std::vector<double>& values) + const std::vector<double>& values, + bool withElIndex) { FUNCNAME_DBG("MeshStructure::setMeshStructureValues()"); @@ -518,12 +520,13 @@ namespace AMDiS { bool feSpaceHasNonVertexDofs = (feSpace->getBasisFcts()->getDegree() > 1); int nVertexPreDofs = feSpace->getAdmin()->getNumberOfPreDofs(VERTEX); unsigned int counter = 0; -#if (DEBUG != 0) - TEST_EXIT(static_cast<int>(values[0]) == macroElIndex) - ("Value structure code was created for macro element index %d, but should be set to macro element index %d\n", - static_cast<int>(values[0]), macroElIndex); - counter++; -#endif + + if (withElIndex) { + TEST_EXIT(static_cast<int>(values[0]) == macroElIndex) + ("Value structure code was created for macro element index %d, but should be set to macro element index %d\n", + static_cast<int>(values[0]), macroElIndex); + counter++; + } TEST_EXIT_DBG(static_cast<int>(values.size()) >= mesh->getGeo(VERTEX)) ("Should not happen!\n"); @@ -562,7 +565,8 @@ namespace AMDiS { elInfo = stack.traverseNext(elInfo); } - TEST_EXIT_DBG(values.size() == counter)("Should not happen!\n"); + TEST_EXIT_DBG(values.size() == counter) + ("Should not happen! values size %d, counter %d\n", values.size(), counter); } } diff --git a/AMDiS/src/MeshStructure.h b/AMDiS/src/MeshStructure.h index d8ab6efd..bfc211c9 100644 --- a/AMDiS/src/MeshStructure.h +++ b/AMDiS/src/MeshStructure.h @@ -32,6 +32,12 @@ #include "Global.h" #include "BoundaryObject.h" +#if (DEBUG != 0) +#define WITH_ELINDEX true +#else +#define WITH_ELINDEX false +#endif + namespace AMDiS { class MeshStructure @@ -60,7 +66,7 @@ namespace AMDiS { */ void init(Mesh *mesh, int macroElIndex = -1); - void init(BoundaryObject &bound); + void init(BoundaryObject &bound, Element* mesh = NULL); void init(const std::vector<uint64_t>& initCode, int n) { @@ -169,7 +175,8 @@ namespace AMDiS { */ void getMeshStructureValues(int macroElIndex, const DOFVector<double>* vec, - std::vector<double>& values); + std::vector<double>& values, + bool withElIndex = WITH_ELINDEX); /** \brief @@ -182,7 +189,8 @@ namespace AMDiS { */ void setMeshStructureValues(int macroElIndex, DOFVector<double>* vec, - const std::vector<double>& values); + const std::vector<double>& values, + bool withElIndex = WITH_ELINDEX); /// Insert a new element to the structure code. Is used by the init function. void insertElement(bool isLeaf); diff --git a/AMDiS/src/ProblemStat.cc b/AMDiS/src/ProblemStat.cc index ab2145b5..2e455797 100644 --- a/AMDiS/src/ProblemStat.cc +++ b/AMDiS/src/ProblemStat.cc @@ -59,6 +59,7 @@ namespace AMDiS { : StandardProblemIteration(this), name(nameStr), nComponents(-1), + nAddComponents(0), nMeshes(0), traverseInfo(0), solver(NULL), @@ -77,8 +78,11 @@ namespace AMDiS { buildTime(0.0) { Parameters::get(name + "->components", nComponents); + Parameters::get(name + "->additional components", nAddComponents); TEST_EXIT(nComponents > 0)("No value set for parameter \"%s->components\"!\n", name.c_str()); + TEST_EXIT(nAddComponents >= 0)("Wrong parameter \"%s->additional components\"!\n", + name.c_str()); estimator.resize(nComponents, NULL); marker.resize(nComponents, NULL); @@ -121,6 +125,10 @@ namespace AMDiS { if (solution) delete solution; solution = NULL; + + if (solver) + delete solver; + solver = NULL; if (systemMatrix) { for (int i = 0; i < nComponents; i++) @@ -152,8 +160,7 @@ namespace AMDiS { marker[i] = NULL; } } - - + void ProblemStatSeq::initialize(Flag initFlag, ProblemStatSeq *adoptProblem, Flag adoptFlag) @@ -175,7 +182,9 @@ namespace AMDiS { adoptFlag.isSet(INIT_FE_SPACE))) { meshes = adoptProblem->getMeshes(); componentMeshes = adoptProblem->componentMeshes; - + + TEST_EXIT(adoptProblem->getNumAddComponents() + nAddComponents > 0) + ("Not yet implemented.\n"); // If the adopt problem has fewer components than this problem, but only one // mesh for all component, than scal up the componentMeshes array. if (adoptProblem->getNumComponents() < nComponents) { @@ -225,6 +234,9 @@ namespace AMDiS { feSpaces = adoptProblem->getFeSpaces(); componentSpaces = adoptProblem->componentSpaces; traverseInfo = adoptProblem->traverseInfo; + + TEST_EXIT(adoptProblem->getNumAddComponents() + nAddComponents > 0) + ("Not yet implemented.\n"); // If the adopt problem has fewer components than this problem, but only one // fe space for all component, than scal up the componentSpaces array. @@ -376,8 +388,7 @@ namespace AMDiS { void ProblemStatSeq::createMesh() { FUNCNAME("ProblemStat::createMesh()"); - - componentMeshes.resize(nComponents); + map<int, Mesh*> meshForRefinementSet; string meshName(""); @@ -389,8 +400,10 @@ namespace AMDiS { Parameters::get(name + "->dim", dim); TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n", name.c_str()); + + componentMeshes.resize(nComponents + nAddComponents); - for (int i = 0; i < nComponents; i++) { + for (int i = 0; i < nComponents + nAddComponents; i++) { int refSet = -1; Parameters::get(name + "->refinement set[" + lexical_cast<string>(i) + "]", refSet); @@ -445,11 +458,14 @@ namespace AMDiS { Parameters::get(name + "->dim", dim); TEST_EXIT(dim != -1)("no problem dimension specified!\n"); - componentSpaces.resize(nComponents, NULL); + componentSpaces.resize(nComponents + nAddComponents, NULL); traverseInfo.resize(nComponents); - for (int i = 0; i < nComponents; i++) { - TEST_EXIT(componentSpaces[i] == NULL)("feSpace already created\n"); + for (int i = 0; i < nComponents + nAddComponents; i++) { + if (componentSpaces[i] != NULL) { + WARNING("feSpace already created\n"); + continue; + } string componentString = "[" + boost::lexical_cast<string>(i) + "]"; string feSpaceName = ""; @@ -791,7 +807,7 @@ namespace AMDiS { int nMeshes = static_cast<int>(meshes.size()); Flag refineFlag = 0; for (int i = 0; i < nMeshes; i++) - if (adaptInfo->isRefinementAllowed(i)) + if (i >= nComponents || adaptInfo->isRefinementAllowed(i)) refineFlag |= refinementManager->refineMesh(meshes[i]); return refineFlag; @@ -803,7 +819,7 @@ namespace AMDiS { int nMeshes = static_cast<int>(meshes.size()); Flag coarsenFlag = 0; for (int i = 0; i < nMeshes; i++) - if (adaptInfo->isCoarseningAllowed(i)) + if (i >= nComponents || adaptInfo->isCoarseningAllowed(i)) coarsenFlag |= coarseningManager->coarsenMesh(meshes[i]); return coarsenFlag; @@ -828,10 +844,6 @@ namespace AMDiS { FUNCNAME("ProblemStat::buildAfterCoarsen()"); if (dualMeshTraverseRequired()) { -#ifdef HAVE_PARALLEL_DOMAIN_AMDIS - ERROR_EXIT("Dual mesh assemble does not work in parallel code!\n"); -#endif - dualAssemble(adaptInfo, flag, asmMatrix, asmVector); return; } @@ -1004,11 +1016,17 @@ namespace AMDiS { FUNCNAME("ProblemStat::dualAssemble()"); TEST_EXIT(asmVector)("Not yet implemented!\n"); + + Timer t; for (unsigned int i = 0; i < meshes.size(); i++) meshes[i]->dofCompress(); - - Timer t; + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MPI::COMM_WORLD.Barrier(); + INFO(info, 8)("dof compression needed %.5f seconds\n", t.elapsed()); +#endif + t.reset(); Flag assembleFlag = flag | @@ -1122,12 +1140,12 @@ namespace AMDiS { dualTraverse.setFillSubElemMat(true, basisFcts); bool cont = dualTraverse.traverseFirst(meshes[0], meshes[1], -1, -1, assembleFlag, assembleFlag, dualElInfo); - + while (cont) { bool newEl0 = (dualElInfo.rowElInfo->getElement()->getIndex() != oldElIndex0); bool newEl1 = (dualElInfo.colElInfo->getElement()->getIndex() != oldElIndex1); oldElIndex0 = dualElInfo.rowElInfo->getElement()->getIndex(); - oldElIndex1 = dualElInfo.colElInfo->getElement()->getIndex(); + oldElIndex1 = dualElInfo.colElInfo->getElement()->getIndex(); for (int i = 0; i < nComponents; i++) { for (int j = 0; j < nComponents; j++) { @@ -1151,9 +1169,11 @@ namespace AMDiS { if (matrix) matrix->assemble(1.0, elInfo, bound); + if (i == j) rhs->getDOFVector(i)->assemble(1.0, elInfo, bound); + } ElInfo *mainElInfo, *auxElInfo; @@ -1171,11 +1191,11 @@ namespace AMDiS { if (traverseInfo.difAuxSpace(i) && i == j) rhs->getDOFVector(i)->assemble2(1.0, mainElInfo, auxElInfo, dualElInfo.smallElInfo, - dualElInfo.largeElInfo, bound); + dualElInfo.largeElInfo, bound); if (traverseInfo.difAuxSpace(i, j) && matrix) matrix->assemble2(1.0, mainElInfo, auxElInfo, - dualElInfo.smallElInfo, dualElInfo.largeElInfo, bound); + dualElInfo.smallElInfo, dualElInfo.largeElInfo, bound); if (matrix && matrix->getBoundaryManager()) matrix->getBoundaryManager()->fillBoundaryConditions(mainElInfo, matrix); @@ -1206,16 +1226,17 @@ namespace AMDiS { matrix->getBoundaryManager()->fillBoundaryConditions(rowElInfo, matrix); } - if (i == j) + if (i == j) { + ERROR_EXIT("In which case can this routine be reached??\n"); rhs->getDOFVector(i)->assemble(1.0, rowElInfo, bound); - } + } + } } } cont = dualTraverse.traverseNext(dualElInfo); } - for (int i = 0; i < nComponents; i++) { for (int j = 0; j < nComponents; j++) { DOFMatrix *matrix = (asmMatrix ? (*systemMatrix)[i][j] : NULL); @@ -1241,10 +1262,14 @@ namespace AMDiS { solverMatrix.setMatrix(*systemMatrix); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MPI::COMM_WORLD.Barrier(); +#endif INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n", t.elapsed()); + buildTime = t.elapsed(); } diff --git a/AMDiS/src/ProblemStat.h b/AMDiS/src/ProblemStat.h index 03544cbc..f5492819 100644 --- a/AMDiS/src/ProblemStat.h +++ b/AMDiS/src/ProblemStat.h @@ -164,6 +164,11 @@ namespace AMDiS { { return nComponents; } + + virtual int getNumAddComponents() + { + return nAddComponents; + } /// Returns the problem with the given number. If only one problem /// is managed by this master problem, the number hasn't to be given. @@ -327,7 +332,7 @@ namespace AMDiS { { FUNCNAME("ProblemStatSeq::getFeSpace()"); TEST_EXIT(comp < static_cast<int>(componentSpaces.size()) && comp >= 0) - ("invalid component number\n"); + ("invalid component number: %d\n", comp); return componentSpaces[comp]; } @@ -435,11 +440,16 @@ namespace AMDiS { feSpaces[comp] = feSpace; } + void setFeSpaces(std::vector<FiniteElemSpace const*> feSpaces_) + { + feSpaces = feSpaces_; + } + void setComponentSpace(int comp, const FiniteElemSpace *feSpace) { if (static_cast<int>(componentSpaces.size()) < nComponents) componentSpaces.resize(nComponents); - TEST_EXIT(comp >= 0 && comp < nComponents) + TEST_EXIT(comp >= 0 && comp < nComponents + nAddComponents) ("Component number not in feasable range!"); componentSpaces[comp] = feSpace; @@ -515,7 +525,7 @@ namespace AMDiS { { if (static_cast<int>(componentMeshes.size()) < nComponents) componentMeshes.resize(nComponents); - TEST_EXIT(comp >= 0 && comp < nComponents) + TEST_EXIT(comp >= 0 && comp < nComponents + nAddComponents) ("Component number not in feasable range!"); componentMeshes[comp] = mesh; @@ -570,6 +580,9 @@ namespace AMDiS { /// Number of problem components int nComponents; + + /// Number of additional components + int nAddComponents; /// Stores the names for all components. Is used for naming the solution /// vectors, \ref solution. @@ -677,6 +690,8 @@ namespace AMDiS { double solutionTime; double buildTime; + + template <class> friend class detail::CouplingProblemStat; }; #ifndef HAVE_PARALLEL_DOMAIN_AMDIS diff --git a/AMDiS/src/RefinementManager3d.cc b/AMDiS/src/RefinementManager3d.cc index 15a099e0..176b173d 100644 --- a/AMDiS/src/RefinementManager3d.cc +++ b/AMDiS/src/RefinementManager3d.cc @@ -40,7 +40,7 @@ using namespace std; namespace AMDiS { - FixRefinementPatch::ConnectedEdges FixRefinementPatch::connectedEdges(0); + map<Mesh*, FixRefinementPatch::ConnectedEdges> FixRefinementPatch::connectedEdges; void RefinementManager3d::bisectTetrahedron(RCNeighbourList& refineList, int index, @@ -631,7 +631,9 @@ namespace AMDiS { ElInfo* RefinementManager3d::refineFunction(ElInfo* elInfo) { +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS FUNCNAME_DBG("RefinementManager3d::refineFunction()"); +#endif Element *el = elInfo->getElement(); @@ -666,7 +668,7 @@ namespace AMDiS { #ifdef HAVE_PARALLEL_DOMAIN_AMDIS vector<FixRefinementPatch::EdgeInEl> refineEdges; - FixRefinementPatch::getOtherEl(stack, refineEdges); + FixRefinementPatch::getOtherEl(mesh, stack, refineEdges); // if (refineEdges.size()) { // MSG("FIX REFINEMENT PATH ON ELEMENT %d %d: %d additional edges\n", // elInfo->getElement()->getIndex(), @@ -827,12 +829,13 @@ namespace AMDiS { } - void FixRefinementPatch::getOtherEl(TraverseStack *stack, + void FixRefinementPatch::getOtherEl(Mesh* mesh, + TraverseStack *stack, vector<EdgeInEl>& refineEdges) { FUNCNAME_DBG("FixRefinementPatch::getOtherEl()"); - if (!FixRefinementPatch::connectedEdges.empty()) { + if (!FixRefinementPatch::connectedEdges[mesh].empty()) { // === Get stack of current traverse. === vector<ElInfo*> elInfos; vector<int> infos; @@ -840,6 +843,8 @@ namespace AMDiS { int checkIndex = stackUsed; int localEdgeNo = 0; ElInfo *elInfo = elInfos[stackUsed]; + + TEST_EXIT_DBG(elInfo->getMesh() == mesh)("Something is wrong.\n"); // === Calculate the refinement edge number on the macro element level. === @@ -880,11 +885,12 @@ namespace AMDiS { refineEdges.clear(); - for (int i = 0; i < static_cast<int>(connectedEdges.size()); i++) { - if (connectedEdges[i].first.first->getIndex() == macroElIndex && - connectedEdges[i].first.second == localEdgeNo) { + for (int i = 0; i < static_cast<int>(connectedEdges[mesh].size()); i++) { + TEST_EXIT_DBG(connectedEdges[mesh][i].first.first->getMesh() == mesh)("Something is wrong.\n"); + if (connectedEdges[mesh][i].first.first->getIndex() == macroElIndex && + connectedEdges[mesh][i].first.second == localEdgeNo) { // We have found that this edge must be fixed. - refineEdges.push_back(connectedEdges[i].second); + refineEdges.push_back(connectedEdges[mesh][i].second); } } } diff --git a/AMDiS/src/RefinementManager3d.h b/AMDiS/src/RefinementManager3d.h index fe73a153..28993428 100644 --- a/AMDiS/src/RefinementManager3d.h +++ b/AMDiS/src/RefinementManager3d.h @@ -86,9 +86,10 @@ namespace AMDiS { typedef std::pair<EdgeInEl, EdgeInEl> EdgesMap; typedef std::vector<EdgesMap> ConnectedEdges; - static ConnectedEdges connectedEdges; + static std::map<Mesh*, ConnectedEdges> connectedEdges; - static void getOtherEl(TraverseStack *stack, + static void getOtherEl(Mesh* mesh, + TraverseStack *stack, std::vector<EdgeInEl> &refineEdges); }; diff --git a/AMDiS/src/StandardProblemIteration.h b/AMDiS/src/StandardProblemIteration.h index 3ae5226f..f30d04e0 100644 --- a/AMDiS/src/StandardProblemIteration.h +++ b/AMDiS/src/StandardProblemIteration.h @@ -31,7 +31,7 @@ namespace AMDiS { /// A master problem for a single non coupled problem. - class StandardProblemIteration : public ProblemIterationInterface + class StandardProblemIteration : public virtual ProblemIterationInterface { public: /// constructor diff --git a/AMDiS/src/est/Estimator.cc b/AMDiS/src/est/Estimator.cc index c723a2d3..f5cb5807 100644 --- a/AMDiS/src/est/Estimator.cc +++ b/AMDiS/src/est/Estimator.cc @@ -39,10 +39,12 @@ namespace AMDiS { double Estimator::estimate(double ts) - { FUNCNAME("Estimator::estimate()"); + { +// FUNCNAME("Estimator::estimate()"); + bool dualTraverse = false; - +/* for (unsigned int i = 0; i < matrix.size(); i++) { TEST_EXIT(traverseInfo.getStatus(row, i) != SingleComponentInfo::DIF_SPACES_WITH_DIF_AUX) ("Not yet implemented!\n"); @@ -73,10 +75,10 @@ namespace AMDiS { auxFeSpace->getBasisFcts()->getDegree()) ("Mh, do you really want to do this? Think about it ...\n"); } - +*/ -// mesh = uh[row == -1 ? 0 : row]->getFeSpace()->getMesh(); -// auxMesh = NULL; + mesh = uh[row == -1 ? 0 : row]->getFeSpace()->getMesh(); + auxMesh = NULL; init(ts); diff --git a/AMDiS/src/est/ResidualEstimator.cc b/AMDiS/src/est/ResidualEstimator.cc index 3838d795..e0533247 100644 --- a/AMDiS/src/est/ResidualEstimator.cc +++ b/AMDiS/src/est/ResidualEstimator.cc @@ -165,7 +165,7 @@ namespace AMDiS { secondOrderTerms[system] = secondOrderTerms[system] || (*it)->secondOrderTerms(); } } - + #ifdef HAVE_PARALLEL_DOMAIN_AMDIS initParallel(); #endif @@ -180,7 +180,15 @@ namespace AMDiS { if (C1 == 0.0) return; - DOFVector<WorldVector<double> > coords(uh[0]->getFeSpace(), "tmp"); + size_t comp = 0; + for(; comp < uh.size(); comp++) + if(uh[comp]->getFeSpace()->getMesh() == mesh) + break; + + TEST_EXIT_DBG(comp < uh.size())("No mesh in the solution is found?.\n"); + TEST_EXIT_DBG(*(uh[comp]->getFeSpace()->getAdmin()) == mesh->getDofAdmin(0))("The admin is not the first one in the mesh.\n"); + + DOFVector<WorldVector<double> > coords(uh[comp]->getFeSpace(), "tmp"); mesh->getDofIndexCoords(coords); Parallel::InteriorBoundary &intBoundary = @@ -210,14 +218,16 @@ namespace AMDiS { if (bObj.subObj == VERTEX) continue; + bObj.el = intBoundary.getElementPtr(bObj.elIndex, mesh); + TEST_EXIT_DBG(bObj.el)("No element found in the map.\n"); bObj.el->getSubBoundary(bObj, subBound); } - + if (subBound.size() == 0) continue; WorldVector<int> faceIndices; - + for (unsigned int i = 0; i < subBound.size(); i++) { Element *el = subBound[i].el; int oppV = subBound[i].ithObj; @@ -229,7 +239,8 @@ namespace AMDiS { double detNeigh = abs(elInfo->calcGrdLambda(*lambdaNeigh)); stdMpiDet.getSendData(it->first).push_back(detNeigh); - + + for (int system = 0; system < nSystems; system++) { if (matrix[system] == NULL || secondOrderTerms[system] == false) continue; @@ -250,7 +261,7 @@ namespace AMDiS { } stdMpiDet.recv(it->first); - stdMpiGrdUh.recv(it->first); + stdMpiGrdUh.recv(it->first); } stdMpiDet.updateSendDataSize(); @@ -258,7 +269,7 @@ namespace AMDiS { stdMpiDet.startCommunication(); stdMpiGrdUh.startCommunication(); - + for (Parallel::RankToBoundMap::iterator it = allBounds.begin(); it != allBounds.end(); ++it) { vector<BoundaryObject> subBound; @@ -268,18 +279,22 @@ namespace AMDiS { if (bObj.subObj == VERTEX) continue; + bObj.el = intBoundary.getElementPtr(bObj.elIndex, mesh); + TEST_EXIT(bObj.el)("No element found in the map.\n"); bObj.el->getSubBoundary(bObj, subBound); } if (subBound.size() == 0) continue; - + + // Highly possible mesh is not correct, for example: hanging node, if the following error occurs // Highly possible mesh is not correct, for example: hanging node TEST_EXIT_DBG(subBound.size() == stdMpiDet.getRecvData(it->first).size()) - ("Should not happen: %d %d from rank %d\n", subBound.size(), stdMpiDet.getRecvData(it->first).size(), it->first); + ("Should not happen: rank %d from rank %d should recv %d (recv %d)\n", + MPI::COMM_WORLD.Get_rank(), it->first, subBound.size(), stdMpiDet.getRecvData(it->first).size()); TEST_EXIT_DBG(subBound.size() == stdMpiGrdUh.getRecvData(it->first).size()) - ("Should not happen!\n"); + ("Should not happen!\n"); for (unsigned int i = 0; i < subBound.size(); i++) { elBoundDet[subBound[i]] = stdMpiDet.getRecvData(it->first)[i]; diff --git a/AMDiS/src/io/FileWriter.cc b/AMDiS/src/io/FileWriter.cc index 67a6b4aa..cff618c9 100644 --- a/AMDiS/src/io/FileWriter.cc +++ b/AMDiS/src/io/FileWriter.cc @@ -155,7 +155,6 @@ namespace AMDiS // vector<string> componentNames; // for (unsigned int i = 0; i < dataCollectors.size(); i++) // componentNames.push_back(dataCollectors[i]->getValues()->getName()); - VtkWriter::detail::writeParallelFile(paraFilename + paraviewParallelFileExt, MPI::COMM_WORLD.Get_size(), filename, @@ -163,7 +162,8 @@ namespace AMDiS solutionNames, VtkWriter::Vtuformat(paraViewMode), (paraViewPrecision == 1), - writeParaViewVectorFormat); + writeParaViewVectorFormat, + createSubDir > 0); } #endif diff --git a/AMDiS/src/io/FileWriter.hh b/AMDiS/src/io/FileWriter.hh index 1a98bf8d..ef9db694 100644 --- a/AMDiS/src/io/FileWriter.hh +++ b/AMDiS/src/io/FileWriter.hh @@ -263,3 +263,4 @@ namespace AMDiS } // end namespace AMDiS #endif + diff --git a/AMDiS/src/io/detail/VtkWriter.cc b/AMDiS/src/io/detail/VtkWriter.cc index 1c049431..1d834f7a 100644 --- a/AMDiS/src/io/detail/VtkWriter.cc +++ b/AMDiS/src/io/detail/VtkWriter.cc @@ -207,15 +207,16 @@ namespace AMDiS { namespace io { const vector<string> &componentNames, ::AMDiS::io::VtkWriter::Vtuformat format, bool highPrecision, - bool writeAsVector + bool writeAsVector, + bool createSubDir ) { using boost::lexical_cast; vector< string > fileNames(nRanks); - for (int i = 0; i < nRanks; i++) { + for (int i = 0; i < nRanks; i++) fileNames[i] = fnPrefix + "-p" + lexical_cast<string>(i) + "-" + fnPostfix; - } - writeParallelFile(name, nRanks, fileNames, componentNames, format, highPrecision, writeAsVector); + + writeParallelFile(name, nRanks, fileNames, componentNames, format, highPrecision, writeAsVector, createSubDir); } void writeParallelFile(string name, int nRanks, @@ -223,11 +224,11 @@ namespace AMDiS { namespace io { const vector<string> &componentNames, ::AMDiS::io::VtkWriter::Vtuformat format, bool highPrecision, - bool writeAsVector + bool writeAsVector, + bool createSubDir ) { FUNCNAME("writeParallelFile()"); - using boost::lexical_cast; #ifndef HAVE_COMPRESSION @@ -296,9 +297,11 @@ namespace AMDiS { namespace io { for (int i = 0; i < nRanks; i++) { boost::filesystem::path filepath(subNames[i]); - file << " <Piece Source=\"" - << boost::filesystem::basename(filepath) - << boost::filesystem::extension(filepath) << "\"/>\n"; + file << " <Piece Source=\""; + if (createSubDir) + file << "./data/"; + file << boost::filesystem::basename(filepath) + << boost::filesystem::extension(filepath) << "\"/>\n"; } file << " </PUnstructuredGrid>\n"; diff --git a/AMDiS/src/io/detail/VtkWriter.h b/AMDiS/src/io/detail/VtkWriter.h index c01844c8..d65ebbf8 100644 --- a/AMDiS/src/io/detail/VtkWriter.h +++ b/AMDiS/src/io/detail/VtkWriter.h @@ -295,7 +295,8 @@ namespace AMDiS { namespace io { const std::vector<std::string> &componentNames, ::AMDiS::io::VtkWriter::Vtuformat format = ::AMDiS::io::VtkWriter::ASCII, bool highPrecision = false, - bool writeAsVector = false + bool writeAsVector = false, + bool createSubDir = false ); /// Writes a pvtu file which contains the links to the rank files in @subNames @@ -304,7 +305,8 @@ namespace AMDiS { namespace io { const std::vector<std::string> &componentNames, ::AMDiS::io::VtkWriter::Vtuformat format = ::AMDiS::io::VtkWriter::ASCII, bool highPrecision = false, - bool writeAsVector = false + bool writeAsVector = false, + bool createSubDir = false ); /// Writes the connectivity for the case dim = 2 and degree = 2 to an output file. diff --git a/AMDiS/src/parallel/DofComm.cc b/AMDiS/src/parallel/DofComm.cc index 550adde7..2ce3c704 100644 --- a/AMDiS/src/parallel/DofComm.cc +++ b/AMDiS/src/parallel/DofComm.cc @@ -34,40 +34,58 @@ namespace AMDiS { namespace Parallel { void DofComm::init(vector<const FiniteElemSpace*> &fe) { - FUNCNAME("DofComm::init()"); - feSpaces = fe; + mesh = feSpaces[0]->getMesh(); sendDofs.clear(); recvDofs.clear(); periodicDofs.clear(); } - - void DofComm::create(InteriorBoundary &boundary) + void DofComm::create(Mesh* mesh, InteriorBoundary &boundary) { FUNCNAME("DofComm::create()"); + TEST_EXIT(mesh == this->mesh) ("No equal mesh.\n"); - createContainer(boundary.getOwn(), sendDofs); - createContainer(boundary.getOther(), recvDofs); + sendDofs.clear(); + recvDofs.clear(); + periodicDofs.clear(); + + createContainer(mesh, boundary, boundary.getOwn(), sendDofs); + createContainer(mesh, boundary, boundary.getOther(), recvDofs); + +#if (DEBUG != 0) + { + std::set<DegreeOfFreedom> sds; + for (DofComm::Iterator it(sendDofs, feSpaces[0]); + !it.end(); it.nextRank()) + for (; !it.endDofIter(); it.nextDof()) + sds.insert(it.getDofIndex()); + + for (DofComm::Iterator it2(recvDofs, feSpaces[0]); + !it2.end(); it2.nextRank()) + for (; !it2.endDofIter(); it2.nextDof()) + TEST_EXIT(!sds.count(it2.getDofIndex()))("Send and recv have same dofs.\n"); + } +#endif } - void DofComm::createContainer(RankToBoundMap &boundary, + + void DofComm::createContainer(Mesh* mesh, + InteriorBoundary &boundary, + RankToBoundMap &rankToBoundMap, DataType &data) { - FUNCNAME("DofComm::createContainer()"); - // === Fill data. === for (unsigned int i = 0; i < feSpaces.size(); i++) - for (InteriorBoundary::iterator it(boundary); !it.end(); ++it) - it->rankObj.el->getAllDofs(feSpaces[i], it->rankObj, - data[it.getRank()][feSpaces[i]]); - + for (InteriorBoundary::iterator it(rankToBoundMap); !it.end(); ++it) + boundary.getElementPtr(it->rankObj.elIndex, mesh) + ->getAllDofs(feSpaces[i], it->rankObj, data[it.getRank()][feSpaces[i]]); // === Remove empty data containers. === - + DataIter dit = data.begin(); while (dit != data.end()) { FeMapIter it = dit->second.begin(); @@ -100,8 +118,6 @@ namespace AMDiS { namespace Parallel { const FiniteElemSpace *feSpace, bool countDouble) { - FUNCNAME("DofComm::getNumberDofs()"); - DofContainerSet dofSet; DofContainer dofVec; @@ -127,8 +143,6 @@ namespace AMDiS { namespace Parallel { int DofComm::getDegree(const FiniteElemSpace *feSpace, const DegreeOfFreedom *dof) { - FUNCNAME("DofComm::getDegree()"); - int degree = 0; for (map<int, FeMapType>::iterator it = sendDofs.begin(); @@ -151,7 +165,7 @@ namespace AMDiS { namespace Parallel { bool DofComm::Iterator::setNextFeMap() { - FUNCNAME("DofComm::Iterator::setNextFeMap()"); + FUNCNAME_DBG("DofComm::Iterator::setNextFeMap()"); if (dataIter != data.end()) { TEST_EXIT_DBG(dataIter->second.size())("Should not happen!\n"); @@ -182,21 +196,16 @@ namespace AMDiS { namespace Parallel { void MultiLevelDofComm::init(MeshLevelData &levelData, vector<const FiniteElemSpace*> &fe) { - FUNCNAME("MultiLevelDofComm::init()"); - int nLevel = levelData.getNumberOfLevels(); for (int level = 0; level < nLevel; level++) levelDofComm[level].init(fe); } - - void MultiLevelDofComm::create(MultiLevelInteriorBoundary &boundary) + void MultiLevelDofComm::create(Mesh* mesh, MultiLevelInteriorBoundary &boundary) { - FUNCNAME("MultiLevelDofComm::create()"); - for (map<int, DofComm>::iterator it = levelDofComm.begin(); it != levelDofComm.end(); ++it) - it->second.create(boundary[it->first]); + it->second.create(mesh, boundary[it->first]); } } } diff --git a/AMDiS/src/parallel/DofComm.h b/AMDiS/src/parallel/DofComm.h index 40e290ef..c5fb2aff 100644 --- a/AMDiS/src/parallel/DofComm.h +++ b/AMDiS/src/parallel/DofComm.h @@ -46,7 +46,12 @@ namespace AMDiS { namespace Parallel { void init(std::vector<const FiniteElemSpace*> &fe); - void create(InteriorBoundary &boundary); + void create(Mesh* mesh, InteriorBoundary &boundary); + + Mesh* getMesh() + { + return mesh; + } DataType& getSendDofs() { @@ -74,7 +79,9 @@ namespace AMDiS { namespace Parallel { const DegreeOfFreedom *dof); protected: - void createContainer(RankToBoundMap &boundary, + void createContainer(Mesh* mesh, + InteriorBoundary& boundary, + RankToBoundMap& rankToBoundMap, DataType &data); protected: @@ -95,6 +102,8 @@ namespace AMDiS { namespace Parallel { std::vector<const FiniteElemSpace*> feSpaces; + Mesh* mesh; + friend class Iterator; public: @@ -243,10 +252,11 @@ namespace AMDiS { namespace Parallel { class MultiLevelDofComm { public: - void init(MeshLevelData &levelData, - std::vector<const FiniteElemSpace*> &fe); + void init(MeshLevelData &levelData, + std::vector<const FiniteElemSpace*> &fe); - void create(MultiLevelInteriorBoundary &boundary); + void create(Mesh* mesh, MultiLevelInteriorBoundary &boundary); + inline DofComm& operator[](int level) { diff --git a/AMDiS/src/parallel/ElementObjectDatabase.cc b/AMDiS/src/parallel/ElementObjectDatabase.cc index 238aabbb..85fa644b 100644 --- a/AMDiS/src/parallel/ElementObjectDatabase.cc +++ b/AMDiS/src/parallel/ElementObjectDatabase.cc @@ -22,12 +22,24 @@ #include "VertexVector.h" #include "parallel/ElementObjectDatabase.h" #include "parallel/MeshLevelData.h" +#include <fstream> #include "Serializer.h" using namespace std; namespace AMDiS { namespace Parallel { + + void ElementObjectDatabase::init(vector<Mesh*>& meshes_, + map<Mesh*, vector<const FiniteElemSpace*> >& meshToFeSpaces) + { + meshes = meshes_; + for(size_t i = 0; i < meshes.size(); i++) + feSpaces.push_back(meshToFeSpaces[meshes[i]][0]); + + macroMesh = meshes[0]; + feSpace = meshToFeSpaces[macroMesh][0]; + } void ElementObjectData::serialize(std::ostream &out) const { @@ -45,40 +57,50 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::create(map<int, int>& rankMap, MeshLevelData& ld) { - FUNCNAME("ElementObjectDatabase::create()"); + FUNCNAME_DBG("ElementObjectDatabase::create()"); macroElementRankMap = &rankMap; levelData = &ld; - // === Reset temporary data === tmpVertexElements.clear(); tmpEdgeElements.clear(); tmpFaceElements.clear(); - // === Fills macro element data structures. === TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, - Mesh::CALL_LEAF_EL | - Mesh::FILL_NEIGH | - Mesh::FILL_BOUND); - while (elInfo) { - TEST_EXIT_DBG(elInfo->getLevel() == 0)("Should not happen!\n"); - - Element *el = elInfo->getElement(); - macroElIndexMap.insert(make_pair(el->getIndex(), el)); - macroElIndexTypeMap.insert(make_pair(el->getIndex(), elInfo->getType())); - - // Add all sub object of the element to the variable elObjDb. - addElement(elInfo); - - elInfo = stack.traverseNext(elInfo); - } - + ElInfo* elInfo = NULL; + + for(size_t i = 0; i < meshes.size(); i++) { + + elInfo = stack.traverseFirst(meshes[i], -1, + Mesh::CALL_LEAF_EL | + Mesh::FILL_NEIGH | + Mesh::FILL_BOUND); + while (elInfo) { + TEST_EXIT_DBG(elInfo->getLevel() == 0)("Should not happen!\n"); + + Element *el = elInfo->getElement(); + + // Macro data info is stored once. + if (i == 0) { + macroElIndexTypeMap.insert(make_pair(el->getIndex(), elInfo->getType())); + + // Add all sub object of the element to the variable elObjDb. + addElement(el); + + addElementPeriodicBoundary(elInfo); + } + // Element pointer has to be stored for each mesh one copy. + macroElIndexMap[el->getIndex()][meshes[i]] = el; + + elInfo = stack.traverseNext(elInfo); + } + } + // === Move temporary data to original one === for (map<DegreeOfFreedom, vector<ElementObjectData> >::iterator it = tmpVertexElements.begin(); @@ -96,38 +118,33 @@ namespace AMDiS { namespace Parallel { faceElements[it->first] = it->second; tmpFaceElements.clear(); - - // Handle periodic boudaries createPeriodicData(); // Create data about the reverse modes of neighbouring elements. createReverseModeData(); } - - - void ElementObjectDatabase::createMacroElementInfo(vector<MacroElement*> &mel) + + void ElementObjectDatabase::createMacroElementInfo(std::map<Mesh*, std::vector<MacroElement*> >& mel) { macroElIndexMap.clear(); macroElIndexTypeMap.clear(); - - for (vector<MacroElement*>::iterator it = mel.begin(); - it != mel.end(); ++it) { - macroElIndexMap.insert(make_pair((*it)->getIndex(), (*it)->getElement())); - macroElIndexTypeMap.insert(make_pair((*it)->getIndex(), (*it)->getElType())); + + std::map<Mesh*, std::vector<MacroElement*> >::iterator iter = mel.begin(); + while(iter != mel.end()) { + Mesh* mesh = iter->first; + for (vector<MacroElement*>::iterator it = iter->second.begin(); + it != iter->second.end(); it++) { + macroElIndexMap[(*it)->getIndex()][mesh] = (*it)->getElement(); + if(iter == mel.begin()) + macroElIndexTypeMap.insert(make_pair((*it)->getIndex(), (*it)->getElType())); + } + iter++; } } - - void ElementObjectDatabase::addElement(ElInfo *elInfo) + void ElementObjectDatabase::addElement(Element *el) { - FUNCNAME("ElementObjectDatabase::addElement()"); - - TEST_EXIT_DBG(mesh)("Mesh not set!\n"); - - Element *el = elInfo->getElement(); - - // === First, add all element objects to the database. === for (int i = 0; i < el->getGeo(VERTEX); i++) @@ -138,14 +155,20 @@ namespace AMDiS { namespace Parallel { for (int i = 0; i < el->getGeo(FACE); i++) addFace(el, i); + } + + void ElementObjectDatabase::addElementPeriodicBoundary(ElInfo* elInfo) + { + FUNCNAME("ElementObjectDatabase::addElementPeriodicBoundary()"); + TEST_EXIT_DBG(macroMesh)("Mesh not set!\n"); - // === Get periodic boundary information. === + Element *el = elInfo->getElement(); - switch (mesh->getDim()) { + switch (macroMesh->getDim()) { case 2: for (int i = 0; i < el->getGeo(EDGE); i++) { - if (mesh->isPeriodicAssociation(elInfo->getBoundary(EDGE, i))) { + if (macroMesh->isPeriodicAssociation(elInfo->getBoundary(EDGE, i))) { // The current element's i-th edge is periodic. Element *neigh = elInfo->getNeighbour(i); @@ -161,9 +184,9 @@ namespace AMDiS { namespace Parallel { // Add both vertices of the edge to be periodic. DegreeOfFreedom mappedDof0 = - mesh->getPeriodicAssociations(boundaryType)[edge0.first]; + macroMesh->getPeriodicAssociations(boundaryType)[edge0.first]; DegreeOfFreedom mappedDof1 = - mesh->getPeriodicAssociations(boundaryType)[edge0.second]; + macroMesh->getPeriodicAssociations(boundaryType)[edge0.second]; periodicVertices[make_pair(edge0.first, mappedDof0)] = boundaryType; periodicVertices[make_pair(edge0.second, mappedDof1)] = boundaryType; @@ -174,7 +197,7 @@ namespace AMDiS { namespace Parallel { break; case 3: for (int i = 0; i < el->getGeo(FACE); i++) { - if (mesh->isPeriodicAssociation(elInfo->getBoundary(FACE, i))) { + if (macroMesh->isPeriodicAssociation(elInfo->getBoundary(FACE, i))) { // The current element's i-th face is periodic. Element *neigh = elInfo->getNeighbour(i); @@ -189,11 +212,11 @@ namespace AMDiS { namespace Parallel { /// Add all three vertices of the face to be periodic. DegreeOfFreedom mappedDof0 = - mesh->getPeriodicAssociations(boundaryType)[face0.get<0>()]; + macroMesh->getPeriodicAssociations(boundaryType)[face0.get<0>()]; DegreeOfFreedom mappedDof1 = - mesh->getPeriodicAssociations(boundaryType)[face0.get<1>()]; + macroMesh->getPeriodicAssociations(boundaryType)[face0.get<1>()]; DegreeOfFreedom mappedDof2 = - mesh->getPeriodicAssociations(boundaryType)[face0.get<2>()]; + macroMesh->getPeriodicAssociations(boundaryType)[face0.get<2>()]; periodicVertices[make_pair(face0.get<0>(), mappedDof0)] = boundaryType; periodicVertices[make_pair(face0.get<1>(), mappedDof1)] = boundaryType; @@ -204,11 +227,11 @@ namespace AMDiS { namespace Parallel { periodicDofAssoc[face0.get<2>()].insert(boundaryType); TEST_EXIT_DBG(face0.get<0>() == - mesh->getPeriodicAssociations(boundaryType)[face1.get<0>()] && + macroMesh->getPeriodicAssociations(boundaryType)[face1.get<0>()] && face0.get<1>() == - mesh->getPeriodicAssociations(boundaryType)[face1.get<1>()] && + macroMesh->getPeriodicAssociations(boundaryType)[face1.get<1>()] && face0.get<2>() == - mesh->getPeriodicAssociations(boundaryType)[face1.get<2>()]) + macroMesh->getPeriodicAssociations(boundaryType)[face1.get<2>()]) ("Should not happen!\n"); // Create all three edges of the element and add them to be periodic. @@ -231,7 +254,8 @@ namespace AMDiS { namespace Parallel { break; default: ERROR_EXIT("Should not happen!\n"); - } + } + } @@ -248,8 +272,6 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::addEdge(Element *el, int ith) { - FUNCNAME("ElementObjectDatabase::addEdge()"); - DofEdge edge = el->getEdge(ith); int elIndex = el->getIndex(); ElementObjectData elObj(elIndex, ith); @@ -272,9 +294,9 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::createPeriodicData() { - FUNCNAME("ElementObjectDatabase::createPeriodicData()"); + FUNCNAME_DBG("ElementObjectDatabase::createPeriodicData()"); - TEST_EXIT_DBG(mesh)("Mesh not set!\n"); + TEST_EXIT_DBG(macroMesh)("Mesh not set!\n"); // === Return, if there are no periodic vertices, i.e., there are no === // === periodic boundaries in the mesh. === @@ -285,8 +307,8 @@ namespace AMDiS { namespace Parallel { // === Calculate smallest periodic boundary ID in mesh. === smallestPeriodicBcType = 0; - for (map<BoundaryType, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin(); - it != mesh->getPeriodicAssociations().end(); ++it) + for (map<BoundaryType, VertexVector*>::iterator it = macroMesh->getPeriodicAssociations().begin(); + it != macroMesh->getPeriodicAssociations().end(); ++it) smallestPeriodicBcType = std::min(smallestPeriodicBcType, it->first); // === Get all vertex DOFs that have multiple periodic associations. === @@ -299,8 +321,8 @@ namespace AMDiS { namespace Parallel { vector<DegreeOfFreedom> multPeriodicDof2, multPeriodicDof3; for (map<DegreeOfFreedom, std::set<BoundaryType> >::iterator it = periodicDofAssoc.begin(); it != periodicDofAssoc.end(); ++it) { - TEST_EXIT_DBG((mesh->getDim() == 2 && it->second.size() <= 2) || - (mesh->getDim() == 3 && it->second.size() <= 3)) + TEST_EXIT_DBG((macroMesh->getDim() == 2 && it->second.size() <= 2) || + (macroMesh->getDim() == 3 && it->second.size() <= 3)) ("Should not happen!\n"); if (it->second.size() == 2) @@ -309,14 +331,14 @@ namespace AMDiS { namespace Parallel { multPeriodicDof3.push_back(it->first); } - if (mesh->getDim() == 2) { + if (macroMesh->getDim() == 2) { TEST_EXIT_DBG(multPeriodicDof2.size() == 0 || multPeriodicDof2.size() == 4) ("Should not happen (%d)!\n", multPeriodicDof2.size()); TEST_EXIT_DBG(multPeriodicDof3.size() == 0)("Should not happen!\n"); } - if (mesh->getDim() == 3) { + if (macroMesh->getDim() == 3) { TEST_EXIT_DBG(multPeriodicDof3.size() == 0 || multPeriodicDof3.size() == 8) ("Should not happen (%d)!\n", multPeriodicDof3.size()); @@ -401,7 +423,7 @@ namespace AMDiS { namespace Parallel { for (map<DofEdge, std::set<DofEdge> >::iterator it = periodicEdgeAssoc.begin(); it != periodicEdgeAssoc.end(); ++it) { if (it->second.size() > 1) { - TEST_EXIT_DBG(mesh->getDim() == 3)("Should not happen!\n"); + TEST_EXIT_DBG(macroMesh->getDim() == 3)("Should not happen!\n"); TEST_EXIT_DBG(it->second.size() == 2)("Should not happen!\n"); DofEdge edge0 = it->first; @@ -462,31 +484,31 @@ namespace AMDiS { namespace Parallel { #endif } - BoundaryType ElementObjectDatabase::getNewBoundaryType() { - FUNCNAME("ElementObjectDatabase::getNewBoundaryType()"); + FUNCNAME_DBG("ElementObjectDatabase::getNewBoundaryType()"); BoundaryType newPeriodicBoundaryType = 0; - for (map<BoundaryType, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin(); - it != mesh->getPeriodicAssociations().end(); ++it) + for (map<BoundaryType, VertexVector*>::iterator it = macroMesh->getPeriodicAssociations().begin(); + it != macroMesh->getPeriodicAssociations().end(); ++it) newPeriodicBoundaryType = std::min(newPeriodicBoundaryType, it->first); TEST_EXIT_DBG(newPeriodicBoundaryType < 0)("Should not happen!\n"); newPeriodicBoundaryType--; - mesh->getPeriodicAssociations()[newPeriodicBoundaryType] = - new VertexVector(feSpace->getAdmin(), ""); - + for(size_t i = 0; i < meshes.size(); i++) { + meshes[i]->getPeriodicAssociations()[newPeriodicBoundaryType] = + new VertexVector(feSpaces[i]->getAdmin(), ""); + } + return newPeriodicBoundaryType; } - - + BoundaryType ElementObjectDatabase::provideConnectedPeriodicBoundary(BoundaryType b0, BoundaryType b1) { - FUNCNAME("ElementObjectDatabase::provideConnectedPeriodicBoundary()"); + FUNCNAME_DBG("ElementObjectDatabase::provideConnectedPeriodicBoundary()"); std::pair<BoundaryType, BoundaryType> bConn = (b0 <= b1 ? make_pair(b0, b1) : make_pair(b1, b0)); @@ -494,25 +516,27 @@ namespace AMDiS { namespace Parallel { if (bConnMap.count(bConn) == 0) { BoundaryType newPeriodicBoundaryType = getNewBoundaryType(); - VertexVector &vecB0 = mesh->getPeriodicAssociations(b0); - VertexVector &vecB1 = mesh->getPeriodicAssociations(b1); - VertexVector &vecC = mesh->getPeriodicAssociations(newPeriodicBoundaryType); + for(size_t i = 0; i < meshes.size(); i++) { + + VertexVector &vecB0 = meshes[i]->getPeriodicAssociations(b0); + VertexVector &vecB1 = meshes[i]->getPeriodicAssociations(b1); + VertexVector &vecC = meshes[i]->getPeriodicAssociations(newPeriodicBoundaryType); - DOFIteratorBase it(const_cast<DOFAdmin*>(feSpace->getAdmin()), USED_DOFS); + DOFIteratorBase it(const_cast<DOFAdmin*>(feSpaces[i]->getAdmin()), USED_DOFS); - for (it.reset(); !it.end(); ++it) { - if (!it.isDofFree()) { - TEST_EXIT_DBG(vecB1[vecB0[it.getDOFIndex()]] == vecB0[vecB1[it.getDOFIndex()]]) - ("Should not happen!\n"); + for (it.reset(); !it.end(); ++it) { + if (!it.isDofFree()) { + TEST_EXIT_DBG(vecB1[vecB0[it.getDOFIndex()]] == vecB0[vecB1[it.getDOFIndex()]]) + ("Should not happen!\n"); - vecC[it.getDOFIndex()] = vecB1[vecB0[it.getDOFIndex()]]; + vecC[it.getDOFIndex()] = vecB1[vecB0[it.getDOFIndex()]]; + } } } bConnMap[bConn] = newPeriodicBoundaryType; } - - + return bConnMap[bConn]; } @@ -560,8 +584,6 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::clear() { - FUNCNAME("ElementObjectDatabase::clear()"); - vertexElements.clear(); edgeElements.clear(); faceElements.clear(); @@ -592,11 +614,11 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::createReverseModeData() { - FUNCNAME("ElementObjectDatabase::createReverseModeData()"); + FUNCNAME_DBG("ElementObjectDatabase::createReverseModeData()"); // === In 2D, all reverse modes are always true! === - if (mesh->getDim() == 2) + if (macroMesh->getDim() == 2) return; @@ -608,12 +630,12 @@ namespace AMDiS { namespace Parallel { vector<ElementObjectData>& els = edgeIt->second; for (unsigned int i = 0; i < els.size(); i++) { - BoundaryObject obj0(macroElIndexMap[els[i].elIndex], + BoundaryObject obj0(macroElIndexMap[els[i].elIndex][macroMesh], macroElIndexTypeMap[els[i].elIndex], EDGE, els[i].ithObject); for (unsigned int j = i + 1; j < els.size(); j++) { - BoundaryObject obj1(macroElIndexMap[els[j].elIndex], + BoundaryObject obj1(macroElIndexMap[els[j].elIndex][macroMesh], macroElIndexTypeMap[els[j].elIndex], EDGE, els[j].ithObject); @@ -633,12 +655,12 @@ namespace AMDiS { namespace Parallel { vector<ElementObjectData>& els = faceIt->second; for (unsigned int i = 0; i < els.size(); i++) { - BoundaryObject obj0(macroElIndexMap[els[i].elIndex], + BoundaryObject obj0(macroElIndexMap[els[i].elIndex][macroMesh], macroElIndexTypeMap[els[i].elIndex], FACE, els[i].ithObject); for (unsigned int j = i + 1; j < els.size(); j++) { - BoundaryObject obj1(macroElIndexMap[els[j].elIndex], + BoundaryObject obj1(macroElIndexMap[els[j].elIndex][macroMesh], macroElIndexTypeMap[els[j].elIndex], FACE, els[j].ithObject); @@ -661,12 +683,12 @@ namespace AMDiS { namespace Parallel { vector<ElementObjectData> &edges1 = edgeElements[edgeIt->first.second]; for (unsigned int i = 0; i < edges0.size(); i++) { - BoundaryObject obj0(macroElIndexMap[edges0[i].elIndex], + BoundaryObject obj0(macroElIndexMap[edges0[i].elIndex][macroMesh], macroElIndexTypeMap[edges0[i].elIndex], EDGE, edges0[i].ithObject); for (unsigned int j = 0; j < edges1.size(); j++) { - BoundaryObject obj1(macroElIndexMap[edges1[j].elIndex], + BoundaryObject obj1(macroElIndexMap[edges1[j].elIndex][macroMesh], macroElIndexTypeMap[edges1[j].elIndex], EDGE, edges1[j].ithObject); @@ -686,12 +708,12 @@ namespace AMDiS { namespace Parallel { vector<ElementObjectData> &faces0 = faceElements[faceIt->first.first]; vector<ElementObjectData> &faces1 = faceElements[faceIt->first.second]; - TEST_EXIT_DBG(faces0.size() == faces1.size() == 1)("Should not happen!\n"); + TEST_EXIT_DBG((faces0.size() == 1) && (faces1.size() == 1))("Should not happen!\n"); - BoundaryObject obj0(macroElIndexMap[faces0[0].elIndex], + BoundaryObject obj0(macroElIndexMap[faces0[0].elIndex][macroMesh], macroElIndexTypeMap[faces0[0].elIndex], FACE, faces0[0].ithObject); - BoundaryObject obj1(macroElIndexMap[faces1[0].elIndex], + BoundaryObject obj1(macroElIndexMap[faces1[0].elIndex][macroMesh], macroElIndexTypeMap[faces1[0].elIndex], FACE, faces1[0].ithObject); @@ -751,7 +773,7 @@ namespace AMDiS { namespace Parallel { int ElementObjectDatabase::getOwner(vector<ElementObjectData>& objData, int level) { - FUNCNAME("ElementObjectDatabase::getOwner()"); + FUNCNAME_DBG("ElementObjectDatabase::getOwner()"); int owner = -1; @@ -826,8 +848,6 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::serialize(ostream &out) { - FUNCNAME("ElementObjectDatabase::serialize()"); - int nSize = vertexElements.size(); SerUtil::serialize(out, nSize); for (flat_map<DegreeOfFreedom, vector<ElementObjectData> >::iterator it = vertexElements.begin(); @@ -946,8 +966,6 @@ namespace AMDiS { namespace Parallel { void ElementObjectDatabase::deserialize(istream &in) { - FUNCNAME("ElementObjectDatabase::deserialize()"); - int nSize; SerUtil::deserialize(in, nSize); vertexElements.clear(); @@ -1142,7 +1160,7 @@ namespace AMDiS { namespace Parallel { } } - + //TODO: 047 not yet reimplemented. unsigned long ElementObjectDatabase::calculateMemoryUsage() { FUNCNAME("ElementObjectDatabase::calculateMemoryUsage()"); diff --git a/AMDiS/src/parallel/ElementObjectDatabase.h b/AMDiS/src/parallel/ElementObjectDatabase.h index 2e5fed1b..f2355ab8 100644 --- a/AMDiS/src/parallel/ElementObjectDatabase.h +++ b/AMDiS/src/parallel/ElementObjectDatabase.h @@ -38,6 +38,7 @@ //#include "Serializer.h" #include "FiniteElemSpace.h" #include "Mesh.h" +#include "parallel/ParallelTypes.h" namespace AMDiS { namespace Parallel { @@ -102,21 +103,18 @@ namespace AMDiS { namespace Parallel { public: ElementObjectDatabase() : feSpace(NULL), - mesh(NULL), + macroMesh(NULL), iterGeoPos(CENTER), macroElementRankMap(NULL), levelData(NULL) {} - - void setFeSpace(const FiniteElemSpace *fe) - { - feSpace = fe; - mesh = feSpace->getMesh(); - } + + void init(std::vector<Mesh*>&, + std::map<Mesh*, std::vector<const FiniteElemSpace*> >&); Mesh* getMesh() { - return mesh; + return macroMesh; } /* @@ -126,7 +124,7 @@ namespace AMDiS { namespace Parallel { void create(std::map<int, int>& macroElementRankMap, MeshLevelData& levelData); - void createMacroElementInfo(std::vector<MacroElement*> &mel); + void createMacroElementInfo(std::map<Mesh*, std::vector<MacroElement*> >& mel); /// Create for a filled object database the membership information for all /// element objects. An object is owned by a rank, if the rank has the @@ -405,7 +403,7 @@ namespace AMDiS { namespace Parallel { inline bool getEdgeReverseMode(ElementObjectData &obj0, ElementObjectData &obj1) { - if (mesh->getDim() == 2) + if (macroMesh->getDim() == 2) return true; if (edgeReverseMode.empty()) @@ -437,9 +435,17 @@ namespace AMDiS { namespace Parallel { return (t >= smallestPeriodicBcType); } - inline Element* getElementPtr(int index) + inline Element* getElementPtr(int index, Mesh* mesh) { - return macroElIndexMap[index]; + FUNCNAME_DBG("ElementObjectDatabase::getElementPtr()"); + TEST_EXIT_DBG(macroElIndexMap[index][mesh]) + ("No element pointer in macroElIndex map. Something is wrong.\n"); + return macroElIndexMap[index][mesh]; + } + + inline MacroElIndexMap& getElIndexMap() + { + return macroElIndexMap; } inline int getElementType(int index) @@ -469,9 +475,11 @@ namespace AMDiS { namespace Parallel { * periodic boundary, all information about subobjects of the element on * this boundary are collected. * - * \param[in] elInfo ElInfo object of the element. + * \param[in] Element the element. */ - void addElement(ElInfo *elInfo); + void addElement(Element* el); + + void addElementPeriodicBoundary(ElInfo* elInfo); /// Adds the i-th DOF vertex of an element to the object database. void addVertex(Element *el, int ith); @@ -515,9 +523,14 @@ namespace AMDiS { namespace Parallel { private: const FiniteElemSpace* feSpace; - /// The mesh that is used to store all its element information in - /// the database. - Mesh *mesh; + /// The macro mesh that is used to store all its element information in the database. + Mesh *macroMesh; + + /// Used to get mesh or element pointers. meshes[0] is always equal to \ref macroMesh + std::vector<Mesh*> meshes; + + /// Corresponding FE spaces of meshes. + std::vector<const FiniteElemSpace*> feSpaces; /// Maps to each vertex DOF all element objects that represent this vertex. @@ -608,12 +621,14 @@ namespace AMDiS { namespace Parallel { std::map<int, int> *macroElementRankMap; /// Maps to each macro element index a pointer to the corresponding element. - flat_map<int, Element*> macroElIndexMap; + MacroElIndexMap macroElIndexMap; /// Maps to each macro element index the type of this element. flat_map<int, int> macroElIndexTypeMap; MeshLevelData* levelData; + + friend class ParallelDebug; }; } } diff --git a/AMDiS/src/parallel/InteriorBoundary.cc b/AMDiS/src/parallel/InteriorBoundary.cc index bfdfc94d..4eb43ec0 100644 --- a/AMDiS/src/parallel/InteriorBoundary.cc +++ b/AMDiS/src/parallel/InteriorBoundary.cc @@ -31,17 +31,17 @@ namespace AMDiS { namespace Parallel { using namespace std; - void InteriorBoundary::create(MeshLevelData &levelData, int level, ElementObjectDatabase &elObjDb) { - FUNCNAME("InteriorBoundary::clear()"); + FUNCNAME("InteriorBoundary::create()"); own.clear(); other.clear(); periodic.clear(); + macroElIndexMap = elObjDb.getElIndexMap(); Mesh *mesh = elObjDb.getMesh(); TEST_EXIT_DBG(mesh)("Should not happen!\n"); TEST_EXIT_DBG(level < levelData.getNumberOfLevels()) @@ -96,17 +96,16 @@ namespace AMDiS { namespace Parallel { AtomicBoundary bound; bound.maxLevel = elObjDb.getIterateMaxLevel(); - bound.rankObj.el = elObjDb.getElementPtr(rankBoundEl.elIndex); bound.rankObj.elIndex = rankBoundEl.elIndex; bound.rankObj.elType = elObjDb.getElementType(rankBoundEl.elIndex); bound.rankObj.subObj = geoIndex; bound.rankObj.ithObj = rankBoundEl.ithObject; - if (geoIndex == FACE) { for (int edgeNo = 0; edgeNo < 3; edgeNo++) { + Element* el = elObjDb.getElementPtr(bound.rankObj.elIndex, mesh); int edgeOfFace = - bound.rankObj.el->getEdgeOfFace(bound.rankObj.ithObj, edgeNo); + el->getEdgeOfFace(bound.rankObj.ithObj, edgeNo); bound.rankObj.excludedSubstructures.push_back(make_pair(EDGE, edgeOfFace)); } @@ -122,7 +121,6 @@ namespace AMDiS { namespace Parallel { if (!levelData.rankInLevel(it2->first, level)) continue; - bound.neighObj.el = elObjDb.getElementPtr(it2->second.elIndex); bound.neighObj.elIndex = it2->second.elIndex; bound.neighObj.elType = elObjDb.getElementType(it2->second.elIndex); bound.neighObj.subObj = geoIndex; @@ -147,7 +145,6 @@ namespace AMDiS { namespace Parallel { ElementObjectData& ownerBoundEl = objData[owner]; - bound.neighObj.el = elObjDb.getElementPtr(ownerBoundEl.elIndex); bound.neighObj.elIndex = ownerBoundEl.elIndex; bound.neighObj.elType = -1; bound.neighObj.subObj = geoIndex; @@ -168,7 +165,6 @@ namespace AMDiS { namespace Parallel { } } - // === Create periodic boundary data structure. === int removePeriodicBoundary = 0; @@ -190,13 +186,11 @@ namespace AMDiS { namespace Parallel { ElementObjectData& perDofEl1 = elIt->second; AtomicBoundary bound; - bound.rankObj.el = elObjDb.getElementPtr(perDofEl0.elIndex); bound.rankObj.elIndex = perDofEl0.elIndex; bound.rankObj.elType = elObjDb.getElementType(perDofEl0.elIndex); bound.rankObj.subObj = VERTEX; bound.rankObj.ithObj = perDofEl0.ithObject; - bound.neighObj.el = elObjDb.getElementPtr(perDofEl1.elIndex); bound.neighObj.elIndex = perDofEl1.elIndex; bound.neighObj.elType = elObjDb.getElementType(perDofEl1.elIndex); bound.neighObj.subObj = VERTEX; @@ -250,7 +244,6 @@ namespace AMDiS { namespace Parallel { b = bound; } else { ElementObjectData& ownerBoundEl = objData[owner]; - bound.neighObj.el = elObjDb.getElementPtr(ownerBoundEl.elIndex); bound.neighObj.elIndex = ownerBoundEl.elIndex; bound.neighObj.elType = -1; bound.neighObj.ithObj = ownerBoundEl.ithObject; @@ -286,13 +279,11 @@ namespace AMDiS { namespace Parallel { ElementObjectData& perEdgeEl1 = elIt->second; AtomicBoundary bound; - bound.rankObj.el = elObjDb.getElementPtr(perEdgeEl0.elIndex); bound.rankObj.elIndex = perEdgeEl0.elIndex; bound.rankObj.elType = elObjDb.getElementType(perEdgeEl0.elIndex); bound.rankObj.subObj = EDGE; bound.rankObj.ithObj = perEdgeEl0.ithObject; - bound.neighObj.el = elObjDb.getElementPtr(perEdgeEl1.elIndex); bound.neighObj.elIndex = perEdgeEl1.elIndex; bound.neighObj.elType = elObjDb.getElementType(perEdgeEl1.elIndex); bound.neighObj.subObj = EDGE; @@ -326,7 +317,6 @@ namespace AMDiS { namespace Parallel { b = bound; ElementObjectData& ownerBoundEl = objData[owner]; - b.neighObj.el = elObjDb.getElementPtr(ownerBoundEl.elIndex); b.neighObj.elIndex = ownerBoundEl.elIndex; b.neighObj.elType = -1; b.neighObj.ithObj = ownerBoundEl.ithObject; @@ -371,13 +361,11 @@ namespace AMDiS { namespace Parallel { ElementObjectData& perFaceEl1 = elIt->second; AtomicBoundary bound; - bound.rankObj.el = elObjDb.getElementPtr(perFaceEl0.elIndex); bound.rankObj.elIndex = perFaceEl0.elIndex; bound.rankObj.elType = elObjDb.getElementType(perFaceEl0.elIndex); bound.rankObj.subObj = FACE; bound.rankObj.ithObj = perFaceEl0.ithObject; - bound.neighObj.el = elObjDb.getElementPtr(perFaceEl1.elIndex); bound.neighObj.elIndex = perFaceEl1.elIndex; bound.neighObj.elType = elObjDb.getElementType(perFaceEl1.elIndex); bound.neighObj.subObj = FACE; @@ -405,7 +393,6 @@ namespace AMDiS { namespace Parallel { b = bound; ElementObjectData& ownerBoundEl = objData[owner]; - b.neighObj.el = elObjDb.getElementPtr(ownerBoundEl.elIndex); b.neighObj.elIndex = ownerBoundEl.elIndex; b.neighObj.elType = -1; b.neighObj.ithObj = ownerBoundEl.ithObject; @@ -579,8 +566,6 @@ namespace AMDiS { namespace Parallel { void InteriorBoundary::serialize(ostream &out, RankToBoundMap& boundary) { - FUNCNAME("InteriorBoundary::serialize()"); - int mSize = boundary.size(); SerUtil::serialize(out, mSize); for (RankToBoundMap::iterator it = boundary.begin(); @@ -627,7 +612,7 @@ namespace AMDiS { namespace Parallel { RankToBoundMap& boundary, map<int, Element*> &elIndexMap) { - FUNCNAME("InteriorBoundary::deserialize()"); + FUNCNAME_DBG("InteriorBoundary::deserialize()"); int mSize = 0; SerUtil::deserialize(in, mSize); @@ -707,8 +692,6 @@ namespace AMDiS { namespace Parallel { AtomicBoundary& InteriorBoundary::getNewOwn(int rank) { - FUNCNAME("InteriorBoundary::getNewOwn()"); - int size = own[rank].size(); own[rank].resize(size + 1); return own[rank][size]; @@ -717,8 +700,6 @@ namespace AMDiS { namespace Parallel { AtomicBoundary& InteriorBoundary::getNewOther(int rank) { - FUNCNAME("InteriorBoundary::getNewOther()"); - int size = other[rank].size(); other[rank].resize(size + 1); return other[rank][size]; @@ -765,8 +746,6 @@ namespace AMDiS { namespace Parallel { bool InteriorBoundary::removeOwn(BoundaryObject& bound) { - FUNCNAME("InteriorBoundary::removeOwn()"); - bool removed = false; for (map<int, vector<AtomicBoundary> >::iterator it = own.begin(); @@ -787,8 +766,6 @@ namespace AMDiS { namespace Parallel { bool InteriorBoundary::removeOther(BoundaryObject& bound) { - FUNCNAME("InteriorBoundary::removeOther()"); - bool removed = false; for (map<int, vector<AtomicBoundary> >::iterator it = other.begin(); @@ -841,8 +818,6 @@ namespace AMDiS { namespace Parallel { void MultiLevelInteriorBoundary::create(MeshLevelData &levelData, ElementObjectDatabase &elObjDb) { - FUNCNAME(" MultLevelInteriorBoundary::create()"); - levelIntBound.clear(); int nLevel = levelData.getNumberOfLevels(); diff --git a/AMDiS/src/parallel/InteriorBoundary.h b/AMDiS/src/parallel/InteriorBoundary.h index ce9b03f8..2df6d68b 100644 --- a/AMDiS/src/parallel/InteriorBoundary.h +++ b/AMDiS/src/parallel/InteriorBoundary.h @@ -48,6 +48,19 @@ namespace AMDiS { namespace Parallel { { return own; } + + inline MacroElIndexMap& getElIndexMap() + { + return macroElIndexMap; + } + + inline Element* getElementPtr(int index, Mesh* mesh) + { + FUNCNAME_DBG("ElementObjectDatabase::getElementPtr()"); + TEST_EXIT_DBG(macroElIndexMap[index][mesh]) + ("No element pointer in macroElIndex map. Something is wrong.\n"); + return macroElIndexMap[index][mesh]; + } RankToBoundMap& getOther() { @@ -126,6 +139,8 @@ namespace AMDiS { namespace Parallel { private: RankToBoundMap own, other, periodic; + + MacroElIndexMap macroElIndexMap; friend class ParallelDebug; diff --git a/AMDiS/src/parallel/MatrixNnzStructure.cc b/AMDiS/src/parallel/MatrixNnzStructure.cc index a4ee9eb8..fa388647 100644 --- a/AMDiS/src/parallel/MatrixNnzStructure.cc +++ b/AMDiS/src/parallel/MatrixNnzStructure.cc @@ -48,7 +48,6 @@ namespace AMDiS { namespace Parallel { } } - void MatrixNnzStructure::create(Matrix<DOFMatrix*> &mat, ParallelDofMapping &rowDofMap, ParallelDofMapping &colDofMap, @@ -58,11 +57,14 @@ namespace AMDiS { namespace Parallel { { FUNCNAME("MatrixNnzStructure::create()"); - int nRankRows = rowDofMap.getRankDofs(); // Number of DOFs owned by rank. - int rankStartRowIndex = rowDofMap.getStartDofs(); // Smallest global index of a DOF owned by the rank. + int nRankRows = rowDofMap.getRankDofs(); // Number of DOFs owned by rank. + + int rankStartRowIndex = rowDofMap.getStartDofs(); // Smallest global index of a DOF owned by the rank. int nRankCols = colDofMap.getRankDofs(); + int nOverallCols = colDofMap.getOverallDofs(); // Number of global DOFs (this value is thus the same on all ranks). + int rankStartColIndex = colDofMap.getStartDofs(); create(nRankRows, (!localMatrix ? nRankRows : -1)); @@ -98,7 +100,7 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(feSpace)("No FE space found!\n"); - for (DofComm::Iterator it(rowDofMap.getDofComm().getRecvDofs(), feSpace); + for (DofComm::Iterator it(rowDofMap.getDofComm(feSpace).getRecvDofs(), feSpace); !it.end(); it.nextRank()) { sendMatrixEntry[it.getRank()].resize(0); @@ -115,7 +117,7 @@ namespace AMDiS { namespace Parallel { if (mat[i][j]) feSpace = mat[i][j]->getRowFeSpace(); - for (DofComm::Iterator it(rowDofMap.getDofComm().getSendDofs(), feSpace); + for (DofComm::Iterator it(rowDofMap.getDofComm(feSpace).getSendDofs(), feSpace); !it.end(); it.nextRank()) recvFromRank.insert(it.getRank()); } @@ -151,15 +153,15 @@ namespace AMDiS { namespace Parallel { // === Iterate on all DOFs of the row mapping. === - DofMap::iterator rowIt = rowDofMap[rowComp].begin(); + DofMap::iterator rowIt = rowDofMap[rowComp].begin(); // row dofmap DOFIt DofMap::iterator rowEndIt = rowDofMap[rowComp].end(); for (; rowIt != rowEndIt; ++rowIt) { // Go to the corresponding matrix row (note, both the mapping and the // matrix rows are stored in increasing order). - while (cursor.value() != rowIt->first) + while (cursor.value() != rowIt->first) ++cursor; - size_t _row = cursor.value(); + size_t _row = cursor.value(); // DegreeOfFreedom // The corresponding global matrix row index of the current row DOF. int petscRowIdx = 0; @@ -190,7 +192,7 @@ namespace AMDiS { namespace Parallel { if (localMatrix == false) localPetscRowIdx -= rankStartRowIndex; - TEST_EXIT_DBG(localPetscRowIdx >= 0 && localPetscRowIdx < nRankRows) + TEST_EXIT(localPetscRowIdx >= 0 && localPetscRowIdx < nRankRows) ("Should not happen! \n Debug info: DOF = %d globalRowIndx = %d petscRowIdx = %d localPetscRowIdx = %d rStart = %d compontens = %d from %d nRankRows = %d\n", _row, rowDofMap[rowComp][_row].global, diff --git a/AMDiS/src/parallel/MatrixNnzStructure.h b/AMDiS/src/parallel/MatrixNnzStructure.h index 0bf3ef7e..589de906 100644 --- a/AMDiS/src/parallel/MatrixNnzStructure.h +++ b/AMDiS/src/parallel/MatrixNnzStructure.h @@ -62,8 +62,12 @@ namespace AMDiS { namespace Parallel { void create(int nRows0, int nRows1 = -1); public: + // Array containing the number of nonzeros in the various rows of the DIAGONAL + // portion of the local submatrix (possibly different for each row) int *dnnz; + // Array containing the number of nonzeros in the various rows of the OFF-DIAGONAL + // portion of the local submatrix (possibly different for each row) int *onnz; }; diff --git a/AMDiS/src/parallel/MeshDistributor.cc b/AMDiS/src/parallel/MeshDistributor.cc index eda979bf..39ca8816 100644 --- a/AMDiS/src/parallel/MeshDistributor.cc +++ b/AMDiS/src/parallel/MeshDistributor.cc @@ -86,7 +86,7 @@ namespace AMDiS { namespace Parallel { : problemStat(0), initialized(false), name("parallel"), - mesh(NULL), + macroMesh(NULL), refineManager(NULL), partitioner(NULL), initialPartitioner(NULL), @@ -100,7 +100,6 @@ namespace AMDiS { namespace Parallel { repartitioningCounter(0), repartitioningFailed(0), debugOutputDir(""), - lastMeshChangeIndex(0), createBoundaryDofFlag(0), boundaryDofInfo(1), meshAdaptivity(true), @@ -214,12 +213,13 @@ namespace AMDiS { namespace Parallel { ("Parallelization does not work with only one process!\n"); TEST_EXIT(feSpaces.size() > 0) ("No FE space has been defined for the mesh distributor!\n"); - TEST_EXIT(mesh)("No mesh has been defined for the mesh distributor!\n"); + TEST_EXIT(meshes.size() > 0)("No mesh has been defined for the mesh distributor!\n"); // === Sort FE spaces with respect to the degree of the basis === // === functions. Use stuiped bubble sort for this. === + //TODO Maybe unnecessary anymore bool doNext = false; do { doNext = false; @@ -234,9 +234,51 @@ namespace AMDiS { namespace Parallel { } } while (doNext); - elObjDb.setFeSpace(feSpaces[0]); - + // Sort FE spaces seperately for each mesh. + map<Mesh*, vector<const FiniteElemSpace*> >::iterator iter = meshToFeSpaces.begin(); + while(iter != meshToFeSpaces.end()) { + vector<const FiniteElemSpace*>& spaces = iter->second; + + bool doNext = false; + do { + doNext = false; + for (size_t i = 0; i < spaces.size() - 1; i++) { + if (spaces[i]->getBasisFcts()->getDegree() > + spaces[i + 1]->getBasisFcts()->getDegree()) { + const FiniteElemSpace *tmp = spaces[i + 1]; + spaces[i + 1] = spaces[i]; + spaces[i] = tmp; + doNext = true; + } + } + } while (doNext); + ++iter; + } + + // Test, if the mesh is the macro mesh only! Paritioning of the mesh is + // supported only for macro meshes, so it will not work yet if the mesh is + // already refined in some way. + testForMacroMesh(); + +#if (DEBUG != 0) + // Check whether meshes come from the same macro mesh. The way is to compare + // the node coords of each macro element in the meshes. + debug::ElementIdxToCoords macroCoords; + debug::createNodeCoords(macroMesh, macroCoords); + + for (size_t i = 1; i < meshes.size(); i++) { + debug::testNodeCoords(meshes[i], macroCoords); + } +#endif + + // Initialize dof communicators which have been created in addProblemStat. + for (size_t i = 0; i < meshes.size(); i++) + dofComms[meshes[i]].init(levelData, meshToFeSpaces[meshes[i]]); + + // Initialize element object DB + elObjDb.init(meshes, meshToFeSpaces); + // If the problem has been already read from a file, we need only to set // isRankDofs to all matrices and rhs vector and to remove periodic // boundary conditions (if there are some). @@ -247,7 +289,7 @@ namespace AMDiS { namespace Parallel { elObjDb.createMacroElementInfo(allMacroElements); - updateLocalGlobalNumbering(); + updateDofRelatedStruct(); elObjDb.setData(partitionMap, levelData); @@ -268,8 +310,10 @@ namespace AMDiS { namespace Parallel { #if (DEBUG != 0) - debug::ElementIdxToDofs elMap; - debug::createSortedDofs(mesh, elMap); + std::vector<debug::ElementIdxToDofs> elMap(meshes.size()); + for (size_t i = 0; i < meshes.size(); i++) { + debug::createSortedDofs(meshes[i], elMap[i]); + } #endif if (mpiRank == 0) { @@ -281,84 +325,94 @@ namespace AMDiS { namespace Parallel { Parameters::get("parallel->debug->write mesh partitioning", writePartMesh); if (writePartMesh > 0) { - debug::writeElementIndexMesh(mesh , debugOutputDir + "elementIndex"); + debug::writeElementIndexMesh(macroMesh , debugOutputDir + "elementIndex"); ParallelDebug::writePartitioning(*this, debugOutputDir + "part"); } } // Create interior boundary information. createInteriorBoundary(true); - - + // === Remove neighbourhood relations due to periodic bounday conditions. === - - for (deque<MacroElement*>::iterator it = mesh->firstMacroElement(); - it != mesh->endOfMacroElements(); ++it) { - for (int i = 0; i < mesh->getGeo(NEIGH); i++) { - if ((*it)->getNeighbour(i) && - mesh->isPeriodicAssociation((*it)->getBoundary(i))) { - - int neighIndex = (*it)->getNeighbour(i)->getIndex(); - - (*it)->getNeighbour(i)->setNeighbour((*it)->getOppVertex(i), NULL); - (*it)->setNeighbour(i, NULL); - (*it)->setBoundary(i, 0); - - macroElementNeighbours[(*it)->getIndex()][i] = -1; - macroElementNeighbours[neighIndex][(*it)->getOppVertex(i)] = -1; + + for (size_t i = 0; i < meshes.size(); i++) { + for (deque<MacroElement*>::iterator it = meshes[i]->firstMacroElement(); + it != meshes[i]->endOfMacroElements(); ++it) { + for (int j = 0; j < macroMesh->getGeo(NEIGH); j++) { + if ((*it)->getNeighbour(j) && + meshes[i]->isPeriodicAssociation((*it)->getBoundary(j))) { + + int neighIndex = (*it)->getNeighbour(j)->getIndex(); + + (*it)->getNeighbour(j)->setNeighbour((*it)->getOppVertex(j), NULL); + (*it)->setNeighbour(j, NULL); + (*it)->setBoundary(j, 0); + + if (i == 0) { + macroElementNeighbours[(*it)->getIndex()][j] = -1; + macroElementNeighbours[neighIndex][(*it)->getOppVertex(j)] = -1; + } + } } } } - - for (vector<MacroElement*>::iterator it = allMacroElements.begin(); - it != allMacroElements.end(); ++it) { - for (int i = 0; i < mesh->getGeo(NEIGH); i++) { - if ((*it)->getNeighbour(i) && + + for (map<Mesh*, std::vector<MacroElement*> >::iterator iter = allMacroElements.begin(); + iter != allMacroElements.end(); iter++) { + Mesh* mesh = iter->first; + vector<MacroElement*>& allMacros = iter->second; + + for (vector<MacroElement*>::iterator it = allMacros.begin(); + it != allMacros.end(); ++it) { + for (int i = 0; i < macroMesh->getGeo(NEIGH); i++) { + if ((*it)->getNeighbour(i) && mesh->isPeriodicAssociation((*it)->getBoundary(i))) { - - int neighIndex = (*it)->getNeighbour(i)->getIndex(); - - (*it)->getNeighbour(i)->setNeighbour((*it)->getOppVertex(i), NULL); - (*it)->setNeighbour(i, NULL); - (*it)->setBoundary(i, 0); - - macroElementNeighbours[(*it)->getIndex()][i] = -1; - macroElementNeighbours[neighIndex][(*it)->getOppVertex(i)] = -1; - + + int neighIndex = (*it)->getNeighbour(i)->getIndex(); + + (*it)->getNeighbour(i)->setNeighbour((*it)->getOppVertex(i), NULL); + (*it)->setNeighbour(i, NULL); + (*it)->setBoundary(i, 0); + + if (i == 0) { + macroElementNeighbours[(*it)->getIndex()][i] = -1; + macroElementNeighbours[neighIndex][(*it)->getOppVertex(i)] = -1; + } + } } } } // === Remove all macro elements that are not part of the rank partition. === - + removeMacroElements(); - + // === Create new global and local DOF numbering. === - - + // We have to remove the VertexVectors, which contain periodic assoiciations, // because they are not valid anymore after some macro elements have been // removed and the corresponding DOFs were deleted. - for (map<BoundaryType, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin(); - it != mesh->getPeriodicAssociations().end(); ++it) - const_cast<DOFAdmin&>(mesh->getDofAdmin(0)).removeDOFContainer(dynamic_cast<DOFContainer*>(it->second)); + for (size_t i = 0; i < meshes.size(); i++) + for (map<BoundaryType, VertexVector*>::iterator it = meshes[i]->getPeriodicAssociations().begin(); + it != meshes[i]->getPeriodicAssociations().end(); ++it) + const_cast<DOFAdmin&>(meshes[i]->getDofAdmin(0)).removeDOFContainer(dynamic_cast<DOFContainer*>(it->second)); - updateLocalGlobalNumbering(); + updateDofRelatedStruct(); // === In 3D we have to fix the mesh to allow local refinements. === fix3dMeshRefinement(); - // === If in debug mode, make some tests. === #if (DEBUG != 0) MSG("AMDiS runs in debug mode, so make some test ...\n"); ParallelDebug::testAllElements(*this); - debug::testSortedDofs(mesh, elMap); + for (size_t i = 0; i < meshes.size(); i++) + debug::testSortedDofs(meshes[i], elMap[i]); ParallelDebug::testInteriorBoundary(*this); ParallelDebug::followBoundary(*this); @@ -375,50 +429,56 @@ namespace AMDiS { namespace Parallel { #endif // === Global refinements. === - - int globalRefinement = 0; - Parameters::get(mesh->getName() + "->global refinements", globalRefinement); - - if (globalRefinement > 0) { - bool doRefineInter = true; - Parameters::get(mesh->getName() + "->refinement interpol", doRefineInter); - std::map<DOFVector<double>*, RefineCoarsenOperation> rememberOp; - if (!doRefineInter) { - // no refinement during initial global refinement - for (int iadmin = 0; iadmin < mesh->getNumberOfDOFAdmin(); iadmin++) { - std::list<DOFIndexedBase*>::iterator it; - DOFAdmin* admin = const_cast<DOFAdmin*>(&mesh->getDofAdmin(iadmin)); - std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed(); - for (it = admin->beginDOFIndexed(); it != end; it++) { - DOFVector<double>* vec = dynamic_cast<DOFVector<double>*>(*it); - if (vec) { - rememberOp[vec] = vec->getRefineOperation(); - vec->setRefineOperation(NO_OPERATION); + bool oneMeshRefined = false; + for (size_t i = 0; i < meshes.size(); i++) { + + int globalRefinement = 0; + Parameters::get(meshes[i]->getName() + "->global refinements", globalRefinement); + + if (globalRefinement > 0) { + oneMeshRefined = true; + bool doRefineInter = true; + Parameters::get(meshes[i]->getName() + "->refinement interpol", doRefineInter); + std::map<DOFVector<double>*, RefineCoarsenOperation> rememberOp; + if (!doRefineInter) { + // No refinement during initial global refinement + for (int iadmin = 0; iadmin < meshes[i]->getNumberOfDOFAdmin(); iadmin++) { + std::list<DOFIndexedBase*>::iterator it; + DOFAdmin* admin = const_cast<DOFAdmin*>(&meshes[i]->getDofAdmin(iadmin)); + std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed(); + for (it = admin->beginDOFIndexed(); it != end; it++) { + DOFVector<double>* vec = dynamic_cast<DOFVector<double>*>(*it); + if (vec) { + rememberOp[vec] = vec->getRefineOperation(); + vec->setRefineOperation(NO_OPERATION); + } } } } - } - refineManager->globalRefine(mesh, globalRefinement); - if (!doRefineInter) { - // no refinement during initial global refinement - for (int iadmin = 0; iadmin < mesh->getNumberOfDOFAdmin(); iadmin++) { - std::list<DOFIndexedBase*>::iterator it; - DOFAdmin* admin = const_cast<DOFAdmin*>(&mesh->getDofAdmin(iadmin)); - std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed(); - for (it = admin->beginDOFIndexed(); it != end; it++) { - DOFVector<double>* vec = dynamic_cast<DOFVector<double>*>(*it); - if (vec) - vec->setRefineOperation(rememberOp[vec]); + refineManager->globalRefine(meshes[i], globalRefinement); + if (!doRefineInter) { + // No refinement during initial global refinement + for (int iadmin = 0; iadmin < meshes[i]->getNumberOfDOFAdmin(); iadmin++) { + std::list<DOFIndexedBase*>::iterator it; + DOFAdmin* admin = const_cast<DOFAdmin*>(&meshes[i]->getDofAdmin(iadmin)); + std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed(); + for (it = admin->beginDOFIndexed(); it != end; it++) { + DOFVector<double>* vec = dynamic_cast<DOFVector<double>*>(*it); + if (vec) + vec->setRefineOperation(rememberOp[vec]); + } } } - } - updateLocalGlobalNumbering(); + updateDofRelatedStruct(meshes[i]); #if (DEBUG != 0) - ParallelDebug::testPeriodicBoundary(*this); + ParallelDebug::testPeriodicBoundary(*this); #endif + } } - + if (oneMeshRefined) + updateLocalGlobalNumbering(); + // And delete some data, we there is no mesh adaptivty. if (!meshAdaptivity) elObjDb.clear(); @@ -432,24 +492,19 @@ namespace AMDiS { namespace Parallel { { FUNCNAME("MeshDistributor::createInitialPartitioning()"); - // Test, if the mesh is the macro mesh only! Paritioning of the mesh is - // supported only for macro meshes, so it will not work yet if the mesh is - // already refined in some way. - testForMacroMesh(); - // For later mesh repartitioning, we need to store some information about // the macro mesh. createMacroElementInfo(); - // create an initial partitioning of the mesh + // Create an initial partitioning of the mesh bool useInitialPartitioning = initialPartitioner->createInitialPartitioning(); - // set the element weights, which are 1 at the very first begin + // Set the element weights, which are 1 at the very first begin setInitialElementWeights(); if (!useInitialPartitioning) { - // and now partition the mesh + // And now partition the mesh bool partitioningSucceed = initialPartitioner->partition(elemWeights, INITIAL); TEST_EXIT(partitioningSucceed)("Initial partitioning does not work!\n"); @@ -470,7 +525,7 @@ namespace AMDiS { namespace Parallel { elemWeights.clear(); string filename = ""; - Parameters::get(mesh->getName() + "->macro weights", filename); + Parameters::get(macroMesh->getName() + "->macro weights", filename); if (filename != "") { MSG("Read macro weights from %s\n", filename.c_str()); @@ -506,7 +561,7 @@ namespace AMDiS { namespace Parallel { } TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(macroMesh, -1, Mesh::CALL_LEAF_EL); while (elInfo) { elemWeights[elInfo->getElement()->getIndex()] = 1.0; elInfo = stack.traverseNext(elInfo); @@ -523,37 +578,49 @@ namespace AMDiS { namespace Parallel { // === Add all FE spaces from stationary problem. === - + vector<const FiniteElemSpace*> newFeSpaces = probStat->getFeSpaces(); - for (int i = 0; i < static_cast<int>(newFeSpaces.size()); i++) + + for (size_t i = 0; i < newFeSpaces.size(); i++) if (find(feSpaces.begin(), feSpaces.end(), newFeSpaces[i]) == feSpaces.end()) + { + // Find new fespace, then add mesh if it's new + Mesh* mesh = newFeSpaces[i]->getMesh(); + if (find(meshes.begin(), meshes.end(), mesh) == meshes.end()) { + TEST_EXIT(meshes.size() < 2) + ("Currently max two meshes supported on parallel mode.\n"); + + meshes.push_back(mesh); + dofComms[mesh] = MultiLevelDofComm(); + lastMeshChangeIndexs[mesh] = 0; + } + feSpaces.push_back(newFeSpaces[i]); + meshToFeSpaces[mesh].push_back(newFeSpaces[i]); + } - // === Add mesh of stationary problem and create a corresponding === - // === refinement manager object. === - - if (mesh != NULL) { - TEST_EXIT(mesh == probStat->getMesh()) - ("Does not yet support for different meshes! %s\n", probStat->getMesh()->getName().c_str()); - } else { - mesh = probStat->getMesh(); - } + // === Set the first mesh to be the macro mesh and pass it to partitioner. === + // === Create a corresponding refinement manager object. === - switch (mesh->getDim()) { - case 2: - refineManager = new RefinementManager2d(); - break; - case 3: - refineManager = new RefinementManager3d(); - break; - default: - ERROR_EXIT("This should not happen for dim = %d!\n", mesh->getDim()); + if (problemStat.empty()) { + macroMesh = meshes[0]; + + switch (macroMesh->getDim()) { + case 2: + refineManager = new RefinementManager2d(); + break; + case 3: + refineManager = new RefinementManager3d(); + break; + default: + ERROR_EXIT("This should not happen for dim = %d!\n", macroMesh->getDim()); + } + + partitioner->setMesh(macroMesh); + initialPartitioner->setMesh(macroMesh); } - partitioner->setMesh(mesh); - initialPartitioner->setMesh(mesh); - // === Check whether the stationary problem should be serialized. === @@ -639,8 +706,6 @@ namespace AMDiS { namespace Parallel { void MeshDistributor::addProblemStatGlobal(ProblemStatSeq *probStat) { - FUNCNAME("MeshDistributor::addProblemStatGlobal()"); - if (globalMeshDistributor == NULL) globalMeshDistributor = new MeshDistributor(); @@ -678,30 +743,33 @@ namespace AMDiS { namespace Parallel { { FUNCNAME("MeshDistributor::testForMacroMesh()"); - int nMacroElements = 0; + for (size_t i = 0; i < meshes.size(); i++) { + + int nMacroElements = 0; - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); - while (elInfo) { - TEST_EXIT(elInfo->getLevel() == 0) - ("Mesh is already refined! This does not work with parallelization!\n"); + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(meshes[i], -1, Mesh::CALL_LEAF_EL); + while (elInfo) { + TEST_EXIT(elInfo->getLevel() == 0) + ("Mesh is already refined! This does not work with parallelization!\n"); - TEST_EXIT(elInfo->getType() == 0) - ("Only macro elements with level 0 are supported!\n"); - - nMacroElements++; + TEST_EXIT(elInfo->getType() == 0) + ("Only macro elements with level 0 are supported!\n"); + + nMacroElements++; - elInfo = stack.traverseNext(elInfo); - } + elInfo = stack.traverseNext(elInfo); + } - TEST_EXIT(nMacroElements >= MPI::COMM_WORLD.Get_size()) - ("The mesh has less macro elements than number of mpi processes!\n"); + TEST_EXIT(nMacroElements >= MPI::COMM_WORLD.Get_size()) + ("The mesh has less macro elements than number of mpi processes!\n"); + } } void MeshDistributor::synchVector(SystemVector &vec) { - FUNCNAME("MeshDistributor::synchVector()"); + FUNCNAME_DBG("MeshDistributor::synchVector()"); int nLevels = levelData.getNumberOfLevels(); for (int level = nLevels - 1; level >= 0; level--) { @@ -709,54 +777,80 @@ namespace AMDiS { namespace Parallel { if (mpiComm == MPI::COMM_SELF) continue; - - StdMpi<vector<double> > stdMpi(mpiComm); - - for (DofComm::Iterator it(dofComm[level].getSendDofs()); - !it.end(); it.nextRank()) { - vector<double> dofs; + + vector<Mesh*> sysMeshes; + + // std::set of mesh pointer cannot be used for parallel + for (size_t i = 0; i < meshes.size(); i++) + for (int j = 0; j < vec.getSize(); j++) + if (meshes[i] == vec.getFeSpace(j)->getMesh()) { + sysMeshes.push_back(meshes[i]); + break; + } + + TEST_EXIT_DBG(sysMeshes.size() <= 2) + ("This really should not happen.\n"); + + vector<Mesh*>::iterator meshIt = sysMeshes.begin(); + while(meshIt != sysMeshes.end()) + { + StdMpi<vector<double> > stdMpi(mpiComm); - for (int i = 0; i < vec.getSize(); i++) { - DOFVector<double> &dofVec = *(vec.getDOFVector(i)); - for (it.beginDofIter(vec.getFeSpace(i)); !it.endDofIter(); it.nextDof()) - dofs.push_back(dofVec[it.getDofIndex()]); + MultiLevelDofComm& dofComm = dofComms[*meshIt]; + + for (DofComm::Iterator it(dofComm[level].getSendDofs()); + !it.end(); it.nextRank()) { + vector<double> dofs; + + for (int j = 0; j < vec.getSize(); j++) { + if (vec.getFeSpace(j)->getMesh() != *meshIt) + continue; + + DOFVector<double> &dofVec = *(vec.getDOFVector(j)); + for (it.beginDofIter(vec.getFeSpace(j)); !it.endDofIter(); it.nextDof()) + dofs.push_back(dofVec[it.getDofIndex()]); + } + + int rank = it.getRank(); + // if (level > 0) + // rank = levelData.mapRank(rank, 0, level); + stdMpi.send(rank, dofs); } - int rank = it.getRank(); - // if (level > 0) - // rank = levelData.mapRank(rank, 0, level); - stdMpi.send(rank, dofs); - } - - for (DofComm::Iterator it(dofComm[level].getRecvDofs()); - !it.end(); it.nextRank()) { - int rank = it.getRank(); - // if (level > 0) - // rank = levelData.mapRank(rank, 0, level); - stdMpi.recv(rank); - } - - stdMpi.startCommunication(); - - for (DofComm::Iterator it(dofComm[level].getRecvDofs()); - !it.end(); it.nextRank()) { - int rank = it.getRank(); - // if (level > 0) - // rank = levelData.mapRank(rank, 0, level); + for (DofComm::Iterator it(dofComm[level].getRecvDofs()); + !it.end(); it.nextRank()) { + int rank = it.getRank(); + // if (level > 0) + // rank = levelData.mapRank(rank, 0, level); + stdMpi.recv(rank); + } - int counter = 0; - vector<double> &recvData = stdMpi.getRecvData(rank); + stdMpi.startCommunication(); - for (int i = 0; i < vec.getSize(); i++) { - DOFVector<double> &dofVec = *(vec.getDOFVector(i)); + for (DofComm::Iterator it(dofComm[level].getRecvDofs()); + !it.end(); it.nextRank()) { + int rank = it.getRank(); + // if (level > 0) + // rank = levelData.mapRank(rank, 0, level); - for (it.beginDofIter(vec.getFeSpace(i)); !it.endDofIter(); it.nextDof()) { - TEST_EXIT_DBG(counter < recvData.size()) - ("Recv data from rank %d has only %d entries!\n", rank, recvData.size()); - dofVec[it.getDofIndex()] = recvData[counter++]; + size_t counter = 0; + vector<double> &recvData = stdMpi.getRecvData(rank); + + for (int j = 0; j < vec.getSize(); j++) { + if (vec.getFeSpace(j)->getMesh() != *meshIt) + continue; + + DOFVector<double> &dofVec = *(vec.getDOFVector(j)); + + for (it.beginDofIter(vec.getFeSpace(j)); !it.endDofIter(); it.nextDof()) { + TEST_EXIT_DBG(counter < recvData.size()) + ("Recv data from rank %d has only %d entries!\n", rank, recvData.size()); + dofVec[it.getDofIndex()] = recvData[counter++]; + } } } - } + meshIt++; + } // End while } } @@ -765,7 +859,7 @@ namespace AMDiS { namespace Parallel { { FUNCNAME("MeshDistributor::fix3dMeshRefinement()"); - if (mesh->getDim() != 3) + if (macroMesh->getDim() != 3) return; Timer t; @@ -777,9 +871,9 @@ namespace AMDiS { namespace Parallel { std::set<int> rankMacroEls; TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL); + ElInfo *elInfo = stack.traverseFirst(macroMesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { - for (int i = 0; i < mesh->getGeo(EDGE); i++) { + for (int i = 0; i < macroMesh->getGeo(EDGE); i++) { ElementObjectData elData(elInfo->getElement()->getIndex(), i); DofEdge e = elObjDb.getEdgeLocalMap(elData); allEdges.insert(e); @@ -832,44 +926,48 @@ namespace AMDiS { namespace Parallel { // neighbours of each other, but can not reach any other element of the // other index sets by neighbourhood relations. vector<std::set<int> > disconnectedEls; - helpToFix(allEls, edgeNoInEl, disconnectedEls); + helpToFix(allEls, disconnectedEls); // Fix the edges for (int dc0 = 0; dc0 < static_cast<int>(disconnectedEls.size()); dc0++) { for (int dc1 = 0; dc1 < static_cast<int>(disconnectedEls.size()); dc1++) { if (dc0 == dc1) continue; - - int elIdx = *(disconnectedEls[dc1].begin()); - pair<Element*, int> edge0 = - make_pair(elObjDb.getElementPtr(elIdx), edgeNoInEl[elIdx]); - - for (std::set<int>::iterator elIt = disconnectedEls[dc0].begin(); - elIt != disconnectedEls[dc0].end(); ++elIt) { - pair<Element*, int> edge1 = - make_pair(elObjDb.getElementPtr(*elIt), edgeNoInEl[*elIt]); -#if (DEBUG != 0) - DofEdge dofEdge0 = edge0.first->getEdge(edge0.second); - DofEdge dofEdge1 = edge1.first->getEdge(edge1.second); + for (size_t i = 0; i < meshes.size(); i++) { - WorldVector<double> c0, c1; - mesh->getDofIndexCoords(dofEdge0.first, feSpaces[0], c0); - mesh->getDofIndexCoords(dofEdge0.second, feSpaces[0], c1); + int elIdx = *(disconnectedEls[dc1].begin()); - // MSG("FOUND EDGE %d/%d <-> %d/%d\n", - // edge0.first->getIndex(), edge0.second, - // edge1.first->getIndex(), edge1.second); + pair<Element*, int> edge0 = + make_pair(elObjDb.getElementPtr(elIdx, meshes[i]), edgeNoInEl[elIdx]); - // MSG("FOUND EDGE: %d %d with coords %f %f %f %f %f %f\n", - // dofEdge0.first, dofEdge0.second, - // c0[0], c0[1], c0[2], - // c1[0], c1[1], c1[2]); - - TEST_EXIT_DBG(dofEdge0 == dofEdge1)("Should noth happen!\n"); + for (std::set<int>::iterator elIt = disconnectedEls[dc0].begin(); + elIt != disconnectedEls[dc0].end(); ++elIt) { + pair<Element*, int> edge1 = + make_pair(elObjDb.getElementPtr(*elIt, meshes[i]), edgeNoInEl[*elIt]); + +#if (DEBUG != 0) + DofEdge dofEdge0 = edge0.first->getEdge(edge0.second); + DofEdge dofEdge1 = edge1.first->getEdge(edge1.second); + + WorldVector<double> c0, c1; + meshes[i]->getDofIndexCoords(dofEdge0.first, meshToFeSpaces[meshes[i]][0], c0); + meshes[i]->getDofIndexCoords(dofEdge0.second, meshToFeSpaces[meshes[i]][0], c1); + + // MSG("FOUND EDGE %d/%d <-> %d/%d\n", + // edge0.first->getIndex(), edge0.second, + // edge1.first->getIndex(), edge1.second); + + // MSG("FOUND EDGE: %d %d with coords %f %f %f %f %f %f\n", + // dofEdge0.first, dofEdge0.second, + // c0[0], c0[1], c0[2], + // c1[0], c1[1], c1[2]); + + TEST_EXIT_DBG(dofEdge0 == dofEdge1)("Should noth happen!\n"); #endif - FixRefinementPatch::connectedEdges.push_back(make_pair(edge1, edge0)); + FixRefinementPatch::connectedEdges[meshes[i]].push_back(make_pair(edge1, edge0)); + } } } } @@ -881,7 +979,6 @@ namespace AMDiS { namespace Parallel { void MeshDistributor::helpToFix(std::set<int> &elems, - map<int, int> &edgeNoInEl, vector<std::set<int> > &disconnectedEls) { std::set<int> firstElem; @@ -893,7 +990,7 @@ namespace AMDiS { namespace Parallel { do { found = false; for (std::set<int>::iterator elIt = firstElem.begin(); elIt != firstElem.end(); ++elIt) { - for (int i = 0; i < mesh->getGeo(NEIGH); i++) { + for (int i = 0; i < macroMesh->getGeo(NEIGH); i++) { int neighEl = macroElementNeighbours[*elIt][i]; if (neighEl != -1 && otherElems.count(neighEl)) { firstElem.insert(neighEl); @@ -909,7 +1006,7 @@ namespace AMDiS { namespace Parallel { disconnectedEls.push_back(firstElem); if (otherElems.size()) - helpToFix(otherElems, edgeNoInEl, disconnectedEls); + helpToFix(otherElems, disconnectedEls); } @@ -933,19 +1030,22 @@ namespace AMDiS { namespace Parallel { void MeshDistributor::removePeriodicBoundaryConditions() { // Remove periodic boundaries in boundary manager on matrices and vectors. - for (unsigned int i = 0; i < problemStat.size(); i++) + for (size_t i = 0; i < problemStat.size(); i++) removePeriodicBoundaryConditions(problemStat[i]); // Remove periodic boundaries on elements in mesh. - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); - while (elInfo) { - elInfo->getElement()->deleteElementData(PERIODIC); - elInfo = stack.traverseNext(elInfo); - } + for (size_t i = 0; i < meshes.size(); i++) { + + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(meshes[i], -1, Mesh::CALL_EVERY_EL_PREORDER); + while (elInfo) { + elInfo->getElement()->deleteElementData(PERIODIC); + elInfo = stack.traverseNext(elInfo); + } - // Remove periodic vertex associations - mesh->getPeriodicAssociations().clear(); + // Remove periodic vertex associations + meshes[i]->getPeriodicAssociations().clear(); + } } @@ -1122,12 +1222,19 @@ namespace AMDiS { namespace Parallel { Parameters::get("parallel->debug->skip check mesh change", skip); // === If mesh has not been changed on all ranks, return. === - - int recvAllValues = 0; - int sendValue = static_cast<int>(mesh->getChangeIndex() != lastMeshChangeIndex); - mpiComm.Allreduce(&sendValue, &recvAllValues, 1, MPI_INT, MPI_SUM); + vector<int> meshAllValues(meshes.size(), 0); + + for (size_t i = 0; i < meshes.size(); i++) { +#if (DEBUG != 0) + MSG("mesh[%d] change index = %d, stored last index = %d.\n", + i, meshes[i]->getChangeIndex(), lastMeshChangeIndexs[meshes[i]]); +#endif + int sendValue = + static_cast<int>(meshes[i]->getChangeIndex() != lastMeshChangeIndexs[meshes[i]]); + mpiComm.Allreduce(&sendValue, &meshAllValues[i], 1, MPI_INT, MPI_SUM); + } - if (recvAllValues == 0) + if (meshAllValues.size() == count(meshAllValues.begin(), meshAllValues.end(), 0)) return; TEST_EXIT(levelData.getNumberOfLevels() == 1) @@ -1136,70 +1243,79 @@ namespace AMDiS { namespace Parallel { // === At least one rank mesh has been changed, so the boundaries must be === // === adapted to the new mesh structure. === - if (skip == 0) { - int iterationCounter = 0; - + if (skip != 0) { + for (size_t i = 0; i < meshes.size(); i++) + if (meshAllValues[i] != 0) + updateDofRelatedStruct(meshes[i]); + } else { // To check the interior boundaries, the ownership of the boundaries is not // important. Therefore, we add all boundaries to one boundary container. RankToBoundMap allBound; for (InteriorBoundary::iterator it(intBoundary[0].getOwn()); !it.end(); ++it) - if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) || - (mesh->getDim() == 3 && it->rankObj.subObj == FACE)) + if ((macroMesh->getDim() == 2 && it->rankObj.subObj == EDGE) || + (macroMesh->getDim() == 3 && it->rankObj.subObj == FACE)) allBound[it.getRank()].push_back(*it); for (InteriorBoundary::iterator it(intBoundary[0].getOther()); !it.end(); ++it) - if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) || - (mesh->getDim() == 3 && it->rankObj.subObj == FACE)) + if ((macroMesh->getDim() == 2 && it->rankObj.subObj == EDGE) || + (macroMesh->getDim() == 3 && it->rankObj.subObj == FACE)) allBound[it.getRank()].push_back(*it); for (InteriorBoundary::iterator it(intBoundary[0].getPeriodic()); !it.end(); ++it) if (it.getRank() != mpiRank) - if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) || - (mesh->getDim() == 3 && it->rankObj.subObj == FACE)) + if ((macroMesh->getDim() == 2 && it->rankObj.subObj == EDGE) || + (macroMesh->getDim() == 3 && it->rankObj.subObj == FACE)) allBound[it.getRank()].push_back(*it); - do { - bool meshChanged = false; + for (size_t i = 0; i < meshes.size(); i++) { + if (meshAllValues[i] == 0) + continue; + + int iterationCounter = 0; + do { + bool meshChanged = false; // === Check the boundaries and adapt mesh if necessary. === #if (DEBUG != 0) - MSG("Run checkAndAdaptBoundary ...\n"); + MSG("Run checkAndAdaptBoundary for mesh[%d]...\n", i); #endif // Check for periodic boundaries within rank's subdomain. - for (InteriorBoundary::iterator it(intBoundary[0].getPeriodic()); - !it.end(); ++it) { - if (it.getRank() == mpiRank) { - if ((mesh->getDim() == 2 && it->rankObj.subObj == EDGE) || - (mesh->getDim() == 3 && it->rankObj.subObj == FACE)) { - MeshStructure elCode; - elCode.init(it->rankObj); - - MeshManipulation mm(mesh); - meshChanged |= mm.fitElementToMeshCode(elCode, it->neighObj); + for (InteriorBoundary::iterator it(intBoundary[0].getPeriodic()); + !it.end(); ++it) { + if (it.getRank() == mpiRank) { + if ((macroMesh->getDim() == 2 && it->rankObj.subObj == EDGE) || + (macroMesh->getDim() == 3 && it->rankObj.subObj == FACE)) { + MeshStructure elCode; + elCode.init(it->rankObj, elObjDb.getElementPtr(it->rankObj.elIndex, meshes[i])); + + MeshManipulation mm(meshes[i]); + it->neighObj.el = elObjDb.getElementPtr(it->neighObj.elIndex, meshes[i]); + meshChanged |= mm.fitElementToMeshCode(elCode, it->neighObj); + } } } - } - meshChanged |= checkAndAdaptBoundary(allBound); - + meshChanged |= checkAndAdaptBoundary(allBound, meshes[i]); + - // === Check on all ranks if at least one rank's mesh has changed. === - - int sendValue = static_cast<int>(meshChanged); - recvAllValues = 0; - mpiComm.Allreduce(&sendValue, &recvAllValues, 1, MPI_INT, MPI_SUM); + // === Check on all ranks if at least one rank's mesh has changed. === + + int sendValue = static_cast<int>(meshChanged); + meshAllValues[i] = 0; + mpiComm.Allreduce(&sendValue, &meshAllValues[i], 1, MPI_INT, MPI_SUM); + + MSG("Mesh changed on %d ranks!\n", meshAllValues[i]); + iterationCounter++; + } while (meshAllValues[i] != 0); - MSG("Mesh changed on %d ranks!\n", recvAllValues); - iterationCounter++; - } while (recvAllValues != 0); - - MSG("Number of iteration to adapt mesh: %d\n", iterationCounter); + MSG("Number of iteration to adapt mesh: %d\n", iterationCounter); + updateDofRelatedStruct(meshes[i]); + } } - mpiComm.Barrier(); MSG("Parallel mesh adaption needed %.5f seconds\n", t.elapsed()); @@ -1253,7 +1369,11 @@ namespace AMDiS { namespace Parallel { int mpiSize = mpiComm.Get_size(); vector<int> nDofsInRank(mpiSize); - int nDofs = mesh->getDofAdmin(0).getUsedDofs(); + int nDofs = 0; + + for (size_t i = 0; i < meshes.size(); i++) + nDofs += meshes[i]->getDofAdmin(0).getUsedDofs(); + mpiComm.Gather(&nDofs, 1, MPI_INT, &(nDofsInRank[0]), 1, MPI_INT, 0); if (mpiRank == 0) { @@ -1299,7 +1419,7 @@ namespace AMDiS { namespace Parallel { } - bool MeshDistributor::checkAndAdaptBoundary(RankToBoundMap &allBound) + bool MeshDistributor::checkAndAdaptBoundary(RankToBoundMap &allBound, Mesh* mesh) { FUNCNAME_DBG("MeshDistributor::checkAndAdaptBoundary()"); @@ -1312,7 +1432,7 @@ namespace AMDiS { namespace Parallel { for (vector<AtomicBoundary>::iterator boundIt = it->second.begin(); boundIt != it->second.end(); ++boundIt) { MeshStructure elCode; - elCode.init(boundIt->rankObj); + elCode.init(boundIt->rankObj, elObjDb.getElementPtr(boundIt->rankObj.elIndex, mesh)); sendCodes[it->first].push_back(elCode); } } @@ -1330,7 +1450,6 @@ namespace AMDiS { namespace Parallel { bool meshChanged = false; -// int cCounter = 0; for (RankToBoundMap::iterator it = allBound.begin(); it != allBound.end(); ++it) { @@ -1341,7 +1460,7 @@ namespace AMDiS { namespace Parallel { boundIt != it->second.end(); ++boundIt, i++) { MeshStructure elCode; - elCode.init(boundIt->rankObj); + elCode.init(boundIt->rankObj, elObjDb.getElementPtr(boundIt->rankObj.elIndex, mesh)); #if (DEBUG != 0) ParallelDebug::followBoundary(mesh, *boundIt, elCode); @@ -1355,7 +1474,9 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(refineManager)("Refinement manager is not set correctly!\n"); MeshManipulation mm(mesh); + boundIt->rankObj.el = elObjDb.getElementPtr(boundIt->rankObj.elIndex, mesh); meshChanged |= mm.fitElementToMeshCode(recvCodes[i], boundIt->rankObj); + boundIt->rankObj.el = NULL; } } } @@ -1473,11 +1594,13 @@ namespace AMDiS { namespace Parallel { elemWeights.clear(); { - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); - while (elInfo) { - elemWeights[elInfo->getMacroElement()->getIndex()]++; - elInfo = stack.traverseNext(elInfo); + for (size_t i = 0; i < meshes.size(); i++) { + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(meshes[i], -1, Mesh::CALL_LEAF_EL); + while (elInfo) { + elemWeights[elInfo->getMacroElement()->getIndex()]++; + elInfo = stack.traverseNext(elInfo); + } } } @@ -1510,7 +1633,8 @@ namespace AMDiS { namespace Parallel { Timer t; #if (DEBUG != 0) - ParallelDebug::testDoubleDofs(mesh); + for (size_t i = 0; i < meshes.size(); i++) + ParallelDebug::testDoubleDofs(meshes[i]); int writePartMesh = 1; #else int writePartMesh = 0; @@ -1540,7 +1664,7 @@ namespace AMDiS { namespace Parallel { partitioner->partition(elemWeights, ADAPTIVE_REPART); if (!partitioningSucceed) { mpiComm.Barrier(); - repartitioningFailed = repartitioningWaitAfterFail;; + repartitioningFailed = repartitioningWaitAfterFail; MSG("Mesh partitioner created empty partition!\n"); MSG("Mesh repartitioning needed %.5f seconds\n", t.elapsed()); return false; @@ -1561,7 +1685,7 @@ namespace AMDiS { namespace Parallel { } } - TEST_EXIT_DBG(!(partitioner->getSendElements().size() == mesh->getMacroElements().size() && + TEST_EXIT_DBG(!(partitioner->getSendElements().size() == macroMesh->getMacroElements().size() && partitioner->getRecvElements().size() == 0)) ("Partition is empty, should not happen!\n"); @@ -1571,19 +1695,18 @@ namespace AMDiS { namespace Parallel { switch (strategy) { case 0: - quickRepartition(); + // Always starts from meshes[0], the macro mesh + for (size_t i = 0; i < meshes.size(); i++) + quickRepartition(meshes[i]); break; case 1: - fullRepartition(); + for (size_t i = 0; i < meshes.size(); i++) + fullRepartition(meshes[i]); break; default: ERROR_EXIT("Unknown repartition strategy = %d!\n", strategy); } - - partitioner->createPartitionMap(partitionMap); - - createInteriorBoundary(false); - + // This is done outside repartition, don't forget! updateLocalGlobalNumbering(); @@ -1594,7 +1717,8 @@ namespace AMDiS { namespace Parallel { repartitioningCounter, feSpaces[0]); ParallelDebug::testAllElements(*this); - ParallelDebug::testDoubleDofs(mesh); + for (size_t i = 0; i < meshes.size(); i++) + ParallelDebug::testDoubleDofs(meshes[i]); ParallelDebug::testInteriorBoundary(*this); ParallelDebug::testPeriodicBoundary(*this); @@ -1607,12 +1731,12 @@ namespace AMDiS { namespace Parallel { return true; } - void MeshDistributor::quickRepartition() + void MeshDistributor::quickRepartition(Mesh* mesh) { FUNCNAME("MeshDistributor::quickRepartition()"); #if (DEBUG != 0) - MSG("Run quickRepartition ...\n"); + MSG("... Run quickRepartition ...\n"); #endif MPI::Intracomm &mpiComm = MPI::COMM_WORLD; @@ -1620,15 +1744,15 @@ namespace AMDiS { namespace Parallel { // === macro elements. === map<int, MacroElement*> elIndexMap; - for (vector<MacroElement*>::iterator it = allMacroElements.begin(); - it != allMacroElements.end(); ++it) + for (vector<MacroElement*>::iterator it = allMacroElements[mesh].begin(); + it != allMacroElements[mesh].end(); ++it) elIndexMap[(*it)->getIndex()] = *it; // === Create set of all new macro elements this rank will receive from === // === other ranks. === - std::set<MacroElement*> newMacroEl; + vector<MacroElement*> newMacroEl; for (map<int, vector<int> >::iterator it = partitioner->getRecvElements().begin(); it != partitioner->getRecvElements().end(); ++it) { for (vector<int>::iterator elIt = it->second.begin(); @@ -1636,12 +1760,16 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(elIndexMap.count(*elIt) == 1) ("Could not find macro element %d\n", *elIt); - newMacroEl.insert(elIndexMap[*elIt]); + TEST_EXIT_DBG(find(newMacroEl.begin(), newMacroEl.end(), + elIndexMap[*elIt]) == newMacroEl.end()) + ("The mesh received the same macro element %d twice! Something is wrong...\n", *elIt); + + newMacroEl.push_back(elIndexMap[*elIt]); } } std::set<MacroElement*> allMacroEl; - for (std::set<MacroElement*>::iterator it = newMacroEl.begin(); + for (vector<MacroElement*>::iterator it = newMacroEl.begin(); it != newMacroEl.end(); ++it) allMacroEl.insert(*it); @@ -1651,7 +1779,7 @@ namespace AMDiS { namespace Parallel { // === Add new macro elements to mesh. === - for (std::set<MacroElement*>::iterator it = newMacroEl.begin(); + for (vector<MacroElement*>::iterator it = newMacroEl.begin(); it != newMacroEl.end(); ++it) { MacroElement *mel = *it; @@ -1673,6 +1801,9 @@ namespace AMDiS { namespace Parallel { map<int, MeshCodeVec> sendCodes; map<int, vector<vector<double> > > sendValues; + + TEST_EXIT(interchangeVectors.size() > 0) + ("There are no interchange vectors defined!\n"); for (map<int, vector<int> >::iterator it = partitioner->getSendElements().begin(); it != partitioner->getSendElements().end(); ++it) { @@ -1682,11 +1813,17 @@ namespace AMDiS { namespace Parallel { elCode.init(mesh, *elIt); sendCodes[it->first].push_back(elCode); - for (unsigned int i = 0; i < interchangeVectors.size(); i++) { + for (size_t i = 0; i < interchangeVectors.size(); i++) { + //only the vectors defined on the corresponding mesh + if (interchangeVectors[i]->getFeSpace()->getMesh() != mesh) + continue; + vector<double> valVec; elCode.getMeshStructureValues(*elIt, interchangeVectors[i], valVec); sendValues[it->first].push_back(valVec); } + TEST_EXIT_DBG(!sendValues[it->first].empty()) + ("There is no DOFVector defined on this mesh.\n"); } } @@ -1697,9 +1834,6 @@ namespace AMDiS { namespace Parallel { stdMpi.recv(it->first); stdMpi.startCommunication(); - TEST_EXIT(interchangeVectors.size() > 0) - ("There are no interchange vectors defined!\n"); - StdMpi<vector<vector<double> > > stdMpi2(mpiComm, true); stdMpi2.send(sendValues); for (map<int, vector<int> >::iterator it = partitioner->getRecvElements().begin(); @@ -1771,51 +1905,58 @@ namespace AMDiS { namespace Parallel { // Note that also if there are no macros to be deleted, this function will // update the number of elements, vertices, etc. of the mesh. - mesh->removeMacroElements(deleteMacroElements, feSpaces); + mesh->removeMacroElements(deleteMacroElements, meshToFeSpaces[mesh]); // === Remove double DOFs. === MeshManipulation meshManipulation(mesh); - meshManipulation.deleteDoubleDofs(feSpaces, newMacroEl, elObjDb); - + meshManipulation.deleteDoubleDofs(meshToFeSpaces[mesh], newMacroEl, elObjDb); mesh->dofCompress(); - -// partitioner->createPartitionMap(partitionMap); -// -// -// createInteriorBoundary(false); -// -// updateLocalGlobalNumbering(); // === After mesh adaption, set values of interchange vectors. === for (map<int, vector<int> >::iterator it = partitioner->getRecvElements().begin(); it != partitioner->getRecvElements().end(); ++it) { + MeshCodeVec &recvCodes = stdMpi.getRecvData()[it->first]; vector<vector<double> > &recvValues = stdMpi2.getRecvData()[it->first]; + int i = 0, j = 0; for (vector<int>::iterator elIt = it->second.begin(); elIt != it->second.end(); ++elIt) { - for (unsigned int k = 0; k < interchangeVectors.size(); k++) + + for (size_t k = 0; k < interchangeVectors.size(); k++) { + if (interchangeVectors[k]->getFeSpace()->getMesh() != mesh) + continue; + recvCodes[i].setMeshStructureValues(*elIt, interchangeVectors[k], recvValues[j++]); + } i++; } } - // In 3D we have to make some test, if the resulting mesh is valid. - fix3dMeshRefinement(); + if (mesh == macroMesh) { + // In 3D we have to make some test, if the resulting mesh is valid. + fix3dMeshRefinement(); + // PartitionMap is needed for createInteriorBoundary + partitioner->createPartitionMap(partitionMap); + // InteriorBoundary is needed for updateDofRelatedStruct + createInteriorBoundary(false); + } + updateDofRelatedStruct(mesh); + } - void MeshDistributor::fullRepartition() + void MeshDistributor::fullRepartition(Mesh* mesh) { FUNCNAME("MeshDistributor::fullRepartition()"); #if (DEBUG != 0) - MSG("Run fullRepartition ...\n"); + MSG("... Run fullRepartition ...\n"); #endif TEST_EXIT(interchangeVectors.size() > 0) @@ -1826,18 +1967,17 @@ namespace AMDiS { namespace Parallel { MPI::Intracomm &mpiComm = MPI::COMM_WORLD; -#if DEBUG != 0 +#if (DEBUG != 0) int nOldLeaves = mesh->getNumberOfLeaves(); - int nAllOldLeaves = 0; - mpiComm.Allreduce(&nOldLeaves, &nAllOldLeaves, 1, MPI_INT, MPI_SUM); + mpi::globalAdd(mpiComm, nOldLeaves); #endif // === Create map that maps macro element indices to pointers to the === // === macro elements. === map<int, MacroElement*> elIndexMap; - for (vector<MacroElement*>::iterator it = allMacroElements.begin(); - it != allMacroElements.end(); ++it) + for (vector<MacroElement*>::iterator it = allMacroElements[mesh].begin(); + it != allMacroElements[mesh].end(); ++it) elIndexMap[(*it)->getIndex()] = *it; @@ -1877,6 +2017,9 @@ namespace AMDiS { namespace Parallel { elCode.init(mesh, macroId); for (size_t i = 0; i < interchangeVectors.size(); i++) { + if (interchangeVectors[i]->getFeSpace()->getMesh() != mesh) + continue; + vector<double> valVec; elCode.getMeshStructureValues(macroId, interchangeVectors[i], valVec); elValue.push_back(valVec); @@ -1887,16 +2030,15 @@ namespace AMDiS { namespace Parallel { } // === Rebuild all macros in order to clean and renumber the dofs. === - - // Remove domain meshes, not optimized. - mesh->removeMacroElements(allMacroEl, feSpaces); + + mesh->removeAllMacroElements(); TEST_EXIT_DBG(!mesh->getNumberOfMacros()) ("Still %d macros remain?\n", mesh->getNumberOfMacros()); // Add all macros again. - for (vector<MacroElement*>::iterator it = allMacroElements.begin(); - it != allMacroElements.end(); ++it) { + for (vector<MacroElement*>::iterator it = allMacroElements[mesh].begin(); + it != allMacroElements[mesh].end(); ++it) { MacroElement *mel = *it; int elIndex = mel->getIndex(); @@ -1931,8 +2073,8 @@ namespace AMDiS { namespace Parallel { } // New dof indices for all macro elements. - io::MacroReader::restoreMacroDofs(*(mesh->getMacroFileInfo())); - + io::MacroReader::restoreMacroDofs(*(mesh->getMacroFileInfo()), 0); + // === Update the current mesh partition. === for (map<int, vector<int> >::iterator it = partitioner->getSendElements().begin(); @@ -1958,17 +2100,19 @@ namespace AMDiS { namespace Parallel { std::set<MacroElement*> deleteMacroElements; - for (vector<MacroElement*>::iterator it = allMacroElements.begin(); - it != allMacroElements.end(); ++it) + for (vector<MacroElement*>::iterator it = allMacroElements[mesh].begin(); + it != allMacroElements[mesh].end(); ++it) if (allMacroEl.find(*it) == allMacroEl.end()) deleteMacroElements.insert(*it); - + // Note that also if there are no macros to be deleted, this function will // update the number of elements, vertices, etc. of the mesh. - mesh->removeMacroElements(deleteMacroElements, feSpaces); + mesh->removeMacroElements(deleteMacroElements, meshToFeSpaces[mesh]); mesh->dofCompress(); - fix3dMeshRefinement(); - + // In fullRepartition, we need to call fix3d here instead of in the end. + if (mesh == macroMesh) + fix3dMeshRefinement(); + // === Adapte all domain macro elements. === // Send and receive mesh structure codes. @@ -2020,15 +2164,10 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(allMacroEl.find(elIndexMap[*elIt]) != allMacroEl.end()) ("Received a macro element[%d] which doesn't belong to the domain. Something wrong.\n", *elIt); -// MSG("%d-\n", *elIt); -// -// TEST_EXIT_DBG(elIndexMap[*elIt]->getElement()->isLeaf()) -// ("Macro %d already refined before applying mesh structure code?\n", *elIt); recvCodes[i++].fitMeshToStructure(mesh, refineManager, false, *elIt); } } - // === After mesh adaption, set values of interchange vectors. === @@ -2039,19 +2178,20 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(domainMacroCodes.count(macroId)) ("Reserved macro element[%d] has no stored structure data. Something wrong.\n", macroId); - -// MSG("%d-\n", *macroId); -// -// TEST_EXIT_DBG(elIndexMap[macroId]->getElement()->isLeaf()) -// ("Macro %d already refined before applying mesh structure code?\n", macroId); + domainMacroCodes[macroId].fitMeshToStructure(mesh, refineManager, false, macroId); - + + int j = 0; for (size_t i = 0; i < interchangeVectors.size(); i++) { + if (interchangeVectors[i]->getFeSpace()->getMesh() != mesh) + continue; + domainMacroCodes[macroId].setMeshStructureValues(macroId, interchangeVectors[i], - domainMacroValues[macroId][i]); -#if DEBUG != 0 + domainMacroValues[macroId][j++]); + +#if (DEBUG != 0) MeshStructure code; code.init(mesh, macroId); TEST_EXIT(code.getCode() == domainMacroCodes[macroId].getCode()) @@ -2067,21 +2207,30 @@ namespace AMDiS { namespace Parallel { int i = 0, j = 0; for (vector<int>::iterator elIt = it->second.begin(); elIt != it->second.end(); ++elIt) { - for (unsigned int k = 0; k < interchangeVectors.size(); k++) + for (size_t k = 0; k < interchangeVectors.size(); k++) { + if (interchangeVectors[k]->getFeSpace()->getMesh() != mesh) + continue; + recvCodes[i].setMeshStructureValues(*elIt, interchangeVectors[k], recvValues[j++]); + } i++; } } -#if DEBUG != 0 + if (mesh == macroMesh) { + partitioner->createPartitionMap(partitionMap); + createInteriorBoundary(false); + } + updateDofRelatedStruct(mesh); + +#if (DEBUG != 0) int nNewLeaves = mesh->getNumberOfLeaves(); - int nAllNewLeaves = 0; - mpiComm.Allreduce(&nNewLeaves, &nAllNewLeaves, 1, MPI_INT, MPI_SUM); + mpi::globalAdd(mpiComm, nNewLeaves); - TEST_EXIT(nAllOldLeaves == nAllNewLeaves) - ("Overall number of leaves change from %d to %d\n", nAllOldLeaves, nAllNewLeaves); + TEST_EXIT(nOldLeaves == nNewLeaves) + ("Overall number of leaves change from %d to %d\n", nOldLeaves, nNewLeaves); #endif } @@ -2094,9 +2243,15 @@ namespace AMDiS { namespace Parallel { elObjDb.create(partitionMap, levelData); elObjDb.updateRankData(); +#if (DEBUG != 0) + if (mpiRank == 0) + ParallelDebug::writePeriodicElObjInfo(*this, debugOutputDir); +#endif // === If requested, calculate and print memory usage of element === // === object database. === + + //TODO To be reimplemented if (printMemoryUsage && firstCall) { unsigned long memsize = elObjDb.calculateMemoryUsage(); MSG("Memory usage of element object database = %5.f KByte\n", @@ -2111,14 +2266,13 @@ namespace AMDiS { namespace Parallel { if (firstCall) { int tmpSend = static_cast<int>(intBoundary[0].hasPeriodic()); - int tmpRecv = 0; - MPI::COMM_WORLD.Allreduce(&tmpSend, &tmpRecv, 1, MPI_INT, MPI_MAX); - hasPeriodicBoundary = static_cast<bool>(tmpRecv); + mpi::globalAdd(MPI::COMM_WORLD, tmpSend); + hasPeriodicBoundary = static_cast<bool>(tmpSend); } } - void MeshDistributor::createBoundaryDofs() + void MeshDistributor::createBoundaryDofs(Mesh* mesh) { FUNCNAME("MeshDistributor::createBoundaryDofs()"); @@ -2126,14 +2280,19 @@ namespace AMDiS { namespace Parallel { if (printTimings) t = new Timer(); - // === Create DOF communicator. === - - dofComm.init(levelData, feSpaces); - dofComm.create(intBoundary); - - - // === If requested, create more information on communication DOFs. === + // === Create all DOF communicators, if mesh is NULL. === + // === Otherwise create only special one. === + if (!mesh) { + std::map<Mesh*, MultiLevelDofComm>::iterator it = dofComms.begin(); + for (; it != dofComms.end(); it++) + it->second.create(it->first, intBoundary); + } else { + TEST_EXIT_DBG(dofComms.find(mesh) != dofComms.end())("No such mesh.\n"); + dofComms[mesh].create(mesh, intBoundary); + } + // === If requested, create more information on communication DOFs. === + if (createBoundaryDofFlag.isSet(BOUNDARY_SUBOBJ_SORTED)) { int nLevels = levelData.getNumberOfLevels(); @@ -2154,7 +2313,9 @@ namespace AMDiS { namespace Parallel { !it.end(); ++it) { if (it->rankObj.subObj == geo) { DofContainer dofs; - it->rankObj.el->getAllDofs(feSpace, it->rankObj, dofs); + + intBoundary[level].getElementPtr(it->rankObj.elIndex, feSpace->getMesh()) + ->getAllDofs(feSpace, it->rankObj, dofs); if (createBoundaryDofFlag.isSet(BOUNDARY_FILL_INFO_SEND_DOFS)) boundaryDofInfo[level][feSpace]. @@ -2169,7 +2330,9 @@ namespace AMDiS { namespace Parallel { !it.end(); ++it) { if (it->rankObj.subObj == geo) { DofContainer dofs; - it->rankObj.el->getAllDofs(feSpace, it->rankObj, dofs); + + intBoundary[level].getElementPtr(it->rankObj.elIndex, feSpace->getMesh()) + ->getAllDofs(feSpace, it->rankObj, dofs); if (createBoundaryDofFlag.isSet(BOUNDARY_FILL_INFO_RECV_DOFS)) boundaryDofInfo[level][feSpace]. @@ -2190,19 +2353,30 @@ namespace AMDiS { namespace Parallel { void MeshDistributor::removeMacroElements() { - std::set<MacroElement*> macrosToRemove; - for (deque<MacroElement*>::iterator it = mesh->firstMacroElement(); - it != mesh->endOfMacroElements(); ++it) - if (partitioner->getElementInRank()[(*it)->getIndex()] == false) - macrosToRemove.insert(*it); + for (size_t i = 0; i < meshes.size(); i++) { + std::set<MacroElement*> macrosToRemove; + for (deque<MacroElement*>::iterator it = meshes[i]->firstMacroElement(); + it != meshes[i]->endOfMacroElements(); ++it) + if (partitioner->getElementInRank()[(*it)->getIndex()] == false) + macrosToRemove.insert(*it); - mesh->removeMacroElements(macrosToRemove, feSpaces); + meshes[i]->removeMacroElements(macrosToRemove, meshToFeSpaces[meshes[i]]); + } + } + + void MeshDistributor::updateDofRelatedStruct() + { + for (size_t i = 0; i < meshes.size(); i++) + updateDofRelatedStruct(meshes[i]); + + updateLocalGlobalNumbering(); } - - void MeshDistributor::updateLocalGlobalNumbering() + void MeshDistributor::updateDofRelatedStruct(Mesh* mesh) { - FUNCNAME("MeshDistributor::updateLocalGlobalNumbering()"); + FUNCNAME("MeshDistributor::updateDofRelatedStruct()"); + + TEST_EXIT(mesh)("No mesh.\n"); Timer t; @@ -2214,28 +2388,15 @@ namespace AMDiS { namespace Parallel { #endif // === Update DOF communicator objects. === - - createBoundaryDofs(); + createBoundaryDofs(mesh); // === Update all registered DOF mapping objects. === - - updateParallelDofMappings(); - - - // === Create periodic DOF maps, if there are periodic boundaries. === - - if (hasPeriodicBoundary) { - createPeriodicMap(); - - for (int i = 0; i < static_cast<int>(dofMaps.size()); i++) - dofMaps[i]->updateMatIndex(); - } + updateDofsToDofMapping(mesh); // === Update DOF admins due to new number of DOFs. === - - lastMeshChangeIndex = mesh->getChangeIndex(); + lastMeshChangeIndexs[mesh] = mesh->getChangeIndex(); #if (DEBUG != 0) @@ -2243,91 +2404,148 @@ namespace AMDiS { namespace Parallel { stringstream ss; ss << debugOutputDir << "elementMaps." << fileNumber ; - //write local Element Maps to csv file + // Write local Element Maps to csv file ParallelDebug::writeCsvElementMap(feSpaces[0], *(dofMaps[0]), ss.str(), "csv"); fileNumber++; - ParallelDebug::testDofContainerCommunication(*this); - - MSG("------------- Debug information -------------\n"); - MSG("| number of levels: %d\n", levelData.getNumberOfLevels()); - MSG("| number of FE spaces: %d\n", feSpaces.size()); - - - for (int i = 0; i < static_cast<int>(dofMaps.size()); i++) { - vector<const FiniteElemSpace*>& dofMapSpaces = dofMaps[i]->getFeSpaces(); - - for (int j = 0; j < static_cast<int>(dofMapSpaces.size()); j++) { - const FiniteElemSpace *feSpace = dofMapSpaces[j]; - MSG("| FE space = %d (pointer adr %p):\n", j, feSpace); - MSG("| nRankDofs = %d\n", (*(dofMaps[i]))[feSpace].nRankDofs); - MSG("| nOverallDofs = %d\n", (*(dofMaps[i]))[feSpace].nOverallDofs); - MSG("| rStartDofs = %d\n", (*(dofMaps[i]))[feSpace].rStartDofs); - } - } + ParallelDebug::testDofContainerCommunication(*this, mesh); // debug::writeElementIndexMesh(mesh, debugOutputDir + "elementIndex-" + // lexical_cast<string>(mpiRank) + ".vtu"); - ParallelDebug::writeDebugFile(feSpaces[feSpaces.size() - 1], - *(dofMaps[0]), - debugOutputDir + "mpi-dbg", "dat"); debug::testSortedDofs(mesh, elMap); int test = 0; Parameters::get("parallel->remove periodic boundary", test); - if (test == 0) { - ParallelDebug::testCommonDofs(*this, true); - ParallelDebug::testGlobalIndexByCoords(*this); - } + if (test == 0) + ParallelDebug::testCommonDofs(*this, mesh, true); +#endif + + MPI::COMM_WORLD.Barrier(); + MSG("Update parallel data structures needed %.5f seconds\n", t.elapsed()); + } + + void MeshDistributor::updateLocalGlobalNumbering() + { + FUNCNAME("MeshDistributor::updateLocalGlobalNumbering()"); + + Timer t; +#if (DEBUG != 0) + bool printInfo = true; #else + bool printInfo = false; +#endif + Parameters::get("parallel->print dofmap info", printInfo); + + for (size_t i = 0; i < dofMaps.size(); i++) { + dofMaps[i]->update(); + if (printInfo) + dofMaps[i]->printInfo(); + } + + // === Create periodic DOF maps, if there are periodic boundaries. === - for (int i = 0; i < static_cast<int>(dofMaps.size()); i++) { - vector<const FiniteElemSpace*>& dofMapSpaces = dofMaps[i]->getFeSpaces(); + if (hasPeriodicBoundary) { + createPeriodicMap(); - for (int j = 0; j < static_cast<int>(dofMapSpaces.size()); j++) - MSG("FE space %d: nRankDofs = %d nOverallDofs = %d\n", j, - (*(dofMaps[i]))[feSpaces[j]].nRankDofs, - (*(dofMaps[i]))[feSpaces[j]].nOverallDofs); + for (size_t i = 0; i < dofMaps.size(); i++) + dofMaps[i]->updateMatIndex(); } - int tmp = 0; - Parameters::get(name + "->write parallel debug file", tmp); - if (tmp) - ParallelDebug::writeDebugFile(feSpaces[feSpaces.size() - 1], - *(dofMaps[0]), - debugOutputDir + "mpi-dbg", "dat"); -#endif + if (printInfo) { + int test = 0; + Parameters::get("parallel->remove periodic boundary", test); + + MSG("------------- Debug information -------------\n"); + for (size_t k = 0; k < meshes.size(); k++) { + Mesh* mesh = meshes[k]; + + MSG("| mesh pointer adr: %p\n", mesh); + MSG("| number of levels: %d\n", levelData.getNumberOfLevels()); + MSG("| number of FE spaces: %d\n", meshToFeSpaces[mesh].size()); + + + for (size_t i = 0; i < dofMaps.size(); i++) { + vector<const FiniteElemSpace*> dofMapSpaces = dofMaps[i]->getFeSpaces(mesh); + + if (dofMapSpaces.empty()) + continue; + + for (size_t j = 0; j < dofMapSpaces.size(); j++) { + const FiniteElemSpace *feSpace = dofMapSpaces[j]; + MSG("| FE space = %d (pointer adr %p):\n", j, feSpace); + MSG("| nRankDofs = %d\n", (*(dofMaps[i]))[feSpace].nRankDofs); + MSG("| nOverallDofs = %d\n", (*(dofMaps[i]))[feSpace].nOverallDofs); + MSG("| rStartDofs = %d\n", (*(dofMaps[i]))[feSpace].rStartDofs); + } + } + +// ParallelDebug::writeDebugFile(meshToFeSpaces[mesh][meshToFeSpaces[mesh].size() - 1], +// *(dofMaps[0]), +// debugOutputDir + "mpi-dbg", "dat"); + + if (test == 0) + ParallelDebug::testGlobalIndexByCoords(*this, mesh); + } + + } else { + +// int tmp = 0; +// Parameters::get(name + "->write parallel debug file", tmp); + + for (size_t k = 0; k < meshes.size(); k++) { + Mesh* mesh = meshes[k]; + + for (size_t i = 0; i < dofMaps.size(); i++) { + + vector<const FiniteElemSpace*> dofMapSpaces = dofMaps[i]->getFeSpaces(mesh); + + if (dofMapSpaces.empty()) + continue; + + for (size_t j = 0; j < dofMapSpaces.size(); j++) + MSG("FE space %d (mesh ptr %p): nRankDofs = %d nOverallDofs = %d\n", j, dofMapSpaces[j]->getMesh(), + (*(dofMaps[i]))[dofMapSpaces[j]].nRankDofs, + (*(dofMaps[i]))[dofMapSpaces[j]].nOverallDofs); + } + +// Write debug file for each mesh and each dofmap? +// if (tmp) +// ParallelDebug::writeDebugFile(meshToFeSpaces[mesh][meshToFeSpaces[mesh].size() - 1], +// *(dofMaps[0]), +// debugOutputDir + "mpi-dbg", "dat"); + } + } - MSG("Rebuild of parallel data structures needed %.5f seconds\n", t.elapsed()); + MPI::COMM_WORLD.Barrier(); + MSG("Update dof mapping needed %.5f seconds\n", t.elapsed()); } - void MeshDistributor::updateParallelDofMappings() + void MeshDistributor::updateDofsToDofMapping(Mesh* mesh) { - FUNCNAME("MeshDistributor::updateParallelDofMappings()"); + FUNCNAME("MeshDistributor::updateDofsToDofMapping()"); Timer *t = NULL; if (printTimings) t = new Timer(); TEST_EXIT(dofMaps.size())("No DOF mapping defined!\n"); - - for (int i = 0; i < static_cast<int>(dofMaps.size()); i++) { - vector<const FiniteElemSpace*>& dofMapSpaces = dofMaps[i]->getFeSpaces(); + + for (size_t i = 0; i < dofMaps.size(); i++) { + vector<const FiniteElemSpace*> dofMapSpaces = dofMaps[i]->getFeSpaces(mesh); - dofMaps[i]->clear(); - - for (int j = 0; j < static_cast<int>(dofMapSpaces.size()); j++) - updateLocalGlobalNumbering(*(dofMaps[i]), dofMapSpaces[j]); + if (dofMapSpaces.empty()) + continue; + + dofMaps[i]->clear(mesh); + + for (size_t j = 0; j < dofMapSpaces.size(); j++) + updateDofsToDofMapping(*(dofMaps[i]), dofMapSpaces[j]); - dofMaps[i]->update(); -#if (DEBUG != 0) - dofMaps[i]->printInfo(); -#endif } if (printTimings && t) { @@ -2337,10 +2555,12 @@ namespace AMDiS { namespace Parallel { } - void MeshDistributor::updateLocalGlobalNumbering(ParallelDofMapping &dofMap, + void MeshDistributor::updateDofsToDofMapping(ParallelDofMapping &dofMap, const FiniteElemSpace *feSpace) { - DofComm &dcom = dofMap.getDofComm(); + + DofComm &dcom = dofMap[feSpace].getDofComm(); + Mesh* mesh = feSpace->getMesh(); // === Get all DOFs in ranks partition. === @@ -2387,7 +2607,7 @@ namespace AMDiS { namespace Parallel { // MPI::COMM_WORLD.Barrier(); [TODO: CHANGE BECAUSE NOT ALL RANKS HAVE PERIODIC MAP!!!] double first = MPI::Wtime(); - for (unsigned int i = 0; i < feSpaces.size(); i++) + for (size_t i = 0; i < feSpaces.size(); i++) createPeriodicMap(feSpaces[i]); // MPI::COMM_WORLD.Barrier(); @@ -2400,9 +2620,19 @@ namespace AMDiS { namespace Parallel { FUNCNAME("MeshDistributor::createPeriodicMap()"); TEST_EXIT(dofMaps.size())("No DOF mapping defined!\n"); - - DofComm::DataType &periodicDofs = dofComm[0].getPeriodicDofs(); - ComponentDofMap &dofMap = (*(dofMaps[0]))[feSpace]; + + ParallelDofMapping* parDofMap = NULL; + for (size_t i = 0; i < dofMaps.size(); i++) + if (dofMaps[i]->hasFeSpace(feSpace)) { + parDofMap = dofMaps[i]; + break; + } + + TEST_EXIT_DBG(parDofMap)("FE space not found in parallel dof map.\n"); + ComponentDofMap &dofMap = (*parDofMap)[feSpace]; + Mesh* mesh = feSpace->getMesh(); + DofComm::DataType &periodicDofs = dofComms[mesh][0].getPeriodicDofs(); + StdMpi<vector<int> > stdMpi(MPI::COMM_WORLD, false); @@ -2420,15 +2650,15 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(it->second.size() % 2 == 0)("Should not happen!\n"); - for (unsigned int i = 0; i < it->second.size(); i++) { + for (size_t i = 0; i < it->second.size(); i++) { AtomicBoundary &bound = it->second[i]; - - TEST_EXIT_DBG(bound.rankObj.el)("No rank object!\n"); - TEST_EXIT_DBG(bound.neighObj.el)("No neigh object!\n"); - + DofContainer dofs0, dofs1; - bound.rankObj.el->getAllDofs(feSpace, bound.rankObj, dofs0); - bound.neighObj.el->getAllDofs(feSpace, bound.neighObj, dofs1); + + intBoundary[0].getElementPtr(bound.rankObj.elIndex, mesh) + ->getAllDofs(feSpace, bound.rankObj, dofs0); + intBoundary[0].getElementPtr(bound.neighObj.elIndex, mesh) + ->getAllDofs(feSpace, bound.neighObj, dofs1); TEST_EXIT_DBG(dofs0.size() == dofs1.size()) ("Number of DOFs does not fit together: %d %d\n", @@ -2436,7 +2666,7 @@ namespace AMDiS { namespace Parallel { BoundaryType type = bound.type; - for (unsigned int j = 0; j < dofs0.size(); j++) { + for (size_t j = 0; j < dofs0.size(); j++) { DegreeOfFreedom globalDof0 = dofMap[*(dofs0[j])].global; DegreeOfFreedom globalDof1 = dofMap[*(dofs1[j])].global; @@ -2454,7 +2684,8 @@ namespace AMDiS { namespace Parallel { boundIt != it->second.end(); ++boundIt) { int nDofs = dofs.size(); - boundIt->rankObj.el->getAllDofs(feSpace, boundIt->rankObj, dofs); + intBoundary[0].getElementPtr(boundIt->rankObj.elIndex, mesh) + ->getAllDofs(feSpace, boundIt->rankObj, dofs); for (unsigned int i = 0; i < (dofs.size() - nDofs); i++) rankToDofType[it->first].push_back(boundIt->type); @@ -2519,9 +2750,10 @@ namespace AMDiS { namespace Parallel { continue; DofContainer dofs; - boundIt->rankObj.el->getAllDofs(feSpace, boundIt->rankObj, dofs); + intBoundary[0].getElementPtr(boundIt->rankObj.elIndex, mesh) + ->getAllDofs(feSpace, boundIt->rankObj, dofs); - for (unsigned int i = 0; i < dofs.size(); i++) { + for (size_t i = 0; i < dofs.size(); i++) { DegreeOfFreedom globalDof = dofMap[*dofs[i]].global; std::set<BoundaryType>& assoc = @@ -2553,44 +2785,49 @@ namespace AMDiS { namespace Parallel { void MeshDistributor::createMacroElementInfo() { - FUNCNAME("MeshDistributor::createMacroElementInfo()"); - - for (deque<MacroElement*>::iterator it = mesh->firstMacroElement(); - it != mesh->endOfMacroElements(); ++it) { - - allMacroElements.push_back(*it); - + // Store neighbours info. + for (deque<MacroElement*>::iterator it = macroMesh->firstMacroElement(); + it != macroMesh->endOfMacroElements(); ++it) { + int elIndex = (*it)->getIndex(); + + macroElementNeighbours[elIndex].resize(macroMesh->getGeo(NEIGH)); + for (int i = 0; i < macroMesh->getGeo(NEIGH); i++) + macroElementNeighbours[elIndex][i] = + (*it)->getNeighbour(i) ? (*it)->getNeighbour(i)->getIndex() : -1; + } - macroElementNeighbours[elIndex].resize(mesh->getGeo(NEIGH)); - for (int i = 0; i < mesh->getGeo(NEIGH); i++) - macroElementNeighbours[elIndex][i] = - (*it)->getNeighbour(i) ? (*it)->getNeighbour(i)->getIndex() : -1; - } + // Store macro elements + for (size_t i = 0; i < meshes.size(); i++) + for (deque<MacroElement*>::iterator it = meshes[i]->firstMacroElement(); + it != meshes[i]->endOfMacroElements(); ++it) + allMacroElements[meshes[i]].push_back(*it); + } - void MeshDistributor::updateMacroElementInfo() { - deque<MacroElement*>& meshMacros = mesh->getMacroElements(); - - for (unsigned int i = 0; i < allMacroElements.size(); i++) { - for (deque<MacroElement*>::iterator it = meshMacros.begin(); + for (size_t i = 0; i < meshes.size(); i++) { + deque<MacroElement*>& meshMacros = meshes[i]->getMacroElements(); + + vector<MacroElement*>& allMacros = allMacroElements[meshes[i]]; + + for (size_t j = 0; j < allMacros.size(); j++) { + for (deque<MacroElement*>::iterator it = meshMacros.begin(); it != meshMacros.end(); ++it) { - if ((*it)->getIndex() == allMacroElements[i]->getIndex() && - *it != allMacroElements[i]) { - delete allMacroElements[i]; - allMacroElements[i] = *it; + if ((*it)->getIndex() == allMacros[j]->getIndex() && + *it != allMacros[j]) { + delete allMacros[j]; + allMacros[j] = *it; + } } } } } - + //TODO To be changed if necessary void MeshDistributor::serialize(ostream &out) { - FUNCNAME("MeshDistributor::serialize()"); - checkMeshChange(false); partitioner->serialize(out); @@ -2608,8 +2845,8 @@ namespace AMDiS { namespace Parallel { int nSize = allMacroElements.size(); SerUtil::serialize(out, nSize); - for (int i = 0; i < nSize; i++) - allMacroElements[i]->serialize(out); +// for (int i = 0; i < nSize; i++) +// allMacroElements[i]->serialize(out); SerUtil::serialize(out, nMeshChangesAfterLastRepartitioning); SerUtil::serialize(out, repartitioningCounter); @@ -2617,10 +2854,9 @@ namespace AMDiS { namespace Parallel { } + //TODO To be changed if necessary void MeshDistributor::deserialize(istream &in) { - FUNCNAME("MeshDistributor::deserialize()"); - partitioner->deserialize(in); SerUtil::deserialize(in, elemWeights); @@ -2631,7 +2867,7 @@ namespace AMDiS { namespace Parallel { for (unsigned int i = 0; i < feSpaces.size(); i++) { ElementDofIterator elDofIter(feSpaces[i]); TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(meshes[0], -1, Mesh::CALL_LEAF_EL); while (elInfo) { elDofIter.reset(elInfo->getElement()); do { @@ -2644,7 +2880,7 @@ namespace AMDiS { namespace Parallel { elObjDb.deserialize(in); - intBoundary.deserialize(in, mesh); + intBoundary.deserialize(in, meshes[0]); // === Deerialieze FE space dependent data === @@ -2652,15 +2888,15 @@ namespace AMDiS { namespace Parallel { int nSize = 0; SerUtil::deserialize(in, nSize); - allMacroElements.resize(nSize); - for (int i = 0; i < nSize; i++) { - // We do not need the neighbour indices, but must still read them. - vector<int> indices; - allMacroElements[i] = new MacroElement(mesh->getDim()); - allMacroElements[i]->writeNeighboursTo(&indices); - allMacroElements[i]->deserialize(in); - allMacroElements[i]->getElement()->setMesh(mesh); - } +// allMacroElements.resize(nSize); +// for (int i = 0; i < nSize; i++) { +// // We do not need the neighbour indices, but must still read them. +// vector<int> indices; +// allMacroElements[i] = new MacroElement(mesh->getDim()); +// allMacroElements[i]->writeNeighboursTo(&indices); +// allMacroElements[i]->deserialize(in); +// allMacroElements[i]->getElement()->setMesh(mesh); +// } SerUtil::deserialize(in, nMeshChangesAfterLastRepartitioning); SerUtil::deserialize(in, repartitioningCounter); diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index fcff9718..efad03e2 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -115,7 +115,7 @@ namespace AMDiS { namespace Parallel { void removeInterchangeVector(SystemVector* vec); /** \brief - * This function checks if the mesh has changed on at least on rank. In + * This function checks if the mesh has changed on at least one rank. In * this case, the interior boundaries are adapted on all ranks such that * they fit together on all ranks. Furthermore the function * \ref updateLocalGlobalNumbering() is called to update the DOF numberings @@ -134,9 +134,6 @@ namespace AMDiS { namespace Parallel { /// ranks. bool repartitionMesh(); - void quickRepartition(); - - void fullRepartition(); void getImbalanceFactor(double &imbalance, int &minDofs, @@ -159,9 +156,19 @@ namespace AMDiS { namespace Parallel { return name; } - inline Mesh* getMesh() + inline Mesh* getMacroMesh() + { + return macroMesh; + } + + inline Mesh* getMesh(int i = 0) { - return mesh; + return meshes[i]; + } + + inline int getNumberOfMeshes() + { + return meshes.size(); } /// Returns the periodic mapping handler, \ref periodicMap. @@ -174,6 +181,16 @@ namespace AMDiS { namespace Parallel { { return dofComm[level]; } + + DofComm& getDofComm(Mesh* mesh, int level) + { + return dofComms[mesh][level]; + } + + std::map<Mesh*, MultiLevelDofComm>& getDofComms() + { + return dofComms; + } InteriorBoundary& getIntBoundary(int level) { @@ -182,7 +199,16 @@ namespace AMDiS { namespace Parallel { inline long getLastMeshChangeIndex() { - return lastMeshChangeIndex; + int overallMeshChangeIndex = 0; + for(size_t i = 0; i < meshes.size(); i++) { + overallMeshChangeIndex += lastMeshChangeIndexs[meshes[i]]; + } + return overallMeshChangeIndex; + } + + inline long getLastMeshChangeIndex(Mesh* m) + { + return lastMeshChangeIndexs[m]; } inline int getMpiRank() @@ -271,10 +297,42 @@ namespace AMDiS { namespace Parallel { /// DOFVector, but instead sends all values of all DOFVectors all at once. void synchVector(SystemVector &vec); + /// Works quite similar to the function \ref synchVector, but instead the + /// values of subdomain vectors are add along the boundaries. template<typename T> void synchAddVector(DOFVector<T> &vec) { - synchVector(vec, functors::add_assign<T>()); + const FiniteElemSpace *fe = vec.getFeSpace(); + + int nLevels = levelData.getNumberOfLevels(); + for (int level = nLevels - 1; level >= 0; level--) { + StdMpi<std::vector<T> > stdMpi(levelData.getMpiComm(level)); + + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), fe); + !it.end(); it.nextRank()) { + std::vector<T> dofs; + dofs.reserve(it.getDofs().size()); + + for (; !it.endDofIter(); it.nextDof()) + dofs.push_back(vec[it.getDofIndex()]); + + stdMpi.send(it.getRank(), dofs); + } + + for (DofComm::Iterator it(dofComm[level].getSendDofs()); + !it.end(); it.nextRank()) + stdMpi.recv(it.getRank()); + + stdMpi.startCommunication(); + + for (DofComm::Iterator it(dofComm[level].getSendDofs(), fe); + !it.end(); it.nextRank()) + for (; !it.endDofIter(); it.nextDof()) + vec[it.getDofIndex()] += + stdMpi.getRecvData(it.getRank())[it.getDofCounter()]; + } + + synchVector(vec); } /// In 3D, a subdomain may not be a valid AMDiS mesh if it contains two @@ -288,8 +346,6 @@ namespace AMDiS { namespace Parallel { /** \brief Is used only within \ref fix3dMeshRefinement. * * \param[in] elems Set of macro element indices. - * \param[in] edgeNoInEl Maps from each element index in elems to a - * local edge number. * \param[out] disconnectedEls On output, this vector contains sets of * element indices. The union is equal to elems. * Each set contains all element indices, which @@ -298,7 +354,6 @@ namespace AMDiS { namespace Parallel { * cannot be reached via neigbourhood relation. */ void helpToFix(std::set<int> &elems, - std::map<int, int> &edgeNoInEl, std::vector<std::set<int> > &disconnectedEls); void setBoundaryDofRequirement(Flag flag) @@ -334,16 +389,16 @@ namespace AMDiS { namespace Parallel { { return levelData; } - - /// Updates all registered parallel DOF mappings, see \ref dofMaps. - void updateParallelDofMappings(); + + /// Update dof communicators, boundary dof info and the parallel dof mappings. + /// If it is called for all meshes, \ref updateLocalGlobalNumbering is automatically + /// called inside. If it is used for each mesh seperately, please don't forget to + /// add \ref updateLocalGlobalNumbering to update the global matrix index. + void updateDofRelatedStruct(); + + void updateDofRelatedStruct(Mesh* mesh); void updateLocalGlobalNumbering(); - - /// Updates the local and global DOF numbering after the mesh has been - /// changed. - void updateLocalGlobalNumbering(ParallelDofMapping &dmap, - const FiniteElemSpace *feSpace); /// set variable \ref repartitioningAllowed void setRepartitioningAllowed(bool allowed) @@ -357,6 +412,18 @@ namespace AMDiS { namespace Parallel { } protected: + /// Rebuild only part of the mesh domain, which is necessary + void quickRepartition(Mesh* mesh); + + /// Rebuild whole mesh domain + void fullRepartition(Mesh* mesh); + + /// Updates all registered parallel DOF mappings, see \ref dofMaps. + void updateDofsToDofMapping(Mesh* mesh = NULL); + + /// Updates the DOF after the mesh has been changed, see \ref dofMaps. + void updateDofsToDofMapping(ParallelDofMapping &dmap, + const FiniteElemSpace *feSpace); /// Checks if repartition is needed. bool isRepartitionNecessary(); @@ -380,7 +447,7 @@ namespace AMDiS { namespace Parallel { void createInteriorBoundary(bool firstCall); /// - void createBoundaryDofs(); + void createBoundaryDofs(Mesh* mesh = NULL); /// Removes all macro elements from the mesh that are not part of ranks /// partition. @@ -415,12 +482,13 @@ namespace AMDiS { namespace Parallel { * * \param[in] allBound Defines a map from rank to interior boundaries * which should be checked. + * \param[in] mesh The mesh the interior boundaries belong to. * * \return If the mesh has been changed by this function, it returns * true. Otherwise, it returns false, i.e., the given interior * boundaries fit together on both sides. */ - bool checkAndAdaptBoundary(RankToBoundMap &allBound); + bool checkAndAdaptBoundary(RankToBoundMap &allBound, Mesh* mesh); /// Removes all periodic boundary condition information from all matrices and /// vectors of all stationary problems and from the mesh itself. @@ -507,10 +575,16 @@ namespace AMDiS { namespace Parallel { /// Set of all different FE spaces. std::vector<const FiniteElemSpace*> feSpaces; - /// Pointer to the only mesh. Note that we do not yet support multi mesh - /// method, thus even if we consider coupled problems, all problems must - /// be defined on the same mesh. - Mesh *mesh; + /// Always equal to meshes[0] which is used as macro + /// mesh. For example, passed to \ref meshPartitioner. + Mesh *macroMesh; + + /// Meshes to be managed for parallelization. Currently only two meshes + /// are allowed since multi mesh method is limited to two meshes. + std::vector<Mesh*> meshes; + + /// Stores the map of meshes and the corresponding FE spaces defined on them + MeshToFeSpaces meshToFeSpaces; /// A refinement manager that should be used on the mesh. It is used to /// refine elements at interior boundaries in order to fit together with @@ -543,8 +617,11 @@ namespace AMDiS { namespace Parallel { /// partitioning the whole mesh. MultiLevelInteriorBoundary intBoundary; - /// Dof communicator object + /// Dof communicator object // TODO: to be deleted MultiLevelDofComm dofComm; + + /// Dof communicator objects for each mesh + std::map<Mesh*, MultiLevelDofComm> dofComms; PeriodicMap periodicMap; @@ -592,7 +669,7 @@ namespace AMDiS { namespace Parallel { /// Stores the mesh change index. This is used to recognize changes in the /// mesh structure (e.g. through refinement or coarsening managers). - long lastMeshChangeIndex; + std::map<Mesh*, long> lastMeshChangeIndexs; /// Stores for all macro elements of the original macro mesh the /// neighbourhood information based on element indices. Thus, each macro @@ -602,7 +679,9 @@ namespace AMDiS { namespace Parallel { /// Store all macro elements of the overall mesh, i.e., before the /// mesh is redistributed for the first time. - std::vector<MacroElement*> allMacroElements; + /// Store all macro elements of the overall mesh, i.e., before the + /// mesh is redistributed for the first time. + std::map<Mesh*, std::vector<MacroElement*> > allMacroElements; Flag createBoundaryDofFlag; diff --git a/AMDiS/src/parallel/MeshManipulation.cc b/AMDiS/src/parallel/MeshManipulation.cc index d10676dc..91facf8a 100644 --- a/AMDiS/src/parallel/MeshManipulation.cc +++ b/AMDiS/src/parallel/MeshManipulation.cc @@ -53,6 +53,14 @@ namespace AMDiS { namespace Parallel { delete refineManager; } + void MeshManipulation::deleteDoubleDofs(std::vector<const FiniteElemSpace*>& feSpaces, + std::vector<MacroElement*>& newMacroEl, + ElementObjectDatabase &elObjDb) + { + std::set<MacroElement*> newMacroElSet(newMacroEl.begin(), newMacroEl.end()); + deleteDoubleDofs(feSpaces, newMacroElSet, elObjDb); + } + void MeshManipulation::deleteDoubleDofs(vector<const FiniteElemSpace*>& feSpaces, std::set<MacroElement*>& newMacroEl, @@ -90,7 +98,6 @@ namespace AMDiS { namespace Parallel { elInfo = stack.traverseNext(elInfo); } - #if (DEBUG != 0) DOFVector<WorldVector<double> > coords(feSpace, "dofCorrds"); feSpace->getMesh()->getDofIndexCoords(coords); @@ -153,6 +160,8 @@ namespace AMDiS { namespace Parallel { Element *el0 = (*it)->getElement(); Element *el1 = macroIndexMap[elIt->elIndex]->getElement(); + TEST_EXIT_DBG(el0->getMesh() == el1->getMesh())("Mesh is different.\n"); + bool reverseMode = elObjDb.getEdgeReverseMode(elObj, *elIt); BoundaryObject b0(el0, 0, EDGE, i, reverseMode); @@ -163,6 +172,7 @@ namespace AMDiS { namespace Parallel { el0->getAllDofs(feSpace, b0, dofs0, true, &dofGeoIndex0); el1->getAllDofs(feSpace, b1, dofs1, true, &dofGeoIndex1); + #if (DEBUG != 0) if (feSpaces.size()) debug::testDofsByCoords(coords, dofs0, dofs1); @@ -170,7 +180,6 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(dofs0.size() == dofs1.size()) ("Should not happen!\n"); #endif - for (unsigned int i = 0; i < dofs0.size(); i++) { mapDelDofs[dofs0[i]] = dofs1[i]; dofPosIndex[dofs0[i]] = dofGeoIndex0[i]; @@ -234,7 +243,6 @@ namespace AMDiS { namespace Parallel { } } } - macrosProcessed.insert((*it)->getIndex()); } diff --git a/AMDiS/src/parallel/MeshManipulation.h b/AMDiS/src/parallel/MeshManipulation.h index 037ad608..172785ef 100644 --- a/AMDiS/src/parallel/MeshManipulation.h +++ b/AMDiS/src/parallel/MeshManipulation.h @@ -42,6 +42,10 @@ namespace AMDiS { namespace Parallel { void deleteDoubleDofs(std::vector<const FiniteElemSpace*>& feSpaces, std::set<MacroElement*>& newMacroEl, ElementObjectDatabase &elObj); + + void deleteDoubleDofs(std::vector<const FiniteElemSpace*>& feSpaces, + std::vector<MacroElement*>& newMacroEl, + ElementObjectDatabase &elObjDb); /** \brief * Starts the procedure to fit a given edge/face of a macro element with a diff --git a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc index e372bd84..d4276767 100644 --- a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc +++ b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc @@ -50,6 +50,7 @@ namespace AMDiS { namespace Parallel { TEST_EXIT(meshDistributor)("No mesh distributor object defined!\n"); domainComm = meshDistributor->getMpiComm(meshLevel); + if (meshLevel >= 1) coarseSpaceComm = meshDistributor->getMpiComm(meshLevel - 1); @@ -140,14 +141,14 @@ namespace AMDiS { namespace Parallel { bool localMatrix = (domainComm == MPI::COMM_SELF); if (checkMeshChange()) { - int nMat = uniqueCoarseMap.size() + 1; + int nMat = uniqueCoarseMap.size() + 1; // Not multilevel should always be 1 nnz.resize(nMat); for (int i = 0; i < nMat; i++) { nnz[i].resize(nMat); for (int j = 0; j < nMat; j++) nnz[i][j].clear(); } - + nnz[0][0].create(seqMat, *interiorMap, (coarseSpaceMap.size() == 0 ? &(meshDistributor->getPeriodicMap()) : NULL), meshDistributor->getElementObjectDb(), @@ -157,7 +158,7 @@ namespace AMDiS { namespace Parallel { for (int j = 0; j < nMat; j++) { if (i == 0 && j == 0) continue; - + ParallelDofMapping &rowMap = (i == 0 ? *interiorMap : *(uniqueCoarseMap[i - 1])); ParallelDofMapping &colMap = @@ -172,7 +173,6 @@ namespace AMDiS { namespace Parallel { // === Create PETSc matrices and PETSc vectors with the computed === // === nnz data structure. === - int nRankInteriorRows = interiorMap->getRankDofs(); int nOverallInteriorRows = interiorMap->getOverallDofs(); @@ -197,7 +197,7 @@ namespace AMDiS { namespace Parallel { 300, PETSC_NULL, 300, PETSC_NULL, &mat[0][0]); } } - + MatSetOption(mat[0][0], MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); if (meshLevel == 0) { @@ -216,7 +216,6 @@ namespace AMDiS { namespace Parallel { &vecRhs[0]); } - int nCoarseMap = uniqueCoarseMap.size(); for (int i = 0; i < nCoarseMap; i++) { ParallelDofMapping* cMap = uniqueCoarseMap[i]; diff --git a/AMDiS/src/parallel/ParallelDebug.cc b/AMDiS/src/parallel/ParallelDebug.cc index 14fe0d5b..fa4a30e7 100644 --- a/AMDiS/src/parallel/ParallelDebug.cc +++ b/AMDiS/src/parallel/ParallelDebug.cc @@ -181,7 +181,7 @@ namespace AMDiS { namespace Parallel { perMap.periodicDofAssociations[feSpace].begin(); it != perMap.periodicDofAssociations[feSpace].end(); ++it) { WorldVector<double> c; - pdb.mesh->getDofIndexCoords(it->first, pdb.feSpaces[0], c); + pdb.macroMesh->getDofIndexCoords(it->first, pdb.feSpaces[0], c); } @@ -292,7 +292,7 @@ namespace AMDiS { namespace Parallel { for (unsigned int i = 0; i < dofs.size(); i++) { WorldVector<double> c; - pdb.mesh->getDofIndexCoords(*(dofs[i]), feSpace, c); + pdb.macroMesh->getDofIndexCoords(*(dofs[i]), feSpace, c); sendCoords[it->first].push_back(c); rankToDofType[it->first].push_back(boundIt->type); } @@ -321,7 +321,7 @@ namespace AMDiS { namespace Parallel { int nEqual = 0; - for (int j = 0; j < pdb.mesh->getDim(); j++) + for (int j = 0; j < pdb.macroMesh->getDim(); j++) if (c0[j] == c1[j]) nEqual++; @@ -329,9 +329,9 @@ namespace AMDiS { namespace Parallel { MSG("[DBG] %d-ith periodic DOF in boundary between ranks %d <-> %d is not correct!\n", i, mpiRank, it->first); MSG("[DBG] Coords on rank %d: %f %f %f\n", - mpiRank, c0[0], c0[1], (pdb.mesh->getDim() == 3 ? c0[2] : 0.0)); + mpiRank, c0[0], c0[1], (pdb.macroMesh->getDim() == 3 ? c0[2] : 0.0)); MSG("[DBG] Coords on rank %d: %f %f %f\n", - it->first, c1[0], c1[1], (pdb.mesh->getDim() == 3 ? c1[2] : 0.0)); + it->first, c1[0], c1[1], (pdb.macroMesh->getDim() == 3 ? c1[2] : 0.0)); foundError = 1; } @@ -343,13 +343,16 @@ namespace AMDiS { namespace Parallel { } - void ParallelDebug::testCommonDofs(MeshDistributor &pdb, bool printCoords) + // Test if the coordinates of recv and send dofs in dofcomm are matched + void ParallelDebug::testCommonDofs(MeshDistributor &pdb, Mesh* mesh, bool printCoords) { FUNCNAME("ParallelDebug::testCommonDofs()"); Timer t; // Get FE space with basis functions of the highest degree - const FiniteElemSpace *feSpace = pdb.feSpaces[pdb.feSpaces.size() - 1]; + const FiniteElemSpace *feSpace = + pdb.meshToFeSpaces[mesh][pdb.meshToFeSpaces[mesh].size() - 1]; + MultiLevelDofComm& dofComm = pdb.dofComms[mesh]; int testCommonDofs = 1; Parameters::get("dbg->test common dofs", testCommonDofs); @@ -387,14 +390,14 @@ namespace AMDiS { namespace Parallel { RankToCoords recvCoords; DOFVector<WorldVector<double> > coords(feSpace, "dofCorrds"); - pdb.mesh->getDofIndexCoords(coords); + mesh->getDofIndexCoords(coords); - for (DofComm::Iterator it(pdb.dofComm[level].getSendDofs(), feSpace); + for (DofComm::Iterator it(dofComm[level].getSendDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) sendCoords[it.getRank()].push_back(coords[it.getDofIndex()]); - for (DofComm::Iterator it(pdb.dofComm[level].getRecvDofs(), feSpace); + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) recvCoords[it.getRank()].push_back(coords[it.getDofIndex()]); @@ -487,7 +490,7 @@ namespace AMDiS { namespace Parallel { MSG("%s\n", oss.str().c_str()); debug::printInfoByDof(feSpace, - *(pdb.dofComm[level].getRecvDofs()[it->first][feSpace][i])); + *(dofComm[level].getRecvDofs()[it->first][feSpace][i])); } ERROR("Wrong DOFs in rank %d!\n", mpiRank); foundError = 1; @@ -501,83 +504,102 @@ namespace AMDiS { namespace Parallel { MSG("Test common dofs needed %.5f seconds\n", t.elapsed()); } - - void ParallelDebug::testGlobalIndexByCoords(MeshDistributor &pdb) + // Test dofmap dofs with same global index have same coords + void ParallelDebug::testGlobalIndexByCoords(MeshDistributor &pdb, Mesh* mesh) { FUNCNAME("ParallelDebug::testGlobalIndexByCoords()"); // Get FE space with basis functions of the highest degree - const FiniteElemSpace *feSpace = pdb.feSpaces[pdb.feSpaces.size() - 1]; - - DOFVector<WorldVector<double> > coords(feSpace, "tmp"); - pdb.mesh->getDofIndexCoords(coords); - - int nLevels = pdb.levelData.getNumberOfLevels(); - for (int level = 0; level < nLevels; level++) { - MPI::Intracomm &mpiComm = pdb.levelData.getMpiComm(level); - if (mpiComm == MPI::COMM_SELF) - continue; - -// int mpiRank = mpiComm.Get_rank(); -// int mpiSize = mpiComm.Get_size(); - - typedef map<int, WorldVector<double> > CoordsIndexMap; - CoordsIndexMap coordsToIndex; + MultiLevelDofComm& dofComm = pdb.dofComms[mesh]; + + for (size_t i = 0; i < pdb.dofMaps.size(); i++) { + vector<const FiniteElemSpace*> dofMapSpaces = pdb.dofMaps[i]->getFeSpaces(mesh); - DOFIterator<WorldVector<double> > it(&coords, USED_DOFS); - for (it.reset(); !it.end(); ++it) { - int idx = (*(pdb.dofMaps[level]))[feSpace][it.getDOFIndex()].global; - coordsToIndex[idx] = *it; -// MSG(" CHECK FOR DOF %d/%d AT COORDS %f %f %f\n", -// it.getDOFIndex(), -// coordsToIndex[(*it)], -// (*it)[0], (*it)[1], (pdb.mesh->getDim() == 3 ? (*it)[2] : 0.0)); - } + if(dofMapSpaces.empty()) + continue; - StdMpi<CoordsIndexMap> stdMpi(mpiComm, true); - for (DofComm::Iterator it(pdb.dofComm[level].getSendDofs(), feSpace); - !it.end(); it.nextRank()) - stdMpi.send(it.getRank(), coordsToIndex); - for (DofComm::Iterator it(pdb.dofComm[level].getRecvDofs(), feSpace); - !it.end(); it.nextRank()) - stdMpi.recv(it.getRank()); + const FiniteElemSpace *feSpace = NULL; + ParallelDofMapping* dfmap = pdb.dofMaps[i]; - stdMpi.startCommunication(); + size_t j = pdb.meshToFeSpaces[mesh].size() - 1; + for( ; j >= 0; j--) + if(find(dofMapSpaces.begin(), dofMapSpaces.end(), pdb.meshToFeSpaces[mesh][j]) + != dofMapSpaces.end()) + break; + feSpace = pdb.meshToFeSpaces[mesh][j]; - int foundError = 0; - for (DofComm::Iterator it(pdb.dofComm[level].getRecvDofs(), feSpace); - !it.end(); it.nextRank()) { - CoordsIndexMap& otherCoords = stdMpi.getRecvData(it.getRank()); + TEST_EXIT(dfmap || feSpace)("Something is wrong.\n"); - for (; !it.endDofIter(); it.nextDof()) { - WorldVector<double> recvCoords = coords[it.getDofIndex()]; - int idx = (*(pdb.dofMaps[level]))[feSpace][it.getDofIndex()].global; - - TEST_EXIT_DBG(otherCoords.count(idx))("Global index not found in neighbour partition\n"); - - WorldVector<double> diff = otherCoords[idx] - recvCoords; - double dist = sqrt(diff*diff); - if (dist > DBL_TOL) { - stringstream oss; - oss.precision(5); - oss << "DOF at coords "; - for (int i = 0; i < Global::getGeo(WORLD); i++) - oss << recvCoords[i] << " "; - oss << " do not fit together on rank " - << mpiComm.Get_rank() << " (global index: " - << it.getDofIndex() << ") and on rank " - << it.getRank() << " " - << " - LEVEL " << level; - - MSG("[DBG] %s\n", oss.str().c_str()); + DOFVector<WorldVector<double> > coords(feSpace, "tmp"); + mesh->getDofIndexCoords(coords); + + int nLevels = pdb.levelData.getNumberOfLevels(); + for (int level = 0; level < nLevels; level++) { + MPI::Intracomm &mpiComm = pdb.levelData.getMpiComm(level); + if (mpiComm == MPI::COMM_SELF) + continue; + + // int mpiRank = mpiComm.Get_rank(); + // int mpiSize = mpiComm.Get_size(); + + typedef map<int, WorldVector<double> > CoordsIndexMap; + CoordsIndexMap coordsToIndex; + + DOFIterator<WorldVector<double> > it(&coords, USED_DOFS); + for (it.reset(); !it.end(); ++it) { + int idx = (*dfmap)[feSpace][it.getDOFIndex()].global; + coordsToIndex[idx] = *it; + // MSG(" CHECK FOR DOF %d/%d AT COORDS %f %f %f\n", + // it.getDOFIndex(), + // coordsToIndex[(*it)], + // (*it)[0], (*it)[1], (pdb.mesh->getDim() == 3 ? (*it)[2] : 0.0)); + } + + StdMpi<CoordsIndexMap> stdMpi(mpiComm, true); + for (DofComm::Iterator it(dofComm[level].getSendDofs(), feSpace); + !it.end(); it.nextRank()) + stdMpi.send(it.getRank(), coordsToIndex); + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), feSpace); + !it.end(); it.nextRank()) + stdMpi.recv(it.getRank()); + + stdMpi.startCommunication(); + + int foundError = 0; + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), feSpace); + !it.end(); it.nextRank()) { + CoordsIndexMap& otherCoords = stdMpi.getRecvData(it.getRank()); + + for (; !it.endDofIter(); it.nextDof()) { + WorldVector<double> recvCoords = coords[it.getDofIndex()]; + int idx = (*dfmap)[feSpace][it.getDofIndex()].global; - foundError = 1; + TEST_EXIT_DBG(otherCoords.count(idx))("Global index not found in neighbour partition\n"); + + WorldVector<double> diff = otherCoords[idx] - recvCoords; + double dist = sqrt(diff*diff); + if (dist > DBL_TOL) { + stringstream oss; + oss.precision(5); + oss << "DOF at coords "; + for (int i = 0; i < Global::getGeo(WORLD); i++) + oss << recvCoords[i] << " "; + oss << " do not fit together on rank " + << mpiComm.Get_rank() << " (global index: " + << it.getDofIndex() << ") and on rank " + << it.getRank() << " " + << " - LEVEL " << level; + + MSG("[DBG] %s\n", oss.str().c_str()); + + foundError = 1; + } } } - } - mpi::globalAdd(foundError); - TEST_EXIT(foundError == 0)("Error found on at least on rank!\n"); + mpi::globalAdd(foundError); + TEST_EXIT(foundError == 0)("Error found on at least on rank!\n"); + } } } @@ -585,13 +607,15 @@ namespace AMDiS { namespace Parallel { void ParallelDebug::testAllElements(MeshDistributor &pdb) { FUNCNAME("ParallelDebug::testAllElements()"); + + TEST_EXIT(pdb.macroMesh) ("No macro mesh in mesh distributor.\n"); std::set<int> macroElements; int minElementIndex = numeric_limits<int>::max(); int maxElementIndex = numeric_limits<int>::min(); TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(pdb.mesh, 0, Mesh::CALL_EL_LEVEL); + ElInfo *elInfo = stack.traverseFirst(pdb.macroMesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { int elIndex = elInfo->getElement()->getIndex(); minElementIndex = std::min(minElementIndex, elIndex); @@ -599,7 +623,7 @@ namespace AMDiS { namespace Parallel { macroElements.insert(elInfo->getElement()->getIndex()); elInfo = stack.traverseNext(elInfo); } - + MPI::Intracomm mpiComm = MPI::COMM_WORLD; @@ -619,14 +643,14 @@ namespace AMDiS { namespace Parallel { } if (recvId > 1) { - ERROR_EXIT("Element %d is member of more than pne partition!\n", i); + ERROR_EXIT("Element %d is member of more than pne partition!\n", i); } } } } - - void ParallelDebug::testDofContainerCommunication(MeshDistributor &pdb) + // Test dofcomm whether send and recv dofs match + void ParallelDebug::testDofContainerCommunication(MeshDistributor &pdb, Mesh* mesh) { FUNCNAME("ParallelDebug::testDofContainerCommunication()"); @@ -635,24 +659,26 @@ namespace AMDiS { namespace Parallel { typedef map<int, map<const FiniteElemSpace*, DofContainer> >::iterator it_type; MPI::Intracomm &mpiComm = pdb.levelData.getMpiComm(0); + MultiLevelDofComm& dofComm = pdb.dofComms[mesh]; + map<int, int> sendNumber; - for (it_type it = pdb.dofComm[0].getSendDofs().begin(); - it != pdb.dofComm[0].getSendDofs().end(); ++it) + for (it_type it = dofComm[0].getSendDofs().begin(); + it != dofComm[0].getSendDofs().end(); ++it) for (map<const FiniteElemSpace*, DofContainer>::iterator dcIt = it->second.begin(); dcIt != it->second.end(); ++dcIt) sendNumber[it->first] += dcIt->second.size(); map<int, int> recvNumber; - for (it_type it = pdb.dofComm[0].getRecvDofs().begin(); - it != pdb.dofComm[0].getRecvDofs().end(); ++it) + for (it_type it = dofComm[0].getRecvDofs().begin(); + it != dofComm[0].getRecvDofs().end(); ++it) for (map<const FiniteElemSpace*, DofContainer>::iterator dcIt = it->second.begin(); dcIt != it->second.end(); ++dcIt) recvNumber[it->first] += dcIt->second.size(); StdMpi<int> stdMpi(mpiComm); stdMpi.send(sendNumber); - for (it_type it = pdb.dofComm[0].getRecvDofs().begin(); - it != pdb.dofComm[0].getRecvDofs().end(); ++it) + for (it_type it = dofComm[0].getRecvDofs().begin(); + it != dofComm[0].getRecvDofs().end(); ++it) stdMpi.recv(it->first); stdMpi.startCommunication(); @@ -666,12 +692,24 @@ namespace AMDiS { namespace Parallel { foundError = 1; } } + + std::set<DegreeOfFreedom> sendDofs; + for (DofComm::Iterator it(dofComm[0].getSendDofs(), pdb.meshToFeSpaces[mesh][0]); + !it.end(); it.nextRank()) + for (; !it.endDofIter(); it.nextDof()) + sendDofs.insert(it.getDofIndex()); + + for (DofComm::Iterator it2(dofComm[0].getRecvDofs(), pdb.meshToFeSpaces[mesh][0]); + !it2.end(); it2.nextRank()) + for (; !it2.endDofIter(); it2.nextDof()) + TEST_EXIT(!sendDofs.count(it2.getDofIndex())) + ("Send and recv dof contaniners share same dof %d.\n", it2.getDofIndex()); mpi::globalAdd(foundError); TEST_EXIT(foundError == 0)("Error found on at least one rank!\n"); } - + // Test whether one domain has two dofs with same coordinates void ParallelDebug::testDoubleDofs(Mesh *mesh) { FUNCNAME("ParallelDebug::testDoubleDofs()"); @@ -763,7 +801,7 @@ namespace AMDiS { namespace Parallel { dofit != rankDofs.end(); ++dofit) { cout << " " << **dofit << endl; WorldVector<double> coords; - pdb.mesh->getDofIndexCoords(*dofit, pdb.feSpaces[0], coords); + pdb.macroMesh->getDofIndexCoords(*dofit, pdb.feSpaces[0], coords); coords.print(); } @@ -772,7 +810,7 @@ namespace AMDiS { namespace Parallel { dofit != rankAllDofs.end(); ++dofit) { cout << " " << **dofit << endl; WorldVector<double> coords; - pdb.mesh->getDofIndexCoords(*dofit, pdb.feSpaces[0], coords); + pdb.macroMesh->getDofIndexCoords(*dofit, pdb.feSpaces[0], coords); coords.print(); } } @@ -816,14 +854,29 @@ namespace AMDiS { namespace Parallel { it->neighObj.elIndex, it->neighObj.subObj, it->neighObj.ithObj); } } - + + void ParallelDebug::writeDebugFile(MeshToFeSpaces& meshToFeSpaces, + ParallelDofMapping &dofMap, + string debugOutputDir) + { + int i = 0; + MeshToFeSpaces::iterator it = meshToFeSpaces.begin(); + while(it != meshToFeSpaces.end()) { + string prefix = debugOutputDir + "mpi-dbg-mesh" + boost::lexical_cast<string>(i); + writeDebugFile(it->second[it->second.size() - 1], + dofMap, prefix, "dat"); + it++; + i++; + } + + } void ParallelDebug::writeDebugFile(const FiniteElemSpace *feSpace, ParallelDofMapping &dofMap, string prefix, string postfix) { - FUNCNAME("ParallelDebug::writeCoordsFile()"); + FUNCNAME("ParallelDebug::writeDebugFile()"); Mesh *mesh = feSpace->getMesh(); @@ -890,7 +943,7 @@ namespace AMDiS { namespace Parallel { map<int, double> vec; TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(pdb.mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(pdb.macroMesh, -1, Mesh::CALL_LEAF_EL); while (elInfo) { int index = elInfo->getMacroElement()->getIndex(); @@ -898,7 +951,7 @@ namespace AMDiS { namespace Parallel { elInfo = stack.traverseNext(elInfo); } - io::ElementFileWriter::writeFile(vec, pdb.mesh, filename); + io::ElementFileWriter::writeFile(vec, pdb.macroMesh, filename); } @@ -1116,4 +1169,103 @@ namespace AMDiS { namespace Parallel { } } + + void ParallelDebug::writeDofMap(ParallelDofMapping &dofMap, int component, string filename, string postfix) + { + filename += boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()); + filename = filename + "." + postfix; + + ofstream file; + file.open(filename.c_str(), ios::out | ios::trunc); + + DofToMatIndex::MapType& data = dofMap.getMatData(component); + + DofToMatIndex::MapType::iterator it = data.begin(); + + file << &dofMap << "\n"; + file << dofMap[component].nRankDofs << "\n"; + + // +// for (DofComm::Iterator it(dofComm->getRecvDofs(), feSpace); +// !it.end(); it.nextRank()) { +// int rank = it.getRank(); +// // if (meshLevel > 0) +// // rank = levelData->mapRank(rank, 0, meshLevel); +// +// int i = 0; +// for (; !it.endDofIter(); it.nextDof()) +// if (nonRankDofs.count(it.getDofIndex())) +// dofMap[it.getDofIndex()].global = stdMpi.getRecvData(rank)[i++]; +// } + // + + while (it != data.end()) { + if (dofMap.isMatIndexFromGlobal()) + file << it->first << " " << it->second << "\n"; + else + file << it->first << " " << it->second << "\n"; + it++; + } + file.close(); + } + + void ParallelDebug::writePeriodicElObjInfo(MeshDistributor &pdb, string debugOutputDir) + { + string filename = debugOutputDir + "periodic-info.dat"; + ofstream file; + file.open(filename.c_str()); + + ElementObjectDatabase& elObjDb = pdb.getElementObjectDb(); + + file << "periodicVertices:\n"; + for (PerBoundMap<DegreeOfFreedom>::iterator it = elObjDb.periodicVertices.begin(); + it != elObjDb.periodicVertices.end(); it++) { + file << it->first.first << ", " << it->first.second + << " : " << it->second << endl; + } + file << "periodicEdges:\n"; + for (PerBoundMap<DofEdge>::iterator it = elObjDb.periodicEdges.begin(); + it != elObjDb.periodicEdges.end(); it++) { + file << it->first.first.first << " " << it->first.first.second << ", " + << it->first.second.first << " " << it->first.second.second << " : " + << it->second << endl; + } + file << "periodicFaces:\n"; + for (PerBoundMap<DofFace>::iterator it = elObjDb.periodicFaces.begin(); + it != elObjDb.periodicFaces.end(); it++) { + file << it->first.first.get<0>() << it->first.first.get<1>() + << it->first.first.get<2>() << ", " + << it->first.second.get<0>() << it->first.second.get<1>() + << it->first.second.get<2>() << " : " + << it->second << endl; + } + file << "periodicDofAssoc:\n"; + {std::map<DegreeOfFreedom, std::set<BoundaryType> >::iterator it; + for (it = elObjDb.periodicDofAssoc.begin(); + it != elObjDb.periodicDofAssoc.end(); it++) { + file << it->first << endl; + for(std::set<BoundaryType>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + file << *it2 << " "; + file << endl; + }} + file << "periodicEdgeAssoc:\n"; + {std::map<DofEdge, std::set<DofEdge> >::iterator it; + for (it = elObjDb.periodicEdgeAssoc.begin(); + it != elObjDb.periodicEdgeAssoc.end(); it++) { + file << it->first.first << " " << it->first.second << endl; + for(std::set<DofEdge>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + file << "(" << (*it2).first << ", " << (*it2).second << ") "; + file << endl; + }} + file.close(); + } + + void ParallelDebug::writeInterchangeVector(MeshDistributor &pdb, string debugOutputDir) + { + for (size_t i = 0; i < pdb.interchangeVectors.size(); i++) { + string filename = debugOutputDir + "-int" + boost::lexical_cast<string>(i) + ".vtu"; + io::VtkWriter::writeFile(pdb.interchangeVectors[i], filename); + } + } + } } // end namespaces diff --git a/AMDiS/src/parallel/ParallelDebug.h b/AMDiS/src/parallel/ParallelDebug.h index e8e3a83d..fc893904 100644 --- a/AMDiS/src/parallel/ParallelDebug.h +++ b/AMDiS/src/parallel/ParallelDebug.h @@ -76,7 +76,7 @@ namespace AMDiS * \param[in] printCoords If true, the coords of all common dofs are * printed to the screen. */ - static void testCommonDofs(MeshDistributor &pdb, bool printCoords = false); + static void testCommonDofs(MeshDistributor &pdb, Mesh* mesh, bool printCoords = false); /** \brief * This function is used for debugging only. It checks if on all ranks DOFs @@ -86,7 +86,7 @@ namespace AMDiS * * \param[in] pdb Parallel problem definition used for debugging. */ - static void testGlobalIndexByCoords(MeshDistributor &pdb); + static void testGlobalIndexByCoords(MeshDistributor &pdb, Mesh* mesh); /** \brief * Tests if all elements in the macro mesh are memeber of exactly one rank. @@ -101,7 +101,7 @@ namespace AMDiS * * \param[in] pdb Parallel problem definition used for debugging. */ - static void testDofContainerCommunication(MeshDistributor &pdb); + static void testDofContainerCommunication(MeshDistributor &pdb, Mesh* mesh); /// Tests if there are multiple DOFs in mesh with the same coords. static void testDoubleDofs(Mesh *mesh); @@ -161,6 +161,10 @@ namespace AMDiS ParallelDofMapping &dofMap, std::string prefix, std::string postfix); + + static void writeDebugFile(MeshToFeSpaces& meshToFeSpaces, + ParallelDofMapping &dofMap, + std::string debugOutputDir); /** \brief * This functions create a Paraview file with the macro mesh where the @@ -199,6 +203,15 @@ namespace AMDiS ParallelDofMapping &dofMap, std::string prefix, std::string postfix); + + static void writeDofMap(ParallelDofMapping &dofMap, + int component, + std::string filename, + std::string postfix); + + static void writePeriodicElObjInfo(MeshDistributor &pdb, std::string debugOutputDir); + + static void writeInterchangeVector(MeshDistributor &pdb, std::string debugOutputDir); }; } // end namespace Parallel } // end namespace AMDiS diff --git a/AMDiS/src/parallel/ParallelDofMapping.cc b/AMDiS/src/parallel/ParallelDofMapping.cc index 6ae8be43..60ef2d80 100644 --- a/AMDiS/src/parallel/ParallelDofMapping.cc +++ b/AMDiS/src/parallel/ParallelDofMapping.cc @@ -29,8 +29,6 @@ namespace AMDiS { namespace Parallel { void DofToMatIndex::getReverse(int rowIndex, int &component, int &dofIndex) const { - FUNCNAME("DofToMatIndex::getReverse()"); - for (map<int, boost::container::flat_map<DegreeOfFreedom, int> >::const_iterator it0 = data.begin(); it0 != data.end(); ++it0) for (boost::container::flat_map<DegreeOfFreedom, int>::const_iterator it1 = it0->second.begin(); @@ -70,8 +68,6 @@ namespace AMDiS { namespace Parallel { void ComponentDofMap::update() { - FUNCNAME("ComponentDofMap::update()"); - // === Compute local indices for all rank owned DOFs. === for (DofMap::iterator it = dofMap.begin(); it != dofMap.end(); ++it) @@ -95,8 +91,6 @@ namespace AMDiS { namespace Parallel { void ComponentDofMap::computeGlobalMapping() { - FUNCNAME("ComponentDofMap::computeGlobalMapping()"); - for (DofMap::iterator it = dofMap.begin(); it != dofMap.end(); ++it) it->second.global = it->second.local + rStartDofs; } @@ -104,7 +98,7 @@ namespace AMDiS { namespace Parallel { void ComponentDofMap::computeNonLocalIndices() { - FUNCNAME("ComponentDofMap::computeNonLocalIndices()"); + FUNCNAME_DBG("ComponentDofMap::computeNonLocalIndices()"); TEST_EXIT_DBG(dofComm)("No DOF communicator defined!\n"); @@ -116,14 +110,18 @@ namespace AMDiS { namespace Parallel { for (DofComm::Iterator it(dofComm->getSendDofs(), feSpace); !it.end(); it.nextRank()) { int rank = it.getRank(); + // if (meshLevel > 0) // rank = levelData->mapRank(rank, 0, meshLevel); - for (; !it.endDofIter(); it.nextDof()) + for (; !it.endDofIter(); it.nextDof()) { + TEST_EXIT_DBG(dofMap.count(it.getDofIndex())) + ("DOF index not in the dofmap. Something is wrong.\n"); if (dofMap.count(it.getDofIndex()) && !nonRankDofs.count(it.getDofIndex())) stdMpi.getSendData(rank). push_back(dofMap[it.getDofIndex()].global); + } } stdMpi.updateSendDataSize(); @@ -165,19 +163,24 @@ namespace AMDiS { namespace Parallel { // rank = levelData->mapRank(rank, 0, meshLevel); int i = 0; - for (; !it.endDofIter(); it.nextDof()) + for (; !it.endDofIter(); it.nextDof()) { + TEST_EXIT_DBG(nonRankDofs.count(it.getDofIndex()))("Something is wrong.\n"); + if (nonRankDofs.count(it.getDofIndex())) dofMap[it.getDofIndex()].global = stdMpi.getRecvData(rank)[i++]; + } } + } void FeSpaceData::init(vector<const FiniteElemSpace*> &f0, vector<const FiniteElemSpace*> &f1, bool globalMapping) - { + { componentSpaces = f0; feSpaces = f1; + for (vector<const FiniteElemSpace*>::iterator it = feSpaces.begin(); it != feSpaces.end(); ++it) { if (componentData.count(*it)) @@ -185,7 +188,8 @@ namespace AMDiS { namespace Parallel { else componentData.insert(make_pair(*it, ComponentDofMap())); - componentData[*it].setFeSpace(*it); + componentData[*it].setFeSpace(*it); + componentData[*it].setMesh((*it)->getMesh()); componentData[*it].setGlobalMapping(globalMapping); } } @@ -205,6 +209,7 @@ namespace AMDiS { namespace Parallel { componentData.insert(make_pair(component, ComponentDofMap())); componentData[component].setFeSpace(componentSpaces[component]); + componentData[component].setMesh(componentSpaces[component]->getMesh()); componentData[component].setGlobalMapping(globalMapping); } } @@ -212,8 +217,7 @@ namespace AMDiS { namespace Parallel { ParallelDofMapping::ParallelDofMapping(DofMappingMode mode, bool matIndexFromGlobal) - : dofComm(NULL), - globalMapping(true), + : globalMapping(true), needMatIndexFromGlobal(matIndexFromGlobal), nRankDofs(1), nLocalDofs(1), @@ -236,12 +240,10 @@ namespace AMDiS { namespace Parallel { rStartDofs = -1; } - void ParallelDofMapping::init(vector<const FiniteElemSpace*> &fe, vector<const FiniteElemSpace*> &uniqueFe, bool b) { - FUNCNAME("ParallelDofMapping::init()"); globalMapping = b; componentSpaces = fe; @@ -249,20 +251,27 @@ namespace AMDiS { namespace Parallel { data->init(fe, uniqueFe, globalMapping); } - - - void ParallelDofMapping::clear() + + void ParallelDofMapping::clear(Mesh* mesh) { - FUNCNAME("ParallelDofMapping::clear()"); - for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) - it->clear(); + for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) + if (!mesh || it->getMesh() == mesh) + it->clear(); nRankDofs = -1; nLocalDofs = -1; nOverallDofs = -1; rStartDofs = -1; - dofToMatIndex.clear(); + + if (!mesh) + dofToMatIndex.clear(); + else + for (unsigned int component = 0; component < componentSpaces.size(); + component++) { + if (mesh == (*data)[component].getMesh()) + dofToMatIndex.clear(component); + } } @@ -273,24 +282,24 @@ namespace AMDiS { namespace Parallel { for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) it->setMpiComm(m); } - - - void ParallelDofMapping::setDofComm(DofComm &dc) + + + void ParallelDofMapping::setDofComms(std::map<Mesh*, MultiLevelDofComm>& dofComms, int level) { - FUNCNAME("ParallelDofMapping::setDofComm()"); - - dofComm = &dc; - - // Add the DOF communicator also to all FE space DOF mappings. - for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) - it->setDofComm(dc); + FUNCNAME("ParallelDofMapping::setDofComms()"); + + for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) { + + TEST_EXIT(dofComms.find(const_cast<Mesh*>(it->getMesh())) != dofComms.end()) + ("DofComm and ParallelDofMapping not match.\n"); + + it->setDofComm(dofComms[const_cast<Mesh*>(it->getMesh())][level]); + } } int ParallelDofMapping::computeRankDofs() { - FUNCNAME("ParallelDofMapping::computeRankDofs()"); - int result = 0; for (ComponentIterator &it = data->getIteratorComponent(); !it.end(); it.next()) result += it->nRankDofs; @@ -301,8 +310,6 @@ namespace AMDiS { namespace Parallel { int ParallelDofMapping::computeLocalDofs() { - FUNCNAME("ParallelDofMapping::computeLocalDofs()"); - int result = 0; for (ComponentIterator &it = data->getIteratorComponent(); !it.end(); it.next()) result += it->nLocalDofs; @@ -313,8 +320,6 @@ namespace AMDiS { namespace Parallel { int ParallelDofMapping::computeOverallDofs() { - FUNCNAME("ParallelDofMapping::computeOverallDofs()"); - int result = 0; for (ComponentIterator &it = data->getIteratorComponent(); !it.end(); it.next()) result += it->nOverallDofs; @@ -325,46 +330,38 @@ namespace AMDiS { namespace Parallel { int ParallelDofMapping::computeStartDofs() { - FUNCNAME("ParallelDofMapping::computeStartDofs()"); - int result = 0; for (ComponentIterator &it = data->getIteratorComponent(); !it.end(); it.next()) result += it->rStartDofs; return result; } - - - void ParallelDofMapping::update() + + void ParallelDofMapping::update(Mesh* mesh) { - FUNCNAME("ParallelDofMapping::update()"); - // First, update all FE space DOF mappings. for (ComponentIterator &it = data->getIteratorData(); !it.end(); it.next()) - it->update(); - + if (!mesh || it->getMesh() == mesh) + it->update(); + // Compute all numbers from this mappings. nRankDofs = computeRankDofs(); nLocalDofs = computeLocalDofs(); nOverallDofs = computeOverallDofs(); rStartDofs = computeStartDofs(); - // And finally, compute the matrix indices. computeMatIndex(needMatIndexFromGlobal); } - void ParallelDofMapping::updateMatIndex() { - FUNCNAME("ParallelDofMapping::updateMatIndex()"); - computeMatIndex(needMatIndexFromGlobal); } void ParallelDofMapping::computeMatIndex(bool globalIndex) { - FUNCNAME("ParallelDofMapping::computeMatIndex()"); + FUNCNAME_DBG("ParallelDofMapping::computeMatIndex()"); dofToMatIndex.clear(); @@ -377,7 +374,7 @@ namespace AMDiS { namespace Parallel { for (unsigned int component = 0; component < componentSpaces.size(); component++) { - + // Traverse all DOFs of the FE space and create for all rank owned DOFs // a matrix index. DofMap& dofMap = (*data)[component].getMap(); @@ -390,7 +387,6 @@ namespace AMDiS { namespace Parallel { dofToMatIndex.add(component, it->first, globalMatIndex); } } - // Increase the offset for the next FE space by the number of DOFs owned // by the rank in the current FE space. offset += (*data)[component].nRankDofs; @@ -399,8 +395,10 @@ namespace AMDiS { namespace Parallel { if (!globalMapping) continue; + + DofComm* dofComm = &((*data)[component].getDofComm()); TEST_EXIT_DBG(dofComm != NULL)("No communicator given!\n"); - + // === Communicate the matrix indices for all DOFs that are on some === // === interior boundaries. === @@ -410,6 +408,9 @@ namespace AMDiS { namespace Parallel { vector<DegreeOfFreedom> sendGlobalDofs; for (; !it.endDofIter(); it.nextDof()) { + TEST_EXIT_DBG((*data)[component].isRankDof(it.getDofIndex())) + ("Send dof %d is not a rank dof\n", it.getDofIndex()); + if (dofMap.count(it.getDofIndex())) { if (globalIndex) sendGlobalDofs.push_back(dofToMatIndex.get(component, @@ -453,7 +454,6 @@ namespace AMDiS { namespace Parallel { } } - // === Communicate DOFs on periodic boundaries. === stdMpi.clear(); @@ -490,7 +490,7 @@ namespace AMDiS { namespace Parallel { // if (meshLevel > 0) // rank = levelData->mapRank(rank, 0, meshLevel); - int counter = 0; + size_t counter = 0; for (; !it.endDofIter(); it.nextDof()) { if (dofMap.count(it.getDofIndex())) { @@ -519,7 +519,7 @@ namespace AMDiS { namespace Parallel { int firstComponent, int nComponents) { - FUNCNAME("ParallelDofMapping::createIndexSet()"); + FUNCNAME_DBG("ParallelDofMapping::createIndexSet()"); int firstRankDof = -1; ComponentDofMap &compMap = (*data)[firstComponent]; diff --git a/AMDiS/src/parallel/ParallelDofMapping.h b/AMDiS/src/parallel/ParallelDofMapping.h index 443b3eb1..398f9930 100644 --- a/AMDiS/src/parallel/ParallelDofMapping.h +++ b/AMDiS/src/parallel/ParallelDofMapping.h @@ -62,6 +62,11 @@ namespace AMDiS { namespace Parallel { { data.clear(); } + + inline void clear(int component) + { + data[component].clear(); + } /** Add a new mapping for a given DOF. * @@ -228,6 +233,25 @@ namespace AMDiS { namespace Parallel { { return dofMap; } + + const FiniteElemSpace* getFeSpace() const + { + return feSpace; + } + + const Mesh* getMesh() const + { + return mesh; + } + + DofComm& getDofComm() + { + FUNCNAME("ComponentDofMap::getDofComm()"); + + TEST_EXIT_DBG(dofComm)("No DOF communicator object defined!\n"); + + return *dofComm; + } DofMap::iterator begin() { @@ -247,6 +271,11 @@ namespace AMDiS { namespace Parallel { { feSpace = fe; } + + void setMesh(Mesh* mesh_) + { + mesh = mesh_; + } /// Informs the mapping whether a global index must be computed. void setGlobalMapping(bool b) @@ -282,6 +311,8 @@ namespace AMDiS { namespace Parallel { /// The FE space this mapping belongs to. This is used only the get the /// correct DOF communicator in \ref dofComm. const FiniteElemSpace *feSpace; + + const Mesh* mesh; /// Mapping data from DOF indices to local and global indices. DofMap dofMap; @@ -320,6 +351,7 @@ namespace AMDiS { namespace Parallel { class ComponentDataInterface { public: + virtual ~ComponentDataInterface() {}; /// Access via component number virtual ComponentDofMap& operator[](int compNumber) = 0; @@ -653,6 +685,13 @@ namespace AMDiS { namespace Parallel { */ ParallelDofMapping(DofMappingMode mode, bool matIndexFromGlobal = false); + + ~ParallelDofMapping() + { + if (data) + delete data; + data = NULL; + } /** \brief * Initialize the parallel DOF mapping. @@ -686,20 +725,17 @@ namespace AMDiS { namespace Parallel { } /// Clear all data. - void clear(); + void clear(Mesh* mesh = NULL); /// Set the DOF communicator objects that are required to exchange information /// about DOFs that are on interior boundaries. - void setDofComm(DofComm &dofComm); + + void setDofComms(std::map<Mesh*, MultiLevelDofComm>& dofComms, int level); /// Returns the DOF communicator. - DofComm& getDofComm() + DofComm& getDofComm(const FiniteElemSpace* feSpace) { - FUNCNAME("ParallelDofMapping::getDofComm()"); - - TEST_EXIT_DBG(dofComm)("No DOF communicator object defined!\n"); - - return *dofComm; + return (*data)[feSpace].getDofComm(); } inline bool isMatIndexFromGlobal() @@ -739,6 +775,14 @@ namespace AMDiS { namespace Parallel { return nRankDofs; } + + inline int getRankDofs(int component) const + { + int nDofs = (*data)[component].nRankDofs; + TEST_EXIT_DBG(nDofs >= 0)("Should not happen!\n"); + + return nDofs; + } /// Returns \ref nLocalDofs, thus the number of DOFs in ranks subdomain. inline int getLocalDofs() const @@ -747,7 +791,15 @@ namespace AMDiS { namespace Parallel { return nLocalDofs; } + + inline int getLocalDofs(int component) const + { + int nDofs = (*data)[component].nLocalDofs; + TEST_EXIT_DBG(nDofs >= 0)("Should not happen!\n"); + return nDofs; + } + /// Returns \ref nOverallDofs, thus the number of all DOFs in this mapping. inline int getOverallDofs() const { @@ -755,6 +807,14 @@ namespace AMDiS { namespace Parallel { return nOverallDofs; } + + inline int getOverallDofs(int component) const + { + int nDofs = (*data)[component].nOverallDofs; + TEST_EXIT_DBG(nDofs >= 0)("Should not happen!\n"); + + return nDofs; + } /// Returns \ref rStartDofs, thus the smallest global index of a DOF that is /// owned by the rank. @@ -764,13 +824,26 @@ namespace AMDiS { namespace Parallel { return rStartDofs; } + + inline int getStartDofs(int component) const + { + int nDofs = (*data)[component].rStartDofs; + TEST_EXIT_DBG(nDofs >= 0)("Should not happen!\n"); + + return nDofs; + } /// Update the mapping. - void update(); + void update(Mesh* mesh = NULL); /// Updates only the DOF to matrix index mapping void updateMatIndex(); + inline DofToMatIndex::MapType& getMatData(int component) + { + return dofToMatIndex.getData(component); + } + /// Returns the global matrix index of a given DOF for a given /// component number. inline int getMatIndex(int ithComponent, DegreeOfFreedom d) const @@ -793,9 +866,22 @@ namespace AMDiS { namespace Parallel { } /// Returns the set of unique FE spaces. - inline std::vector<const FiniteElemSpace*>& getFeSpaces() + std::vector<const FiniteElemSpace*> getFeSpaces(Mesh* mesh = NULL) { - return feSpaces; + if (!mesh) + return feSpaces; + + std::vector<const FiniteElemSpace*> thisMeshSpaces; + for (size_t i = 0; i < feSpaces.size(); i++) + if (feSpaces[i]->getMesh() == mesh) + thisMeshSpaces.push_back(feSpaces[i]); + return thisMeshSpaces; + } + + bool hasFeSpace(const FiniteElemSpace* feSpace) + { + return (std::find(feSpaces.begin(), feSpaces.end(), feSpace) + != feSpaces.end()); } // Writes all data of this object to an output stream. @@ -839,9 +925,6 @@ namespace AMDiS { namespace Parallel { private: MPI::Intracomm mpiComm; - /// DOF communicator for all DOFs on interior boundaries. - DofComm *dofComm; - /// Is true if there are DOFs in at least one subdomain that are not owned /// by the rank. If the value is false, each rank contains only DOFs that /// are also owned by this rank. diff --git a/AMDiS/src/parallel/ParallelProblemStat.cc b/AMDiS/src/parallel/ParallelProblemStat.cc index 5353dc28..f6236949 100644 --- a/AMDiS/src/parallel/ParallelProblemStat.cc +++ b/AMDiS/src/parallel/ParallelProblemStat.cc @@ -66,6 +66,7 @@ namespace AMDiS { namespace Parallel { Flag adoptFlag) { FUNCNAME("ParallelProblemStat::initialize()"); + MSG("ParallelProblemStat::initialize()\n"); MSG("Initialization phase 0 needed %.5f seconds\n", MPI::Wtime() - initTimeStamp); @@ -81,7 +82,17 @@ namespace AMDiS { namespace Parallel { ("ParallelProblem loaded, but no ParallelSolver selected! This does not fit together.\n"); parallelSolver->setMeshDistributor(meshDistributor, 0); - parallelSolver->init(getComponentSpaces(), getFeSpaces()); + + // For the additional component with extra mesh and fespace, we don't need to put them + // into the parallel system. + std::vector<const FiniteElemSpace*> tmpFeSpaces, tmpComponentSpaces(getComponentSpaces().begin(), + getComponentSpaces().begin() + getNumComponents()); + + for (int i = 0; i < tmpComponentSpaces.size(); i++) + if (std::find(tmpFeSpaces.begin(), tmpFeSpaces.end(), tmpComponentSpaces[i]) == tmpFeSpaces.end()) + tmpFeSpaces.push_back(tmpComponentSpaces[i]); + + parallelSolver->init(tmpComponentSpaces, tmpFeSpaces); } diff --git a/AMDiS/src/parallel/ParallelSolver.cc b/AMDiS/src/parallel/ParallelSolver.cc index 11b318d9..887f52c7 100644 --- a/AMDiS/src/parallel/ParallelSolver.cc +++ b/AMDiS/src/parallel/ParallelSolver.cc @@ -41,7 +41,6 @@ namespace AMDiS { namespace Parallel { meshDistributor->removeDofMap(dofMap); } - void ParallelSolver::init(std::vector<const FiniteElemSpace*> &fe0, std::vector<const FiniteElemSpace*> &fe1, bool createGlobalMapping) @@ -61,7 +60,10 @@ namespace AMDiS { namespace Parallel { dofMap.init(componentSpaces, feSpaces); dofMap.setMpiComm(levelData.getMpiComm(meshLevel)); - dofMap.setDofComm(meshDistributor->getDofComm(meshLevel)); + + // The meshes and fespaces of the dofmap come from the main problem. + // The meshes and feSpaces of dofcomms may come from diff problems. + dofMap.setDofComms(meshDistributor->getDofComms(), meshLevel); dofMap.clear(); meshDistributor->registerDofMap(dofMap); } diff --git a/AMDiS/src/parallel/ParallelTypes.h b/AMDiS/src/parallel/ParallelTypes.h index eafd48e8..82395d46 100644 --- a/AMDiS/src/parallel/ParallelTypes.h +++ b/AMDiS/src/parallel/ParallelTypes.h @@ -78,6 +78,10 @@ namespace AMDiS { namespace Parallel { typedef std::vector<MeshStructure> MeshCodeVec; typedef std::map<int, std::vector<AtomicBoundary> > RankToBoundMap; + + typedef boost::container::flat_map<int, boost::container::flat_map<Mesh*, Element*> > MacroElIndexMap; + + typedef std::map<Mesh*, std::vector<const FiniteElemSpace*> > MeshToFeSpaces; } } // end namespaces #endif diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index a77a9221..e3b52fbe 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -135,7 +135,7 @@ namespace AMDiS { namespace Parallel { levelData.getMpiComm(meshLevel + 1) != MPI::COMM_SELF) { dofMapSubDomain.init(componentSpaces, feSpaces); dofMapSubDomain.setMpiComm(levelData.getMpiComm(meshLevel + 1)); - dofMapSubDomain.setDofComm(meshDistributor->getDofComm(meshLevel + 1)); + dofMapSubDomain.setDofComms(meshDistributor->getDofComms(), meshLevel + 1); dofMapSubDomain.clear(); meshDistributor->registerDofMap(dofMapSubDomain); } @@ -228,8 +228,8 @@ namespace AMDiS { namespace Parallel { if (fetiPreconditioner == FETI_DIRICHLET) interiorDofMap.clear(); - primalDofMap.setDofComm(meshDistributor->getDofComm(meshLevel)); - lagrangeMap.setDofComm(meshDistributor->getDofComm(meshLevel)); + primalDofMap.setDofComms(meshDistributor->getDofComms(), meshLevel); + lagrangeMap.setDofComms(meshDistributor->getDofComms(), meshLevel); primalDofMap.setMpiComm(levelData.getMpiComm(meshLevel)); dualDofMap.setMpiComm(levelData.getMpiComm(meshLevel)); @@ -238,11 +238,11 @@ namespace AMDiS { namespace Parallel { if (fetiPreconditioner == FETI_DIRICHLET) interiorDofMap.setMpiComm(levelData.getMpiComm(meshLevel + 1)); - localDofMap.setDofComm(meshDistributor->getDofComm(meshLevel + 1)); + localDofMap.setDofComms(meshDistributor->getDofComms(), meshLevel + 1); if (stokesMode) { interfaceDofMap.clear(); - interfaceDofMap.setDofComm(meshDistributor->getDofComm(meshLevel)); + interfaceDofMap.setDofComms(meshDistributor->getDofComms(), meshLevel); interfaceDofMap.setMpiComm(levelData.getMpiComm(0)); } @@ -1537,7 +1537,7 @@ namespace AMDiS { namespace Parallel { massMapping = new ParallelDofMapping(COMPONENT_WISE, true); massMapping->init(pressureFeSpace, pressureFeSpace); - massMapping->setDofComm(meshDistributor->getDofComm(meshLevel)); + massMapping->setDofComms(meshDistributor->getDofComms(), meshLevel); massMapping->setMpiComm(meshDistributor->getMeshLevelData().getMpiComm(0)); } (*massMapping)[0] = interfaceDofMap[pressureComponent]; diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc index dbb2bfa5..7c29a966 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc @@ -186,7 +186,7 @@ namespace AMDiS { namespace Parallel { FUNCNAME_DBG("PetscSolverGlobalMatrix::fillPetscMatrixWithCoarseSpace()"); TEST_EXIT_DBG(interiorMap)("No interiorMap! Should not happen!\n"); - TEST_EXIT_DBG(coarseSpaceMap.size() == seqMat->getSize()) + TEST_EXIT_DBG(coarseSpaceMap.size() == (size_t)seqMat->getSize()) ("Wrong sizes %d %d\n", coarseSpaceMap.size(), seqMat->getSize()); // === Prepare traverse of sequentially created matrices. === @@ -875,8 +875,7 @@ namespace AMDiS { namespace Parallel { // Get PETSc's mat index of the row DOF. int index = 0; if (interiorMap->isMatIndexFromGlobal()) - index = - interiorMap->getMatIndex(rowComp, globalRowDof) + rStartInterior; + index = interiorMap->getMatIndex(rowComp, globalRowDof) + rStartInterior; else index = interiorMap->getMatIndex(rowComp, dof) + rStartInterior; diff --git a/AMDiS/src/parallel/PetscSolverSchur.cc b/AMDiS/src/parallel/PetscSolverSchur.cc index 0713cc8f..9092ff50 100644 --- a/AMDiS/src/parallel/PetscSolverSchur.cc +++ b/AMDiS/src/parallel/PetscSolverSchur.cc @@ -35,6 +35,7 @@ namespace AMDiS { namespace Parallel { TEST_EXIT_DBG(interiorMap)("No parallel DOF map defined!\n"); const FiniteElemSpace *feSpace = componentSpaces[0]; + Mesh* mesh = feSpace->getMesh(); // typedef map<int, DofContainer> RankToDofContainer; #if 0 typedef map<DegreeOfFreedom, bool> DofIndexToBool; @@ -42,7 +43,7 @@ namespace AMDiS { namespace Parallel { boundaryDofs.clear(); std::set<DegreeOfFreedom> boundaryLocalDofs; - for (DofComm::Iterator it(meshDistributor->getDofComm(0).getSendDofs(), feSpace); + for (DofComm::Iterator it(meshDistributor->getDofComm(mesh, 0).getSendDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) { boundaryLocalDofs.insert(it.getDofIndex()); @@ -104,7 +105,7 @@ namespace AMDiS { namespace Parallel { std::set<DegreeOfFreedom> otherBoundaryLocalDofs; - for (DofComm::Iterator it(meshDistributor->getDofComm(0).getRecvDofs(), feSpace); + for (DofComm::Iterator it(meshDistributor->getDofComm(mesh, 0).getRecvDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) otherBoundaryLocalDofs.insert(it.getDofIndex()); @@ -140,7 +141,7 @@ namespace AMDiS { namespace Parallel { StdMpi<vector<DegreeOfFreedom> > stdMpi(domainComm); - for (DofComm::Iterator it(meshDistributor->getDofComm(0).getSendDofs(), feSpace); + for (DofComm::Iterator it(meshDistributor->getDofComm(mesh, 0).getSendDofs(), feSpace); !it.end(); it.nextRank()) { stdMpi.getSendData(it.getRank()).resize(0); stdMpi.getSendData(it.getRank()).reserve(it.getDofs().size()); @@ -157,13 +158,13 @@ namespace AMDiS { namespace Parallel { stdMpi.updateSendDataSize(); - for (DofComm::Iterator it(meshDistributor->getDofComm(0).getRecvDofs(), feSpace); + for (DofComm::Iterator it(meshDistributor->getDofComm(mesh, 0).getRecvDofs(), feSpace); !it.end(); it.nextRank()) stdMpi.recv(it.getRank()); stdMpi.startCommunication(); - for (DofComm::Iterator it(meshDistributor->getDofComm(0).getRecvDofs(), feSpace); + for (DofComm::Iterator it(meshDistributor->getDofComm(mesh, 0).getRecvDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) { int globalRecvDof = (*interiorMap)[feSpace][it.getDofIndex()].global; diff --git a/AMDiS/src/utility/to_string.hpp b/AMDiS/src/utility/to_string.hpp new file mode 100644 index 00000000..a60baf20 --- /dev/null +++ b/AMDiS/src/utility/to_string.hpp @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: + * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * This file is part of AMDiS + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + + + +/** \file to_string.hpp */ + +#ifndef AMDIS_UTILITY_TO_STRING_HPP +#define AMDIS_UTILITY_TO_STRING_HPP + +#include <string> +#include <boost/lexical_cast.hpp> + +namespace AMDiS { + + template <class T> + inline std::string to_string(const T& value) + { + return boost::lexical_cast<std::string>(value); + } + +} // end namspace AMDiS + +#endif // AMDIS_UTILITY_TO_STRING_HPP diff --git a/extensions/ProblemStatMassConserve.h b/extensions/ProblemStatMassConserve.h index 37a20de5..24def0d5 100644 --- a/extensions/ProblemStatMassConserve.h +++ b/extensions/ProblemStatMassConserve.h @@ -42,9 +42,9 @@ struct ProblemStatMassConserve : public ExtendedProblemStat, public StandardRefi prob2(NULL), comp(0) { -#ifdef HAVE_PARALLEL_DOMAIN_AMDIS - TEST_EXIT(false)("Multi-Mesh approach does not work in parallel mode for the moment. Need to be implemented!\n"); -#endif +// #ifdef HAVE_PARALLEL_DOMAIN_AMDIS +// TEST_EXIT(false)("Multi-Mesh approach does not work in parallel mode for the moment. Need to be implemented!\n"); +// #endif Parameters::get(name_ + "->mass conservation component", comp); @@ -213,9 +213,10 @@ struct ProblemStatMassConserve : public ExtendedProblemStat, public StandardRefi bool storeMatrixData = false) { SolverMatrix<Matrix<DOFMatrix*> > solverMatrix_; - Matrix<DOFMatrix*> mat(1,1); - mat[0][0] = prob2->getSystemMatrix(0,0); - solverMatrix_.setMatrix(mat); +// Matrix<DOFMatrix*> mat(1,1); +// mat[0][0] = prob2->getSystemMatrix(0,0); +// solverMatrix_.setMatrix(mat); + solverMatrix_.setMatrix(*(prob2->getSystemMatrix())); std::vector<const FiniteElemSpace*> feSpaces0; feSpaces0.push_back(prob2->getFeSpace(0)); diff --git a/extensions/ProblemStatMassConserve_mm.h b/extensions/ProblemStatMassConserve_mm.h new file mode 100644 index 00000000..c1792b1c --- /dev/null +++ b/extensions/ProblemStatMassConserve_mm.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * Mass-conserving ProblemStat for AMDiS + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis/trunk/extensions + * + * Author: Simon Praetorius + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + +/** \file ProblemStatMassConserve_mm.h */ + + +#ifndef AMDIS_EXTENSIONS_PROBLEM_STAT_MASS_CONSERVE_MULTI_MESH +#define AMDIS_EXTENSIONS_PROBLEM_STAT_MASS_CONSERVE_MULTI_MESH + +#include "ExtendedProblemStat.h" +#include "Refinement.h" +#include <boost/lexical_cast.hpp> + +namespace AMDiS { + +/// Implementation of ProblemStat to allow for the conservation of mass of one +/// solution component, i.e. project the old-solution to the new mesh so that +/// the scalar-product is conserved: \f$ (u^*, v) = (u^\text{old}, v) \f$, where \f$ u^*,v \f$ live on the +/// new mesh and \f$ u^\text{old} \f$ lives on the old mesh. +struct ProblemStatMassConserve : public ExtendedProblemStat, public StandardRefineOperation +{ + ProblemStatMassConserve(std::string name_) + : ExtendedProblemStat(name_), + initialMeshAdoption(false), + comp(-1), + old_solution(NULL) + { + Parameters::get(name_ + "->mass conservation component", comp); + assert( comp >= 0 ); + + Parameters::get(name_ + "->additional components", nAddComponents); + nAddComponents++; + Parameters::set(name_ + "->additional components", nAddComponents); + + comp_old = nComponents - 1 + nAddComponents; + + int degree = 1; + Parameters::get(name_ + "->polynomial degree[" + boost::lexical_cast<std::string>(comp) + "]", degree); + Parameters::set(name_ + "->polynomial degree[" + boost::lexical_cast<std::string>(comp_old) + "]", degree); + + int refSet = 123; + Parameters::set(name_ + "->refinement set[" + boost::lexical_cast<std::string>(comp_old) + "]", refSet); + } + + ~ProblemStatMassConserve() + { + if (old_solution) { + delete old_solution; old_solution = NULL; + } + } + + virtual void initialize(Flag initFlag, + ProblemStatSeq *adoptProblem = NULL, + Flag adoptFlag = INIT_NOTHING) override + { + ExtendedProblemStat::initialize(initFlag, adoptProblem, adoptFlag); + old_solution = new DOFVector<double>(getFeSpace(comp_old), "old-solution"); + } + + void buildAfterCoarsen(AdaptInfo *adaptInfo, Flag flag, + bool assembleMatrix = true, + bool assembleVector = true) override + { FUNCNAME("ProblemStatMassConserve_mm::buildAfterCoarsen()"); + + if (!initialMeshAdoption) { + fitMeshes(comp, comp_old); + old_solution->interpol(getSolution(comp)); + initialMeshAdoption = true; + } + ExtendedProblemStat::buildAfterCoarsen(adaptInfo, flag, assembleMatrix, assembleVector); + } + + /// copy solution to old_solution after regular solve + void solve(AdaptInfo *adaptInfo, + bool createMatrixData = true, + bool storeMatrixData = false) override + { FUNCNAME("ProblemStatMassConserve_mm::solve()"); + + ExtendedProblemStat::solve(adaptInfo, createMatrixData, storeMatrixData); + + fitMeshes(comp, comp_old); + old_solution->interpol(getSolution(comp)); + } + + DOFVector<double>* getOldSolution(int comp0 = 0) { assert( comp0 == comp ); return old_solution; } + +protected: + void fitMeshes(int comp1, int comp2) + { + MeshStructure meshStructure2; + meshStructure2.init(getMesh(comp1)); + getCoarseningManager()->globalCoarsen(getMesh(comp2), -2); + meshStructure2.fitMeshToStructure(getMesh(comp2), getRefinementManager()); + } + +private: + /// true if initial-solution/-mesh is copied to temporary problem + bool initialMeshAdoption; + + /// component the should be copnserved + int comp; + int comp_old; + + DOFVector<double>* old_solution; +}; + +} + +#endif // PROBLEM_STAT_MASS_CONSERVE \ No newline at end of file diff --git a/extensions/Refinement.h b/extensions/Refinement.h index 9765182b..9069e5b4 100644 --- a/extensions/Refinement.h +++ b/extensions/Refinement.h @@ -70,7 +70,7 @@ public: virtual ~RefinementLevel() { - finalize(); +// finalize(); delete coarseningManager; delete refinementManager; @@ -98,7 +98,7 @@ public: refineOperation = refineOperation_; } - void refine(bool onlyRefine= false) + void refine(bool onlyRefine= false, bool meshRepartation = false) { FUNCNAME("RefinementLevel::refine()"); @@ -122,6 +122,11 @@ public: calcMeshSizes(minH, maxH, minLevel, maxLevel, false); int nr = mesh->getNumberOfVertices(); meshChanged = meshChanged && oldOldNr!=nr && oldNr!=nr; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + int sendValue = static_cast<int>(meshChanged); + Parallel::mpi::globalAdd(MPI::COMM_WORLD, sendValue); + meshChanged = static_cast<bool>(sendValue); +#endif if (meshChanged) { MSG("(local) mesh sizes: [%f, %f], Vs: %d, ELs: %d\n", minH, maxH, nr, mesh->getNumberOfElements()); @@ -131,14 +136,17 @@ public: oldOldNr = oldNr; oldNr = nr; } +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(meshRepartation); +#endif calcMeshSizes(minH, maxH, minLevel, maxLevel, true); MSG("Final (global) mesh: [%f, %f], Vs: %d, ELs: %d, Level: [%d, %d]\n", minH, maxH, mesh->getNumberOfVertices(), mesh->getNumberOfElements(), minLevel, maxLevel); } - void refine(int numRefinements_, bool onlyRefine= false) { + void refine(int numRefinements_, bool onlyRefine= false, bool repartation = false) { numRefinements = numRefinements_; - refine(onlyRefine); + refine(onlyRefine, repartation); numRefinements = numRefinements0; } @@ -318,7 +326,7 @@ public: virtual ~RefinementLocal() { - finalize(); +// finalize(); delete coarseningManager; delete refinementManager; @@ -377,6 +385,11 @@ public: calcMeshSizes(minH, maxH, minLevel, maxLevel, false); int nr = mesh->getNumberOfVertices(); meshChanged = meshChanged && oldOldNr!=nr && oldNr!=nr; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + int sendValue = static_cast<int>(meshChanged); + Parallel::mpi::globalAdd(MPI::COMM_WORLD, sendValue); + meshChanged = static_cast<bool>(sendValue); +#endif if (meshChanged) { MSG("(local) mesh sizes: [%f, %f], Vs: %d, ELs: %d\n", minH, maxH, nr, mesh->getNumberOfElements()); @@ -386,6 +399,9 @@ public: oldOldNr = oldNr; oldNr = nr; } +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(); +#endif calcMeshSizes(minH, maxH, minLevel, maxLevel, true); MSG("Final (global) mesh: [%f, %f], Vs: %d, ELs: %d, Level: [%d, %d]\n", minH, maxH, mesh->getNumberOfVertices(), mesh->getNumberOfElements(), minLevel, maxLevel); diff --git a/extensions/Refinement_Level.h b/extensions/Refinement_Level.h index 7dabe69e..5753d5ad 100644 --- a/extensions/Refinement_Level.h +++ b/extensions/Refinement_Level.h @@ -20,6 +20,7 @@ #define EXTENSIONS_REFINEMENT_LEVEL_PHASEFIELD_H #include "ElementFunction.h" +#include "Refinement.h" namespace AMDiS { namespace extensions { diff --git a/extensions/base_problems/CouplingBaseProblem.h b/extensions/base_problems/CouplingBaseProblem.h index 653fe3e9..d12de90a 100644 --- a/extensions/base_problems/CouplingBaseProblem.h +++ b/extensions/base_problems/CouplingBaseProblem.h @@ -42,23 +42,12 @@ public: if (prob3_) baseProblems.push_back(prob3_); if (prob4_) baseProblems.push_back(prob4_); } - - CouplingBaseProblem(std::string name_, - std::vector<BaseProblemType*> probs_) - : CProblemStat(name_), name(name_) - { - dow = Global::getGeo(WORLD); - TEST_EXIT(probs_.size()>1)("You should have at least one base problem!\n"); - for ( int i = 0 ; i < probs_.size() ; ++i ) - if ( probs_[i] ) - baseProblems.push_back( probs_[i] ); - } ~CouplingBaseProblem() { } - virtual void initialize(Flag initFlag, - ProblemStatSeq *adoptProblem = NULL, - Flag adoptFlag = INIT_NOTHING) override + void initialize(Flag initFlag, + ProblemStatSeq *adoptProblem = NULL, + Flag adoptFlag = INIT_NOTHING) override { for (size_t i = 0; i < baseProblems.size(); i++) { for (size_t j = 0; j < baseProblems[i]->getNumProblems(); j++) diff --git a/extensions/base_problems/CouplingBaseProblem2.h b/extensions/base_problems/CouplingBaseProblem2.h index df2c140a..55b27b01 100644 --- a/extensions/base_problems/CouplingBaseProblem2.h +++ b/extensions/base_problems/CouplingBaseProblem2.h @@ -23,7 +23,9 @@ #include "GenericLoops.h" +#ifndef MAX_NUM_COUPLED_PROBLEMS #define MAX_NUM_COUPLED_PROBLEMS 10 +#endif namespace AMDiS { namespace base_problems { @@ -100,8 +102,8 @@ namespace detail { template<class ProblemType=ProblemStat, BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(MAX_NUM_COUPLED_PROBLEMS, class BaseProblemType, void) > class CouplingBaseProblem : public CouplingIterationInterface, - public CouplingTimeInterface, - public AMDiS::detail::CouplingProblemStat<ProblemType> + public CouplingTimeInterface, + public AMDiS::detail::CouplingProblemStat<ProblemType> { public: typedef AMDiS::detail::CouplingProblemStat<ProblemType> CProblemStat; @@ -128,7 +130,9 @@ public: template<BOOST_PP_ENUM(BOOST_PP_INC(n), BASEPROBLEM_TYPES, BaseProblemType)> \ CouplingBaseProblem(std::string name_, \ BOOST_PP_REPEAT_ ## z(BOOST_PP_INC(n), BASEPROBLEM_ARGS2, nil) ) \ - : CProblemStat(name_),\ + : ProblemIterationInterface(),\ + ProblemTimeInterface(),\ + CProblemStat(name_),\ baseProblems( BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), *prob) ), name(name_) \ { dow = Global::getGeo(WORLD); } \ /****************************************************************************/ @@ -139,8 +143,8 @@ public: ~CouplingBaseProblem() { } virtual void initialize(Flag initFlag, - ProblemStatSeq *adoptProblem = NULL, - Flag adoptFlag = INIT_NOTHING) override + ProblemStatSeq *adoptProblem = NULL, + Flag adoptFlag = INIT_NOTHING) override { using namespace AMDiS::extensions; tools::FOR_EACH< detail::AddProblem >::loop2(*this, baseProblems); @@ -225,6 +229,41 @@ public: else throw(std::runtime_error("problem with given name '" + name_ + "' does not exist")); } + + // final overriders for some functions... + + virtual void serialize(std::ostream &out) {}; + virtual void deserialize(std::istream &in) {}; + + // using CouplingIterationInterface::beginIteration + virtual void beginIteration(AdaptInfo *adaptInfo) override + { + CouplingIterationInterface::beginIteration(adaptInfo); + } + + // using CouplingIterationInterface::oneIteration + virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo) override + { + return CouplingIterationInterface::oneIteration(adaptInfo,toDo); + } + + // using CouplingIterationInterface::endIteration + virtual void endIteration(AdaptInfo *adaptInfo) override + { + CouplingIterationInterface::endIteration(adaptInfo); + } + + // using CProblemStat::getNumProblems + virtual int getNumProblems() override + { + return CProblemStat::getNumProblems(); + } + + // using CProblemStat::getProblem + virtual ProblemType *getProblem(int number = 0) override + { + return CProblemStat::getProblem(number); + } protected: BaseProblemsTupleType baseProblems; diff --git a/extensions/base_problems/CouplingBaseProblem2_cxx11.h b/extensions/base_problems/CouplingBaseProblem2_cxx11.h index 748fce8b..d28e6937 100644 --- a/extensions/base_problems/CouplingBaseProblem2_cxx11.h +++ b/extensions/base_problems/CouplingBaseProblem2_cxx11.h @@ -17,84 +17,86 @@ namespace AMDiS { -namespace detail { - - /// for generic loops this struct can be passed - struct AddProblem { - template<typename CouplingProblemStatType, typename BaseProblemType> - static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { - for (size_t j = 0; j < baseProblem.getNumProblems(); j++) - couplingProblemStat.addProblem(baseProblem.getProblem(j)); - } - }; - - /// for generic loops this struct can be passed - struct AddTimeInterface { - template<typename CouplingProblemStatType, typename BaseProblemType> - static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { - couplingProblemStat.addTimeInterface(&baseProblem); - } - }; +namespace extensions { + + namespace detail { - /// for generic loops this struct can be passed - struct AddIterationInterface { - template<typename CouplingProblemStatType, typename BaseProblemType> - static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { - couplingProblemStat.addIterationInterface(&baseProblem); - } - }; + /// for generic loops this struct can be passed + struct AddProblem { + template<typename CouplingProblemStatType, typename BaseProblemType> + static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { + for (size_t j = 0; j < baseProblem.getNumProblems(); j++) + couplingProblemStat.addProblem(baseProblem.getProblem(j)); + } + }; + + /// for generic loops this struct can be passed + struct AddTimeInterface { + template<typename CouplingProblemStatType, typename BaseProblemType> + static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { + couplingProblemStat.addTimeInterface(&baseProblem); + } + }; + + /// for generic loops this struct can be passed + struct AddIterationInterface { + template<typename CouplingProblemStatType, typename BaseProblemType> + static void call(CouplingProblemStatType& couplingProblemStat, BaseProblemType& baseProblem) { + couplingProblemStat.addIterationInterface(&baseProblem); + } + }; + + /// Functor for generic loops. Method initData() is called for each element in a sequence. + struct InitData { + template<typename BaseProblemType> + static void call(BaseProblemType& baseProblem) { baseProblem.initData(); } + }; + + /// Functor for generic loops. Method initData() is called for each element in a sequence. + struct FinalizeData { + template<typename BaseProblemType> + static void call(BaseProblemType& baseProblem) { baseProblem.finalizeData(); } + }; + + /// Functor for generic loops. Method fillOperators() is called for each element in a sequence. + struct FillOperators { + template<typename BaseProblemType> + static void call(BaseProblemType& baseProblem) { baseProblem.fillOperators(); } + }; + + /// Functor for generic loops. Method fillBoundaryConditions() is called for each element in a sequence. + struct FillBoundaryConditions { + template<typename BaseProblemType> + static void call(BaseProblemType& baseProblem) { baseProblem.fillBoundaryConditions(); } + }; - /// Functor for generic loops. Method initData() is called for each element in a sequence. - struct InitData { - template<typename BaseProblemType> - static void call(BaseProblemType& baseProblem) { baseProblem.initData(); } - }; - /// Functor for generic loops. Method initData() is called for each element in a sequence. - struct FinalizeData { - template<typename BaseProblemType> - static void call(BaseProblemType& baseProblem) { baseProblem.finalizeData(); } - }; + struct FindProblem { + template<typename BaseProblemType, typename ProblemType> + static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType& prob) { + if (baseProblem.getName() == name) + prob = baseProblem.getProblem(); + } + }; - /// Functor for generic loops. Method fillOperators() is called for each element in a sequence. - struct FillOperators { - template<typename BaseProblemType> - static void call(BaseProblemType& baseProblem) { baseProblem.fillOperators(); } - }; + struct FindBaseProblem { + template<typename BaseProblemType, typename ProblemType> + static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob) { + typedef typename boost::mpl::if_<typename boost::is_same<BaseProblemType, ProblemType>::type, + boost::mpl::bool_<true>, + boost::mpl::bool_<false> >::type assign; + call(baseProblem, name, prob, assign()); + } + template<typename BaseProblemType, typename ProblemType> + static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<true>) { + if (baseProblem.getName() == name) + prob = &baseProblem; + } + template<typename BaseProblemType, typename ProblemType> + static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<false>) {} + }; - /// Functor for generic loops. Method fillBoundaryConditions() is called for each element in a sequence. - struct FillBoundaryConditions { - template<typename BaseProblemType> - static void call(BaseProblemType& baseProblem) { baseProblem.fillBoundaryConditions(); } - }; - - - struct FindProblem { - template<typename BaseProblemType, typename ProblemType> - static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType& prob) { - if (baseProblem.getName() == name) - prob = baseProblem.getProblem(); - } - }; - - struct FindBaseProblem { - template<typename BaseProblemType, typename ProblemType> - static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob) { - typedef typename boost::mpl::if_<typename boost::is_same<BaseProblemType, ProblemType>::type, - boost::mpl::bool_<true>, - boost::mpl::bool_<false> >::type assign; - call(baseProblem, name, prob, assign()); - } - template<typename BaseProblemType, typename ProblemType> - static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<true>) { - if (baseProblem.getName() == name) - prob = &baseProblem; - } - template<typename BaseProblemType, typename ProblemType> - static void call(BaseProblemType& baseProblem, const std::string& name, ProblemType*& prob, boost::mpl::bool_<false>) {} - }; - -} // end namespace detail + } // end namespace detail /** * \ingroup Problem @@ -103,16 +105,18 @@ namespace detail { */ template<typename ProblemType=ProblemStat, typename... BaseProblemTypes > class CouplingBaseProblem : public CouplingIterationInterface, - public CouplingTimeInterface, - public detail::CouplingProblemStat<ProblemType> + public CouplingTimeInterface, + public AMDiS::detail::CouplingProblemStat<ProblemType> { public: - typedef detail::CouplingProblemStat<ProblemType> CProblemStat; + typedef AMDiS::detail::CouplingProblemStat<ProblemType> CProblemStat; typedef std::tuple<BaseProblemTypes&...> BaseProblemsTupleType; template<typename... BaseProblemTypes_> CouplingBaseProblem(std::string name_, BaseProblemTypes_&&... baseProblems_) - : CProblemStat(name_), + : ProblemIterationInterface(), // virtual base class constructor + ProblemTimeInterface(), // virtual base class constructor + CProblemStat(name_), baseProblems(baseProblems_...), name(name_) { @@ -131,8 +135,8 @@ public: * method. **/ virtual void initialize(Flag initFlag, - ProblemStatSeq *adoptProblem = NULL, - Flag adoptFlag = INIT_NOTHING) override + ProblemStatSeq *adoptProblem = NULL, + Flag adoptFlag = INIT_NOTHING) override { tools::FOR_EACH< detail::AddProblem >::loop2(*this, baseProblems); tools::FOR_EACH< detail::AddIterationInterface >::loop2(*this, baseProblems); @@ -217,7 +221,42 @@ public: else throw(std::runtime_error("problem with given name '" + name_ + "' does not exist")); } - + + // final overriders for some functions... + + virtual void serialize(std::ostream &out) {}; + virtual void deserialize(std::istream &in) {}; + + // using CouplingIterationInterface::beginIteration + virtual void beginIteration(AdaptInfo *adaptInfo) override + { + CouplingIterationInterface::beginIteration(adaptInfo); + } + + // using CouplingIterationInterface::oneIteration + virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo) override + { + return CouplingIterationInterface::oneIteration(adaptInfo,toDo); + } + + // using CouplingIterationInterface::endIteration + virtual void endIteration(AdaptInfo *adaptInfo) override + { + CouplingIterationInterface::endIteration(adaptInfo); + } + + // using CProblemStat::getNumProblems + virtual int getNumProblems() override + { + return CProblemStat::getNumProblems(); + } + + // using CProblemStat::getProblem + virtual ProblemType *getProblem(int number = 0) override + { + return CProblemStat::getProblem(number); + } + protected: BaseProblemsTupleType baseProblems; @@ -227,6 +266,8 @@ protected: std::string name; }; +} // end namespace extensions + } // end namespace AMDiS #endif // COUPLING_BASE_PROBLEM_H diff --git a/extensions/base_problems/NavierStokes_TH_MultiPhase.hh b/extensions/base_problems/NavierStokes_TH_MultiPhase.hh index 62c0dec9..b536b888 100644 --- a/extensions/base_problems/NavierStokes_TH_MultiPhase.hh +++ b/extensions/base_problems/NavierStokes_TH_MultiPhase.hh @@ -242,3 +242,4 @@ void NavierStokes_TH_MultiPhase<P>::addLaplaceTerm(int i) } // end namespace detail } } + diff --git a/extensions/demo/multimesh/CMakeLists.txt b/extensions/demo/multimesh/CMakeLists.txt new file mode 100644 index 00000000..74786f7e --- /dev/null +++ b/extensions/demo/multimesh/CMakeLists.txt @@ -0,0 +1,33 @@ +project("dendrites_karma") +cmake_minimum_required(VERSION 2.8) + +find_package(AMDIS REQUIRED) + +if(AMDIS_FOUND) + message("amdis was found\n") + include(${AMDIS_USE_FILE}) + SET(BASIS_LIBS ${AMDIS_LIBRARIES}) +endif(AMDIS_FOUND) + + +set(dendrites ./src/dendrites.cc + ./src/MyProblemInstat.cc + ./src/Refinement.cc) + +set(diffuse ./src/diffuseDomain.cc) + +set(chns src/cahnHilliard_navierStokes.cc) + + +add_executable("dendrites" ${dendrites}) +target_link_libraries("dendrites" ${BASIS_LIBS}) + +add_executable("diffuse" ${diffuse}) +target_link_libraries("diffuse" ${BASIS_LIBS}) + +add_executable("chns" ${chns}) +target_link_libraries("chns" ${BASIS_LIBS}) + + +add_executable("chns_mm" src/cahnHilliard_navierStokes_mm.cc) +target_link_libraries("chns_mm" ${BASIS_LIBS}) \ No newline at end of file diff --git a/extensions/demo/multimesh/init/cahnHilliard_navierStokes.dat.2d b/extensions/demo/multimesh/init/cahnHilliard_navierStokes.dat.2d new file mode 100644 index 00000000..7c1ba3db --- /dev/null +++ b/extensions/demo/multimesh/init/cahnHilliard_navierStokes.dat.2d @@ -0,0 +1,126 @@ +dimension of world: 2 + +parallel->repartitioning: 0 +parallel->repartitioning->strategy: 1 % 0..quick, 1..full + +% =================== MESH ================================ +mesh_name: mesh +mesh->macro file name: ./macro/macro.square.2d +mesh->global refinements: 0 + +mesh->refinement->level in outer domain: 3 +mesh->refinement->level in inner domain: 3 +mesh->refinement->level on interface: 10 +mesh->refinement->initial level: 7 +mesh->check: 0 + +% ============== USER-PARAMETER ========================== +ch->epsilon: 0.01 +ch->gamma: 1 +ch->double-well type: 0 + +ch->initial interface: 2 +ch->ellipse->a: 0.3 +ch->ellipse->b: 0.5 + +ns->viscosity: 1 +ns->density: 1 + +ns->theta: 0.5 +%ns->force: [0.0, -1.0] % gravitational force + +ns->laplace operator: 0 +% type of laplace operator: +% 0... div(nu*grad(u)), +% 1... div(0.5*nu*(grad(u)+grad(u)^T)) + +ns->non-linear term: 2 +% type of non-linear term: +% 0... u^old*grad(u_i^old), +% 1... u'*grad(u_i^old), +% 2... u^old*grad(u'_i) +% 3... (1)+(2)-(0) + + + +ch->space->mass conservation component: 0 + +% =========== OUTPUT ============================================== +prefix: _restrict3 +ch->space->output->filename: ./output/ch${prefix}_ + +ns->velocity->output->filename: ./output/velocity${prefix}_ +ns->space->output[2]->filename: ./output/pressure${prefix}_ + +% ==================== TIMESTEPS =============================== +adapt->timestep: 1.e-2 +adapt->max timestep: 1e+10 +adapt->min timestep: 1e-10 +adapt->start time: 0.0 +adapt->end time: 3 %1.e-2 + +% ============= PROBLEM-SPACES - CH ============================= +ch->space->components: 2 +ch->space->polynomial degree[0]: 3 +ch->space->polynomial degree[1]: 3 + +ch->space->dim: 2 +ch->space->mesh: mesh + +% ============= PROBLEM-SPACES - NS =========================== +ns->space->components: 3 +ns->space->polynomial degree[0]: 2 +ns->space->polynomial degree[1]: 2 +ns->space->polynomial degree[2]: 1 + +ns->space->dim: 2 +ns->space->mesh: mesh + +% ============= PROBLEM-SPACES - CHNS =========================== +chns->components: 5 +chns->dim: 2 +chns->mesh: mesh + +% ================== SOLVER - CH ================================ +ch->space->solver: direct +%ch->space->solver->backend: mtl +ch->space->solver->petsc prefix: ch +ch->space->solver->symmetric strategy: 0 +ch->space->solver->store symbolic: 0 +ch->space->solver->tolerance: 1.e-8 +ch->space->solver->info: 1 + +% ================== SOLVER - NS ================================ +ns->space->solver: direct +%ns->space->solver->backend: mtl +ns->space->solver->petsc prefix: ns +ns->space->solver->symmetric strategy: 0 +ns->space->solver->store symbolic: 0 +ns->space->solver->tolerance: 1.e-8 +ns->space->solver->info: 1 + +% =================== OUTPUT - CH =============================== +ch->space->output->ParaView animation: 1 +ch->space->output->ParaView format: 1 +ch->space->output->write every i-th timestep: 1 +ch->space->output->append index: 1 +ch->space->output->index length: 9 +ch->space->output->index decimals: 7 + +% =================== OUTPUT - NS =============================== +ns->velocity->output->ParaView animation: 1 +ns->velocity->output->ParaView vector format: 1 +ns->velocity->output->write vector as 3d vector: 1 +ns->velocity->output->write every i-th timestep: 10 +ns->velocity->output->append index: 1 +ns->velocity->output->index length: 9 +ns->velocity->output->index decimals: 7 + +ns->space->output[2]->ParaView animation: 1 +ns->space->output[2]->ParaView format: 1 +ns->space->output[2]->write every i-th timestep: 10 +ns->space->output[2]->append index: 1 +ns->space->output[2]->index length: 9 +ns->space->output[2]->index decimals: 7 + + diff --git a/extensions/demo/multimesh/init/dend002.dat.2d.m.bicg.2p b/extensions/demo/multimesh/init/dend002.dat.2d.m.bicg.2p new file mode 100644 index 00000000..6f86f2b8 --- /dev/null +++ b/extensions/demo/multimesh/init/dend002.dat.2d.m.bicg.2p @@ -0,0 +1,138 @@ +dimension of world: 2 + + +parallel->repartitioning: 1 +parallel->repartitioning->strategy: 1 % 0..quick, 1..full +parallel->pre refine: 8 + + +dendrites->write arh file: 1 +dendrites->write phi arh: ./output/phi800.arh +dendrites->write rho arh: ./output/rho800.arh + +%dendrites->read arh file: ./output/dend.arh +%dendrites->read phi arh: ./output/phi.arh +%dendrites->read rho arh: ./output/rho.arh + + + +dendritesMesh->macro file name: ./macro/macro_corner_1x1.2d +dendritesMesh->global refinements: 10 + +dendritesMesh->scal x: 1000 +dendritesMesh->scal y: 1000 + + +dendrites->space->dim: 2 + +dendrites->space->polynomial degree[0]: 1 +dendrites->space->polynomial degree[1]: 1 + +dendrites->space->mesh: dendritesMesh +dendrites->space->components: 2 + +dendrites->space->refinement set[0]: 0 +dendrites->space->refinement set[1]: 1 + + +dendrites->space->solver: bicgstab +%dendrites->space->solver: umfpack +dendrites->space->solver->ell: 4 +dendrites->space->solver->max iteration: 1000 +dendrites->space->solver->tolerance: 1.e-8 +dendrites->space->solver->info: 5 +dendrites->space->solver->left precon: no +dendrites->space->solver->right precon: no + +dendrites->space->estimator[0]: residual +dendrites->space->estimator[0]->C0: 0.0 +dendrites->space->estimator[0]->C1: 1.0 +dendrites->space->estimator[0]->C2: 0.0 +dendrites->space->estimator[0]->C3: 0.0 + +dendrites->space->estimator[1]: residual +dendrites->space->estimator[1]->C0: 0.0 +dendrites->space->estimator[1]->C1: 1.0 +dendrites->space->estimator[1]->C2: 0.0 +dendrites->space->estimator[1]->C3: 0.0 + +dendrites->adapt[0]->tolerance: 0.5 +dendrites->adapt[0]->info: 8 +dendrites->adapt[0]->coarsen allowed: 1 + +dendrites->adapt[1]->tolerance: 0.25 +dendrites->adapt[1]->info: 8 +dendrites->adapt[1]->coarsen allowed: 1 + + +dendrites->adapt->timestep: 1.0 +dendrites->adapt->max timestep: 1.0 +dendrites->adapt->end time: 800.0 +dendrites->adapt->start time: 0.0 + +dendrites->adapt->strategy: 0 % 0=explicit, 1=implicit +dendrites->adapt->max iteration: 1 + +dendrites->initial->marker[0]->strategy: 0 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS +dendrites->initial->marker[1]->strategy: 0 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS + +dendrites->initial->adapt->max iteration: 1 +dendrites->initial->adapt->info: 8 + +dendrites->space->marker[0]->strategy: 3 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS +dendrites->space->marker[0]->ESTheta: 0.8 +dendrites->space->marker[0]->ESThetaC: 0.2 +dendrites->space->marker[0]->info: 8 +dendrites->space->marker[0]->min refinement level: 10 + +dendrites->space->marker[1]->strategy: 3 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS +dendrites->space->marker[1]->ESTheta: 0.8 +dendrites->space->marker[1]->ESThetaC: 0.2 +dendrites->space->marker[1]->info: 8 +dendrites->space->marker[1]->min refinement level: 10 + +dendrites->space->output[0]->filename: ./output/002/phi2 +dendrites->space->output[0]->ParaView format: 1 +dendrites->space->output[0]->ParaView mode: 2 +dendrites->space->output[0]->ParaView create subdirectory: 1 +dendrites->space->output[0]->ParaView animation: 1 +dendrites->space->output[0]->write every i-th timestep: 25 +dendrites->space->output[0]->append index: 1 +dendrites->space->output[0]->index length: 8 +dendrites->space->output[0]->index decimals: 2 + +dendrites->space->output[1]->filename: ./output/002/rho2 +dendrites->space->output[1]->ParaView format: 1 +dendrites->space->output[1]->ParaView mode: 2 +dendrites->space->output[1]->ParaView create subdirectory: 1 +dendrites->space->output[1]->ParaView animation: 1 +dendrites->space->output[1]->write every i-th timestep: 25 +dendrites->space->output[1]->append index: 1 +dendrites->space->output[1]->index length: 8 +dendrites->space->output[1]->index decimals: 2 + +dendrites->space->output->write every i-th timestep: 25 + +dendrites->space->output->write serialization: 0 +dendrites->space->output->serialization filename: ./output/002/dendrites.ser + +dendrites->space->input->read serialization: 0 +dendrites->space->input->serialization filename: ./output/002/dendrites.ser + + +% === INTERFACE PARAMETER === + +dendrites->radius: 3.00 % radius of initial island + +dendrites->h init interface: 0.1 +dendrites->h interface: 0.1 +dendrites->ref interface: 0 + +% === MODEL PARAMETER === + +dendrites->karma model->D: 1.00 +dendrites->karma model->gamma: 0.05 +dendrites->karma model->rho initial: 0.65 + + +parallel->output->serialization filename: ./output/002/parallel.ser diff --git a/extensions/demo/multimesh/init/heat.dat.2d.m_1015_1010 b/extensions/demo/multimesh/init/heat.dat.2d.m_1015_1010 new file mode 100644 index 00000000..9b1f0edf --- /dev/null +++ b/extensions/demo/multimesh/init/heat.dat.2d.m_1015_1010 @@ -0,0 +1,85 @@ +dimension of world: 2 + +parallel->repartitioning: 1 +parallel->repartitioning->strategy: 1 % 0..quick, 1..full +parallel->repartitioning->imbalance: 0.05 % =5% + + +mesh->macro file name: ./macro/macro.square.2d + +% phase +mesh->max refinement level: 30 +mesh->update refinement level: 30 +mesh->refinement->level in inner domain: 10 +mesh->refinement->level in outer domain: 10 +mesh->refinement->level on interface: 15 +mesh->refinement->initial level: 0 +mesh->refinement->interface width: 0.03 + +% heat +mesh2->max refinement level: 30 +mesh2->update refinement level: 30 +mesh2->refinement->level in inner domain: 10 % +mesh2->refinement->level in outer domain: 10 % +mesh2->refinement->level on interface: 10 +mesh2->refinement->initial level: 0 +mesh2->refinement->interface width: 0.03 + +%mesh->refinement->global heat refine: 3 + +mesh->scale mesh: 1 +mesh->dimension: [2, 2] + +radius: 3.5 +center: [2,2] +epsilon: 0.1 + + +heat->mesh: mesh +heat->dim: 2 +heat->components: 1 +heat->additional components: 1 +heat->polynomial degree[0]: 1 +heat->polynomial degree[1]: 1 +heat->refinement set[0]: 0 +heat->refinement set[1]: 1 + +heat->solver: cg +heat->solver->max iteration: 10000 +heat->solver->tolerance: 1.e-8 +heat->solver->info: 2 +heat->solver->left precon: no +heat->solver->right precon: no + +% heat->estimator[0]: residual +% heat->estimator[0]->C0: 0.0 +% heat->estimator[0]->C1: 1.0 +% heat->estimator[0]->C2: 0.0 +% heat->estimator[0]->C3: 0.0 + +adapt[0]->tolerance: 0.05 +adapt[0]->time tolerance: 0.05 + +adapt->strategy: 0 % 0=explicit, 1=implicit +adapt->max iteration: 100 + +adapt[0]->coarsen allowed: 1 +adapt[0]->refine bisections: 2 +adapt[0]->coarsen bisections: 2 + +heat->marker[0]->strategy: 0 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS +heat->marker[0]->MSGamma: 0.5 +heat->marker[0]->MSGammaC: 0.1 + +% ==================== TIMESTEPS =============================== +adapt->timestep: 1 +adapt->start time: 0 +adapt->end time: 3 + +heat->output->filename: ./output/heat_m_ +heat->output->ParaView animation: 1 +heat->output->ParaView format: 1 +heat->output->write every i-th timestep: 1 +heat->output->append index: 1 +heat->output->index length: 9 +heat->output->index decimals: 7 diff --git a/extensions/demo/multimesh/init/heat.dat.2d.s_16_16 b/extensions/demo/multimesh/init/heat.dat.2d.s_16_16 new file mode 100644 index 00000000..4d9fc84f --- /dev/null +++ b/extensions/demo/multimesh/init/heat.dat.2d.s_16_16 @@ -0,0 +1,76 @@ +dimension of world: 2 + +parallel->repartitioning: 1 +parallel->repartition ith change: 5 +parallel->repartitioning->strategy: 0 % 0..quick, 1..full +parallel->repartitioning->imbalance: 0.1 % =10% + + +mesh->macro file name: ./macro/macro.square.2d + + +mesh->max refinement level: 30 +mesh->update refinement level: 30 +mesh->refinement->level in inner domain: 16 +mesh->refinement->level in outer domain: 16 +mesh->refinement->level on interface: 16 +mesh->refinement->initial level: 0 +mesh->refinement->interface width: 0.03 + +mesh->scale mesh: 1 +mesh->dimension: [2, 2] + +radius: 3.5 +center: [2,2] +epsilon: 0.1 + + +heat->mesh: mesh +heat->dim: 2 +heat->components: 1 +heat->additional components: 1 +heat->polynomial degree[0]: 1 +heat->polynomial degree[1]: 1 +%heat->refinement set[0]: 0 +%heat->refinement set[1]: 0 + +heat->solver: cg +heat->solver->max iteration: 10000 +heat->solver->tolerance: 1.e-8 +heat->solver->info: 2 +heat->solver->left precon: no +heat->solver->right precon: no + +%heat->estimator[0]: residual +%heat->estimator[0]->C0: 0.0 +%heat->estimator[0]->C1: 1.0 +%heat->estimator[0]->C2: 0.0 +%heat->estimator[0]->C3: 0.0 + +adapt[0]->tolerance: 0.05 +adapt[0]->time tolerance: 0.05 + +adapt->strategy: 0 % 0=explicit, 1=implicit +adapt->max iteration: 100 + +adapt[0]->coarsen allowed: 1 +adapt[0]->refine bisections: 2 +adapt[0]->coarsen bisections: 2 + +heat->marker[0]->strategy: 0 % 0=none, 1=GR, 2=MS, 3=ES, 4=GERS +heat->marker[0]->MSGamma: 0.5 +heat->marker[0]->MSGammaC: 0.1 + +% ==================== TIMESTEPS =============================== +adapt->timestep: 1 +adapt->start time: 0 +adapt->end time: 3 + +heat->output->filename: ./output/heat_s_ +heat->output->ParaView animation: 1 +heat->output->ParaView format: 1 +heat->output->write every i-th timestep: 1 +heat->output->append index: 1 +heat->output->index length: 9 +heat->output->index decimals: 7 + diff --git a/extensions/demo/multimesh/macro/macro.square.2d b/extensions/demo/multimesh/macro/macro.square.2d new file mode 100644 index 00000000..7d310bfb --- /dev/null +++ b/extensions/demo/multimesh/macro/macro.square.2d @@ -0,0 +1,47 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of elements: 8 +number of vertices: 9 + +vertex coordinates: +-1 -1 +0 -1 +1 -1 +-1 0 +0 0 +1 0 +-1 1 +0 1 +1 1 + +element vertices: +0 4 3 +4 0 1 +1 5 4 +5 1 2 +3 7 6 +7 3 4 +4 8 7 +8 4 5 + +element boundaries: +0 1 0 +3 0 0 +0 0 0 +3 2 0 +4 1 0 +0 0 0 +4 0 0 +0 2 0 + +element neighbours: +5 -1 1 +-1 2 0 +7 1 3 +-1 -1 2 +-1 -1 5 +0 6 4 +-1 5 7 +2 -1 6 + diff --git a/extensions/demo/multimesh/macro/macro.square.2d.666466.tmp b/extensions/demo/multimesh/macro/macro.square.2d.666466.tmp new file mode 100644 index 00000000..17c80569 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro.square.2d.666466.tmp @@ -0,0 +1,236 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 25 +number of elements: 32 + +vertex coordinates: +-1.000000e+00 -1.000000e+00 +0.000000e+00 -1.000000e+00 +1.000000e+00 -1.000000e+00 +-1.000000e+00 0.000000e+00 +0.000000e+00 0.000000e+00 +1.000000e+00 0.000000e+00 +-1.000000e+00 1.000000e+00 +0.000000e+00 1.000000e+00 +1.000000e+00 1.000000e+00 +-5.000000e-01 5.000000e-01 +5.000000e-01 5.000000e-01 +-1.000000e+00 -5.000000e-01 +-5.000000e-01 -1.000000e+00 +-1.000000e+00 5.000000e-01 +5.000000e-01 -1.000000e+00 +0.000000e+00 -5.000000e-01 +0.000000e+00 5.000000e-01 +-5.000000e-01 1.000000e+00 +5.000000e-01 -5.000000e-01 +-5.000000e-01 0.000000e+00 +1.000000e+00 5.000000e-01 +5.000000e-01 1.000000e+00 +1.000000e+00 -5.000000e-01 +5.000000e-01 0.000000e+00 +-5.000000e-01 -5.000000e-01 + +element vertices: +24 3 11 +0 24 11 +24 4 19 +3 24 19 +24 1 15 +4 24 15 +24 0 12 +1 24 12 +18 4 15 +1 18 15 +18 5 23 +4 18 23 +18 2 22 +5 18 22 +18 1 14 +2 18 14 +9 6 13 +3 9 13 +9 7 17 +6 9 17 +9 4 16 +7 9 16 +9 3 19 +4 9 19 +10 7 16 +4 10 16 +10 8 21 +7 10 21 +10 5 20 +8 10 20 +10 4 23 +5 10 23 + +element boundaries: +1 0 0 +0 1 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +3 0 0 +0 3 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +2 0 0 +0 2 0 +3 0 0 +0 3 0 +1 0 0 +0 1 0 +4 0 0 +0 4 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +4 0 0 +0 4 0 +2 0 0 +0 2 0 +0 0 0 +0 0 0 + +element neighbours: +-1 1 3 +0 -1 6 +23 3 5 +2 22 0 +9 5 7 +4 8 2 +-1 7 1 +6 -1 4 +5 9 11 +8 4 14 +31 11 13 +10 30 8 +-1 13 15 +12 -1 10 +-1 15 9 +14 -1 12 +-1 17 19 +16 -1 22 +-1 19 21 +18 -1 16 +25 21 23 +20 24 18 +3 23 17 +22 2 20 +21 25 27 +24 20 30 +-1 27 29 +26 -1 24 +-1 29 31 +28 -1 26 +11 31 25 +30 10 28 + +projections: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element region: +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 + +surface region: +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 diff --git a/extensions/demo/multimesh/macro/macro.square.2d.685642.tmp b/extensions/demo/multimesh/macro/macro.square.2d.685642.tmp new file mode 100644 index 00000000..287a9815 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro.square.2d.685642.tmp @@ -0,0 +1,236 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 25 +number of elements: 32 + +vertex coordinates: +-1.000000e+00 -1.000000e+00 +0.000000e+00 -1.000000e+00 +1.000000e+00 -1.000000e+00 +-1.000000e+00 0.000000e+00 +0.000000e+00 0.000000e+00 +1.000000e+00 0.000000e+00 +-1.000000e+00 1.000000e+00 +0.000000e+00 1.000000e+00 +1.000000e+00 1.000000e+00 +-5.000000e-01 -5.000000e-01 +-1.000000e+00 -5.000000e-01 +-5.000000e-01 5.000000e-01 +-5.000000e-01 0.000000e+00 +5.000000e-01 -5.000000e-01 +0.000000e+00 -5.000000e-01 +-5.000000e-01 -1.000000e+00 +5.000000e-01 5.000000e-01 +5.000000e-01 0.000000e+00 +1.000000e+00 -5.000000e-01 +5.000000e-01 -1.000000e+00 +-1.000000e+00 5.000000e-01 +-5.000000e-01 1.000000e+00 +0.000000e+00 5.000000e-01 +5.000000e-01 1.000000e+00 +1.000000e+00 5.000000e-01 + +element vertices: +9 3 10 +0 9 10 +9 4 12 +3 9 12 +9 1 14 +4 9 14 +9 0 15 +1 9 15 +13 4 14 +1 13 14 +13 5 17 +4 13 17 +13 2 18 +5 13 18 +13 1 19 +2 13 19 +11 6 20 +3 11 20 +11 7 21 +6 11 21 +11 4 22 +7 11 22 +11 3 12 +4 11 12 +16 7 22 +4 16 22 +16 8 23 +7 16 23 +16 5 24 +8 16 24 +16 4 17 +5 16 17 + +element boundaries: +1 0 0 +0 1 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +3 0 0 +0 3 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +2 0 0 +0 2 0 +3 0 0 +0 3 0 +1 0 0 +0 1 0 +4 0 0 +0 4 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +4 0 0 +0 4 0 +2 0 0 +0 2 0 +0 0 0 +0 0 0 + +element neighbours: +-1 1 3 +0 -1 6 +23 3 5 +2 22 0 +9 5 7 +4 8 2 +-1 7 1 +6 -1 4 +5 9 11 +8 4 14 +31 11 13 +10 30 8 +-1 13 15 +12 -1 10 +-1 15 9 +14 -1 12 +-1 17 19 +16 -1 22 +-1 19 21 +18 -1 16 +25 21 23 +20 24 18 +3 23 17 +22 2 20 +21 25 27 +24 20 30 +-1 27 29 +26 -1 24 +-1 29 31 +28 -1 26 +11 31 25 +30 10 28 + +projections: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element region: +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 + +surface region: +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 diff --git a/extensions/demo/multimesh/macro/macro_corner_1x1.2d b/extensions/demo/multimesh/macro/macro_corner_1x1.2d new file mode 100644 index 00000000..1e525f90 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro_corner_1x1.2d @@ -0,0 +1,24 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 5 +number of elements: 4 + +vertex coordinates: +0.0 0.0 +1.0 0.0 +1.0 1.0 +0.0 1.0 +0.5 0.5 + +element vertices: +0 1 4 +1 2 4 +2 3 4 +3 0 4 + +element boundaries: +0 0 1 +0 0 1 +0 0 1 +0 0 1 diff --git a/extensions/demo/multimesh/macro/macro_corner_1x1.2d.736102.tmp b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.736102.tmp new file mode 100644 index 00000000..f152f950 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.736102.tmp @@ -0,0 +1,6708 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 545 +number of elements: 1024 + +vertex coordinates: +0.000000e+00 0.000000e+00 +1.000000e+00 0.000000e+00 +1.000000e+00 1.000000e+00 +0.000000e+00 1.000000e+00 +5.000000e-01 5.000000e-01 +5.000000e-01 0.000000e+00 +0.000000e+00 5.000000e-01 +2.500000e-01 2.500000e-01 +1.000000e+00 5.000000e-01 +7.500000e-01 2.500000e-01 +5.000000e-01 2.500000e-01 +2.500000e-01 0.000000e+00 +3.750000e-01 1.250000e-01 +5.000000e-01 1.000000e+00 +2.500000e-01 7.500000e-01 +2.500000e-01 5.000000e-01 +3.750000e-01 3.750000e-01 +3.750000e-01 2.500000e-01 +7.500000e-01 0.000000e+00 +6.250000e-01 1.250000e-01 +5.000000e-01 1.250000e-01 +4.375000e-01 1.875000e-01 +0.000000e+00 2.500000e-01 +1.250000e-01 1.250000e-01 +2.500000e-01 1.250000e-01 +3.125000e-01 1.875000e-01 +3.750000e-01 1.875000e-01 +7.500000e-01 7.500000e-01 +7.500000e-01 5.000000e-01 +6.250000e-01 3.750000e-01 +5.000000e-01 3.750000e-01 +4.375000e-01 3.125000e-01 +4.375000e-01 2.500000e-01 +4.062500e-01 2.187500e-01 +3.750000e-01 0.000000e+00 +4.375000e-01 6.250000e-02 +4.375000e-01 1.250000e-01 +4.062500e-01 1.562500e-01 +6.250000e-01 2.500000e-01 +5.625000e-01 1.875000e-01 +5.000000e-01 1.875000e-01 +4.687500e-01 2.187500e-01 +1.250000e-01 3.750000e-01 +2.500000e-01 3.750000e-01 +3.125000e-01 3.125000e-01 +3.125000e-01 2.500000e-01 +3.437500e-01 2.187500e-01 +1.250000e-01 2.500000e-01 +1.875000e-01 1.875000e-01 +2.500000e-01 1.875000e-01 +2.812500e-01 2.187500e-01 +3.125000e-01 6.250000e-02 +3.125000e-01 1.250000e-01 +3.437500e-01 1.562500e-01 +6.250000e-01 0.000000e+00 +5.625000e-01 6.250000e-02 +5.000000e-01 6.250000e-02 +4.687500e-01 9.375000e-02 +3.750000e-01 6.250000e-02 +4.062500e-01 9.375000e-02 +4.375000e-01 0.000000e+00 +4.687500e-01 3.125000e-02 +4.687500e-01 1.562500e-01 +5.000000e-01 7.500000e-01 +3.750000e-01 6.250000e-01 +3.750000e-01 5.000000e-01 +4.375000e-01 4.375000e-01 +4.375000e-01 3.750000e-01 +5.625000e-01 3.125000e-01 +5.000000e-01 3.125000e-01 +4.687500e-01 3.437500e-01 +3.750000e-01 3.125000e-01 +4.062500e-01 3.437500e-01 +4.687500e-01 2.812500e-01 +6.250000e-01 6.250000e-01 +6.250000e-01 5.000000e-01 +5.625000e-01 4.375000e-01 +5.000000e-01 4.375000e-01 +4.687500e-01 4.062500e-01 +5.000000e-01 6.250000e-01 +4.375000e-01 5.625000e-01 +4.375000e-01 5.000000e-01 +4.687500e-01 4.687500e-01 +3.125000e-01 4.375000e-01 +3.750000e-01 4.375000e-01 +4.062500e-01 4.062500e-01 +3.437500e-01 2.812500e-01 +3.125000e-01 3.750000e-01 +3.437500e-01 3.437500e-01 +1.875000e-01 3.125000e-01 +2.500000e-01 3.125000e-01 +2.812500e-01 2.812500e-01 +4.062500e-01 2.812500e-01 +1.250000e-01 0.000000e+00 +1.875000e-01 6.250000e-02 +1.875000e-01 1.250000e-01 +2.500000e-01 6.250000e-02 +2.187500e-01 9.375000e-02 +0.000000e+00 1.250000e-01 +6.250000e-02 6.250000e-02 +1.250000e-01 6.250000e-02 +1.562500e-01 9.375000e-02 +1.875000e-01 0.000000e+00 +2.187500e-01 3.125000e-02 +2.187500e-01 1.562500e-01 +1.875000e-01 2.500000e-01 +2.187500e-01 2.187500e-01 +6.250000e-02 1.875000e-01 +1.250000e-01 1.875000e-01 +1.562500e-01 1.562500e-01 +6.250000e-02 0.000000e+00 +9.375000e-02 3.125000e-02 +6.250000e-02 1.250000e-01 +9.375000e-02 9.375000e-02 +0.000000e+00 6.250000e-02 +3.125000e-02 3.125000e-02 +1.562500e-01 3.125000e-02 +3.125000e-01 0.000000e+00 +3.437500e-01 3.125000e-02 +3.437500e-01 9.375000e-02 +2.812500e-01 3.125000e-02 +4.062500e-01 3.125000e-02 +2.812500e-01 1.562500e-01 +2.812500e-01 9.375000e-02 +1.000000e+00 2.500000e-01 +8.750000e-01 1.250000e-01 +7.500000e-01 1.250000e-01 +6.875000e-01 6.250000e-02 +6.875000e-01 1.875000e-01 +6.875000e-01 1.250000e-01 +8.750000e-01 0.000000e+00 +8.125000e-01 6.250000e-02 +7.500000e-01 6.250000e-02 +7.187500e-01 9.375000e-02 +6.250000e-01 6.250000e-02 +6.562500e-01 9.375000e-02 +6.875000e-01 0.000000e+00 +7.187500e-01 3.125000e-02 +8.750000e-01 3.750000e-01 +8.750000e-01 2.500000e-01 +8.125000e-01 1.875000e-01 +7.500000e-01 1.875000e-01 +7.187500e-01 1.562500e-01 +7.500000e-01 3.750000e-01 +6.875000e-01 3.125000e-01 +6.875000e-01 2.500000e-01 +7.187500e-01 2.187500e-01 +6.250000e-01 1.875000e-01 +6.562500e-01 1.562500e-01 +5.625000e-01 0.000000e+00 +5.937500e-01 3.125000e-02 +5.625000e-01 1.250000e-01 +5.937500e-01 9.375000e-02 +5.312500e-01 3.125000e-02 +6.562500e-01 3.125000e-02 +1.000000e+00 1.250000e-01 +9.375000e-01 6.250000e-02 +8.750000e-01 6.250000e-02 +8.125000e-01 0.000000e+00 +8.437500e-01 3.125000e-02 +8.125000e-01 1.250000e-01 +8.437500e-01 9.375000e-02 +7.812500e-01 3.125000e-02 +9.375000e-01 0.000000e+00 +9.062500e-01 3.125000e-02 +1.000000e+00 6.250000e-02 +9.687500e-01 3.125000e-02 +9.375000e-01 1.875000e-01 +9.375000e-01 1.250000e-01 +9.062500e-01 9.375000e-02 +7.812500e-01 1.562500e-01 +8.750000e-01 1.875000e-01 +8.437500e-01 1.562500e-01 +8.125000e-01 3.125000e-01 +8.125000e-01 2.500000e-01 +7.812500e-01 2.187500e-01 +7.812500e-01 9.375000e-02 +6.250000e-01 3.125000e-01 +5.625000e-01 2.500000e-01 +5.937500e-01 2.812500e-01 +5.625000e-01 3.750000e-01 +5.937500e-01 3.437500e-01 +5.312500e-01 2.812500e-01 +6.562500e-01 2.812500e-01 +7.500000e-01 3.125000e-01 +7.187500e-01 2.812500e-01 +6.875000e-01 4.375000e-01 +6.875000e-01 3.750000e-01 +6.562500e-01 3.437500e-01 +5.312500e-01 4.062500e-01 +6.250000e-01 4.375000e-01 +5.937500e-01 4.062500e-01 +5.625000e-01 5.625000e-01 +5.625000e-01 5.000000e-01 +5.312500e-01 4.687500e-01 +5.312500e-01 3.437500e-01 +5.312500e-01 1.562500e-01 +5.937500e-01 1.562500e-01 +5.312500e-01 2.187500e-01 +5.312500e-01 9.375000e-02 +6.562500e-01 2.187500e-01 +5.937500e-01 2.187500e-01 +1.000000e+00 7.500000e-01 +8.750000e-01 6.250000e-01 +8.750000e-01 5.000000e-01 +8.125000e-01 4.375000e-01 +8.125000e-01 3.750000e-01 +7.500000e-01 4.375000e-01 +7.812500e-01 4.062500e-01 +1.000000e+00 3.750000e-01 +9.375000e-01 4.375000e-01 +8.750000e-01 4.375000e-01 +8.437500e-01 4.062500e-01 +7.500000e-01 6.250000e-01 +8.125000e-01 5.625000e-01 +8.125000e-01 5.000000e-01 +7.812500e-01 4.687500e-01 +7.812500e-01 3.437500e-01 +7.812500e-01 2.812500e-01 +9.375000e-01 3.125000e-01 +8.750000e-01 3.125000e-01 +8.437500e-01 3.437500e-01 +1.000000e+00 6.250000e-01 +9.375000e-01 5.625000e-01 +9.375000e-01 5.000000e-01 +9.062500e-01 4.687500e-01 +9.375000e-01 3.750000e-01 +9.062500e-01 4.062500e-01 +1.000000e+00 4.375000e-01 +9.687500e-01 4.687500e-01 +8.437500e-01 4.687500e-01 +6.875000e-01 5.625000e-01 +6.875000e-01 5.000000e-01 +6.562500e-01 4.687500e-01 +6.562500e-01 4.062500e-01 +7.187500e-01 4.687500e-01 +5.937500e-01 4.687500e-01 +7.187500e-01 3.437500e-01 +7.187500e-01 4.062500e-01 +9.375000e-01 2.500000e-01 +9.062500e-01 2.187500e-01 +9.062500e-01 1.562500e-01 +1.000000e+00 1.875000e-01 +9.687500e-01 2.187500e-01 +8.437500e-01 2.187500e-01 +9.687500e-01 9.375000e-02 +9.687500e-01 1.562500e-01 +1.000000e+00 3.125000e-01 +9.687500e-01 3.437500e-01 +9.062500e-01 3.437500e-01 +9.687500e-01 2.812500e-01 +9.687500e-01 4.062500e-01 +8.437500e-01 2.812500e-01 +9.062500e-01 2.812500e-01 +7.500000e-01 1.000000e+00 +8.750000e-01 8.750000e-01 +8.750000e-01 7.500000e-01 +9.375000e-01 6.875000e-01 +8.125000e-01 6.875000e-01 +8.750000e-01 6.875000e-01 +1.000000e+00 8.750000e-01 +9.375000e-01 8.125000e-01 +9.375000e-01 7.500000e-01 +9.062500e-01 7.187500e-01 +9.375000e-01 6.250000e-01 +9.062500e-01 6.562500e-01 +1.000000e+00 6.875000e-01 +9.687500e-01 7.187500e-01 +6.250000e-01 8.750000e-01 +7.500000e-01 8.750000e-01 +8.125000e-01 8.125000e-01 +8.125000e-01 7.500000e-01 +8.437500e-01 7.187500e-01 +6.250000e-01 7.500000e-01 +6.875000e-01 6.875000e-01 +7.500000e-01 6.875000e-01 +7.812500e-01 7.187500e-01 +8.125000e-01 6.250000e-01 +8.437500e-01 6.562500e-01 +1.000000e+00 5.625000e-01 +9.687500e-01 5.937500e-01 +8.750000e-01 5.625000e-01 +9.062500e-01 5.937500e-01 +9.687500e-01 5.312500e-01 +9.687500e-01 6.562500e-01 +8.750000e-01 1.000000e+00 +9.375000e-01 9.375000e-01 +9.375000e-01 8.750000e-01 +1.000000e+00 8.125000e-01 +9.687500e-01 8.437500e-01 +8.750000e-01 8.125000e-01 +9.062500e-01 8.437500e-01 +9.687500e-01 7.812500e-01 +1.000000e+00 9.375000e-01 +9.687500e-01 9.062500e-01 +9.375000e-01 1.000000e+00 +9.687500e-01 9.687500e-01 +8.125000e-01 9.375000e-01 +8.750000e-01 9.375000e-01 +9.062500e-01 9.062500e-01 +8.437500e-01 7.812500e-01 +8.125000e-01 8.750000e-01 +8.437500e-01 8.437500e-01 +6.875000e-01 8.125000e-01 +7.500000e-01 8.125000e-01 +7.812500e-01 7.812500e-01 +9.062500e-01 7.812500e-01 +6.875000e-01 6.250000e-01 +7.500000e-01 5.625000e-01 +7.187500e-01 5.937500e-01 +6.250000e-01 5.625000e-01 +6.562500e-01 5.937500e-01 +7.187500e-01 5.312500e-01 +7.187500e-01 6.562500e-01 +6.875000e-01 7.500000e-01 +7.187500e-01 7.187500e-01 +5.625000e-01 6.875000e-01 +6.250000e-01 6.875000e-01 +6.562500e-01 6.562500e-01 +5.937500e-01 5.312500e-01 +5.625000e-01 6.250000e-01 +5.937500e-01 5.937500e-01 +5.000000e-01 5.625000e-01 +5.312500e-01 5.312500e-01 +6.562500e-01 5.312500e-01 +8.437500e-01 5.312500e-01 +8.437500e-01 5.937500e-01 +7.812500e-01 5.312500e-01 +9.062500e-01 5.312500e-01 +7.812500e-01 6.562500e-01 +7.812500e-01 5.937500e-01 +2.500000e-01 1.000000e+00 +3.750000e-01 8.750000e-01 +5.000000e-01 8.750000e-01 +5.625000e-01 8.125000e-01 +6.250000e-01 8.125000e-01 +5.625000e-01 7.500000e-01 +5.937500e-01 7.812500e-01 +6.250000e-01 1.000000e+00 +5.625000e-01 9.375000e-01 +5.625000e-01 8.750000e-01 +5.937500e-01 8.437500e-01 +3.750000e-01 7.500000e-01 +4.375000e-01 8.125000e-01 +5.000000e-01 8.125000e-01 +5.312500e-01 7.812500e-01 +6.562500e-01 7.812500e-01 +7.187500e-01 7.812500e-01 +6.875000e-01 9.375000e-01 +6.875000e-01 8.750000e-01 +6.562500e-01 8.437500e-01 +3.750000e-01 1.000000e+00 +4.375000e-01 9.375000e-01 +5.000000e-01 9.375000e-01 +5.312500e-01 9.062500e-01 +6.250000e-01 9.375000e-01 +5.937500e-01 9.062500e-01 +5.625000e-01 1.000000e+00 +5.312500e-01 9.687500e-01 +5.312500e-01 8.437500e-01 +4.375000e-01 6.875000e-01 +5.000000e-01 6.875000e-01 +5.312500e-01 6.562500e-01 +5.937500e-01 6.562500e-01 +5.312500e-01 7.187500e-01 +5.312500e-01 5.937500e-01 +6.562500e-01 7.187500e-01 +5.937500e-01 7.187500e-01 +7.500000e-01 9.375000e-01 +7.812500e-01 9.062500e-01 +8.437500e-01 9.062500e-01 +8.125000e-01 1.000000e+00 +7.812500e-01 9.687500e-01 +7.812500e-01 8.437500e-01 +9.062500e-01 9.687500e-01 +8.437500e-01 9.687500e-01 +6.875000e-01 1.000000e+00 +6.562500e-01 9.687500e-01 +6.562500e-01 9.062500e-01 +7.187500e-01 9.687500e-01 +5.937500e-01 9.687500e-01 +7.187500e-01 8.437500e-01 +7.187500e-01 9.062500e-01 +0.000000e+00 7.500000e-01 +1.250000e-01 8.750000e-01 +2.500000e-01 8.750000e-01 +3.125000e-01 9.375000e-01 +3.125000e-01 8.125000e-01 +3.125000e-01 8.750000e-01 +1.250000e-01 1.000000e+00 +1.875000e-01 9.375000e-01 +2.500000e-01 9.375000e-01 +2.812500e-01 9.062500e-01 +3.750000e-01 9.375000e-01 +3.437500e-01 9.062500e-01 +3.125000e-01 1.000000e+00 +2.812500e-01 9.687500e-01 +1.250000e-01 6.250000e-01 +1.250000e-01 7.500000e-01 +1.875000e-01 8.125000e-01 +2.500000e-01 8.125000e-01 +2.812500e-01 8.437500e-01 +2.500000e-01 6.250000e-01 +3.125000e-01 6.875000e-01 +3.125000e-01 7.500000e-01 +2.812500e-01 7.812500e-01 +3.750000e-01 8.125000e-01 +3.437500e-01 8.437500e-01 +4.375000e-01 1.000000e+00 +4.062500e-01 9.687500e-01 +4.375000e-01 8.750000e-01 +4.062500e-01 9.062500e-01 +4.687500e-01 9.687500e-01 +3.437500e-01 9.687500e-01 +0.000000e+00 8.750000e-01 +6.250000e-02 9.375000e-01 +1.250000e-01 9.375000e-01 +1.875000e-01 1.000000e+00 +1.562500e-01 9.687500e-01 +1.875000e-01 8.750000e-01 +1.562500e-01 9.062500e-01 +2.187500e-01 9.687500e-01 +6.250000e-02 1.000000e+00 +9.375000e-02 9.687500e-01 +0.000000e+00 9.375000e-01 +3.125000e-02 9.687500e-01 +6.250000e-02 8.125000e-01 +6.250000e-02 8.750000e-01 +9.375000e-02 9.062500e-01 +2.187500e-01 8.437500e-01 +1.250000e-01 8.125000e-01 +1.562500e-01 8.437500e-01 +1.875000e-01 6.875000e-01 +1.875000e-01 7.500000e-01 +2.187500e-01 7.812500e-01 +2.187500e-01 9.062500e-01 +3.750000e-01 6.875000e-01 +4.375000e-01 7.500000e-01 +4.062500e-01 7.187500e-01 +4.375000e-01 6.250000e-01 +4.062500e-01 6.562500e-01 +4.687500e-01 7.187500e-01 +3.437500e-01 7.187500e-01 +2.500000e-01 6.875000e-01 +2.812500e-01 7.187500e-01 +3.125000e-01 5.625000e-01 +3.125000e-01 6.250000e-01 +3.437500e-01 6.562500e-01 +4.687500e-01 5.937500e-01 +3.750000e-01 5.625000e-01 +4.062500e-01 5.937500e-01 +4.687500e-01 5.312500e-01 +4.687500e-01 6.562500e-01 +4.687500e-01 8.437500e-01 +4.062500e-01 8.437500e-01 +4.687500e-01 7.812500e-01 +4.687500e-01 9.062500e-01 +3.437500e-01 7.812500e-01 +4.062500e-01 7.812500e-01 +1.250000e-01 5.000000e-01 +1.875000e-01 5.625000e-01 +1.875000e-01 6.250000e-01 +2.500000e-01 5.625000e-01 +2.187500e-01 5.937500e-01 +0.000000e+00 6.250000e-01 +6.250000e-02 5.625000e-01 +1.250000e-01 5.625000e-01 +1.562500e-01 5.937500e-01 +1.875000e-01 4.375000e-01 +1.875000e-01 5.000000e-01 +2.187500e-01 5.312500e-01 +2.187500e-01 6.562500e-01 +2.187500e-01 7.187500e-01 +6.250000e-02 6.875000e-01 +1.250000e-01 6.875000e-01 +1.562500e-01 6.562500e-01 +0.000000e+00 3.750000e-01 +6.250000e-02 4.375000e-01 +6.250000e-02 5.000000e-01 +9.375000e-02 5.312500e-01 +6.250000e-02 6.250000e-01 +9.375000e-02 5.937500e-01 +0.000000e+00 5.625000e-01 +3.125000e-02 5.312500e-01 +1.562500e-01 5.312500e-01 +3.125000e-01 5.000000e-01 +3.437500e-01 5.312500e-01 +3.437500e-01 5.937500e-01 +2.812500e-01 5.312500e-01 +4.062500e-01 5.312500e-01 +2.812500e-01 6.562500e-01 +2.812500e-01 5.937500e-01 +6.250000e-02 7.500000e-01 +9.375000e-02 7.812500e-01 +9.375000e-02 8.437500e-01 +0.000000e+00 8.125000e-01 +3.125000e-02 7.812500e-01 +1.562500e-01 7.812500e-01 +3.125000e-02 9.062500e-01 +3.125000e-02 8.437500e-01 +0.000000e+00 6.875000e-01 +3.125000e-02 6.562500e-01 +9.375000e-02 6.562500e-01 +3.125000e-02 7.187500e-01 +3.125000e-02 5.937500e-01 +1.562500e-01 7.187500e-01 +9.375000e-02 7.187500e-01 +6.250000e-02 3.125000e-01 +1.250000e-01 3.125000e-01 +6.250000e-02 2.500000e-01 +9.375000e-02 2.812500e-01 +6.250000e-02 3.750000e-01 +9.375000e-02 3.437500e-01 +0.000000e+00 3.125000e-01 +3.125000e-02 2.812500e-01 +1.562500e-01 2.812500e-01 +2.187500e-01 2.812500e-01 +1.875000e-01 3.750000e-01 +1.562500e-01 3.437500e-01 +0.000000e+00 4.375000e-01 +3.125000e-02 4.062500e-01 +1.250000e-01 4.375000e-01 +9.375000e-02 4.062500e-01 +3.125000e-02 4.687500e-01 +3.125000e-02 3.437500e-01 +0.000000e+00 1.875000e-01 +3.125000e-02 1.562500e-01 +9.375000e-02 1.562500e-01 +3.125000e-02 2.187500e-01 +3.125000e-02 9.375000e-02 +1.562500e-01 2.187500e-01 +9.375000e-02 2.187500e-01 +2.500000e-01 4.375000e-01 +2.812500e-01 4.062500e-01 +3.437500e-01 4.062500e-01 +2.812500e-01 4.687500e-01 +2.812500e-01 3.437500e-01 +4.062500e-01 4.687500e-01 +3.437500e-01 4.687500e-01 +1.562500e-01 4.687500e-01 +1.562500e-01 4.062500e-01 +2.187500e-01 4.687500e-01 +9.375000e-02 4.687500e-01 +2.187500e-01 3.437500e-01 +2.187500e-01 4.062500e-01 + +element vertices: +26 21 33 +17 26 33 +26 12 37 +21 26 37 +32 21 41 +10 32 41 +32 17 33 +21 32 33 +45 25 46 +17 45 46 +45 7 50 +25 45 50 +26 25 53 +12 26 53 +26 17 46 +25 26 46 +36 35 57 +20 36 57 +36 12 59 +35 36 59 +56 35 61 +5 56 61 +56 20 57 +35 56 57 +40 21 62 +20 40 62 +40 10 41 +21 40 41 +36 21 37 +12 36 37 +36 20 62 +21 36 62 +67 31 70 +30 67 70 +67 16 72 +31 67 72 +69 31 73 +10 69 73 +69 30 70 +31 69 70 +77 66 78 +30 77 78 +77 4 82 +66 77 82 +67 66 85 +16 67 85 +67 30 78 +66 67 78 +71 44 86 +17 71 86 +71 16 88 +44 71 88 +45 44 91 +7 45 91 +45 17 86 +44 45 86 +32 31 92 +17 32 92 +32 10 73 +31 32 73 +71 31 72 +16 71 72 +71 17 92 +31 71 92 +95 94 97 +24 95 97 +95 23 101 +94 95 101 +96 94 103 +11 96 103 +96 24 97 +94 96 97 +49 48 104 +24 49 104 +49 7 106 +48 49 106 +95 48 109 +23 95 109 +95 24 104 +48 95 104 +100 99 111 +93 100 111 +100 23 113 +99 100 113 +110 99 115 +0 110 115 +110 93 111 +99 110 111 +102 94 116 +93 102 116 +102 11 103 +94 102 103 +100 94 101 +23 100 101 +100 93 116 +94 100 116 +58 51 118 +34 58 118 +58 12 119 +51 58 119 +117 51 120 +11 117 120 +117 34 118 +51 117 118 +60 35 121 +34 60 121 +60 5 61 +35 60 61 +58 35 59 +12 58 59 +58 34 121 +35 58 121 +52 25 122 +24 52 122 +52 12 53 +25 52 53 +49 25 50 +7 49 50 +49 24 122 +25 49 122 +96 51 123 +24 96 123 +96 11 120 +51 96 120 +52 51 119 +12 52 119 +52 24 123 +51 52 123 +129 127 133 +126 129 133 +129 19 135 +127 129 135 +132 127 137 +18 132 137 +132 126 133 +127 132 133 +141 128 142 +126 141 142 +141 9 146 +128 141 146 +129 128 148 +19 129 148 +129 126 142 +128 129 142 +134 55 150 +54 134 150 +134 19 152 +55 134 152 +149 55 153 +5 149 153 +149 54 150 +55 149 150 +136 127 154 +54 136 154 +136 18 137 +127 136 137 +134 127 135 +19 134 135 +134 54 154 +127 134 154 +157 131 159 +130 157 159 +157 125 161 +131 157 161 +158 131 162 +18 158 162 +158 130 159 +131 158 159 +163 156 164 +130 163 164 +163 1 166 +156 163 166 +157 156 169 +125 157 169 +157 130 164 +156 157 164 +160 140 170 +126 160 170 +160 125 172 +140 160 172 +141 140 175 +9 141 175 +141 126 170 +140 141 170 +132 131 176 +126 132 176 +132 18 162 +131 132 162 +160 131 161 +125 160 161 +160 126 176 +131 160 176 +177 68 179 +38 177 179 +177 29 181 +68 177 181 +178 68 182 +10 178 182 +178 38 179 +68 178 179 +145 144 183 +38 145 183 +145 9 185 +144 145 185 +177 144 188 +29 177 188 +177 38 183 +144 177 183 +180 76 189 +30 180 189 +180 29 191 +76 180 191 +77 76 194 +4 77 194 +77 30 189 +76 77 189 +69 68 195 +30 69 195 +69 10 182 +68 69 182 +180 68 181 +29 180 181 +180 30 195 +68 180 195 +151 39 196 +20 151 196 +151 19 197 +39 151 197 +40 39 198 +10 40 198 +40 20 196 +39 40 196 +56 55 199 +20 56 199 +56 5 153 +55 56 153 +151 55 152 +19 151 152 +151 20 199 +55 151 199 +147 128 200 +38 147 200 +147 19 148 +128 147 148 +145 128 146 +9 145 146 +145 38 200 +128 145 200 +178 39 201 +38 178 201 +178 10 198 +39 178 198 +147 39 197 +19 147 197 +147 38 201 +39 147 201 +206 205 208 +143 206 208 +206 138 212 +205 206 212 +207 205 216 +28 207 216 +207 143 208 +205 207 208 +184 173 217 +143 184 217 +184 9 218 +173 184 218 +206 173 221 +138 206 221 +206 143 217 +173 206 217 +211 210 225 +204 211 225 +211 138 227 +210 211 227 +224 210 229 +8 224 229 +224 204 225 +210 224 225 +215 205 230 +204 215 230 +215 28 216 +205 215 216 +211 205 212 +138 211 212 +211 204 230 +205 211 230 +190 186 233 +75 190 233 +190 29 234 +186 190 234 +232 186 235 +28 232 235 +232 75 233 +186 232 233 +193 76 236 +75 193 236 +193 4 194 +76 193 194 +190 76 191 +29 190 191 +190 75 236 +76 190 236 +187 144 237 +143 187 237 +187 29 188 +144 187 188 +184 144 185 +9 184 185 +184 143 237 +144 184 237 +207 186 238 +143 207 238 +207 28 235 +186 207 235 +187 186 234 +29 187 234 +187 143 238 +186 187 238 +171 167 240 +139 171 240 +171 125 241 +167 171 241 +239 167 243 +124 239 243 +239 139 240 +167 239 240 +174 140 244 +139 174 244 +174 9 175 +140 174 175 +171 140 172 +125 171 172 +171 139 244 +140 171 244 +168 156 245 +155 168 245 +168 125 169 +156 168 169 +165 156 166 +1 165 166 +165 155 245 +156 165 245 +242 167 246 +155 242 246 +242 124 243 +167 242 243 +168 167 241 +125 168 241 +168 155 246 +167 168 246 +226 219 248 +209 226 248 +226 138 249 +219 226 249 +247 219 250 +124 247 250 +247 209 248 +219 247 248 +228 210 251 +209 228 251 +228 8 229 +210 228 229 +226 210 227 +138 226 227 +226 209 251 +210 226 251 +220 173 252 +139 220 252 +220 138 221 +173 220 221 +174 173 218 +9 174 218 +174 139 252 +173 174 252 +239 219 253 +139 239 253 +239 124 250 +219 239 250 +220 219 249 +138 220 249 +220 139 253 +219 220 253 +259 257 263 +256 259 263 +259 203 265 +257 259 265 +262 257 267 +202 262 267 +262 256 263 +257 262 263 +271 258 272 +256 271 272 +271 27 276 +258 271 276 +259 258 278 +203 259 278 +259 256 272 +258 259 272 +264 223 280 +222 264 280 +264 203 282 +223 264 282 +279 223 283 +8 279 283 +279 222 280 +223 279 280 +266 257 284 +222 266 284 +266 202 267 +257 266 267 +264 257 265 +203 264 265 +264 222 284 +257 264 284 +287 261 289 +260 287 289 +287 255 291 +261 287 291 +288 261 292 +202 288 292 +288 260 289 +261 288 289 +293 286 294 +260 293 294 +293 2 296 +286 293 296 +287 286 299 +255 287 299 +287 260 294 +286 287 294 +290 270 300 +256 290 300 +290 255 302 +270 290 302 +271 270 305 +27 271 305 +271 256 300 +270 271 300 +262 261 306 +256 262 306 +262 202 292 +261 262 292 +290 261 291 +255 290 291 +290 256 306 +261 290 306 +307 231 309 +213 307 309 +307 74 311 +231 307 311 +308 231 312 +28 308 312 +308 213 309 +231 308 309 +275 274 313 +213 275 313 +275 27 315 +274 275 315 +307 274 318 +74 307 318 +307 213 313 +274 307 313 +310 192 319 +75 310 319 +310 74 321 +192 310 321 +193 192 323 +4 193 323 +193 75 319 +192 193 319 +232 231 324 +75 232 324 +232 28 312 +231 232 312 +310 231 311 +74 310 311 +310 75 324 +231 310 324 +281 214 325 +204 281 325 +281 203 326 +214 281 326 +215 214 327 +28 215 327 +215 204 325 +214 215 325 +224 223 328 +204 224 328 +224 8 283 +223 224 283 +281 223 282 +203 281 282 +281 204 328 +223 281 328 +277 258 329 +213 277 329 +277 203 278 +258 277 278 +275 258 276 +27 275 276 +275 213 329 +258 275 329 +308 214 330 +213 308 330 +308 28 327 +214 308 327 +277 214 326 +203 277 326 +277 213 330 +214 277 330 +335 334 337 +273 335 337 +335 268 341 +334 335 341 +336 334 345 +63 336 345 +336 273 337 +334 336 337 +314 303 346 +273 314 346 +314 27 347 +303 314 347 +335 303 350 +268 335 350 +335 273 346 +303 335 346 +340 339 354 +333 340 354 +340 268 356 +339 340 356 +353 339 358 +13 353 358 +353 333 354 +339 353 354 +344 334 359 +333 344 359 +344 63 345 +334 344 345 +340 334 341 +268 340 341 +340 333 359 +334 340 359 +320 316 362 +79 320 362 +320 74 363 +316 320 363 +361 316 364 +63 361 364 +361 79 362 +316 361 362 +322 192 365 +79 322 365 +322 4 323 +192 322 323 +320 192 321 +74 320 321 +320 79 365 +192 320 365 +317 274 366 +273 317 366 +317 74 318 +274 317 318 +314 274 315 +27 314 315 +314 273 366 +274 314 366 +336 316 367 +273 336 367 +336 63 364 +316 336 364 +317 316 363 +74 317 363 +317 273 367 +316 317 367 +301 297 369 +269 301 369 +301 255 370 +297 301 370 +368 297 372 +254 368 372 +368 269 369 +297 368 369 +304 270 373 +269 304 373 +304 27 305 +270 304 305 +301 270 302 +255 301 302 +301 269 373 +270 301 373 +298 286 374 +285 298 374 +298 255 299 +286 298 299 +295 286 296 +2 295 296 +295 285 374 +286 295 374 +371 297 375 +285 371 375 +371 254 372 +297 371 372 +298 297 370 +255 298 370 +298 285 375 +297 298 375 +355 348 377 +338 355 377 +355 268 378 +348 355 378 +376 348 379 +254 376 379 +376 338 377 +348 376 377 +357 339 380 +338 357 380 +357 13 358 +339 357 358 +355 339 356 +268 355 356 +355 338 380 +339 355 380 +349 303 381 +269 349 381 +349 268 350 +303 349 350 +304 303 347 +27 304 347 +304 269 381 +303 304 381 +368 348 382 +269 368 382 +368 254 379 +348 368 379 +349 348 378 +268 349 378 +349 269 382 +348 349 382 +388 386 392 +385 388 392 +388 332 394 +386 388 394 +391 386 396 +331 391 396 +391 385 392 +386 391 392 +400 387 401 +385 400 401 +400 14 405 +387 400 405 +388 387 407 +332 388 407 +388 385 401 +387 388 401 +393 352 409 +351 393 409 +393 332 411 +352 393 411 +408 352 412 +13 408 412 +408 351 409 +352 408 409 +395 386 413 +351 395 413 +395 331 396 +386 395 396 +393 386 394 +332 393 394 +393 351 413 +386 393 413 +416 390 418 +389 416 418 +416 384 420 +390 416 420 +417 390 421 +331 417 421 +417 389 418 +390 417 418 +422 415 423 +389 422 423 +422 3 425 +415 422 425 +416 415 428 +384 416 428 +416 389 423 +415 416 423 +419 399 429 +385 419 429 +419 384 431 +399 419 431 +400 399 434 +14 400 434 +400 385 429 +399 400 429 +391 390 435 +385 391 435 +391 331 421 +390 391 421 +419 390 420 +384 419 420 +419 385 435 +390 419 435 +436 360 438 +342 436 438 +436 64 440 +360 436 440 +437 360 441 +63 437 441 +437 342 438 +360 437 438 +404 403 442 +342 404 442 +404 14 444 +403 404 444 +436 403 447 +64 436 447 +436 342 442 +403 436 442 +439 80 448 +79 439 448 +439 64 450 +80 439 450 +322 80 451 +4 322 451 +322 79 448 +80 322 448 +361 360 452 +79 361 452 +361 63 441 +360 361 441 +439 360 440 +64 439 440 +439 79 452 +360 439 452 +410 343 453 +333 410 453 +410 332 454 +343 410 454 +344 343 455 +63 344 455 +344 333 453 +343 344 453 +353 352 456 +333 353 456 +353 13 412 +352 353 412 +410 352 411 +332 410 411 +410 333 456 +352 410 456 +406 387 457 +342 406 457 +406 332 407 +387 406 407 +404 387 405 +14 404 405 +404 342 457 +387 404 457 +437 343 458 +342 437 458 +437 63 455 +343 437 455 +406 343 454 +332 406 454 +406 342 458 +343 406 458 +461 460 463 +402 461 463 +461 397 467 +460 461 467 +462 460 470 +15 462 470 +462 402 463 +460 462 463 +443 432 471 +402 443 471 +443 14 472 +432 443 472 +461 432 475 +397 461 475 +461 402 471 +432 461 471 +466 465 479 +459 466 479 +466 397 481 +465 466 481 +478 465 483 +6 478 483 +478 459 479 +465 478 479 +469 460 484 +459 469 484 +469 15 470 +460 469 470 +466 460 467 +397 466 467 +466 459 484 +460 466 484 +449 445 486 +65 449 486 +449 64 487 +445 449 487 +485 445 488 +15 485 488 +485 65 486 +445 485 486 +81 80 489 +65 81 489 +81 4 451 +80 81 451 +449 80 450 +64 449 450 +449 65 489 +80 449 489 +446 403 490 +402 446 490 +446 64 447 +403 446 447 +443 403 444 +14 443 444 +443 402 490 +403 443 490 +462 445 491 +402 462 491 +462 15 488 +445 462 488 +446 445 487 +64 446 487 +446 402 491 +445 446 491 +430 426 493 +398 430 493 +430 384 494 +426 430 494 +492 426 496 +383 492 496 +492 398 493 +426 492 493 +433 399 497 +398 433 497 +433 14 434 +399 433 434 +430 399 431 +384 430 431 +430 398 497 +399 430 497 +427 415 498 +414 427 498 +427 384 428 +415 427 428 +424 415 425 +3 424 425 +424 414 498 +415 424 498 +495 426 499 +414 495 499 +495 383 496 +426 495 496 +427 426 494 +384 427 494 +427 414 499 +426 427 499 +480 473 501 +464 480 501 +480 397 502 +473 480 502 +500 473 503 +383 500 503 +500 464 501 +473 500 501 +482 465 504 +464 482 504 +482 6 483 +465 482 483 +480 465 481 +397 480 481 +480 464 504 +465 480 504 +474 432 505 +398 474 505 +474 397 475 +432 474 475 +433 432 472 +14 433 472 +433 398 505 +432 433 505 +492 473 506 +398 492 506 +492 383 503 +473 492 503 +474 473 502 +397 474 502 +474 398 506 +473 474 506 +508 507 510 +47 508 510 +508 42 512 +507 508 512 +509 507 514 +22 509 514 +509 47 510 +507 509 510 +105 89 515 +47 105 515 +105 7 516 +89 105 516 +508 89 518 +42 508 518 +508 47 515 +89 508 515 +511 477 520 +476 511 520 +511 42 522 +477 511 522 +519 477 523 +6 519 523 +519 476 520 +477 519 520 +513 507 524 +476 513 524 +513 22 514 +507 513 514 +511 507 512 +42 511 512 +511 476 524 +507 511 524 +112 107 526 +98 112 526 +112 23 527 +107 112 527 +525 107 528 +22 525 528 +525 98 526 +107 525 526 +114 99 529 +98 114 529 +114 0 115 +99 114 115 +112 99 113 +23 112 113 +112 98 529 +99 112 529 +108 48 530 +47 108 530 +108 23 109 +48 108 109 +105 48 106 +7 105 106 +105 47 530 +48 105 530 +509 107 531 +47 509 531 +509 22 528 +107 509 528 +108 107 527 +23 108 527 +108 47 531 +107 108 531 +87 83 533 +43 87 533 +87 16 534 +83 87 534 +532 83 535 +15 532 535 +532 43 533 +83 532 533 +90 44 536 +43 90 536 +90 7 91 +44 90 91 +87 44 88 +16 87 88 +87 43 536 +44 87 536 +84 66 537 +65 84 537 +84 16 85 +66 84 85 +81 66 82 +4 81 82 +81 65 537 +66 81 537 +485 83 538 +65 485 538 +485 15 535 +83 485 535 +84 83 534 +16 84 534 +84 65 538 +83 84 538 +521 468 539 +459 521 539 +521 42 540 +468 521 540 +469 468 541 +15 469 541 +469 459 539 +468 469 539 +478 477 542 +459 478 542 +478 6 523 +477 478 523 +521 477 522 +42 521 522 +521 459 542 +477 521 542 +517 89 543 +43 517 543 +517 42 518 +89 517 518 +90 89 516 +7 90 516 +90 43 543 +89 90 543 +532 468 544 +43 532 544 +532 15 541 +468 532 541 +517 468 540 +42 517 540 +517 43 544 +468 517 544 + +element boundaries: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element neighbours: +7 1 3 +0 6 14 +29 3 13 +2 28 0 +27 5 7 +4 26 58 +1 7 57 +6 0 4 +15 9 11 +8 14 54 +117 11 53 +10 116 8 +115 13 15 +12 114 2 +9 15 1 +14 8 12 +23 17 19 +16 22 30 +109 19 29 +18 108 16 +107 21 23 +20 106 234 +17 23 233 +22 16 20 +31 25 27 +24 30 230 +5 27 229 +26 4 24 +3 29 31 +28 2 18 +25 31 17 +30 24 28 +39 33 35 +32 38 46 +61 35 45 +34 60 32 +59 37 39 +36 58 218 +33 39 217 +38 32 36 +47 41 43 +40 46 214 +981 43 213 +42 980 40 +979 45 47 +44 978 34 +41 47 33 +46 40 44 +55 49 51 +48 54 62 +973 51 61 +50 972 48 +971 53 55 +52 970 10 +49 55 9 +54 48 52 +63 57 59 +56 62 6 +37 59 5 +58 36 56 +35 61 63 +60 34 50 +57 63 49 +62 56 60 +71 65 67 +64 70 78 +93 67 77 +66 92 64 +91 69 71 +68 90 122 +65 71 121 +70 64 68 +79 73 75 +72 78 118 +949 75 117 +74 948 72 +947 77 79 +76 946 66 +73 79 65 +78 72 76 +87 81 83 +80 86 94 +941 83 93 +82 940 80 +939 85 87 +84 938 -1 +81 87 -1 +86 80 84 +95 89 91 +88 94 -1 +69 91 -1 +90 68 88 +67 93 95 +92 66 82 +89 95 81 +94 88 92 +103 97 99 +96 102 110 +125 99 109 +98 124 96 +123 101 103 +100 122 -1 +97 103 -1 +102 96 100 +111 105 107 +104 110 -1 +21 107 -1 +106 20 104 +19 109 111 +108 18 98 +105 111 97 +110 104 108 +119 113 115 +112 118 126 +13 115 125 +114 12 112 +11 117 119 +116 10 74 +113 119 73 +118 112 116 +127 121 123 +120 126 70 +101 123 69 +122 100 120 +99 125 127 +124 98 114 +121 127 113 +126 120 124 +135 129 131 +128 134 142 +157 131 141 +130 156 128 +155 133 135 +132 154 186 +129 135 185 +134 128 132 +143 137 139 +136 142 182 +245 139 181 +138 244 136 +243 141 143 +140 242 130 +137 143 129 +142 136 140 +151 145 147 +144 150 158 +237 147 157 +146 236 144 +235 149 151 +148 234 -1 +145 151 -1 +150 144 148 +159 153 155 +152 158 -1 +133 155 -1 +154 132 152 +131 157 159 +156 130 146 +153 159 145 +158 152 156 +167 161 163 +160 166 174 +189 163 173 +162 188 160 +187 165 167 +164 186 -1 +161 167 -1 +166 160 164 +175 169 171 +168 174 -1 +341 171 -1 +170 340 168 +339 173 175 +172 338 162 +169 175 161 +174 168 172 +183 177 179 +176 182 190 +333 179 189 +178 332 176 +331 181 183 +180 330 138 +177 183 137 +182 176 180 +191 185 187 +184 190 134 +165 187 133 +186 164 184 +163 189 191 +188 162 178 +185 191 177 +190 184 188 +199 193 195 +192 198 206 +221 195 205 +194 220 192 +219 197 199 +196 218 250 +193 199 249 +198 192 196 +207 201 203 +200 206 246 +309 203 245 +202 308 200 +307 205 207 +204 306 194 +201 207 193 +206 200 204 +215 209 211 +208 214 222 +301 211 221 +210 300 208 +299 213 215 +212 298 42 +209 215 41 +214 208 212 +223 217 219 +216 222 38 +197 219 37 +218 196 216 +195 221 223 +220 194 210 +217 223 209 +222 216 220 +231 225 227 +224 230 238 +253 227 237 +226 252 224 +251 229 231 +228 250 26 +225 231 25 +230 224 228 +239 233 235 +232 238 22 +149 235 21 +234 148 232 +147 237 239 +236 146 226 +233 239 225 +238 232 236 +247 241 243 +240 246 254 +141 243 253 +242 140 240 +139 245 247 +244 138 202 +241 247 201 +246 240 244 +255 249 251 +248 254 198 +229 251 197 +250 228 248 +227 253 255 +252 226 242 +249 255 241 +254 248 252 +263 257 259 +256 262 270 +285 259 269 +258 284 256 +283 261 263 +260 282 314 +257 263 313 +262 256 260 +271 265 267 +264 270 310 +373 267 309 +266 372 264 +371 269 271 +268 370 258 +265 271 257 +270 264 268 +279 273 275 +272 278 286 +365 275 285 +274 364 272 +363 277 279 +276 362 490 +273 279 489 +278 272 276 +287 281 283 +280 286 486 +261 283 485 +282 260 280 +259 285 287 +284 258 274 +281 287 273 +286 280 284 +295 289 291 +288 294 302 +317 291 301 +290 316 288 +315 293 295 +292 314 474 +289 295 473 +294 288 292 +303 297 299 +296 302 470 +213 299 469 +298 212 296 +211 301 303 +300 210 290 +297 303 289 +302 296 300 +311 305 307 +304 310 318 +205 307 317 +306 204 304 +203 309 311 +308 202 266 +305 311 265 +310 304 308 +319 313 315 +312 318 262 +293 315 261 +314 292 312 +291 317 319 +316 290 306 +313 319 305 +318 312 316 +327 321 323 +320 326 334 +349 323 333 +322 348 320 +347 325 327 +324 346 378 +321 327 377 +326 320 324 +335 329 331 +328 334 374 +181 331 373 +330 180 328 +179 333 335 +332 178 322 +329 335 321 +334 328 332 +343 337 339 +336 342 350 +173 339 349 +338 172 336 +171 341 343 +340 170 -1 +337 343 -1 +342 336 340 +351 345 347 +344 350 -1 +325 347 -1 +346 324 344 +323 349 351 +348 322 338 +345 351 337 +350 344 348 +359 353 355 +352 358 366 +381 355 365 +354 380 352 +379 357 359 +356 378 -1 +353 359 -1 +358 352 356 +367 361 363 +360 366 -1 +277 363 -1 +362 276 360 +275 365 367 +364 274 354 +361 367 353 +366 360 364 +375 369 371 +368 374 382 +269 371 381 +370 268 368 +267 373 375 +372 266 330 +369 375 329 +374 368 372 +383 377 379 +376 382 326 +357 379 325 +378 356 376 +355 381 383 +380 354 370 +377 383 369 +382 376 380 +391 385 387 +384 390 398 +413 387 397 +386 412 384 +411 389 391 +388 410 442 +385 391 441 +390 384 388 +399 393 395 +392 398 438 +501 395 437 +394 500 392 +499 397 399 +396 498 386 +393 399 385 +398 392 396 +407 401 403 +400 406 414 +493 403 413 +402 492 400 +491 405 407 +404 490 -1 +401 407 -1 +406 400 404 +415 409 411 +408 414 -1 +389 411 -1 +410 388 408 +387 413 415 +412 386 402 +409 415 401 +414 408 412 +423 417 419 +416 422 430 +445 419 429 +418 444 416 +443 421 423 +420 442 -1 +417 423 -1 +422 416 420 +431 425 427 +424 430 -1 +597 427 -1 +426 596 424 +595 429 431 +428 594 418 +425 431 417 +430 424 428 +439 433 435 +432 438 446 +589 435 445 +434 588 432 +587 437 439 +436 586 394 +433 439 393 +438 432 436 +447 441 443 +440 446 390 +421 443 389 +442 420 440 +419 445 447 +444 418 434 +441 447 433 +446 440 444 +455 449 451 +448 454 462 +477 451 461 +450 476 448 +475 453 455 +452 474 506 +449 455 505 +454 448 452 +463 457 459 +456 462 502 +565 459 501 +458 564 456 +563 461 463 +460 562 450 +457 463 449 +462 456 460 +471 465 467 +464 470 478 +557 467 477 +466 556 464 +555 469 471 +468 554 298 +465 471 297 +470 464 468 +479 473 475 +472 478 294 +453 475 293 +474 452 472 +451 477 479 +476 450 466 +473 479 465 +478 472 476 +487 481 483 +480 486 494 +509 483 493 +482 508 480 +507 485 487 +484 506 282 +481 487 281 +486 480 484 +495 489 491 +488 494 278 +405 491 277 +490 404 488 +403 493 495 +492 402 482 +489 495 481 +494 488 492 +503 497 499 +496 502 510 +397 499 509 +498 396 496 +395 501 503 +500 394 458 +497 503 457 +502 496 500 +511 505 507 +504 510 454 +485 507 453 +506 484 504 +483 509 511 +508 482 498 +505 511 497 +510 504 508 +519 513 515 +512 518 526 +541 515 525 +514 540 512 +539 517 519 +516 538 570 +513 519 569 +518 512 516 +527 521 523 +520 526 566 +629 523 565 +522 628 520 +627 525 527 +524 626 514 +521 527 513 +526 520 524 +535 529 531 +528 534 542 +621 531 541 +530 620 528 +619 533 535 +532 618 746 +529 535 745 +534 528 532 +543 537 539 +536 542 742 +517 539 741 +538 516 536 +515 541 543 +540 514 530 +537 543 529 +542 536 540 +551 545 547 +544 550 558 +573 547 557 +546 572 544 +571 549 551 +548 570 730 +545 551 729 +550 544 548 +559 553 555 +552 558 726 +469 555 725 +554 468 552 +467 557 559 +556 466 546 +553 559 545 +558 552 556 +567 561 563 +560 566 574 +461 563 573 +562 460 560 +459 565 567 +564 458 522 +561 567 521 +566 560 564 +575 569 571 +568 574 518 +549 571 517 +570 548 568 +547 573 575 +572 546 562 +569 575 561 +574 568 572 +583 577 579 +576 582 590 +605 579 589 +578 604 576 +603 581 583 +580 602 634 +577 583 633 +582 576 580 +591 585 587 +584 590 630 +437 587 629 +586 436 584 +435 589 591 +588 434 578 +585 591 577 +590 584 588 +599 593 595 +592 598 606 +429 595 605 +594 428 592 +427 597 599 +596 426 -1 +593 599 -1 +598 592 596 +607 601 603 +600 606 -1 +581 603 -1 +602 580 600 +579 605 607 +604 578 594 +601 607 593 +606 600 604 +615 609 611 +608 614 622 +637 611 621 +610 636 608 +635 613 615 +612 634 -1 +609 615 -1 +614 608 612 +623 617 619 +616 622 -1 +533 619 -1 +618 532 616 +531 621 623 +620 530 610 +617 623 609 +622 616 620 +631 625 627 +624 630 638 +525 627 637 +626 524 624 +523 629 631 +628 522 586 +625 631 585 +630 624 628 +639 633 635 +632 638 582 +613 635 581 +634 612 632 +611 637 639 +636 610 626 +633 639 625 +638 632 636 +647 641 643 +640 646 654 +669 643 653 +642 668 640 +667 645 647 +644 666 698 +641 647 697 +646 640 644 +655 649 651 +648 654 694 +757 651 693 +650 756 648 +755 653 655 +652 754 642 +649 655 641 +654 648 652 +663 657 659 +656 662 670 +749 659 669 +658 748 656 +747 661 663 +660 746 -1 +657 663 -1 +662 656 660 +671 665 667 +664 670 -1 +645 667 -1 +666 644 664 +643 669 671 +668 642 658 +665 671 657 +670 664 668 +679 673 675 +672 678 686 +701 675 685 +674 700 672 +699 677 679 +676 698 -1 +673 679 -1 +678 672 676 +687 681 683 +680 686 -1 +853 683 -1 +682 852 680 +851 685 687 +684 850 674 +681 687 673 +686 680 684 +695 689 691 +688 694 702 +845 691 701 +690 844 688 +843 693 695 +692 842 650 +689 695 649 +694 688 692 +703 697 699 +696 702 646 +677 699 645 +698 676 696 +675 701 703 +700 674 690 +697 703 689 +702 696 700 +711 705 707 +704 710 718 +733 707 717 +706 732 704 +731 709 711 +708 730 762 +705 711 761 +710 704 708 +719 713 715 +712 718 758 +821 715 757 +714 820 712 +819 717 719 +716 818 706 +713 719 705 +718 712 716 +727 721 723 +720 726 734 +813 723 733 +722 812 720 +811 725 727 +724 810 554 +721 727 553 +726 720 724 +735 729 731 +728 734 550 +709 731 549 +730 708 728 +707 733 735 +732 706 722 +729 735 721 +734 728 732 +743 737 739 +736 742 750 +765 739 749 +738 764 736 +763 741 743 +740 762 538 +737 743 537 +742 736 740 +751 745 747 +744 750 534 +661 747 533 +746 660 744 +659 749 751 +748 658 738 +745 751 737 +750 744 748 +759 753 755 +752 758 766 +653 755 765 +754 652 752 +651 757 759 +756 650 714 +753 759 713 +758 752 756 +767 761 763 +760 766 710 +741 763 709 +762 740 760 +739 765 767 +764 738 754 +761 767 753 +766 760 764 +775 769 771 +768 774 782 +797 771 781 +770 796 768 +795 773 775 +772 794 826 +769 775 825 +774 768 772 +783 777 779 +776 782 822 +885 779 821 +778 884 776 +883 781 783 +780 882 770 +777 783 769 +782 776 780 +791 785 787 +784 790 798 +877 787 797 +786 876 784 +875 789 791 +788 874 1002 +785 791 1001 +790 784 788 +799 793 795 +792 798 998 +773 795 997 +794 772 792 +771 797 799 +796 770 786 +793 799 785 +798 792 796 +807 801 803 +800 806 814 +829 803 813 +802 828 800 +827 805 807 +804 826 986 +801 807 985 +806 800 804 +815 809 811 +808 814 982 +725 811 981 +810 724 808 +723 813 815 +812 722 802 +809 815 801 +814 808 812 +823 817 819 +816 822 830 +717 819 829 +818 716 816 +715 821 823 +820 714 778 +817 823 777 +822 816 820 +831 825 827 +824 830 774 +805 827 773 +826 804 824 +803 829 831 +828 802 818 +825 831 817 +830 824 828 +839 833 835 +832 838 846 +861 835 845 +834 860 832 +859 837 839 +836 858 890 +833 839 889 +838 832 836 +847 841 843 +840 846 886 +693 843 885 +842 692 840 +691 845 847 +844 690 834 +841 847 833 +846 840 844 +855 849 851 +848 854 862 +685 851 861 +850 684 848 +683 853 855 +852 682 -1 +849 855 -1 +854 848 852 +863 857 859 +856 862 -1 +837 859 -1 +858 836 856 +835 861 863 +860 834 850 +857 863 849 +862 856 860 +871 865 867 +864 870 878 +893 867 877 +866 892 864 +891 869 871 +868 890 -1 +865 871 -1 +870 864 868 +879 873 875 +872 878 -1 +789 875 -1 +874 788 872 +787 877 879 +876 786 866 +873 879 865 +878 872 876 +887 881 883 +880 886 894 +781 883 893 +882 780 880 +779 885 887 +884 778 842 +881 887 841 +886 880 884 +895 889 891 +888 894 838 +869 891 837 +890 868 888 +867 893 895 +892 866 882 +889 895 881 +894 888 892 +903 897 899 +896 902 910 +925 899 909 +898 924 896 +923 901 903 +900 922 954 +897 903 953 +902 896 900 +911 905 907 +904 910 950 +1013 907 949 +906 1012 904 +1011 909 911 +908 1010 898 +905 911 897 +910 904 908 +919 913 915 +912 918 926 +1005 915 925 +914 1004 912 +1003 917 919 +916 1002 -1 +913 919 -1 +918 912 916 +927 921 923 +920 926 -1 +901 923 -1 +922 900 920 +899 925 927 +924 898 914 +921 927 913 +926 920 924 +935 929 931 +928 934 942 +957 931 941 +930 956 928 +955 933 935 +932 954 -1 +929 935 -1 +934 928 932 +943 937 939 +936 942 -1 +85 939 -1 +938 84 936 +83 941 943 +940 82 930 +937 943 929 +942 936 940 +951 945 947 +944 950 958 +77 947 957 +946 76 944 +75 949 951 +948 74 906 +945 951 905 +950 944 948 +959 953 955 +952 958 902 +933 955 901 +954 932 952 +931 957 959 +956 930 946 +953 959 945 +958 952 956 +967 961 963 +960 966 974 +989 963 973 +962 988 960 +987 965 967 +964 986 1018 +961 967 1017 +966 960 964 +975 969 971 +968 974 1014 +53 971 1013 +970 52 968 +51 973 975 +972 50 962 +969 975 961 +974 968 972 +983 977 979 +976 982 990 +45 979 989 +978 44 976 +43 981 983 +980 42 810 +977 983 809 +982 976 980 +991 985 987 +984 990 806 +965 987 805 +986 964 984 +963 989 991 +988 962 978 +985 991 977 +990 984 988 +999 993 995 +992 998 1006 +1021 995 1005 +994 1020 992 +1019 997 999 +996 1018 794 +993 999 793 +998 992 996 +1007 1001 1003 +1000 1006 790 +917 1003 789 +1002 916 1000 +915 1005 1007 +1004 914 994 +1001 1007 993 +1006 1000 1004 +1015 1009 1011 +1008 1014 1022 +909 1011 1021 +1010 908 1008 +907 1013 1015 +1012 906 970 +1009 1015 969 +1014 1008 1012 +1023 1017 1019 +1016 1022 966 +997 1019 965 +1018 996 1016 +995 1021 1023 +1020 994 1010 +1017 1023 1009 +1022 1016 1020 + +projections: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element region: +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 + +surface region: +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 diff --git a/extensions/demo/multimesh/macro/macro_corner_1x1.2d.801668.tmp b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.801668.tmp new file mode 100644 index 00000000..f152f950 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.801668.tmp @@ -0,0 +1,6708 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 545 +number of elements: 1024 + +vertex coordinates: +0.000000e+00 0.000000e+00 +1.000000e+00 0.000000e+00 +1.000000e+00 1.000000e+00 +0.000000e+00 1.000000e+00 +5.000000e-01 5.000000e-01 +5.000000e-01 0.000000e+00 +0.000000e+00 5.000000e-01 +2.500000e-01 2.500000e-01 +1.000000e+00 5.000000e-01 +7.500000e-01 2.500000e-01 +5.000000e-01 2.500000e-01 +2.500000e-01 0.000000e+00 +3.750000e-01 1.250000e-01 +5.000000e-01 1.000000e+00 +2.500000e-01 7.500000e-01 +2.500000e-01 5.000000e-01 +3.750000e-01 3.750000e-01 +3.750000e-01 2.500000e-01 +7.500000e-01 0.000000e+00 +6.250000e-01 1.250000e-01 +5.000000e-01 1.250000e-01 +4.375000e-01 1.875000e-01 +0.000000e+00 2.500000e-01 +1.250000e-01 1.250000e-01 +2.500000e-01 1.250000e-01 +3.125000e-01 1.875000e-01 +3.750000e-01 1.875000e-01 +7.500000e-01 7.500000e-01 +7.500000e-01 5.000000e-01 +6.250000e-01 3.750000e-01 +5.000000e-01 3.750000e-01 +4.375000e-01 3.125000e-01 +4.375000e-01 2.500000e-01 +4.062500e-01 2.187500e-01 +3.750000e-01 0.000000e+00 +4.375000e-01 6.250000e-02 +4.375000e-01 1.250000e-01 +4.062500e-01 1.562500e-01 +6.250000e-01 2.500000e-01 +5.625000e-01 1.875000e-01 +5.000000e-01 1.875000e-01 +4.687500e-01 2.187500e-01 +1.250000e-01 3.750000e-01 +2.500000e-01 3.750000e-01 +3.125000e-01 3.125000e-01 +3.125000e-01 2.500000e-01 +3.437500e-01 2.187500e-01 +1.250000e-01 2.500000e-01 +1.875000e-01 1.875000e-01 +2.500000e-01 1.875000e-01 +2.812500e-01 2.187500e-01 +3.125000e-01 6.250000e-02 +3.125000e-01 1.250000e-01 +3.437500e-01 1.562500e-01 +6.250000e-01 0.000000e+00 +5.625000e-01 6.250000e-02 +5.000000e-01 6.250000e-02 +4.687500e-01 9.375000e-02 +3.750000e-01 6.250000e-02 +4.062500e-01 9.375000e-02 +4.375000e-01 0.000000e+00 +4.687500e-01 3.125000e-02 +4.687500e-01 1.562500e-01 +5.000000e-01 7.500000e-01 +3.750000e-01 6.250000e-01 +3.750000e-01 5.000000e-01 +4.375000e-01 4.375000e-01 +4.375000e-01 3.750000e-01 +5.625000e-01 3.125000e-01 +5.000000e-01 3.125000e-01 +4.687500e-01 3.437500e-01 +3.750000e-01 3.125000e-01 +4.062500e-01 3.437500e-01 +4.687500e-01 2.812500e-01 +6.250000e-01 6.250000e-01 +6.250000e-01 5.000000e-01 +5.625000e-01 4.375000e-01 +5.000000e-01 4.375000e-01 +4.687500e-01 4.062500e-01 +5.000000e-01 6.250000e-01 +4.375000e-01 5.625000e-01 +4.375000e-01 5.000000e-01 +4.687500e-01 4.687500e-01 +3.125000e-01 4.375000e-01 +3.750000e-01 4.375000e-01 +4.062500e-01 4.062500e-01 +3.437500e-01 2.812500e-01 +3.125000e-01 3.750000e-01 +3.437500e-01 3.437500e-01 +1.875000e-01 3.125000e-01 +2.500000e-01 3.125000e-01 +2.812500e-01 2.812500e-01 +4.062500e-01 2.812500e-01 +1.250000e-01 0.000000e+00 +1.875000e-01 6.250000e-02 +1.875000e-01 1.250000e-01 +2.500000e-01 6.250000e-02 +2.187500e-01 9.375000e-02 +0.000000e+00 1.250000e-01 +6.250000e-02 6.250000e-02 +1.250000e-01 6.250000e-02 +1.562500e-01 9.375000e-02 +1.875000e-01 0.000000e+00 +2.187500e-01 3.125000e-02 +2.187500e-01 1.562500e-01 +1.875000e-01 2.500000e-01 +2.187500e-01 2.187500e-01 +6.250000e-02 1.875000e-01 +1.250000e-01 1.875000e-01 +1.562500e-01 1.562500e-01 +6.250000e-02 0.000000e+00 +9.375000e-02 3.125000e-02 +6.250000e-02 1.250000e-01 +9.375000e-02 9.375000e-02 +0.000000e+00 6.250000e-02 +3.125000e-02 3.125000e-02 +1.562500e-01 3.125000e-02 +3.125000e-01 0.000000e+00 +3.437500e-01 3.125000e-02 +3.437500e-01 9.375000e-02 +2.812500e-01 3.125000e-02 +4.062500e-01 3.125000e-02 +2.812500e-01 1.562500e-01 +2.812500e-01 9.375000e-02 +1.000000e+00 2.500000e-01 +8.750000e-01 1.250000e-01 +7.500000e-01 1.250000e-01 +6.875000e-01 6.250000e-02 +6.875000e-01 1.875000e-01 +6.875000e-01 1.250000e-01 +8.750000e-01 0.000000e+00 +8.125000e-01 6.250000e-02 +7.500000e-01 6.250000e-02 +7.187500e-01 9.375000e-02 +6.250000e-01 6.250000e-02 +6.562500e-01 9.375000e-02 +6.875000e-01 0.000000e+00 +7.187500e-01 3.125000e-02 +8.750000e-01 3.750000e-01 +8.750000e-01 2.500000e-01 +8.125000e-01 1.875000e-01 +7.500000e-01 1.875000e-01 +7.187500e-01 1.562500e-01 +7.500000e-01 3.750000e-01 +6.875000e-01 3.125000e-01 +6.875000e-01 2.500000e-01 +7.187500e-01 2.187500e-01 +6.250000e-01 1.875000e-01 +6.562500e-01 1.562500e-01 +5.625000e-01 0.000000e+00 +5.937500e-01 3.125000e-02 +5.625000e-01 1.250000e-01 +5.937500e-01 9.375000e-02 +5.312500e-01 3.125000e-02 +6.562500e-01 3.125000e-02 +1.000000e+00 1.250000e-01 +9.375000e-01 6.250000e-02 +8.750000e-01 6.250000e-02 +8.125000e-01 0.000000e+00 +8.437500e-01 3.125000e-02 +8.125000e-01 1.250000e-01 +8.437500e-01 9.375000e-02 +7.812500e-01 3.125000e-02 +9.375000e-01 0.000000e+00 +9.062500e-01 3.125000e-02 +1.000000e+00 6.250000e-02 +9.687500e-01 3.125000e-02 +9.375000e-01 1.875000e-01 +9.375000e-01 1.250000e-01 +9.062500e-01 9.375000e-02 +7.812500e-01 1.562500e-01 +8.750000e-01 1.875000e-01 +8.437500e-01 1.562500e-01 +8.125000e-01 3.125000e-01 +8.125000e-01 2.500000e-01 +7.812500e-01 2.187500e-01 +7.812500e-01 9.375000e-02 +6.250000e-01 3.125000e-01 +5.625000e-01 2.500000e-01 +5.937500e-01 2.812500e-01 +5.625000e-01 3.750000e-01 +5.937500e-01 3.437500e-01 +5.312500e-01 2.812500e-01 +6.562500e-01 2.812500e-01 +7.500000e-01 3.125000e-01 +7.187500e-01 2.812500e-01 +6.875000e-01 4.375000e-01 +6.875000e-01 3.750000e-01 +6.562500e-01 3.437500e-01 +5.312500e-01 4.062500e-01 +6.250000e-01 4.375000e-01 +5.937500e-01 4.062500e-01 +5.625000e-01 5.625000e-01 +5.625000e-01 5.000000e-01 +5.312500e-01 4.687500e-01 +5.312500e-01 3.437500e-01 +5.312500e-01 1.562500e-01 +5.937500e-01 1.562500e-01 +5.312500e-01 2.187500e-01 +5.312500e-01 9.375000e-02 +6.562500e-01 2.187500e-01 +5.937500e-01 2.187500e-01 +1.000000e+00 7.500000e-01 +8.750000e-01 6.250000e-01 +8.750000e-01 5.000000e-01 +8.125000e-01 4.375000e-01 +8.125000e-01 3.750000e-01 +7.500000e-01 4.375000e-01 +7.812500e-01 4.062500e-01 +1.000000e+00 3.750000e-01 +9.375000e-01 4.375000e-01 +8.750000e-01 4.375000e-01 +8.437500e-01 4.062500e-01 +7.500000e-01 6.250000e-01 +8.125000e-01 5.625000e-01 +8.125000e-01 5.000000e-01 +7.812500e-01 4.687500e-01 +7.812500e-01 3.437500e-01 +7.812500e-01 2.812500e-01 +9.375000e-01 3.125000e-01 +8.750000e-01 3.125000e-01 +8.437500e-01 3.437500e-01 +1.000000e+00 6.250000e-01 +9.375000e-01 5.625000e-01 +9.375000e-01 5.000000e-01 +9.062500e-01 4.687500e-01 +9.375000e-01 3.750000e-01 +9.062500e-01 4.062500e-01 +1.000000e+00 4.375000e-01 +9.687500e-01 4.687500e-01 +8.437500e-01 4.687500e-01 +6.875000e-01 5.625000e-01 +6.875000e-01 5.000000e-01 +6.562500e-01 4.687500e-01 +6.562500e-01 4.062500e-01 +7.187500e-01 4.687500e-01 +5.937500e-01 4.687500e-01 +7.187500e-01 3.437500e-01 +7.187500e-01 4.062500e-01 +9.375000e-01 2.500000e-01 +9.062500e-01 2.187500e-01 +9.062500e-01 1.562500e-01 +1.000000e+00 1.875000e-01 +9.687500e-01 2.187500e-01 +8.437500e-01 2.187500e-01 +9.687500e-01 9.375000e-02 +9.687500e-01 1.562500e-01 +1.000000e+00 3.125000e-01 +9.687500e-01 3.437500e-01 +9.062500e-01 3.437500e-01 +9.687500e-01 2.812500e-01 +9.687500e-01 4.062500e-01 +8.437500e-01 2.812500e-01 +9.062500e-01 2.812500e-01 +7.500000e-01 1.000000e+00 +8.750000e-01 8.750000e-01 +8.750000e-01 7.500000e-01 +9.375000e-01 6.875000e-01 +8.125000e-01 6.875000e-01 +8.750000e-01 6.875000e-01 +1.000000e+00 8.750000e-01 +9.375000e-01 8.125000e-01 +9.375000e-01 7.500000e-01 +9.062500e-01 7.187500e-01 +9.375000e-01 6.250000e-01 +9.062500e-01 6.562500e-01 +1.000000e+00 6.875000e-01 +9.687500e-01 7.187500e-01 +6.250000e-01 8.750000e-01 +7.500000e-01 8.750000e-01 +8.125000e-01 8.125000e-01 +8.125000e-01 7.500000e-01 +8.437500e-01 7.187500e-01 +6.250000e-01 7.500000e-01 +6.875000e-01 6.875000e-01 +7.500000e-01 6.875000e-01 +7.812500e-01 7.187500e-01 +8.125000e-01 6.250000e-01 +8.437500e-01 6.562500e-01 +1.000000e+00 5.625000e-01 +9.687500e-01 5.937500e-01 +8.750000e-01 5.625000e-01 +9.062500e-01 5.937500e-01 +9.687500e-01 5.312500e-01 +9.687500e-01 6.562500e-01 +8.750000e-01 1.000000e+00 +9.375000e-01 9.375000e-01 +9.375000e-01 8.750000e-01 +1.000000e+00 8.125000e-01 +9.687500e-01 8.437500e-01 +8.750000e-01 8.125000e-01 +9.062500e-01 8.437500e-01 +9.687500e-01 7.812500e-01 +1.000000e+00 9.375000e-01 +9.687500e-01 9.062500e-01 +9.375000e-01 1.000000e+00 +9.687500e-01 9.687500e-01 +8.125000e-01 9.375000e-01 +8.750000e-01 9.375000e-01 +9.062500e-01 9.062500e-01 +8.437500e-01 7.812500e-01 +8.125000e-01 8.750000e-01 +8.437500e-01 8.437500e-01 +6.875000e-01 8.125000e-01 +7.500000e-01 8.125000e-01 +7.812500e-01 7.812500e-01 +9.062500e-01 7.812500e-01 +6.875000e-01 6.250000e-01 +7.500000e-01 5.625000e-01 +7.187500e-01 5.937500e-01 +6.250000e-01 5.625000e-01 +6.562500e-01 5.937500e-01 +7.187500e-01 5.312500e-01 +7.187500e-01 6.562500e-01 +6.875000e-01 7.500000e-01 +7.187500e-01 7.187500e-01 +5.625000e-01 6.875000e-01 +6.250000e-01 6.875000e-01 +6.562500e-01 6.562500e-01 +5.937500e-01 5.312500e-01 +5.625000e-01 6.250000e-01 +5.937500e-01 5.937500e-01 +5.000000e-01 5.625000e-01 +5.312500e-01 5.312500e-01 +6.562500e-01 5.312500e-01 +8.437500e-01 5.312500e-01 +8.437500e-01 5.937500e-01 +7.812500e-01 5.312500e-01 +9.062500e-01 5.312500e-01 +7.812500e-01 6.562500e-01 +7.812500e-01 5.937500e-01 +2.500000e-01 1.000000e+00 +3.750000e-01 8.750000e-01 +5.000000e-01 8.750000e-01 +5.625000e-01 8.125000e-01 +6.250000e-01 8.125000e-01 +5.625000e-01 7.500000e-01 +5.937500e-01 7.812500e-01 +6.250000e-01 1.000000e+00 +5.625000e-01 9.375000e-01 +5.625000e-01 8.750000e-01 +5.937500e-01 8.437500e-01 +3.750000e-01 7.500000e-01 +4.375000e-01 8.125000e-01 +5.000000e-01 8.125000e-01 +5.312500e-01 7.812500e-01 +6.562500e-01 7.812500e-01 +7.187500e-01 7.812500e-01 +6.875000e-01 9.375000e-01 +6.875000e-01 8.750000e-01 +6.562500e-01 8.437500e-01 +3.750000e-01 1.000000e+00 +4.375000e-01 9.375000e-01 +5.000000e-01 9.375000e-01 +5.312500e-01 9.062500e-01 +6.250000e-01 9.375000e-01 +5.937500e-01 9.062500e-01 +5.625000e-01 1.000000e+00 +5.312500e-01 9.687500e-01 +5.312500e-01 8.437500e-01 +4.375000e-01 6.875000e-01 +5.000000e-01 6.875000e-01 +5.312500e-01 6.562500e-01 +5.937500e-01 6.562500e-01 +5.312500e-01 7.187500e-01 +5.312500e-01 5.937500e-01 +6.562500e-01 7.187500e-01 +5.937500e-01 7.187500e-01 +7.500000e-01 9.375000e-01 +7.812500e-01 9.062500e-01 +8.437500e-01 9.062500e-01 +8.125000e-01 1.000000e+00 +7.812500e-01 9.687500e-01 +7.812500e-01 8.437500e-01 +9.062500e-01 9.687500e-01 +8.437500e-01 9.687500e-01 +6.875000e-01 1.000000e+00 +6.562500e-01 9.687500e-01 +6.562500e-01 9.062500e-01 +7.187500e-01 9.687500e-01 +5.937500e-01 9.687500e-01 +7.187500e-01 8.437500e-01 +7.187500e-01 9.062500e-01 +0.000000e+00 7.500000e-01 +1.250000e-01 8.750000e-01 +2.500000e-01 8.750000e-01 +3.125000e-01 9.375000e-01 +3.125000e-01 8.125000e-01 +3.125000e-01 8.750000e-01 +1.250000e-01 1.000000e+00 +1.875000e-01 9.375000e-01 +2.500000e-01 9.375000e-01 +2.812500e-01 9.062500e-01 +3.750000e-01 9.375000e-01 +3.437500e-01 9.062500e-01 +3.125000e-01 1.000000e+00 +2.812500e-01 9.687500e-01 +1.250000e-01 6.250000e-01 +1.250000e-01 7.500000e-01 +1.875000e-01 8.125000e-01 +2.500000e-01 8.125000e-01 +2.812500e-01 8.437500e-01 +2.500000e-01 6.250000e-01 +3.125000e-01 6.875000e-01 +3.125000e-01 7.500000e-01 +2.812500e-01 7.812500e-01 +3.750000e-01 8.125000e-01 +3.437500e-01 8.437500e-01 +4.375000e-01 1.000000e+00 +4.062500e-01 9.687500e-01 +4.375000e-01 8.750000e-01 +4.062500e-01 9.062500e-01 +4.687500e-01 9.687500e-01 +3.437500e-01 9.687500e-01 +0.000000e+00 8.750000e-01 +6.250000e-02 9.375000e-01 +1.250000e-01 9.375000e-01 +1.875000e-01 1.000000e+00 +1.562500e-01 9.687500e-01 +1.875000e-01 8.750000e-01 +1.562500e-01 9.062500e-01 +2.187500e-01 9.687500e-01 +6.250000e-02 1.000000e+00 +9.375000e-02 9.687500e-01 +0.000000e+00 9.375000e-01 +3.125000e-02 9.687500e-01 +6.250000e-02 8.125000e-01 +6.250000e-02 8.750000e-01 +9.375000e-02 9.062500e-01 +2.187500e-01 8.437500e-01 +1.250000e-01 8.125000e-01 +1.562500e-01 8.437500e-01 +1.875000e-01 6.875000e-01 +1.875000e-01 7.500000e-01 +2.187500e-01 7.812500e-01 +2.187500e-01 9.062500e-01 +3.750000e-01 6.875000e-01 +4.375000e-01 7.500000e-01 +4.062500e-01 7.187500e-01 +4.375000e-01 6.250000e-01 +4.062500e-01 6.562500e-01 +4.687500e-01 7.187500e-01 +3.437500e-01 7.187500e-01 +2.500000e-01 6.875000e-01 +2.812500e-01 7.187500e-01 +3.125000e-01 5.625000e-01 +3.125000e-01 6.250000e-01 +3.437500e-01 6.562500e-01 +4.687500e-01 5.937500e-01 +3.750000e-01 5.625000e-01 +4.062500e-01 5.937500e-01 +4.687500e-01 5.312500e-01 +4.687500e-01 6.562500e-01 +4.687500e-01 8.437500e-01 +4.062500e-01 8.437500e-01 +4.687500e-01 7.812500e-01 +4.687500e-01 9.062500e-01 +3.437500e-01 7.812500e-01 +4.062500e-01 7.812500e-01 +1.250000e-01 5.000000e-01 +1.875000e-01 5.625000e-01 +1.875000e-01 6.250000e-01 +2.500000e-01 5.625000e-01 +2.187500e-01 5.937500e-01 +0.000000e+00 6.250000e-01 +6.250000e-02 5.625000e-01 +1.250000e-01 5.625000e-01 +1.562500e-01 5.937500e-01 +1.875000e-01 4.375000e-01 +1.875000e-01 5.000000e-01 +2.187500e-01 5.312500e-01 +2.187500e-01 6.562500e-01 +2.187500e-01 7.187500e-01 +6.250000e-02 6.875000e-01 +1.250000e-01 6.875000e-01 +1.562500e-01 6.562500e-01 +0.000000e+00 3.750000e-01 +6.250000e-02 4.375000e-01 +6.250000e-02 5.000000e-01 +9.375000e-02 5.312500e-01 +6.250000e-02 6.250000e-01 +9.375000e-02 5.937500e-01 +0.000000e+00 5.625000e-01 +3.125000e-02 5.312500e-01 +1.562500e-01 5.312500e-01 +3.125000e-01 5.000000e-01 +3.437500e-01 5.312500e-01 +3.437500e-01 5.937500e-01 +2.812500e-01 5.312500e-01 +4.062500e-01 5.312500e-01 +2.812500e-01 6.562500e-01 +2.812500e-01 5.937500e-01 +6.250000e-02 7.500000e-01 +9.375000e-02 7.812500e-01 +9.375000e-02 8.437500e-01 +0.000000e+00 8.125000e-01 +3.125000e-02 7.812500e-01 +1.562500e-01 7.812500e-01 +3.125000e-02 9.062500e-01 +3.125000e-02 8.437500e-01 +0.000000e+00 6.875000e-01 +3.125000e-02 6.562500e-01 +9.375000e-02 6.562500e-01 +3.125000e-02 7.187500e-01 +3.125000e-02 5.937500e-01 +1.562500e-01 7.187500e-01 +9.375000e-02 7.187500e-01 +6.250000e-02 3.125000e-01 +1.250000e-01 3.125000e-01 +6.250000e-02 2.500000e-01 +9.375000e-02 2.812500e-01 +6.250000e-02 3.750000e-01 +9.375000e-02 3.437500e-01 +0.000000e+00 3.125000e-01 +3.125000e-02 2.812500e-01 +1.562500e-01 2.812500e-01 +2.187500e-01 2.812500e-01 +1.875000e-01 3.750000e-01 +1.562500e-01 3.437500e-01 +0.000000e+00 4.375000e-01 +3.125000e-02 4.062500e-01 +1.250000e-01 4.375000e-01 +9.375000e-02 4.062500e-01 +3.125000e-02 4.687500e-01 +3.125000e-02 3.437500e-01 +0.000000e+00 1.875000e-01 +3.125000e-02 1.562500e-01 +9.375000e-02 1.562500e-01 +3.125000e-02 2.187500e-01 +3.125000e-02 9.375000e-02 +1.562500e-01 2.187500e-01 +9.375000e-02 2.187500e-01 +2.500000e-01 4.375000e-01 +2.812500e-01 4.062500e-01 +3.437500e-01 4.062500e-01 +2.812500e-01 4.687500e-01 +2.812500e-01 3.437500e-01 +4.062500e-01 4.687500e-01 +3.437500e-01 4.687500e-01 +1.562500e-01 4.687500e-01 +1.562500e-01 4.062500e-01 +2.187500e-01 4.687500e-01 +9.375000e-02 4.687500e-01 +2.187500e-01 3.437500e-01 +2.187500e-01 4.062500e-01 + +element vertices: +26 21 33 +17 26 33 +26 12 37 +21 26 37 +32 21 41 +10 32 41 +32 17 33 +21 32 33 +45 25 46 +17 45 46 +45 7 50 +25 45 50 +26 25 53 +12 26 53 +26 17 46 +25 26 46 +36 35 57 +20 36 57 +36 12 59 +35 36 59 +56 35 61 +5 56 61 +56 20 57 +35 56 57 +40 21 62 +20 40 62 +40 10 41 +21 40 41 +36 21 37 +12 36 37 +36 20 62 +21 36 62 +67 31 70 +30 67 70 +67 16 72 +31 67 72 +69 31 73 +10 69 73 +69 30 70 +31 69 70 +77 66 78 +30 77 78 +77 4 82 +66 77 82 +67 66 85 +16 67 85 +67 30 78 +66 67 78 +71 44 86 +17 71 86 +71 16 88 +44 71 88 +45 44 91 +7 45 91 +45 17 86 +44 45 86 +32 31 92 +17 32 92 +32 10 73 +31 32 73 +71 31 72 +16 71 72 +71 17 92 +31 71 92 +95 94 97 +24 95 97 +95 23 101 +94 95 101 +96 94 103 +11 96 103 +96 24 97 +94 96 97 +49 48 104 +24 49 104 +49 7 106 +48 49 106 +95 48 109 +23 95 109 +95 24 104 +48 95 104 +100 99 111 +93 100 111 +100 23 113 +99 100 113 +110 99 115 +0 110 115 +110 93 111 +99 110 111 +102 94 116 +93 102 116 +102 11 103 +94 102 103 +100 94 101 +23 100 101 +100 93 116 +94 100 116 +58 51 118 +34 58 118 +58 12 119 +51 58 119 +117 51 120 +11 117 120 +117 34 118 +51 117 118 +60 35 121 +34 60 121 +60 5 61 +35 60 61 +58 35 59 +12 58 59 +58 34 121 +35 58 121 +52 25 122 +24 52 122 +52 12 53 +25 52 53 +49 25 50 +7 49 50 +49 24 122 +25 49 122 +96 51 123 +24 96 123 +96 11 120 +51 96 120 +52 51 119 +12 52 119 +52 24 123 +51 52 123 +129 127 133 +126 129 133 +129 19 135 +127 129 135 +132 127 137 +18 132 137 +132 126 133 +127 132 133 +141 128 142 +126 141 142 +141 9 146 +128 141 146 +129 128 148 +19 129 148 +129 126 142 +128 129 142 +134 55 150 +54 134 150 +134 19 152 +55 134 152 +149 55 153 +5 149 153 +149 54 150 +55 149 150 +136 127 154 +54 136 154 +136 18 137 +127 136 137 +134 127 135 +19 134 135 +134 54 154 +127 134 154 +157 131 159 +130 157 159 +157 125 161 +131 157 161 +158 131 162 +18 158 162 +158 130 159 +131 158 159 +163 156 164 +130 163 164 +163 1 166 +156 163 166 +157 156 169 +125 157 169 +157 130 164 +156 157 164 +160 140 170 +126 160 170 +160 125 172 +140 160 172 +141 140 175 +9 141 175 +141 126 170 +140 141 170 +132 131 176 +126 132 176 +132 18 162 +131 132 162 +160 131 161 +125 160 161 +160 126 176 +131 160 176 +177 68 179 +38 177 179 +177 29 181 +68 177 181 +178 68 182 +10 178 182 +178 38 179 +68 178 179 +145 144 183 +38 145 183 +145 9 185 +144 145 185 +177 144 188 +29 177 188 +177 38 183 +144 177 183 +180 76 189 +30 180 189 +180 29 191 +76 180 191 +77 76 194 +4 77 194 +77 30 189 +76 77 189 +69 68 195 +30 69 195 +69 10 182 +68 69 182 +180 68 181 +29 180 181 +180 30 195 +68 180 195 +151 39 196 +20 151 196 +151 19 197 +39 151 197 +40 39 198 +10 40 198 +40 20 196 +39 40 196 +56 55 199 +20 56 199 +56 5 153 +55 56 153 +151 55 152 +19 151 152 +151 20 199 +55 151 199 +147 128 200 +38 147 200 +147 19 148 +128 147 148 +145 128 146 +9 145 146 +145 38 200 +128 145 200 +178 39 201 +38 178 201 +178 10 198 +39 178 198 +147 39 197 +19 147 197 +147 38 201 +39 147 201 +206 205 208 +143 206 208 +206 138 212 +205 206 212 +207 205 216 +28 207 216 +207 143 208 +205 207 208 +184 173 217 +143 184 217 +184 9 218 +173 184 218 +206 173 221 +138 206 221 +206 143 217 +173 206 217 +211 210 225 +204 211 225 +211 138 227 +210 211 227 +224 210 229 +8 224 229 +224 204 225 +210 224 225 +215 205 230 +204 215 230 +215 28 216 +205 215 216 +211 205 212 +138 211 212 +211 204 230 +205 211 230 +190 186 233 +75 190 233 +190 29 234 +186 190 234 +232 186 235 +28 232 235 +232 75 233 +186 232 233 +193 76 236 +75 193 236 +193 4 194 +76 193 194 +190 76 191 +29 190 191 +190 75 236 +76 190 236 +187 144 237 +143 187 237 +187 29 188 +144 187 188 +184 144 185 +9 184 185 +184 143 237 +144 184 237 +207 186 238 +143 207 238 +207 28 235 +186 207 235 +187 186 234 +29 187 234 +187 143 238 +186 187 238 +171 167 240 +139 171 240 +171 125 241 +167 171 241 +239 167 243 +124 239 243 +239 139 240 +167 239 240 +174 140 244 +139 174 244 +174 9 175 +140 174 175 +171 140 172 +125 171 172 +171 139 244 +140 171 244 +168 156 245 +155 168 245 +168 125 169 +156 168 169 +165 156 166 +1 165 166 +165 155 245 +156 165 245 +242 167 246 +155 242 246 +242 124 243 +167 242 243 +168 167 241 +125 168 241 +168 155 246 +167 168 246 +226 219 248 +209 226 248 +226 138 249 +219 226 249 +247 219 250 +124 247 250 +247 209 248 +219 247 248 +228 210 251 +209 228 251 +228 8 229 +210 228 229 +226 210 227 +138 226 227 +226 209 251 +210 226 251 +220 173 252 +139 220 252 +220 138 221 +173 220 221 +174 173 218 +9 174 218 +174 139 252 +173 174 252 +239 219 253 +139 239 253 +239 124 250 +219 239 250 +220 219 249 +138 220 249 +220 139 253 +219 220 253 +259 257 263 +256 259 263 +259 203 265 +257 259 265 +262 257 267 +202 262 267 +262 256 263 +257 262 263 +271 258 272 +256 271 272 +271 27 276 +258 271 276 +259 258 278 +203 259 278 +259 256 272 +258 259 272 +264 223 280 +222 264 280 +264 203 282 +223 264 282 +279 223 283 +8 279 283 +279 222 280 +223 279 280 +266 257 284 +222 266 284 +266 202 267 +257 266 267 +264 257 265 +203 264 265 +264 222 284 +257 264 284 +287 261 289 +260 287 289 +287 255 291 +261 287 291 +288 261 292 +202 288 292 +288 260 289 +261 288 289 +293 286 294 +260 293 294 +293 2 296 +286 293 296 +287 286 299 +255 287 299 +287 260 294 +286 287 294 +290 270 300 +256 290 300 +290 255 302 +270 290 302 +271 270 305 +27 271 305 +271 256 300 +270 271 300 +262 261 306 +256 262 306 +262 202 292 +261 262 292 +290 261 291 +255 290 291 +290 256 306 +261 290 306 +307 231 309 +213 307 309 +307 74 311 +231 307 311 +308 231 312 +28 308 312 +308 213 309 +231 308 309 +275 274 313 +213 275 313 +275 27 315 +274 275 315 +307 274 318 +74 307 318 +307 213 313 +274 307 313 +310 192 319 +75 310 319 +310 74 321 +192 310 321 +193 192 323 +4 193 323 +193 75 319 +192 193 319 +232 231 324 +75 232 324 +232 28 312 +231 232 312 +310 231 311 +74 310 311 +310 75 324 +231 310 324 +281 214 325 +204 281 325 +281 203 326 +214 281 326 +215 214 327 +28 215 327 +215 204 325 +214 215 325 +224 223 328 +204 224 328 +224 8 283 +223 224 283 +281 223 282 +203 281 282 +281 204 328 +223 281 328 +277 258 329 +213 277 329 +277 203 278 +258 277 278 +275 258 276 +27 275 276 +275 213 329 +258 275 329 +308 214 330 +213 308 330 +308 28 327 +214 308 327 +277 214 326 +203 277 326 +277 213 330 +214 277 330 +335 334 337 +273 335 337 +335 268 341 +334 335 341 +336 334 345 +63 336 345 +336 273 337 +334 336 337 +314 303 346 +273 314 346 +314 27 347 +303 314 347 +335 303 350 +268 335 350 +335 273 346 +303 335 346 +340 339 354 +333 340 354 +340 268 356 +339 340 356 +353 339 358 +13 353 358 +353 333 354 +339 353 354 +344 334 359 +333 344 359 +344 63 345 +334 344 345 +340 334 341 +268 340 341 +340 333 359 +334 340 359 +320 316 362 +79 320 362 +320 74 363 +316 320 363 +361 316 364 +63 361 364 +361 79 362 +316 361 362 +322 192 365 +79 322 365 +322 4 323 +192 322 323 +320 192 321 +74 320 321 +320 79 365 +192 320 365 +317 274 366 +273 317 366 +317 74 318 +274 317 318 +314 274 315 +27 314 315 +314 273 366 +274 314 366 +336 316 367 +273 336 367 +336 63 364 +316 336 364 +317 316 363 +74 317 363 +317 273 367 +316 317 367 +301 297 369 +269 301 369 +301 255 370 +297 301 370 +368 297 372 +254 368 372 +368 269 369 +297 368 369 +304 270 373 +269 304 373 +304 27 305 +270 304 305 +301 270 302 +255 301 302 +301 269 373 +270 301 373 +298 286 374 +285 298 374 +298 255 299 +286 298 299 +295 286 296 +2 295 296 +295 285 374 +286 295 374 +371 297 375 +285 371 375 +371 254 372 +297 371 372 +298 297 370 +255 298 370 +298 285 375 +297 298 375 +355 348 377 +338 355 377 +355 268 378 +348 355 378 +376 348 379 +254 376 379 +376 338 377 +348 376 377 +357 339 380 +338 357 380 +357 13 358 +339 357 358 +355 339 356 +268 355 356 +355 338 380 +339 355 380 +349 303 381 +269 349 381 +349 268 350 +303 349 350 +304 303 347 +27 304 347 +304 269 381 +303 304 381 +368 348 382 +269 368 382 +368 254 379 +348 368 379 +349 348 378 +268 349 378 +349 269 382 +348 349 382 +388 386 392 +385 388 392 +388 332 394 +386 388 394 +391 386 396 +331 391 396 +391 385 392 +386 391 392 +400 387 401 +385 400 401 +400 14 405 +387 400 405 +388 387 407 +332 388 407 +388 385 401 +387 388 401 +393 352 409 +351 393 409 +393 332 411 +352 393 411 +408 352 412 +13 408 412 +408 351 409 +352 408 409 +395 386 413 +351 395 413 +395 331 396 +386 395 396 +393 386 394 +332 393 394 +393 351 413 +386 393 413 +416 390 418 +389 416 418 +416 384 420 +390 416 420 +417 390 421 +331 417 421 +417 389 418 +390 417 418 +422 415 423 +389 422 423 +422 3 425 +415 422 425 +416 415 428 +384 416 428 +416 389 423 +415 416 423 +419 399 429 +385 419 429 +419 384 431 +399 419 431 +400 399 434 +14 400 434 +400 385 429 +399 400 429 +391 390 435 +385 391 435 +391 331 421 +390 391 421 +419 390 420 +384 419 420 +419 385 435 +390 419 435 +436 360 438 +342 436 438 +436 64 440 +360 436 440 +437 360 441 +63 437 441 +437 342 438 +360 437 438 +404 403 442 +342 404 442 +404 14 444 +403 404 444 +436 403 447 +64 436 447 +436 342 442 +403 436 442 +439 80 448 +79 439 448 +439 64 450 +80 439 450 +322 80 451 +4 322 451 +322 79 448 +80 322 448 +361 360 452 +79 361 452 +361 63 441 +360 361 441 +439 360 440 +64 439 440 +439 79 452 +360 439 452 +410 343 453 +333 410 453 +410 332 454 +343 410 454 +344 343 455 +63 344 455 +344 333 453 +343 344 453 +353 352 456 +333 353 456 +353 13 412 +352 353 412 +410 352 411 +332 410 411 +410 333 456 +352 410 456 +406 387 457 +342 406 457 +406 332 407 +387 406 407 +404 387 405 +14 404 405 +404 342 457 +387 404 457 +437 343 458 +342 437 458 +437 63 455 +343 437 455 +406 343 454 +332 406 454 +406 342 458 +343 406 458 +461 460 463 +402 461 463 +461 397 467 +460 461 467 +462 460 470 +15 462 470 +462 402 463 +460 462 463 +443 432 471 +402 443 471 +443 14 472 +432 443 472 +461 432 475 +397 461 475 +461 402 471 +432 461 471 +466 465 479 +459 466 479 +466 397 481 +465 466 481 +478 465 483 +6 478 483 +478 459 479 +465 478 479 +469 460 484 +459 469 484 +469 15 470 +460 469 470 +466 460 467 +397 466 467 +466 459 484 +460 466 484 +449 445 486 +65 449 486 +449 64 487 +445 449 487 +485 445 488 +15 485 488 +485 65 486 +445 485 486 +81 80 489 +65 81 489 +81 4 451 +80 81 451 +449 80 450 +64 449 450 +449 65 489 +80 449 489 +446 403 490 +402 446 490 +446 64 447 +403 446 447 +443 403 444 +14 443 444 +443 402 490 +403 443 490 +462 445 491 +402 462 491 +462 15 488 +445 462 488 +446 445 487 +64 446 487 +446 402 491 +445 446 491 +430 426 493 +398 430 493 +430 384 494 +426 430 494 +492 426 496 +383 492 496 +492 398 493 +426 492 493 +433 399 497 +398 433 497 +433 14 434 +399 433 434 +430 399 431 +384 430 431 +430 398 497 +399 430 497 +427 415 498 +414 427 498 +427 384 428 +415 427 428 +424 415 425 +3 424 425 +424 414 498 +415 424 498 +495 426 499 +414 495 499 +495 383 496 +426 495 496 +427 426 494 +384 427 494 +427 414 499 +426 427 499 +480 473 501 +464 480 501 +480 397 502 +473 480 502 +500 473 503 +383 500 503 +500 464 501 +473 500 501 +482 465 504 +464 482 504 +482 6 483 +465 482 483 +480 465 481 +397 480 481 +480 464 504 +465 480 504 +474 432 505 +398 474 505 +474 397 475 +432 474 475 +433 432 472 +14 433 472 +433 398 505 +432 433 505 +492 473 506 +398 492 506 +492 383 503 +473 492 503 +474 473 502 +397 474 502 +474 398 506 +473 474 506 +508 507 510 +47 508 510 +508 42 512 +507 508 512 +509 507 514 +22 509 514 +509 47 510 +507 509 510 +105 89 515 +47 105 515 +105 7 516 +89 105 516 +508 89 518 +42 508 518 +508 47 515 +89 508 515 +511 477 520 +476 511 520 +511 42 522 +477 511 522 +519 477 523 +6 519 523 +519 476 520 +477 519 520 +513 507 524 +476 513 524 +513 22 514 +507 513 514 +511 507 512 +42 511 512 +511 476 524 +507 511 524 +112 107 526 +98 112 526 +112 23 527 +107 112 527 +525 107 528 +22 525 528 +525 98 526 +107 525 526 +114 99 529 +98 114 529 +114 0 115 +99 114 115 +112 99 113 +23 112 113 +112 98 529 +99 112 529 +108 48 530 +47 108 530 +108 23 109 +48 108 109 +105 48 106 +7 105 106 +105 47 530 +48 105 530 +509 107 531 +47 509 531 +509 22 528 +107 509 528 +108 107 527 +23 108 527 +108 47 531 +107 108 531 +87 83 533 +43 87 533 +87 16 534 +83 87 534 +532 83 535 +15 532 535 +532 43 533 +83 532 533 +90 44 536 +43 90 536 +90 7 91 +44 90 91 +87 44 88 +16 87 88 +87 43 536 +44 87 536 +84 66 537 +65 84 537 +84 16 85 +66 84 85 +81 66 82 +4 81 82 +81 65 537 +66 81 537 +485 83 538 +65 485 538 +485 15 535 +83 485 535 +84 83 534 +16 84 534 +84 65 538 +83 84 538 +521 468 539 +459 521 539 +521 42 540 +468 521 540 +469 468 541 +15 469 541 +469 459 539 +468 469 539 +478 477 542 +459 478 542 +478 6 523 +477 478 523 +521 477 522 +42 521 522 +521 459 542 +477 521 542 +517 89 543 +43 517 543 +517 42 518 +89 517 518 +90 89 516 +7 90 516 +90 43 543 +89 90 543 +532 468 544 +43 532 544 +532 15 541 +468 532 541 +517 468 540 +42 517 540 +517 43 544 +468 517 544 + +element boundaries: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element neighbours: +7 1 3 +0 6 14 +29 3 13 +2 28 0 +27 5 7 +4 26 58 +1 7 57 +6 0 4 +15 9 11 +8 14 54 +117 11 53 +10 116 8 +115 13 15 +12 114 2 +9 15 1 +14 8 12 +23 17 19 +16 22 30 +109 19 29 +18 108 16 +107 21 23 +20 106 234 +17 23 233 +22 16 20 +31 25 27 +24 30 230 +5 27 229 +26 4 24 +3 29 31 +28 2 18 +25 31 17 +30 24 28 +39 33 35 +32 38 46 +61 35 45 +34 60 32 +59 37 39 +36 58 218 +33 39 217 +38 32 36 +47 41 43 +40 46 214 +981 43 213 +42 980 40 +979 45 47 +44 978 34 +41 47 33 +46 40 44 +55 49 51 +48 54 62 +973 51 61 +50 972 48 +971 53 55 +52 970 10 +49 55 9 +54 48 52 +63 57 59 +56 62 6 +37 59 5 +58 36 56 +35 61 63 +60 34 50 +57 63 49 +62 56 60 +71 65 67 +64 70 78 +93 67 77 +66 92 64 +91 69 71 +68 90 122 +65 71 121 +70 64 68 +79 73 75 +72 78 118 +949 75 117 +74 948 72 +947 77 79 +76 946 66 +73 79 65 +78 72 76 +87 81 83 +80 86 94 +941 83 93 +82 940 80 +939 85 87 +84 938 -1 +81 87 -1 +86 80 84 +95 89 91 +88 94 -1 +69 91 -1 +90 68 88 +67 93 95 +92 66 82 +89 95 81 +94 88 92 +103 97 99 +96 102 110 +125 99 109 +98 124 96 +123 101 103 +100 122 -1 +97 103 -1 +102 96 100 +111 105 107 +104 110 -1 +21 107 -1 +106 20 104 +19 109 111 +108 18 98 +105 111 97 +110 104 108 +119 113 115 +112 118 126 +13 115 125 +114 12 112 +11 117 119 +116 10 74 +113 119 73 +118 112 116 +127 121 123 +120 126 70 +101 123 69 +122 100 120 +99 125 127 +124 98 114 +121 127 113 +126 120 124 +135 129 131 +128 134 142 +157 131 141 +130 156 128 +155 133 135 +132 154 186 +129 135 185 +134 128 132 +143 137 139 +136 142 182 +245 139 181 +138 244 136 +243 141 143 +140 242 130 +137 143 129 +142 136 140 +151 145 147 +144 150 158 +237 147 157 +146 236 144 +235 149 151 +148 234 -1 +145 151 -1 +150 144 148 +159 153 155 +152 158 -1 +133 155 -1 +154 132 152 +131 157 159 +156 130 146 +153 159 145 +158 152 156 +167 161 163 +160 166 174 +189 163 173 +162 188 160 +187 165 167 +164 186 -1 +161 167 -1 +166 160 164 +175 169 171 +168 174 -1 +341 171 -1 +170 340 168 +339 173 175 +172 338 162 +169 175 161 +174 168 172 +183 177 179 +176 182 190 +333 179 189 +178 332 176 +331 181 183 +180 330 138 +177 183 137 +182 176 180 +191 185 187 +184 190 134 +165 187 133 +186 164 184 +163 189 191 +188 162 178 +185 191 177 +190 184 188 +199 193 195 +192 198 206 +221 195 205 +194 220 192 +219 197 199 +196 218 250 +193 199 249 +198 192 196 +207 201 203 +200 206 246 +309 203 245 +202 308 200 +307 205 207 +204 306 194 +201 207 193 +206 200 204 +215 209 211 +208 214 222 +301 211 221 +210 300 208 +299 213 215 +212 298 42 +209 215 41 +214 208 212 +223 217 219 +216 222 38 +197 219 37 +218 196 216 +195 221 223 +220 194 210 +217 223 209 +222 216 220 +231 225 227 +224 230 238 +253 227 237 +226 252 224 +251 229 231 +228 250 26 +225 231 25 +230 224 228 +239 233 235 +232 238 22 +149 235 21 +234 148 232 +147 237 239 +236 146 226 +233 239 225 +238 232 236 +247 241 243 +240 246 254 +141 243 253 +242 140 240 +139 245 247 +244 138 202 +241 247 201 +246 240 244 +255 249 251 +248 254 198 +229 251 197 +250 228 248 +227 253 255 +252 226 242 +249 255 241 +254 248 252 +263 257 259 +256 262 270 +285 259 269 +258 284 256 +283 261 263 +260 282 314 +257 263 313 +262 256 260 +271 265 267 +264 270 310 +373 267 309 +266 372 264 +371 269 271 +268 370 258 +265 271 257 +270 264 268 +279 273 275 +272 278 286 +365 275 285 +274 364 272 +363 277 279 +276 362 490 +273 279 489 +278 272 276 +287 281 283 +280 286 486 +261 283 485 +282 260 280 +259 285 287 +284 258 274 +281 287 273 +286 280 284 +295 289 291 +288 294 302 +317 291 301 +290 316 288 +315 293 295 +292 314 474 +289 295 473 +294 288 292 +303 297 299 +296 302 470 +213 299 469 +298 212 296 +211 301 303 +300 210 290 +297 303 289 +302 296 300 +311 305 307 +304 310 318 +205 307 317 +306 204 304 +203 309 311 +308 202 266 +305 311 265 +310 304 308 +319 313 315 +312 318 262 +293 315 261 +314 292 312 +291 317 319 +316 290 306 +313 319 305 +318 312 316 +327 321 323 +320 326 334 +349 323 333 +322 348 320 +347 325 327 +324 346 378 +321 327 377 +326 320 324 +335 329 331 +328 334 374 +181 331 373 +330 180 328 +179 333 335 +332 178 322 +329 335 321 +334 328 332 +343 337 339 +336 342 350 +173 339 349 +338 172 336 +171 341 343 +340 170 -1 +337 343 -1 +342 336 340 +351 345 347 +344 350 -1 +325 347 -1 +346 324 344 +323 349 351 +348 322 338 +345 351 337 +350 344 348 +359 353 355 +352 358 366 +381 355 365 +354 380 352 +379 357 359 +356 378 -1 +353 359 -1 +358 352 356 +367 361 363 +360 366 -1 +277 363 -1 +362 276 360 +275 365 367 +364 274 354 +361 367 353 +366 360 364 +375 369 371 +368 374 382 +269 371 381 +370 268 368 +267 373 375 +372 266 330 +369 375 329 +374 368 372 +383 377 379 +376 382 326 +357 379 325 +378 356 376 +355 381 383 +380 354 370 +377 383 369 +382 376 380 +391 385 387 +384 390 398 +413 387 397 +386 412 384 +411 389 391 +388 410 442 +385 391 441 +390 384 388 +399 393 395 +392 398 438 +501 395 437 +394 500 392 +499 397 399 +396 498 386 +393 399 385 +398 392 396 +407 401 403 +400 406 414 +493 403 413 +402 492 400 +491 405 407 +404 490 -1 +401 407 -1 +406 400 404 +415 409 411 +408 414 -1 +389 411 -1 +410 388 408 +387 413 415 +412 386 402 +409 415 401 +414 408 412 +423 417 419 +416 422 430 +445 419 429 +418 444 416 +443 421 423 +420 442 -1 +417 423 -1 +422 416 420 +431 425 427 +424 430 -1 +597 427 -1 +426 596 424 +595 429 431 +428 594 418 +425 431 417 +430 424 428 +439 433 435 +432 438 446 +589 435 445 +434 588 432 +587 437 439 +436 586 394 +433 439 393 +438 432 436 +447 441 443 +440 446 390 +421 443 389 +442 420 440 +419 445 447 +444 418 434 +441 447 433 +446 440 444 +455 449 451 +448 454 462 +477 451 461 +450 476 448 +475 453 455 +452 474 506 +449 455 505 +454 448 452 +463 457 459 +456 462 502 +565 459 501 +458 564 456 +563 461 463 +460 562 450 +457 463 449 +462 456 460 +471 465 467 +464 470 478 +557 467 477 +466 556 464 +555 469 471 +468 554 298 +465 471 297 +470 464 468 +479 473 475 +472 478 294 +453 475 293 +474 452 472 +451 477 479 +476 450 466 +473 479 465 +478 472 476 +487 481 483 +480 486 494 +509 483 493 +482 508 480 +507 485 487 +484 506 282 +481 487 281 +486 480 484 +495 489 491 +488 494 278 +405 491 277 +490 404 488 +403 493 495 +492 402 482 +489 495 481 +494 488 492 +503 497 499 +496 502 510 +397 499 509 +498 396 496 +395 501 503 +500 394 458 +497 503 457 +502 496 500 +511 505 507 +504 510 454 +485 507 453 +506 484 504 +483 509 511 +508 482 498 +505 511 497 +510 504 508 +519 513 515 +512 518 526 +541 515 525 +514 540 512 +539 517 519 +516 538 570 +513 519 569 +518 512 516 +527 521 523 +520 526 566 +629 523 565 +522 628 520 +627 525 527 +524 626 514 +521 527 513 +526 520 524 +535 529 531 +528 534 542 +621 531 541 +530 620 528 +619 533 535 +532 618 746 +529 535 745 +534 528 532 +543 537 539 +536 542 742 +517 539 741 +538 516 536 +515 541 543 +540 514 530 +537 543 529 +542 536 540 +551 545 547 +544 550 558 +573 547 557 +546 572 544 +571 549 551 +548 570 730 +545 551 729 +550 544 548 +559 553 555 +552 558 726 +469 555 725 +554 468 552 +467 557 559 +556 466 546 +553 559 545 +558 552 556 +567 561 563 +560 566 574 +461 563 573 +562 460 560 +459 565 567 +564 458 522 +561 567 521 +566 560 564 +575 569 571 +568 574 518 +549 571 517 +570 548 568 +547 573 575 +572 546 562 +569 575 561 +574 568 572 +583 577 579 +576 582 590 +605 579 589 +578 604 576 +603 581 583 +580 602 634 +577 583 633 +582 576 580 +591 585 587 +584 590 630 +437 587 629 +586 436 584 +435 589 591 +588 434 578 +585 591 577 +590 584 588 +599 593 595 +592 598 606 +429 595 605 +594 428 592 +427 597 599 +596 426 -1 +593 599 -1 +598 592 596 +607 601 603 +600 606 -1 +581 603 -1 +602 580 600 +579 605 607 +604 578 594 +601 607 593 +606 600 604 +615 609 611 +608 614 622 +637 611 621 +610 636 608 +635 613 615 +612 634 -1 +609 615 -1 +614 608 612 +623 617 619 +616 622 -1 +533 619 -1 +618 532 616 +531 621 623 +620 530 610 +617 623 609 +622 616 620 +631 625 627 +624 630 638 +525 627 637 +626 524 624 +523 629 631 +628 522 586 +625 631 585 +630 624 628 +639 633 635 +632 638 582 +613 635 581 +634 612 632 +611 637 639 +636 610 626 +633 639 625 +638 632 636 +647 641 643 +640 646 654 +669 643 653 +642 668 640 +667 645 647 +644 666 698 +641 647 697 +646 640 644 +655 649 651 +648 654 694 +757 651 693 +650 756 648 +755 653 655 +652 754 642 +649 655 641 +654 648 652 +663 657 659 +656 662 670 +749 659 669 +658 748 656 +747 661 663 +660 746 -1 +657 663 -1 +662 656 660 +671 665 667 +664 670 -1 +645 667 -1 +666 644 664 +643 669 671 +668 642 658 +665 671 657 +670 664 668 +679 673 675 +672 678 686 +701 675 685 +674 700 672 +699 677 679 +676 698 -1 +673 679 -1 +678 672 676 +687 681 683 +680 686 -1 +853 683 -1 +682 852 680 +851 685 687 +684 850 674 +681 687 673 +686 680 684 +695 689 691 +688 694 702 +845 691 701 +690 844 688 +843 693 695 +692 842 650 +689 695 649 +694 688 692 +703 697 699 +696 702 646 +677 699 645 +698 676 696 +675 701 703 +700 674 690 +697 703 689 +702 696 700 +711 705 707 +704 710 718 +733 707 717 +706 732 704 +731 709 711 +708 730 762 +705 711 761 +710 704 708 +719 713 715 +712 718 758 +821 715 757 +714 820 712 +819 717 719 +716 818 706 +713 719 705 +718 712 716 +727 721 723 +720 726 734 +813 723 733 +722 812 720 +811 725 727 +724 810 554 +721 727 553 +726 720 724 +735 729 731 +728 734 550 +709 731 549 +730 708 728 +707 733 735 +732 706 722 +729 735 721 +734 728 732 +743 737 739 +736 742 750 +765 739 749 +738 764 736 +763 741 743 +740 762 538 +737 743 537 +742 736 740 +751 745 747 +744 750 534 +661 747 533 +746 660 744 +659 749 751 +748 658 738 +745 751 737 +750 744 748 +759 753 755 +752 758 766 +653 755 765 +754 652 752 +651 757 759 +756 650 714 +753 759 713 +758 752 756 +767 761 763 +760 766 710 +741 763 709 +762 740 760 +739 765 767 +764 738 754 +761 767 753 +766 760 764 +775 769 771 +768 774 782 +797 771 781 +770 796 768 +795 773 775 +772 794 826 +769 775 825 +774 768 772 +783 777 779 +776 782 822 +885 779 821 +778 884 776 +883 781 783 +780 882 770 +777 783 769 +782 776 780 +791 785 787 +784 790 798 +877 787 797 +786 876 784 +875 789 791 +788 874 1002 +785 791 1001 +790 784 788 +799 793 795 +792 798 998 +773 795 997 +794 772 792 +771 797 799 +796 770 786 +793 799 785 +798 792 796 +807 801 803 +800 806 814 +829 803 813 +802 828 800 +827 805 807 +804 826 986 +801 807 985 +806 800 804 +815 809 811 +808 814 982 +725 811 981 +810 724 808 +723 813 815 +812 722 802 +809 815 801 +814 808 812 +823 817 819 +816 822 830 +717 819 829 +818 716 816 +715 821 823 +820 714 778 +817 823 777 +822 816 820 +831 825 827 +824 830 774 +805 827 773 +826 804 824 +803 829 831 +828 802 818 +825 831 817 +830 824 828 +839 833 835 +832 838 846 +861 835 845 +834 860 832 +859 837 839 +836 858 890 +833 839 889 +838 832 836 +847 841 843 +840 846 886 +693 843 885 +842 692 840 +691 845 847 +844 690 834 +841 847 833 +846 840 844 +855 849 851 +848 854 862 +685 851 861 +850 684 848 +683 853 855 +852 682 -1 +849 855 -1 +854 848 852 +863 857 859 +856 862 -1 +837 859 -1 +858 836 856 +835 861 863 +860 834 850 +857 863 849 +862 856 860 +871 865 867 +864 870 878 +893 867 877 +866 892 864 +891 869 871 +868 890 -1 +865 871 -1 +870 864 868 +879 873 875 +872 878 -1 +789 875 -1 +874 788 872 +787 877 879 +876 786 866 +873 879 865 +878 872 876 +887 881 883 +880 886 894 +781 883 893 +882 780 880 +779 885 887 +884 778 842 +881 887 841 +886 880 884 +895 889 891 +888 894 838 +869 891 837 +890 868 888 +867 893 895 +892 866 882 +889 895 881 +894 888 892 +903 897 899 +896 902 910 +925 899 909 +898 924 896 +923 901 903 +900 922 954 +897 903 953 +902 896 900 +911 905 907 +904 910 950 +1013 907 949 +906 1012 904 +1011 909 911 +908 1010 898 +905 911 897 +910 904 908 +919 913 915 +912 918 926 +1005 915 925 +914 1004 912 +1003 917 919 +916 1002 -1 +913 919 -1 +918 912 916 +927 921 923 +920 926 -1 +901 923 -1 +922 900 920 +899 925 927 +924 898 914 +921 927 913 +926 920 924 +935 929 931 +928 934 942 +957 931 941 +930 956 928 +955 933 935 +932 954 -1 +929 935 -1 +934 928 932 +943 937 939 +936 942 -1 +85 939 -1 +938 84 936 +83 941 943 +940 82 930 +937 943 929 +942 936 940 +951 945 947 +944 950 958 +77 947 957 +946 76 944 +75 949 951 +948 74 906 +945 951 905 +950 944 948 +959 953 955 +952 958 902 +933 955 901 +954 932 952 +931 957 959 +956 930 946 +953 959 945 +958 952 956 +967 961 963 +960 966 974 +989 963 973 +962 988 960 +987 965 967 +964 986 1018 +961 967 1017 +966 960 964 +975 969 971 +968 974 1014 +53 971 1013 +970 52 968 +51 973 975 +972 50 962 +969 975 961 +974 968 972 +983 977 979 +976 982 990 +45 979 989 +978 44 976 +43 981 983 +980 42 810 +977 983 809 +982 976 980 +991 985 987 +984 990 806 +965 987 805 +986 964 984 +963 989 991 +988 962 978 +985 991 977 +990 984 988 +999 993 995 +992 998 1006 +1021 995 1005 +994 1020 992 +1019 997 999 +996 1018 794 +993 999 793 +998 992 996 +1007 1001 1003 +1000 1006 790 +917 1003 789 +1002 916 1000 +915 1005 1007 +1004 914 994 +1001 1007 993 +1006 1000 1004 +1015 1009 1011 +1008 1014 1022 +909 1011 1021 +1010 908 1008 +907 1013 1015 +1012 906 970 +1009 1015 969 +1014 1008 1012 +1023 1017 1019 +1016 1022 966 +997 1019 965 +1018 996 1016 +995 1021 1023 +1020 994 1010 +1017 1023 1009 +1022 1016 1020 + +projections: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element region: +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 + +surface region: +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 diff --git a/extensions/demo/multimesh/macro/macro_corner_1x1.2d.991261.tmp b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.991261.tmp new file mode 100644 index 00000000..f152f950 --- /dev/null +++ b/extensions/demo/multimesh/macro/macro_corner_1x1.2d.991261.tmp @@ -0,0 +1,6708 @@ +DIM: 2 +DIM_OF_WORLD: 2 + +number of vertices: 545 +number of elements: 1024 + +vertex coordinates: +0.000000e+00 0.000000e+00 +1.000000e+00 0.000000e+00 +1.000000e+00 1.000000e+00 +0.000000e+00 1.000000e+00 +5.000000e-01 5.000000e-01 +5.000000e-01 0.000000e+00 +0.000000e+00 5.000000e-01 +2.500000e-01 2.500000e-01 +1.000000e+00 5.000000e-01 +7.500000e-01 2.500000e-01 +5.000000e-01 2.500000e-01 +2.500000e-01 0.000000e+00 +3.750000e-01 1.250000e-01 +5.000000e-01 1.000000e+00 +2.500000e-01 7.500000e-01 +2.500000e-01 5.000000e-01 +3.750000e-01 3.750000e-01 +3.750000e-01 2.500000e-01 +7.500000e-01 0.000000e+00 +6.250000e-01 1.250000e-01 +5.000000e-01 1.250000e-01 +4.375000e-01 1.875000e-01 +0.000000e+00 2.500000e-01 +1.250000e-01 1.250000e-01 +2.500000e-01 1.250000e-01 +3.125000e-01 1.875000e-01 +3.750000e-01 1.875000e-01 +7.500000e-01 7.500000e-01 +7.500000e-01 5.000000e-01 +6.250000e-01 3.750000e-01 +5.000000e-01 3.750000e-01 +4.375000e-01 3.125000e-01 +4.375000e-01 2.500000e-01 +4.062500e-01 2.187500e-01 +3.750000e-01 0.000000e+00 +4.375000e-01 6.250000e-02 +4.375000e-01 1.250000e-01 +4.062500e-01 1.562500e-01 +6.250000e-01 2.500000e-01 +5.625000e-01 1.875000e-01 +5.000000e-01 1.875000e-01 +4.687500e-01 2.187500e-01 +1.250000e-01 3.750000e-01 +2.500000e-01 3.750000e-01 +3.125000e-01 3.125000e-01 +3.125000e-01 2.500000e-01 +3.437500e-01 2.187500e-01 +1.250000e-01 2.500000e-01 +1.875000e-01 1.875000e-01 +2.500000e-01 1.875000e-01 +2.812500e-01 2.187500e-01 +3.125000e-01 6.250000e-02 +3.125000e-01 1.250000e-01 +3.437500e-01 1.562500e-01 +6.250000e-01 0.000000e+00 +5.625000e-01 6.250000e-02 +5.000000e-01 6.250000e-02 +4.687500e-01 9.375000e-02 +3.750000e-01 6.250000e-02 +4.062500e-01 9.375000e-02 +4.375000e-01 0.000000e+00 +4.687500e-01 3.125000e-02 +4.687500e-01 1.562500e-01 +5.000000e-01 7.500000e-01 +3.750000e-01 6.250000e-01 +3.750000e-01 5.000000e-01 +4.375000e-01 4.375000e-01 +4.375000e-01 3.750000e-01 +5.625000e-01 3.125000e-01 +5.000000e-01 3.125000e-01 +4.687500e-01 3.437500e-01 +3.750000e-01 3.125000e-01 +4.062500e-01 3.437500e-01 +4.687500e-01 2.812500e-01 +6.250000e-01 6.250000e-01 +6.250000e-01 5.000000e-01 +5.625000e-01 4.375000e-01 +5.000000e-01 4.375000e-01 +4.687500e-01 4.062500e-01 +5.000000e-01 6.250000e-01 +4.375000e-01 5.625000e-01 +4.375000e-01 5.000000e-01 +4.687500e-01 4.687500e-01 +3.125000e-01 4.375000e-01 +3.750000e-01 4.375000e-01 +4.062500e-01 4.062500e-01 +3.437500e-01 2.812500e-01 +3.125000e-01 3.750000e-01 +3.437500e-01 3.437500e-01 +1.875000e-01 3.125000e-01 +2.500000e-01 3.125000e-01 +2.812500e-01 2.812500e-01 +4.062500e-01 2.812500e-01 +1.250000e-01 0.000000e+00 +1.875000e-01 6.250000e-02 +1.875000e-01 1.250000e-01 +2.500000e-01 6.250000e-02 +2.187500e-01 9.375000e-02 +0.000000e+00 1.250000e-01 +6.250000e-02 6.250000e-02 +1.250000e-01 6.250000e-02 +1.562500e-01 9.375000e-02 +1.875000e-01 0.000000e+00 +2.187500e-01 3.125000e-02 +2.187500e-01 1.562500e-01 +1.875000e-01 2.500000e-01 +2.187500e-01 2.187500e-01 +6.250000e-02 1.875000e-01 +1.250000e-01 1.875000e-01 +1.562500e-01 1.562500e-01 +6.250000e-02 0.000000e+00 +9.375000e-02 3.125000e-02 +6.250000e-02 1.250000e-01 +9.375000e-02 9.375000e-02 +0.000000e+00 6.250000e-02 +3.125000e-02 3.125000e-02 +1.562500e-01 3.125000e-02 +3.125000e-01 0.000000e+00 +3.437500e-01 3.125000e-02 +3.437500e-01 9.375000e-02 +2.812500e-01 3.125000e-02 +4.062500e-01 3.125000e-02 +2.812500e-01 1.562500e-01 +2.812500e-01 9.375000e-02 +1.000000e+00 2.500000e-01 +8.750000e-01 1.250000e-01 +7.500000e-01 1.250000e-01 +6.875000e-01 6.250000e-02 +6.875000e-01 1.875000e-01 +6.875000e-01 1.250000e-01 +8.750000e-01 0.000000e+00 +8.125000e-01 6.250000e-02 +7.500000e-01 6.250000e-02 +7.187500e-01 9.375000e-02 +6.250000e-01 6.250000e-02 +6.562500e-01 9.375000e-02 +6.875000e-01 0.000000e+00 +7.187500e-01 3.125000e-02 +8.750000e-01 3.750000e-01 +8.750000e-01 2.500000e-01 +8.125000e-01 1.875000e-01 +7.500000e-01 1.875000e-01 +7.187500e-01 1.562500e-01 +7.500000e-01 3.750000e-01 +6.875000e-01 3.125000e-01 +6.875000e-01 2.500000e-01 +7.187500e-01 2.187500e-01 +6.250000e-01 1.875000e-01 +6.562500e-01 1.562500e-01 +5.625000e-01 0.000000e+00 +5.937500e-01 3.125000e-02 +5.625000e-01 1.250000e-01 +5.937500e-01 9.375000e-02 +5.312500e-01 3.125000e-02 +6.562500e-01 3.125000e-02 +1.000000e+00 1.250000e-01 +9.375000e-01 6.250000e-02 +8.750000e-01 6.250000e-02 +8.125000e-01 0.000000e+00 +8.437500e-01 3.125000e-02 +8.125000e-01 1.250000e-01 +8.437500e-01 9.375000e-02 +7.812500e-01 3.125000e-02 +9.375000e-01 0.000000e+00 +9.062500e-01 3.125000e-02 +1.000000e+00 6.250000e-02 +9.687500e-01 3.125000e-02 +9.375000e-01 1.875000e-01 +9.375000e-01 1.250000e-01 +9.062500e-01 9.375000e-02 +7.812500e-01 1.562500e-01 +8.750000e-01 1.875000e-01 +8.437500e-01 1.562500e-01 +8.125000e-01 3.125000e-01 +8.125000e-01 2.500000e-01 +7.812500e-01 2.187500e-01 +7.812500e-01 9.375000e-02 +6.250000e-01 3.125000e-01 +5.625000e-01 2.500000e-01 +5.937500e-01 2.812500e-01 +5.625000e-01 3.750000e-01 +5.937500e-01 3.437500e-01 +5.312500e-01 2.812500e-01 +6.562500e-01 2.812500e-01 +7.500000e-01 3.125000e-01 +7.187500e-01 2.812500e-01 +6.875000e-01 4.375000e-01 +6.875000e-01 3.750000e-01 +6.562500e-01 3.437500e-01 +5.312500e-01 4.062500e-01 +6.250000e-01 4.375000e-01 +5.937500e-01 4.062500e-01 +5.625000e-01 5.625000e-01 +5.625000e-01 5.000000e-01 +5.312500e-01 4.687500e-01 +5.312500e-01 3.437500e-01 +5.312500e-01 1.562500e-01 +5.937500e-01 1.562500e-01 +5.312500e-01 2.187500e-01 +5.312500e-01 9.375000e-02 +6.562500e-01 2.187500e-01 +5.937500e-01 2.187500e-01 +1.000000e+00 7.500000e-01 +8.750000e-01 6.250000e-01 +8.750000e-01 5.000000e-01 +8.125000e-01 4.375000e-01 +8.125000e-01 3.750000e-01 +7.500000e-01 4.375000e-01 +7.812500e-01 4.062500e-01 +1.000000e+00 3.750000e-01 +9.375000e-01 4.375000e-01 +8.750000e-01 4.375000e-01 +8.437500e-01 4.062500e-01 +7.500000e-01 6.250000e-01 +8.125000e-01 5.625000e-01 +8.125000e-01 5.000000e-01 +7.812500e-01 4.687500e-01 +7.812500e-01 3.437500e-01 +7.812500e-01 2.812500e-01 +9.375000e-01 3.125000e-01 +8.750000e-01 3.125000e-01 +8.437500e-01 3.437500e-01 +1.000000e+00 6.250000e-01 +9.375000e-01 5.625000e-01 +9.375000e-01 5.000000e-01 +9.062500e-01 4.687500e-01 +9.375000e-01 3.750000e-01 +9.062500e-01 4.062500e-01 +1.000000e+00 4.375000e-01 +9.687500e-01 4.687500e-01 +8.437500e-01 4.687500e-01 +6.875000e-01 5.625000e-01 +6.875000e-01 5.000000e-01 +6.562500e-01 4.687500e-01 +6.562500e-01 4.062500e-01 +7.187500e-01 4.687500e-01 +5.937500e-01 4.687500e-01 +7.187500e-01 3.437500e-01 +7.187500e-01 4.062500e-01 +9.375000e-01 2.500000e-01 +9.062500e-01 2.187500e-01 +9.062500e-01 1.562500e-01 +1.000000e+00 1.875000e-01 +9.687500e-01 2.187500e-01 +8.437500e-01 2.187500e-01 +9.687500e-01 9.375000e-02 +9.687500e-01 1.562500e-01 +1.000000e+00 3.125000e-01 +9.687500e-01 3.437500e-01 +9.062500e-01 3.437500e-01 +9.687500e-01 2.812500e-01 +9.687500e-01 4.062500e-01 +8.437500e-01 2.812500e-01 +9.062500e-01 2.812500e-01 +7.500000e-01 1.000000e+00 +8.750000e-01 8.750000e-01 +8.750000e-01 7.500000e-01 +9.375000e-01 6.875000e-01 +8.125000e-01 6.875000e-01 +8.750000e-01 6.875000e-01 +1.000000e+00 8.750000e-01 +9.375000e-01 8.125000e-01 +9.375000e-01 7.500000e-01 +9.062500e-01 7.187500e-01 +9.375000e-01 6.250000e-01 +9.062500e-01 6.562500e-01 +1.000000e+00 6.875000e-01 +9.687500e-01 7.187500e-01 +6.250000e-01 8.750000e-01 +7.500000e-01 8.750000e-01 +8.125000e-01 8.125000e-01 +8.125000e-01 7.500000e-01 +8.437500e-01 7.187500e-01 +6.250000e-01 7.500000e-01 +6.875000e-01 6.875000e-01 +7.500000e-01 6.875000e-01 +7.812500e-01 7.187500e-01 +8.125000e-01 6.250000e-01 +8.437500e-01 6.562500e-01 +1.000000e+00 5.625000e-01 +9.687500e-01 5.937500e-01 +8.750000e-01 5.625000e-01 +9.062500e-01 5.937500e-01 +9.687500e-01 5.312500e-01 +9.687500e-01 6.562500e-01 +8.750000e-01 1.000000e+00 +9.375000e-01 9.375000e-01 +9.375000e-01 8.750000e-01 +1.000000e+00 8.125000e-01 +9.687500e-01 8.437500e-01 +8.750000e-01 8.125000e-01 +9.062500e-01 8.437500e-01 +9.687500e-01 7.812500e-01 +1.000000e+00 9.375000e-01 +9.687500e-01 9.062500e-01 +9.375000e-01 1.000000e+00 +9.687500e-01 9.687500e-01 +8.125000e-01 9.375000e-01 +8.750000e-01 9.375000e-01 +9.062500e-01 9.062500e-01 +8.437500e-01 7.812500e-01 +8.125000e-01 8.750000e-01 +8.437500e-01 8.437500e-01 +6.875000e-01 8.125000e-01 +7.500000e-01 8.125000e-01 +7.812500e-01 7.812500e-01 +9.062500e-01 7.812500e-01 +6.875000e-01 6.250000e-01 +7.500000e-01 5.625000e-01 +7.187500e-01 5.937500e-01 +6.250000e-01 5.625000e-01 +6.562500e-01 5.937500e-01 +7.187500e-01 5.312500e-01 +7.187500e-01 6.562500e-01 +6.875000e-01 7.500000e-01 +7.187500e-01 7.187500e-01 +5.625000e-01 6.875000e-01 +6.250000e-01 6.875000e-01 +6.562500e-01 6.562500e-01 +5.937500e-01 5.312500e-01 +5.625000e-01 6.250000e-01 +5.937500e-01 5.937500e-01 +5.000000e-01 5.625000e-01 +5.312500e-01 5.312500e-01 +6.562500e-01 5.312500e-01 +8.437500e-01 5.312500e-01 +8.437500e-01 5.937500e-01 +7.812500e-01 5.312500e-01 +9.062500e-01 5.312500e-01 +7.812500e-01 6.562500e-01 +7.812500e-01 5.937500e-01 +2.500000e-01 1.000000e+00 +3.750000e-01 8.750000e-01 +5.000000e-01 8.750000e-01 +5.625000e-01 8.125000e-01 +6.250000e-01 8.125000e-01 +5.625000e-01 7.500000e-01 +5.937500e-01 7.812500e-01 +6.250000e-01 1.000000e+00 +5.625000e-01 9.375000e-01 +5.625000e-01 8.750000e-01 +5.937500e-01 8.437500e-01 +3.750000e-01 7.500000e-01 +4.375000e-01 8.125000e-01 +5.000000e-01 8.125000e-01 +5.312500e-01 7.812500e-01 +6.562500e-01 7.812500e-01 +7.187500e-01 7.812500e-01 +6.875000e-01 9.375000e-01 +6.875000e-01 8.750000e-01 +6.562500e-01 8.437500e-01 +3.750000e-01 1.000000e+00 +4.375000e-01 9.375000e-01 +5.000000e-01 9.375000e-01 +5.312500e-01 9.062500e-01 +6.250000e-01 9.375000e-01 +5.937500e-01 9.062500e-01 +5.625000e-01 1.000000e+00 +5.312500e-01 9.687500e-01 +5.312500e-01 8.437500e-01 +4.375000e-01 6.875000e-01 +5.000000e-01 6.875000e-01 +5.312500e-01 6.562500e-01 +5.937500e-01 6.562500e-01 +5.312500e-01 7.187500e-01 +5.312500e-01 5.937500e-01 +6.562500e-01 7.187500e-01 +5.937500e-01 7.187500e-01 +7.500000e-01 9.375000e-01 +7.812500e-01 9.062500e-01 +8.437500e-01 9.062500e-01 +8.125000e-01 1.000000e+00 +7.812500e-01 9.687500e-01 +7.812500e-01 8.437500e-01 +9.062500e-01 9.687500e-01 +8.437500e-01 9.687500e-01 +6.875000e-01 1.000000e+00 +6.562500e-01 9.687500e-01 +6.562500e-01 9.062500e-01 +7.187500e-01 9.687500e-01 +5.937500e-01 9.687500e-01 +7.187500e-01 8.437500e-01 +7.187500e-01 9.062500e-01 +0.000000e+00 7.500000e-01 +1.250000e-01 8.750000e-01 +2.500000e-01 8.750000e-01 +3.125000e-01 9.375000e-01 +3.125000e-01 8.125000e-01 +3.125000e-01 8.750000e-01 +1.250000e-01 1.000000e+00 +1.875000e-01 9.375000e-01 +2.500000e-01 9.375000e-01 +2.812500e-01 9.062500e-01 +3.750000e-01 9.375000e-01 +3.437500e-01 9.062500e-01 +3.125000e-01 1.000000e+00 +2.812500e-01 9.687500e-01 +1.250000e-01 6.250000e-01 +1.250000e-01 7.500000e-01 +1.875000e-01 8.125000e-01 +2.500000e-01 8.125000e-01 +2.812500e-01 8.437500e-01 +2.500000e-01 6.250000e-01 +3.125000e-01 6.875000e-01 +3.125000e-01 7.500000e-01 +2.812500e-01 7.812500e-01 +3.750000e-01 8.125000e-01 +3.437500e-01 8.437500e-01 +4.375000e-01 1.000000e+00 +4.062500e-01 9.687500e-01 +4.375000e-01 8.750000e-01 +4.062500e-01 9.062500e-01 +4.687500e-01 9.687500e-01 +3.437500e-01 9.687500e-01 +0.000000e+00 8.750000e-01 +6.250000e-02 9.375000e-01 +1.250000e-01 9.375000e-01 +1.875000e-01 1.000000e+00 +1.562500e-01 9.687500e-01 +1.875000e-01 8.750000e-01 +1.562500e-01 9.062500e-01 +2.187500e-01 9.687500e-01 +6.250000e-02 1.000000e+00 +9.375000e-02 9.687500e-01 +0.000000e+00 9.375000e-01 +3.125000e-02 9.687500e-01 +6.250000e-02 8.125000e-01 +6.250000e-02 8.750000e-01 +9.375000e-02 9.062500e-01 +2.187500e-01 8.437500e-01 +1.250000e-01 8.125000e-01 +1.562500e-01 8.437500e-01 +1.875000e-01 6.875000e-01 +1.875000e-01 7.500000e-01 +2.187500e-01 7.812500e-01 +2.187500e-01 9.062500e-01 +3.750000e-01 6.875000e-01 +4.375000e-01 7.500000e-01 +4.062500e-01 7.187500e-01 +4.375000e-01 6.250000e-01 +4.062500e-01 6.562500e-01 +4.687500e-01 7.187500e-01 +3.437500e-01 7.187500e-01 +2.500000e-01 6.875000e-01 +2.812500e-01 7.187500e-01 +3.125000e-01 5.625000e-01 +3.125000e-01 6.250000e-01 +3.437500e-01 6.562500e-01 +4.687500e-01 5.937500e-01 +3.750000e-01 5.625000e-01 +4.062500e-01 5.937500e-01 +4.687500e-01 5.312500e-01 +4.687500e-01 6.562500e-01 +4.687500e-01 8.437500e-01 +4.062500e-01 8.437500e-01 +4.687500e-01 7.812500e-01 +4.687500e-01 9.062500e-01 +3.437500e-01 7.812500e-01 +4.062500e-01 7.812500e-01 +1.250000e-01 5.000000e-01 +1.875000e-01 5.625000e-01 +1.875000e-01 6.250000e-01 +2.500000e-01 5.625000e-01 +2.187500e-01 5.937500e-01 +0.000000e+00 6.250000e-01 +6.250000e-02 5.625000e-01 +1.250000e-01 5.625000e-01 +1.562500e-01 5.937500e-01 +1.875000e-01 4.375000e-01 +1.875000e-01 5.000000e-01 +2.187500e-01 5.312500e-01 +2.187500e-01 6.562500e-01 +2.187500e-01 7.187500e-01 +6.250000e-02 6.875000e-01 +1.250000e-01 6.875000e-01 +1.562500e-01 6.562500e-01 +0.000000e+00 3.750000e-01 +6.250000e-02 4.375000e-01 +6.250000e-02 5.000000e-01 +9.375000e-02 5.312500e-01 +6.250000e-02 6.250000e-01 +9.375000e-02 5.937500e-01 +0.000000e+00 5.625000e-01 +3.125000e-02 5.312500e-01 +1.562500e-01 5.312500e-01 +3.125000e-01 5.000000e-01 +3.437500e-01 5.312500e-01 +3.437500e-01 5.937500e-01 +2.812500e-01 5.312500e-01 +4.062500e-01 5.312500e-01 +2.812500e-01 6.562500e-01 +2.812500e-01 5.937500e-01 +6.250000e-02 7.500000e-01 +9.375000e-02 7.812500e-01 +9.375000e-02 8.437500e-01 +0.000000e+00 8.125000e-01 +3.125000e-02 7.812500e-01 +1.562500e-01 7.812500e-01 +3.125000e-02 9.062500e-01 +3.125000e-02 8.437500e-01 +0.000000e+00 6.875000e-01 +3.125000e-02 6.562500e-01 +9.375000e-02 6.562500e-01 +3.125000e-02 7.187500e-01 +3.125000e-02 5.937500e-01 +1.562500e-01 7.187500e-01 +9.375000e-02 7.187500e-01 +6.250000e-02 3.125000e-01 +1.250000e-01 3.125000e-01 +6.250000e-02 2.500000e-01 +9.375000e-02 2.812500e-01 +6.250000e-02 3.750000e-01 +9.375000e-02 3.437500e-01 +0.000000e+00 3.125000e-01 +3.125000e-02 2.812500e-01 +1.562500e-01 2.812500e-01 +2.187500e-01 2.812500e-01 +1.875000e-01 3.750000e-01 +1.562500e-01 3.437500e-01 +0.000000e+00 4.375000e-01 +3.125000e-02 4.062500e-01 +1.250000e-01 4.375000e-01 +9.375000e-02 4.062500e-01 +3.125000e-02 4.687500e-01 +3.125000e-02 3.437500e-01 +0.000000e+00 1.875000e-01 +3.125000e-02 1.562500e-01 +9.375000e-02 1.562500e-01 +3.125000e-02 2.187500e-01 +3.125000e-02 9.375000e-02 +1.562500e-01 2.187500e-01 +9.375000e-02 2.187500e-01 +2.500000e-01 4.375000e-01 +2.812500e-01 4.062500e-01 +3.437500e-01 4.062500e-01 +2.812500e-01 4.687500e-01 +2.812500e-01 3.437500e-01 +4.062500e-01 4.687500e-01 +3.437500e-01 4.687500e-01 +1.562500e-01 4.687500e-01 +1.562500e-01 4.062500e-01 +2.187500e-01 4.687500e-01 +9.375000e-02 4.687500e-01 +2.187500e-01 3.437500e-01 +2.187500e-01 4.062500e-01 + +element vertices: +26 21 33 +17 26 33 +26 12 37 +21 26 37 +32 21 41 +10 32 41 +32 17 33 +21 32 33 +45 25 46 +17 45 46 +45 7 50 +25 45 50 +26 25 53 +12 26 53 +26 17 46 +25 26 46 +36 35 57 +20 36 57 +36 12 59 +35 36 59 +56 35 61 +5 56 61 +56 20 57 +35 56 57 +40 21 62 +20 40 62 +40 10 41 +21 40 41 +36 21 37 +12 36 37 +36 20 62 +21 36 62 +67 31 70 +30 67 70 +67 16 72 +31 67 72 +69 31 73 +10 69 73 +69 30 70 +31 69 70 +77 66 78 +30 77 78 +77 4 82 +66 77 82 +67 66 85 +16 67 85 +67 30 78 +66 67 78 +71 44 86 +17 71 86 +71 16 88 +44 71 88 +45 44 91 +7 45 91 +45 17 86 +44 45 86 +32 31 92 +17 32 92 +32 10 73 +31 32 73 +71 31 72 +16 71 72 +71 17 92 +31 71 92 +95 94 97 +24 95 97 +95 23 101 +94 95 101 +96 94 103 +11 96 103 +96 24 97 +94 96 97 +49 48 104 +24 49 104 +49 7 106 +48 49 106 +95 48 109 +23 95 109 +95 24 104 +48 95 104 +100 99 111 +93 100 111 +100 23 113 +99 100 113 +110 99 115 +0 110 115 +110 93 111 +99 110 111 +102 94 116 +93 102 116 +102 11 103 +94 102 103 +100 94 101 +23 100 101 +100 93 116 +94 100 116 +58 51 118 +34 58 118 +58 12 119 +51 58 119 +117 51 120 +11 117 120 +117 34 118 +51 117 118 +60 35 121 +34 60 121 +60 5 61 +35 60 61 +58 35 59 +12 58 59 +58 34 121 +35 58 121 +52 25 122 +24 52 122 +52 12 53 +25 52 53 +49 25 50 +7 49 50 +49 24 122 +25 49 122 +96 51 123 +24 96 123 +96 11 120 +51 96 120 +52 51 119 +12 52 119 +52 24 123 +51 52 123 +129 127 133 +126 129 133 +129 19 135 +127 129 135 +132 127 137 +18 132 137 +132 126 133 +127 132 133 +141 128 142 +126 141 142 +141 9 146 +128 141 146 +129 128 148 +19 129 148 +129 126 142 +128 129 142 +134 55 150 +54 134 150 +134 19 152 +55 134 152 +149 55 153 +5 149 153 +149 54 150 +55 149 150 +136 127 154 +54 136 154 +136 18 137 +127 136 137 +134 127 135 +19 134 135 +134 54 154 +127 134 154 +157 131 159 +130 157 159 +157 125 161 +131 157 161 +158 131 162 +18 158 162 +158 130 159 +131 158 159 +163 156 164 +130 163 164 +163 1 166 +156 163 166 +157 156 169 +125 157 169 +157 130 164 +156 157 164 +160 140 170 +126 160 170 +160 125 172 +140 160 172 +141 140 175 +9 141 175 +141 126 170 +140 141 170 +132 131 176 +126 132 176 +132 18 162 +131 132 162 +160 131 161 +125 160 161 +160 126 176 +131 160 176 +177 68 179 +38 177 179 +177 29 181 +68 177 181 +178 68 182 +10 178 182 +178 38 179 +68 178 179 +145 144 183 +38 145 183 +145 9 185 +144 145 185 +177 144 188 +29 177 188 +177 38 183 +144 177 183 +180 76 189 +30 180 189 +180 29 191 +76 180 191 +77 76 194 +4 77 194 +77 30 189 +76 77 189 +69 68 195 +30 69 195 +69 10 182 +68 69 182 +180 68 181 +29 180 181 +180 30 195 +68 180 195 +151 39 196 +20 151 196 +151 19 197 +39 151 197 +40 39 198 +10 40 198 +40 20 196 +39 40 196 +56 55 199 +20 56 199 +56 5 153 +55 56 153 +151 55 152 +19 151 152 +151 20 199 +55 151 199 +147 128 200 +38 147 200 +147 19 148 +128 147 148 +145 128 146 +9 145 146 +145 38 200 +128 145 200 +178 39 201 +38 178 201 +178 10 198 +39 178 198 +147 39 197 +19 147 197 +147 38 201 +39 147 201 +206 205 208 +143 206 208 +206 138 212 +205 206 212 +207 205 216 +28 207 216 +207 143 208 +205 207 208 +184 173 217 +143 184 217 +184 9 218 +173 184 218 +206 173 221 +138 206 221 +206 143 217 +173 206 217 +211 210 225 +204 211 225 +211 138 227 +210 211 227 +224 210 229 +8 224 229 +224 204 225 +210 224 225 +215 205 230 +204 215 230 +215 28 216 +205 215 216 +211 205 212 +138 211 212 +211 204 230 +205 211 230 +190 186 233 +75 190 233 +190 29 234 +186 190 234 +232 186 235 +28 232 235 +232 75 233 +186 232 233 +193 76 236 +75 193 236 +193 4 194 +76 193 194 +190 76 191 +29 190 191 +190 75 236 +76 190 236 +187 144 237 +143 187 237 +187 29 188 +144 187 188 +184 144 185 +9 184 185 +184 143 237 +144 184 237 +207 186 238 +143 207 238 +207 28 235 +186 207 235 +187 186 234 +29 187 234 +187 143 238 +186 187 238 +171 167 240 +139 171 240 +171 125 241 +167 171 241 +239 167 243 +124 239 243 +239 139 240 +167 239 240 +174 140 244 +139 174 244 +174 9 175 +140 174 175 +171 140 172 +125 171 172 +171 139 244 +140 171 244 +168 156 245 +155 168 245 +168 125 169 +156 168 169 +165 156 166 +1 165 166 +165 155 245 +156 165 245 +242 167 246 +155 242 246 +242 124 243 +167 242 243 +168 167 241 +125 168 241 +168 155 246 +167 168 246 +226 219 248 +209 226 248 +226 138 249 +219 226 249 +247 219 250 +124 247 250 +247 209 248 +219 247 248 +228 210 251 +209 228 251 +228 8 229 +210 228 229 +226 210 227 +138 226 227 +226 209 251 +210 226 251 +220 173 252 +139 220 252 +220 138 221 +173 220 221 +174 173 218 +9 174 218 +174 139 252 +173 174 252 +239 219 253 +139 239 253 +239 124 250 +219 239 250 +220 219 249 +138 220 249 +220 139 253 +219 220 253 +259 257 263 +256 259 263 +259 203 265 +257 259 265 +262 257 267 +202 262 267 +262 256 263 +257 262 263 +271 258 272 +256 271 272 +271 27 276 +258 271 276 +259 258 278 +203 259 278 +259 256 272 +258 259 272 +264 223 280 +222 264 280 +264 203 282 +223 264 282 +279 223 283 +8 279 283 +279 222 280 +223 279 280 +266 257 284 +222 266 284 +266 202 267 +257 266 267 +264 257 265 +203 264 265 +264 222 284 +257 264 284 +287 261 289 +260 287 289 +287 255 291 +261 287 291 +288 261 292 +202 288 292 +288 260 289 +261 288 289 +293 286 294 +260 293 294 +293 2 296 +286 293 296 +287 286 299 +255 287 299 +287 260 294 +286 287 294 +290 270 300 +256 290 300 +290 255 302 +270 290 302 +271 270 305 +27 271 305 +271 256 300 +270 271 300 +262 261 306 +256 262 306 +262 202 292 +261 262 292 +290 261 291 +255 290 291 +290 256 306 +261 290 306 +307 231 309 +213 307 309 +307 74 311 +231 307 311 +308 231 312 +28 308 312 +308 213 309 +231 308 309 +275 274 313 +213 275 313 +275 27 315 +274 275 315 +307 274 318 +74 307 318 +307 213 313 +274 307 313 +310 192 319 +75 310 319 +310 74 321 +192 310 321 +193 192 323 +4 193 323 +193 75 319 +192 193 319 +232 231 324 +75 232 324 +232 28 312 +231 232 312 +310 231 311 +74 310 311 +310 75 324 +231 310 324 +281 214 325 +204 281 325 +281 203 326 +214 281 326 +215 214 327 +28 215 327 +215 204 325 +214 215 325 +224 223 328 +204 224 328 +224 8 283 +223 224 283 +281 223 282 +203 281 282 +281 204 328 +223 281 328 +277 258 329 +213 277 329 +277 203 278 +258 277 278 +275 258 276 +27 275 276 +275 213 329 +258 275 329 +308 214 330 +213 308 330 +308 28 327 +214 308 327 +277 214 326 +203 277 326 +277 213 330 +214 277 330 +335 334 337 +273 335 337 +335 268 341 +334 335 341 +336 334 345 +63 336 345 +336 273 337 +334 336 337 +314 303 346 +273 314 346 +314 27 347 +303 314 347 +335 303 350 +268 335 350 +335 273 346 +303 335 346 +340 339 354 +333 340 354 +340 268 356 +339 340 356 +353 339 358 +13 353 358 +353 333 354 +339 353 354 +344 334 359 +333 344 359 +344 63 345 +334 344 345 +340 334 341 +268 340 341 +340 333 359 +334 340 359 +320 316 362 +79 320 362 +320 74 363 +316 320 363 +361 316 364 +63 361 364 +361 79 362 +316 361 362 +322 192 365 +79 322 365 +322 4 323 +192 322 323 +320 192 321 +74 320 321 +320 79 365 +192 320 365 +317 274 366 +273 317 366 +317 74 318 +274 317 318 +314 274 315 +27 314 315 +314 273 366 +274 314 366 +336 316 367 +273 336 367 +336 63 364 +316 336 364 +317 316 363 +74 317 363 +317 273 367 +316 317 367 +301 297 369 +269 301 369 +301 255 370 +297 301 370 +368 297 372 +254 368 372 +368 269 369 +297 368 369 +304 270 373 +269 304 373 +304 27 305 +270 304 305 +301 270 302 +255 301 302 +301 269 373 +270 301 373 +298 286 374 +285 298 374 +298 255 299 +286 298 299 +295 286 296 +2 295 296 +295 285 374 +286 295 374 +371 297 375 +285 371 375 +371 254 372 +297 371 372 +298 297 370 +255 298 370 +298 285 375 +297 298 375 +355 348 377 +338 355 377 +355 268 378 +348 355 378 +376 348 379 +254 376 379 +376 338 377 +348 376 377 +357 339 380 +338 357 380 +357 13 358 +339 357 358 +355 339 356 +268 355 356 +355 338 380 +339 355 380 +349 303 381 +269 349 381 +349 268 350 +303 349 350 +304 303 347 +27 304 347 +304 269 381 +303 304 381 +368 348 382 +269 368 382 +368 254 379 +348 368 379 +349 348 378 +268 349 378 +349 269 382 +348 349 382 +388 386 392 +385 388 392 +388 332 394 +386 388 394 +391 386 396 +331 391 396 +391 385 392 +386 391 392 +400 387 401 +385 400 401 +400 14 405 +387 400 405 +388 387 407 +332 388 407 +388 385 401 +387 388 401 +393 352 409 +351 393 409 +393 332 411 +352 393 411 +408 352 412 +13 408 412 +408 351 409 +352 408 409 +395 386 413 +351 395 413 +395 331 396 +386 395 396 +393 386 394 +332 393 394 +393 351 413 +386 393 413 +416 390 418 +389 416 418 +416 384 420 +390 416 420 +417 390 421 +331 417 421 +417 389 418 +390 417 418 +422 415 423 +389 422 423 +422 3 425 +415 422 425 +416 415 428 +384 416 428 +416 389 423 +415 416 423 +419 399 429 +385 419 429 +419 384 431 +399 419 431 +400 399 434 +14 400 434 +400 385 429 +399 400 429 +391 390 435 +385 391 435 +391 331 421 +390 391 421 +419 390 420 +384 419 420 +419 385 435 +390 419 435 +436 360 438 +342 436 438 +436 64 440 +360 436 440 +437 360 441 +63 437 441 +437 342 438 +360 437 438 +404 403 442 +342 404 442 +404 14 444 +403 404 444 +436 403 447 +64 436 447 +436 342 442 +403 436 442 +439 80 448 +79 439 448 +439 64 450 +80 439 450 +322 80 451 +4 322 451 +322 79 448 +80 322 448 +361 360 452 +79 361 452 +361 63 441 +360 361 441 +439 360 440 +64 439 440 +439 79 452 +360 439 452 +410 343 453 +333 410 453 +410 332 454 +343 410 454 +344 343 455 +63 344 455 +344 333 453 +343 344 453 +353 352 456 +333 353 456 +353 13 412 +352 353 412 +410 352 411 +332 410 411 +410 333 456 +352 410 456 +406 387 457 +342 406 457 +406 332 407 +387 406 407 +404 387 405 +14 404 405 +404 342 457 +387 404 457 +437 343 458 +342 437 458 +437 63 455 +343 437 455 +406 343 454 +332 406 454 +406 342 458 +343 406 458 +461 460 463 +402 461 463 +461 397 467 +460 461 467 +462 460 470 +15 462 470 +462 402 463 +460 462 463 +443 432 471 +402 443 471 +443 14 472 +432 443 472 +461 432 475 +397 461 475 +461 402 471 +432 461 471 +466 465 479 +459 466 479 +466 397 481 +465 466 481 +478 465 483 +6 478 483 +478 459 479 +465 478 479 +469 460 484 +459 469 484 +469 15 470 +460 469 470 +466 460 467 +397 466 467 +466 459 484 +460 466 484 +449 445 486 +65 449 486 +449 64 487 +445 449 487 +485 445 488 +15 485 488 +485 65 486 +445 485 486 +81 80 489 +65 81 489 +81 4 451 +80 81 451 +449 80 450 +64 449 450 +449 65 489 +80 449 489 +446 403 490 +402 446 490 +446 64 447 +403 446 447 +443 403 444 +14 443 444 +443 402 490 +403 443 490 +462 445 491 +402 462 491 +462 15 488 +445 462 488 +446 445 487 +64 446 487 +446 402 491 +445 446 491 +430 426 493 +398 430 493 +430 384 494 +426 430 494 +492 426 496 +383 492 496 +492 398 493 +426 492 493 +433 399 497 +398 433 497 +433 14 434 +399 433 434 +430 399 431 +384 430 431 +430 398 497 +399 430 497 +427 415 498 +414 427 498 +427 384 428 +415 427 428 +424 415 425 +3 424 425 +424 414 498 +415 424 498 +495 426 499 +414 495 499 +495 383 496 +426 495 496 +427 426 494 +384 427 494 +427 414 499 +426 427 499 +480 473 501 +464 480 501 +480 397 502 +473 480 502 +500 473 503 +383 500 503 +500 464 501 +473 500 501 +482 465 504 +464 482 504 +482 6 483 +465 482 483 +480 465 481 +397 480 481 +480 464 504 +465 480 504 +474 432 505 +398 474 505 +474 397 475 +432 474 475 +433 432 472 +14 433 472 +433 398 505 +432 433 505 +492 473 506 +398 492 506 +492 383 503 +473 492 503 +474 473 502 +397 474 502 +474 398 506 +473 474 506 +508 507 510 +47 508 510 +508 42 512 +507 508 512 +509 507 514 +22 509 514 +509 47 510 +507 509 510 +105 89 515 +47 105 515 +105 7 516 +89 105 516 +508 89 518 +42 508 518 +508 47 515 +89 508 515 +511 477 520 +476 511 520 +511 42 522 +477 511 522 +519 477 523 +6 519 523 +519 476 520 +477 519 520 +513 507 524 +476 513 524 +513 22 514 +507 513 514 +511 507 512 +42 511 512 +511 476 524 +507 511 524 +112 107 526 +98 112 526 +112 23 527 +107 112 527 +525 107 528 +22 525 528 +525 98 526 +107 525 526 +114 99 529 +98 114 529 +114 0 115 +99 114 115 +112 99 113 +23 112 113 +112 98 529 +99 112 529 +108 48 530 +47 108 530 +108 23 109 +48 108 109 +105 48 106 +7 105 106 +105 47 530 +48 105 530 +509 107 531 +47 509 531 +509 22 528 +107 509 528 +108 107 527 +23 108 527 +108 47 531 +107 108 531 +87 83 533 +43 87 533 +87 16 534 +83 87 534 +532 83 535 +15 532 535 +532 43 533 +83 532 533 +90 44 536 +43 90 536 +90 7 91 +44 90 91 +87 44 88 +16 87 88 +87 43 536 +44 87 536 +84 66 537 +65 84 537 +84 16 85 +66 84 85 +81 66 82 +4 81 82 +81 65 537 +66 81 537 +485 83 538 +65 485 538 +485 15 535 +83 485 535 +84 83 534 +16 84 534 +84 65 538 +83 84 538 +521 468 539 +459 521 539 +521 42 540 +468 521 540 +469 468 541 +15 469 541 +469 459 539 +468 469 539 +478 477 542 +459 478 542 +478 6 523 +477 478 523 +521 477 522 +42 521 522 +521 459 542 +477 521 542 +517 89 543 +43 517 543 +517 42 518 +89 517 518 +90 89 516 +7 90 516 +90 43 543 +89 90 543 +532 468 544 +43 532 544 +532 15 541 +468 532 541 +517 468 540 +42 517 540 +517 43 544 +468 517 544 + +element boundaries: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 1 +0 0 1 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element neighbours: +7 1 3 +0 6 14 +29 3 13 +2 28 0 +27 5 7 +4 26 58 +1 7 57 +6 0 4 +15 9 11 +8 14 54 +117 11 53 +10 116 8 +115 13 15 +12 114 2 +9 15 1 +14 8 12 +23 17 19 +16 22 30 +109 19 29 +18 108 16 +107 21 23 +20 106 234 +17 23 233 +22 16 20 +31 25 27 +24 30 230 +5 27 229 +26 4 24 +3 29 31 +28 2 18 +25 31 17 +30 24 28 +39 33 35 +32 38 46 +61 35 45 +34 60 32 +59 37 39 +36 58 218 +33 39 217 +38 32 36 +47 41 43 +40 46 214 +981 43 213 +42 980 40 +979 45 47 +44 978 34 +41 47 33 +46 40 44 +55 49 51 +48 54 62 +973 51 61 +50 972 48 +971 53 55 +52 970 10 +49 55 9 +54 48 52 +63 57 59 +56 62 6 +37 59 5 +58 36 56 +35 61 63 +60 34 50 +57 63 49 +62 56 60 +71 65 67 +64 70 78 +93 67 77 +66 92 64 +91 69 71 +68 90 122 +65 71 121 +70 64 68 +79 73 75 +72 78 118 +949 75 117 +74 948 72 +947 77 79 +76 946 66 +73 79 65 +78 72 76 +87 81 83 +80 86 94 +941 83 93 +82 940 80 +939 85 87 +84 938 -1 +81 87 -1 +86 80 84 +95 89 91 +88 94 -1 +69 91 -1 +90 68 88 +67 93 95 +92 66 82 +89 95 81 +94 88 92 +103 97 99 +96 102 110 +125 99 109 +98 124 96 +123 101 103 +100 122 -1 +97 103 -1 +102 96 100 +111 105 107 +104 110 -1 +21 107 -1 +106 20 104 +19 109 111 +108 18 98 +105 111 97 +110 104 108 +119 113 115 +112 118 126 +13 115 125 +114 12 112 +11 117 119 +116 10 74 +113 119 73 +118 112 116 +127 121 123 +120 126 70 +101 123 69 +122 100 120 +99 125 127 +124 98 114 +121 127 113 +126 120 124 +135 129 131 +128 134 142 +157 131 141 +130 156 128 +155 133 135 +132 154 186 +129 135 185 +134 128 132 +143 137 139 +136 142 182 +245 139 181 +138 244 136 +243 141 143 +140 242 130 +137 143 129 +142 136 140 +151 145 147 +144 150 158 +237 147 157 +146 236 144 +235 149 151 +148 234 -1 +145 151 -1 +150 144 148 +159 153 155 +152 158 -1 +133 155 -1 +154 132 152 +131 157 159 +156 130 146 +153 159 145 +158 152 156 +167 161 163 +160 166 174 +189 163 173 +162 188 160 +187 165 167 +164 186 -1 +161 167 -1 +166 160 164 +175 169 171 +168 174 -1 +341 171 -1 +170 340 168 +339 173 175 +172 338 162 +169 175 161 +174 168 172 +183 177 179 +176 182 190 +333 179 189 +178 332 176 +331 181 183 +180 330 138 +177 183 137 +182 176 180 +191 185 187 +184 190 134 +165 187 133 +186 164 184 +163 189 191 +188 162 178 +185 191 177 +190 184 188 +199 193 195 +192 198 206 +221 195 205 +194 220 192 +219 197 199 +196 218 250 +193 199 249 +198 192 196 +207 201 203 +200 206 246 +309 203 245 +202 308 200 +307 205 207 +204 306 194 +201 207 193 +206 200 204 +215 209 211 +208 214 222 +301 211 221 +210 300 208 +299 213 215 +212 298 42 +209 215 41 +214 208 212 +223 217 219 +216 222 38 +197 219 37 +218 196 216 +195 221 223 +220 194 210 +217 223 209 +222 216 220 +231 225 227 +224 230 238 +253 227 237 +226 252 224 +251 229 231 +228 250 26 +225 231 25 +230 224 228 +239 233 235 +232 238 22 +149 235 21 +234 148 232 +147 237 239 +236 146 226 +233 239 225 +238 232 236 +247 241 243 +240 246 254 +141 243 253 +242 140 240 +139 245 247 +244 138 202 +241 247 201 +246 240 244 +255 249 251 +248 254 198 +229 251 197 +250 228 248 +227 253 255 +252 226 242 +249 255 241 +254 248 252 +263 257 259 +256 262 270 +285 259 269 +258 284 256 +283 261 263 +260 282 314 +257 263 313 +262 256 260 +271 265 267 +264 270 310 +373 267 309 +266 372 264 +371 269 271 +268 370 258 +265 271 257 +270 264 268 +279 273 275 +272 278 286 +365 275 285 +274 364 272 +363 277 279 +276 362 490 +273 279 489 +278 272 276 +287 281 283 +280 286 486 +261 283 485 +282 260 280 +259 285 287 +284 258 274 +281 287 273 +286 280 284 +295 289 291 +288 294 302 +317 291 301 +290 316 288 +315 293 295 +292 314 474 +289 295 473 +294 288 292 +303 297 299 +296 302 470 +213 299 469 +298 212 296 +211 301 303 +300 210 290 +297 303 289 +302 296 300 +311 305 307 +304 310 318 +205 307 317 +306 204 304 +203 309 311 +308 202 266 +305 311 265 +310 304 308 +319 313 315 +312 318 262 +293 315 261 +314 292 312 +291 317 319 +316 290 306 +313 319 305 +318 312 316 +327 321 323 +320 326 334 +349 323 333 +322 348 320 +347 325 327 +324 346 378 +321 327 377 +326 320 324 +335 329 331 +328 334 374 +181 331 373 +330 180 328 +179 333 335 +332 178 322 +329 335 321 +334 328 332 +343 337 339 +336 342 350 +173 339 349 +338 172 336 +171 341 343 +340 170 -1 +337 343 -1 +342 336 340 +351 345 347 +344 350 -1 +325 347 -1 +346 324 344 +323 349 351 +348 322 338 +345 351 337 +350 344 348 +359 353 355 +352 358 366 +381 355 365 +354 380 352 +379 357 359 +356 378 -1 +353 359 -1 +358 352 356 +367 361 363 +360 366 -1 +277 363 -1 +362 276 360 +275 365 367 +364 274 354 +361 367 353 +366 360 364 +375 369 371 +368 374 382 +269 371 381 +370 268 368 +267 373 375 +372 266 330 +369 375 329 +374 368 372 +383 377 379 +376 382 326 +357 379 325 +378 356 376 +355 381 383 +380 354 370 +377 383 369 +382 376 380 +391 385 387 +384 390 398 +413 387 397 +386 412 384 +411 389 391 +388 410 442 +385 391 441 +390 384 388 +399 393 395 +392 398 438 +501 395 437 +394 500 392 +499 397 399 +396 498 386 +393 399 385 +398 392 396 +407 401 403 +400 406 414 +493 403 413 +402 492 400 +491 405 407 +404 490 -1 +401 407 -1 +406 400 404 +415 409 411 +408 414 -1 +389 411 -1 +410 388 408 +387 413 415 +412 386 402 +409 415 401 +414 408 412 +423 417 419 +416 422 430 +445 419 429 +418 444 416 +443 421 423 +420 442 -1 +417 423 -1 +422 416 420 +431 425 427 +424 430 -1 +597 427 -1 +426 596 424 +595 429 431 +428 594 418 +425 431 417 +430 424 428 +439 433 435 +432 438 446 +589 435 445 +434 588 432 +587 437 439 +436 586 394 +433 439 393 +438 432 436 +447 441 443 +440 446 390 +421 443 389 +442 420 440 +419 445 447 +444 418 434 +441 447 433 +446 440 444 +455 449 451 +448 454 462 +477 451 461 +450 476 448 +475 453 455 +452 474 506 +449 455 505 +454 448 452 +463 457 459 +456 462 502 +565 459 501 +458 564 456 +563 461 463 +460 562 450 +457 463 449 +462 456 460 +471 465 467 +464 470 478 +557 467 477 +466 556 464 +555 469 471 +468 554 298 +465 471 297 +470 464 468 +479 473 475 +472 478 294 +453 475 293 +474 452 472 +451 477 479 +476 450 466 +473 479 465 +478 472 476 +487 481 483 +480 486 494 +509 483 493 +482 508 480 +507 485 487 +484 506 282 +481 487 281 +486 480 484 +495 489 491 +488 494 278 +405 491 277 +490 404 488 +403 493 495 +492 402 482 +489 495 481 +494 488 492 +503 497 499 +496 502 510 +397 499 509 +498 396 496 +395 501 503 +500 394 458 +497 503 457 +502 496 500 +511 505 507 +504 510 454 +485 507 453 +506 484 504 +483 509 511 +508 482 498 +505 511 497 +510 504 508 +519 513 515 +512 518 526 +541 515 525 +514 540 512 +539 517 519 +516 538 570 +513 519 569 +518 512 516 +527 521 523 +520 526 566 +629 523 565 +522 628 520 +627 525 527 +524 626 514 +521 527 513 +526 520 524 +535 529 531 +528 534 542 +621 531 541 +530 620 528 +619 533 535 +532 618 746 +529 535 745 +534 528 532 +543 537 539 +536 542 742 +517 539 741 +538 516 536 +515 541 543 +540 514 530 +537 543 529 +542 536 540 +551 545 547 +544 550 558 +573 547 557 +546 572 544 +571 549 551 +548 570 730 +545 551 729 +550 544 548 +559 553 555 +552 558 726 +469 555 725 +554 468 552 +467 557 559 +556 466 546 +553 559 545 +558 552 556 +567 561 563 +560 566 574 +461 563 573 +562 460 560 +459 565 567 +564 458 522 +561 567 521 +566 560 564 +575 569 571 +568 574 518 +549 571 517 +570 548 568 +547 573 575 +572 546 562 +569 575 561 +574 568 572 +583 577 579 +576 582 590 +605 579 589 +578 604 576 +603 581 583 +580 602 634 +577 583 633 +582 576 580 +591 585 587 +584 590 630 +437 587 629 +586 436 584 +435 589 591 +588 434 578 +585 591 577 +590 584 588 +599 593 595 +592 598 606 +429 595 605 +594 428 592 +427 597 599 +596 426 -1 +593 599 -1 +598 592 596 +607 601 603 +600 606 -1 +581 603 -1 +602 580 600 +579 605 607 +604 578 594 +601 607 593 +606 600 604 +615 609 611 +608 614 622 +637 611 621 +610 636 608 +635 613 615 +612 634 -1 +609 615 -1 +614 608 612 +623 617 619 +616 622 -1 +533 619 -1 +618 532 616 +531 621 623 +620 530 610 +617 623 609 +622 616 620 +631 625 627 +624 630 638 +525 627 637 +626 524 624 +523 629 631 +628 522 586 +625 631 585 +630 624 628 +639 633 635 +632 638 582 +613 635 581 +634 612 632 +611 637 639 +636 610 626 +633 639 625 +638 632 636 +647 641 643 +640 646 654 +669 643 653 +642 668 640 +667 645 647 +644 666 698 +641 647 697 +646 640 644 +655 649 651 +648 654 694 +757 651 693 +650 756 648 +755 653 655 +652 754 642 +649 655 641 +654 648 652 +663 657 659 +656 662 670 +749 659 669 +658 748 656 +747 661 663 +660 746 -1 +657 663 -1 +662 656 660 +671 665 667 +664 670 -1 +645 667 -1 +666 644 664 +643 669 671 +668 642 658 +665 671 657 +670 664 668 +679 673 675 +672 678 686 +701 675 685 +674 700 672 +699 677 679 +676 698 -1 +673 679 -1 +678 672 676 +687 681 683 +680 686 -1 +853 683 -1 +682 852 680 +851 685 687 +684 850 674 +681 687 673 +686 680 684 +695 689 691 +688 694 702 +845 691 701 +690 844 688 +843 693 695 +692 842 650 +689 695 649 +694 688 692 +703 697 699 +696 702 646 +677 699 645 +698 676 696 +675 701 703 +700 674 690 +697 703 689 +702 696 700 +711 705 707 +704 710 718 +733 707 717 +706 732 704 +731 709 711 +708 730 762 +705 711 761 +710 704 708 +719 713 715 +712 718 758 +821 715 757 +714 820 712 +819 717 719 +716 818 706 +713 719 705 +718 712 716 +727 721 723 +720 726 734 +813 723 733 +722 812 720 +811 725 727 +724 810 554 +721 727 553 +726 720 724 +735 729 731 +728 734 550 +709 731 549 +730 708 728 +707 733 735 +732 706 722 +729 735 721 +734 728 732 +743 737 739 +736 742 750 +765 739 749 +738 764 736 +763 741 743 +740 762 538 +737 743 537 +742 736 740 +751 745 747 +744 750 534 +661 747 533 +746 660 744 +659 749 751 +748 658 738 +745 751 737 +750 744 748 +759 753 755 +752 758 766 +653 755 765 +754 652 752 +651 757 759 +756 650 714 +753 759 713 +758 752 756 +767 761 763 +760 766 710 +741 763 709 +762 740 760 +739 765 767 +764 738 754 +761 767 753 +766 760 764 +775 769 771 +768 774 782 +797 771 781 +770 796 768 +795 773 775 +772 794 826 +769 775 825 +774 768 772 +783 777 779 +776 782 822 +885 779 821 +778 884 776 +883 781 783 +780 882 770 +777 783 769 +782 776 780 +791 785 787 +784 790 798 +877 787 797 +786 876 784 +875 789 791 +788 874 1002 +785 791 1001 +790 784 788 +799 793 795 +792 798 998 +773 795 997 +794 772 792 +771 797 799 +796 770 786 +793 799 785 +798 792 796 +807 801 803 +800 806 814 +829 803 813 +802 828 800 +827 805 807 +804 826 986 +801 807 985 +806 800 804 +815 809 811 +808 814 982 +725 811 981 +810 724 808 +723 813 815 +812 722 802 +809 815 801 +814 808 812 +823 817 819 +816 822 830 +717 819 829 +818 716 816 +715 821 823 +820 714 778 +817 823 777 +822 816 820 +831 825 827 +824 830 774 +805 827 773 +826 804 824 +803 829 831 +828 802 818 +825 831 817 +830 824 828 +839 833 835 +832 838 846 +861 835 845 +834 860 832 +859 837 839 +836 858 890 +833 839 889 +838 832 836 +847 841 843 +840 846 886 +693 843 885 +842 692 840 +691 845 847 +844 690 834 +841 847 833 +846 840 844 +855 849 851 +848 854 862 +685 851 861 +850 684 848 +683 853 855 +852 682 -1 +849 855 -1 +854 848 852 +863 857 859 +856 862 -1 +837 859 -1 +858 836 856 +835 861 863 +860 834 850 +857 863 849 +862 856 860 +871 865 867 +864 870 878 +893 867 877 +866 892 864 +891 869 871 +868 890 -1 +865 871 -1 +870 864 868 +879 873 875 +872 878 -1 +789 875 -1 +874 788 872 +787 877 879 +876 786 866 +873 879 865 +878 872 876 +887 881 883 +880 886 894 +781 883 893 +882 780 880 +779 885 887 +884 778 842 +881 887 841 +886 880 884 +895 889 891 +888 894 838 +869 891 837 +890 868 888 +867 893 895 +892 866 882 +889 895 881 +894 888 892 +903 897 899 +896 902 910 +925 899 909 +898 924 896 +923 901 903 +900 922 954 +897 903 953 +902 896 900 +911 905 907 +904 910 950 +1013 907 949 +906 1012 904 +1011 909 911 +908 1010 898 +905 911 897 +910 904 908 +919 913 915 +912 918 926 +1005 915 925 +914 1004 912 +1003 917 919 +916 1002 -1 +913 919 -1 +918 912 916 +927 921 923 +920 926 -1 +901 923 -1 +922 900 920 +899 925 927 +924 898 914 +921 927 913 +926 920 924 +935 929 931 +928 934 942 +957 931 941 +930 956 928 +955 933 935 +932 954 -1 +929 935 -1 +934 928 932 +943 937 939 +936 942 -1 +85 939 -1 +938 84 936 +83 941 943 +940 82 930 +937 943 929 +942 936 940 +951 945 947 +944 950 958 +77 947 957 +946 76 944 +75 949 951 +948 74 906 +945 951 905 +950 944 948 +959 953 955 +952 958 902 +933 955 901 +954 932 952 +931 957 959 +956 930 946 +953 959 945 +958 952 956 +967 961 963 +960 966 974 +989 963 973 +962 988 960 +987 965 967 +964 986 1018 +961 967 1017 +966 960 964 +975 969 971 +968 974 1014 +53 971 1013 +970 52 968 +51 973 975 +972 50 962 +969 975 961 +974 968 972 +983 977 979 +976 982 990 +45 979 989 +978 44 976 +43 981 983 +980 42 810 +977 983 809 +982 976 980 +991 985 987 +984 990 806 +965 987 805 +986 964 984 +963 989 991 +988 962 978 +985 991 977 +990 984 988 +999 993 995 +992 998 1006 +1021 995 1005 +994 1020 992 +1019 997 999 +996 1018 794 +993 999 793 +998 992 996 +1007 1001 1003 +1000 1006 790 +917 1003 789 +1002 916 1000 +915 1005 1007 +1004 914 994 +1001 1007 993 +1006 1000 1004 +1015 1009 1011 +1008 1014 1022 +909 1011 1021 +1010 908 1008 +907 1013 1015 +1012 906 970 +1009 1015 969 +1014 1008 1012 +1023 1017 1019 +1016 1022 966 +997 1019 965 +1018 996 1016 +995 1021 1023 +1020 994 1010 +1017 1023 1009 +1022 1016 1020 + +projections: +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 + +element region: +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 + +surface region: +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 +-1 -1 -1 diff --git a/extensions/demo/multimesh/src/Anisotropy.h b/extensions/demo/multimesh/src/Anisotropy.h new file mode 100644 index 00000000..82ce4fc8 --- /dev/null +++ b/extensions/demo/multimesh/src/Anisotropy.h @@ -0,0 +1,175 @@ +#include "AMDiS.h" + +inline double pow2(const double &v) +{ + return v * v; +} + +inline double pow4(const double &v) +{ + return v * v * v * v; +} + +// === Anisotropy functions for 2D === + +class Aniso2d_Square : public AbstractFunction<double, WorldVector<double> > +{ +public: + Aniso2d_Square(double g) + : AbstractFunction<double, WorldVector<double> >(2), + gamma(g), + anisoReg(1e-6) + { + eps2 = 1.0 - 3.0 * gamma; + eps4 = 4.0 * gamma / (1.0 - 3.0 * gamma); + } + + double operator()(const WorldVector<double>& n) const + { + double eta = eps2 * + (1.0 + eps4 * (pow4(n[0]) + pow4(n[1])) / (pow4(norm(&n)) + anisoReg)); + + return eta * eta; + } + +private: + double gamma; + + double anisoReg; + + double eps2, eps4; +}; + + +class Aniso2d_Laplace : public AbstractFunction<WorldMatrix<double>, WorldVector<double> > +{ +public: + Aniso2d_Laplace(double g) + : AbstractFunction<WorldMatrix<double>, WorldVector<double> >(2), + gamma(g), + anisoReg(1e-6) + { + eps2 = 1.0 - 3.0 * gamma; + eps4 = 4.0 * gamma / (1.0 - 3.0 * gamma); + } + + WorldMatrix<double> operator()(const WorldVector<double>& n) const + { + WorldMatrix<double> result; + result.set(0.0); + + double d = (pow4(n[0]) + pow4(n[1])) / (pow4(norm(&n)) + anisoReg); + double normSquare = pow2(norm(&n)) + anisoReg; + double eta = eps2 * (1 + eps4 * d); + + result[0][0] = + eta * (eta + 16.0 * gamma * (pow2(n[0]) / normSquare - d)); + + result[1][1] = + eta * (eta + 16.0 * gamma * (pow2(n[1]) / normSquare - d)); + + return result; + } + +private: + double gamma; + + double anisoReg; + + double eps2, eps4; +}; + + +// === Anisotropy functions for 3D === + +class Aniso3d_Square : public AbstractFunction<double, WorldVector<double> > +{ +public: + Aniso3d_Square(double g) + : AbstractFunction<double, WorldVector<double> >(2), + gamma(g), + anisoReg(1e-6) + { + eps2 = 1.0 - 3.0 * gamma; + eps4 = 4.0 * gamma / (1.0 - 3.0 * gamma); + } + + double operator()(const WorldVector<double>& n) const + { + double eta = eps2 * + (1.0 + eps4 * (pow4(n[0]) + pow4(n[1]) + pow4(n[2])) / (pow4(norm(&n)) + anisoReg)); + + return eta * eta; + } + +private: + double gamma; + + double anisoReg; + + double eps2, eps4; +}; + + +class Aniso3d_Laplace : public AbstractFunction<WorldMatrix<double>, WorldVector<double> > +{ +public: + Aniso3d_Laplace(double g) + : AbstractFunction<WorldMatrix<double>, WorldVector<double> >(2), + gamma(g), + anisoReg(1e-6) + { + eps2 = 1.0 - 3.0 * gamma; + eps4 = 4.0 * gamma / (1.0 - 3.0 * gamma); + } + + WorldMatrix<double> operator()(const WorldVector<double>& n) const + { + WorldMatrix<double> &result = const_cast<WorldMatrix<double>&>(tmpWorldMat); + result.set(0.0); + + double d = (pow4(n[0]) + pow4(n[1]) + pow4(n[2])) / (pow4(norm(&n)) + anisoReg); + double normSquare = pow2(norm(&n)) + anisoReg; + double eta = eps2 * (1 + eps4 * d); + + result[0][0] = + eta * (eta + 16.0 * gamma * (pow2(n[0]) / normSquare - d)); + + result[1][1] = + eta * (eta + 16.0 * gamma * (pow2(n[1]) / normSquare - d)); + + result[2][2] = + eta * (eta + 16.0 * gamma * (pow2(n[2]) / normSquare - d)); + + return result; + } + +private: + WorldMatrix<double> tmpWorldMat; + + double gamma; + + double anisoReg; + + double eps2, eps4; +}; + + +class NullFct : public AbstractFunction<WorldVector<double>, WorldMatrix<double> > +{ +public: + + NullFct() + : AbstractFunction<WorldVector<double>, WorldMatrix<double> >(1) + { + result.set(0.0); + } + + WorldVector<double> operator()(const WorldMatrix<double>& n) const + { + return result; + } + +private: + WorldVector<double> result; +}; diff --git a/extensions/demo/multimesh/src/CahnHilliard_mm.h b/extensions/demo/multimesh/src/CahnHilliard_mm.h new file mode 100644 index 00000000..ab4f6072 --- /dev/null +++ b/extensions/demo/multimesh/src/CahnHilliard_mm.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * + * Extension of AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: Simon Praetorius et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + +#ifndef CAHN_HILLIARD_H +#define CAHN_HILLIARD_H + +#include "AMDiS.h" +#include "BaseProblem.h" +#include "ProblemStatMassConserve_mm.h" +#include "chns.h" +#include "operations/functors.hpp" + +namespace AMDiS { namespace base_problems { + +namespace detail { + + struct c_; // name for the concentration component + + class CahnHilliard_mm : public BaseProblem<ProblemStatMassConserve> + { + public: // definition of types + + typedef BaseProblem<ProblemStatMassConserve> super; + typedef CahnHilliard_mm self; + using super::prob; + + public: // public methods + + CahnHilliard_mm(const std::string &name_); + ~CahnHilliard_mm() {}; + + void solveInitialProblem(AMDiS::AdaptInfo *adaptInfo) override; + + double getEpsilon() { return eps; } + int getDoubleWellType() { return doubleWell; } + + void fillOperators() override; + void fillBoundaryConditions() override {} + + void finalizeData() override; + + protected: // protected variables + + bool useMobility; + bool useReinit; + + unsigned dim; + + int doubleWell; + + double gamma; + double eps; + double minusEps; + double epsInv; + double minusEpsInv; + double epsSqr; + double minusEpsSqr; + }; + + + class MobilityCH0_mm : public FunctorBase //: public AbstractFunction<double,double> + { + public: + MobilityCH0_mm(double gamma_=1.0) : + gamma(gamma_), + delta(1.e-6) { } + + typedef double result_type; + int getDegree(int d0) const { return d0 * 4; } + + double operator()(const double &ch) const + { + double phase = std::max(0.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(phase)*sqr(phase-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; + }; + + class MobilityCH1_mm : public FunctorBase // : public AbstractFunction<double,double> + { + public: + MobilityCH1_mm(double gamma_=1.0) : + gamma(gamma_), + delta(1.e-6) { } + + typedef double result_type; + int getDegree(int d0) const { return d0 * 4; } + + double operator()(const double &ch) const + { + double phase = std::max(-1.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(sqr(phase)-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; + }; + +} // end namespace detail + +typedef detail::CahnHilliard_mm CahnHilliard_mm; + +} } + +#include "CahnHilliard_mm.hh" + +#endif // CAHN_HILLIARD_H diff --git a/extensions/demo/multimesh/src/CahnHilliard_mm.hh b/extensions/demo/multimesh/src/CahnHilliard_mm.hh new file mode 100644 index 00000000..978ce3f6 --- /dev/null +++ b/extensions/demo/multimesh/src/CahnHilliard_mm.hh @@ -0,0 +1,222 @@ +/****************************************************************************** + * + * Extension of AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: Simon Praetorius et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + + +#include "SignedDistFunctors.h" +#include "PhaseFieldConvert.h" + +#include "HL_SignedDistTraverse.h" +#include "Recovery.h" +#include "GenericOperatorTerm.h" + +namespace AMDiS { namespace base_problems { + +namespace detail { + + +CahnHilliard_mm::CahnHilliard_mm(const std::string &name_) : + super(name_), + useMobility(false), + useReinit(false), + doubleWell(0), + gamma(1.0), + eps(0.1), + minusEps(-0.1), + epsInv(10.0), + minusEpsInv(-10.0), + epsSqr(0.01), + minusEpsSqr(-0.01) +{ + // parameters for CH + Parameters::get(name_ + "->use mobility", useMobility); // mobility + Parameters::get(name_ + "->gamma", gamma); // mobility + Parameters::get(name_ + "->epsilon", eps); // interface width + + // type of double well: 0= [0,1], 1= [-1,1] + Parameters::get(name_ + "->double-well type", doubleWell); + + Parameters::get(name_ + "->use reinit", useReinit); + + // transformation of the parameters + minusEps = -eps; + epsInv = 1.0/eps; + minusEpsInv = -epsInv; + epsSqr = sqr(eps); + minusEpsSqr = -epsSqr; +} + + + +void CahnHilliard_mm::solveInitialProblem(AdaptInfo *adaptInfo) +{ + using namespace AMDiS::extensions; + Flag initFlag = self::initDataFromFile(adaptInfo); + + if (!initFlag.isSet(DATA_ADOPTED)) { + int initialInterface = 0; + Initfile::get(self::name + "->initial interface", initialInterface); + double initialEps = eps; + Initfile::get(self::name + "->initial epsilon", initialEps); + + if (initialInterface == 0) { + /// horizontale Linie + double a= 0.0, dir= -1.0; + Initfile::get(self::name + "->line->pos", a); + Initfile::get(self::name + "->line->direction", dir); + prob->getSolution()->getDOFVector(0)->interpol(new Plane(a, dir)); + } + else if (initialInterface == 1) { + /// schraege Linie + double theta = m_pi/4.0; + prob->getSolution()->getDOFVector(0)->interpol(new PlaneRotation(0.0, theta, 1.0)); + transformDOFInterpolation(prob->getSolution()->getDOFVector(0),new PlaneRotation(0.0, -theta, -1.0), new AMDiS::Min<double>); + } + else if (initialInterface == 2) { + /// Ellipse + double a= 1.0, b= 1.0; + Initfile::get(self::name + "->ellipse->a", a); + Initfile::get(self::name + "->ellipse->b", b); + prob->getSolution()->getDOFVector(0)->interpol(new Ellipse(a,b)); + } + else if (initialInterface == 3) { + /// zwei horizontale Linien + double a= 0.75, b= 0.375; + Initfile::get(self::name + "->lines->pos1", a); + Initfile::get(self::name + "->lines->pos2", b); + prob->getSolution()->getDOFVector(0)->interpol(new Plane(a, -1.0)); + transformDOFInterpolation(prob->getSolution()->getDOFVector(0),new Plane(b, 1.0), new AMDiS::Max<double>); + } + else if (initialInterface == 4) { + /// Kreis + double radius= 1.0; + Initfile::get(self::name + "->kreis->radius", radius); + prob->getSolution()->getDOFVector(0)->interpol(new Circle(radius)); + } else if (initialInterface == 5) { + /// Rechteck + double width = 0.5; + double height = 0.3; + WorldVector<double> center; center.set(0.5); + Initfile::get(self::name + "->rectangle->width", width); + Initfile::get(self::name + "->rectangle->height", height); + Initfile::get(self::name + "->rectangle->center", center); + prob->getSolution()->getDOFVector(0)->interpol(new Rectangle(width, height, center)); + } + + if (useReinit) { + FiniteElemSpace* feSpace = FiniteElemSpace::provideFeSpace( + const_cast<DOFAdmin*>(self::getMesh()->getVertexAdmin()), + Lagrange::getLagrange(self::getMesh()->getDim(), 1), + self::getMesh(), + "P1"); + DOFVector<double> tmp(feSpace, "tmp"); + tmp.interpol(prob->getSolution()->getDOFVector(0)); + + HL_SignedDistTraverse reinit("reinit", self::getMesh()->getDim()); + reinit.calcSignedDistFct(adaptInfo, &tmp); + +#ifndef HAVE_PARALLEL_DOMAIN_AMDIS + Recovery recovery(L2_NORM, 1); + recovery.recoveryUh(&tmp, *prob->getSolution()->getDOFVector(0)); +#else + prob->getSolution()->getDOFVector(0)->interpol(&tmp); +#endif + } + + + /// create phase-field from signed-dist-function + if (doubleWell == 0) { + forEachDOF(prob->getSolution()->getDOFVector(0), + new SignedDistToPhaseField(initialEps)); + } else { + forEachDOF(prob->getSolution()->getDOFVector(0), + new SignedDistToCh(initialEps)); + } + } +} + + +void CahnHilliard_mm::fillOperators() +{ + const FiniteElemSpace* feSpace0 = prob->getFeSpace(0); + const FiniteElemSpace* feSpace1 = prob->getFeSpace(1); + + DOFVector<double>* c = prob->getSolution()->getDOFVector(0); +// DOFVector<double>* mu = prob->getSolution()->getDOFVector(1); + + // -nabla*(grad(c)) + Operator *opChL = new Operator(feSpace0, feSpace0); + addSOT(opChL, 1.0); + + // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 + Operator *opChLM = new Operator(feSpace1, feSpace1); + if (useMobility) { + if (doubleWell == 0) + addSOT(opChLM, function_(MobilityCH0_mm(gamma), valueOf(c)) ); + else + addSOT(opChLM, function_(MobilityCH1_mm(gamma), valueOf(c)) ); + } else + addSOT(opChLM, gamma ); + + // -2*c_old^3 + 3/2*c_old^2 + Operator *opChWExpl = new Operator(feSpace0, feSpace0); + Operator *opChWImpl = new Operator(feSpace0, feSpace0); + if (doubleWell == 0) { + addZOT(opChWExpl, -2.0*pow<3>(valueOf(c)) + 1.5*pow<2>(valueOf(c))); + addZOT(opChWImpl, -3.0*pow<2>(valueOf(c)) + 3.0*valueOf(c) - 0.5); + } else { + addZOT(opChWExpl, -2.0*pow<3>(valueOf(c))); + addZOT(opChWImpl, -3.0*pow<2>(valueOf(c)) + 1.0); + } + + + // mu + eps^2*laplace(c) + c - 3*(c_old^2)*c = -2*c_old^3 [+ BC] + // ---------------------------------------------------------------------- + prob->addMatrixOperator(*opChWImpl, 0, 0); /// < -3*phi*c*c_old^2 , psi > + prob->addMatrixOperator(*opChL, 0, 0, &minusEpsSqr, &minusEpsSqr); /// < -eps^2*phi*grad(c) , grad(psi) > + // . . . vectorOperators . . . . . . . . . . . . . . . + prob->addVectorOperator(*opChWExpl, 0); /// < -2*phi*c_old^3 , psi > + + Operator *opM01new = new Operator(feSpace0, feSpace1); + addZOT(opM01new, 1.0); + prob->addMatrixOperator(*opM01new, 0, 1); /// < phi*mu , psi > + + // dt(c) = laplace(mu) - u*grad(c) + // ----------------------------------- + Operator *opM10new = new Operator(feSpace1, feSpace0); + addZOT(opM10new, 1.0); + prob->addMatrixOperator(*opM10new, 1, 0, self::getInvTau(), self::getInvTau()); /// < phi*c/tau , psi > + prob->addMatrixOperator(*opChLM, 1, 1); /// < phi*grad(mu) , grad(psi) > + // . . . vectorOperators . . . . . . . . . . . . . . . + Operator *opChMold = new Operator(feSpace1, feSpace0); + addZOT(opChMold, 1.0); opChMold->setUhOld(prob->getOldSolution(0)); +// addZOT(opChMold, valueOf(prob->getSolution(0))); + prob->addVectorOperator(*opChMold, 1, self::getInvTau(), self::getInvTau()); /// < phi*c^old/tau , psi > +} + + + +void CahnHilliard_mm::finalizeData() +{ +// self::setAssembleMatrixOnlyOnce_butTimestepChange(0,1); +// self::setAssembleMatrixOnlyOnce_butTimestepChange(1,0); +// if (!useMobility) +// self::setAssembleMatrixOnlyOnce_butTimestepChange(1,1); +} + +} // end namespace detail + +} } diff --git a/extensions/demo/multimesh/src/MyProblemInstat.cc b/extensions/demo/multimesh/src/MyProblemInstat.cc new file mode 100644 index 00000000..7f13a648 --- /dev/null +++ b/extensions/demo/multimesh/src/MyProblemInstat.cc @@ -0,0 +1,158 @@ +#include "AMDiS.h" +#include "MyProblemInstat.h" +#include "Refinement.h" + +using namespace AMDiS; + +void MyProblemInstat::solveInitialProblem(AdaptInfo *adaptInfo) +{ + FUNCNAME("MyProblemInstat::solveInitialProblem()"); + + + string phiArh = "", rhoArh = ""; int nProc; + Parameters::get("dendrites->read phi arh", phiArh); + Parameters::get("dendrites->read rho arh", rhoArh); + Parameters::get("dendrites->number of processors", nProc); + + if (phiArh != "" && rhoArh != "") { + + io::Arh2Reader::readFile(phiArh.c_str(), + problemStat->getSolution(0), NULL, NULL, true, nProc); + io::Arh2Reader::readFile(rhoArh.c_str(), + problemStat->getSolution(1), NULL, NULL, true, nProc); + + oldSolution->getDOFVector(0)->copy(*(problemStat->getSolution()->getDOFVector(0))); + oldSolution->getDOFVector(1)->copy(*(problemStat->getSolution()->getDOFVector(1))); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(false); +#endif + return; + } + + if (serial <= 0) { + + double r = 0.0; + Parameters::get("dendrites->radius", r); + + AbstractFunction<double, WorldVector<double> > *signedDistFct = new Circle(r); + AbstractFunction<double, WorldVector<double> > *initialPhaseField = + new InitialPhaseField(signedDistFct); + + Refinement refinePhi(problemStat->getSolution()->getDOFVector(0), + initialPhaseField, + problemStat->getRefinementManager(0), + problemStat->getCoarseningManager(0)); + refinePhi.refine(hInitInterface); + + if (problemStat->getMesh(0) != problemStat->getMesh(1)) { + Refinement refineRho(problemStat->getSolution()->getDOFVector(1), + initialPhaseField, + problemStat->getRefinementManager(1), + problemStat->getCoarseningManager(1)); + refineRho.refine(hInitInterface); + } + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(false); +#endif + problemStat->getSolution()->getDOFVector(1)->set(-rhoInitial); + + delete signedDistFct; + delete initialPhaseField; + } + + problemStat->getMesh(0)->dofCompress(); + problemStat->getMesh(1)->dofCompress(); +} + + +void MyProblemInstat::closeTimestep(AdaptInfo *adaptInfo) +{ + FUNCNAME("MyProblemInstat::closeTimestep()"); + + ProblemInstat::closeTimestep(adaptInfo); + + if (refInterface) { + Refinement refinePhi(problemStat->getSolution()->getDOFVector(0), + NULL, + problemStat->getRefinementManager(0), + problemStat->getCoarseningManager(0)); + refinePhi.refine(hInterface); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(false); +#endif + } + + if (problemStat->getMesh(0)->getDim() == 3) + return; + +#ifndef HAVE_PARALLEL_DOMAIN_AMDIS + + /* + mtl::dense_vector<double> localVec(problemStat->getFeSpace(0)->getBasisFcts()->getNumber()); + DOFVector<double> *phi = problemStat->getSolution()->getDOFVector(0); + + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(problemStat->getMesh(0), -1, + Mesh::CALL_LEAF_EL | + Mesh::FILL_COORDS); + while (elInfo) { + std::vector<int> zeroCoords(0); + + for (int i = 0; i < 3; i++) + if (elInfo->getCoord(i)[1] == 0.0) + zeroCoords.push_back(i); + + if (zeroCoords.size() == 2) { + phi->getLocalVector(elInfo->getElement(), localVec); + + if (sign(localVec[zeroCoords[0]]) != sign(localVec[zeroCoords[1]])) { + if (elInfo->getCoord(zeroCoords[0])[0] > elInfo->getCoord(zeroCoords[1])[0]) + std::swap(zeroCoords[0], zeroCoords[1]); + + TEST_EXIT(localVec[zeroCoords[0]] > 0.0)("Error 1\n"); + TEST_EXIT(localVec[zeroCoords[1]] < 0.0)("Error 2\n"); + + double m = (localVec[zeroCoords[0]] - localVec[zeroCoords[1]]) / + (elInfo->getCoord(zeroCoords[1])[0] - elInfo->getCoord(zeroCoords[0])[0]); + double xZero = + elInfo->getCoord(zeroCoords[0])[0] + (localVec[zeroCoords[0]] / m); + + MSG("Tip-x position at t = %f : %f\n", adaptInfo->getTime(), xZero); + } + } + + zeroCoords.clear(); + + for (int i = 0; i < 3; i++) + if (elInfo->getCoord(i)[0] == 0.0) + zeroCoords.push_back(i); + + if (zeroCoords.size() == 2) { + phi->getLocalVector(elInfo->getElement(), localVec); + + if (sign(localVec[zeroCoords[0]]) != sign(localVec[zeroCoords[1]])) { + if (elInfo->getCoord(zeroCoords[0])[1] > elInfo->getCoord(zeroCoords[1])[1]) + std::swap(zeroCoords[0], zeroCoords[1]); + + TEST_EXIT(localVec[zeroCoords[0]] > 0.0)("Error 1\n"); + TEST_EXIT(localVec[zeroCoords[1]] < 0.0)("Error 2\n"); + + double m = (localVec[zeroCoords[0]] - localVec[zeroCoords[1]]) / + (elInfo->getCoord(zeroCoords[1])[1] - elInfo->getCoord(zeroCoords[0])[1]); + double yZero = + elInfo->getCoord(zeroCoords[0])[1] + (localVec[zeroCoords[0]] / m); + + MSG("Tip-y position at t = %f : %f\n", adaptInfo->getTime(), yZero); + } + } + + elInfo = stack.traverseNext(elInfo); + } + */ + +#endif + +} diff --git a/extensions/demo/multimesh/src/MyProblemInstat.h b/extensions/demo/multimesh/src/MyProblemInstat.h new file mode 100644 index 00000000..b85aadad --- /dev/null +++ b/extensions/demo/multimesh/src/MyProblemInstat.h @@ -0,0 +1,96 @@ +#include "AMDiS.h" + +using namespace AMDiS; + +class Circle : public AbstractFunction<double, WorldVector<double> > +{ +public: + Circle(double radius_, WorldVector<double> midPoint_) + : radius(radius_), + midPoint(midPoint_) + {} + + Circle(double radius_) + : radius(radius_) + { + midPoint.set(0.0); + } + + double operator()(const WorldVector<double>& x) const + { + double result = 0.0; + for (int k = 0; k < x.getSize(); k++) + result += sqr(x[k] - midPoint[k]); + + result = sqrt(result) - radius; + return result; + }; +private: + double radius; + WorldVector<double> midPoint; +}; + + +class InitialPhaseField : public AbstractFunction<double, WorldVector<double> > +{ +public: + InitialPhaseField(AbstractFunction<double,WorldVector<double> > *dist_) + : dist(dist_) + {} + + double operator()(const WorldVector<double> &x) const + { + return -tanh((*dist)(x) / sqrt(2.0)); + } + +private: + AbstractFunction<double,WorldVector<double> > *dist; +}; + + +class MyProblemInstat : public ProblemInstat +{ +public: + MyProblemInstat(std::string name, ProblemStat &probStat) + : ProblemInstat(name, probStat), + hInitInterface(0.0), + hInterface(0.0), + refInterface(0), + rhoInitial(0.0), + serial(0) + { + FUNCNAME("MyProblemInstat::MyProblemInstat()"); + + Parameters::get("dendrites->h init interface", hInitInterface); + Parameters::get("dendrites->h interface", hInterface); + Parameters::get("dendrites->ref interface", refInterface); + Parameters::get("dendrites->karma model->rho initial", rhoInitial); + Parameters::get("dendrites->space->input->read serialization", serial); + + TEST_EXIT(rhoInitial > 0.0)("Initial rho must be greater than 0!\n"); + } + + void solveInitialProblem(AdaptInfo *adaptInfo); + + void closeTimestep(AdaptInfo *adaptInfo); + +private: + inline int sign(double value) + { + return (value < 0.0 ? 1 : 0); + } + +private: + /// Minimal length of each edge of all elements in the phase field transition; + double hInitInterface; + + double hInterface; + + /// If non zero, do not use estimator and marking strategy, but instead the interface + /// refinement algorithm on the solution vector. + int refInterface; + + double rhoInitial; + + int serial; +}; diff --git a/extensions/demo/multimesh/src/Refinement.cc b/extensions/demo/multimesh/src/Refinement.cc new file mode 100644 index 00000000..ffd6a57f --- /dev/null +++ b/extensions/demo/multimesh/src/Refinement.cc @@ -0,0 +1,184 @@ +#include <limits> +#include "Refinement.h" + +using namespace std; +using namespace AMDiS; + + +Refinement::Refinement(DOFVector<double> *phasefield_, + AbstractFunction<double, WorldVector<double> > *phasefieldFct_, + RefinementManager *refinementManager_, + CoarseningManager *coarseningManager_) + : phasefield(phasefield_), + phasefieldFct(phasefieldFct_), + refinementManager(refinementManager_), + coarseningManager(coarseningManager_), + info_(0) +{ + feSpace = phasefield->getFeSpace(); + mesh = feSpace->getMesh(); +} + + +Refinement::~Refinement() +{ +} + + +void Refinement::refine(double h) +{ + FUNCNAME("Refinement::refine()"); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MPI::COMM_WORLD.Barrier(); + double first = MPI::Wtime(); + double m0 = 0.0, m1 = 0.0; +#endif + // build mesh for phasefield-function + bool meshChanged=true; + Flag markFlag; + double minH = 0.0, maxH = 1.0, oldMinH = 100.0, oldMaxH = 0.0; + + int i = 0; + while (meshChanged || minH != oldMinH || maxH != oldMaxH) { + oldMinH = minH; + oldMaxH = maxH; + + if (phasefieldFct != NULL) + phasefield->interpol(phasefieldFct); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + double t0 = MPI::Wtime(); + markElements(markFlag, h); + m0 += MPI::Wtime() - t0; + + t0 = MPI::Wtime(); + meshChanged = refineMesh(markFlag); + m1 += MPI::Wtime() - t0; + +#else + markElements(markFlag, h); + meshChanged = refineMesh(markFlag); +#endif + + calcMeshSizes(minH, maxH); + + if (meshChanged || minH != oldMinH || maxH != oldMaxH) { + int nr = phasefield->getUsedSize(); + MSG("%d Mesh sizes: [%f, %f], DOFs: %d, ELs: %d\n", i++, + minH, maxH, nr, mesh->getNumberOfLeaves()); + } + } + + if (phasefieldFct != NULL) + phasefield->interpol(phasefieldFct); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::mpi::globalMax(m0); + Parallel::mpi::globalMax(m1); + + MPI::COMM_WORLD.Barrier(); + MSG("Local mesh refinement (phase field) needed %.5f seconds [ %.5f %.5f ]\n", MPI::Wtime() - first, m0, m1); +#endif +} + + +void Refinement::calcMeshSizes(double &minH, double &maxH) +{ + int dim = mesh->getDim(); + FixVec<WorldVector<double>, VERTEX> coords(dim, NO_INIT); + + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); + minH=1e15; maxH=0.0; + while (elInfo) { + coords = elInfo->getCoords(); + double h = 0.0; + for (int i = 0; i < coords.getSize(); i++) + for(int j = i + 1; j < coords.getSize(); j++) + if (i != j) + h = std::max(h, norm(coords[i] - coords[j])); + minH = std::min(h, minH); + maxH = std::max(h, maxH); + elInfo = stack.traverseNext(elInfo); + } +} + + +void Refinement::markElements(Flag &markFlag, double hInterface) +{ + DOFVector<double> *vec = phasefield; + const DOFAdmin* admin = feSpace->getAdmin(); + const BasisFunction *basFcts = feSpace->getBasisFcts(); + + int dim = mesh->getDim(); + int numBasFcts = basFcts->getNumber(); + + std::vector<DegreeOfFreedom> localIndices(numBasFcts); + FixVec<WorldVector<double>, VERTEX> coords(dim, NO_INIT); + + bool elMarkRefine=false, elMarkCoarsen=false; + + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); + while (elInfo) { + Element *el = elInfo->getElement(); + basFcts->getLocalIndices(el, admin, localIndices); + // for every vertex + double smax = -1e12, smin = 1e12; + coords = elInfo->getCoords(); + for (int i = 0; i < numBasFcts; i++) { + // search for coords of this vertex in the coord-list of this dof + smin = std::min(smin, (*vec)[localIndices[i]]); + smax = std::max(smax, (*vec)[localIndices[i]]); + } + + if (smin < 0.1 && smax > -0.1) { + double h = 0.0; + for (int i = 0; i < coords.getSize(); i++) + for (int j = i + 1; j < coords.getSize(); j++) + h = std::max(h, norm(coords[i] - coords[j])); + + if (h > hInterface) { + elMarkRefine = true; + elInfo->getElement()->setMark(1); + } + } else { + if (smax - smin > 0.2) { + elMarkRefine = true; + elInfo->getElement()->setMark(1); + } + if (smax -smin < 0.1) { + elMarkCoarsen = true; + elInfo->getElement()->setMark(-1); + } + } + + elInfo = stack.traverseNext(elInfo); + } + + markFlag = 0; + if (elMarkRefine) + markFlag = 1; + if (elMarkCoarsen) + markFlag |= 2; +} + + +bool Refinement::refineMesh(Flag markFlag) +{ + FUNCNAME("Refinement::refineMesh()"); + + int oldSize = phasefield->getUsedSize(); + if (markFlag.isSet(1)) + refinementManager->refineMesh(mesh); + if (markFlag.isSet(2)) + coarseningManager->coarsenMesh(mesh); + if (markFlag.isSet(1) || markFlag.isSet(2)) { + int newSize = phasefield->getUsedSize(); + if (oldSize != newSize) + return true; + INFO(info_,1)(">> InterfaceRefinement refined DOFs: %d\n",newSize); + } + return false; +} + diff --git a/extensions/demo/multimesh/src/Refinement.h b/extensions/demo/multimesh/src/Refinement.h new file mode 100644 index 00000000..8d0b6845 --- /dev/null +++ b/extensions/demo/multimesh/src/Refinement.h @@ -0,0 +1,39 @@ +/** \file Refinement.h */ + +#ifndef REFINEMENT_PHASEFIELD_H +#define REFINEMENT_PHASEFIELD_H + +#include "AMDiS.h" + +using namespace std; +using namespace AMDiS; + +/* define instationary problem */ +class Refinement +{ +public: + Refinement(DOFVector<double> *phasefield, AbstractFunction<double, WorldVector<double> > *phasefieldFct, RefinementManager *refinementManager, CoarseningManager *coarseningManager); + ~Refinement(); + + void refine(double h); + + void calcMeshSizes(double &minH, double &maxH); + void markElements(Flag &markFlag, double hInterface); + bool refineMesh(Flag markFlag); + +protected: + inline double norm(const WorldVector<double> &x) + { + return sqrt(x * x); + } + +protected: + AbstractFunction<double, WorldVector<double> > *phasefieldFct; + DOFVector<double> *phasefield; + const FiniteElemSpace *feSpace; + Mesh *mesh; + RefinementManager *refinementManager; + CoarseningManager *coarseningManager; + int info_; +}; +#endif // REFINEMENT_PHASEFIELD_H diff --git a/extensions/demo/multimesh/src/cahnHilliard_navierStokes.cc b/extensions/demo/multimesh/src/cahnHilliard_navierStokes.cc new file mode 100644 index 00000000..f36d323f --- /dev/null +++ b/extensions/demo/multimesh/src/cahnHilliard_navierStokes.cc @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * Extension of AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: Simon Praetorius et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + +#include "AMDiS.h" +#if __cplusplus > 199711L + #include "CouplingBaseProblem2_cxx11.h" +#else + #include "CouplingBaseProblem2.h" +#endif +#include "CahnHilliard.h" +// #include "ProblemStatMassConserve2.h" // using COARSE_RESTRICT +#include "ProblemStatMassConserve.h" // using multi mesh +#include "NavierStokes_TaylorHood.h" +#include "Refinement.h" +#include "MeshFunction_Level.h" + +using namespace AMDiS; + +typedef base_problems::detail::CahnHilliard<ProblemStatMassConserve> CHType; +typedef NavierStokes_TaylorHood NSType; + +class CahnHilliardNavierStokes : public CouplingBaseProblem< ProblemStat, CHType, NSType > +{ +public: // typedefs + + typedef CouplingBaseProblem< ProblemStat, CHType, NSType > super; + +public: // methods + + /// Constructor + CahnHilliardNavierStokes(std::string name, + CHType &chProb_, + NSType &nsProb_) + : super(name, chProb_, nsProb_), + chProb(&chProb_), + nsProb(&nsProb_), + refFunction(NULL), + refinement(NULL), + minus1(-1.0) + { } + + /// Destructor + ~CahnHilliardNavierStokes() + { + if (refFunction) { delete refFunction; refFunction = NULL; } + if (refinement) { delete refinement; refinement = NULL; } + } + + /// Called before first adaption loop + virtual void initData() + { + refFunction = new PhaseFieldRefinement(chProb->getMesh()); + refinement = new RefinementLevelDOF(chProb->getFeSpace(0), + refFunction, + chProb->getSolution()->getDOFVector(0)); + } + + /// Set initial condition and perform initial refinement + virtual void solveInitialProblem(AdaptInfo *adaptInfo) + { + // initial refinement + refinement->refine(0); + + // refine until interfaces is resolved + for (int i = 0; i < 5; ++i) { + chProb->solveInitialProblem(adaptInfo); + refinement->refine(5); + } + + super::solveInitialProblem(adaptInfo); + + std::string prefix = ""; + Parameters::get("prefix", prefix); + + double c = chProb->getSolution()->getDOFVector(0)->Int(); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (MPI::COMM_WORLD.Get_rank() == 0) +#endif + { + std::ofstream out(("concentration" + prefix + ".dat").c_str(), ios_base::out); + out.setf(std::ios::scientific, std::ios::floatfield ); + out.precision(16); + out << c << "\n"; + } + // activate mass-conservative coarsening + refinement->setRefineOperation(adaptInfo, chProb->getProblem()); + } + + /// Called at the end of each timestep. + virtual void closeTimestep(AdaptInfo *adaptInfo) + { + super::closeTimestep(adaptInfo); + + std::string prefix = ""; + Parameters::get("prefix", prefix); + + double c = chProb->getSolution()->getDOFVector(0)->Int(); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (MPI::COMM_WORLD.Get_rank() == 0) +#endif + { + std::ofstream out(("concentration" + prefix + ".dat").c_str(), ios_base::app); + out.setf(std::ios::scientific, std::ios::floatfield ); + out.precision(16); + out << c << "\n"; + } + + refinement->refine(1); + // checkMeshChange + } + + virtual void fillCouplingOperators() + { + double M0 = 1.0; + Parameters::get(name + "->M0",M0); + + DOFVector<double>* c = chProb->getSolution()->getDOFVector(0); + DOFVector<double>* mu = chProb->getSolution()->getDOFVector(1); + + // < grad(mu) * c , theta > + for (size_t i = 0; i < dow; i++) { + Operator *opCGradMu = new Operator(nsProb->getFeSpace(i), + chProb->getFeSpace(0)); + addZOT(opCGradMu, M0 * valueOf(mu) * derivativeOf(c, i) ); + nsProb->getProblem(0)->addVectorOperator(opCGradMu, i); + } + + // < - u * c , grad(theta) > + for (size_t i = 0; i < dow; i++) { + Operator *opUGradC = new Operator(chProb->getFeSpace(1), + chProb->getFeSpace(0)); + addFOT(opUGradC, -valueOf(nsProb->getSolution()->getDOFVector(i)), i, GRD_PSI ); + chProb->getProblem()->addMatrixOperator(opUGradC, 1, 0); + } + } + +protected: // variables + + CHType *chProb; + NSType *nsProb; + PhaseFieldRefinement* refFunction; + RefinementLevelDOF *refinement; + + double minus1; + double concentration; +}; + + +int main(int argc, char** argv) +{ FUNCNAME("main"); + + AMDiS::init(argc, argv); + Timer t; + + CHType chProb("ch"); + NSType nsProb("ns"); + + CahnHilliardNavierStokes chns("chns", chProb, nsProb); + chns.initialize(INIT_ALL); + chns.initTimeInterface(); + + // Adapt-Infos + AdaptInfo adaptInfo("adapt", chns.getNumComponents()); + AdaptInstationary adaptInstat("adapt", chns, adaptInfo, chns, adaptInfo); + + int error_code = adaptInstat.adapt(); + + MSG("elapsed time= %d sec\n", t.elapsed()); + AMDiS::finalize(); + + return error_code; +} + diff --git a/extensions/demo/multimesh/src/cahnHilliard_navierStokes_mm.cc b/extensions/demo/multimesh/src/cahnHilliard_navierStokes_mm.cc new file mode 100644 index 00000000..e9399e4e --- /dev/null +++ b/extensions/demo/multimesh/src/cahnHilliard_navierStokes_mm.cc @@ -0,0 +1,186 @@ +/****************************************************************************** + * + * Extension of AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: Simon Praetorius et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + +#include "AMDiS.h" +#if __cplusplus > 199711L + #include "CouplingBaseProblem2_cxx11.h" +#else + #include "CouplingBaseProblem2.h" +#endif +#include "CahnHilliard_mm.h" +#include "ProblemStatMassConserve_mm.h" // using multi mesh +#include "NavierStokes_TaylorHood.h" +#include "Refinement.h" +#include "MeshFunction_Level.h" + +using namespace AMDiS; + +typedef base_problems::CahnHilliard_mm CHType; +typedef NavierStokes_TaylorHood NSType; + +class CahnHilliardNavierStokes : public CouplingBaseProblem< ProblemStat, CHType, NSType > +{ +public: // typedefs + + typedef CouplingBaseProblem< ProblemStat, CHType, NSType > super; + +public: // methods + + /// Constructor + CahnHilliardNavierStokes(std::string name, + CHType &chProb_, + NSType &nsProb_) + : super(name, chProb_, nsProb_), + chProb(&chProb_), + nsProb(&nsProb_), + refFunction(NULL), + refinement(NULL), + minus1(-1.0) + { } + + /// Destructor + ~CahnHilliardNavierStokes() + { + if (refFunction) { delete refFunction; refFunction = NULL; } + if (refinement) { delete refinement; refinement = NULL; } + } + + /// Called before first adaption loop + virtual void initData() + { + refFunction = new PhaseFieldRefinement(chProb->getMesh()); + refinement = new RefinementLevelDOF(chProb->getFeSpace(0), + refFunction, + chProb->getSolution()->getDOFVector(0)); + } + + /// Set initial condition and perform initial refinement + virtual void solveInitialProblem(AdaptInfo *adaptInfo) + { + // initial refinement + refinement->refine(0); + + // refine until interfaces is resolved + for (int i = 0; i < 5; ++i) { + chProb->solveInitialProblem(adaptInfo); + refinement->refine(5); + } + + super::solveInitialProblem(adaptInfo); + + std::string prefix = ""; + Parameters::get("prefix", prefix); + + double c = chProb->getSolution()->getDOFVector(0)->Int(); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (MPI::COMM_WORLD.Get_rank() == 0) +#endif + { + std::ofstream out(("concentration" + prefix + ".dat").c_str(), ios_base::out); + out.setf(std::ios::scientific, std::ios::floatfield ); + out.precision(16); + out << c << "\n"; + } + // activate mass-conservative coarsening + refinement->setRefineOperation(adaptInfo, chProb->getProblem()); + } + + /// Called at the end of each timestep. + virtual void closeTimestep(AdaptInfo *adaptInfo) + { + super::closeTimestep(adaptInfo); + + std::string prefix = ""; + Parameters::get("prefix", prefix); + + double c = chProb->getSolution()->getDOFVector(0)->Int(); +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (MPI::COMM_WORLD.Get_rank() == 0) +#endif + { + std::ofstream out(("concentration" + prefix + ".dat").c_str(), ios_base::app); + out.setf(std::ios::scientific, std::ios::floatfield ); + out.precision(16); + out << c << "\n"; + } + + refinement->refine(1); + // checkMeshChange + } + + virtual void fillCouplingOperators() + { + double M0 = 1.0; + Parameters::get(name + "->M0",M0); + + DOFVector<double>* c = chProb->getSolution()->getDOFVector(0); + DOFVector<double>* mu = chProb->getSolution()->getDOFVector(1); + + // < grad(mu) * c , theta > + for (size_t i = 0; i < dow; i++) { + Operator *opCGradMu = new Operator(nsProb->getFeSpace(i), + chProb->getFeSpace(0)); + addZOT(opCGradMu, M0 * valueOf(mu) * derivativeOf(c, i) ); + nsProb->getProblem(0)->addVectorOperator(opCGradMu, i); + } + + // < - u * c , grad(theta) > + for (size_t i = 0; i < dow; i++) { + Operator *opUGradC = new Operator(chProb->getFeSpace(1), + chProb->getFeSpace(0)); + addFOT(opUGradC, -valueOf(nsProb->getSolution()->getDOFVector(i)), i, GRD_PSI ); + chProb->getProblem()->addMatrixOperator(opUGradC, 1, 0); + } + } + +protected: // variables + + CHType *chProb; + NSType *nsProb; + PhaseFieldRefinement* refFunction; + RefinementLevelDOF *refinement; + + double minus1; + double concentration; +}; + + +int main(int argc, char** argv) +{ FUNCNAME("main"); + + AMDiS::init(argc, argv); + Timer t; + + CHType chProb("ch"); + NSType nsProb("ns"); + + CahnHilliardNavierStokes chns("chns", chProb, nsProb); + chns.initialize(INIT_ALL); + chns.initTimeInterface(); + + // Adapt-Infos + AdaptInfo adaptInfo("adapt", chns.getNumComponents()); + AdaptInstationary adaptInstat("adapt", chns, adaptInfo, chns, adaptInfo); + + int error_code = adaptInstat.adapt(); + + MSG("elapsed time= %d sec\n", t.elapsed()); + AMDiS::finalize(); + + return error_code; +} + diff --git a/extensions/demo/multimesh/src/dendrites.cc b/extensions/demo/multimesh/src/dendrites.cc new file mode 100644 index 00000000..fe753b94 --- /dev/null +++ b/extensions/demo/multimesh/src/dendrites.cc @@ -0,0 +1,234 @@ +#include "AMDiS.h" +#include "MyProblemInstat.h" +#include "Anisotropy.h" + +using namespace AMDiS; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS +using namespace AMDiS::Parallel; +#endif +using namespace AMDiS::io; + +class DoublewellExpl : public AbstractFunction<double, double> +{ +public: + DoublewellExpl() + : AbstractFunction<double, double>(3) + {} + + double operator()(const double& u) const + { + return 2.0 * u * u * u; + } +}; + +class DoublewellImpl : public AbstractFunction<double, double> +{ +public: + DoublewellImpl() + : AbstractFunction<double, double>(2) + {} + + double operator()(const double& u) const + { + return 3.0 * u * u - 1.0; + } +}; + +class Karma : public AbstractFunction<double, double> +{ +public: + Karma() + : AbstractFunction<double, double>(4) + {} + + double operator()(const double& u) const + { + return pow((1.0 - u * u), 2.0); + } +}; + +using namespace std; +typedef vector<vector<double> > DataVec; + +void scalMesh(Mesh *mesh, double scalFactorX, double scalFactorY, double scalFactorZ) +{ + for (std::deque<MacroElement*>::iterator it = mesh->firstMacroElement(); + it != mesh->endOfMacroElements(); ++it) { + for (int i = 0; i < mesh->getGeo(VERTEX); i++) { + WorldVector<double> &x = (*it)->getCoord(i); + + if (scalFactorX != 0.0) + x[0] *= scalFactorX; + + if (scalFactorY != 0.0) + x[1] *= scalFactorY; + + if (scalFactorZ != 0.0) + x[2] *= scalFactorZ; + } + } +} + + +int main(int argc, char** argv) +{ + FUNCNAME("main"); + + Timer t; + + AMDiS::init(argc, argv); + + ProblemStat dendSpace("dendrites->space"); + dendSpace.initialize(INIT_ALL); + + MyProblemInstat probInstat("dendrites", dendSpace); + probInstat.initialize(INIT_ALL); + + // create adapt info + AdaptInfo adaptInfo("dendrites->adapt", dendSpace.getNumComponents()); + + // create initial adapt info + AdaptInfo adaptInfoInitial("dendrites->initial->adapt", dendSpace.getNumComponents()); + + // create instationary adapt + AdaptInstationary adaptInstat("dendrites->adapt", + dendSpace, + adaptInfo, + probInstat, + adaptInfoInitial); + + // === Scal mesh === + + double scalFactorX = 0.0; + Parameters::get("dendritesMesh->scal x", scalFactorX); + + double scalFactorY = 0.0; + Parameters::get("dendritesMesh->scal y", scalFactorY); + + double scalFactorZ = 0.0; + Parameters::get("dendritesMesh->scal z", scalFactorZ); + + if (!dendSpace.isDeserialized()) { + if (scalFactorX != 0.0 || scalFactorY != 0.0 || scalFactorZ != 0.0) { + scalMesh(dendSpace.getMesh(0), scalFactorX, scalFactorY, scalFactorZ); + + if (dendSpace.getMesh(0) != dendSpace.getMesh(1)) + scalMesh(dendSpace.getMesh(1), scalFactorX, scalFactorY, scalFactorZ); + + if (scalFactorZ == 0.0) + MSG("Mesh scaled with %f x %f\n", scalFactorX, scalFactorY); + else + MSG("Mesh scaled with %f x %f x %f\n", scalFactorX, scalFactorY, scalFactorZ); + } + } + + + + double thermalDif = 0.0; + Parameters::get("dendrites->karma model->D", thermalDif); + + double a2 = 0.6267; + double lambda = thermalDif / a2; + + double gamma = 0.0; + Parameters::get("dendrites->karma model->gamma", gamma); + + double rhoInitial = 0.0; + Parameters::get("dendrites->karma model->rho initial", rhoInitial); + + MSG("Karma model parameters:\n"); + MSG(" D = %f\n", thermalDif); + MSG(" gamma = %f\n", gamma); + MSG(" Delta = %f\n", rhoInitial); + MSG("\n"); + + DOFVector<double> *oldPhi = probInstat.getOldSolution()->getDOFVector(0); + + AbstractFunction<double, WorldVector<double> > *anisoSquare; + AbstractFunction<WorldMatrix<double>, WorldVector<double> > *anisoLaplace; + + switch (dendSpace.getMesh(0)->getDim()) { + case 2: + anisoSquare = new Aniso2d_Square(gamma); + anisoLaplace = new Aniso2d_Laplace(gamma); + break; + case 3: + anisoSquare = new Aniso3d_Square(gamma); + anisoLaplace = new Aniso3d_Laplace(gamma); + break; + default: + ERROR_EXIT("This should not happen!\n"); + } + + NullFct nullFct; + + /// + + Operator opPhiTau(dendSpace.getFeSpace(0), dendSpace.getFeSpace(0)); + opPhiTau.addZeroOrderTerm(new FctGradient_ZOT(oldPhi, anisoSquare)); + opPhiTau.setUhOld(probInstat.getOldSolution()->getDOFVector(0)); + dendSpace.addMatrixOperator(opPhiTau, 0, 0, probInstat.getInvTau(), probInstat.getInvTau()); + dendSpace.addVectorOperator(opPhiTau, 0, probInstat.getInvTau(), probInstat.getInvTau()); + + Operator opDoublewellImpl(dendSpace.getFeSpace(0), dendSpace.getFeSpace(0)); + opDoublewellImpl.addZeroOrderTerm(new VecAtQP_ZOT(oldPhi, new DoublewellImpl)); + dendSpace.addMatrixOperator(opDoublewellImpl, 0, 0); + + Operator opDoublewellExpl(dendSpace.getFeSpace(0)); + opDoublewellExpl.addZeroOrderTerm(new VecAtQP_ZOT(oldPhi, new DoublewellExpl)); + dendSpace.addVectorOperator(opDoublewellExpl, 0); + + Operator opKarmaFct(dendSpace.getFeSpace(0), dendSpace.getFeSpace(1)); + opKarmaFct.addZeroOrderTerm(new VecAtQP_ZOT(oldPhi, new Karma)); + dendSpace.addMatrixOperator(opKarmaFct, 0, 1, &lambda, &lambda); + + Operator opAnisoLaplace(dendSpace.getFeSpace(0), dendSpace.getFeSpace(0)); + opAnisoLaplace.addSecondOrderTerm(new MatrixGradient_SOT(oldPhi, anisoLaplace, &nullFct)); + dendSpace.addMatrixOperator(opAnisoLaplace, 0, 0); + + + /// + + Operator opLaplace(dendSpace.getFeSpace(1), dendSpace.getFeSpace(1)); + opLaplace.addSecondOrderTerm(new Simple_SOT(&thermalDif)); + dendSpace.addMatrixOperator(opLaplace, 1, 1); + + Operator opUTau(dendSpace.getFeSpace(1), dendSpace.getFeSpace(1)); + opUTau.addZeroOrderTerm(new Simple_ZOT); + opUTau.setUhOld(probInstat.getOldSolution()->getDOFVector(1)); + dendSpace.addMatrixOperator(opUTau, 1, 1, probInstat.getInvTau(), probInstat.getInvTau()); + dendSpace.addVectorOperator(opUTau, 1, probInstat.getInvTau(), probInstat.getInvTau()); + + + Operator opPhiUTau(dendSpace.getFeSpace(1), dendSpace.getFeSpace(0)); + opPhiUTau.addZeroOrderTerm(new Simple_ZOT(-0.5)); + opPhiUTau.setUhOld(probInstat.getOldSolution()->getDOFVector(0)); + dendSpace.addMatrixOperator(opPhiUTau, 1, 0, probInstat.getInvTau(), probInstat.getInvTau()); + dendSpace.addVectorOperator(opPhiUTau, 1, probInstat.getInvTau(), probInstat.getInvTau()); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MeshDistributor::globalMeshDistributor->addInterchangeVector(probInstat.getOldSolution()); + MeshDistributor::globalMeshDistributor->addInterchangeVector(dendSpace.getSolution()); +#endif + + // ===== start adaption loop ===== + int errorCode = adaptInstat.adapt(); + + + printf("whole process needs %.5f seconds\n", t.elapsed()); + + + bool isWrite = false; string phiname, rhoname; + Parameters::get("dendrites->write arh file", isWrite); + Parameters::get("dendrites->write phi arh", phiname); + Parameters::get("dendrites->write rho arh", rhoname); + + if (isWrite) { + io::Arh2Writer::writeFile(dendSpace.getSolution(0), phiname.c_str()); + io::Arh2Writer::writeFile(dendSpace.getSolution(1), rhoname.c_str()); + } + + AMDiS::finalize(); + + return errorCode; +} diff --git a/extensions/demo/multimesh/src/diffuseDomain.cc b/extensions/demo/multimesh/src/diffuseDomain.cc new file mode 100644 index 00000000..ba67e18f --- /dev/null +++ b/extensions/demo/multimesh/src/diffuseDomain.cc @@ -0,0 +1,340 @@ +#include "AMDiS.h" +#include <fstream> +#include "Refinement.h" +#include "Refinement_Level.h" +#include "SignedDistFunctors.h" +#include "Helpers.h" +#include "PhaseFieldConvert.h" +#include "GenericOperatorTerm.h" +#include "ExtendedProblemStat.h" + + +#define USE_UH_OLD 1 + + +using namespace AMDiS; + + +class MySignedDistRefinement : public SignedDistRefinement +{ +public: + MySignedDistRefinement(Mesh* mesh_) : SignedDistRefinement(mesh_) + { + Parameters::get("mesh2->refinement->level in inner domain",lInner); + Parameters::get("mesh2->refinement->level in outer domain",lOuter); + Parameters::get("mesh2->refinement->level on interface",lInterface); + + lInterface-= mesh->getMacroElementLevel(); + lInner-= mesh->getMacroElementLevel(); + lOuter-= mesh->getMacroElementLevel(); + + int local_globalSize = 10; + Parameters::get("mesh2->refinement->initial level", local_globalSize); + globalSize = local_globalSize; + + Parameters::get("mesh2->refinement->interface width",interfaceWidth); + Parameters::get("mesh2->refinement->fade out width",fadeOutWidth); + Parameters::get("mesh2->refinement->sign in inner domain",signInInnerDomain); + }; +}; + + +/// Dirichlet boundary function +class G : public AbstractFunction<double, WorldVector<double> >, + public TimedObject +{ +public: + /// Implementation of AbstractFunction::operator(). + + double operator()(const WorldVector<double>& x) const + { + return 1.0; + } +}; + + + +/// RHS function +class F : public AbstractFunction<double, WorldVector<double> >, + public TimedObject +{ +public: + F(int degree) : AbstractFunction<double, WorldVector<double> >(degree) {} + + /// Implementation of AbstractFunction::operator(). + double operator()(const WorldVector<double>& x) const + { + return 1.0; + } +}; + +struct DDProblemInstat : ProblemInstat +{ + DDProblemInstat(std::string name, ProblemStat& prob) + : ProblemInstat(name, prob), + radius(1.0), + epsilon(0.1), + maxLevel(15), + temperRefment(NULL), + temperRefFct(NULL), + c(radius, center), + ic(radius, center) + { + Parameters::get("radius", radius); + Parameters::get("epsilon", epsilon); + center.set(0.0); + Parameters::get("center", center); + Parameters::get("mesh->max refinement level", maxLevel); + } + + ~DDProblemInstat() + { + if (phase) + delete phase; + phase = NULL; + + if (phaseRefFct) + delete phaseRefFct; + phaseRefFct = NULL; + + if (phaseRefment) + delete phaseRefment; + phaseRefment = NULL; + + if (temperRefFct) + delete temperRefFct; + temperRefFct = NULL; + + if (temperRefment) + delete temperRefment; + temperRefment = NULL; + } + + void initialize(Flag initFlag, + ProblemInstat *adoptProblem = NULL, + Flag adoptFlag = INIT_NOTHING) override + { + problemStat->initialize(initFlag); + + ProblemInstat::initialize(INIT_NOTHING); + + phase = new DOFVector<double>(problemStat->getFeSpace(1), "phase2"); + phaseRefFct = new SignedDistRefinement(problemStat->getMesh(1)); + phaseRefment = new RefinementLevelCoords2(problemStat->getFeSpace(1), + phaseRefFct, &c); + + if (problemStat->getMeshes().size() == 2) { + temperRefFct = new MySignedDistRefinement(problemStat->getMesh(0)); + temperRefment = new RefinementLevelCoords2(problemStat->getFeSpace(0), + temperRefFct, &c); + } + } + + + + void solveInitialProblem(AdaptInfo *adaptInfo) override + { + FUNCNAME("DDProblemInstat::solveInitialProblem"); + Timer t; + + SignedDistFctToPhaseField* p = + new SignedDistFctToPhaseField(epsilon, &ic, 3.0); + + phaseRefment->refine(maxLevel); + phase->interpol(p); +// phase->interpol(new One()); + *phase << valueOf(phase) + 1.e-5; + + + if (problemStat->getMeshes().size() == 2) { + temperRefment->refine(maxLevel, false, true); // when not use marker and estimator + +// int refLevel = 0; +// Parameters::get("mesh->refinement->global heat refine", refLevel); +// MSG("refLevel is %d\n", refLevel); +// problemStat->getRefinementManager()->globalRefine(problemStat->getMesh(0), refLevel); + } + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MPI::COMM_WORLD.Barrier(); +#endif + MSG("mesh refinement and interpolation need %.5f seconds\n", t.elapsed()); + + delete p; + } + + + DOFVector<double>* getPhase() { return phase; } + + double getEpsilon() { return epsilon; } + + +protected: + + double radius; + double epsilon; + int maxLevel; + + WorldVector<double> center; + + SignedDistRefinement* phaseRefFct; + SignedDistRefinement* temperRefFct; + + RefinementLevelCoords2* phaseRefment; + RefinementLevelCoords2* temperRefment; + + Circle c; + InverseCircle ic; + + DOFVector<double>* phase; + +}; + + + +// =========================================================================== + +// ===== main program ======================================================== + +// =========================================================================== + + +int main(int argc, char* argv[]) +{ + FUNCNAME("main"); + + AMDiS::init(argc, argv); + + // ===== create and init the scalar problem ===== + + ProblemStat heatSpace("heat"); + + DDProblemInstat instat("heat", heatSpace); + + instat.initialize(INIT_ALL); + + // === create adapt info === + + AdaptInfo adaptInfo("adapt", heatSpace.getNumComponents()); + + // create instationary adapt + + AdaptInstationary adaptInstat("adapt",heatSpace,adaptInfo,instat,adaptInfo); + + + // scale the mesh to a given size + + bool scaleMesh = false; + + Initfile::get("mesh->scale mesh",scaleMesh); + + if (scaleMesh) { + WorldVector<double> scale; scale.set(1.0); + Initfile::get("mesh->dimension",scale); + for (int i = 0; i < heatSpace.getMeshes().size(); i++) + Helpers::scaleMesh(heatSpace.getMesh(i), scale); + } + + bool operatorOpt = true; + Initfile::get("optimized operator", operatorOpt); + + + // ===== create rhs functions ===== + + + int degree = heatSpace.getFeSpace()->getBasisFcts()->getDegree(); + F *rhsFct = new F(degree); + rhsFct->setTimePtr(adaptInfo.getTimePtr()); + + + // ===== create operators ===== + + + // create laplace + Operator A(heatSpace.getFeSpace()); + addSOT(A, valueOf(instat.getPhase())); + heatSpace.addMatrixOperator(A, 0, 0); + + + // create zero order operator + Operator C(heatSpace.getFeSpace()); + addZOT(C, valueOf(instat.getPhase())); + heatSpace.addMatrixOperator(C, 0, 0, instat.getInvTau(), instat.getInvTau()); + + +#if USE_UH_OLD + + Operator C2(heatSpace.getFeSpace()); + C2.setUhOld(heatSpace.getSolution(0)); + addZOT(C2, valueOf(instat.getPhase())); + heatSpace.addVectorOperator(C2, 0, instat.getInvTau(), instat.getInvTau()); + +#else + + Operator C2(heatSpace.getFeSpace()); + addZOT(C2, valueOf(heatSpace.getSolution(0)) * valueOf(instat.getPhase())); + heatSpace.addVectorOperator(C2, 0, instat.getInvTau(), instat.getInvTau()); + +#endif + + Operator DBC(heatSpace.getFeSpace()); + addZOT(DBC, (36.0 / instat.getEpsilon()) * (1.0 - valueOf(instat.getPhase()))); + heatSpace.addMatrixOperator(DBC, 0, 0); + + + // create RHS operator + Operator F(heatSpace.getFeSpace()); + addZOT(F, valueOf(instat.getPhase()) * eval(rhsFct)); + heatSpace.addVectorOperator(F, 0); + + if (A.getNeedDualTraverse()) + MSG("A need dual traversal.\n"); + if (C.getNeedDualTraverse()) + MSG("C need dual traversal.\n"); + if (C2.getNeedDualTraverse()) + MSG("C2 need dual traversal.\n"); + if (DBC.getNeedDualTraverse()) + MSG("DBC need dual traversal.\n"); + if (F.getNeedDualTraverse()) + MSG("F need dual traversal.\n"); + + + if (!operatorOpt) { + A.useOptimizedAssembler(false); + C.useOptimizedAssembler(false); + C2.useOptimizedAssembler(false); + DBC.useOptimizedAssembler(false); + F.useOptimizedAssembler(false); + } + + + + // ===== create boundary functions ===== + + G *boundaryFct = new G; +// boundaryFct->setTimePtr(instat.getTime()); + + heatSpace.addDirichletBC(1, 0, 0, boundaryFct); + + heatSpace.addDirichletBC(3, 0, 0, boundaryFct); + + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + MPI::COMM_WORLD.Barrier(); +#endif + + Timer t; + // ===== start adaption loop ===== + + adaptInstat.adapt(); + + printf("whole process needs %.5f seconds\n", t.elapsed()); + + delete rhsFct;rhsFct=NULL; + delete boundaryFct;boundaryFct=NULL; + + AMDiS::finalize(); +} + + + diff --git a/extensions/demo/other/init/cahnHilliard_navierStokes.dat.2d b/extensions/demo/other/init/cahnHilliard_navierStokes.dat.2d index 6f428c97..b80b775a 100644 --- a/extensions/demo/other/init/cahnHilliard_navierStokes.dat.2d +++ b/extensions/demo/other/init/cahnHilliard_navierStokes.dat.2d @@ -58,8 +58,8 @@ adapt->end time: 100.0 % ============= PROBLEM-SPACES - CH ============================= ch->space->components: 2 -ch->space->polynomial degree[0]: 3 -ch->space->polynomial degree[1]: 3 +ch->space->polynomial degree[0]: 1 +ch->space->polynomial degree[1]: 1 ch->space->dim: 2 ch->space->mesh: mesh @@ -80,7 +80,7 @@ chns->mesh: mesh % ================== SOLVER - CH ================================ ch->space->solver: direct -ch->space->solver->backend: mtl +%ch->space->solver->backend: mtl ch->space->solver->petsc prefix: ch ch->space->solver->symmetric strategy: 0 ch->space->solver->store symbolic: 0 @@ -89,7 +89,7 @@ ch->space->solver->info: 1 % ================== SOLVER - NS ================================ ns->space->solver: direct -ns->space->solver->backend: mtl +%ns->space->solver->backend: mtl ns->space->solver->petsc prefix: ns ns->space->solver->symmetric strategy: 0 ns->space->solver->store symbolic: 0 -- GitLab