diff --git a/AMDiS/CMakeLists.txt b/AMDiS/CMakeLists.txt index dbc3584056314922e7d570e04158031a1eba2e3d..cb9fbf9146880bd382074a9258aec9ad2bd48c4c 100644 --- a/AMDiS/CMakeLists.txt +++ b/AMDiS/CMakeLists.txt @@ -122,6 +122,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc ${SOURCE_DIR}/MacroElement.cc ${SOURCE_DIR}/Marker.cc ${SOURCE_DIR}/MatrixVector.cc +# ${SOURCE_DIR}/Test_MatrixVectorOperations.cc ${SOURCE_DIR}/Mesh.cc ${SOURCE_DIR}/MeshStructure.cc ${SOURCE_DIR}/Operator.cc @@ -175,6 +176,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc ${SOURCE_DIR}/io/detail/Arh2Writer.cc ${SOURCE_DIR}/io/DofWriter.cc ${SOURCE_DIR}/io/ElementFileWriter.cc + ${SOURCE_DIR}/io/FileWriterInterface.cc ${SOURCE_DIR}/io/FileWriter.cc ${SOURCE_DIR}/io/GNUPlotWriter.cc ${SOURCE_DIR}/io/MacroInfo.cc @@ -433,9 +435,7 @@ if(ENABLE_EXTENSIONS) ${EXTENSIONS_DIR}/POperators.cc ${EXTENSIONS_DIR}/SingularDirichletBC2.cc ${EXTENSIONS_DIR}/time/ExtendedRosenbrockStationary.cc - ${EXTENSIONS_DIR}/pugixml/src/pugixml.cpp - ${EXTENSIONS_DIR}/preconditioner/PhaseFieldCrystal_.cc - ${EXTENSIONS_DIR}/preconditioner/CahnHilliard_.cc) + ${EXTENSIONS_DIR}/pugixml/src/pugixml.cpp) if(ENABLE_SEQ_PETSC) list(APPEND EXTENSIONS_SRC @@ -510,11 +510,15 @@ if(ENABLE_EXTENSIONS) ${EXTENSIONS_DIR}/base_problems/CahnHilliard.cc ${EXTENSIONS_DIR}/base_problems/CahnHilliard_RB.cc ${EXTENSIONS_DIR}/base_problems/CahnHilliardNavierStokes.cc - # ${EXTENSIONS_DIR}/base_problems/DiffuseDomainFsi.cc + ${EXTENSIONS_DIR}/base_problems/CahnHilliardNavierStokes_RB.cc + ${EXTENSIONS_DIR}/base_problems/CahnHilliardNavierStokes_TwoPhase.cc + ${EXTENSIONS_DIR}/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc + ${EXTENSIONS_DIR}/base_problems/DiffuseDomainFsi.cc ${EXTENSIONS_DIR}/base_problems/LinearElasticity.cc ${EXTENSIONS_DIR}/base_problems/LinearElasticityPhase.cc - # ${EXTENSIONS_DIR}/base_problems/NavierStokes_Chorin.cc +# ${EXTENSIONS_DIR}/base_problems/NavierStokes_Chorin.cc ${EXTENSIONS_DIR}/base_problems/NavierStokesCahnHilliard.cc +# ${EXTENSIONS_DIR}/base_problems/NavierStokesPhase_Chorin.cc ${EXTENSIONS_DIR}/base_problems/NavierStokesPhase_TaylorHood.cc ${EXTENSIONS_DIR}/base_problems/NavierStokes_TaylorHood.cc ${EXTENSIONS_DIR}/base_problems/NavierStokes_TaylorHood_RB.cc @@ -524,7 +528,10 @@ if(ENABLE_EXTENSIONS) ${EXTENSIONS_DIR}/base_problems/PhaseFieldCrystal_Phase.cc ${EXTENSIONS_DIR}/base_problems/PhaseFieldCrystal_RB.cc ${EXTENSIONS_DIR}/base_problems/PolarizationField.cc - ${EXTENSIONS_DIR}/base_problems/QuasiCrystal.cc) + ${EXTENSIONS_DIR}/base_problems/QuasiCrystal.cc + ${EXTENSIONS_DIR}/base_problems/QuasiCrystal_RB.cc +# ${EXTENSIONS_DIR}/base_problems/VacancyPhaseFieldCrystal.cc + ) list(APPEND COMPILEFLAGS "-DHAVE_BASE_PROBLEMS=1") list(APPEND AMDIS_INCLUDE_DIRS ${EXTENSIONS_DIR}/base_problems) if(WIN32) @@ -635,6 +642,11 @@ INSTALL(FILES ${HEADERS} DESTINATION include/amdis/) list(APPEND deb_add_dirs "include/amdis") +FILE(GLOB HEADERS "${SOURCE_DIR}/config/*.h*") +INSTALL(FILES ${HEADERS} + DESTINATION include/amdis/config/) +list(APPEND deb_add_dirs "include/amdis/config") + FILE(GLOB HEADERS "${SOURCE_DIR}/*.hh") INSTALL(FILES ${HEADERS} DESTINATION include/amdis/) diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index 36d4cbca42ce71b87f28b5c38e4f9e3627586091..c9030f3008b9dd14f0f9ccaea12e7360e97d2378 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -76,6 +76,7 @@ #include "Marker.h" // #include "MathFunctions.h" #include "MatrixVector.h" +#include "MatrixVectorOperations.h" #include "Mesh.h" #include "MeshStructure.h" #include "ComponentTraverseInfo.h" diff --git a/AMDiS/src/Assembler.cc b/AMDiS/src/Assembler.cc index addc88debb83ea7146af443dd5323dc1f9d59bb7..b73de0b3d1860ea175e8245003603734086a3760 100644 --- a/AMDiS/src/Assembler.cc +++ b/AMDiS/src/Assembler.cc @@ -64,7 +64,7 @@ namespace AMDiS { Element *el = elInfo->getElement(); if (el != lastMatEl || !operat->isOptimized()) { - initElement(elInfo); + initElement(elInfo, elInfo); if (rememberElMat) set_to_zero(elementMatrix); @@ -123,12 +123,14 @@ namespace AMDiS { } 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()); + smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); // muste be moved to next if-else block when generalized for multiple polynomial degrees if (!rowColFeSpaceEqual) { if (smallElInfo == colElInfo) @@ -321,14 +323,7 @@ namespace AMDiS { calculateElementMatrix(elInfo, elementMatrix); } - // vec += elementMatrix*uhOldLoc; - for (int i = 0; i < nRow; i++) { - double val = 0.0; - for (int j = 0; j < nCol; j++) - val += elementMatrix[i][j] * uhOldLoc[j]; - - vec[i] += val; - } + vec += elementMatrix*uhOldLoc; } @@ -358,15 +353,10 @@ namespace AMDiS { if (mainElInfo->getElement() != lastMatEl) { set_to_zero(elementMatrix); calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo, - false, elementMatrix); + rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix); } - for (int i = 0; i < nBasFcts; i++) { - double val = 0.0; - for (int j = 0; j < nBasFcts; j++) - val += elementMatrix[i][j] * uhOldLoc[j]; - vec[i] += val; - } + vec += elementMatrix * uhOldLoc; } diff --git a/AMDiS/src/BallProject.h b/AMDiS/src/BallProject.h index 020056834f14da6593dfd4d03f99c663e681a700..6bbef335b3bb6c38b260f9bab4de823cc0d8f244 100644 --- a/AMDiS/src/BallProject.h +++ b/AMDiS/src/BallProject.h @@ -25,6 +25,8 @@ #ifndef AMDIS_BALLPROJECT_H #define AMDIS_BALLPROJECT_H +#include "MatrixVectorOperations.h" + namespace AMDiS { /** \brief diff --git a/AMDiS/src/Cholesky.cc b/AMDiS/src/Cholesky.cc index 92c5353285e4551fd17003cdf80d90378ff42588..618f4f05d8fbb33e7b58de0b1b653bc08487bdb7 100644 --- a/AMDiS/src/Cholesky.cc +++ b/AMDiS/src/Cholesky.cc @@ -20,6 +20,7 @@ #include "Cholesky.h" +#include "MatrixVectorOperations.h" namespace AMDiS { diff --git a/AMDiS/src/Config.h b/AMDiS/src/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..a9f7415bf27bef60f5597a16af0fe483a98f7480 --- /dev/null +++ b/AMDiS/src/Config.h @@ -0,0 +1,38 @@ +#pragma once + +/** \brief current AMDiS version */ +#ifndef AMDIS_VERSION +#define AMDIS_VERSION "AMDiS: Version 0.9.1" +#endif + +#include <boost/config.hpp> + +#define CACHE_LINE 16 + +#if defined(__clang__) // Clang/LLVM. + #include "config/Config_clang.h" + +#elif defined(__ICC) || defined(__INTEL_COMPILER) // Intel ICC/ICPC. + #include "config/Config_intel.h" + +#elif defined(__GNUC__) || defined(__GNUG__) // GNU GCC/G++. + #include "config/Config_gcc.h" + +#elif defined(__HP_cc) || defined(__HP_aCC) + error: not supported compiler + +#elif defined(__IBMC__) || defined(__IBMCPP__) + error: not supported compiler + +#elif defined(_MSC_VER) // Microsoft Visual Studio. + #include "config/Config_msc.h" + +#elif defined(__PGI) // Portland Group PGCC/PGCPP. + error: not supported compiler +// #include "Config_pgi.h" + +#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) + error: not supported compiler +#endif + +#include "config/Config_defaults.h" \ No newline at end of file diff --git a/AMDiS/src/CylinderProject.h b/AMDiS/src/CylinderProject.h index a2214551b1a771bb0d2f203f7d0847729bf5fb6d..07c1ba75982aadc5bad328427d32d112b1f53276 100644 --- a/AMDiS/src/CylinderProject.h +++ b/AMDiS/src/CylinderProject.h @@ -25,6 +25,8 @@ #ifndef AMDIS_CYLINDERPROJECT_H #define AMDIS_CYLINDERPROJECT_H +#include "MatrixVectorOperations.h" + namespace AMDiS { /** \brief diff --git a/AMDiS/src/DOFVector.h b/AMDiS/src/DOFVector.h index 3de444693e9b989082039acf1a298fc6dfa6c3f8..49e6125d4a3dbe02b7e3494b2416e663c93f387f 100644 --- a/AMDiS/src/DOFVector.h +++ b/AMDiS/src/DOFVector.h @@ -350,10 +350,10 @@ namespace AMDiS { {} /// Constructs a DOFVector with name n belonging to FiniteElemSpace f - DOFVector(const FiniteElemSpace* f, std::string n, bool addToSynch = true); + DOFVector(const FiniteElemSpace* f, std::string n, bool addToSynch = false); /// Initialization. - void init(const FiniteElemSpace* f, std::string n, bool addToSynch = true); + void init(const FiniteElemSpace* f, std::string n, bool addToSynch = false); /// Copy Constructor DOFVector(const DOFVector& rhs) : DOFVectorBase<T>() diff --git a/AMDiS/src/DOFVector.hh b/AMDiS/src/DOFVector.hh index 11338d36e5cbc20c2c6f7e164bd9962d7440f16e..f01c6ee9fb0095a0293066c127b13e76e0cf0b4a 100644 --- a/AMDiS/src/DOFVector.hh +++ b/AMDiS/src/DOFVector.hh @@ -130,7 +130,7 @@ namespace AMDiS { (this->feSpace->getAdmin())->addDOFIndexed(this); this->boundaryManager = new BoundaryManager(f); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS - if ( Parallel::MeshDistributor::globalMeshDistributor != NULL) + if (addToSynch && Parallel::MeshDistributor::globalMeshDistributor != NULL) Parallel::MeshDistributor::globalMeshDistributor->addInterchangeVector(this); #endif } diff --git a/AMDiS/src/DualTraverse.h b/AMDiS/src/DualTraverse.h index 64d84f0a35d875e51ed8acc49f0cf75be4c43893..b5b2c2c9fc653d25404923e984f6111771e8c72e 100644 --- a/AMDiS/src/DualTraverse.h +++ b/AMDiS/src/DualTraverse.h @@ -37,10 +37,10 @@ namespace AMDiS { */ struct DualElInfo { - ElInfo *rowElInfo; - ElInfo *colElInfo; - ElInfo *smallElInfo; - ElInfo *largeElInfo; + ElInfo *rowElInfo; ///< elInfo related to testfunction + ElInfo *colElInfo; ///< elInfo related to trialfunction + ElInfo *smallElInfo; ///< the smaller element of (rowElInfo, colElInfo) with refinementPath relative to largeElInfo + ElInfo *largeElInfo; ///< the larger element of (rowElInfo, colElInfo) }; /// Parallel traversal of two meshes. diff --git a/AMDiS/src/ElInfo.h b/AMDiS/src/ElInfo.h index 4fb5d6a49fce5300ea1e6420d1e7250671fc6319..f4dc850f70bf98cbc18c282ed31b1289c89f2479 100644 --- a/AMDiS/src/ElInfo.h +++ b/AMDiS/src/ElInfo.h @@ -252,7 +252,7 @@ namespace AMDiS { virtual mtl::dense2D<double>& getSubElemGradCoordsMat(int degree) const { - return subElemGradMatrices[degree][std::make_pair(refinementPathLength, refinementPath)]; + return getSubElemCoordsMat(degree); } /** \} */ diff --git a/AMDiS/src/ElInfo1d.cc b/AMDiS/src/ElInfo1d.cc index d1e9b076e9b4dfb0e867969257d18c9251518847..cb11ff1aa17d839dbeaf8dbf4c5001265bf53541 100644 --- a/AMDiS/src/ElInfo1d.cc +++ b/AMDiS/src/ElInfo1d.cc @@ -367,22 +367,7 @@ namespace AMDiS { mtl::dense2D<double>& ElInfo1d::getSubElemGradCoordsMat(int degree) const { - FUNCNAME("ElInfo1d::getSubElemGradCoordsMat()"); - - TEST_EXIT(degree == 1)("Not supported for basis functions with degree > 1!\n"); - - using namespace mtl; - - if (subElemGradMatrices[degree].count(std::make_pair(refinementPathLength, refinementPath)) == 0) { - dense2D<double> mat(mat_d1); - - for (int i = 0; i < refinementPathLength; i++) - mat *= 0.5; - - subElemGradMatrices[1][std::make_pair(refinementPathLength, refinementPath)] = mat; - } - - return subElemGradMatrices[degree][std::make_pair(refinementPathLength, refinementPath)]; + return getSubElemCoordsMat(degree); } diff --git a/AMDiS/src/ElInfo2d.cc b/AMDiS/src/ElInfo2d.cc index 83864e3d261467058c105ae6b5cfb082306f0526..99b9ccf69149a8d0bdca91a3fbe108256235dd30 100644 --- a/AMDiS/src/ElInfo2d.cc +++ b/AMDiS/src/ElInfo2d.cc @@ -66,64 +66,64 @@ namespace AMDiS { - double ElInfo2d::mat_d3_left_val[10][10] = {{0.0, 1.0, -0.0625, 0.3125, 0.0, 0.0, 0.0625, 0.0, 0.0, -0.0625}, - {0.0, 0.0, -0.0625, 0.0625, 0.0, 0.0, 0.0625, 0.0, 0.0, 0.0625}, + double ElInfo2d::mat_d3_left_val[10][10] = {{0.0, 1.0, -6.25e-02, 3.125e-01, 0.0, 0.0, 6.25e-02, 0.0, 0.0, -6.25e-02}, + {0.0, 0.0, -6.25e-02, 6.25e-02, 0.0, 0.0, 6.25e-02, 0.0, 0.0, 6.25e-02}, {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.25, 0.0, 0.0, -0.125}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.5e-01, 0.0, 0.0, -0.125}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.0, 1.0, 0.375}, - {0.0, 0.0, 0.5625, 0.9375, 1.0, 0.0, -0.0625, 0.0, 0.0, 0.1875}, - {0.0, 0.0, 0.5625, -0.3125, 0.0, 0.0, -0.0625, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.5, 0.0, 0.0, 0.75}}; + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -2.5e-01, 0.0, 1.0, 0.375}, + {0.0, 0.0, 5.625e-01, 9.375e-01, 1.0, 0.0, -6.25e-02, 0.0, 0.0, 1.875e-01}, + {0.0, 0.0, 5.625e-01, -3.125e-01, 0.0, 0.0, -6.25e-02, 0.0, 0.0, -1.875e-01}, + {0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.5, 0.0, 0.0, 7.5e-01}}; mtl::dense2D<double> ElInfo2d::mat_d3_left(mat_d3_left_val); - double ElInfo2d::mat_d3_right_val[10][10] = {{0.0, 0.0, -0.0625, 0.0625, 0.0, 0.0, 0.0625, 0.0, 0.0, 0.0625}, - {1.0, 0.0, -0.0625, 0.0625, 0.0, 0.0, 0.3125, 0.0, 0.0, -0.0625}, - {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.25, 0.0, 0.0, 0.0, 1.0, 0.0, 0.375}, - {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, - {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, -0.125}, - {0.0, 0.0, 0.5625, -0.0625, 0.0, 0.0, -0.3125, 0.0, 0.0, -0.1875}, - {0.0, 0.0, 0.5625, -0.0625, 0.0, 1.0, 0.9375, 0.0, 0.0, 0.1875}, - {0.0, 0.0, 0.0, 0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 0.75}}; + double ElInfo2d::mat_d3_right_val[10][10] = {{0.0, 0.0, -6.25e-02, 6.25e-02, 0.0, 0.0, 6.25e-02, 0.0, 0.0, 6.25e-02}, + {1.0, 0.0, -6.25e-02, 6.25e-02, 0.0, 0.0, 3.125e-01, 0.0, 0.0, -6.25e-02}, + {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, -2.5e-01, 0.0, 0.0, 0.0, 1.0, 0.0, 0.375}, + {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, + {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, -2.5e-01, 0.0, 0.0, 0.0, 0.0, 0.0, -0.125}, + {0.0, 0.0, 5.625e-01, -6.25e-02, 0.0, 0.0, -3.125e-01, 0.0, 0.0, -1.875e-01}, + {0.0, 0.0, 5.625e-01, -6.25e-02, 0.0, 1.0, 9.375e-01, 0.0, 0.0, 1.875e-01}, + {0.0, 0.0, 0.0, 0.5, 1.0, 0.0, 0.0, 0.0, 0.0, 7.5e-01}}; mtl::dense2D<double> ElInfo2d::mat_d3_right(mat_d3_right_val); - double ElInfo2d::mat_d4_left_val[15][15] = {{0.0, 1.0, 0.0, 2.734375e-01, 0.0, -3.90625e-02, 2.34375e-02, 0.0, -3.90625e-02, 0.0, 0.0, 0.0, 2.34375e-02, -3.90625e-02, 0.0}, - {0.0, 0.0, 0.0, -3.90625e-02, 0.0, 2.34375e-02, 2.34375e-02, 0.0, -3.90625e-02, 0.0, 0.0, 0.0, -3.90625e-02, -3.90625e-02, 0.0}, + double ElInfo2d::mat_d4_left_val[15][15] = {{0.0, 1.0, 0.0, 2.734375e-01, 0.0, -3.906250e-02, 2.343750e-02, 0.0, -3.906250e-02, 0.0, 0.0, 0.0, 2.343750e-02, -3.906250e-02, 0.0}, + {0.0, 0.0, 0.0, -3.906250e-02, 0.0, 2.343750e-02, 2.343750e-02, 0.0, -3.906250e-02, 0.0, 0.0, 0.0, -3.906250e-02, -3.906250e-02, 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, -6.25e-02, 0.0, 1.875e-01, 0.0, 0.0, 0.0, 1.25e-01, 6.25e-02, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.75e-01, 0.0, 0.0, 0.0, -1.25e-01, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.e-01, 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, -3.75e-01, 0.0, 1.0, 0.0, 3.75e-01, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -6.25e-02, 0.0, 1.875e-01, 0.0, 0.0, 1.0, -1.25e-01, 3.125e-01, 0.0}, - {0.0, 0.0, 0.0, 1.09375e+00, 1.0, 4.6875e-01, -9.375e-02, 0.0, 3.125e-02, 0.0, 0.0, 0.0, -3.125e-02, 1.5625e-01, 0.0}, - {0.0, 0.0, 1.0, -5.46875e-01, 0.0, 7.03125e-01, 1.40625e-01, 0.0, 1.5625e-02, 0.0, 0.0, 0.0, -4.6875e-02, -2.34375e-01, 0.0}, - {0.0, 0.0, 0.0, 2.1875e-01, 0.0, -1.5625e-01, -9.375e-02, 0.0, 3.125e-02, 0.0, 0.0, 0.0, 9.375e-02, 1.5625e-01, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.625e-01, 0.0, -1.875e-01, 0.0, 0.0, 0.0, 3.75e-01, 9.375e-01, 1.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.625e-01, 0.0, -1.875e-01, 0.0, 0.0, 0.0, -3.75e-01, -3.125e-01, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -6.25e-02, 0.0, 1.875e-01, 0.0, 0.0, 0.0, 0.125, 6.25e-02, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.375, 0.0, 0.0, 0.0, -0.125, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 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.375, 0.0, 1.0, 0.0, 0.375, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -6.25e-02, 0.0, 1.875e-01, 0.0, 0.0, 1.0, -0.125, 3.125e-01, 0.0}, + {0.0, 0.0, 0.0, 1.093750e+00, 1.0, 4.687500e-01, -9.375e-02, 0.0, 3.125e-02, 0.0, 0.0, 0.0, -3.125e-02, 1.562500e-01, 0.0}, + {0.0, 0.0, 1.0, -5.468750e-01, 0.0, 7.031250e-01, 1.406250e-01, 0.0, 1.562500e-02, 0.0, 0.0, 0.0, -4.687500e-02, -2.343750e-01, 0.0}, + {0.0, 0.0, 0.0, 2.187500e-01, 0.0, -1.562500e-01, -9.375e-02, 0.0, 3.125e-02, 0.0, 0.0, 0.0, 9.375e-02, 1.562500e-01, 0.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.625e-01, 0.0, -1.875e-01, 0.0, 0.0, 0.0, 0.375, 9.375e-01, 1.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.625e-01, 0.0, -1.875e-01, 0.0, 0.0, 0.0, -0.375, -3.125e-01, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 7.5e-01, 0.0, 0.0, 0.0, 7.5e-01, 0.0, 0.0}}; mtl::dense2D<double> ElInfo2d::mat_d4_left(mat_d4_left_val); - double ElInfo2d::mat_d4_right_val[15][15] = {{0.0, 0.0, 0.0, -3.90625e-02, 0.0, 2.34375e-02, 2.34375e-02, 0.0, -3.90625e-02, 0.0, 0.0, 0.0, -3.90625e-02, -3.90625e-02, 0.0}, - {1.0, 0.0, 0.0, -3.90625e-02, 0.0, 2.34375e-02, -3.90625e-02, 0.0, 2.734375e-01, 0.0, 0.0, 0.0, -3.90625e-02, 2.34375e-02, 0.0}, - {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, 1.875e-01, 0.0, -6.25e-02, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 3.125e-01, -1.25e-01, 0.0}, - {0.0, 0.0, 0.0, -3.75e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 3.75e-01, 0.0}, - {0.0, 0.0, 0.0, 5.0e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 5.0e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, -3.75e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.25e-01, 0.0}, - {0.0, 0.0, 0.0, 1.875e-01, 0.0, -6.25e-02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.25e-02, 1.25e-01, 0.0}, - {0.0, 0.0, 0.0, 3.125e-02, 0.0, -9.375e-02, -1.5625e-01, 0.0, 2.1875e-01, 0.0, 0.0, 0.0, 1.5625e-01, 9.375e-02, 0.0}, - {0.0, 0.0, 1.0, 1.5625e-02, 0.0, 1.40625e-01, 7.03125e-01, 0.0, -5.46875e-01, 0.0, 0.0, 0.0, -2.34375e-01, -4.6875e-02, 0.0}, - {0.0, 0.0, 0.0, 3.125e-02, 0.0, -9.375e-02, 4.6875e-01, 1.0, 1.09375e+00, 0.0, 0.0, 0.0, 1.5625e-01, -3.125e-02, 0.0}, - {0.0, 0.0, 0.0, -1.875e-01, 0.0, 5.625e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.125e-01, -3.75e-01, 0.0}, - {0.0, 0.0, 0.0, -1.875e-01, 0.0, 5.625e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.375e-01, 3.75e-01, 1.0}, - {0.0, 0.0, 0.0, 7.5e-01, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.5e-01, 0.0}}; + double ElInfo2d::mat_d4_right_val[15][15] = {{0.0, 0.0, 0.0, -3.906250e-02, 0.0, 2.343750e-02, 2.343750e-02, 0.0, -3.906250e-02, 0.0, 0.0, 0.0, -3.906250e-02, -3.906250e-02, 0.0}, + {1.0, 0.0, 0.0, -3.906250e-02, 0.0, 2.343750e-02, -3.906250e-02, 0.0, 2.734375e-01, 0.0, 0.0, 0.0, -3.906250e-02, 2.343750e-02, 0.0}, + {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, 1.875e-01, 0.0, -6.25e-02, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 3.125e-01, -0.125, 0.0}, + {0.0, 0.0, 0.0, -0.375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.375, 0.0}, + {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, + {0.0, 0.0, 0.0, -0.375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.125, 0.0}, + {0.0, 0.0, 0.0, 1.875e-01, 0.0, -6.25e-02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.25e-02, 0.125, 0.0}, + {0.0, 0.0, 0.0, 3.125e-02, 0.0, -9.375e-02, -1.562500e-01, 0.0, 2.187500e-01, 0.0, 0.0, 0.0, 1.562500e-01, 9.375e-02, 0.0}, + {0.0, 0.0, 1.0, 1.562500e-02, 0.0, 1.406250e-01, 7.031250e-01, 0.0, -5.468750e-01, 0.0, 0.0, 0.0, -2.343750e-01, -4.687500e-02, 0.0}, + {0.0, 0.0, 0.0, 3.125e-02, 0.0, -9.375e-02, 4.687500e-01, 1.0, 1.093750e+00, 0.0, 0.0, 0.0, 1.562500e-01, -3.125e-02, 0.0}, + {0.0, 0.0, 0.0, -1.875e-01, 0.0, 5.625e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -3.125e-01, -0.375, 0.0}, + {0.0, 0.0, 0.0, -1.875e-01, 0.0, 5.625e-01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.375e-01, 0.375, 1.0}, + {0.0, 0.0, 0.0, 7.5e-01, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.5e-01, 0.0}}; mtl::dense2D<double> ElInfo2d::mat_d4_right(mat_d4_right_val); @@ -873,39 +873,6 @@ namespace AMDiS { mtl::dense2D<double>& ElInfo2d::getSubElemGradCoordsMat(int degree) const { - FUNCNAME("ElInfo2d::getSubElemGradCoordsMat()"); - - TEST_EXIT(degree == 1)("Not supported for basis functions with degree > 1!\n"); - - using namespace mtl; - - if (subElemGradMatrices[degree].count(std::make_pair(refinementPathLength, refinementPath)) == 0) { - dense2D<double> mat(3, 3), tmpMat(3, 3); - mat = 1; - - double test_left[3][3] = {{0.0, 0.0, 0.5}, - {-0.5, -0.5, 0.0}, - {1.0, 0.0, 0.0}}; - double test_right[3][3] = {{0.0, 0.0, 0.5}, - {0.5, -0.5, 0.0}, - {0.0, 1.0, 0.0}}; - - mtl::dense2D<double> mat_left(test_left); - mtl::dense2D<double> mat_right(test_right); - - - for (int i = 0; i < refinementPathLength; i++) - if (refinementPath & (1 << i)) { - tmpMat = mat_right * mat; - mat = tmpMat; - } else { - tmpMat = mat_left * mat; - mat = tmpMat; - } - - subElemGradMatrices[1][std::make_pair(refinementPathLength, refinementPath)] = mat; - } - - return subElemGradMatrices[degree][std::make_pair(refinementPathLength, refinementPath)]; + return getSubElemCoordsMat(degree); } } diff --git a/AMDiS/src/ElInfo3d.cc b/AMDiS/src/ElInfo3d.cc index f12d656a35b67b2e6d68089081a8b4ed43a2edbd..df70e11ddf8199aca87b75ce7727012901baef8b 100644 --- a/AMDiS/src/ElInfo3d.cc +++ b/AMDiS/src/ElInfo3d.cc @@ -824,11 +824,7 @@ namespace AMDiS { mtl::dense2D<double>& ElInfo3d::getSubElemGradCoordsMat(int degree) const { - FUNCNAME("ElInfo3d::getSubElemGradCoordsMat()"); - - ERROR_EXIT("Not yet implemented!\n"); - - return subElemGradMatrices[degree][std::make_pair(refinementPathLength, refinementPath)]; + return getSubElemCoordsMat(degree); } } diff --git a/AMDiS/src/Expressions.h b/AMDiS/src/Expressions.h index a1ea58e15e2b6e32a4ff99eeaeecce0cebfb29d5..cc5771fff66ab2c259d3e0d0c664f7a25a25f1f0 100644 --- a/AMDiS/src/Expressions.h +++ b/AMDiS/src/Expressions.h @@ -28,6 +28,7 @@ #include "AMDiS_fwd.h" #include "OperatorTerm.h" #include "Functors.h" +#include "MatrixVectorOperations.h" #include <boost/static_assert.hpp> #include <boost/type_traits.hpp> @@ -94,6 +95,7 @@ namespace AMDiS { +/// helper class to adopt the correct OperatorTerm based on the term order template<int Order> struct GetTerm { typedef typename boost::mpl::if_c<Order == 0, ZeroOrderTerm, @@ -103,19 +105,27 @@ struct GetTerm { >::type >::type >::type type; }; - +/// basic interface for OperatorTerms based on expressions template<typename Term, int Order = -1> struct GenericOperatorTerm : public GetTerm<Order>::type { typedef typename GetTerm<Order>::type super; + /// Expression term stored as copy Term term; + + /// constructor + /// adds all feSpaces provided by the expression term to auxFeSpaces liste GenericOperatorTerm(const Term& term_) : super(term_.getDegree()), term(term_) { term.insertFeSpaces(this->auxFeSpaces); +#ifndef NDEBUG + test_auxFeSpaces(this->auxFeSpaces); +#endif } + /// calls initElement() for \ref term void initElement(const ElInfo* elInfo, SubAssembler* subAssembler, Quadrature *quad) @@ -123,6 +133,7 @@ struct GenericOperatorTerm : public GetTerm<Order>::type term.initElement(this, elInfo, subAssembler, quad, NULL); } + /// calls initElement() for \ref term void initElement(const ElInfo* smallElInfo, const ElInfo* largeElInfo, SubAssembler* subAssembler, @@ -130,9 +141,22 @@ struct GenericOperatorTerm : public GetTerm<Order>::type { term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad, NULL); } -}; - + /// test for only one mesh allowed in expressions + template<typename FeSpaceList> + void test_auxFeSpaces(FeSpaceList const& auxFeSpaces) + { + typedef typename FeSpaceList::const_iterator fe_iter; + if (auxFeSpaces.size() > 0) { + Mesh* mesh0 = (*auxFeSpaces.begin())->getMesh(); + for (fe_iter it = auxFeSpaces.begin(); it != auxFeSpaces.end(); it++) { + if ((*it)->getMesh() != mesh0) { + ERROR_EXIT("Only one mesh allowed in expression.\n"); + } + } + } + } +}; template<typename Term> struct GenericOperatorTerm<Term, -1> : public GenericOperatorTerm<Term, -2> @@ -687,7 +711,7 @@ template<typename Term> inline typename boost::enable_if<typename traits::is_expr<Term>::type, typename Term::value_type>::type max(Term term) { - typename Term::value_type value0 = -1.e25; + typename Term::value_type value0 = std::numeric_limits<typename Term::value_type>::min(); value0 = accumulate(term, functors::max<typename Term::value_type>(), value0); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS @@ -701,7 +725,7 @@ template<typename Term> inline typename boost::enable_if<typename traits::is_expr<Term>::type, typename Term::value_type>::type min(Term term) { - typename Term::value_type value0 = 1.e25; + typename Term::value_type value0 = std::numeric_limits<typename Term::value_type>::max(); value0 = accumulate(term, functors::min<typename Term::value_type>(), value0); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS @@ -715,7 +739,7 @@ template<typename Term> inline typename boost::enable_if<typename traits::is_expr<Term>::type, typename Term::value_type>::type abs_max(Term term) { - typename Term::value_type value0 = 0.0; + typename Term::value_type value0 = 0; value0 = accumulate(term, functors::abs_max<typename Term::value_type>(), value0); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS @@ -729,7 +753,7 @@ template<typename Term> inline typename boost::enable_if<typename traits::is_expr<Term>::type, typename Term::value_type>::type abs_min(Term term) { - typename Term::value_type value0 = 1.e25; + typename Term::value_type value0 = std::numeric_limits<typename Term::value_type>::max(); value0 = accumulate(term, functors::abs_min<typename Term::value_type>(), value0); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS @@ -744,19 +768,61 @@ abs_min(Term term) template<typename T, typename Term> inline typename boost::enable_if< typename boost::mpl::and_<typename traits::is_expr<Term>::type, - typename boost::is_convertible<typename Term::value_type, T>::type + typename traits::is_convertible<typename Term::value_type, T>::type >::type >::type transformDOF(Term term, DOFVector<T>* result); +/// Assign an expression to a DOFVector (using multi-mesh if term and result vector are on different meshes) +template<typename T, typename Term> +inline typename boost::enable_if< + typename boost::mpl::and_<typename traits::is_expr<Term>::type, + typename traits::is_convertible<typename Term::value_type, T>::type + >::type + >::type +transformDOF_mm(Term term, DOFVector<T>* result); + /// Assign an expression to a DOFVector template<typename T, typename Term> typename boost::enable_if< typename boost::mpl::and_<typename traits::is_expr<Term>::type, - typename boost::is_convertible<typename Term::value_type, T>::type + typename traits::is_convertible<typename Term::value_type, T>::type >::type, DOFVector<T>& >::type -operator<<(DOFVector<T>& result, const Term& term); +operator<<(DOFVector<T>& result, const Term& term) +{ + transformDOF(term, &result); + return result; +} + + +/// Assign a constant value to a DOFVector +// template<typename T, typename S> +// typename boost::enable_if< +// typename boost::mpl::or_< +// typename boost::mpl::and_< +// typename traits::is_scalar<T>::type, +// typename traits::is_scalar<S>::type, +// typename boost::is_convertible<S, T>::type +// >::type, +// typename boost::mpl::and_< +// typename traits::is_vector<T>::type, +// typename traits::is_vector<S>::type, +// typename boost::is_convertible<typename S::value_type, typename T::value_type>::type +// >::type, +// typename boost::mpl::and_< +// typename traits::is_matrix<T>::type, +// typename traits::is_matrix<S>::type, +// typename boost::is_convertible<typename S::value_type, typename T::value_type>::type +// >::type +// >::type, +// DOFVector<T>& // return type +// >::type +// operator<<(DOFVector<T>& result, const S& value) +// { +// result.set(value); +// return result; +// } // ----------------------------------------------------------------------------- @@ -764,7 +830,11 @@ operator<<(DOFVector<T>& result, const Term& term); template<typename Term> typename boost::enable_if<typename traits::is_expr<Term>::type, std::ostream& >::type -operator<<(std::ostream& result, const Term& term); +operator<<(std::ostream& result, const Term& term) +{ + result << term.str(); + return result; +} } // end namespace AMDiS diff --git a/AMDiS/src/Expressions.hh b/AMDiS/src/Expressions.hh index 22c4fb163be3fb4d2c2b02191735eed8927364d1..7d7c7c65404925d8966edbb3ae4fa329d6ba9fd5 100644 --- a/AMDiS/src/Expressions.hh +++ b/AMDiS/src/Expressions.hh @@ -23,36 +23,6 @@ /** \file Expressions.hh */ namespace AMDiS { - -#if 0 -namespace detail { - - template<typename Term, typename T, typename Enable = void> - struct GenericOperatorTerm { }; - - template<typename Term, typename T> - struct GenericOperatorTerm<Term, T, typename boost::enable_if<traits::is_scalar<T> >::type> { - typedef GenericZeroOrderTerm<Term> type; - }; - - template<typename Term, typename T> - struct GenericOperatorTerm<Term, T, typename boost::enable_if<traits::is_vector<T> >::type> { - typedef GenericFirstOrderTerm_b<Term> type; - }; - - template<typename Term, typename T > - struct GenericOperatorTerm<Term, T, typename boost::enable_if<traits::is_matrix<T> >::type> { - typedef GenericSecondOrderTerm_A<Term, true> type; - }; - -} // end namespace detail - -template<typename Term> -struct GenericOperatorTerm { - typedef typename detail::GenericOperatorTerm<Term, typename Term::value_type>::type type; -}; -#endif - template<typename Term> inline typename boost::enable_if<typename traits::is_expr<Term>::type, typename Term::value_type>::type @@ -139,32 +109,38 @@ accumulate(Term term, Functor f, typename Term::value_type value0) template<typename T, typename Term> inline typename boost::enable_if< typename boost::mpl::and_<typename traits::is_expr<Term>::type, - typename boost::is_convertible<typename Term::value_type, T>::type + typename traits::is_convertible<typename Term::value_type, T>::type >::type >::type transformDOF(Term term, DOFVector<T>* result) { - typedef typename Term::value_type TOut; - TOut tmp; nullify(tmp); + GenericOperatorTerm<Term> ot(term); + std::set<const FiniteElemSpace*> feSpaces = ot.getAuxFeSpaces(); + Mesh* mesh = result->getFeSpace()->getMesh(); + if (feSpaces.size() > 0 && mesh != (*feSpaces.begin())->getMesh()) + return transformDOF_mm(term, result); + + + typedef typename Term::value_type TOut; DOFVector<TOut> temp(result->getFeSpace(), "temp"); DOFVector<int> assigned(result->getFeSpace(), "assigned"); - GenericOperatorTerm<Term> ot(term); - Mesh* mesh = result->getFeSpace()->getMesh(); - const FiniteElemSpace* resultFeSpace = temp.getFeSpace(); const BasisFunction *basisFcts = resultFeSpace->getBasisFcts(); int nBasisFcts = basisFcts->getNumber(); - assigned.set(0); - temp.set(tmp); - std::vector<DegreeOfFreedom> localIndices(nBasisFcts); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_GRD_LAMBDA); + term.initElement(&ot, elInfo, NULL, NULL, basisFcts); + + + TOut tmp(term(0)); nullify(tmp); + assigned.set(0); + temp.set(tmp); while (elInfo) { term.initElement(&ot, elInfo, NULL, NULL, basisFcts); @@ -187,31 +163,88 @@ transformDOF(Term term, DOFVector<T>* result) DOFIterator<T> resultIter(result, USED_DOFS); DOFIterator<int> assignedIter(&assigned, USED_DOFS); for (tempIter.reset(), resultIter.reset(), assignedIter.reset(); !resultIter.end(); ++tempIter, ++resultIter, ++assignedIter) { - *resultIter = (*tempIter) * (1.0/static_cast<double>(*assignedIter)); + *resultIter = (*tempIter); + *resultIter/= (*assignedIter); } } + +// works only for nodal basis functions! template<typename T, typename Term> -typename boost::enable_if< +inline typename boost::enable_if< typename boost::mpl::and_<typename traits::is_expr<Term>::type, - typename boost::is_convertible<typename Term::value_type, T>::type - >::type, - DOFVector<T>& >::type -operator<<(DOFVector<T>& result, const Term& term) + typename traits::is_convertible<typename Term::value_type, T>::type + >::type + >::type +transformDOF_mm(Term term, DOFVector<T>* result) { - transformDOF(term, &result); - return result; -} + typedef typename Term::value_type TOut; + + GenericOperatorTerm<Term> ot(term); + std::set<const FiniteElemSpace*> feSpaces = ot.getAuxFeSpaces(); + + Mesh* mesh1 = result->getFeSpace()->getMesh(); + Mesh* mesh2 = (*feSpaces.begin())->getMesh(); + + DOFVector<TOut> temp(result->getFeSpace(), "temp"); + DOFVector<int> assigned(result->getFeSpace(), "assigned"); + + const FiniteElemSpace* resultFeSpace = temp.getFeSpace(); + const BasisFunction *basisFcts = resultFeSpace->getBasisFcts(); + int nBasisFcts = basisFcts->getNumber(); + + std::vector<DegreeOfFreedom> localIndices(nBasisFcts); + mtl::dense_vector<TOut> vecLocalCoeffs(nBasisFcts); + DimVec<double> *lambda = NULL; + DimVec<double> *lambda_1 = new DimVec<double>; + WorldVector<double> coords; + + DualTraverse dualTraverse; + DualElInfo dualElInfo; + + Flag assembleFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_GRD_LAMBDA; + bool cont = dualTraverse.traverseFirst(mesh1, mesh2, -1, -1, + assembleFlag, assembleFlag, dualElInfo); + term.initElement(&ot, dualElInfo.colElInfo, NULL, NULL, basisFcts); + + TOut tmp(term(0)); nullify(tmp); + assigned.set(0); + temp.set(tmp); + + while (cont) { + term.initElement(&ot, dualElInfo.colElInfo, NULL, NULL, basisFcts); + basisFcts->getLocalIndices(dualElInfo.rowElInfo->getElement(), resultFeSpace->getAdmin(), localIndices); + + for (int i = 0; i < nBasisFcts; i++) + vecLocalCoeffs[i] = term(i); + + for (int i = 0; i < nBasisFcts; i++) { + lambda = basisFcts->getCoords(i); + dualElInfo.rowElInfo->coordToWorld(*lambda, coords); + int inside = dualElInfo.colElInfo->worldToCoord(coords, lambda_1); + if (inside < 0) { + temp[localIndices[i]] += basisFcts->evalUh(*lambda_1, vecLocalCoeffs); + assigned[localIndices[i]]++; + } + } + cont = dualTraverse.traverseNext(dualElInfo); + } -template<typename Term> -typename boost::enable_if<typename traits::is_expr<Term>::type, - std::ostream& >::type -operator<<(std::ostream& result, const Term& term) -{ - result << term.str(); - return result; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->synchAddVector(temp); + Parallel::MeshDistributor::globalMeshDistributor->synchAddVector(assigned); +#endif + + + DOFIterator<TOut> tempIter(&temp, USED_DOFS); + DOFIterator<T> resultIter(result, USED_DOFS); + DOFIterator<int> assignedIter(&assigned, USED_DOFS); + for (tempIter.reset(), resultIter.reset(), assignedIter.reset(); !resultIter.end(); ++tempIter, ++resultIter, ++assignedIter) { + *resultIter = (*tempIter); + *resultIter/= (*assignedIter); + } } } // end namespace AMDiS diff --git a/AMDiS/src/FirstOrderTerm.h b/AMDiS/src/FirstOrderTerm.h index 3915ee6ffede5e236bce29562f4b7ea5ae001f76..a3439635c8ff6b477f7d27f0070a43705124b3f1 100644 --- a/AMDiS/src/FirstOrderTerm.h +++ b/AMDiS/src/FirstOrderTerm.h @@ -31,6 +31,7 @@ #include "AbstractFunction.h" #include "ElInfo.h" #include "traits/size.hpp" +#include "MatrixVectorOperations.h" namespace AMDiS { diff --git a/AMDiS/src/FixVec.h b/AMDiS/src/FixVec.h index 3828213ae4c46202ff52d98637be201539b31c57..c8986d4ead16f4739aaa38e8a96a459ed204d8dc 100644 --- a/AMDiS/src/FixVec.h +++ b/AMDiS/src/FixVec.h @@ -69,7 +69,7 @@ namespace AMDiS { : Vector<T>(calcSize(dim)) { TEST_EXIT_DBG(initType == VALUE_LIST)("wrong initType or wrong initializer\n"); - setValues(ini); + this->setValues(ini); } /// constructor with default value initialisation. initType must be @@ -144,7 +144,7 @@ namespace AMDiS { /// constructs a VectorOfFixVecs via an value list. dim is passed to /// FixVec's constructors. size_ is the number of contained FixVecs. initType /// must be VALUE_LIST. ini contains the initialisation values. - VectorOfFixVecs(int d, int s, InitType initType, const FixVecType* ini) + VectorOfFixVecs(int d, int s, InitType initType, FixVecType const* ini) : size(s), dim(d) { @@ -341,7 +341,7 @@ namespace AMDiS { {} /// Calls the corresponding constructor of FixVec - DimVec(int dim, InitType initType, T* ini) + DimVec(int dim, InitType initType, T const* ini) : FixVec<T,PARTS>(dim, initType, ini) {} @@ -378,7 +378,7 @@ namespace AMDiS { } /// Calls the corresponding constructor of VectorOfFixVecs - DimMat(int dim, InitType initType, T* ini) + DimMat(int dim, InitType initType, T const* ini) : Matrix<T>(dim + 1, dim + 1) { TEST_EXIT_DBG(initType == VALUE_LIST)("wrong initType or wrong initializer\n"); @@ -396,28 +396,61 @@ namespace AMDiS { class WorldVector : public FixVec<T, WORLD> { public: + typedef WorldVector self; + typedef FixVec<T, WORLD> super; + /// Calls the corresponding constructor of AlgoVec WorldVector() - : FixVec<T, WORLD>(Global::getGeo(WORLD), NO_INIT) + : super(Global::getGeo(WORLD), NO_INIT) {} /// Calls the corresponding constructor of AlgoVec - WorldVector(InitType initType, T* ini) - : FixVec<T, WORLD>(Global::getGeo(WORLD), initType, ini) + WorldVector(InitType initType, T const* ini) + : super(Global::getGeo(WORLD), initType, ini) {} /// Calls the corresponding constructor of AlgoVec WorldVector(InitType initType, const T& ini) - : FixVec<T, WORLD>(Global::getGeo(WORLD), initType, ini) + : super(Global::getGeo(WORLD), initType, ini) + {} + + +// /// Copy constructor for other of different value_type +// template <typename S> +// WorldVector(Vector<S> const& other) +// : super(Global::getGeo(WORLD), NO_INIT) +// { +// operator=(other); +// } +// + /// Copy constructor for other of same value_type + WorldVector(self const& other) + : super(other) {} + + + /// Assignement operator + template <typename S> + inline self& operator=(const Vector<S>& rhs) + { + this->setValues(rhs.getValArray()); + return *this; + } + + /// Assignement operator + inline self& operator=(const self& rhs) + { + this->setValues(rhs.getValArray()); + return *this; + } - /// Sets all entries to d + /// Sets all entries to scal template <typename S> - inline const WorldVector<T>& - operator=(const S& d) + typename enable_if<boost::is_convertible<S, T>, WorldVector<T> >::type & + operator=(S scal) { - this->set(d); - return (*this); + this->set(scal); + return *this; } /// Sets the arrays value to the geometric midpoint of the points p1 and p2. @@ -447,17 +480,20 @@ namespace AMDiS { class WorldMatrix : public Matrix<T> { public: + typedef WorldMatrix self; + typedef Matrix<T> super; + /// Calls the corresponding constructor of FixVec WorldMatrix() - : Matrix<T>(Global::getGeo(WORLD), Global::getGeo(WORLD)) + : super(Global::getGeo(WORLD), Global::getGeo(WORLD)) {} /// Calls the corresponding constructor of FixVec WorldMatrix(InitType initType, T* ini) - : Matrix<T>(Global::getGeo(WORLD), Global::getGeo(WORLD)) + : super(Global::getGeo(WORLD), Global::getGeo(WORLD)) { TEST_EXIT_DBG(initType == VALUE_LIST)("???\n"); - setValues(ini); + this->setValues(ini); } /** \brief @@ -465,14 +501,48 @@ namespace AMDiS { * to ini */ WorldMatrix(InitType initType, const T& ini) - : Matrix<T>(Global::getGeo(WORLD), Global::getGeo(WORLD)) + : super(Global::getGeo(WORLD), Global::getGeo(WORLD)) { TEST_EXIT_DBG(initType == DEFAULT_VALUE)("wrong initType or wrong initializer\n"); this->set(ini); } - // import assignment operator from base class - using Matrix<T>::operator=; +// /// Copy constructor for other of different value_type +// template <typename S> +// WorldMatrix(Matrix<S> const& other) +// : super(Global::getGeo(WORLD), Global::getGeo(WORLD)) +// { +// this->setValues(other.getValArray()); +// } +// +// /// Copy constructor + WorldMatrix(self const& other) + : super(other) + { } + + /// Assignement operator + template <typename S> + inline self& operator=(const Matrix<S>& rhs) + { + this->setValues(rhs.getValArray()); + return *this; + } + + /// Assignement operator + inline self& operator=(const self& rhs) + { + this->setValues(rhs.getValArray()); + return *this; + } + + /// Assignement operator for scalars + template <typename S> + typename enable_if<boost::is_convertible<S, T>, WorldMatrix<T> >::type & + operator=(S rhs) + { + this->set(rhs); + return *this; + } /// Returns true if the matrix is a diagonal matrix, returns false otherwise. bool isDiagMatrix() const; @@ -495,12 +565,6 @@ namespace AMDiS { void vecProduct(const WorldVector<T>& v1, const WorldVector<T>& v2); }; - - - /// returns the euclidian distance of a and b - template<typename T, GeoIndex d> - double absteukl(const FixVec<T,d>& a, const FixVec<T,d>& b); - /// FixVec operator for stream output template<typename T, GeoIndex d> std::ostream& operator <<(std::ostream& out, const FixVec<T,d>& fixvec) @@ -517,177 +581,6 @@ namespace AMDiS { /// creates and inits and double array double *createAndInitArray(int size, ...); - template<typename T> - WorldVector<T> operator*(const WorldVector<T>& v, double d) - { - WorldVector<T> result = v; - result *= d; - return result; - } - - template<typename T> - WorldVector<T> operator*(double d, const WorldVector<T>& v) - { - return v * d; - } - - template<typename T> - WorldVector<T> operator/(const WorldVector<T>& v, double d) - { - WorldVector<T> result = v; - result = v * (1.0/d); - return result; - } - - template<typename T> - WorldVector<T>& operator+=(WorldVector<T>& v1, - const WorldVector<T>& v2) - { - add(v1, v2, v1); - return v1; - } - - template<typename T> - WorldVector<T>& operator-=(WorldVector<T>& v1, - const WorldVector<T>& v2) - { - axpy(-1.0, v2, v1); - return v1; - } - - template<typename T> - WorldVector<T> operator+(const WorldVector<T>& v1, - const WorldVector<T>& v2) - { - WorldVector<T> result = v1; - result += v2; - return result; - } - - template<typename T> - WorldVector<T> operator-(const WorldVector<T>& v1, - const WorldVector<T>& v2) - { - WorldVector<T> result = v1; - result -= v2; - return result; - } - - inline bool operator<(const WorldVector<double>& v1, const WorldVector<double>& v2) - { - int dow = Global::getGeo(WORLD); - for (int i = 0; i < dow; i++) { - if (abs(v1[i] - v2[i]) < DBL_TOL) - continue; - return v1[i] < v2[i]; - } - return false; - } - - inline bool operator==(const WorldVector<double>& v1, const WorldVector<double>& v2) - { - int dow = Global::getGeo(WORLD); - for (int i = 0; i < dow; i++) - if (abs(v1[i] - v2[i]) > DBL_TOL) - return false; - - return true; - } - - template<typename T> - WorldMatrix<T>& operator*=(WorldMatrix<T>& m, T scal); - - template<typename T> - WorldMatrix<T>& operator-=(WorldMatrix<T>& m1, const WorldMatrix<T>& m2); - - template<typename T> - WorldMatrix<T>& operator+=(WorldMatrix<T>& m1, const WorldMatrix<T>& m2); - - template<typename T> - WorldMatrix<T> operator*(WorldMatrix<T> v, double d) - { - v *= d; - return v; - } - - template<typename T> - WorldMatrix<T> operator*(double d, WorldMatrix<T> v) - { - v *= d; - return v; - } - - template<typename T> - WorldMatrix<T> operator/(WorldMatrix<T> v, double d) - { - v *= 1./d; - return v; - } - - template<typename T> - WorldVector<T> operator*(const WorldMatrix<T>& M, const WorldVector<T>& v ) - { - WorldVector<T> res; - res.multMatrixVec(M,v); - return res; - } - - template<typename T> - WorldMatrix<T> operator+(WorldMatrix<T> M1, const WorldMatrix<T>& M2 ) - { - M1 += M2; - return M1; - } - - template<typename T> - WorldMatrix<T> operator-(WorldMatrix<T> M1, const WorldMatrix<T>& M2 ) - { - M1 -= M2; - return M1; - } - - template<typename T> - WorldVector<WorldVector<T> > - operator*(const WorldVector<WorldVector<T> >& A, const WorldVector<WorldVector<T> >& B) - { - WorldVector<WorldVector<T> > result; - nullify(result); - for (size_t r = 0; r < num_rows(A); r++) - for (size_t c = 0; c < num_cols(A); c++) - for (size_t i = 0; i < num_cols(A); i++) - result[r][c] += A[r][i] * B[i][c]; - return result; - } - - template<typename T> - void set_to_zero(WorldVector<WorldVector<T> >& mat) - { - nullify(mat); - } - - template<typename T> - WorldVector<T> operator-(WorldVector<T> v) - { - v *= -1.0; - return v; - } - - template<typename T> - WorldMatrix<T> operator-(WorldMatrix<T> v) - { - v *= -1.0; - return v; - } - - inline double norm(const WorldVector<double>& v) - { - double val = 0.0; - for (int i = 0; i < Global::getGeo(WORLD); i++) - val += v[i] * v[i]; - return sqrt(val); - } - - template<typename T> struct GradientType { @@ -772,8 +665,6 @@ namespace mtl } // end namespace traits } // end namespace mtl - - #include "FixVec.hh" #endif // AMDIS_FIXVEC_H diff --git a/AMDiS/src/FixVec.hh b/AMDiS/src/FixVec.hh index 98b9aaebb1e053987b1839da5e1a606db6a4f368..24704567cc6d492758472a2762d99692e9dab5b7 100644 --- a/AMDiS/src/FixVec.hh +++ b/AMDiS/src/FixVec.hh @@ -34,17 +34,6 @@ namespace AMDiS { } } - template<typename T, GeoIndex d> - double absteukl(const FixVec<T,d>& a,const FixVec<T,d>& b) - { - double erg = 0.0; - - for (int i = 0; i < a.getSize() ; i++) - erg = erg + ((a[i] - b[i]) * (a[i] - b[i])); - - return sqrt(erg); - } - template<typename T> void WorldVector<T>::multMatrixVec(const WorldMatrix<T> &m, const WorldVector<T> &v) { @@ -107,36 +96,4 @@ namespace AMDiS { *thisIt = *v1It * *v2It; } - template<typename T> - WorldMatrix<T>& operator*=(WorldMatrix<T>& m, T scal) - { - for (T* mIt = m.begin(); mIt != m.end(); mIt++) - *mIt *= scal; - - return m; - } - - template<typename T> - WorldMatrix<T>& operator-=(WorldMatrix<T>& m1, const WorldMatrix<T>& m2) - { - T *m1It, *m2It; - for (m1It = m1.begin(), m2It = m2.begin(); - m1It != m1.end(); - m1It++, m2It++) - *m1It -= *m2It; - - return m1; - } - - template<typename T> - WorldMatrix<T>& operator+=(WorldMatrix<T>& m1, const WorldMatrix<T>& m2) - { - T* m1It, *m2It; - for (m1It = m1.begin(), m2It = m2.begin(); - m1It != m1.end(); - m1It++, m2It++) - *m1It += *m2It; - - return m1; - } } diff --git a/AMDiS/src/Global.h b/AMDiS/src/Global.h index 42405845a9cc5ed8144a3c8f22ab26efa86ed57f..2f44fdc50c4b19a315bf2039f165afa83fdbed67 100644 --- a/AMDiS/src/Global.h +++ b/AMDiS/src/Global.h @@ -31,29 +31,7 @@ #ifndef AMDIS_GLOBAL_H #define AMDIS_GLOBAL_H -#if (__GNUC__) && (__GNUC__ > 2) -#define OPENMODE std::ios::openmode -#else -#define OPENMODE std::ios::open_mode -#endif - -#include <boost/config.hpp> - -// TODO: better c++11 test! -#if (defined BOOST_NO_CXX11_OVERRIDE) || __cplusplus <= 199711L || ((defined _MSC_VER) && _MSC_VER < 1100) - #define override -#endif -#if !((defined BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_DECLTYPE)) - #define HAS_CPP11_DECLTYPE -#endif -#if !((defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) || (defined BOOST_NO_VARIADIC_TEMPLATES)) || (defined BOOST_HAS_VARIADIC_TMPL) - #define HAS_VARIADIC_TEMPLATES -#endif - -/** \brief current AMDiS version */ -#ifndef AMDIS_VERSION -#define AMDIS_VERSION "AMDiS: Version 0.9.1" -#endif +#include "Config.h" #include <string> #include <vector> @@ -66,7 +44,7 @@ #include <float.h> #include <time.h> -#ifdef _WIN32 +#ifdef _MSC_VER #include <io.h> #else #include <unistd.h> @@ -87,7 +65,7 @@ namespace AMDiS { extern const char *funcName; - const int amdisRevisionNumber = 1700; + const int amdisRevisionNumber = 1700; // TODO: how to update this value /// Used by matrix vector multiplication typedef enum { NoTranspose, @@ -179,7 +157,7 @@ namespace AMDiS { /// check for file existence inline bool file_exists(const std::string filename) { -#ifdef _WIN32 +#ifdef _MSC_VER return _access(filename.c_str(), 0) == 0; #else return access(filename.c_str(), F_OK) == 0; @@ -470,7 +448,9 @@ namespace AMDiS { BOUNDARY =-5, /**< index for boundary nodes of an element. This could be * vertices, edges or faces. */ - PROJECTION=-6 /**< index for element and boundary projections */ + PROJECTION=-6, /**< index for element and boundary projections */ + + NO_INDEX =-127 } GeoIndex; #define MAXPART FACE diff --git a/AMDiS/src/MacroElement.h b/AMDiS/src/MacroElement.h index 7dd5996ca20eb288f96eb5b74029da4ccdbb42c9..d2e2c0ed5949b5ba96e0aa8885fa23382f861e22 100644 --- a/AMDiS/src/MacroElement.h +++ b/AMDiS/src/MacroElement.h @@ -82,6 +82,15 @@ namespace AMDiS { return neighbour[i]; } + /// Returns the i-th inverse neighbour of this MacroElement \ref neighbour_inv[i] + /// Uses the inverse neighbour relation in graph-structured meshes where + /// elements can have more than one neighbour + /// If [b] is neighbour of [a], then is [a] neighbour_inv of [b] + inline MacroElement* getNeighbourInv(int i) const + { + return neighbour_inv[i]; + } + /// Returns the i-th opp-vertex of this MacroElement \ref oppVertex[i] inline int getOppVertex(int i) const { @@ -202,6 +211,9 @@ namespace AMDiS { /// Pointers to all neighbours of this MacroElement FixVec<MacroElement*, NEIGH> neighbour; + /// Pointers to all neighbours of this MacroElement + FixVec<MacroElement*, NEIGH> neighbour_inv; + /// opp vertices of this MacroElement FixVec<int, NEIGH> oppVertex; diff --git a/AMDiS/src/MatrixVector.h b/AMDiS/src/MatrixVector.h index 354c67511d7c7abb29a6fd692fac06d72d4b4941..b502ddcf102d368f4903b632fde8d3b2a12ee42a 100644 --- a/AMDiS/src/MatrixVector.h +++ b/AMDiS/src/MatrixVector.h @@ -29,6 +29,7 @@ #include "Global.h" #include "AMDiS_fwd.h" #include "Serializable.h" +#include "traits/basic.hpp" // not dependenciess on other AMDiS types namespace AMDiS { @@ -38,17 +39,43 @@ namespace AMDiS { { public: - typedef T value_type; + typedef T value_type; + typedef Vector self; /// Constructor. Vector(int i = 0) - : size(i), + : size(0), valArray(NULL) { - if (size == 0) + resize(i); + } + + /// Copy constructor. + Vector(self const& rhs) + : Serializable(), + size(rhs.getSize()), + valArray(new T[rhs.getSize()]) + { + setValues(rhs.getValArray()); + } + + /// Copy constructor for other of different value_type + template <typename S> + Vector(Vector<S> const& rhs) + : Serializable(), + size(rhs.getSize()), + valArray(new T[rhs.getSize()]) + { + setValues(rhs.getValArray()); + } + + /// Destructor. + virtual ~Vector() + { + if (valArray != NULL) { + delete [] valArray; valArray = NULL; - else - valArray = new T[size]; + } } inline bool used() const @@ -59,7 +86,7 @@ namespace AMDiS { /// Change the size of the vector to newSize. inline void resize(int newSize) { - if (size != newSize) { + if (size != newSize && newSize > 0) { if (valArray != NULL) delete [] valArray; valArray = new T[newSize]; @@ -67,42 +94,25 @@ namespace AMDiS { } } - /// Copy constructor. - Vector(const Vector<T>& rhs) - : Serializable(), - size(rhs.size) + /// Assignement operator + template <typename S> + inline self& operator=(Vector<S> const& rhs) { - valArray = new T[rhs.size]; - *this = rhs; // uses operator=() - } - - /// Destructor. - virtual ~Vector() - { - if (valArray != NULL) { - delete [] valArray; - valArray = NULL; - } + resize(rhs.getSize()); + this->setValues(rhs.getValArray()); + return *this; } - - /// Assignement operator - inline const Vector<T>& operator=(const Vector<T>& rhs) + + inline self& operator=(self const& rhs) { - TEST_EXIT_DBG(rhs.size == size) - ("Invalid sizes %d != %d!\n", rhs.size, size); - - T *rhsIt, *thisIt; - for (rhsIt = rhs.begin(), thisIt = this->begin(); - rhsIt != rhs.end(); - ++rhsIt, ++thisIt) - *thisIt = *rhsIt; - + resize(rhs.getSize()); + this->setValues(rhs.getValArray()); return *this; } - /// Assignement operator + /// Assignement operator for scalars template <typename S> - inline const Vector<T>& + typename enable_if<boost::is_convertible<S, T>, Vector<T> >::type & operator=(const S& scal) { for (T *thisIt = this->begin(); thisIt != this->end(); ++thisIt) @@ -112,54 +122,52 @@ namespace AMDiS { } /// Assignement operator - inline const Vector<T>& operator=(const T* vec) + inline self& operator=(const T* vec) { - T *thisIt; - const T *vecIt; - for (thisIt = this->begin(), vecIt = &vec[0]; - thisIt != this->end(); - ++thisIt, ++vecIt) - *thisIt = *vecIt; - + this->setValues(vec); return *this; } /// Sets all entries to scal. template <typename S> - inline typename boost::disable_if<boost::mpl::and_<boost::is_integral<S>, boost::is_pointer<T> >, const Vector<T>& >::type - set(const S& scal) + inline typename disable_if<and_<boost::is_integral<S>, boost::is_pointer<T> >, Vector<T>& >::type + set(S const& scal) { return *this = scal; } - inline const Vector<T>& set(const T& scal) + inline Vector<T>& set(T const& scal) { return *this = scal; } + void setValues_aux(const T* values, true_) // trivially copyable + { + std::memcpy(valArray, values, sizeof(T)*size); + } + + template <typename S> + void setValues_aux(const S* values, false_) // NOT trivially copyable + { + std::copy(values, values + size, valArray); + } /// Sets all entries. - inline const Vector<T>& setValues(const T* values) - { - T *thisIt; - const T *valuesIt; - for (thisIt = this->begin(), valuesIt = values; - thisIt != this->end(); - ++thisIt, ++valuesIt) - *thisIt = *valuesIt; - - return *this; + template <typename S> + void setValues(const S* values) + { + typedef typename and_< boost::is_same<S,T>, traits::is_trivially_copyable<S> >::type use_memcpy; + setValues_aux(values, use_memcpy()); } /// Sets all entries. - inline void fill(const T value) + inline void fill(T value) { - for (T *thisIt = this->begin(); thisIt != this->end(); thisIt++) - *thisIt = value; + std::fill(valArray, valArray + size, value); } /// Comparison operator. - inline bool operator==(const Vector<T>& rhs) const + inline bool operator==(Vector<T> const& rhs) const { if (size != rhs.size) return false; @@ -175,7 +183,7 @@ namespace AMDiS { } /// Comparison operator. - inline bool operator!=(const Vector<T>& rhs) const + inline bool operator!=(Vector<T> const& rhs) const { return !(*this==rhs); } @@ -207,13 +215,18 @@ namespace AMDiS { } /// Returns \ref size. - virtual int getSize() const + inline int getSize() const { return size; } /// Returns \ref valArray as T-array - inline T *getValArray() + inline T* getValArray() + { + return valArray; + } + + inline T const* getValArray() const { return valArray; } @@ -257,12 +270,26 @@ namespace AMDiS { class Matrix : public Vector<T> { public: + typedef Matrix self; + typedef Vector<T> super; + + /// Default constructor. + Matrix() + : Vector<T>(0), rows(0), cols(0) + {} + /// Constructor. Matrix(int r, int c) - : Vector<T>(r * c), + : super(r * c), rows(r), cols(c) {} + + Matrix(self const& other) + : super(other), + rows(other.getNumRows()), + cols(other.getNumCols()) + { } /// Changes the size of the matrix to newRows x newCols. inline void resize(int newRows, int newCols) @@ -274,10 +301,27 @@ namespace AMDiS { } } - /// Assignement operator. - inline const Matrix<T>& operator=(const T& scal) + /// Assignement operator + template <typename S> + inline self& operator=(const Matrix<S>& rhs) + { + resize(rhs.getNumRows(), rhs.getNumCols()); + this->setValues(rhs.getValArray()); + return *this; + } + + inline self& operator=(self const& rhs) + { + resize(rhs.getNumRows(), rhs.getNumCols()); + this->setValues(rhs.getValArray()); + return *this; + } + + /// Assignement operator for scalars. + inline Matrix<T>& operator=(const T& scal) { - return static_cast<const Matrix<T>&>(Vector<T>::operator=(scal)); + Vector<T>::operator=(scal); + return *this; } /// @@ -331,16 +375,16 @@ namespace AMDiS { } /// Returns \ref rows. - inline int getSize() const - { - return rows; - } +// inline int getSize() const +// { +// return rows*cols; +// } /// Returns pointer after the last vector element. - inline T *end() const - { - return this->valArray + (cols * rows); - } +// inline T *end() const +// { +// return this->valArray + (cols * rows); +// } void print() const { @@ -359,189 +403,6 @@ namespace AMDiS { /// Number of matrix columns. int cols; }; - - /// Matrix vector multiplication. - template<typename T> - inline const Vector<T>& mv(const Matrix<T>& m, const Vector<T>& v, Vector<T>& result) - { - TEST_EXIT_DBG(m.getNumCols() == v.getSize())("m and v not compatible\n"); - TEST_EXIT_DBG(v.getSize() == result.getSize())("wrong result size\n"); - - T *resultIt, *mIt, *vIt; - - for (resultIt = result.begin(), mIt = m.begin(); - resultIt != result.end(); - ++resultIt) { - *resultIt = 0; - for (vIt = v.begin(); vIt != v.end(); ++vIt, ++mIt) - *resultIt += *mIt * *vIt; - } - - return result; - } - - /// Matrix vector multiplication. - template<typename T> - inline const Vector<T>& operator*=(const Vector<T>& v, const Matrix<T>& m) - { - return mv(m, v, v); - } - - /// Matrix vector multiplication. - template<typename T> - inline Vector<T> operator*(const Matrix<T>& m, const Vector<T>& v) - { - Vector<T> result(v.getSize()); - return mv(m, v, result); - } - - /// Scalar product. - template<typename T> - inline double operator*(const Vector<T>& v1, const Vector<T>& v2) - { - double result = 0.0; - - T *v1It, *v2It; - for (v1It = v1.begin(), v2It = v2.begin(); - v1It != v1.end(); - ++v1It, ++v2It) - result += *v1It * *v2It; - - return result; - } - - /// Vector addition. - template<typename T> - inline const Vector<T>& add(const Vector<T>& v1, const Vector<T>& v2, Vector<T>& result) - { - TEST_EXIT_DBG(v1.getSize() == v2.getSize())("invalid size in test v1 == v2\n"); - TEST_EXIT_DBG(v2.getSize() == result.getSize())("invalid size in test v2 == result\n"); - T *v1It, *v2It, *resultIt; - for (v1It = v1.begin(), v2It = v2.begin(), resultIt = result.begin(); - v1It != v1.end(); - ++v1It, ++v2It, ++resultIt) - *resultIt = *v1It + *v2It; - - return result; - } - - /// scalar * vector - template<typename T, typename S> - inline const Vector<T>& mult(const S& scal, - const Vector<T>& v, - Vector<T>& result) - { - TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n"); - - T *vIt, *resultIt; - for (vIt = v.begin(), resultIt = result.begin(); - vIt != v.end(); - ++vIt, ++resultIt) - *resultIt = scal * *vIt; - - return result; - } - - /// vector + scalar - template<typename T> - inline const Vector<T>& add(const Vector<T>& v, const T& scal, Vector<T>& result) - { - TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n"); - T *vIt, *resultIt; - for (vIt = v.begin(), resultIt = result.begin(); - vIt != v.end(); - ++vIt, ++resultIt) - *resultIt = *vIt + scal; - - return result; - } - - /// y = a * x + y. - template<typename T, typename S> - inline const Vector<T>& axpy(const S& a, - const Vector<T> &x, - Vector<T> &y) - { - TEST_EXIT_DBG(x.getSize() == y.getSize())("invalid size\n"); - T *xIt, *yIt; - for (xIt = x.begin(), yIt = y.begin(); - xIt != x.end(); - ++xIt, ++yIt) - *yIt += a * *xIt; - - return y; - } - - template<typename T, typename S> - inline const Vector<T>& operator*=(Vector<T>& v, const S& scal) - { - return mult(scal, v, v); - } - - template<typename T> - inline Vector<T> operator*(const Vector<T>& v, const T& scal) - { - Vector<T> result = v; - result *= scal; - return result; - } - - template<typename T> - inline const Vector<T>& operator+(const Vector<T>& v1, const T& scal) - { - Vector<T> result(v1.getSize()); - return add(v1, scal, result); - } - - template<typename T> - inline const Vector<T>& operator+=(Vector<T>& v1, const Vector<T>& v2) - { - return add(v1, v2, v1); - } - - template<typename T> - inline Vector<T> operator+(const Vector<T>& v1, const Vector<T>& v2) - { - Vector<T> result = v1; - result += v2; - return result; - } - - template<typename T> - const Vector<T>& operator-=(Vector<T>& v1, const Vector<T>& v2) - { - return axpy(-1.0, v2, v1); - } - - template<typename T> - Vector<T> operator-(const Vector<T>& v1, const Vector<T>& v2) - { - Vector<T> result = v1; - result -= v2; - return result; - } - - template<typename T> - inline double norm(const Vector<T> *v) - { - T *vIt; - double result = 0; - for (vIt = v->begin(); vIt != v->end(); ++vIt) - result += *vIt * *vIt; - return sqrt(result); - } - - template<typename T> - void vectorProduct(const Vector<T>& x, - const Vector<T>& y, - Vector<T>& z) - { - FUNCNAME_DBG("vectorProduct()"); - TEST_EXIT_DBG(Global::getGeo(WORLD) == 3)("DIM_OF_WORLD != 3\n"); - z[0] = x[1] * y[2] - x[2] * y[1]; - z[1] = x[2] * y[0] - x[0] * y[2]; - z[2] = x[0] * y[1] - x[1] * y[0]; - } template<typename T> inline size_t num_rows(const Vector<T>& vec) diff --git a/AMDiS/src/MatrixVectorOperations.h b/AMDiS/src/MatrixVectorOperations.h new file mode 100644 index 0000000000000000000000000000000000000000..3190dc1e73a2b86ed52b3bd66a4b9cfcb435cc96 --- /dev/null +++ b/AMDiS/src/MatrixVectorOperations.h @@ -0,0 +1,579 @@ +/****************************************************************************** + * + * 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 MatrixVectorOperations.h */ + +#ifndef AMDIS_MATVEC_OPERATIONS_H +#define AMDIS_MATVEC_OPERATIONS_H + +#include "Traits.h" + +namespace AMDiS { + + // --------------------------------------------------------------------------- + // Operations with Vector and Matrix + + /// Matrix vector multiplication. + template<typename T> + inline const Vector<T>& mv(const Matrix<T>& m, const Vector<T>& v, Vector<T>& result) + { + TEST_EXIT_DBG(m.getNumCols() == v.getSize())("m and v not compatible\n"); + TEST_EXIT_DBG(v.getSize() == result.getSize())("wrong result size\n"); + + T *resultIt, *mIt, *vIt; + + for (resultIt = result.begin(), mIt = m.begin(); + resultIt != result.end(); + ++resultIt) { + *resultIt = 0; + for (vIt = v.begin(); vIt != v.end(); ++vIt, ++mIt) + *resultIt += *mIt * *vIt; + } + + return result; + } + + /// Vector addition. + template<typename T> + inline const Vector<T>& add(const Vector<T>& v1, const Vector<T>& v2, Vector<T>& result) + { + TEST_EXIT_DBG(v1.getSize() == v2.getSize())("invalid size in test v1 == v2\n"); + TEST_EXIT_DBG(v2.getSize() == result.getSize())("invalid size in test v2 == result\n"); + T *v1It, *v2It, *resultIt; + for (v1It = v1.begin(), v2It = v2.begin(), resultIt = result.begin(); + v1It != v1.end(); + ++v1It, ++v2It, ++resultIt) + *resultIt = *v1It + *v2It; + + return result; + } + + /// scalar * vector + template<typename T, typename S> + inline const Vector<T>& mult(const S& scal, + const Vector<T>& v, + Vector<T>& result) + { + TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n"); + + T *vIt, *resultIt; + for (vIt = v.begin(), resultIt = result.begin(); + vIt != v.end(); + ++vIt, ++resultIt) + *resultIt = scal * *vIt; + + return result; + } + + /// vector + scalar + template<typename T> + inline const Vector<T>& add(const Vector<T>& v, const T& scal, Vector<T>& result) + { + TEST_EXIT_DBG(v.getSize() == result.getSize())("invalid size\n"); + T *vIt, *resultIt; + for (vIt = v.begin(), resultIt = result.begin(); + vIt != v.end(); + ++vIt, ++resultIt) + *resultIt = *vIt + scal; + + return result; + } + + /// y = a * x + y. + template<typename T, typename S> + inline const Vector<T>& axpy(const S& a, + const Vector<T> &x, + Vector<T> &y) + { + TEST_EXIT_DBG(x.getSize() == y.getSize())("invalid size\n"); + T *xIt, *yIt; + for (xIt = x.begin(), yIt = y.begin(); + xIt != x.end(); + ++xIt, ++yIt) + *yIt += a * *xIt; + + return y; + } + + // times / divides + // --------------- + + /// Matrix vector multiplication: vector := matrix * vector + template<typename T> + inline const Vector<T>& operator*=(const Vector<T>& v, const Matrix<T>& m) + { + return mv(m, v, v); + } + + /// Matrix vector multiplication: vector := matrix * vector + template<typename T> + inline Vector<T> operator*(const Matrix<T>& m, const Vector<T>& v) + { + Vector<T> result(m.getNumCols()); + return mv(m, v, result); + } + + /// Scalar product: scalar := vector * vector + template<typename T, typename S> + inline typename traits::mult_type<T,S>::type + operator*(const Vector<T>& v1, const Vector<S>& v2) + { + typename traits::mult_type<T,S>::type result; + nullify(result); + + T *v1It; + S *v2It; + for (v1It = v1.begin(), v2It = v2.begin(); + v1It != v1.end(); + ++v1It, ++v2It) + result += *v1It * *v2It; + + return result; + } + + /// vector *= scalar (elementwise) + template <typename T, typename S> + Vector<T>& operator*=(Vector<T>& v, S scal) + { + T *vIt; + for (vIt = v.begin(); vIt != v.end(); ++vIt) + *vIt *= scal; + return v; + } + + /// vector := vector * scalar (elementwise) + template <typename T, typename S> + Vector<typename traits::mult_type<T, S>::type> + operator*(Vector<T> const& v, S scal) + { + Vector<typename traits::mult_type<T, S>::type> result = v; + result *= scal; + return result; + } + + /// vector /= scalar (elementwise) + template <typename T, typename S> + Vector<T>& operator/=(Vector<T>& v, S scal) + { + T *vIt; + for (vIt = v.begin(); vIt != v.end(); ++vIt) + *vIt /= scal; + return v; + } + + /// vector := vector / scalar (elementwise) + template <typename T, typename S> + Vector<typename traits::mult_type<T, S>::type> + operator/(Vector<T> const& v, S scal) + { + Vector<typename traits::mult_type<T, S>::type> result = v; + result /= scal; + return result; + } + + // plus / minus + // ------------ + + /// vector += scalar + template <typename T, typename S> + typename boost::enable_if<typename traits::is_scalar<S>::type, + Vector<T> >::type& + operator+=(Vector<T>& x, S scal) + { + T *xIt; + for (xIt = x.begin(); xIt != x.end(); ++xIt) + *xIt += scal; + return x; + } + + /// vector := vector + scalar + template <typename T, typename S> + typename boost::enable_if<typename traits::is_scalar<S>::type, + Vector<T> >::type + operator+(Vector<T> result, T scal) + { + result += scal; + return result; + } + + /// vector += vector + template <typename T, typename S> + Vector<T>& operator+=(Vector<T>& x, const Vector<S>& y) + { + T *xIt; + S *yIt; + for (xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt) + *xIt += *yIt; + return x; + } + + /// vector := vector + vector + template <typename T, typename S> + Vector<T> operator+(Vector<T> result, const Vector<S>& v2) + { + result += v2; + return result; + } + + /// vector -= vector + template <typename T, typename S> + Vector<T>& operator-=(Vector<T>& x, const Vector<S>& y) + { + T *xIt; + S *yIt; + for (xIt = x.begin(), yIt = y.begin(); xIt != x.end(); ++xIt, ++yIt) + *xIt -= *yIt; + return x; + } + + /// vector := vector - vector + template <typename T, typename S> + Vector<T> operator-(Vector<T> result, const Vector<S>& v2) + { + result -= v2; + return result; + } + + // special operators + // ----------------- + + /// 2-norm of a vector + template<typename T> + inline T norm(const Vector<T> *v) + { + T result; nullify(result); + for (T* vIt = v->begin(); vIt != v->end(); ++vIt) + result += *vIt * *vIt; + return std::sqrt(result); + } + + /// 2-norm of a vector + template<typename T> + inline T norm(const Vector<T>& v) + { + return norm(&v); + } + + /// cross-product of two vectors: vector := vector x vector (only in 3d) + template<typename T> + void vectorProduct(const Vector<T>& x, + const Vector<T>& y, + Vector<T>& z) + { + FUNCNAME_DBG("vectorProduct()"); + TEST_EXIT_DBG(Global::getGeo(WORLD) == 3)("DIM_OF_WORLD != 3\n"); + z[0] = x[1] * y[2] - x[2] * y[1]; + z[1] = x[2] * y[0] - x[0] * y[2]; + z[2] = x[0] * y[1] - x[1] * y[0]; + } + + // --------------------------------------------------------------------------- + // Operations with WorldVector and WorldMatrix + + // times / divides + // --------------- + + /// Scalar product: scalar := vector * vector + template<typename T, typename S> + inline typename traits::mult_type<T,S>::type + operator*(const WorldVector<T>& v1, const WorldVector<S>& v2) + { + typename traits::mult_type<T,S>::type result; + nullify(result); + + T *v1It; + S *v2It; + for (v1It = v1.begin(), v2It = v2.begin(); + v1It != v1.end(); + ++v1It, ++v2It) + result += *v1It * *v2It; + + return result; + } + + /// vector := vector * scalar (elementwise) + template<typename T, typename S> + WorldVector<T> + operator*(WorldVector<T> const& v, S scal) + { + WorldVector<T> result = v; + result *= scal; // calls operator*=(Vector<T>, S) + return result; + } + + /// vector := scalar * vector (elementwise) + template<typename T, typename S> + WorldVector<T> + operator*(S scal, WorldVector<T> const& v) + { + WorldVector<T> result = v; + result *= scal; // calls operator*=(Vector<T>, S) + return result; + } + + /// vector := vector / scalar (elementwise) + template<typename T, typename S> + WorldVector<T> + operator/(WorldVector<T> const& v, S scal) + { + WorldVector<T> result = v; + result /= scal; // calls operator/=(Vector<T>, S) + return result; + } + + /// matrix *= scalar (elementwise) +// template<typename T> +// WorldMatrix<T>& operator*=(WorldMatrix<T>& m, T scal) +// { +// for (T* mIt = m.begin(); mIt != m.end(); mIt++) +// *mIt *= scal; +// +// return m; +// } + + /// matrix := matrix * scalar (elementwise) + template <typename T, typename S> + WorldMatrix<T> + operator*(WorldMatrix<T> const& m, S scal) + { + WorldMatrix<T> result = m; + result *= scal; // calls operator*=(Vector<T>, S) + return result; + } + + /// matrix := scalar * matrix (elementwise) + template <typename T, typename S> + WorldMatrix<T> + operator*(S scal, WorldMatrix<T> const& m) + { + WorldMatrix<T> result = m; + result *= scal; // calls operator*=(Vector<T>, S) + return result; + } + + /// matrix := matrix / scalar (elementwise) + template <typename T, typename S> + WorldMatrix<T> + operator/(WorldMatrix<T> const& m, S scal) + { + WorldMatrix<T> result = m; + result /= scal; // calls operator/=(Vector<T>, S) + return result; + } + + /// vector := matrix * vector + template<typename T> + WorldVector<T> operator*(const WorldMatrix<T>& M, const WorldVector<T>& v ) + { + WorldVector<T> res; + res.multMatrixVec(M,v); + return res; + } + + /// matrix := matrix * matrix + template<typename T> + WorldVector<WorldVector<T> > + operator*(const WorldVector<WorldVector<T> >& A, const WorldVector<WorldVector<T> >& B) + { + WorldVector<WorldVector<T> > result; + nullify(result); + for (size_t r = 0; r < num_rows(A); r++) + for (size_t c = 0; c < num_cols(A); c++) + for (size_t i = 0; i < num_cols(A); i++) + result[r][c] += A[r][i] * B[i][c]; + return result; + } + + // plus / minus + // ------------ + +// NOTE: call operators of Vector<T> directly +#if 0 + template<typename T> + WorldVector<T>& operator+=(WorldVector<T>& v1, + const WorldVector<T>& v2) + { + add(v1, v2, v1); + return v1; + } + + template<typename T> + WorldVector<T>& operator-=(WorldVector<T>& v1, + const WorldVector<T>& v2) + { + axpy(-1.0, v2, v1); + return v1; + } +#endif + + /// vector := vector + vector + template <typename T, typename S> + WorldVector<T>& + operator+=(WorldVector<T>& v1, WorldVector<S> const& v2) + { + static_cast<Vector<T>&>(v1) += static_cast<Vector<S> const&>(v2); + return v1; + } + + /// vector := vector + vector + template <typename T, typename S> + WorldVector<typename traits::add_type<T, S>::type> + operator+(WorldVector<T> result, const WorldVector<S>& v2) + { + result += v2; // calls operator+=(Vector<T>, Vector<T>) + return result; + } + + /// vector := vector - vector + template <typename T, typename S> + WorldVector<typename traits::add_type<T, S>::type> + operator-(WorldVector<T> result, const WorldVector<S>& v2) + { + result -= v2; // calls operator-=(Vector<T>, Vector<T>) + return result; + } + + /// matrix += matrix + template <typename T, typename S> + WorldMatrix<T>& operator+=(WorldMatrix<T>& m1, const WorldMatrix<S>& m2) + { + T* m1It; + S* m2It; + for (m1It = m1.begin(), m2It = m2.begin(); + m1It != m1.end(); + m1It++, m2It++) + *m1It += *m2It; + + return m1; + } + + /// matrix := matrix + matrix + template <typename T, typename S> + WorldMatrix<T> operator+(WorldMatrix<T> M1, const WorldMatrix<S>& M2 ) + { + M1 += M2; + return M1; + } + + /// matrix -= matrix + template <typename T, typename S> + WorldMatrix<T>& operator-=(WorldMatrix<T>& m1, const WorldMatrix<S>& m2) + { + T *m1It; + S *m2It; + for (m1It = m1.begin(), m2It = m2.begin(); + m1It != m1.end(); + m1It++, m2It++) + *m1It -= *m2It; + + return m1; + } + + /// matrix := matrix - matrix + template <typename T, typename S> + WorldMatrix<T> operator-(WorldMatrix<T> M1, const WorldMatrix<S>& M2 ) + { + M1 -= M2; + return M1; + } + + // unary minus operators + // --------------------- + + /// vector := -vector (elementwise) + template<typename T> + WorldVector<T> operator-(WorldVector<T> v) + { + v *= -1.0; + return v; + } + + /// matrix := -matrix (elementwise) + template<typename T> + WorldMatrix<T> operator-(WorldMatrix<T> v) + { + v *= -1.0; + return v; + } + + // comparison operators + // -------------------- + + /// test for less-then (elementwise) up to DBL_TOL + inline bool operator<(const WorldVector<double>& v1, const WorldVector<double>& v2) + { + int dow = Global::getGeo(WORLD); + for (int i = 0; i < dow; i++) { + if (std::abs(v1[i] - v2[i]) < DBL_TOL) + continue; + return v1[i] < v2[i]; + } + return false; + } + + /// test for equality (elementwise) up to DBL_TOL + inline bool operator==(const WorldVector<double>& v1, const WorldVector<double>& v2) + { + int dow = Global::getGeo(WORLD); + for (int i = 0; i < dow; i++) + if (std::abs(v1[i] - v2[i]) > DBL_TOL) + return false; + + return true; + } + + // special operators + // ----------------- + + /// wrapper for nullify + template<typename T> + void set_to_zero(WorldVector<WorldVector<T> >& mat) + { + nullify(mat); + } + +// NOTE: call norm(Vector<T>) directly +#if 0 + inline double norm(const WorldVector<double>& v) + { + double val = 0.0; + for (int i = 0; i < Global::getGeo(WORLD); i++) + val += v[i] * v[i]; + return sqrt(val); + } +#endif + + /// returns the euclidian distance of a and b + template<typename T, GeoIndex d> + double absteukl(const FixVec<T,d>& a,const FixVec<T,d>& b) + { + double erg = 0.0; + for (int i = 0; i < a.getSize(); ++i) + erg += sqr(a[i] - b[i]); + + return std::sqrt(erg); + } + +} // end namespace AMDiS + +#endif // AMDIS_MATVEC_OPERATIONS_H + diff --git a/AMDiS/src/ProblemInstat.cc b/AMDiS/src/ProblemInstat.cc index de493c6ea83cb172a5647d02964403254a58b1de..6a99b7e4d88cd74e3e1822a33d78d755c0debb27 100644 --- a/AMDiS/src/ProblemInstat.cc +++ b/AMDiS/src/ProblemInstat.cc @@ -139,7 +139,7 @@ namespace AMDiS { oldSolution = new SystemVector("old solution", problemStat->getFeSpaces(), size); for (int i = 0; i < size; i++) { oldSolution->setDOFVector(i, new DOFVector<double>(problemStat->getFeSpace(i), - name + "_uOld")); + name + "_uOld", true)); oldSolution->getDOFVector(i)->setCoarsenOperation(COARSE_INTERPOL); if (problemStat->getEstimator(i)) diff --git a/AMDiS/src/SecondOrderTerm.h b/AMDiS/src/SecondOrderTerm.h index b8dfb1b7700bd3614bc35f8e5af8543f9072f62e..ef52a0c87c14996ff8a64e5a250693a96abeadcf 100644 --- a/AMDiS/src/SecondOrderTerm.h +++ b/AMDiS/src/SecondOrderTerm.h @@ -29,6 +29,7 @@ #include "OperatorTerm.h" #include "ElInfo.h" #include "AbstractFunction.h" +#include "MatrixVectorOperations.h" namespace AMDiS { diff --git a/AMDiS/src/SubAssembler.cc b/AMDiS/src/SubAssembler.cc index 59b68ce2fe3645afa9b14b6dd415988f30797be1..65d66542d82ab44bdbafacaa3ac96b85ff598d2b 100644 --- a/AMDiS/src/SubAssembler.cc +++ b/AMDiS/src/SubAssembler.cc @@ -135,7 +135,7 @@ namespace AMDiS { // calls initElement of each term for (vector<OperatorTerm*>::iterator it = terms.begin(); it != terms.end(); ++it) { - if (largeElInfo == NULL) + if (largeElInfo == NULL || smallElInfo == largeElInfo) (*it)->initElement(smallElInfo, this, quad); else (*it)->initElement(smallElInfo, largeElInfo, this, quad); diff --git a/AMDiS/src/TransformDOF.h b/AMDiS/src/TransformDOF.h index 0764e21179633f543c0a3862e150f078b90bc538..18822002970f9c7212913d1eba3f985c51aa928d 100644 --- a/AMDiS/src/TransformDOF.h +++ b/AMDiS/src/TransformDOF.h @@ -736,13 +736,13 @@ template<typename T> inline void transformDOFInterpolation( // ==================================================================================== -template<typename T> -T accumulateDOF_simple(DOFVector<T> *vec, - T value0, - BinaryAbstractFunction<T, T, T> *binary_op) +template<typename S, typename T> +S accumulateDOF_simple(DOFVector<T> *vec, + S value0, + BinaryAbstractFunction<S, S, T> *binary_op) { DOFIterator<T> vecIter(vec, USED_DOFS); - T value = value0; + S value = value0; for(vecIter.reset(); !vecIter.end(); ++vecIter) { value = (*binary_op)(value, *vecIter); diff --git a/AMDiS/src/ZeroOrderTerm.h b/AMDiS/src/ZeroOrderTerm.h index 5c0dc44632e62ab1030972839218b6c835a84bbf..549a2efe43d17bc33d99d34191e6786881684881 100644 --- a/AMDiS/src/ZeroOrderTerm.h +++ b/AMDiS/src/ZeroOrderTerm.h @@ -28,6 +28,7 @@ #include "AMDiS_fwd.h" #include "OperatorTerm.h" #include "AbstractFunction.h" +#include "MatrixVectorOperations.h" namespace AMDiS { diff --git a/AMDiS/src/config/Config_clang.h b/AMDiS/src/config/Config_clang.h new file mode 100644 index 0000000000000000000000000000000000000000..1daa7f50061a6d7dd48a77e87d3f95d67010cefd --- /dev/null +++ b/AMDiS/src/config/Config_clang.h @@ -0,0 +1,60 @@ +#pragma once + +#define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#define COMPILER_VERSION "Clang: CLANG_VERSION" + +// alignement specification +// ------------------------ +#define ALIGNED(type,name,N) type name[N] __attribute__ ((aligned(CACHE_LINE))) +typedef double aligned_double __attribute__ ((aligned(CACHE_LINE))); +typedef float aligned_float __attribute__ ((aligned(CACHE_LINE))); +typedef int aligned_int __attribute__ ((aligned(CACHE_LINE))); +typedef size_t aligned_size_t __attribute__ ((aligned(CACHE_LINE))); + +// some compiler attributes +// ------------------------ +#define NOINLINE __attribute__ ((noinline)) +#define ALWAYS_INLINE __attribute__ ((always_inline)) +#define OPENMODE std::ios::openmode + +// C++11 features +// -------------- +#if __cplusplus > 199711L + +#if CLANG_VERSION >= 20900 + #define HAS_VARIADIC_TEMPLATES 1 +#endif + +#if CLANG_VERSION >= 30000 + #define HAS_ALIAS_TEMPLATES 1 +#endif + +#if CLANG_VERSION >= 20900 + #define HAS_DECLTYPE 1 +#endif + +#if CLANG_VERSION >= 30100 + #define HAS_CONSTEXPR 1 +#endif + +#if CLANG_VERSION >= 30000 + #define HAS_DELEGATING_CONSTRUCTORS 1 +#endif + +#if CLANG_VERSION >= 30000 + #define HAS_RANGE_BASED_FOR 1 +#endif + +#if CLANG_VERSION >= 30100 + #define HAS_INITIALIZER_LISTS 1 +#endif + +#if CLANG_VERSION >= 30000 + #define HAS_OVERRIDE 1 +#endif + +#if CLANG_VERSION >= 20900 + #define HAS_TYPED_ENUMS 1 +#endif + +#endif \ No newline at end of file diff --git a/AMDiS/src/config/Config_defaults.h b/AMDiS/src/config/Config_defaults.h new file mode 100644 index 0000000000000000000000000000000000000000..8341f43ad54b872b71b7826b56e1b4886b235a7b --- /dev/null +++ b/AMDiS/src/config/Config_defaults.h @@ -0,0 +1,69 @@ +#pragma once + +#ifndef COMPILER_NAME + #define COMPILER_NAME "Unknown" +#endif +#ifndef COMPILER_VERSION + #define COMPILER_VERSION 0 +#endif + +// alignement specification +// ------------------------ +#ifndef ALIGNED +#define ALIGNED(type,name,N) type name[N] +typedef double aligned_double; +typedef float aligned_float; +typedef int aligned_int; +typedef size_t aligned_size_t; +#endif + +// some compiler attributes +// ------------------------ +#ifndef NOINLINE + #define NOINLINE +#endif +#ifndef ALWAYS_INLINE + #define ALWAYS_INLINE +#endif +#ifndef OPENMODE + #define OPENMODE std::ios::openmode +#endif + +// C++11 features +// -------------- +#ifndef HAS_VARIADIC_TEMPLATES + #define HAS_VARIADIC_TEMPLATES 0 +#endif + +#ifndef HAS_ALIAS_TEMPLATES + #define HAS_ALIAS_TEMPLATES 0 +#endif + +#ifndef HAS_DECLTYPE + #define HAS_DECLTYPE 0 +#endif + +#ifndef HAS_CONSTEXPR + #define HAS_CONSTEXPR 0 +#endif + +#ifndef HAS_DELEGATING_CONSTRUCTORS + #define HAS_DELEGATING_CONSTRUCTORS 0 +#endif + +#ifndef HAS_RANGE_BASED_FOR + #define HAS_RANGE_BASED_FOR 0 +#endif + +#ifndef HAS_INITIALIZER_LISTS + #define HAS_INITIALIZER_LISTS 0 +#endif + +#ifndef HAS_OVERRIDE + #define HAS_OVERRIDE 0 + #define override +#endif + +#ifndef HAS_TYPED_ENUMS + #define HAS_TYPED_ENUMS 0 +#endif \ No newline at end of file diff --git a/AMDiS/src/config/Config_gcc.h b/AMDiS/src/config/Config_gcc.h new file mode 100644 index 0000000000000000000000000000000000000000..2247ed3beb5ba1dcad252e7558fc700bd5908539 --- /dev/null +++ b/AMDiS/src/config/Config_gcc.h @@ -0,0 +1,62 @@ +#pragma once + +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) + +#define COMPIER_NAME "gcc" +#define COMPILER_VERSION GCC_VERSION + +// alignement specification +// ------------------------ +#define ALIGNED(type,name,N) type name[N] __attribute__ ((aligned(CACHE_LINE))) +typedef double aligned_double __attribute__ ((aligned(CACHE_LINE))); +typedef float aligned_float __attribute__ ((aligned(CACHE_LINE))); +typedef int aligned_int __attribute__ ((aligned(CACHE_LINE))); +typedef size_t aligned_size_t __attribute__ ((aligned(CACHE_LINE))); + +// some compiler attributes +// ------------------------ +#define NOINLINE __attribute__ ((noinline)) +#define ALWAYS_INLINE __attribute__ ((always_inline)) +#define OPENMODE std::ios::openmode + +// C++11 features +// -------------- +#if __cplusplus > 199711L + +#if GCC_VERSION >= 40300 + #define HAS_VARIADIC_TEMPLATES 1 +#endif + +#if GCC_VERSION >= 40700 + #define HAS_ALIAS_TEMPLATES 1 +#endif + +#if __cpp_decltype >= 200707 + #define HAS_DECLTYPE 1 +#endif + +#if GCC_VERSION >= 40600 + #define HAS_CONSTEXPR 1 +#endif + +#if GCC_VERSION >= 40700 + #define HAS_DELEGATING_CONSTRUCTORS 1 +#endif + +#if GCC_VERSION >= 40600 + #define HAS_RANGE_BASED_FOR 1 +#endif + +#if GCC_VERSION >= 40400 + #define HAS_INITIALIZER_LISTS 1 +#endif + +#if GCC_VERSION >= 40700 + #define HAS_OVERRIDE 1 +#endif + +#if GCC_VERSION >= 40400 + #define HAS_TYPED_ENUMS 1 +#endif + +#endif \ No newline at end of file diff --git a/AMDiS/src/config/Config_intel.h b/AMDiS/src/config/Config_intel.h new file mode 100644 index 0000000000000000000000000000000000000000..4053bcb9017953ae8d048565c916221c3ff1e533 --- /dev/null +++ b/AMDiS/src/config/Config_intel.h @@ -0,0 +1,63 @@ +#pragma once + +// MMmm (M...major, m...minor) +#define INTEL_VERSION __INTEL_COMPILER + +#define COMPIER_NAME "icc" +#define COMPILER_VERSION INTEL_VERSION + +// alignement specification +// ------------------------ +#define ALIGNED(type,name,N) __declspec(align(CACHE_LINE)) type name[N] +typedef __declspec(align(CACHE_LINE)) double aligned_double; +typedef __declspec(align(CACHE_LINE)) float aligned_float; +typedef __declspec(align(CACHE_LINE)) int aligned_int; +typedef __declspec(align(CACHE_LINE)) size_t aligned_size_t; + +// some compiler attributes +// ------------------------ +#define NOINLINE +#define ALWAYS_INLINE +#define OPENMODE std::ios::openmode + +// C++11 features +// -------------- +#if __cplusplus > 199711L + +#if INTEL_VERSION >= 1201 + #define HAS_VARIADIC_TEMPLATES 1 +#endif + +#if INTEL_VERSION >= 1201 + #define HAS_ALIAS_TEMPLATES 1 +#endif + +#if INTEL_VERSION >= 1200 + #define HAS_DECLTYPE 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_CONSTEXPR 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_DELEGATING_CONSTRUCTORS 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_RANGE_BASED_FOR 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_INITIALIZER_LISTS 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_OVERRIDE 1 +#endif + +#if INTEL_VERSION >= 1400 + #define HAS_TYPED_ENUMS 1 +#endif + +#endif \ No newline at end of file diff --git a/AMDiS/src/config/Config_msc.h b/AMDiS/src/config/Config_msc.h new file mode 100644 index 0000000000000000000000000000000000000000..14edbf107821a100d63fd6e16ff39e153d776c00 --- /dev/null +++ b/AMDiS/src/config/Config_msc.h @@ -0,0 +1,66 @@ +#pragma once + +#define MSC_VERSION _MSV_VER +// MSC_VERSION == 1800 (Visual Studio 2013) +// MSC_VERSION == 1700 (Visual Studio 2012) +// MSC_VERSION == 1600 (Visual Studio 2010) +// MSC_VERSION == 1500 (Visual Studio 2008) + +#define COMPIER_NAME "msc" +#define COMPILER_VERSION MSC_VERSION + +// alignement specification +// ------------------------ +#define ALIGNED(type,name,N) __declspec(align(CACHE_LINE)) type name[N] +typedef __declspec(align(CACHE_LINE)) double aligned_double; +typedef __declspec(align(CACHE_LINE)) float aligned_float; +typedef __declspec(align(CACHE_LINE)) int aligned_int; +typedef __declspec(align(CACHE_LINE)) size_t aligned_size_t; + +// some compiler attributes +// ------------------------ +#define NOINLINE __declspec(noinline) +#define ALWAYS_INLINE __forceinline +#define OPENMODE std::ios::open_mode + +// C++11 features +// -------------- +#if __cplusplus > 199711L + +#if MSC_VERSION >= 1800 + #define HAS_VARIADIC_TEMPLATES 1 +#endif + +#if MSC_VERSION >= 1800 + #define HAS_ALIAS_TEMPLATES 1 +#endif + +#if MSC_VERSION >= 1600 + #define HAS_DECLTYPE 1 +#endif + +// #if MSC_VERSION >= 2000 (?) +#define HAS_CONSTEXPR 0 +// #endif + +#if MSC_VERSION >= 1800 + #define HAS_DELEGATING_CONSTRUCTORS 1 +#endif + +#if MSC_VERSION >= 1700 + #define HAS_RANGE_BASED_FOR 1 +#endif + +#if MSC_VERSION >= 1800 + #define HAS_INITIALIZER_LISTS 1 +#endif + +#if MSC_VERSION >= 1700 + #define HAS_OVERRIDE 1 +#endif + +#if MSC_VERSION >= 1700 + #define HAS_TYPED_ENUMS 1 +#endif + +#endif \ No newline at end of file diff --git a/AMDiS/src/config/Config_pgi.h b/AMDiS/src/config/Config_pgi.h new file mode 100644 index 0000000000000000000000000000000000000000..377a985072d75cb9aa8cf824d528dd688ec00751 --- /dev/null +++ b/AMDiS/src/config/Config_pgi.h @@ -0,0 +1,6 @@ +#pragma once + +#define PGI_VERSION (__PGIC__ * 10000 + __PGIC_MINOR * 100 + __PGIC_PATCHLEVEL__) + +#define COMPIER_NAME "pgi" +#define COMPILER_VERSION PGI_VERSION \ No newline at end of file diff --git a/AMDiS/src/expressions/add_expr.hpp b/AMDiS/src/expressions/add_expr.hpp index 085427ec575c2528fe25486b8057798d42f41042..c98554b317df95d4d02b3bf0a8f96098773ea40f 100644 --- a/AMDiS/src/expressions/add_expr.hpp +++ b/AMDiS/src/expressions/add_expr.hpp @@ -60,6 +60,32 @@ namespace AMDiS std::string str() const { return std::string("(") + super::term1.str() + " + " + super::term2.str() + ")"; } }; + /// Expression that represents "E1 - E2" + template<typename Term1, typename Term2> + struct Subtract : public LazyOperatorTerm2<Term1, Term2> + { + typedef LazyOperatorTerm2<Term1, Term2> super; + typedef typename traits::add_type + < + typename Term1::value_type, + typename Term2::value_type + >::type value_type; + + BOOST_STATIC_ASSERT_MSG( !(boost::is_same<value_type, traits::no_valid_type>::value), "********** ERROR: Can not subtract terms **********" ); + + Subtract(const Term1& term1_, const Term2& term2_) + : super(term1_, term2_) {} + + int getDegree() const + { + return std::max(super::term1.getDegree(), super::term2.getDegree()); + } + + inline value_type operator()(const int& iq) const { return super::term1(iq) - super::term2(iq); } + + std::string str() const { return std::string("(") + super::term1.str() + " - " + super::term2.str() + ")"; } + }; + /// Expression that represents "-E" template<typename Term> struct Negative : public LazyOperatorTerm1<Term> @@ -107,24 +133,15 @@ namespace AMDiS > > {}; - template<typename Term1, typename Term2> struct Subtract : boost::enable_if < typename traits::is_valid_arg2<Term1, Term2>::type, - typename boost::mpl::if_< - typename traits::is_constant<Term2>::type, - expressions::Add - < - typename traits::to_expr<Term1>::type, - typename traits::to_expr<Term2>::type - >, - expressions::Add - < - typename traits::to_expr<Term1>::type, - expressions::Negative< typename traits::to_expr<Term2>::type > - > - >::type + expressions::Subtract + < + typename traits::to_expr<Term1>::type, + typename traits::to_expr<Term2>::type + > > {}; } @@ -159,7 +176,10 @@ namespace AMDiS inline typename result_of::Subtract<Term1, Term2>::type operator-(const Term1& t1, const Term2& t2) { - return t1 + (-t2); + typedef typename traits::to_expr<Term1>::to Expr1; + typedef typename traits::to_expr<Term2>::to Expr2; + return expressions::Subtract< typename Expr1::type, typename Expr2::type > + (Expr1::get(t1), Expr2::get(t2)); } } // end namespace AMDiS diff --git a/AMDiS/src/expressions/valueOf.hpp b/AMDiS/src/expressions/valueOf.hpp index 5b7536192ed16e771cc3b602beeb710523a00ed8..ef4ed4e1a8d79cf15e8422c4efadc53c11ae9748 100644 --- a/AMDiS/src/expressions/valueOf.hpp +++ b/AMDiS/src/expressions/valueOf.hpp @@ -128,7 +128,7 @@ namespace AMDiS /// Expressions that extracts the matrix-value of a Matrix<DOFVector> at QPs template<template<class> class Matrix, typename T, typename Name> struct ValueOf<Matrix<DOFVector<T>*>, Name, - typename boost::enable_if<typename traits::is_matrix<Matrix<T> >::type>::type > + typename enable_if< traits::is_matrix<Matrix<T> > >::type > : public LazyOperatorTermBase { typedef Matrix<T> value_type; @@ -138,7 +138,7 @@ namespace AMDiS mutable mtl::dense_vector<value_type> vec; mutable Matrix<mtl::dense_vector<T> > coeff; - ValueOf(Matrix<DOFVector<T>*>& vector) : vecDV(vector) + ValueOf(Matrix<DOFVector<T>*> const& vector) : vecDV(vector) { resize(coeff, num_rows(vecDV), num_cols(vecDV)); } diff --git a/AMDiS/src/expressions/value_expr.hpp b/AMDiS/src/expressions/value_expr.hpp index f7c80e86ae6f80f8f9eb70fd1f1eed1afdb1728e..4f6de8bde3379e157904b2af5158712bff4843f4 100644 --- a/AMDiS/src/expressions/value_expr.hpp +++ b/AMDiS/src/expressions/value_expr.hpp @@ -62,23 +62,10 @@ namespace AMDiS { typedef Vector<int> value_type; value_type V; - - template<typename OT> - void initElement(OT* ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad, - const BasisFunction *basisFct = NULL) - { - V.resize(Size); - int values[Size] = {V0, V1, V2}; - V.setValues(&values); - } - - template<typename OT> - void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad, - const BasisFunction *basisFct = NULL) - { - initElement(ot, smallElInfo, subAssembler, quad, basisFct); + + CVector() : V(Size) { + int values[3] = {V0, V1, V2}; + V.setValues(values); } inline value_type operator()(const int& iq) const { return V; } @@ -87,6 +74,45 @@ namespace AMDiS }; + /// Expression that encapsulates a compiletime vector + template<int V0 = 0, int V1 = 0, int V2 = 0> + struct WVector : public LazyOperatorTermBase + { + typedef WorldVector<int> value_type; + value_type V; + + WVector() { + V[0] = V0; + if (size(V) > 1) V[1] = V1; + if (size(V) > 2) V[2] = V2; + } + + inline value_type operator()(const int& iq) const { return V; } + + std::string str() const { return std::string("[V(") + boost::lexical_cast<std::string>(size(V)) + ")]"; } + }; + + template<int I = -1> + struct E : public LazyOperatorTermBase + { + typedef WorldVector<int> value_type; + value_type V; + + E(int I_ = -1) { + assert((I >= 0 && I_ < 0) || (I < 0 && I_ >= 0)); + V = 0; V[std::max(I, I_)] = 1; + } + + inline value_type operator()(const int& iq) const { return V; } + + std::string str() const { return std::string("[V(") + boost::lexical_cast<std::string>(size(V)) + ")]"; } + }; + + template<> struct E<0> : WVector<1> {}; + template<> struct E<1> : WVector<0,1> {}; + template<> struct E<2> : WVector<0,0,1> {}; + + /// Expression that encapsulates a compiletime matrix template<int Rows, int Cols, int V0 = 0, int V1 = 0, int V2 = 0, int V3 = 0, int V4 = 0, int V5 = 0, @@ -94,31 +120,86 @@ namespace AMDiS struct CMatrix : public LazyOperatorTermBase { typedef Matrix<int> value_type; - value_type V; - - template<typename OT> - void initElement(OT* ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad, - const BasisFunction *basisFct = NULL) - { - V.resize(Rows, Cols); - int values[Rows*Cols] = {V0, V1, V2, V3, V4, V5, V6, V7, V8}; - V.setValues(&values); - } - - template<typename OT> - void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad, - const BasisFunction *basisFct = NULL) - { - initElement(ot, smallElInfo, subAssembler, quad, basisFct); + value_type M; + + CMatrix() : M(Rows, Cols) { + int values[9] = {V0, V1, V2, V3, V4, V5, V6, V7, V8}; + M.setValues(values); } - inline value_type operator()(const int& iq) const { return V; } + inline value_type operator()(const int& iq) const { return M; } std::string str() const { return std::string("[M(") + boost::lexical_cast<std::string>(Rows) + ","+ boost::lexical_cast<std::string>(Cols) + ")]"; } }; + + /// Expression that encapsulates a compiletime matrix + template<int V0 = 0, int V1 = 0, int V2 = 0, + int V3 = 0, int V4 = 0, int V5 = 0, + int V6 = 0, int V7 = 0, int V8 = 0> + struct WMatrix : public LazyOperatorTermBase + { + typedef WorldMatrix<int> value_type; + value_type M; + + WMatrix() { + M[0][0] = V0; + if (Global::getGeo(WORLD) == 2) { + M[0][1] = V1; + M[1][0] = V2; M[1][1] = V3; + } else if (Global::getGeo(WORLD) == 3) { + M[0][1] = V1; M[0][2] = V2; + M[1][0] = V3; M[1][1] = V4; M[1][2] = V5; + M[2][0] = V6; M[2][1] = V7; M[2][2] = V8; + } + } + + inline value_type operator()(const int& iq) const { return M; } + + std::string str() const { return std::string("[M(") + boost::lexical_cast<std::string>(Global::getGeo(WORLD)) + ","+ boost::lexical_cast<std::string>(Global::getGeo(WORLD)) + ")]"; } + }; + + + template<int N = -1> + struct Eye : public LazyOperatorTermBase + { + typedef Matrix<int> value_type; + value_type M; + size_t n; + + Eye(int n) : M(n,n) { + assert((N >= 0 && n < 0) || (N < 0 && n >= 0)); + M = 0; + for (size_t i = 0; i < n; ++i) + M[i][i] = 1; + } + + inline value_type operator()(const int& iq) const { return M; } + + std::string str() const { return std::string("[M(") + boost::lexical_cast<std::string>(n) + ","+ boost::lexical_cast<std::string>(n) + ")]"; } + }; + + template<> + struct Eye<-2> : public LazyOperatorTermBase + { + typedef WorldMatrix<int> value_type; + value_type M; + + Eye() { + M = 0; + for (size_t i = 0; i < Global::getGeo(WORLD); ++i) + M[i][i] = 1; + } + + inline value_type operator()(const int& iq) const { return M; } + + std::string str() const { return std::string("[M(") + boost::lexical_cast<std::string>(Global::getGeo(WORLD)) + ","+ boost::lexical_cast<std::string>(Global::getGeo(WORLD)) + ")]"; } + }; + + template<> struct Eye<1> : CMatrix<1,1, 1> {}; + template<> struct Eye<2> : CMatrix<2,2, 1,0, 0,1> {}; + template<> struct Eye<3> : CMatrix<3,3, 1,0,0, 0,1,0, 0,0,1> {}; + } // end namespace expressions @@ -212,6 +293,27 @@ namespace AMDiS template<typename T> inline expressions::Reference<T> ref_(T* value) { return expressions::Reference<T>(value); } + + // unit vectors + template<int I> + inline expressions::E<I> E() + { return expressions::E<I>(); } + + inline expressions::E<-1> E(int i) + { return expressions::E<-1>(i); } + + // unit matrix + template<int N> + inline expressions::Eye<N> eye() + { return expressions::Eye<N>(); } // NxN unit-matrix + + inline expressions::Eye<-1> eye(int n) + { return expressions::Eye<-1>(n); } // nxn unit-matrix + + inline expressions::Eye<-2> eye() + { return expressions::Eye<-2>(); } // dow x dow unit-matrix + + } // end namespace AMDiS #endif // AMDIS_VALUE_EXPR_HPP diff --git a/AMDiS/src/expressions/vec_functors.hpp b/AMDiS/src/expressions/vec_functors.hpp index 83d22d9b22553b01153a624b053e3a4f28d7625c..d67d870bc5e234c8adc2b5c8eb681bcdfe70f5e8 100644 --- a/AMDiS/src/expressions/vec_functors.hpp +++ b/AMDiS/src/expressions/vec_functors.hpp @@ -29,6 +29,18 @@ #include "operations/norm.hpp" #include "operations/product.hpp" +/** + * This file provides expressions for vectors and matrices: + * (where v_expr is an expression of vector type, and m_expr an + * expression of matrix type) + * + * two_norm(v_expr) ... the 2-norm of a vector v: result = sqrt(v^H * v) + * one_norm(v_expr) ... the 1-norm of a vector v: result = sum_i(abs(v_i)) + * one_norm(m_expr) ... the 1-norm of a matrix m: result = max_j(sum_i(abs(m_ij)) + * p_norm<P>(v_expr) .. the P-norm of a vector v: result = [sum_i(abs(v_i)^P)]^(1/P) + * + **/ + namespace AMDiS { namespace traits @@ -173,7 +185,7 @@ namespace AMDiS struct one_norm<T, tag::expression> : result_of::UnaryExpr<functors::OneNorm, T, traits::is_vector, traits::is_matrix> {}; } - /// the 2-norm of a vector v: result = sqrt(v^H * v) + /// the 1-norm of a vector v: result = max_i(abs(v_i)) template<typename Term> inline typename result_of::one_norm<Term, tag::expression>::type one_norm_dispatch(const Term& t, tag::expression) diff --git a/AMDiS/src/io/FileWriter.cc b/AMDiS/src/io/FileWriter.cc index 2afc9f5fc009b2a259ea7c9531f67f8eba57d32e..67a6b4aa46c4df11a763b0e80248127c7e136f6e 100644 --- a/AMDiS/src/io/FileWriter.cc +++ b/AMDiS/src/io/FileWriter.cc @@ -52,10 +52,10 @@ namespace AMDiS { template<> FileWriter<double>::FileWriter(std::string name_, - Mesh *mesh_, - SystemVector *vecs) + Mesh *mesh_, + SystemVector *vecs) : name(name_), - mesh(mesh_) + mesh(mesh_) { initialize(); @@ -63,211 +63,164 @@ namespace AMDiS * Removed by Siqi. not sure. * for (int i = 0; i < static_cast<int>(vecs->getSize()); i++) * TEST_EXIT(vecs->getDOFVector(0)->getFeSpace() == vecs->getDOFVector(i)->getFeSpace()) - * ("All FeSpace have to be equal!\n"); + * ("All FeSpace have to be equal!\n"); */ feSpace = vecs->getDOFVector(0)->getFeSpace(); solutionVecs.resize(vecs->getSize()); for (int i = 0; i < static_cast<int>(vecs->getSize()); i++) - solutionVecs[i] = vecs->getDOFVector(i); + solutionVecs[i] = vecs->getDOFVector(i); for (size_t i = 0; i < solutionVecs.size(); i++) - solutionNames.push_back(solutionVecs[i]->getName()); + solutionNames.push_back(solutionVecs[i]->getName()); } template<> void FileWriter<double>::writeFiles(AdaptInfo *adaptInfo, - bool force, - int level, - Flag flag, - bool (*writeElem)(ElInfo*)) + bool force, + int level, + Flag flag, + bool (*writeElem)(ElInfo*)) { FUNCNAME("FileWriter<T>::writeFiles()"); using namespace ::AMDiS::io; - if (timeModulo > 0.0) { - if ((lastWriteTime != 0.0 && adaptInfo->getTime() < lastWriteTime + timeModulo) && !force) - return; - } else { - if ((adaptInfo->getTimestepNumber() % tsModulo != 0) && !force) - return; - } - - lastWriteTime = adaptInfo->getTime(); + if (!super::doWriteTimestep(adaptInfo, force)) + return; //-----------------by Siqi---------------------// if (writeAMDiSFormat || writePeriodicFormat || writeParaViewFormat - || writeParaViewVectorFormat || writeParaViewAnimation - || writeDofFormat || (writeArhFormat && !writeArh2Format) || writePovrayFormat) + || writeParaViewVectorFormat || writeParaViewAnimation + || writeDofFormat || (writeArhFormat && !writeArh2Format) || writePovrayFormat) { - for (int i = 0; i < static_cast<int>(solutionVecs.size()); i++) - TEST_EXIT(solutionVecs[0]->getFeSpace() == solutionVecs[i]->getFeSpace()) - ("All FeSpaces have to be equal!\n"); + for (int i = 0; i < static_cast<int>(solutionVecs.size()); i++) + TEST_EXIT(solutionVecs[0]->getFeSpace() == solutionVecs[i]->getFeSpace()) + ("All FeSpaces have to be equal!\n"); } - + // Containers, which store the data to be written; std::vector<DataCollector<>*> dataCollectors(solutionVecs.size()); if (writeElem) { - for (int i = 0; i < static_cast<int>(dataCollectors.size()); i++) - dataCollectors[i] = new DataCollector<>(feSpace, solutionVecs[i], - level, flag, writeElem); + for (int i = 0; i < static_cast<int>(dataCollectors.size()); i++) + dataCollectors[i] = new DataCollector<>(feSpace, solutionVecs[i], + level, flag, writeElem); } else { - for (int i = 0; i < static_cast<int>(dataCollectors.size()); i++) - dataCollectors[i] = new DataCollector<>(feSpace, solutionVecs[i], - traverseLevel, - flag | traverseFlag, - writeElement); + for (int i = 0; i < static_cast<int>(dataCollectors.size()); i++) + dataCollectors[i] = new DataCollector<>(feSpace, solutionVecs[i], + traverseLevel, + flag | traverseFlag, + writeElement); } - std::string fn = filename; - - if (createParaViewSubDir) { - using namespace boost::filesystem; - path vtu_path = fn; - path data_basedir("data"); - path vtu_filename = vtu_path.filename(); - vtu_path.remove_filename() /= data_basedir; - try { - create_directory(vtu_path); - vtu_path /= vtu_filename; - fn = vtu_path.string(); - } catch (...) {} - } - - #if HAVE_PARALLEL_DOMAIN_AMDIS - std::string paraFilename = fn; - fn += "-p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()) + "-"; - std::string postfix = ""; - #endif - - - ///TODO: use the getParaViewFilename.. consistent with the parallel domain?? - if (appendIndex) { - TEST_EXIT(indexLength <= 99)("index lenght > 99\n"); - TEST_EXIT(indexDecimals <= 97)("index decimals > 97\n"); - TEST_EXIT(indexDecimals < indexLength)("index length <= index decimals\n"); - - char formatStr[9]; - char timeStr[20]; - - sprintf(formatStr, "%%0%d.%df", indexLength, indexDecimals); - sprintf(timeStr, formatStr, adaptInfo ? adaptInfo->getTime() : 0.0); - - fn += timeStr; - #if HAVE_PARALLEL_DOMAIN_AMDIS - paraFilename += timeStr; - postfix += timeStr + paraviewFileExt; - #endif - } else { - #if HAVE_PARALLEL_DOMAIN_AMDIS - postfix += paraviewFileExt; - #endif - } - - - #if HAVE_PARALLEL_DOMAIN_AMDIS - std::string fn_ = paraFilename; - #else - std::string fn_ = fn; - #endif + std::string fn, fn_; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + std::string paraFilename, postfix; + super::getFilename(adaptInfo, fn, paraFilename, postfix); + postfix += paraviewFileExt; + fn_ = paraFilename; +#else + super::getFilename(adaptInfo, fn); + fn_ = fn; +#endif + if (writeAMDiSFormat) { - MacroWriter::writeMacro(dataCollectors[0], - const_cast<char*>((fn + amdisMeshExt).c_str()), - adaptInfo ? adaptInfo->getTime() : 0.0); - MSG("macro file written to %s\n", (fn + amdisMeshExt).c_str()); - - ValueWriter::writeValues(dataCollectors[0], - (fn + amdisDataExt).c_str(), - adaptInfo ? adaptInfo->getTime() : 0.0); - MSG("value file written to %s\n", (fn + amdisDataExt).c_str()); + MacroWriter::writeMacro(dataCollectors[0], + const_cast<char*>((fn + amdisMeshExt).c_str()), + adaptInfo ? adaptInfo->getTime() : 0.0); + MSG("macro file written to %s\n", (fn + amdisMeshExt).c_str()); + + ValueWriter::writeValues(dataCollectors[0], + (fn + amdisDataExt).c_str(), + adaptInfo ? adaptInfo->getTime() : 0.0); + MSG("value file written to %s\n", (fn + amdisDataExt).c_str()); } if (writePeriodicFormat) { - MacroWriter::writePeriodicFile(dataCollectors[0], - (fn + periodicFileExt).c_str()); - MSG("periodic file written to %s\n", (fn + periodicFileExt).c_str()); + MacroWriter::writePeriodicFile(dataCollectors[0], + (fn + periodicFileExt).c_str()); + MSG("periodic file written to %s\n", (fn + periodicFileExt).c_str()); } if (writeParaViewFormat) { - std::string vtu_file = fn + paraviewFileExt; - VtkWriter::Aux vtkWriter(&dataCollectors, - solutionNames, - VtkWriter::Vtuformat(paraViewMode), (paraViewPrecision == 1), writeParaViewVectorFormat); - vtkWriter.writeFile(vtu_file); + std::string vtu_file = fn + paraviewFileExt; + VtkWriter::Aux vtkWriter(&dataCollectors, + solutionNames, + VtkWriter::Vtuformat(paraViewMode), (paraViewPrecision == 1), writeParaViewVectorFormat); + vtkWriter.writeFile(vtu_file); #if HAVE_PARALLEL_DOMAIN_AMDIS - if (MPI::COMM_WORLD.Get_rank() == 0) { -// 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, - postfix, - solutionNames, - VtkWriter::Vtuformat(paraViewMode), - (paraViewPrecision == 1), - writeParaViewVectorFormat); - } + if (MPI::COMM_WORLD.Get_rank() == 0) { +// 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, + postfix, + solutionNames, + VtkWriter::Vtuformat(paraViewMode), + (paraViewPrecision == 1), + writeParaViewVectorFormat); + } #endif - MSG("ParaView file written to %s\n", (fn + paraviewFileExt).c_str()); + MSG("ParaView file written to %s\n", (fn + paraviewFileExt).c_str()); } // write vtu-vector files if (writeParaViewVectorFormat && !writeParaViewFormat) { - VtkVectorWriter::writeFile(solutionVecs, fn_ + paraviewFileExt, true, writeAs3dVector); - MSG("ParaView file written to %s\n", (fn_ + paraviewFileExt).c_str()); + VtkVectorWriter::writeFile(solutionVecs, fn_ + paraviewFileExt, true, writeAs3dVector); + MSG("ParaView file written to %s\n", (fn_ + paraviewFileExt).c_str()); } if (writeParaViewAnimation) { - std::string pvd_file = fn_ + paraviewFileExt; + std::string pvd_file = fn_ + paraviewFileExt; #if HAVE_PARALLEL_DOMAIN_AMDIS - pvd_file = fn_ + paraviewParallelFileExt; - if (MPI::COMM_WORLD.Get_rank() == 0) + pvd_file = fn_ + paraviewParallelFileExt; + if (MPI::COMM_WORLD.Get_rank() == 0) #endif - { - VtkWriter::detail::updateAnimationFile(adaptInfo, - pvd_file, - ¶viewAnimationFrames, - filename + ".pvd"); - } + { + VtkWriter::detail::updateAnimationFile(adaptInfo, + pvd_file, + ¶viewAnimationFrames, + filename + ".pvd"); + } } if (writeDofFormat) { - DofWriter::writeFile(solutionVecs, fn + ".dof"); + DofWriter::writeFile(solutionVecs, fn + ".dof"); } // write Arh files if (!writeArh2Format && writeArhFormat) - ArhWriter::write(fn_ + ".arh", feSpace->getMesh(), solutionVecs); + ArhWriter::write(fn_ + ".arh", feSpace->getMesh(), solutionVecs); else if (writeArh2Format) - Arh2Writer::writeFile(solutionVecs, fn_ + ".arh"); + Arh2Writer::writeFile(solutionVecs, fn_ + ".arh"); #ifdef HAVE_PNG if (writePngFormat) { - PngWriter pngWriter(dataCollectors[0]); - pngWriter.writeFile(fn + ".png", pngType); + PngWriter pngWriter(dataCollectors[0]); + pngWriter.writeFile(fn + ".png", pngType); - MSG("PNG image file written to %s\n", (fn + ".png").c_str()); + MSG("PNG image file written to %s\n", (fn + ".png").c_str()); } #endif if (writePovrayFormat) { - PovrayWriter povrayWriter(dataCollectors[0]); - povrayWriter.writeFile(fn + ".pov"); + PovrayWriter povrayWriter(dataCollectors[0]); + povrayWriter.writeFile(fn + ".pov"); - MSG("Povray script written to %s\n", (fn + ".pov").c_str()); + MSG("Povray script written to %s\n", (fn + ".pov").c_str()); } for (int i = 0; i < static_cast<int>(dataCollectors.size()); i++) - delete dataCollectors[i]; + delete dataCollectors[i]; } template<> diff --git a/AMDiS/src/io/FileWriter.h b/AMDiS/src/io/FileWriter.h index 710b44d6a609508fb900bcf1469b5eeb9d848937..b66cf361fd338679c50ab6f87cc43979bcf4961c 100644 --- a/AMDiS/src/io/FileWriter.h +++ b/AMDiS/src/io/FileWriter.h @@ -52,6 +52,8 @@ namespace AMDiS { template<typename T> class FileWriter : public ::AMDiS::FileWriterInterface { + typedef ::AMDiS::FileWriterInterface super; + public: /// Constructor for a filewriter for one data component. FileWriter(std::string name, Mesh *mesh, DOFVector<T> *vec); @@ -65,8 +67,8 @@ namespace AMDiS { /// Constructor for a filewriter with more than one data component. FileWriter(std::string name, - Mesh *mesh, - SystemVector *vecs); + Mesh *mesh, + SystemVector *vecs); /// Destructor virtual ~FileWriter(); @@ -75,24 +77,31 @@ namespace AMDiS { virtual void writeFiles(AdaptInfo *adaptInfo, bool force, int level = -1, Flag traverseFlag = Mesh::CALL_LEAF_EL, - bool (*writeElem)(ElInfo*) = NULL); + bool (*writeElem)(ElInfo*) = NULL) override; std::vector<std::pair<double, std::string> >& getParaviewAnimationFrames() { return paraviewAnimationFrames; } - bool getWriteParaViewFormat() const { return writeParaViewFormat; } - std::string getParaViewFilename(AdaptInfo* info) const ; - const std::vector< std::string >& getSolutionNames() const - { return solutionNames; } + bool getWriteParaViewFormat() const + { + return writeParaViewFormat; + } + + std::string getParaViewFilename(AdaptInfo* info) const; + + const std::vector<std::string>& getSolutionNames() const + { + return solutionNames; + } protected: /// Initialization of the filewriter. void initialize(); /// Reads all file writer dependend parameters from the init file. - void readParameters(); + virtual void readParameters(std::string name) override; /// Name of the writer. std::string name; @@ -129,9 +138,6 @@ namespace AMDiS { /// 1: extend number of component to 3, so that paraview can display the std::vector as worldstd::vector bool writeAs3dVector; - - /// create a subdirectory where to put the vtu file - bool createParaViewSubDir; /// 0: Don't write ParaView animation file; 1: Write ParaView animation file. int writeParaViewAnimation; @@ -166,22 +172,6 @@ namespace AMDiS { /// name of the template file that will be prepended to all created *.pov files std::string povrayTemplate; - /// 0: Don't append time index to filename prefix. - /// 1: Append time index to filename prefix. - int appendIndex; - - /// Total length of appended time index. - int indexLength; - - /// Number of decimals in time index. - int indexDecimals; - - /// Timestep modulo: write only every tsModulo-th timestep! - int tsModulo; - - /// Time modulo: write at first iteration after lastWriteTime + timeModulo - double timeModulo; - double lastWriteTime; /// Stores a set of std::pairs of timepoint and filename to write a ParaView /// animation file. diff --git a/AMDiS/src/io/FileWriter.hh b/AMDiS/src/io/FileWriter.hh index 1c2c6c6156585884092c929bcd80059bbc13e04d..1a98bf8d31fdf988f62f09114da9d1ac8684385b 100644 --- a/AMDiS/src/io/FileWriter.hh +++ b/AMDiS/src/io/FileWriter.hh @@ -101,7 +101,7 @@ namespace AMDiS : name(name_), mesh(mesh_) { - ERROR("SystemVector contains DOFVectors of type double, so the FileWriter<not double> can not be used!\n"); + ERROR_EXIT("SystemVector contains DOFVectors of type double, so the FileWriter<not double> can not be used!\n"); } @@ -130,7 +130,6 @@ namespace AMDiS paraViewPrecision = 0; writeParaViewVectorFormat = 0; writeAs3dVector = false; - createParaViewSubDir = false; writeParaViewAnimation = 0; writePeriodicFormat = 0; writePngFormat = 0; @@ -139,24 +138,19 @@ namespace AMDiS writeArhFormat = 0; writeArh2Format = 0; pngType = 0; - appendIndex = 0; - indexLength = 5; - indexDecimals = 3; - tsModulo = 1; - timeModulo = -1.0; - lastWriteTime = 0.0; nTmpSolutions = 0; paraviewAnimationFrames.resize(0), compression = NONE; - readParameters(); + readParameters(name); } template<typename T> - void FileWriter<T>::readParameters() + void FileWriter<T>::readParameters(std::string name) { - Parameters::get(name + "->filename", filename); + super::readParameters(name); + Parameters::get(name + "->AMDiS format", writeAMDiSFormat); Parameters::get(name + "->AMDiS mesh ext", amdisMeshExt); Parameters::get(name + "->AMDiS data ext", amdisDataExt); @@ -166,17 +160,11 @@ namespace AMDiS Parameters::get(name + "->ParaView vector format", writeParaViewVectorFormat); Parameters::get(name + "->write vector as 3d vector", writeAs3dVector); Parameters::get(name + "->ParaView animation", writeParaViewAnimation); - Parameters::get(name + "->ParaView create subdirectory", createParaViewSubDir); Parameters::get(name + "->ParaView ext", paraviewFileExt); Parameters::get(name + "->Periodic format", writePeriodicFormat); Parameters::get(name + "->Periodic ext", periodicFileExt); Parameters::get(name + "->PNG format", writePngFormat); Parameters::get(name + "->PNG type", pngType); - Parameters::get(name + "->append index", appendIndex); - Parameters::get(name + "->index length", indexLength); - Parameters::get(name + "->index decimals", indexDecimals); - Parameters::get(name + "->write every i-th timestep", tsModulo); - Parameters::get(name + "->write after timestep", timeModulo); Parameters::get(name + "->Povray format", writePovrayFormat); Parameters::get(name + "->Povray template", povrayTemplate); @@ -206,15 +194,8 @@ namespace AMDiS { FUNCNAME("FileWriter<T>::writeFiles()"); - if (timeModulo > 0.0) { - if ((lastWriteTime != 0.0 && adaptInfo->getTime() < lastWriteTime + timeModulo) && !force) - return; - } else { - if ((adaptInfo->getTimestepNumber() % tsModulo != 0) && !force) - return; - } - - lastWriteTime = adaptInfo->getTime(); + if (!super::doWriteTimestep(adaptInfo, force)) + return; // Containers, which store the data to be written; std::vector<DataCollector<T>*> dataCollectors(solutionVecs.size()); @@ -231,35 +212,14 @@ namespace AMDiS writeElement); } - std::string fn = filename; - - #if HAVE_PARALLEL_DOMAIN_AMDIS - std::string paraFilename = fn; - fn += "-p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()) + "-"; - std::string postfix = ""; - #endif - - if (appendIndex) { - TEST_EXIT(indexLength <= 99)("index lenght > 99\n"); - TEST_EXIT(indexDecimals <= 97)("index decimals > 97\n"); - TEST_EXIT(indexDecimals < indexLength)("index length <= index decimals\n"); - - char formatStr[9]; - char timeStr[20]; - - sprintf(formatStr, "%%0%d.%df", indexLength, indexDecimals); - sprintf(timeStr, formatStr, adaptInfo ? adaptInfo->getTime() : 0.0); - - fn += timeStr; - #if HAVE_PARALLEL_DOMAIN_AMDIS - paraFilename += timeStr; - postfix += timeStr + paraviewFileExt; - #endif - } else { - #if HAVE_PARALLEL_DOMAIN_AMDIS - postfix += paraviewFileExt; - #endif - } + std::string fn; +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + std::string paraFilename, postfix; + super::getFilename(adaptInfo, fn, paraFilename, postfix); + postfix += paraviewFileExt; +#else + super::getFilename(adaptInfo, fn); +#endif if (writeParaViewVectorFormat) { io::VtkVectorWriter::Aux<T> vtkVectorWriter(&dataCollectors, writeAs3dVector); diff --git a/AMDiS/src/io/FileWriterInterface.cc b/AMDiS/src/io/FileWriterInterface.cc new file mode 100644 index 0000000000000000000000000000000000000000..6d696200e3400ae83c71ffd2569489ef93078310 --- /dev/null +++ b/AMDiS/src/io/FileWriterInterface.cc @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * 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 FileWriterInterface.cc */ + + +#include "FileWriterInterface.h" +#include "AdaptInfo.h" +#include "Initfile.h" + +#include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> + +namespace AMDiS { + + bool FileWriterInterface::doWriteTimestep(AdaptInfo *adaptInfo, bool force) + { + if (!force) { + if (timeModulo > 0.0) { + if (lastWriteTime > adaptInfo->getStartTime() + && adaptInfo->getTime() < lastWriteTime + timeModulo) + return false; + } else { + if (adaptInfo->getTimestepNumber() % tsModulo != 0) + return false; + } + } + + lastWriteTime = adaptInfo->getTime(); + return true; + } + + + void FileWriterInterface::readParameters(std::string name) + { + Parameters::get(name + "->filename", filename); + Parameters::get(name + "->append index", appendIndex); + Parameters::get(name + "->index length", indexLength); + Parameters::get(name + "->index decimals", indexDecimals); + Parameters::get(name + "->write every i-th timestep", tsModulo); + Parameters::get(name + "->write after timestep", timeModulo); + + Parameters::get(name + "->ParaView create subdirectory", createSubDir); + if (createSubDir < 0) + Parameters::get(name + "->create subdirectory", createSubDir); + } + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + void FileWriterInterface::getFilename(AdaptInfo* adaptInfo, std::string& fn, std::string& paraFilename, std::string& postfix) +#else + void FileWriterInterface::getFilename(AdaptInfo* adaptInfo, std::string& fn) +#endif + { + fn = filename; + + if (createSubDir > 0) { + using namespace boost::filesystem; + path vtu_path = fn; + path data_basedir("data"); + path vtu_filename = vtu_path.filename(); + vtu_path.remove_filename() /= data_basedir; + try { + create_directory(vtu_path); + vtu_path /= vtu_filename; + fn = vtu_path.string(); + } catch (...) {} + } + +#if HAVE_PARALLEL_DOMAIN_AMDIS + paraFilename = filename; + fn += "-p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()) + "-"; + postfix = ""; +#endif + + if (appendIndex) { + TEST_EXIT(indexLength <= 99)("index lenght > 99\n"); + TEST_EXIT(indexDecimals <= 97)("index decimals > 97\n"); + TEST_EXIT(indexDecimals < indexLength)("index length <= index decimals\n"); + + char formatStr[9]; + char timeStr[20]; + + sprintf(formatStr, "%%0%d.%df", indexLength, indexDecimals); + sprintf(timeStr, formatStr, adaptInfo ? adaptInfo->getTime() : 0.0); + + fn += timeStr; +#if HAVE_PARALLEL_DOMAIN_AMDIS + paraFilename += timeStr; + postfix += timeStr; +#endif + } + } +} diff --git a/AMDiS/src/io/FileWriterInterface.h b/AMDiS/src/io/FileWriterInterface.h index 43e0faf9995d47cedd42a2243785ad3521fba570..a45bb10f520cf8155640318b4d5e256d4ce13325 100644 --- a/AMDiS/src/io/FileWriterInterface.h +++ b/AMDiS/src/io/FileWriterInterface.h @@ -41,6 +41,13 @@ namespace AMDiS { public: FileWriterInterface() : filename(""), + appendIndex(0), + indexLength(5), + indexDecimals(3), + createSubDir(-1), + tsModulo(1), + timeModulo(-1.0), + lastWriteTime(-1.0), traverseLevel(-1), traverseFlag(Mesh::CALL_LEAF_EL), writeElement(NULL) @@ -58,14 +65,8 @@ namespace AMDiS { Flag traverseFlag = Mesh::CALL_LEAF_EL, bool (*writeElem)(ElInfo*) = NULL) = 0; - void setTraverseProperties(int level, - Flag flag, - bool (*writeElem)(ElInfo*)) - { - traverseLevel = level; - traverseFlag |= flag; - writeElement = writeElem; - } + /// Test whether timestep should be written + virtual bool doWriteTimestep(AdaptInfo *adaptInfo, bool force); std::string getFilename() { @@ -76,15 +77,59 @@ namespace AMDiS { { filename = n; } + + void setWriteModulo(int tsModulo_ = 1, double timeModulo_ = -1.0) + { + tsModulo = tsModulo_; + timeModulo = timeModulo_; + } + + void setTraverseProperties(int level, + Flag flag, + bool (*writeElem)(ElInfo*)) + { + traverseLevel = level; + traverseFlag |= flag; + writeElement = writeElem; + } protected: + /// Reads all file writer dependend parameters from the init file. + virtual void readParameters(std::string name); + + /// create a filename that includes the timestep and possibly a processor ID in parallel mode +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + void getFilename(AdaptInfo* adaptInfo, std::string& fn, std::string& paraFilename, std::string& postfix); +#else + void getFilename(AdaptInfo* adaptInfo, std::string& fn); +#endif + /// Used filename prefix. std::string filename; - int traverseLevel; + /// 0: Don't append time index to filename prefix. + /// 1: Append time index to filename prefix. + int appendIndex; - Flag traverseFlag; + /// Total length of appended time index. + int indexLength; + /// Number of decimals in time index. + int indexDecimals; + + /// create a subdirectory where to put the files + int createSubDir; + + /// Timestep modulo: write only every tsModulo-th timestep! + int tsModulo; + + /// Time modulo: write at first iteration after lastWriteTime + timeModulo + double timeModulo; + double lastWriteTime; + + /// Traverse properties + int traverseLevel; + Flag traverseFlag; bool (*writeElement)(ElInfo*); }; diff --git a/AMDiS/src/io/MacroInfo.cc b/AMDiS/src/io/MacroInfo.cc index 5645c1834f937ff0705027d810de6dafe408153c..6e1a73874ed633c2f6b4f57449748936c3fbd74c 100644 --- a/AMDiS/src/io/MacroInfo.cc +++ b/AMDiS/src/io/MacroInfo.cc @@ -65,6 +65,7 @@ namespace AMDiS { mel[i]->elType = 0; } neigh_set = false; + neigh_inverse_set = false; bound_set = false; } @@ -82,6 +83,7 @@ namespace AMDiS { mesh = NULL; neigh_set = false; + neigh_inverse_set = false; nElements = 0; nVertices = 0; @@ -95,18 +97,19 @@ namespace AMDiS { /* fscanf(), else false */ /********************************************************************************/ - int MacroInfo::read_indices(FILE *file, DimVec<int> &id) + int MacroInfo::read_indices(FILE *file, Vector<int> &id) { int dim = mesh->getDim(); + TEST_EXIT_DBG(id.getSize() == dim+1)("Vector has wrong dimension!"); for (int i = 0; i <= dim; i++) if (fscanf(file, "%d", &id[i]) != 1) - return(false); + return false; - return(true); + return true; } -#define N_KEYS 14 +#define N_KEYS 15 #define N_MIN_KEYS 7 static const char *keys[N_KEYS] = { "DIM", // 0 @@ -122,7 +125,8 @@ namespace AMDiS { "element region", // 10 "surface region", // 11 "mesh name", // 12 - "time" // 13 + "time", // 13 + "element neighbours inverse" // 14 (for graph-structured meshes with >1 neighbors) }; @@ -165,9 +169,10 @@ namespace AMDiS { double dbl; char line[256]; int line_no, n_keys, sort_key[N_KEYS], nv_key, ne_key; - int key_def[N_KEYS] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int key_def[N_KEYS] = {0,0,0,0,0,0,0,0,0,0,0,0,0}; const char *key; DimVec<int> *ind = NULL; + FixVec<int, NEIGH> *ind_neigh = NULL; TEST_EXIT(filename != "")("No filename specified!\n"); @@ -259,6 +264,7 @@ namespace AMDiS { TEST_EXIT(result == 1)("cannot read DIM correctly in file %s\n", filename.c_str()); ind = new DimVec<int>(dim, NO_INIT); + ind_neigh = new FixVec<int, NEIGH>(dim, NO_INIT); key_def[0] = true; break; @@ -343,14 +349,12 @@ namespace AMDiS { for (int i = 0; i < nElements; i++) { // boundary information of ith element - result = read_indices(file, *ind); + result = read_indices(file, *ind_neigh); TEST_EXIT(result) ("cannot read boundary type of element %d in file %s\n", i, filename.c_str()); // fill boundary of macro-element - io::MacroReader::fillMelBoundary(mesh, - mel[i], - VecConv<int,NEIGH,PARTS>::convertVec((*ind), mesh)); + io::MacroReader::fillMelBoundary(mesh, mel[i], *ind_neigh); } this->fillBoundaryInfo(mesh); @@ -371,10 +375,8 @@ namespace AMDiS { for (int i = 0; i < nElements; i++) { // neighbour information about ith element - if (read_indices(file, *ind)) { - io::MacroReader::fillMelNeigh(mel[i], mel, - VecConv<int,NEIGH,PARTS>::convertVec((*ind), - mesh)); + if (read_indices(file, *ind_neigh)) { + io::MacroReader::fillMelNeigh(mel[i], mel, *ind_neigh); } else { // setting of neighbours fails @@ -498,6 +500,32 @@ namespace AMDiS { // line "time" result = fscanf(file, "%*s %*s"); break; + + case 14: + // block "element neighbours inverse" + result = fscanf(file, "%*s %*s %*s"); + + // === Fill MEL neighbour pointers: === + // === if they are specified in the file: read them from file, === + // === else init them by a call of fill_mel_neighbour() === + + neigh_inverse_set = true; + for (int i = 0; i < nElements; i++) { + // neighbour information about ith element + + if (read_indices(file, *ind_neigh)) { + io::MacroReader::fillMelNeighInv(mel[i], mel, *ind_neigh); + } else { + // setting of neighbours fails + ERROR_EXIT("Problem while reading 'element neighbours inverse' of element %d\n", i); + neigh_inverse_set = false; + break; + } + } + + key_def[7] = true; + break; + } } @@ -520,6 +548,8 @@ namespace AMDiS { for (int k = 0; k < mesh->getGeo(NEIGH); k++) if (mel[i]->neighbour[k]) mel[i]->boundary[k] = INTERIOR; + else if (neigh_inverse_set && mel[i]->neighbour_inv[k]) + mel[i]->boundary[k] = INTERIOR; else mel[i]->boundary[k] = 1; } diff --git a/AMDiS/src/io/MacroInfo.h b/AMDiS/src/io/MacroInfo.h index 2067498825c9024663406def903ad44dc8be7728..0cbd7dca366dfdbcfc7dbedd0c5ab93e05103b43 100644 --- a/AMDiS/src/io/MacroInfo.h +++ b/AMDiS/src/io/MacroInfo.h @@ -55,6 +55,9 @@ namespace AMDiS { /// true, if neighbour information is in macro file bool neigh_set; + + /// true, if inverse neighbour information is in macro file (see MacroReader.h) + bool neigh_inverse_set; /// true, if boundary information is in macro file bool bound_set; @@ -93,7 +96,7 @@ namespace AMDiS { protected: /// Reads indices from macro file - int read_indices(FILE *file, DimVec<int> &id); + int read_indices(FILE *file, Vector<int> &id); bool initialized; }; diff --git a/AMDiS/src/io/MacroReader.cc b/AMDiS/src/io/MacroReader.cc index 0881b25ac5604bac19396c351fd592bd7014f46b..61bba3f93c7f9ce3000b1c376ad24fb599cba1f6 100644 --- a/AMDiS/src/io/MacroReader.cc +++ b/AMDiS/src/io/MacroReader.cc @@ -317,14 +317,25 @@ namespace AMDiS { namespace io { MacroElement *neigh = const_cast<MacroElement*>(mel[i]->getNeighbour(k)); if (neigh) { - int j = 0; - for (; j < mesh->getGeo(NEIGH); j++) - if (neigh->getNeighbour(j) == *(mel + i)) - break; - - TEST_EXIT(j < mesh->getGeo(NEIGH))("el %d no neighbour of neighbour %d\n", - mel[i]->getIndex(), neigh->getIndex()); - mel[i]->setOppVertex(k, j); + if (!macroInfo->neigh_inverse_set) { + int j = 0; + for (; j < mesh->getGeo(NEIGH); j++) + if (neigh->getNeighbour(j) == *(mel + i)) + break; + + TEST_EXIT(j < mesh->getGeo(NEIGH))("el %d no neighbour of neighbour %d\n", + mel[i]->getIndex(), neigh->getIndex()); + mel[i]->setOppVertex(k, j); + } else { + int j = 0; + for (; j < mesh->getGeo(NEIGH); j++) + if (neigh->getNeighbourInv(j) == *(mel + i)) + break; + + TEST_EXIT(j < mesh->getGeo(NEIGH))("el %d no neighbour-inv of neighbour %d\n", + mel[i]->getIndex(), neigh->getIndex()); + mel[i]->setOppVertex(k, j); + } } else { mel[i]->setOppVertex(k, -1); } @@ -948,7 +959,7 @@ namespace AMDiS { namespace io { } void MacroReader::fillMelBoundary(Mesh *mesh, MacroElement *mel, - FixVec<BoundaryType ,NEIGH> ind) + FixVec<BoundaryType,NEIGH> const& ind) { for (int i = 0; i < mesh->getGeo(NEIGH); i++) mel->boundary[i] = ind[i]; @@ -957,7 +968,7 @@ namespace AMDiS { namespace io { void MacroReader::fillMelNeigh(MacroElement *mel, std::deque<MacroElement*>& macro_elements, - FixVec<int,NEIGH> ind) + FixVec<int,NEIGH> const& ind) { int dim = mel->element->getMesh()->getDim(); @@ -970,6 +981,21 @@ namespace AMDiS { namespace io { } + void MacroReader::fillMelNeighInv(MacroElement *mel, + std::deque<MacroElement*>& macro_elements, + FixVec<int,NEIGH> const& ind) + { + int dim = mel->element->getMesh()->getDim(); + + for (int k = 0; k < Global::getGeo(NEIGH, dim); k++) { + if (ind[k] >= 0) + mel->neighbour_inv[k] = macro_elements[ind[k]]; + else + mel->neighbour_inv[k] = NULL; + } + } + + // ordnet Eintraege in Macro-Element macro bzgl. Verfeinerungskante ka um // (coord, bound, boundary, neigh, oppVertex) diff --git a/AMDiS/src/io/MacroReader.h b/AMDiS/src/io/MacroReader.h index 79ffa4f8a5e6d74b59ff8f55a47eb3d01a4c0354..f2ac2bfd37595319c0e854e7939e19f739779bef 100644 --- a/AMDiS/src/io/MacroReader.h +++ b/AMDiS/src/io/MacroReader.h @@ -120,11 +120,21 @@ namespace AMDiS { namespace io { int mel_edge_no, int *n_neigh); static void fillMelBoundary(Mesh *, MacroElement *mel, - FixVec<BoundaryType ,NEIGH>); + FixVec<BoundaryType,NEIGH> const&); static void fillMelNeigh(MacroElement *mel, std::deque<MacroElement*>& macro_elements, - FixVec<int,NEIGH> ind); + FixVec<int,NEIGH> const&); + + // for graph-structured meshes that have elements with >1 neighbors + // (0)--[a]--(1)---[b]--(2) + // \____[c]__(3) + // + // neigh: [a]->[b], [b]->[c], [c]->[a] + // neigh_inv: [b]->[a], [c]->[b], [a]->[c] + static void fillMelNeighInv(MacroElement *mel, + std::deque<MacroElement*>& macro_elements, + FixVec<int,NEIGH> const&); static void umbVkantMacro(Mesh *mesh, MacroElement *, diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index 10571d3b3902784b73685db4b7dda57952354855..a77a922177df3ba964305cd9f65f8eeb85922471 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -201,7 +201,7 @@ namespace AMDiS { namespace Parallel { FUNCNAME("PetscSolverFeti::createDirichletData()"); if (dirichletMode == 1) { - int nComponents = mat.getSize(); + int nComponents = mat.getNumRows(); for (int component = 0; component < nComponents; component++) { DOFMatrix* dofMat = mat[component][component]; if (!dofMat) diff --git a/AMDiS/src/reinit/NormEps.cc b/AMDiS/src/reinit/NormEps.cc index d2874f241d23cd7ae2c93bde4c633cae4f6f0a4a..a2f2b6a4d4b1e514c63a3b5a4922d8675183bc48 100644 --- a/AMDiS/src/reinit/NormEps.cc +++ b/AMDiS/src/reinit/NormEps.cc @@ -20,6 +20,7 @@ #include "NormEps.h" +#include "MatrixVectorOperations.h" namespace reinit { diff --git a/AMDiS/src/solver/BlockPreconditioner.h b/AMDiS/src/solver/BlockPreconditioner.h index e11f8c1068153d6048d784f2b5fd3edece14e4f4..c16336675286ae07c37f328ceb4d496bab5589e6 100644 --- a/AMDiS/src/solver/BlockPreconditioner.h +++ b/AMDiS/src/solver/BlockPreconditioner.h @@ -30,12 +30,13 @@ namespace AMDiS { /// Basis preconditioner structure for block-preconditioners - template< typename MatrixType > - struct BlockPreconditioner : ITL_PreconditionerBase<MatrixType, MTLTypes::MTLVector> - { - typedef ITL_PreconditionerBase<MatrixType, MTLTypes::MTLVector> super; - typedef BlockPreconditioner<MatrixType> self; - + template <class MatrixType, class VectorType = MTLTypes::MTLVector> + struct BlockPreconditioner : public ITL_PreconditionerBase<MatrixType, VectorType> + { + typedef BlockPreconditioner self; + typedef ITL_PreconditionerBase<MatrixType, VectorType> super; + typedef super precon_base; + BlockPreconditioner() : A(NULL), fullMatrix(NULL) { } @@ -59,12 +60,12 @@ namespace AMDiS { } } - virtual void solve(const MTLTypes::MTLVector& b, MTLTypes::MTLVector& x) const + virtual void solve(const VectorType& b, VectorType& x) const { FUNCNAME("BlockPreconditioner::solve()"); TEST_EXIT(false)("Must be implemented in derived classes!\n"); } - virtual void adjoint_solve(const MTLTypes::MTLVector& x, MTLTypes::MTLVector& y) const + virtual void adjoint_solve(const VectorType& x, VectorType& y) const { FUNCNAME("BlockPreconditioner::adjoint_solve()"); TEST_EXIT(false)("Must be implemented in derived classes!\n"); } @@ -84,7 +85,7 @@ namespace AMDiS { return A->getSubMatrix(i, j); } - template<typename SolverType, typename RunnerType> + template <class SolverType, class RunnerType> static void createSubSolver(std::string param, SolverType*& solver, RunnerType*& runner, std::string solverType = "0", std::string preconType = "no", int max_iter = 100, double tol = 1.e-8) diff --git a/AMDiS/src/solver/LinearSolver.h b/AMDiS/src/solver/LinearSolver.h index d7439f74f94a594f90d53ecaf54c9123314ea7b2..5dece3930ed82fec5ec328970d181fe588ab53b8 100644 --- a/AMDiS/src/solver/LinearSolver.h +++ b/AMDiS/src/solver/LinearSolver.h @@ -82,7 +82,7 @@ namespace AMDiS { #ifdef HAVE_PARALLEL_MTL4 template< typename MatrixType > - struct LinearSolverBase<MatrixType, ParallelMapper, typename boost::enable_if< mtl::traits::is_distributed<MatrixType> > > + struct LinearSolverBase<MatrixType, ParallelMapper, typename enable_if< mtl::traits::is_distributed<MatrixType> > > : public ParallelSolver { typedef ParallelMapper Mapper; diff --git a/AMDiS/src/solver/LinearSolverInterface.h b/AMDiS/src/solver/LinearSolverInterface.h index 7244cf212b13b52f98f2d00339a54af52c4356e0..19848f3e4d981db30ee9557b92538456a2e7c922 100644 --- a/AMDiS/src/solver/LinearSolverInterface.h +++ b/AMDiS/src/solver/LinearSolverInterface.h @@ -127,6 +127,7 @@ namespace AMDiS { MSG("Residual norm: ||b-Ax|| = %e\n", residual); } +#if DEBUG != 0 if (getIterations() > 0) { MSG("Nr. of iterations needed = %d\n", getIterations()); } @@ -134,16 +135,21 @@ namespace AMDiS { if (error_code != 0) { MSG("ERROR-Code = %d\n", error_code); } + + if (!isNumber(residual) || !isNumber(rel_residual)) { + MSG("Residual or relative residual is NaN/Inf!\n"); + } +#endif // test for absolute tolerance - bool isAbsTolReached=(isNumber(residual) && (residual < 0.0 || tolerance < 1.e-30 || residual <= tolerance)); - // TEST_EXIT(isAbsTolReached || !breakTolNotReached); - // ("Tolerance tol = %e could not be reached!\n Set tolerance by '->solver->tolerance:' \n", tolerance); + TEST_EXIT((isNumber(residual) && (residual < 0.0 || tolerance < 1.e-30 || residual <= tolerance)) + || !breakTolNotReached) + ("Tolerance tol = %e could not be reached!\n Set tolerance by '->solver->tolerance:' \n", tolerance); // test for relative tolerance - bool isRelTolReached=(isNumber(rel_residual) && (rel_residual < 0.0 || relative < 1.e-30 || rel_residual <= relative)) || (residual < 1.e-30); - TEST_EXIT(isAbsTolReached || isRelTolReached ||!breakTolNotReached ) - ("Relative tolerance rtol = %e could not be reached!\n tolerance tol = %e could not be reached!\n Set tolerance by '->solver->relative tolerance:' \n Set tolerance by '->solver->tolerance:' \n", relative, tolerance); + TEST_EXIT((isNumber(rel_residual) && (rel_residual < 0.0 || relative < 1.e-30 || rel_residual <= relative)) + || (residual < 1.e-30) || !breakTolNotReached) + ("Relative tolerance rtol = %e could not be reached!\n Set tolerance by '->solver->relative tolerance:' \n", relative); } return error_code; } diff --git a/AMDiS/src/solver/Mapper.h b/AMDiS/src/solver/Mapper.h index b2deab963481f4df2ce6f483dc22db315cbc58a2..0078f1d2335c8886be68fa14939649a62de4b240 100644 --- a/AMDiS/src/solver/Mapper.h +++ b/AMDiS/src/solver/Mapper.h @@ -98,7 +98,7 @@ namespace AMDiS { rowOffset(0), colOffset(0), nrow(0), ncol(0), sizes(nComp) { const Matrix<DOFMatrix* >& orMat(*sm.getOriginalMat()); - const int ns = orMat.getSize(); + const int ns = orMat.getNumRows(); for (int i= 0; i < ns; i++) { sizes[i] = orMat[i][i]->getFeSpace()->getAdmin()->getUsedSize(); nrow += sizes[i]; diff --git a/AMDiS/src/solver/MatrixStreams.h b/AMDiS/src/solver/MatrixStreams.h index 1193da9f6ae5add2c75f67f8039814f199337356..0f7d62817573a0d2f1413643d7e5dc14b56d288e 100644 --- a/AMDiS/src/solver/MatrixStreams.h +++ b/AMDiS/src/solver/MatrixStreams.h @@ -55,7 +55,7 @@ namespace AMDiS { void operator<<(MatrixType& matrix, MatMap<const SolverMatrix<Matrix<DOFMatrix* > >, Mapper >& Asolver) { const Matrix< DOFMatrix* >& A = *(Asolver.mat.getOriginalMat()); - int ns = A.getSize(); + int ns = A.getNumRows(); Mapper& mapper(Asolver.mapper); set_to_zero(matrix); @@ -86,7 +86,7 @@ namespace AMDiS { void operator<<(MatrixType& matrix, MatMap<const Matrix<MatrixType* >, Mapper >& Asolver) { Matrix< MatrixType* >& A = *(Asolver.mat); - int ns = A.getSize(); + int ns = A.getNumRows(); Mapper& mapper(Asolver.mapper); set_to_zero(matrix); diff --git a/AMDiS/src/traits/basic.hpp b/AMDiS/src/traits/basic.hpp new file mode 100644 index 0000000000000000000000000000000000000000..af2fb919a846977841e359ff79b186b879eed5e8 --- /dev/null +++ b/AMDiS/src/traits/basic.hpp @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * 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 basic.hpp */ + +#ifndef AMDIS_BASIC_TRAITS_HPP +#define AMDIS_BASIC_TRAITS_HPP + +#include <boost/version.hpp> +#include <boost/mpl/logical.hpp> + +#include "boost/numeric/ublas/detail/returntype_deduction.hpp" +#if BOOST_VERSION >= 105600 +#include <boost/core/enable_if.hpp> +#else +#include <boost/utility/enable_if.hpp> +#endif + +#ifdef HAS_CPP11 +#include <type_traits> +#endif + +namespace AMDiS +{ + + // introduce some shortcuts for boost::mpl + // --------------------------------------- + using boost::mpl::true_; + using boost::mpl::false_; + using boost::mpl::and_; + using boost::mpl::or_; + + using boost::enable_if; + using boost::disable_if; + + namespace traits + { + + // dummy type + typedef boost::numeric::ublas::error_cant_deduce_type no_valid_type; + + +#ifdef HAS_CPP11 + template <typename T> + struct is_trivially_copyable : std::is_trivially_copyable<T> {}; +#else + template <typename T> + struct is_trivially_copyable : boost::is_pod<T> {}; +#endif + + + } +} + + +#endif // AMDIS_BASIC_TRAITS_HPP diff --git a/AMDiS/src/traits/category.hpp b/AMDiS/src/traits/category.hpp index 0d00ddcbaf823f6ef45c082279f11172c2a1bc26..267cfbc5c04b6181201264380485991a0b5029b1 100644 --- a/AMDiS/src/traits/category.hpp +++ b/AMDiS/src/traits/category.hpp @@ -249,6 +249,30 @@ namespace AMDiS template<typename T> struct is_matrix : has_tag<T, tag::matrix> {}; + // ------------------------------------------------------------------------- + template<typename T, typename S, typename Enable = void> + struct is_convertible : boost::is_convertible<T, S> {}; + + template<typename T, typename S> + struct is_convertible<T, S, typename boost::enable_if< + typename boost::mpl::and_< + typename is_vector<T>::type, + typename is_vector<S>::type + >::type + >::type > + : boost::is_convertible<typename T::value_type, typename S::value_type> {}; + + template<typename T, typename S> + struct is_convertible<T, S, typename boost::enable_if< + typename boost::mpl::and_< + typename is_matrix<T>::type, + typename is_matrix<S>::type + >::type + >::type > + : boost::is_convertible<typename T::value_type, typename S::value_type> {}; + + + } // end namespace traits } // end namespace AMDiS diff --git a/AMDiS/src/traits/scalar_types.hpp b/AMDiS/src/traits/scalar_types.hpp index ac7520965f3788510d990aae6b2668e4825cddd7..7295a0bc7c87043b3dddb54a1c3f40782986c35b 100644 --- a/AMDiS/src/traits/scalar_types.hpp +++ b/AMDiS/src/traits/scalar_types.hpp @@ -25,6 +25,10 @@ #ifndef AMDIS_TYPE_TRAITS_SCALAR_TYPES_HPP #define AMDIS_TYPE_TRAITS_SCALAR_TYPES_HPP +#ifdef HAS_CPP11 +#include <type_traits> +#endif + namespace AMDiS { namespace traits @@ -45,7 +49,6 @@ namespace AMDiS typename boost::is_floating_point<T>::type, typename is_integer<T>::type >::type {}; - } // end namespace traits diff --git a/extensions/ExtendedProblemStat.h b/extensions/ExtendedProblemStat.h index d6f305e1c516879d2bdb8aa36bfa865261f4241c..fb58f1d516eaab09f01a06dfffe72000feba5a49 100644 --- a/extensions/ExtendedProblemStat.h +++ b/extensions/ExtendedProblemStat.h @@ -41,13 +41,13 @@ class ExtendedProblemStat : public ProblemStat_ public: ExtendedProblemStat(std::string nameStr, ProblemIterationInterface *problemIteration = NULL) - : - #if defined NONLIN_PROBLEM - ProblemStat_(nameStr) - #else - ProblemStat_(nameStr, problemIteration) - #endif - , oldMeshChangeIdx(0) + : + #if defined NONLIN_PROBLEM + ProblemStat_(nameStr), + #else + ProblemStat_(nameStr, problemIteration), + #endif + oldMeshChangeIdx(0) { exactSolutions.resize(nComponents); for (int i = 0; i < nComponents; ++i) @@ -56,9 +56,8 @@ public: template<typename SubProblemType> ExtendedProblemStat(std::string nameStr, SubProblemType *subProblem) - : - ProblemStat_(nameStr, subProblem) - , oldMeshChangeIdx(0) + : ProblemStat_(nameStr, subProblem), + oldMeshChangeIdx(0) { exactSolutions.resize(nComponents); for (int i = 0; i < nComponents; ++i) @@ -88,8 +87,10 @@ public: Flag adoptFlag = INIT_NOTHING) { ProblemStat_::initialize(initFlag, adoptProblem, adoptFlag); - for (int i = 0; i < nComponents; ++i) - exactSolutions[i] = new DOFVector< double >(getFeSpace(i), "exact_solution"); + if (initFlag.isSet(INIT_EXACT_SOLUTION)) { + for (int i = 0; i < nComponents; ++i) + exactSolutions[i] = new DOFVector<double>(getFeSpace(i), "exact_solution"); + } } @@ -120,7 +121,8 @@ public: ////////////////////////////////////////////////////////////////////////////// void buildAfterCoarsen(AdaptInfo *adaptInfo, Flag flag, bool asmMatrix, bool asmVector) - { + { FUNCNAME_DBG("ExtendedProblemStat::buildAfterCoarsen()"); + ProblemStat_::buildAfterCoarsen(adaptInfo, flag, asmMatrix, asmVector); // update periodic data @@ -149,13 +151,19 @@ public: } // apply dirichlet boundary conditions - for (size_t k = 0; k < singularDirichletBC.size(); k++) - applyDirichletBC(singularDirichletBC[k], asmMatrix, asmVector); + size_t num_dbc = 0; + for (size_t k = 0; k < singularDirichletBC.size(); k++) { + if (applyDirichletBC(singularDirichletBC[k], asmMatrix, asmVector)) + ++num_dbc; + } + MSG_DBG("DBC applied at %d DOFs\n", num_dbc); // update solverMatrix if (asmMatrix && (singularDirichletBC.size() > 0 || manualPeriodicBC.size() > 0)) { solverMatrix.setMatrix(*getSystemMatrix()); } + + bc_dof.clear(); } @@ -191,6 +199,7 @@ public: void addDirichletBC(BoundaryType type, int row, int col, ValueContainer *values) { + MSG("addDirichletBC(%d, %d)\n", row, col); BoundaryTypeContainer *bound = new BoundaryTypeContainer(type); DirichletBcDataList.push_back( new DirichletBcData<BoundaryTypeContainer, ValueContainer>( @@ -345,13 +354,18 @@ public: protected: // traverse matrix rows and set unity row where dirichlet condition shall be applied. - void applyDirichletBC(size_t row_, size_t col_, + bool applyDirichletBC(size_t row_, size_t col_, DegreeOfFreedom idx, double value, bool asmMatrix = true, bool asmVector = true) { using namespace mtl; typedef DOFMatrix::base_matrix_type Matrix; - + + std::pair<BcDofType::iterator, bool> ret; + ret = bc_dof.insert(std::make_pair(std::make_pair(row_,col_),idx)); + if (!ret.second) + return false; // dof already inserted + Matrix::size_type idx_= idx; bool value1set = false; @@ -397,12 +411,13 @@ protected: (*getRhsVector(row_))[idx] = value; // set Dirichlet-Value at rhs-vector (*solution->getDOFVector(col_))[idx] = value; // set Dirichlet-value for solution component + return true; } - void applyDirichletBC(SingularDirichletBC &sbc, bool asmMatrix = true, bool asmVector = true) + bool applyDirichletBC(SingularDirichletBC &sbc, bool asmMatrix = true, bool asmVector = true) { - applyDirichletBC(sbc.row, sbc.col, sbc.idx, sbc.value, asmMatrix, asmVector); + return applyDirichletBC(sbc.row, sbc.col, sbc.idx, sbc.value, asmMatrix, asmVector); } @@ -444,6 +459,9 @@ protected: (*(getRhsVector(row)))[indices[i].second] += (*(getRhsVector(row)))[indices[i].first]; (*(getRhsVector(row)))[indices[i].first] = 0.0; } + + bc_dof.insert(std::make_pair(std::make_pair(row,row),indices[i].first)); + bc_dof.insert(std::make_pair(std::make_pair(row,row),indices[i].second)); } // add periodic associations of first and second indices, but only in the diagonal blocks @@ -538,6 +556,9 @@ private: // data for dirichlet boundary conditions std::vector<SingularDirichletBC> singularDirichletBC; std::vector<DirichletBcDataBase*> DirichletBcDataList; + + typedef std::set<std::pair<std::pair<size_t,size_t>,DegreeOfFreedom> > BcDofType; + BcDofType bc_dof; std::map<const FiniteElemSpace*, bool> feSpaceVisited; diff --git a/extensions/MeshFunction_Level.h b/extensions/MeshFunction_Level.h index 80b72a5ab37b742fd50f76f3a19bf0866884083c..61a33ba444d5a2ba17e115b59bdeb5b11d98b17e 100644 --- a/extensions/MeshFunction_Level.h +++ b/extensions/MeshFunction_Level.h @@ -19,11 +19,74 @@ #ifndef EXTENSIONS_MESH_FUNCTION_LEVEL_H #define EXTENSIONS_MESH_FUNCTION_LEVEL_H -#include "Refinement.h" - namespace AMDiS { namespace extensions { +/** \brief + * Abstract class that can be passed to RefinementLevel* as indicator where + * to refine the mesh up to which level. It is an AbstractFunction that + * overloads the operator() method to return a level or a meshsize depending + * on the coords/data passed to the operator. + * You can switch between meshsize and level with the methods hToLevel(double) and + * levelToH(int) + **/ +template<typename T, typename T2> +class MeshRefinementFunction : public AbstractFunction<T2, T> +{ +public: + + MeshRefinementFunction(Mesh* mesh_) : + AbstractFunction<T2, T>(0), + mesh(mesh_), + globalSize(0) + { + h0 = getMacroMeshSize(mesh); + reduction = 1.0 / std::sqrt(2.0); // if dim==2 + } + + int getGlobalSize() { return globalSize; } + + double meshSize() { return h0; } + + virtual void init(ElInfo* elInfo) {} + + virtual T2 operator()(const T &value) const { return globalSize; } + virtual T2 getLevel() const { return globalSize; } + + virtual double indicator(const T &value) const { return 1.0; } + +protected: + + int hToLevel(double h) { + int level = static_cast<int>(std::floor(std::log(h / h0) / std::log(reduction))); + return level; + } + + double levelToH(int level) { + double h = std::pow(reduction,level)*h0; + return h; + } + + double getMacroMeshSize(Mesh* mesh) { + FixVec<WorldVector<double>, VERTEX> coords = mesh->getMacroElement(0)->getCoord(); + double h = 0.0; + for (int i = 0; i < coords.size(); ++i) + for (int j = i + 1; j < coords.size(); ++j) + h = std::max(h, norm(coords[i]-coords[j])); + return h; + } + +protected: + + Mesh* mesh; + + int globalSize; + + double h0; + double reduction; +}; + + /** \brief * Base-Implementation of a MeshRefinementFunction for refinement of phase-field * interfaces. operator() must be overwritten in subclasses. Class provides @@ -36,7 +99,7 @@ class PhaseFieldRefinementBase : public MeshRefinementFunction<T, int> { public: - PhaseFieldRefinementBase(Mesh *mesh) : + PhaseFieldRefinementBase(Mesh *mesh, std::string name = "mesh->refinement") : MeshRefinementFunction<T, int>(mesh), lInner(10), lOuter(10), @@ -46,22 +109,22 @@ public: minOuterPhase(0.001), maxOuterPhase(0.999) { - Parameters::get("mesh->refinement->level in inner domain",lInner); - Parameters::get("mesh->refinement->level in outer domain",lOuter); - Parameters::get("mesh->refinement->level on interface",lInterface); + Parameters::get(name + "->level in inner domain",lInner); + Parameters::get(name + "->level in outer domain",lOuter); + Parameters::get(name + "->level on interface",lInterface); lInterface-= mesh->getMacroElementLevel(); lInner-= mesh->getMacroElementLevel(); lOuter-= mesh->getMacroElementLevel(); int local_globalSize = 10; - Parameters::get("mesh->refinement->initial level", local_globalSize); + Parameters::get(name + "->initial level", local_globalSize); MeshRefinementFunction<T, int>::globalSize = local_globalSize; - Parameters::get("mesh->refinement->min interface value",minPhase); - Parameters::get("mesh->refinement->max interface value",maxPhase); - Parameters::get("mesh->refinement->min outer interface value",minOuterPhase); - Parameters::get("mesh->refinement->max outer interface value",maxOuterPhase); + Parameters::get(name + "->min interface value",minPhase); + Parameters::get(name + "->max interface value",maxPhase); + Parameters::get(name + "->min outer interface value",minOuterPhase); + Parameters::get(name + "->max outer interface value",maxOuterPhase); } double meshSize() { return levelToH(MeshRefinementFunction<T, int>::globalSize); } @@ -87,7 +150,9 @@ class PhaseFieldRefinement : public PhaseFieldRefinementBase<double> { public: - PhaseFieldRefinement(Mesh* mesh_) : PhaseFieldRefinementBase<double>(mesh_) {}; + PhaseFieldRefinement(Mesh* mesh_, std::string name = "mesh->refinement") + : PhaseFieldRefinementBase<double>(mesh_, name) + { }; int operator()(const double& phase) const { int result= lOuter; @@ -114,13 +179,13 @@ public: class PhaseFieldCoordsRefinement : public PhaseFieldRefinementBase< std::pair<WorldVector<double>, double> > { public: - PhaseFieldCoordsRefinement(Mesh* mesh_, std::vector<WorldVector<double> > points_, double radius_) : - PhaseFieldRefinementBase< std::pair<WorldVector<double>, double> >(mesh_), - lPoints(14), - points(points_), - radius(radius_) + PhaseFieldCoordsRefinement(Mesh* mesh_, std::vector<WorldVector<double> > points_, double radius_, std::string name = "mesh->refinement") + : PhaseFieldRefinementBase< std::pair<WorldVector<double>, double> >(mesh_, name), + lPoints(14), + points(points_), + radius(radius_) { - Parameters::get("mesh->refinement->level on points",lPoints); + Parameters::get(name + "->level on points", lPoints); lPoints-= mesh->getMacroElementLevel(); } @@ -163,15 +228,14 @@ private: class CoordsRefinement : public MeshRefinementFunction< WorldVector<double>, int > { public: - CoordsRefinement(Mesh* mesh_, std::vector<WorldVector<double> > points_, double radius_) - : - MeshRefinementFunction< WorldVector<double>, int >(mesh_), - points(points_), - radius(radius_) + CoordsRefinement(Mesh* mesh_, std::vector<WorldVector<double> > points_, double radius_, std::string name = "mesh->refinement") + : MeshRefinementFunction< WorldVector<double>, int >(mesh_), + points(points_), + radius(radius_) { lInner= 15; lPoints = 20; - Parameters::get("mesh->refinement->level on points",lPoints); - Parameters::get("mesh->refinement->level in inner domain",lInner); + Parameters::get(name + "->level on points",lPoints); + Parameters::get(name + "->level in inner domain",lInner); lPoints-= mesh->getMacroElementLevel(); lInner-= mesh->getMacroElementLevel(); @@ -206,15 +270,14 @@ private: class PhaseFieldChRefinement : public PhaseFieldRefinementBase< std::vector<double> > { public: - PhaseFieldChRefinement(Mesh* mesh_) - : - PhaseFieldRefinementBase< std::vector<double> >(mesh_), - lInterfaceDomain(14) + PhaseFieldChRefinement(Mesh* mesh_, std::string name = "mesh->refinement") + : PhaseFieldRefinementBase< std::vector<double> >(mesh_, name), + lInterfaceDomain(14) { - Parameters::get("mesh->refinement->level on domain interface",lInterfaceDomain); + Parameters::get(name + "->level on domain interface",lInterfaceDomain); lInterfaceDomain-= mesh->getMacroElementLevel(); - Parameters::get("mesh->refinement->initial level", globalSize); + Parameters::get(name + "->initial level", globalSize); } int operator()(const std::vector<double>& phases) const @@ -254,8 +317,9 @@ class SignedDistRefinementBase : public MeshRefinementFunction<T, int> { public: - SignedDistRefinementBase(Mesh *mesh) : + SignedDistRefinementBase(Mesh *mesh, std::string name = "mesh->refinement") : MeshRefinementFunction<T, int>(mesh), + name(name), lInner(10), lOuter(10), lInterface(14), @@ -263,26 +327,27 @@ public: fadeOutWidth(0.0), signInInnerDomain(-1.0) { - Parameters::get("mesh->refinement->level in inner domain",lInner); - Parameters::get("mesh->refinement->level in outer domain",lOuter); - Parameters::get("mesh->refinement->level on interface",lInterface); + Parameters::get(name + "->level in inner domain",lInner); + Parameters::get(name + "->level in outer domain",lOuter); + Parameters::get(name + "->level on interface",lInterface); lInterface-= mesh->getMacroElementLevel(); lInner-= mesh->getMacroElementLevel(); lOuter-= mesh->getMacroElementLevel(); int local_globalSize = 10; - Parameters::get("mesh->refinement->initial level", local_globalSize); + Parameters::get(name + "->initial level", local_globalSize); MeshRefinementFunction<T, int>::globalSize = local_globalSize; - Parameters::get("mesh->refinement->interface width",interfaceWidth); - Parameters::get("mesh->refinement->fade out width",fadeOutWidth); - Parameters::get("mesh->refinement->sign in inner domain",signInInnerDomain); + Parameters::get(name + "->interface width",interfaceWidth); + Parameters::get(name + "->fade out width",fadeOutWidth); + Parameters::get(name + "->sign in inner domain",signInInnerDomain); } double meshSize() { return levelToH(MeshRefinementFunction<T, int>::globalSize); } protected: + std::string name; int lInner; int lOuter; @@ -302,7 +367,7 @@ class SignedDistRefinement : public SignedDistRefinementBase<double> { public: - SignedDistRefinement(Mesh* mesh_) : SignedDistRefinementBase<double>(mesh_) {}; + SignedDistRefinement(Mesh* mesh_, std::string name = "mesh->refinement") : SignedDistRefinementBase<double>(mesh_, name) {}; int operator()(const double& dist) const { int result= lOuter; @@ -324,11 +389,10 @@ public: class ESIndicator : public MeshRefinementFunction< std::vector<double>, int > { public: - ESIndicator(Mesh* mesh_) - : - MeshRefinementFunction< std::vector<double>, int >(mesh_) + ESIndicator(Mesh* mesh_, std::string name = "mesh->refinement") + : MeshRefinementFunction< std::vector<double>, int >(mesh_) { - Parameters::get("mesh->refinement->initial level", globalSize); + Parameters::get(name + "->initial level", globalSize); } int operator()(const std::vector<double>& means) const diff --git a/extensions/MeshIndicator.h b/extensions/MeshIndicator.h index 2d9332284ffffd52945420056bf2067e33e29fd2..fd3ea21115bb70b7cae9391dfc29940011187208 100644 --- a/extensions/MeshIndicator.h +++ b/extensions/MeshIndicator.h @@ -237,7 +237,7 @@ namespace tools { template<typename T1, typename T2> - typename ProductType<T1,T2>::type integrate_VecTimesCoords(const DOFVector<T1> &vec, + typename traits::mult_type<T1,T2>::type integrate_VecTimesCoords(const DOFVector<T1> &vec, AbstractFunction<T2, WorldVector<double> > *fct, MeshIndicator *meshIndicator) { FUNCNAME("integrate_VecTimesCoords()"); @@ -245,7 +245,7 @@ namespace tools { TEST_EXIT(fct)("No function defined!\n"); TEST_EXIT(meshIndicator)("No MeshIndicator defined!\n"); - typedef typename ProductType<T1,T2>::type TOut; + typedef typename traits::mult_type<T1,T2>::type TOut; const FiniteElemSpace *feSpace = vec.getFeSpace(); Mesh *mesh = feSpace->getMesh(); diff --git a/extensions/RefineFunctions.h b/extensions/RefineFunctions.h new file mode 100644 index 0000000000000000000000000000000000000000..d073ad4d5d14f5312eefe1a0e5c96e7b779e47ff --- /dev/null +++ b/extensions/RefineFunctions.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * 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 EXTENSIONS_REFINE_FUNCTIONS_H +#define EXTENSIONS_REFINE_FUNCTIONS_H + +#include <vector> +#include <string> + +#include "Global.h" +#include "Mesh.h" +#include "Initfile.h" +#include "operations/functors.hpp" + +namespace AMDiS { namespace extensions { + + struct PhaseFieldRefineFct : public FunctorBase + { + typedef int result_type; + + PhaseFieldRefineFct(std::string name, Mesh* mesh) + : lInner(10), + lOuter(10), + lInterface(14), + minPhase(0.05), + maxPhase(0.95), + minOuterPhase(0.001), + maxOuterPhase(0.999) + { + Parameters::get(name + "->level in inner domain", lInner); + Parameters::get(name + "->level in outer domain", lOuter); + Parameters::get(name + "->level on interface", lInterface); + + Parameters::get(name + "->min interface value", minPhase); + Parameters::get(name + "->max interface value", maxPhase); + Parameters::get(name + "->min outer interface value", minOuterPhase); + Parameters::get(name + "->max outer interface value", maxOuterPhase); + + lInterface-= mesh->getMacroElementLevel(); + lInner-= mesh->getMacroElementLevel(); + lOuter-= mesh->getMacroElementLevel(); + } + + inline int operator()(double phase) const + { + int result = lOuter; + if (minPhase < phase && phase < maxPhase) + result = lInterface; // auf dem Interface + else if (phase > minOuterPhase && phase <= minPhase) + result = std::max(lOuter, static_cast<int>(std::floor((lOuter+lInterface)/2.0))); + else if (phase < maxOuterPhase && phase >= maxPhase) + result = std::max(lInner, static_cast<int>(std::floor((lInner+lInterface)/2.0))); + else if (phase > (minPhase+maxPhase)/2.0) + result = lInner; + return result; + } + + protected: + int lInner; + int lOuter; + int lInterface; + + double minPhase; + double maxPhase; + double minOuterPhase; + double maxOuterPhase; + }; + +} } + +#endif \ No newline at end of file diff --git a/extensions/RefineOperations.h b/extensions/RefineOperations.h new file mode 100644 index 0000000000000000000000000000000000000000..dc1554abf501af7972fe6cc6b6b4304794127268 --- /dev/null +++ b/extensions/RefineOperations.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * 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 EXTENSIONS_REFINE_OPERATION_H +#define EXTENSIONS_REFINE_OPERATION_H + +#include <vector> +#include "AMDiS_fwd.h" + +namespace AMDiS { namespace extensions { + + /// Operations performed before and after refinement/ coarsening + struct StandardRefineOperation + { + virtual ~StandardRefineOperation() {}; + virtual void beforeRefine(AdaptInfo* adaptInfo, Flag markFlag) {} + virtual void beforeCoarsen(AdaptInfo* adaptInfo, Flag markFlag) {} + virtual void afterCoarsen(AdaptInfo* adaptInfo, Flag markFlag) {} + }; + + /// vector of operations performed before and after refinement/ coarsening + struct CoupledRefineOperation : public StandardRefineOperation + { + CoupledRefineOperation(std::vector<StandardRefineOperation*> operations_) + : operations(operations_) {} + + void beforeRefine(AdaptInfo* adaptInfo, Flag markFlag) override + { + for (size_t i = 0; i < operations.size(); i++) + operations[i]->beforeRefine(adaptInfo, markFlag); + } + + void beforeCoarsen(AdaptInfo* adaptInfo, Flag markFlag) override + { + for (size_t i = 0; i < operations.size(); i++) + operations[i]->beforeCoarsen(adaptInfo, markFlag); + } + void afterCoarsen(AdaptInfo* adaptInfo, Flag markFlag) override + { + for (size_t i = 0; i < operations.size(); i++) + operations[i]->afterCoarsen(adaptInfo, markFlag); + } + + protected: + std::vector<StandardRefineOperation*> operations; + }; + +} } + +#endif diff --git a/extensions/Refinement.h b/extensions/Refinement.h index 9dadce2ca5553b863b334e86a2b32f33e030a1ca..282cdf4ef5bcc45b5dda291b36a15bec03ad9e51 100644 --- a/extensions/Refinement.h +++ b/extensions/Refinement.h @@ -20,111 +20,11 @@ #define EXTENSIONS_REFINEMENT_H #include "ElementFunction.h" +#include "RefineOperations.h" +#include "MeshFunction_Level.h" namespace AMDiS { namespace extensions { - -/** \brief - * Abstract class that can be passed to RefinementLevel* as indicator where - * to refine the mesh up to which level. It is an AbstractFunction that - * overloads the operator() method to return a level or a meshsize depending - * on the coords/data passed to the operator. - * You can switch between meshsize and level with the methods hToLevel(double) and - * levelToH(int) - **/ -template<typename T, typename T2> -class MeshRefinementFunction : public AbstractFunction<T2, T> -{ -public: - - MeshRefinementFunction(Mesh* mesh_) : - AbstractFunction<T2, T>(0), - mesh(mesh_), - globalSize(0) - { - h0 = getMacroMeshSize(mesh); - reduction = 1.0 / std::sqrt(2.0); // if dim==2 - } - - int getGlobalSize() { return globalSize; } - - double meshSize() { return h0; } - - virtual void init(ElInfo* elInfo) {} - - virtual T2 operator()(const T &value) const { return globalSize; } - virtual T2 getLevel() const { return globalSize; } - - virtual double indicator(const T &value) const { return 1.0; } - -protected: - - int hToLevel(double h) { - int level = static_cast<int>(std::floor(std::log(h / h0) / std::log(reduction))); - return level; - } - - double levelToH(int level) { - double h = std::pow(reduction,level)*h0; - return h; - } - - double getMacroMeshSize(Mesh* mesh) { - FixVec<WorldVector<double>, VERTEX> coords = mesh->getMacroElement(0)->getCoord(); - double h = 0.0; - for (int i = 0; i < coords.size(); ++i) - for (int j = i + 1; j < coords.size(); ++j) - h = std::max(h, norm(coords[i]-coords[j])); - return h; - } - -protected: - - Mesh* mesh; - - int globalSize; - - double h0; - double reduction; -}; - -/// Operations performed before and after refinement/ coarsening -struct StandardRefineOperation -{ - virtual ~StandardRefineOperation() {}; - virtual void beforeRefine(AdaptInfo* adaptInfo, Flag markFlag) {} - virtual void beforeCoarsen(AdaptInfo* adaptInfo, Flag markFlag) {} - virtual void afterCoarsen(AdaptInfo* adaptInfo, Flag markFlag) {} -}; - -/// vector of operations performed before and after refinement/ coarsening -struct CoupledRefineOperation : public StandardRefineOperation -{ - CoupledRefineOperation(std::vector<StandardRefineOperation*> operations_) - : operations(operations_) {} - - void beforeRefine(AdaptInfo* adaptInfo, Flag markFlag) override - { - for (size_t i = 0; i < operations.size(); i++) - operations[i]->beforeRefine(adaptInfo, markFlag); - } - - void beforeCoarsen(AdaptInfo* adaptInfo, Flag markFlag) override - { - for (size_t i = 0; i < operations.size(); i++) - operations[i]->beforeCoarsen(adaptInfo, markFlag); - } - void afterCoarsen(AdaptInfo* adaptInfo, Flag markFlag) override - { - for (size_t i = 0; i < operations.size(); i++) - operations[i]->afterCoarsen(adaptInfo, markFlag); - } - -protected: - std::vector<StandardRefineOperation*> operations; -}; - - /** \brief * Base class for Refinement structure to perform local anisotropic refinement */ @@ -140,6 +40,7 @@ public: adaptInfo(NULL), refineOperation(NULL), numRefinements0(15), + finished(true), globalRefined(false) { FUNCNAME("RefinementLevel::RefinementLevel()"); @@ -167,13 +68,26 @@ public: refineOperation = new StandardRefineOperation; } - virtual ~RefinementLevel() { + virtual ~RefinementLevel() + { + finalize(); + delete coarseningManager; delete refinementManager; if (refineOperation) delete refineOperation; } + void finalize() + { + if (!finished) { + #ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(); + #endif + } + finished = true; + } + void setRefineOperation(AdaptInfo* adaptInfo_, StandardRefineOperation* refineOperation_) { @@ -319,6 +233,8 @@ public: bool refineMesh(Flag markFlag, bool onlyRefine) { + finished = false; + int oldSize = mesh->getNumberOfVertices(); refineOperation->beforeRefine(adaptInfo, markFlag); if (markFlag.isSet(1)) @@ -355,6 +271,7 @@ protected: int numRefinements; int numRefinements0; + bool finished; bool globalRefined; }; @@ -372,6 +289,7 @@ public: adaptInfo(NULL), refineOperation(NULL), numRefinements0(15), + finished(true), globalRefined(false) { FUNCNAME("RefinementLevel::RefinementLevel()"); @@ -398,13 +316,26 @@ public: refineOperation = new StandardRefineOperation; } - virtual ~RefinementLocal() { + virtual ~RefinementLocal() + { + finalize(); + delete coarseningManager; delete refinementManager; if (refineOperation) delete refineOperation; } + void finalize() + { + if (!finished) { + #ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(); + #endif + } + finished = true; + } + void setRefineOperation(AdaptInfo* adaptInfo_, StandardRefineOperation* refineOperation_) { @@ -579,6 +510,8 @@ public: bool refineMesh(Flag markFlag, bool onlyRefine) { + finished = false; + int oldSize = mesh->getNumberOfVertices(); refineOperation->beforeRefine(adaptInfo, markFlag); if (markFlag.isSet(1)) @@ -611,6 +544,7 @@ protected: int numRefinements; int numRefinements0; + bool finished; bool globalRefined; bool onlyRefine; }; diff --git a/extensions/RefinementExpression.h b/extensions/RefinementExpression.h new file mode 100644 index 0000000000000000000000000000000000000000..09837c1133f3d3d54c2fd14d540998b2c6fe5c75 --- /dev/null +++ b/extensions/RefinementExpression.h @@ -0,0 +1,355 @@ +/****************************************************************************** + * + * 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 EXTENSIONS_REFINEMENT_EXPRESSION_H +#define EXTENSIONS_REFINEMENT_EXPRESSION_H + +#include "ProblemStat.h" +#include "ElementFunction.h" +#include "RefineFunctions.h" +#include "RefineOperations.h" +#include "Expressions.h" + +namespace AMDiS { namespace extensions { + + +/** \brief + * Base class for Refinement structure to perform local anisotropic refinement + */ +class RefinementExpression +{ +public: + + RefinementExpression(ProblemStat& prob, int component = 0, bool doCalcMeshSize_ = false) + : mesh(prob.getMesh(component)), + adaptInfo(NULL), + refineOperation(NULL), + numRefinements0(15), + doCalcMeshSize(doCalcMeshSize_), + onlyRefine(false), + finished(true), + refinementManagerCreated(false) + { + coarseningManager = prob.getCoarseningManager(); + refinementManager = prob.getRefinementManager(); + numRefinements = numRefinements0; + refineOperation = new StandardRefineOperation; + } + + RefinementExpression(Mesh *mesh_, bool doCalcMeshSize_ = false) + : mesh(mesh_), + adaptInfo(NULL), + refineOperation(NULL), + numRefinements0(15), + doCalcMeshSize(doCalcMeshSize_), + onlyRefine(false), + finished(true), + refinementManagerCreated(true) + { + FUNCNAME("RefinementExpression::RefinementLevel()"); + + switch (mesh->getDim()) { + case 1: + coarseningManager = new CoarseningManager1d(); + refinementManager = new RefinementManager1d(); + break; + case 2: + coarseningManager = new CoarseningManager2d(); + refinementManager = new RefinementManager2d(); + break; + case 3: + coarseningManager = new CoarseningManager3d(); + refinementManager = new RefinementManager3d(); + break; + default: + ERROR_EXIT("invalid dim!\n"); + } + + numRefinements = numRefinements0; + + refineOperation = new StandardRefineOperation; + } + + virtual ~RefinementExpression() + { + finalize(); + + if (refinementManagerCreated) { + delete coarseningManager; + delete refinementManager; + } + + if (refineOperation) + delete refineOperation; + } + + void finalize() + { + if (!finished) { + #ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::MeshDistributor::globalMeshDistributor->checkMeshChange(); + #endif + } + finished = true; + } + + template <typename Term> + bool refine(Term term) + { + FUNCNAME("RefinementExpression::refine()"); + + double minH = 0.0, maxH = 1.0; + int minLevel = 100, maxLevel = 0; + int oldMeshChangeIdx = mesh->getChangeIndex(); + + bool meshChanged = true; + Flag markFlag; + int oldNr = 0, oldOldNr = 0, i = 0; + while (meshChanged && i < numRefinements) { + markElements(term, markFlag); + meshChanged = refineMesh(markFlag, onlyRefine); + + // compare nr of vertices + int nr = mesh->getNumberOfVertices(); + meshChanged = meshChanged && oldOldNr!=nr && oldNr!=nr; + + if (meshChanged) { + if (doCalcMeshSize) { + calcMeshSizes(minH, maxH, minLevel, maxLevel, false); + MSG("(local) mesh sizes: [%f, %f], Vs: %d, ELs: %d\n", + minH, maxH, nr, mesh->getNumberOfElements()); + } else { + MSG("(local) #Vertics: %d, #Elements: %d\n", nr, mesh->getNumberOfElements()); + } + } + + oldOldNr = oldNr; + oldNr = nr; + i++; + } + + 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); + + return oldMeshChangeIdx != mesh->getChangeIndex(); + } + + + template <typename Term> + bool refine(int numRefinements_, Term term, bool onlyRefine_= false) + { + numRefinements = numRefinements_; + setOnlyRefine(onlyRefine_); + bool refined = refine(term); + numRefinements = numRefinements0; + return refined; + } + + + template <int N, typename Term> + bool refine(Term term, bool onlyRefine_= false) + { + numRefinements = N; + setOnlyRefine(onlyRefine_); + bool refined = refine(term); + numRefinements = numRefinements0; + return refined; + } + + + template<typename Term> + void markElements(Term term, Flag &markFlag) + { + bool elMarkRefine = false, elMarkCoarsen = false; + + GenericOperatorTerm<Term> ot(term); + + int dim = mesh->getDim(); + Quadrature* quad = Quadrature::provideQuadrature(dim, 0); // 1 point in the center + + Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_GRD_LAMBDA; + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag); + while (elInfo) { + term.initElement(&ot, elInfo, NULL, quad); + + int refineLevel = boost::numeric_cast<int>(term(0)); // eval expression + int oldLevel = elInfo->getLevel(); + elInfo->getElement()->setMark( calcMark(refineLevel, oldLevel) ); + + elMarkRefine |= elInfo->getElement()->getMark() == 1; + elMarkCoarsen |= elInfo->getElement()->getMark() == -1; + elInfo = stack.traverseNext(elInfo); + } + + markFlag= 0; + if(elMarkRefine) + markFlag = 1; + if(elMarkCoarsen) + markFlag|= 2; + } + + int getNumRefinements() + { + return numRefinements; + } + + void calcMeshSizes(double& minH, double& maxH, int& minLevel, int& maxLevel, bool allReduce = false) + { + FixVec<WorldVector<double>, VERTEX> coords(mesh->getDim(), NO_INIT); + + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); + minH = 1e15; maxH = 0.0; + int k = 0; + minLevel = 100; + maxLevel = 0; + while (elInfo) { + maxLevel = std::max(maxLevel,elInfo->getLevel()); + minLevel = std::min(minLevel,elInfo->getLevel()); + coords = elInfo->getCoords(); + double h = 0.0; + for (int i = 0; i < coords.size(); i++) { + for (int j = 0; j < coords.size(); 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); + k++; + } + minLevel += mesh->getMacroElementLevel(); + maxLevel += mesh->getMacroElementLevel(); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (allReduce) { + Parallel::mpi::globalMin(minH); + Parallel::mpi::globalMax(maxH); + Parallel::mpi::globalMin(minLevel); + Parallel::mpi::globalMax(maxLevel); + } +#endif + } + + + double calcMeshSize(ElInfo *elInfo, bool allReduce = false) + { + FixVec<WorldVector<double>, VERTEX> coords(mesh->getDim(), NO_INIT); + coords = elInfo->getCoords(); + double h = 0.0; + for (int i = 0; i < coords.size(); i++) { + for (int j = 0; j < coords.size(); j++) { + if (i != j) + h = std::max(h,norm(coords[i]-coords[j])); + } + } +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (allReduce) + Parallel::mpi::globalMax(h); +#endif + + return h; + } + + + int calcMark(double refineH, double currentH) + { + return (refineH < currentH ? + 1 : (refineH > currentH * (mesh->getDim() == 1 ? + 2.0 : (mesh->getDim() == 2 ? + std::sqrt(2.0) : + std::sqrt(2.0)/2.0 + 0.5)) ? + -1 : + 0)); + } + + + int calcMark(int refineLevel, int currentLevel) + { + int levelDiff = refineLevel - currentLevel; + return (levelDiff > 0 ? 1 : (levelDiff < 0 ? -1 : 0)); + } + + + bool refineMesh(Flag markFlag, bool onlyRefine) + { + finished = false; + + int oldSize = mesh->getNumberOfVertices(); + refineOperation->beforeRefine(adaptInfo, markFlag); + if (markFlag.isSet(1)) + refinementManager->refineMesh(mesh); + + refineOperation->beforeCoarsen(adaptInfo, markFlag); + if (markFlag.isSet(2) && !onlyRefine) + coarseningManager->coarsenMesh(mesh); + + refineOperation->afterCoarsen(adaptInfo, markFlag); + + if (markFlag.isSet(1) || markFlag.isSet(2)) { + int newSize = mesh->getNumberOfVertices(); + if (oldSize != newSize) + return true; + } + return false; + } + + void setRefineOperation(AdaptInfo* adaptInfo_, + StandardRefineOperation* refineOperation_) + { + if (refineOperation) + delete refineOperation; + + adaptInfo = adaptInfo_; + refineOperation = refineOperation_; + } + + void setOnlyRefine(bool onlyRefine_) + { + onlyRefine = onlyRefine_; + } + + void setCalcMeshSize(bool calc) { doCalcMeshSize = calc; } + + RefinementManager* getRefinementManager() { return refinementManager; } + CoarseningManager* getCoarseningManager() { return coarseningManager; } + +protected: + + Mesh* mesh; + RefinementManager* refinementManager; + CoarseningManager* coarseningManager; + + AdaptInfo* adaptInfo; + StandardRefineOperation* refineOperation; + + int numRefinements; + int numRefinements0; + + bool doCalcMeshSize; + bool onlyRefine; + bool finished; + bool refinementManagerCreated; +}; + +} } + +#endif // EXTENSIONS_REFINEMENT_EXPRESSION_H diff --git a/extensions/base_problems/CahnHilliard.h b/extensions/base_problems/CahnHilliard.h index e22f54b0ff8ba93d166d4f4b44c8fa3c20c4d863..a178877a83da36c69c563541d12870bd00b619e4 100644 --- a/extensions/base_problems/CahnHilliard.h +++ b/extensions/base_problems/CahnHilliard.h @@ -34,7 +34,7 @@ namespace detail { { public: // definition of types - typedef BaseProblem<ProblemStatType> super; + typedef BaseProblem<ProblemStatType> super; typedef CahnHilliard<ProblemStatType> self; public: // public methods diff --git a/extensions/base_problems/CahnHilliard.hh b/extensions/base_problems/CahnHilliard.hh index 2e8835a57fcfe02f1345208efcb09a486f515362..7062310d89f6bf1fd58a9dbafa31bfba604365f5 100644 --- a/extensions/base_problems/CahnHilliard.hh +++ b/extensions/base_problems/CahnHilliard.hh @@ -21,200 +21,201 @@ #include "HL_SignedDistTraverse.h" #include "Recovery.h" -#include "GenericOperatorTerm.h" +#include "Expressions.h" namespace AMDiS { namespace base_problems { namespace detail { - -template<typename P> -CahnHilliard<P>::CahnHilliard(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; -} - - -template<typename P> -void CahnHilliard<P>::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); - self::prob->getSolution()->getDOFVector(0)->interpol(new Plane(a, dir)); - } - else if (initialInterface == 1) { - /// schraege Linie - double theta = m_pi/4.0; - self::prob->getSolution()->getDOFVector(0)->interpol(new PlaneRotation(0.0, theta, 1.0)); - transformDOFInterpolation(self::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); - self::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); - self::prob->getSolution()->getDOFVector(0)->interpol(new Plane(a, -1.0)); - transformDOFInterpolation(self::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); - self::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); - self::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(self::prob->getSolution()->getDOFVector(0)); + template<typename P> + CahnHilliard<P>::CahnHilliard(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 - HL_SignedDistTraverse reinit("reinit", self::getMesh()->getDim()); - reinit.calcSignedDistFct(adaptInfo, &tmp); + // type of double well: 0= [0,1], 1= [-1,1] + Parameters::get(name_ + "->double-well type", doubleWell); -#ifndef HAVE_PARALLEL_DOMAIN_AMDIS - Recovery recovery(L2_NORM, 1); - recovery.recoveryUh(&tmp, *self::prob->getSolution()->getDOFVector(0)); -#else - self::prob->getSolution()->getDOFVector(0)->interpol(&tmp); -#endif + Parameters::get(name_ + "->use reinit", useReinit); + + // transformation of the parameters + minusEps = -eps; + epsInv = 1.0/eps; + minusEpsInv = -epsInv; + epsSqr = sqr(eps); + minusEpsSqr = -epsSqr; + } + + + template<typename P> + void CahnHilliard<P>::solveInitialProblem(AdaptInfo *adaptInfo) + { + using namespace AMDiS::extensions; + Flag initFlag = self::initDataFromFile(adaptInfo); + + DOFVector<double>* c = self::prob->getSolution()->getDOFVector(1); + + if (!initFlag.isSet(DATA_ADOPTED)) { + int initialInterface = 0; + Parameters::get(self::name + "->initial interface", initialInterface); + double initialEps = eps; + Parameters::get(self::name + "->initial epsilon", initialEps); + + if (initialInterface == 0) { + /// horizontale Linie + double a= 0.0, dir= -1.0; + Parameters::get(self::name + "->line->pos", a); + Parameters::get(self::name + "->line->direction", dir); + c->interpol(new Plane(a, dir)); + } + else if (initialInterface == 1) { + /// schraege Linie + double theta = m_pi/4.0; + c->interpol(new PlaneRotation(0.0, theta, 1.0)); + transformDOFInterpolation(c, new PlaneRotation(0.0, -theta, -1.0), new AMDiS::Min<double>); + } + else if (initialInterface == 2) { + /// Ellipse + double a= 1.0, b= 1.0; + Parameters::get(self::name + "->ellipse->a", a); + Parameters::get(self::name + "->ellipse->b", b); + c->interpol(new Ellipse(a,b)); + } + else if (initialInterface == 3) { + /// zwei horizontale Linien + double a= 0.75, b= 0.375; + Parameters::get(self::name + "->lines->pos1", a); + Parameters::get(self::name + "->lines->pos2", b); + c->interpol(new Plane(a, -1.0)); + transformDOFInterpolation(c, new Plane(b, 1.0), new AMDiS::Max<double>); + } + else if (initialInterface == 4) { + /// Kreis + double radius= 1.0; + Parameters::get(self::name + "->kreis->radius", radius); + c->interpol(new Circle(radius)); + } else if (initialInterface == 5) { + /// Rechteck + double width = 0.5; + double height = 0.3; + WorldVector<double> center; center.set(0.5); + Parameters::get(self::name + "->rectangle->width", width); + Parameters::get(self::name + "->rectangle->height", height); + Parameters::get(self::name + "->rectangle->center", center); + c->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(c); + + HL_SignedDistTraverse reinit("reinit", self::getMesh()->getDim()); + reinit.calcSignedDistFct(adaptInfo, &tmp); + + #ifndef HAVE_PARALLEL_DOMAIN_AMDIS + Recovery recovery(L2_NORM, 1); + recovery.recoveryUh(&tmp, *c); + #else + c->interpol(&tmp); + #endif + } + + + /// create phase-field from signed-dist-function + if (doubleWell == 0) { + forEachDOF(c, new SignedDistToPhaseField(initialEps)); + } else { + forEachDOF(c, new SignedDistToCh(initialEps)); + } } + } + + template<typename P> + void CahnHilliard<P>::fillOperators() + { + const FiniteElemSpace* feSpace0 = self::prob->getFeSpace(0); + const FiniteElemSpace* feSpace1 = self::prob->getFeSpace(1); + DOFVector<double>* c = self::prob->getSolution()->getDOFVector(1); - /// create phase-field from signed-dist-function + // -nabla*(grad(c)) + Operator *opChL = new Operator(feSpace0, feSpace1); + addSOT(opChL, 1.0); + + // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 + Operator *opChLM = new Operator(feSpace1, feSpace0); + if (useMobility) { + if (doubleWell == 0) + addSOT(opChLM, function_(MobilityCH0_(gamma), valueOf(c)) ); + else + addSOT(opChLM, function_(MobilityCH1_(gamma), valueOf(c)) ); + } else + addSOT(opChLM, gamma ); + + // -2*c_old^3 + 3/2*c_old^2 + Operator *opChWExpl = new Operator(feSpace0, feSpace1); + Operator *opChWImpl = new Operator(feSpace0, feSpace1); if (doubleWell == 0) { - forEachDOF(self::prob->getSolution()->getDOFVector(0), - new SignedDistToPhaseField(initialEps)); + 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 { - forEachDOF(self::prob->getSolution()->getDOFVector(0), - new SignedDistToCh(initialEps)); + addZOT(opChWExpl, -2.0*pow<3>(valueOf(c))); + addZOT(opChWImpl, -3.0*pow<2>(valueOf(c)) + 1.0); } - } -} - -template<typename P> -void CahnHilliard<P>::fillOperators() -{ - const FiniteElemSpace* feSpace0 = self::prob->getFeSpace(0); - const FiniteElemSpace* feSpace1 = self::prob->getFeSpace(1); - - DOFVector<double>* c = self::prob->getSolution()->getDOFVector(0); -// DOFVector<double>* mu = self::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_(gamma), valueOf(c)) ); - else - addSOT(opChLM, function_(MobilityCH1_(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] + // ---------------------------------------------------------------------- + self::prob->addMatrixOperator(*opChWImpl, 0, 1); /// < -3*phi*c*c_old^2 , psi > + self::prob->addMatrixOperator(*opChL, 0, 1, &minusEpsSqr, &minusEpsSqr); /// < -eps^2*phi*grad(c) , grad(psi) > + + // . . . vectorOperators . . . . . . . . . . . . . . . + self::prob->addVectorOperator(*opChWExpl, 0); /// < -2*phi*c_old^3 , psi > + + Operator *opM01new = new Operator(feSpace0, feSpace0); + addZOT(opM01new, 1.0); + self::prob->addMatrixOperator(*opM01new, 0, 0); /// < phi*mu , psi > + + // dt(c) = laplace(mu) - u*grad(c) + // ----------------------------------- + Operator *opM10new = new Operator(feSpace1, feSpace1); + addZOT(opM10new, 1.0); + self::prob->addMatrixOperator(*opM10new, 1, 1); /// < phi*c/tau , psi > + self::prob->addMatrixOperator(*opChLM, 1, 0, self::getTau(), self::getTau()); /// < phi*grad(mu) , grad(psi) > + + // . . . vectorOperators . . . . . . . . . . . . . . . + Operator *opChMold = new Operator(feSpace1, feSpace1); + addZOT(opChMold, valueOf(c)); + self::prob->addVectorOperator(*opChMold, 1); /// < phi*c^old/tau , psi > } - - // mu + eps^2*laplace(c) + c - 3*(c_old^2)*c = -2*c_old^3 [+ BC] - // ---------------------------------------------------------------------- - self::prob->addMatrixOperator(*opChWImpl, 0, 0); /// < -3*phi*c*c_old^2 , psi > - self::prob->addMatrixOperator(*opChL, 0, 0, &minusEpsSqr, &minusEpsSqr); /// < -eps^2*phi*grad(c) , grad(psi) > - // . . . vectorOperators . . . . . . . . . . . . . . . - self::prob->addVectorOperator(*opChWExpl, 0); /// < -2*phi*c_old^3 , psi > - - Operator *opM01new = new Operator(feSpace0, feSpace1); - addZOT(opM01new, 1.0); - self::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); - self::prob->addMatrixOperator(*opM10new, 1, 0, self::getInvTau(), self::getInvTau()); /// < phi*c/tau , psi > - self::prob->addMatrixOperator(*opChLM, 1, 1); /// < phi*grad(mu) , grad(psi) > - // . . . vectorOperators . . . . . . . . . . . . . . . - Operator *opChMold = new Operator(feSpace1, feSpace0); - addZOT(opChMold, valueOf(c)); - self::prob->addVectorOperator(*opChMold, 1, self::getInvTau(), self::getInvTau()); /// < phi*c^old/tau , psi > -} - - -template<typename P> -void CahnHilliard<P>::finalizeData() -{ -// self::setAssembleMatrixOnlyOnce_butTimestepChange(0,1); -// self::setAssembleMatrixOnlyOnce_butTimestepChange(1,0); -// if (!useMobility) -// self::setAssembleMatrixOnlyOnce_butTimestepChange(1,1); -} + + template<typename P> + void CahnHilliard<P>::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/base_problems/CahnHilliardNavierStokes_TwoPhase.cc b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc index 6743b4ea2669d3b0c0754c4247febd913542a1f5..b3a5959496aae52ec6b12f93d20e86717cae03a9 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc @@ -19,6 +19,7 @@ #include "SignedDistFunctors.h" #include "PhaseFieldConvert.h" #include "POperators.h" +#include "Expressions.h" namespace AMDiS { namespace base_problems { @@ -79,7 +80,7 @@ CahnHilliardNavierStokes_TwoPhase::CahnHilliardNavierStokes_TwoPhase(const std:: // Parameters for NS-Coupling // cahn-hiliard-force: sigma*mu*grad(c) Initfile::get(name + "->sigma", sigma); // surface tension - surfaceTension = sigma*3.0/(2.0*sqrt(2.0)) / eps; + surfaceTension = sigma*3.0/(2.0*std::sqrt(2.0)) / eps; MSG("surface tension: %e\n", surfaceTension); @@ -149,6 +150,8 @@ void CahnHilliardNavierStokes_TwoPhase::fillOperators() // variable order: // (c, mu, u0, u1 [, u2], p) + DOFVector<double>* c = prob->getSolution()->getDOFVector(0); + WorldVector<DOFVector<double>* > vel; for (size_t i = 0; i < dow; i++) vel[i] = prob->getSolution()->getDOFVector(2+i); @@ -158,26 +161,22 @@ void CahnHilliardNavierStokes_TwoPhase::fillOperators() // ----------------------------------- /// < phi*c/tau , psi > Operator *opChMnew = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); - opChMnew->addZeroOrderTerm(new Simple_ZOT); - prob->addMatrixOperator(*opChMnew, 0, 0, getInvTau()); + addZOT(opChMnew, 1.0 ); + prob->addMatrixOperator(*opChMnew, 0, 0, getInvTau(), getInvTau()); /// < phi*c^old/tau , psi > Operator *opChMold = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); - opChMold->addZeroOrderTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(0))); - prob->addVectorOperator(*opChMold,0, getInvTau()); + addZOT(opChMold, valueOf(c) ); + prob->addVectorOperator(*opChMold,0, getInvTau(), getInvTau()); /// < phi*grad(mu) , grad(psi) > // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 Operator *opChLM = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); if (useMobility) { if (doubleWell == 0) - opChLM->addSecondOrderTerm(new VecAtQP_SOT( - prob->getSolution()->getDOFVector(0), - new MobilityCH0(gamma))); + addSOT(opChLM, function_(wrap(new MobilityCH0(gamma)), valueOf(c)) ); else - opChLM->addSecondOrderTerm(new VecAtQP_SOT( - prob->getSolution()->getDOFVector(0), - new MobilityCH1(gamma))); + addSOT(opChLM, function_(wrap(new MobilityCH1(gamma)), valueOf(c)) ); } else opChLM->addSecondOrderTerm(new Simple_SOT(gamma)); prob->addMatrixOperator(*opChLM, 0, 1); @@ -185,9 +184,9 @@ void CahnHilliardNavierStokes_TwoPhase::fillOperators() /// < u_old * grad(c) - u_old * grad(c_old), psi > Operator *uGradC = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); if (useConservationForm) - uGradC->addTerm(new WorldVec_FOT(vel, -1.0), GRD_PSI); + addFOT(uGradC, -1.0*valueOf(vel), GRD_PSI); else - uGradC->addTerm(new WorldVec_FOT(vel), GRD_PHI); + addFOT(uGradC, valueOf(vel), GRD_PHI); prob->addMatrixOperator(*uGradC, 0, 0); uGradC->setUhOld(prob->getSolution()->getDOFVector(0)); prob->addVectorOperator(*uGradC, 0); @@ -196,10 +195,9 @@ void CahnHilliardNavierStokes_TwoPhase::fillOperators() for (size_t i = 0; i < dow; i++) { Operator *uGradC2 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); if (useConservationForm) - uGradC2->addTerm(new VecAndPartialDerivative_FOT(prob->getSolution()->getDOFVector(0), i, -1.0), GRD_PSI); - else { - uGradC2->addTerm(new PartialDerivative_ZOT(prob->getSolution()->getDOFVector(0), i)); - } + addFOT(uGradC2, -valueOf(c), i, GRD_PSI); + else + addZOT(uGradC2, derivativeOf(c, i) ); prob->addMatrixOperator(*uGradC2, 0, 2+i); } @@ -209,33 +207,28 @@ void CahnHilliardNavierStokes_TwoPhase::fillOperators() /// < -3*phi*c*c_old^2 , psi > // -3*c_old^2 * c Operator *opChWImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); - opChWImpl->addZeroOrderTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(0), - (doubleWell == 0 ? static_cast<AbstractFunction<double, double>*>(new DoubleWell0Diff(-1.0)) - : static_cast<AbstractFunction<double, double>*>(new DoubleWell1Diff(-1.0))))); + if (doubleWell == 0) + addZOT(opChWImpl, function_(wrap(new DoubleWell0Diff(-1.0)), valueOf(c)) ); + else + addZOT(opChWImpl, function_(wrap(new DoubleWell1Diff(-1.0)), valueOf(c)) ); prob->addMatrixOperator(*opChWImpl, 1, 0); /// < -2*phi*c_old^3 , psi > // -2*c_old^3 + 3/2*c_old^2 Operator *opChWExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); - opChWExpl->addZeroOrderTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(0), - new Pow3Functor(-2.0))); - if (doubleWell == 0) { - opChWExpl->addZeroOrderTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(0), - new Pow2Functor(3.0/2.0))); - } + addZOT(opChWExpl, -2.0 * pow<3>(valueOf(c)) ); + if (doubleWell == 0) + addZOT(opChWExpl, 1.5 * pow<2>(valueOf(c)) ); prob->addVectorOperator(*opChWExpl, 1); /// < -eps^2*phi*grad(c) , grad(psi) > Operator *opChL = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); - opChL->addSecondOrderTerm(new Simple_SOT); - prob->addMatrixOperator(*opChL, 1, 0, &minusEpsSqr); + addSOT(opChL, minusEpsSqr); + prob->addMatrixOperator(*opChL, 1, 0); /// < phi*mu , psi > Operator *opChM = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); - opChM->addZeroOrderTerm(new Simple_ZOT); + addZOT(opChM, 1.0); prob->addMatrixOperator(*opChM, 1, 1); // ----------------------------------------------------------------------------------- diff --git a/extensions/base_problems/DiffuseDomainFsi.cc b/extensions/base_problems/DiffuseDomainFsi.cc index 1fe67f263b12e1bdce12be4dc016a8c045ae0cec..873af228edf0ec9585589a55f7bbf9c73b4bf7a2 100644 --- a/extensions/base_problems/DiffuseDomainFsi.cc +++ b/extensions/base_problems/DiffuseDomainFsi.cc @@ -15,7 +15,7 @@ * ******************************************************************************/ #include "DiffuseDomainFsi.h" - +#include "Expressions.h" namespace AMDiS { namespace base_problems { @@ -87,7 +87,7 @@ void DiffuseDomainFsi::initData() velocity = new DOFVector<WorldVector<double> >(getFeSpace(0), "velocity"); displacement = new DOFVector<WorldVector<double> >(getFeSpace(dow+1), "displacement"); - dbc_factor = beta/pow(epsilon, alpha); + dbc_factor = beta/std::pow(epsilon, alpha); MSG_DBG("dbc_factor = %f\n", dbc_factor); pressure_factor = -(lambda+(2.0/3.0)*mu); MSG("pressure_factor = %f\n", pressure_factor); @@ -121,7 +121,7 @@ void DiffuseDomainFsi::initTimestep(AdaptInfo *adaptInfo) super::initTimestep(adaptInfo); transformDOF(1.0, phase, phaseInv, new Subtract<double>); transformDOF(phaseInv, 1.e-7, phaseInvDisturbed, new Max<double>); - VtkWriter::writeFile(phaseInv, "phaseInv.vtu"); + io::writeFile(phaseInv, "phaseInv.vtu"); } @@ -219,9 +219,7 @@ void DiffuseDomainFsi::fillOperators() /// < (1-phase) * u^old*grad(eta_i) , psi > for(size_t j = 0; j < dow; ++j) { Operator *opUGradE2 = new Operator(prob->getFeSpace(dow+1+i),prob->getFeSpace(dow+1+i)); - opUGradE2->addTerm(new Vec2ProductPartial_FOT( - phaseInvDisturbed, - prob->getSolution()->getDOFVector(j), j), GRD_PHI); + addFOT(opUGradE2, valueOf(phaseInvDisturbed) * valueOf(prob->getSolution()->getDOFVector(j)), j, GRD_PHI); prob->addMatrixOperator(*opUGradE2, dow+1+i, dow+1+i); } @@ -234,12 +232,12 @@ void DiffuseDomainFsi::fillOperators() for (size_t i = 0; i < dow; ++i) { /// < phase*d_i(u_i) , psi > Operator *opDivU = new Operator(prob->getFeSpace(dow),prob->getFeSpace(i)); - opDivU->addTerm(new VecAndPartialDerivative_FOT(phase, i), GRD_PHI); + addFOT(opDivU, valueOf(phase), i, GRD_PHI); prob->addMatrixOperator(*opDivU, dow, i); /// < (1-phase)*d_i(eta_i) , psi > Operator *opDivEta = new Operator(prob->getFeSpace(dow),prob->getFeSpace(dow+1+i)); - opDivEta->addTerm(new VecAndPartialDerivative_FOT(phaseInv, i, pressure_factor), GRD_PHI); + addFOT(opDivU, pressure_factor * valueOf(phaseInv), i, GRD_PHI); prob->addMatrixOperator(*opDivEta, dow, dow+1+i); } diff --git a/extensions/base_problems/NavierStokes_TH_MultiPhase.h b/extensions/base_problems/NavierStokes_TH_MultiPhase.h index b7e421e125bbdc65f3a61c3b85ebad988a9ec4b1..ae267b49195bd439f7e074c6232b2faa623fb90b 100644 --- a/extensions/base_problems/NavierStokes_TH_MultiPhase.h +++ b/extensions/base_problems/NavierStokes_TH_MultiPhase.h @@ -51,11 +51,13 @@ namespace detail { * initTimeInterface of super **/ void initData() override; + void transferInitialSolution(AdaptInfo *adaptInfo) override; /** initTimestep of super and * initialization of densityPhase and viscosityPhase **/ void initTimestep(AdaptInfo *adaptInfo) override; + void closeTimestep(AdaptInfo *adaptInfo) override; /** pointer to the multiPhase DOFVector, that * indicates the different phases. Will be initialized @@ -94,6 +96,23 @@ namespace detail { else return density2; } + + void rejectTimestep() + { + *stepSolution = *oldSolution; + } + + void acceptTimestep() + { FUNCNAME("NavierStokes_TH_MultiPhase::acceptTimestep"); + MSG("Timestep accepted.\n"); + *oldSolution = *self::prob->getSolution(); + *stepSolution = *self::prob->getSolution(); + } + + SystemVector* getStepSolution() + { + return stepSolution; + } protected: // variables @@ -119,6 +138,9 @@ namespace detail { /// phase inticator DOFVector<double> *multiPhase; + + SystemVector* oldSolution; + SystemVector* stepSolution; }; @@ -126,46 +148,30 @@ namespace detail { /** linear interpolation between two values (like density, viscosity) * using a phase-field variable in [-1,1] **/ - class LinearInterpolation1 : public AbstractFunction<double, double> - { - public: + struct LinearInterpolation1 : public FunctorBase + { + typedef double result_type; + int getDegree(int d0) const { return 1; } - LinearInterpolation1(double c1, double c2) : - AbstractFunction<double, double>(1) - { a = (c1-c2)/2.0; b = (c1+c2)/2.0; cmin=std::min(c1,c2); cmax=std::max(c1,c2);} + LinearInterpolation1(double c1, double c2) + { + a = (c1-c2)/2.0; + b = (c1+c2)/2.0; + cmin = std::min(c1,c2); + cmax = std::max(c1,c2); + } - double operator()(const double &phase) const { + double operator()(const double &phase) const + { double result = b+a*phase; - if (result<cmin) result = cmin; - if (result>cmax) result = cmax; + if (result < cmin) result = cmin; + if (result > cmax) result = cmax; return result; } private: double a,b,cmin,cmax; }; - - /** linear interpolation between two values (like density, viscosity) - * using a phase-field variable in [0,1] - **/ - class LinearInterpolation0 : public AbstractFunction<double, double> - { - public: - - LinearInterpolation0(double val1_, double val2_) : - AbstractFunction<double, double>(1), - val1(val1_), val2(val2_) {} - - double operator()(const double &phase) const { - return phase*val1 + (1.0-phase)*val2; - } - - private: - - double val1; - double val2; - }; - } typedef base_problems::detail::NavierStokes_TH_MultiPhase<AMDiS::ProblemStat> NavierStokes_TH_MultiPhase; diff --git a/extensions/base_problems/NavierStokes_TH_MultiPhase.hh b/extensions/base_problems/NavierStokes_TH_MultiPhase.hh index 47c75066ceaa07ad29564ee9f592af6209347339..9beca9369970e4790ed30b784e5a60fae163b934 100644 --- a/extensions/base_problems/NavierStokes_TH_MultiPhase.hh +++ b/extensions/base_problems/NavierStokes_TH_MultiPhase.hh @@ -14,25 +14,26 @@ * See also license.opensource.txt in the distribution. * ******************************************************************************/ -// #ifdef HAVE_PARALLEL_DOMAIN_AMDIS -// #include "parallel/MeshDistributor.h" -// #endif + +#include "Expressions.h" namespace AMDiS { namespace base_problems { namespace detail { template<typename P> -NavierStokes_TH_MultiPhase<P>::NavierStokes_TH_MultiPhase(const std::string &name_, bool createProblem) : - super(name_, createProblem), - viscosity1(1.0), - viscosity2(1.0), - density1(1.0), - density2(1.0), - phaseFieldType(0), - densityPhase(NULL), - viscosityPhase(NULL), - multiPhase(NULL) +NavierStokes_TH_MultiPhase<P>::NavierStokes_TH_MultiPhase(const std::string &name_, bool createProblem) + : super(name_, createProblem), + viscosity1(1.0), + viscosity2(1.0), + density1(1.0), + density2(1.0), + phaseFieldType(0), + densityPhase(NULL), + viscosityPhase(NULL), + multiPhase(NULL), + stepSolution(NULL), + oldSolution(NULL) { FUNCNAME("NavierStokes_TH_MultiPhase::_constructor()"); Initfile::get(self::name + "->viscosity1", viscosity1); // viscosity of fluid 1 @@ -61,6 +62,14 @@ NavierStokes_TH_MultiPhase<P>::~NavierStokes_TH_MultiPhase() delete viscosityPhase; viscosityPhase = NULL; } + if (oldSolution) { + delete oldSolution; + oldSolution = NULL; + } + if (stepSolution) { + delete stepSolution; + stepSolution = NULL; + } } @@ -70,6 +79,9 @@ void NavierStokes_TH_MultiPhase<P>::initData() densityPhase = new DOFVector<double>(self::prob->getFeSpace(0), "densityPhase"); viscosityPhase = new DOFVector<double>(self::prob->getFeSpace(0), "viscosityPhase"); + oldSolution = new SystemVector(*self::prob->getSolution()); + stepSolution = new SystemVector(*self::prob->getSolution()); + #ifdef HAVE_PARALLEL_DOMAIN_AMDIS Parallel::MeshDistributor::globalMeshDistributor->addInterchangeVector(densityPhase); Parallel::MeshDistributor::globalMeshDistributor->addInterchangeVector(viscosityPhase); @@ -82,37 +94,48 @@ void NavierStokes_TH_MultiPhase<P>::initData() } +template<typename P> +void NavierStokes_TH_MultiPhase<P>::transferInitialSolution(AdaptInfo *adaptInfo) +{ + super::transferInitialSolution(adaptInfo); + *oldSolution = *self::prob->getSolution(); + *stepSolution = *self::prob->getSolution(); +} + + template<typename P> void NavierStokes_TH_MultiPhase<P>::initTimestep(AdaptInfo *adaptInfo) { super::initTimestep(adaptInfo); if (multiPhase) { if (phaseFieldType == 0) { - LinearInterpolation0 dLI(density1, density2); - LinearInterpolation0 vLI(viscosity1, viscosity2); - transformDOF(multiPhase, densityPhase, &dLI); - transformDOF(multiPhase, viscosityPhase, &vLI); + *viscosityPhase << viscosity2 + valueOf(multiPhase)*(viscosity1 - viscosity2); + *densityPhase << density2 + valueOf(multiPhase)*(density1 - density2); } else { - LinearInterpolation1 dLI(density1, density2); - LinearInterpolation1 vLI(viscosity1, viscosity2); - transformDOF(multiPhase, densityPhase, &dLI); - transformDOF(multiPhase, viscosityPhase, &vLI); + *viscosityPhase << function_(LinearInterpolation1(viscosity1, viscosity2), valueOf(multiPhase)); + *densityPhase << function_(LinearInterpolation1(density1, density2), valueOf(multiPhase)); } } } +template<typename P> +void NavierStokes_TH_MultiPhase<P>::closeTimestep(AdaptInfo *adaptInfo) +{ + super::closeTimestep(adaptInfo); + acceptTimestep(); +} + + template<typename P> void NavierStokes_TH_MultiPhase<P>::fillOperators() { using namespace extensions; - int degree_u = self::prob->getFeSpace(0)->getBasisFcts()->getDegree(); -// int degree_p = self::prob->getFeSpace(self::dow)->getBasisFcts()->getDegree(); - - WorldVector<DOFVector<double>* > vel; + WorldVector<DOFVector<double>* > vel, vel_old; for (unsigned i = 0; i < self::dow; i++) { - vel[i]= self::prob->getSolution()->getDOFVector(i); + vel[i]= stepSolution->getDOFVector(i); + vel_old[i]= oldSolution->getDOFVector(i); } // fill operators for prob @@ -120,26 +143,26 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() /// < (1/tau)*rho*u'_i , psi > Operator *opTime = new Operator(self::getFeSpace(i), self::getFeSpace(i)); if (density1 == density2 || !densityPhase) - opTime->addTerm(new Simple_ZOT(density1)); + addZOT(opTime, density1); else - opTime->addTerm(new VecAtQP_ZOT(densityPhase)); + addZOT(opTime, valueOf(densityPhase)); self::prob->addMatrixOperator(*opTime, i, i, self::getInvTau(), self::getInvTau()); /// < (1/tau)*rho*u_i^old , psi > Operator *opTimeOld = new Operator(self::getFeSpace(i), self::getFeSpace(i)); if (density1 == density2 || !densityPhase) - opTimeOld->addTerm(new VecAtQP_ZOT(self::prob->getSolution()->getDOFVector(i), new AMDiS::Factor<double>(density1, degree_u))); + addZOT(opTimeOld, density1 * valueOf(vel_old[i])); else - opTimeOld->addTerm(new Vec2AtQP_ZOT(densityPhase, self::prob->getSolution()->getDOFVector(i))); + addZOT(opTimeOld, valueOf(densityPhase) * valueOf(vel_old[i])); self::prob->addVectorOperator(*opTimeOld, i, self::getInvTau(), self::getInvTau()); /// < u^old*grad(u_i^old) , psi > Operator *opUGradU0 = new Operator(self::getFeSpace(i),self::getFeSpace(i)); if (density1 == density2 || !densityPhase) - opUGradU0->addTerm(new WorldVec_FOT(vel, density1), GRD_PHI); + addFOT(opUGradU0, density1 * valueOf(vel), GRD_PHI); else - opUGradU0->addTerm(new WorldVecPhase_FOT(densityPhase, vel, 1.0), GRD_PHI); - opUGradU0->setUhOld(self::prob->getSolution()->getDOFVector(i)); + addFOT(opUGradU0, valueOf(densityPhase) * valueOf(vel), GRD_PHI); + opUGradU0->setUhOld(vel[i]); self::prob->addVectorOperator(*opUGradU0, i); @@ -147,9 +170,9 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() for (size_t j = 0; j < self::dow; ++j) { Operator *opUGradU1 = new Operator(self::getFeSpace(i),self::getFeSpace(j)); if (density1 == density2 || !densityPhase) - opUGradU1->addTerm(new PartialDerivative_ZOT(self::prob->getSolution()->getDOFVector(i), j, density1)); + addZOT(opUGradU1, density1 * derivativeOf(vel[i], j)); else - opUGradU1->addTerm(new VecAndPartialDerivative_ZOT(densityPhase, self::prob->getSolution()->getDOFVector(i), j)); + addZOT(opUGradU1, valueOf(densityPhase) * derivativeOf(vel[i], j)); self::prob->addMatrixOperator(*opUGradU1, i, j); } @@ -157,9 +180,9 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() for (size_t j = 0; j < self::dow; ++j) { Operator *opUGradU2 = new Operator(self::getFeSpace(i),self::getFeSpace(i)); if (density1 == density2 || !densityPhase) - opUGradU2->addTerm(new VecAndPartialDerivative_FOT(self::prob->getSolution()->getDOFVector(j), j, density1), GRD_PHI); + addFOT(opUGradU2, density1 * valueOf(vel[j]), j, GRD_PHI); else - opUGradU2->addTerm(new Vec2AndPartialDerivative_FOT(densityPhase, self::prob->getSolution()->getDOFVector(j), j), GRD_PHI); + addFOT(opUGradU2, valueOf(densityPhase) * valueOf(vel[j]), j, GRD_PHI); self::prob->addMatrixOperator(*opUGradU2, i, i); } @@ -168,16 +191,16 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() /// < p , d_i(psi) > Operator *opGradP = new Operator(self::getFeSpace(i),self::getFeSpace(self::dow)); - opGradP->addTerm(new PartialDerivative_FOT(i, -1.0), GRD_PSI); + addFOT(opGradP, -1.0, i, GRD_PSI); self::prob->addMatrixOperator(*opGradP, i, self::dow); /// external force, e.g. gravitational force if (std::abs(self::force[i]) > DBL_TOL) { Operator *opForce = new Operator(self::getFeSpace(i), self::getFeSpace(i)); if (density1 == density2 || !densityPhase) - opForce->addTerm(new Simple_ZOT(density1*self::force[i])); + addZOT(opForce, density1*self::force[i] ); else - opForce->addTerm(new VecAtQP_ZOT(densityPhase, NULL, self::force[i])); + addZOT(opForce, valueOf(densityPhase)*self::force[i] ); self::prob->addVectorOperator(*opForce, i); } } @@ -186,12 +209,11 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() for (size_t i = 0; i < self::dow; ++i) { /// < d_i(u'_i) , psi > Operator *opDivU = new Operator(self::getFeSpace(self::dow),self::getFeSpace(i)); - opDivU->addTerm(new PartialDerivative_FOT(i), GRD_PHI); + addFOT(opDivU, 1.0, i, GRD_PHI); self::prob->addMatrixOperator(*opDivU, self::dow, i); } Operator *opZero = new Operator(self::getFeSpace(self::dow),self::getFeSpace(self::dow)); - opZero->addTerm(new Simple_ZOT(0.0)); self::prob->addMatrixOperator(*opZero, self::dow, self::dow); } @@ -199,23 +221,21 @@ void NavierStokes_TH_MultiPhase<P>::fillOperators() template<typename P> void NavierStokes_TH_MultiPhase<P>::addLaplaceTerm(int i) { - using namespace extensions; /// < alpha*[grad(u)+grad(u)^t] , grad(psi) > if (viscosity1 != viscosity2 && viscosityPhase) { for (unsigned j = 0; j < self::dow; ++j) { Operator *opLaplaceUi1 = new Operator(self::getFeSpace(i), self::getFeSpace(j)); - opLaplaceUi1->addTerm(new VecAtQP_IJ_SOT(viscosityPhase, NULL, j, i)); + addSOT(opLaplaceUi1, valueOf(viscosityPhase), j, i); self::prob->addMatrixOperator(*opLaplaceUi1, i, j); } } /// < alpha*grad(u'_i) , grad(psi) > Operator *opLaplaceUi = new Operator(self::getFeSpace(i), self::getFeSpace(i)); - if (viscosity1 == viscosity2 || !viscosityPhase) { - opLaplaceUi->addTerm(new Simple_SOT(viscosity1)); - } else { - opLaplaceUi->addTerm(new VecAtQP_SOT(viscosityPhase)); - } + if (viscosity1 == viscosity2 || !viscosityPhase) + addSOT(opLaplaceUi, viscosity1); + else + addSOT(opLaplaceUi, valueOf(viscosityPhase)); self::prob->addMatrixOperator(*opLaplaceUi, i, i); } diff --git a/extensions/base_problems/NavierStokes_TaylorHood.h b/extensions/base_problems/NavierStokes_TaylorHood.h index be0c948336069ad5057bd06cc23133f84f4f13e9..0e0ea152b012b78f3aa5c6aef42f40da9fe467c9 100644 --- a/extensions/base_problems/NavierStokes_TaylorHood.h +++ b/extensions/base_problems/NavierStokes_TaylorHood.h @@ -21,7 +21,7 @@ #include "AMDiS.h" #include "BaseProblem.h" #include "ExtendedProblemStat.h" -#include "GenericOperatorTerm.h" +#include "Expressions.h" namespace AMDiS { namespace base_problems { diff --git a/extensions/base_problems/PhaseFieldCrystal.h b/extensions/base_problems/PhaseFieldCrystal.h index a0c2c8049dc8042da6c8ffc414fa1116481447e4..e68333957d07fcec72d26bab7ddd487cec393b94 100644 --- a/extensions/base_problems/PhaseFieldCrystal.h +++ b/extensions/base_problems/PhaseFieldCrystal.h @@ -28,22 +28,62 @@ namespace detail { public: PhaseFieldCrystal(const std::string &name_, bool createProblem = true); - ~PhaseFieldCrystal() {} + + ~PhaseFieldCrystal() + { + if (oldSolution) { + delete oldSolution; + oldSolution = NULL; + } + if (stepSolution) { + delete stepSolution; + stepSolution = NULL; + } + } DOFVector<double>* getDensity() { return self::prob->getSolution(1); } double calcEnergy(); + void initData() override ; + void transferInitialSolution(AdaptInfo *adaptInfo) override; + + void closeTimestep(AdaptInfo *adaptInfo) override; + void fillOperators() override ; void fillBoundaryConditions() override {}; - + + void rejectTimestep() + { + *stepSolution = *oldSolution; + } + + void acceptTimestep() + { FUNCNAME("PhaseFieldCrystal::acceptTimestep"); + MSG("Timestep accepted.\n"); + *oldSolution = *self::prob->getSolution(); + *stepSolution = *self::prob->getSolution(); + } + + SystemVector* getStepSolution() + { + return stepSolution; + } + + SystemVector* getOldSolution() + { + return oldSolution; + } + protected: - bool useMobility; + int mobility_type; double r; - double rho0; double density; double M0; + + SystemVector* oldSolution; + SystemVector* stepSolution; }; } // end namespace detail diff --git a/extensions/base_problems/PhaseFieldCrystal.hh b/extensions/base_problems/PhaseFieldCrystal.hh index acec2f6688dccb060274bb81d024d753dc65f10e..ebe4b7258779344f5a8055f8d6f0476f2f310542 100644 --- a/extensions/base_problems/PhaseFieldCrystal.hh +++ b/extensions/base_problems/PhaseFieldCrystal.hh @@ -1,24 +1,43 @@ -#include "GenericOperatorTerm.h" +#include "Expressions.h" namespace AMDiS { namespace base_problems { namespace detail { template<typename P> - PhaseFieldCrystal<P>::PhaseFieldCrystal(const std::string &name_, bool createProblem) : - super(name_, createProblem), - useMobility(false), - r(-0.4), // temperature deviation - rho0(1.0), // liquid density - density(-0.3), // mean density - M0(1.0) // mobility + PhaseFieldCrystal<P>::PhaseFieldCrystal(const std::string &name_, bool createProblem) + : super(name_, createProblem), + mobility_type(0), + r(-0.4), // temperature deviation + density(-0.3), // mean density + M0(1.0), // mobility + oldSolution(NULL), + stepSolution(NULL) { Parameters::get(name_ + "->r",r); - Parameters::get(name_ + "->rho0", rho0); Parameters::get(name_ + "->density", density); Parameters::get(name_ + "->M0", M0); - Parameters::get(name_ + "->use mobility", useMobility); + Parameters::get(name_ + "->mobility type", mobility_type); + } + + + template<typename P> + void PhaseFieldCrystal<P>::initData() + { + super::initData(); + + oldSolution = new SystemVector(*self::prob->getSolution()); + stepSolution = new SystemVector(*self::prob->getSolution()); + } + + + template<typename P> + void PhaseFieldCrystal<P>::transferInitialSolution(AdaptInfo *adaptInfo) + { + super::transferInitialSolution(adaptInfo); + *oldSolution = *self::prob->getSolution(); + *stepSolution = *self::prob->getSolution(); } @@ -29,7 +48,8 @@ namespace AMDiS { namespace base_problems { const FiniteElemSpace* feSpace1 = self::prob->getFeSpace(1); const FiniteElemSpace* feSpace2 = self::prob->getFeSpace(2); - DOFVector<double>* rho = self::prob->getSolution(1); + DOFVector<double>* rho = stepSolution->getDOFVector(1); + DOFVector<double>* rho_old = oldSolution->getDOFVector(1); // dt(rho) = laplace(mu) - u*grad(rho) // ----------------------------------- @@ -38,21 +58,24 @@ namespace AMDiS { namespace base_problems { self::prob->addMatrixOperator(opM11, 1, 1); Operator *opLM = new Operator(feSpace1, feSpace0); - if (useMobility) - addSOT(opLM, max(abs_(valueOf(rho) + 1.5)*M0, 1.e-5)); - else + if (mobility_type == 0) addSOT(opLM, M0); + else if (mobility_type == 1) + addSOT(opLM, max(abs_(valueOf(rho) + 1.5)*M0, 1.e-5)); + else if (mobility_type == 2) + addSOT(opLM, max(valueOf(rho)*M0, 1.e-5)); + self::prob->addMatrixOperator(opLM, 1, 0, self::getTau(), self::getTau()); // -laplace(mu) // . . . vectorOperators . . . . . . . . . . . . . . . Operator *opMold = new Operator(feSpace1); - addZOT(opMold, valueOf(rho)); + addZOT(opMold, valueOf(rho_old)); self::prob->addVectorOperator(opMold, 1); // mu-2*nu-laplace(nu)-(1+r)*rho = (rho_old^3) + ExtPot - eps^2/(rho_old+0.9) // ---------------------------------------------------------------------- Operator *op01 = new Operator(feSpace0, feSpace1); - addZOT(op01, -(1.0 + ref_(r)) - 3.0 * pow<2>(valueOf(rho)) ); + addZOT(op01, -(1.0 + ref_(&r)) - 3.0 * pow<2>(valueOf(rho)) ); addSOT(op01, 2.0); self::prob->addMatrixOperator(op01, 0, 1); @@ -90,6 +113,14 @@ namespace AMDiS { namespace base_problems { return integrate( 0.5*valueOf(rho)*valueOf(mu) - 0.25*pow<4>(valueOf(rho)) ); } + + template<typename P> + void PhaseFieldCrystal<P>::closeTimestep(AdaptInfo *adaptInfo) + { + super::closeTimestep(adaptInfo); + acceptTimestep(); + } + } // end namespace detail } } diff --git a/extensions/base_problems/PhaseFieldCrystal_Phase.h b/extensions/base_problems/PhaseFieldCrystal_Phase.h index 5e1b0510009e53b78fcab8181bc764fb50d3d809..fffb75accb9043249b0ddc8f2e07c5f6399eea6b 100644 --- a/extensions/base_problems/PhaseFieldCrystal_Phase.h +++ b/extensions/base_problems/PhaseFieldCrystal_Phase.h @@ -19,7 +19,7 @@ #define PHASE_FIELD_CRYSTAL_PHASE_H #include "PhaseFieldCrystal.h" -#include "GenericOperatorTerm.h" +#include "Expressions.h" namespace AMDiS { namespace base_problems { @@ -33,12 +33,13 @@ namespace AMDiS { namespace base_problems { { public: // typedefs - typedef PhaseFieldCrystal_Phase<ProblemStatType> self; - typedef PhaseFieldCrystal<ProblemStatType> super; + typedef PhaseFieldCrystal_Phase<ProblemStatType> self; + typedef PhaseFieldCrystal<ProblemStatType> super; public: // methods PhaseFieldCrystal_Phase(const std::string &name_); + ~PhaseFieldCrystal_Phase(); DOFVector<double> *getPhase() diff --git a/extensions/base_problems/PhaseFieldCrystal_Phase.hh b/extensions/base_problems/PhaseFieldCrystal_Phase.hh index b65cc9a29abfde42d9761f0d08c74837f44b7695..183fdbf648528aadace2245fbb3c34f260c8a40c 100644 --- a/extensions/base_problems/PhaseFieldCrystal_Phase.hh +++ b/extensions/base_problems/PhaseFieldCrystal_Phase.hh @@ -1,91 +1,100 @@ namespace AMDiS { namespace base_problems { - namespace detail - { +namespace detail +{ -template<typename P> -PhaseFieldCrystal_Phase<P>::PhaseFieldCrystal_Phase(const std::string &name_) : - super(name_), - phase(NULL), - phaseDisturbed(NULL) -{} + template<typename P> + PhaseFieldCrystal_Phase<P>::PhaseFieldCrystal_Phase(const std::string &name_) + : super(name_), + phase(NULL), + phaseDisturbed(NULL) + { } -template<typename P> -PhaseFieldCrystal_Phase<P>::~PhaseFieldCrystal_Phase() -{ - delete phase; - delete phaseDisturbed; -} - - -template<typename P> -void PhaseFieldCrystal_Phase<P>::fillOperators() -{ - const FiniteElemSpace* feSpace0 = self::prob->getFeSpace(0); - const FiniteElemSpace* feSpace1 = self::prob->getFeSpace(1); - const FiniteElemSpace* feSpace2 = self::prob->getFeSpace(2); - - DOFVector<double>* rho = self::prob->getSolution(1); - - // dt(rho) = laplace(mu) - u*grad(rho) - // ----------------------------------- - Operator *opM11 = new Operator(feSpace1, feSpace1); - addZOT(opM11, valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(opM11, 1, 1); - - Operator *opLM = new Operator(feSpace1, feSpace0); - if (super::useMobility) - addSOT(opLM, valueOf(phaseDisturbed) * max(abs_(valueOf(rho) + 1.5)*super::M0, 1.e-5)); - else - addSOT(opLM, valueOf(phaseDisturbed) * super::M0); - self::prob->addMatrixOperator(opLM, 1, 0, self::getTau(), self::getTau()); // -laplace(mu) - - // . . . vectorOperators . . . . . . . . . . . . . . . - Operator *opMold = new Operator(feSpace1); - addZOT(opMold, valueOf(rho) * valueOf(phaseDisturbed)); - self::prob->addVectorOperator(opMold, 1); - - // mu-2*nu-laplace(nu)-(1+r)*rho = (rho_old^3) + ExtPot - eps^2/(rho_old+0.9) - // ---------------------------------------------------------------------- - Operator *op01 = new Operator(feSpace0, feSpace1); - addZOT(op01, valueOf(phaseDisturbed) * ( -(1.0 + ref_(super::r)) - 3.0 * pow<2>(valueOf(rho)) ) ); - addSOT(op01, 2.0 * valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(op01, 0, 1); - - Operator *op00 = new Operator(feSpace0, feSpace0); - addZOT(op00, valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(op00, 0, 0); - - Operator *op02 = new Operator(feSpace0, feSpace2); - addSOT(op02, valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(op02, 0, 2); - - // . . . vectorOperators . . . . . . . . . . . . . . . - Operator *op0 = new Operator(feSpace0); - addZOT(op0, -2.0 * valueOf(phaseDisturbed) * pow<3>(valueOf(rho)) ); - self::prob->addVectorOperator(op0, 0); - - // 0 = nu-laplace(rho) - // ------------------- - Operator *op21 = new Operator(feSpace2, feSpace1); - addSOT(op21, valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(op21, 2, 1); // -laplace(rho) - - Operator *op22 = new Operator(feSpace2, feSpace2); - addZOT(op22, valueOf(phaseDisturbed)); - self::prob->addMatrixOperator(op22, 2, 2); // nu -} - - -template<typename P> -double PhaseFieldCrystal_Phase<P>::calcEnergy() -{ - DOFVector<double>* rho = self::prob->getSolution(1); - DOFVector<double>* mu = self::prob->getSolution(0); - - return integrate( valueOf(phase) * ( 0.5*valueOf(rho)*valueOf(mu) - 0.25*pow<4>(valueOf(rho)) ) ); -} + template<typename P> + PhaseFieldCrystal_Phase<P>::~PhaseFieldCrystal_Phase() + { + if (phase) { + delete phase; + phase = NULL; + } + if (phaseDisturbed) { + delete phaseDisturbed; + phaseDisturbed = NULL; + } + } + + + template<typename P> + void PhaseFieldCrystal_Phase<P>::fillOperators() + { + const FiniteElemSpace* feSpace0 = self::prob->getFeSpace(0); + const FiniteElemSpace* feSpace1 = self::prob->getFeSpace(1); + const FiniteElemSpace* feSpace2 = self::prob->getFeSpace(2); + + DOFVector<double>* rho = super::getStepSolution()->getDOFVector(1); + DOFVector<double>* rho_old = super::getOldSolution()->getDOFVector(1); + + // dt(rho) = laplace(mu) - u*grad(rho) + // ----------------------------------- + Operator *opM11 = new Operator(feSpace1, feSpace1); + addZOT(opM11, valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(opM11, 1, 1); + + Operator *opLM = new Operator(feSpace1, feSpace0); + if (super::mobility_type == 1) + addSOT(opLM, valueOf(phaseDisturbed) * max(abs_(valueOf(rho) + 1.5)*super::M0, 1.e-5)); + else if (super::mobility_type == 2) + addSOT(opLM, valueOf(phaseDisturbed) * max(valueOf(rho)*super::M0, 1.e-5)); + else + addSOT(opLM, valueOf(phaseDisturbed) * super::M0); + self::prob->addMatrixOperator(opLM, 1, 0, self::getTau(), self::getTau()); // -laplace(mu) + + // . . . vectorOperators . . . . . . . . . . . . . . . + Operator *opMold = new Operator(feSpace1); + addZOT(opMold, valueOf(rho_old) * valueOf(phaseDisturbed)); + self::prob->addVectorOperator(opMold, 1); + + // mu-2*nu-laplace(nu)-(1+r)*rho = (rho_old^3) + ExtPot - eps^2/(rho_old+0.9) + // ---------------------------------------------------------------------- + Operator *op01 = new Operator(feSpace0, feSpace1); + addZOT(op01, valueOf(phaseDisturbed) * ( -(1.0 + ref_(super::r)) - 3.0 * pow<2>(valueOf(rho)) ) ); + addSOT(op01, 2.0 * valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(op01, 0, 1); + + Operator *op00 = new Operator(feSpace0, feSpace0); + addZOT(op00, valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(op00, 0, 0); + + Operator *op02 = new Operator(feSpace0, feSpace2); + addSOT(op02, valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(op02, 0, 2); + + // . . . vectorOperators . . . . . . . . . . . . . . . + Operator *op0 = new Operator(feSpace0); + addZOT(op0, -2.0 * valueOf(phaseDisturbed) * pow<3>(valueOf(rho)) ); + self::prob->addVectorOperator(op0, 0); + + // 0 = nu-laplace(rho) + // ------------------- + Operator *op21 = new Operator(feSpace2, feSpace1); + addSOT(op21, valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(op21, 2, 1); // -laplace(rho) + + Operator *op22 = new Operator(feSpace2, feSpace2); + addZOT(op22, valueOf(phaseDisturbed)); + self::prob->addMatrixOperator(op22, 2, 2); // nu + } + + + template<typename P> + double PhaseFieldCrystal_Phase<P>::calcEnergy() + { + DOFVector<double>* rho = self::prob->getSolution(1); + DOFVector<double>* mu = self::prob->getSolution(0); + + return integrate( valueOf(phase) * ( 0.5*valueOf(rho)*valueOf(mu) - 0.25*pow<4>(valueOf(rho)) ) ); + } } // end namespace detail diff --git a/extensions/base_problems/NavierStokesPhase_Chorin.cc b/extensions/base_problems/deprecated/NavierStokesPhase_Chorin.cc similarity index 100% rename from extensions/base_problems/NavierStokesPhase_Chorin.cc rename to extensions/base_problems/deprecated/NavierStokesPhase_Chorin.cc diff --git a/extensions/base_problems/NavierStokesPhase_Chorin.h b/extensions/base_problems/deprecated/NavierStokesPhase_Chorin.h similarity index 100% rename from extensions/base_problems/NavierStokesPhase_Chorin.h rename to extensions/base_problems/deprecated/NavierStokesPhase_Chorin.h diff --git a/extensions/base_problems/NavierStokes_Chorin.cc b/extensions/base_problems/deprecated/NavierStokes_Chorin.cc similarity index 100% rename from extensions/base_problems/NavierStokes_Chorin.cc rename to extensions/base_problems/deprecated/NavierStokes_Chorin.cc diff --git a/extensions/base_problems/NavierStokes_Chorin.h b/extensions/base_problems/deprecated/NavierStokes_Chorin.h similarity index 100% rename from extensions/base_problems/NavierStokes_Chorin.h rename to extensions/base_problems/deprecated/NavierStokes_Chorin.h diff --git a/extensions/base_problems/VacancyPhaseFieldCrystal.cc b/extensions/base_problems/deprecated/VacancyPhaseFieldCrystal.cc similarity index 100% rename from extensions/base_problems/VacancyPhaseFieldCrystal.cc rename to extensions/base_problems/deprecated/VacancyPhaseFieldCrystal.cc diff --git a/extensions/base_problems/VacancyPhaseFieldCrystal.h b/extensions/base_problems/deprecated/VacancyPhaseFieldCrystal.h similarity index 100% rename from extensions/base_problems/VacancyPhaseFieldCrystal.h rename to extensions/base_problems/deprecated/VacancyPhaseFieldCrystal.h diff --git a/extensions/preconditioner/BlockPreconditioner.h b/extensions/preconditioner/BlockPreconditioner.h deleted file mode 100644 index d5f2161c7d6d2bd936ec1e55f452a53330e4fff7..0000000000000000000000000000000000000000 --- a/extensions/preconditioner/BlockPreconditioner.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * - * 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 BLOCK_PRECONDITIONER_H -#define BLOCK_PRECONDITIONER_H - -#include "solver/ITL_Preconditioner.h" -#include "solver/SolverMatrix.h" - -namespace AMDiS { - - struct BlockPreconditioner : BasePreconditioner - { - typedef SolverMatrix<Matrix<DOFMatrix*> > BlockMatrix; - - BlockPreconditioner() : A(NULL), fullMatrix(NULL) {} - - virtual ~BlockPreconditioner() {} - - /// extract iranges from BlockMatrix to be used to extract sub-vectors and sub-matrices. - void init(const BlockMatrix& A_, const MTLTypes::MTLMatrix& fullMatrix_) - { - A = &A_; - fullMatrix = &fullMatrix_; - - BlockMapper mapper(A_); - rows.resize(mapper.getNumComponents()); - int start = 0; - for (int i = 0; i < mapper.getNumComponents(); i++) { - mapper.setRow(i+1); - int finish = mapper.row(0); - rows[i].set(start, finish); - start = finish; - } - } - - virtual void solve(const MTLTypes::MTLVector& b, MTLTypes::MTLVector& x) const - { FUNCNAME("BlockPreconditioner::solve()"); - TEST_EXIT(false)("Noch nicht implementiert!\n"); - } - - virtual void adjoint_solve(const MTLTypes::MTLVector& x, MTLTypes::MTLVector& y) const - { FUNCNAME("BlockPreconditioner::adjoint_solve()"); - TEST_EXIT(false)("Noch nicht implementiert!\n"); - } - - mtl::irange& getRows(size_t i) - { - return rows[i]; - } - - - protected: - - template<typename SolverType, typename RunnerType> - void createSubSolver(std::string param, SolverType*& solver, RunnerType*& runner, std::string solverType = "0") - { - // definition of standard-backends -#if defined HAVE_PARALLEL_PETSC - string backend("p_petsc"); -#elif defined HAVE_PARALLEL_MTL - string backend("p_mtl"); -#elif defined HAVE_PETSC - string backend("petsc"); -#else - string backend("mtl"); -#endif - - // === read backend-name === - string initFileStr = param + "->solver"; - Parameters::get(initFileStr + "->backend", backend); - - // === read solver-name === - Parameters::get(initFileStr, solverType); - - if (backend != "0" && backend != "no" && backend != "") - solverType = backend + "_" + solverType; - - LinearSolverCreator *solverCreator = - dynamic_cast<LinearSolverCreator*>(CreatorMap<LinearSolver>::getCreator(solverType, initFileStr)); - TEST_EXIT(solverCreator) - ("No valid solver type found in parameter \"%s\"\n", initFileStr.c_str()); - solverCreator->setName(initFileStr); - solver = dynamic_cast<SolverType*>(solverCreator->create()); - assert(solver != NULL); - - runner = dynamic_cast<RunnerType*>(solver->getRunner()); - assert(runner != NULL); - } - - - const SolverMatrix<Matrix<DOFMatrix*> >* A; - const MTLTypes::MTLMatrix* fullMatrix; - - std::vector<mtl::irange> rows; - }; - -} // end namespace - -#endif // BLOCK_PRECONDITIONER_H diff --git a/extensions/preconditioner/CahnHilliard_.cc b/extensions/preconditioner/CahnHilliard_.cc deleted file mode 100644 index 03151202c3c94bc7543a99511a181c50d5769dbc..0000000000000000000000000000000000000000 --- a/extensions/preconditioner/CahnHilliard_.cc +++ /dev/null @@ -1,219 +0,0 @@ -/****************************************************************************** - * - * 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 "CahnHilliard_.h" -// #include "Views.h" -#include "SignedDistFunctors.h" -#include "PhaseFieldConvert.h" - -#include "HL_SignedDistTraverse.h" -#include "Recovery.h" - -namespace AMDiS { namespace base_problems { - -CahnHilliard_::CahnHilliard_(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_::solveInitialProblem(AdaptInfo *adaptInfo) -{ - using namespace extensions; - Flag initFlag = initDataFromFile(adaptInfo); - - if (!initFlag.isSet(DATA_ADOPTED)) { - int initialInterface = 0; - Initfile::get(name + "->initial interface", initialInterface); - double initialEps = eps; - Initfile::get(name + "->initial epsilon", initialEps); - - if (initialInterface == 0) { - /// horizontale Linie - double a= 0.0, dir= -1.0; - Initfile::get(name + "->line->pos", a); - Initfile::get(name + "->line->direction", dir); - prob->getSolution()->getDOFVector(1)->interpol(new Plane(a, dir)); - } - else if (initialInterface == 1) { - /// schraege Linie - double theta = m_pi/4.0; - prob->getSolution()->getDOFVector(1)->interpol(new PlaneRotation(0.0, theta, 1.0)); - transformDOFInterpolation(prob->getSolution()->getDOFVector(1),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(name + "->ellipse->a", a); - Initfile::get(name + "->ellipse->b", b); - prob->getSolution()->getDOFVector(1)->interpol(new Ellipse(a,b)); - } - else if (initialInterface == 3) { - /// zwei horizontale Linien - double a= 0.75, b= 0.375; - Initfile::get(name + "->lines->pos1", a); - Initfile::get(name + "->lines->pos2", b); - prob->getSolution()->getDOFVector(1)->interpol(new Plane(a, -1.0)); - transformDOFInterpolation(prob->getSolution()->getDOFVector(1),new Plane(b, 1.0), new AMDiS::Max<double>); - } - else if (initialInterface == 4) { - /// Kreis - double radius= 1.0; - Initfile::get(name + "->kreis->radius", radius); - prob->getSolution()->getDOFVector(1)->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(name + "->rectangle->width", width); - Initfile::get(name + "->rectangle->height", height); - Initfile::get(name + "->rectangle->center", center); - prob->getSolution()->getDOFVector(1)->interpol(new Rectangle(width, height, center)); - } - - // TODO: Redistancing einfügen! - if (useReinit) { - FiniteElemSpace* feSpace = FiniteElemSpace::provideFeSpace( - const_cast<DOFAdmin*>(getMesh()->getVertexAdmin()), - Lagrange::getLagrange(getMesh()->getDim(), 1), - getMesh(), - "P1"); - DOFVector<double> tmp(feSpace, "tmp"); - tmp.interpol(prob->getSolution()->getDOFVector(1)); - - HL_SignedDistTraverse reinit("reinit", getMesh()->getDim()); - reinit.calcSignedDistFct(adaptInfo, &tmp); - -#ifndef HAVE_PARALLEL_DOMAIN_AMDIS - Recovery recovery(L2_NORM, 1); - recovery.recoveryUh(&tmp, *prob->getSolution()->getDOFVector(1)); -#else - prob->getSolution()->getDOFVector(1)->interpol(&tmp); -#endif - } - - - /// create phase-field from signed-dist-function - if (doubleWell == 0) { - forEachDOF(prob->getSolution()->getDOFVector(1), - new SignedDistToPhaseField(initialEps)); - } else { - forEachDOF(prob->getSolution()->getDOFVector(1), - new SignedDistToCh(initialEps)); - } - } -} - - -void CahnHilliard_::fillOperators() -{ - const FiniteElemSpace* feSpace = prob->getFeSpace(); - int degree = feSpace->getBasisFcts()->getDegree(); - - // c - Operator *opChMnew = new Operator(feSpace, feSpace); - opChMnew->addTerm(new Simple_ZOT); - Operator *opChMold = new Operator(feSpace, feSpace); - opChMold->addTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(1))); - // -nabla*(grad(c)) - Operator *opChL = new Operator(feSpace, feSpace); - opChL->addTerm(new Simple_SOT); - - // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 - Operator *opChLM = new Operator(feSpace, feSpace); - if (useMobility) { - if (doubleWell == 0) - opChLM->addTerm(new VecAtQP_SOT( - prob->getSolution()->getDOFVector(1), - new MobilityCH0(gamma, degree))); - else - opChLM->addTerm(new VecAtQP_SOT( - prob->getSolution()->getDOFVector(1), - new MobilityCH1(gamma, degree))); - } else - opChLM->addTerm(new Simple_SOT(gamma)); - - // -2*c_old^3 + 3/2*c_old^2 - Operator *opChMPowExpl = new Operator(feSpace, feSpace); - opChMPowExpl->addTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(1), - new AMDiS::Pow<3>(-2.0, 3*degree))); - if (doubleWell == 0) { - opChMPowExpl->addTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(1), - new AMDiS::Pow<2>(3.0/2.0, 2*degree))); - } - - // -3*c_old^2 * c - Operator *opChMPowImpl = new Operator(feSpace, feSpace); - opChMPowImpl->addTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(1), - new AMDiS::Pow<2>(-3.0, 2*degree))); - if (doubleWell == 0) { - opChMPowImpl->addTerm(new VecAtQP_ZOT( - prob->getSolution()->getDOFVector(1), - NULL, 3.0)); - opChMPowImpl->addTerm(new Simple_ZOT(-0.5)); - } else { - opChMPowImpl->addZeroOrderTerm(new Simple_ZOT(1.0)); - } - - // mu + eps^2*laplace(c) + c - 3*(c_old^2)*c = -2*c_old^3 [+ BC] - // ---------------------------------------------------------------------- - prob->addMatrixOperator(*opChMPowImpl,0,1); /// < -3*c*c_old^2 , psi > - prob->addMatrixOperator(*opChL,0,1, &minusEpsSqr); /// < -eps^2*grad(c) , grad(psi) > - prob->addMatrixOperator(*opChMnew,0,0); /// < mu , psi > - // . . . vectorOperators . . . . . . . . . . . . . . . - prob->addVectorOperator(*opChMPowExpl,0); /// < -2*c_old^3 , psi > - - - // dt(c) = laplace(mu) - u*grad(c) - // ----------------------------------- - prob->addMatrixOperator(*opChMnew,1,1); /// < c , psi > - prob->addMatrixOperator(*opChLM,1,0, getTau()); /// < tau*grad(mu) , grad(psi) > - // . . . vectorOperators . . . . . . . . . . . . . . . - prob->addVectorOperator(*opChMold,1); /// < c^old , psi > - -} - -} } diff --git a/extensions/preconditioner/CahnHilliard_.h b/extensions/preconditioner/CahnHilliard_.h deleted file mode 100644 index 4c7bde8095a5a7a257287be39093adafa1154569..0000000000000000000000000000000000000000 --- a/extensions/preconditioner/CahnHilliard_.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * 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_PRECON_H -#define CAHN_HILLIARD_PRECON_H - -#include "AMDiS.h" -#include "BaseProblem.h" -#include "chns.h" - -namespace AMDiS { namespace base_problems { - -class CahnHilliard_ : public BaseProblem<ProblemStat> -{ -public: // definition of types - - typedef BaseProblem<ProblemStat> super; - -public: // public methods - - CahnHilliard_(const std::string &name_); - ~CahnHilliard_() {}; - - void solveInitialProblem(AdaptInfo *adaptInfo); - - double getEpsilon() { return eps; } - int getDoubleWellType() { return doubleWell; } - - void fillOperators() override; - void fillBoundaryConditions() 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; -}; - -} } - -#endif // CAHN_HILLIARD_PRECON_H diff --git a/extensions/preconditioner/MTLPreconCahnHilliard.h b/extensions/preconditioner/MTLPreconCahnHilliard.h index f5f19dbc19b921ed608419da803b61d70d96f5c4..07b2f168128355ac01d334a3cbd0fd0f189f3a81 100644 --- a/extensions/preconditioner/MTLPreconCahnHilliard.h +++ b/extensions/preconditioner/MTLPreconCahnHilliard.h @@ -14,126 +14,138 @@ * See also license.opensource.txt in the distribution. * ******************************************************************************/ + #ifndef MTL_CH_PRECONDITIONER_H #define MTL_CH_PRECONDITIONER_H #include "AMDiS.h" -#include "BlockPreconditioner.h" +#include "solver/BlockPreconditioner.h" namespace AMDiS { namespace extensions { - -using namespace std; -template< typename MatrixType = MTLTypes::MTLMatrix, typename VectorType = MTLTypes::MTLVector > -struct MTLPreconCahnHilliard : BlockPreconditioner +/// Block preconditioner for the Cahn-Hilliard equation +/** + * Based on the paper "Efficient preconditioners for large scale binary + * Cahn-Hilliard models", P.Boyanova, M.Do-Quang, M.Neytcheva + * + * The Cahn-Hilliard equation must be provided in the form: + * + * mu - Phi'(c) + eps^2*laplace(c) = 0 + * -gamma*tau*laplace(mu) + c + tau*(u*nabla)c = c^old + * + * respective in matrix form: + * + * [ M , -(J + eps^2*L) ] [mu] = [Phi'(c^old) - J*c^old] + * [ gamma*tau*L, M + tau*W ] [c ] = [M*c^old ] + * + * with M...mass matrix, L...laplace matrix, J...discretization of + * jacobian of Phi', W...discretization of transport term + * + */ +template<typename MatrixType> +struct MTLPreconChBase : BlockPreconditioner<MatrixType> { - typedef BlockPreconditioner super; + typedef MTLTypes::MTLVector VectorType; + + typedef BlockPreconditioner<MatrixType> super; + typedef MTLPreconChBase<MatrixType> self; + typedef typename super::precon_base precon_base; - class Creator : public PreconditionCreator + struct Creator : public CreatorInterfaceName<precon_base> { - public: - virtual ~Creator() {} - - BasePreconditioner* create() { - return new MTLPreconCahnHilliard(this->name); - } - }; - - - MTLPreconCahnHilliard(std::string name) - : name(name), - eps(NULL), delta(NULL), - solverM(NULL), solverMpL(NULL), runnerM(NULL), runnerMpL(NULL) + virtual ~Creator() {} + precon_base* create() { return new self(this->name); } + }; + + /// constructor + MTLPreconChBase(std::string name) + : name(name), + eps(0.1), gamma(1.0), tau(NULL), + solverM(NULL), solverMpL(NULL), runnerM(NULL), runnerMpL(NULL) { - createSubSolver(name + "->subsolver M", solverM, runnerM); - createSubSolver(name + "->subsolver MpL", solverMpL, runnerMpL); + super::createSubSolver(name + "->subsolver M", solverM, runnerM, "cg", "diag", 5, 1.e-3); + super::createSubSolver(name + "->subsolver MpL", solverMpL, runnerMpL, "cg", "diag", 20, 1.e-3); } - virtual ~MTLPreconCahnHilliard() + /// destructor + virtual ~MTLPreconChBase() { exit(); delete solverM; delete solverMpL; } + /// prepare needed data, e.g. the matrix MpL = M + a*L and initialize the runners + virtual void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); - virtual void init(const typename super::BlockMatrix& A, const MatrixType& fullMatrix); - + /// apply the preconditioner P to a vector b, i.e. solve Px = b virtual void solve(const VectorType& b, VectorType& x) const; - virtual void exit() { runnerM->exit(); runnerMpL->exit(); } + const MatrixType& getM() const { return *matM; } // c + const MatrixType& getL() const { return *matL; } // laplace(c) - const MatrixType& getM() const - { - return A->getSubMatrix(0,0); - } - - - const MatrixType& getL() const - { - return L; // gamma*tau*L - } - - - double getEps() const - { - return *eps; - } - - - double getDelta() const - { - return *delta; - } - + /// return delta = \ref tau * \ref gamma + double getDelta() const { return (*tau) * gamma; } - void setData(double* eps_, double* delta_) + /// the preconditioner needs some data from the Cahn-Hilliard equation. + /// This is passed in the struct data. + template<typename Data> + void setData(Data* data) { - eps = eps_; - delta = delta_; + tau = data->tau; + eps = data->eps; + gamma = data->gamma; + matM = &data->getM(); + matL = &data->getL(); } protected: + /// solve the mass equation Mx = b template <typename VectorX, typename VectorB> void solveM(VectorX& x, const VectorB& b) const { runnerM->solve(getM(), x, b); } - + /// solve a diffusion equation (M+a*L)x = b template <typename VectorX, typename VectorB> void solveMpL(VectorX& x, const VectorB& b) const { runnerMpL->solve(MpL, x, b); } +protected: + MatrixType* matM; + MatrixType* matL; - MatrixType M; MatrixType MpL; - MatrixType L; - mutable MTLVector y1; - mutable MTLVector y2; + mutable VectorType y1; + mutable VectorType y2; - LinearSolver* solverM; - LinearSolver* solverMpL; + LinearSolverInterface* solverM; + LinearSolverInterface* solverMpL; - MTL4Runner<MatrixType, VectorType>* runnerM; - MTL4Runner<MatrixType, VectorType>* runnerMpL; + RunnerBase<MatrixType, VectorType>* runnerM; + RunnerBase<MatrixType, VectorType>* runnerMpL; std::string name; - double* eps; - double* delta; + double eps; + double gamma; + double* tau; }; + +typedef MTLPreconChBase<MTLTypes::MTLMatrix> MTLPreconCahnHilliard; + } } #include "MTLPreconCahnHilliard.hh" diff --git a/extensions/preconditioner/MTLPreconCahnHilliard.hh b/extensions/preconditioner/MTLPreconCahnHilliard.hh index e64f0ec2d14033510cfe4e12e3621f938af3b093..f49202e0782d99ea36e2e55cb219522582d65a7f 100644 --- a/extensions/preconditioner/MTLPreconCahnHilliard.hh +++ b/extensions/preconditioner/MTLPreconCahnHilliard.hh @@ -17,28 +17,16 @@ namespace AMDiS { namespace extensions { -template< typename MatrixType, typename VectorType > -void MTLPreconCahnHilliard< MatrixType, VectorType >::init(const BlockMatrix& A_, const MTLMatrix& fullMatrix_) -{ FUNCNAME("MTLPreconCahnHilliard::init()"); +template< typename MatrixType > +void MTLPreconChBase< MatrixType >::init(const SolverMatrix<Matrix<DOFMatrix*> >& A_, const MatrixType& fullMatrix_) +{ FUNCNAME("MTLPreconChBase::init()"); super::init(A_, fullMatrix_); - - assert(eps != NULL); - assert(delta != NULL); - - const FiniteElemSpace* feSpace = (*A_.getOriginalMat())[0][0]->getFeSpace(); - DOFMatrix laplaceMatrix(feSpace, feSpace); - Operator laplaceOp(feSpace, feSpace); - Simple_SOT sot; - laplaceOp.addTerm(&sot); - laplaceMatrix.assembleOperator(laplaceOp); - - L.change_dim(num_rows(getM()), num_cols(getM())); - L = laplaceMatrix.getBaseMatrix(); + assert(tau != NULL); // helper-matrix MpL = M + eps*sqrt(delta)*L MpL.change_dim(num_rows(getM()), num_cols(getM())); - MpL = getM() + ( getEps()*sqrt(getDelta()) ) * getL(); + MpL = getM() + ( eps*std::sqrt(getDelta()) ) * getL(); // temporary variables y1.change_dim(num_rows(getM())); @@ -49,19 +37,19 @@ void MTLPreconCahnHilliard< MatrixType, VectorType >::init(const BlockMatrix& A_ } -template< typename MatrixType, typename VectorType > -void MTLPreconCahnHilliard< MatrixType, VectorType >::solve(const MTLVector& b, MTLVector& x) const -{ FUNCNAME("MTLPreconCahnHilliard::solve()"); +template< typename MatrixType > +void MTLPreconChBase< MatrixType >::solve(const VectorType& b, VectorType& x) const +{ FUNCNAME("MTLPreconChBase::solve()"); x.change_dim(num_rows(b)); - const MTLVector b1(b[rows[0]]); - const MTLVector b2(b[rows[1]]); + const VectorType b1(b[super::getRowRange(0)]); + const VectorType b2(b[super::getRowRange(1)]); - MTLVector x1(x[rows[0]]); - MTLVector x2(x[rows[1]]); + VectorType x1(x[super::getRowRange(0)]); + VectorType x2(x[super::getRowRange(1)]); - double factor = getEps()/sqrt(getDelta()); + double factor = eps/std::sqrt(getDelta()); solveM(y1, b1); y2 = getL() * y1; diff --git a/extensions/preconditioner/MTLPreconCahnHilliard2.h b/extensions/preconditioner/MTLPreconCahnHilliard2.h new file mode 100644 index 0000000000000000000000000000000000000000..0f08541229a361ffa394335f25e66b4079978d28 --- /dev/null +++ b/extensions/preconditioner/MTLPreconCahnHilliard2.h @@ -0,0 +1,253 @@ +/****************************************************************************** + * + * 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 MTL_CH_PRECONDITIONER2_H +#define MTL_CH_PRECONDITIONER2_H + +#include "AMDiS.h" +#include "solver/BlockPreconditioner.h" + +namespace AMDiS { namespace extensions { + +struct MTLPreconCh2Sub : BlockPreconditioner<MTLTypes::MTLMatrix> +{ + typedef MTLTypes::MTLMatrix MatrixType; + typedef MTLTypes::MTLVector VectorType; + + typedef BlockPreconditioner<MatrixType> super; + typedef MTLPreconCh2Sub self; + + + MTLPreconCh2Sub(std::string name) + : name(name), + eps(0.1), gamma(1.0), tau(NULL), + solverMpL(NULL), runnerMpL(NULL) + { + super::createSubSolver(name + "->subsolver MpL", solverMpL, runnerMpL, "cg", "diag", 10, 1.e-3); + } + + + virtual ~MTLPreconCh2Sub() + { + exit(); + delete solverMpL; + } + + /// prepare needed data, e.g. the matrix MpL = M + a*L and initialize the runners + virtual void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); + + /// apply the preconditioner P to a vector b, i.e. solve Px = b + virtual void solve(const VectorType& b, VectorType& x) const; + + virtual void exit() + { + runnerMpL->exit(); + } + + const MatrixType& getM() const { return *matM; } // c + const MatrixType& getL() const { return *matL; } // laplace(c) + + /// return delta = \ref tau * \ref gamma + double getDelta() const { return (*tau) * gamma; } + + /// the preconditioner needs some data from the Cahn-Hilliard equation. + /// This is passed in the struct data. + template<typename Data> + void setData(Data* data) + { + tau = data->tau; + eps = data->eps; + gamma = data->gamma; + matM = &data->getM(); + matL = &data->getL(); + } + +protected: + /// solve a diffusion equation (M+a*L)x = b + template <typename VectorX, typename VectorB> + void solveMpL(VectorX& x, const VectorB& b) const + { + runnerMpL->solve(MpL, x, b); + } + +protected: + MatrixType* matM; + MatrixType* matL; + + MatrixType MpL; + + mutable VectorType y1; + mutable VectorType y2; + + LinearSolverInterface* solverMpL; + + RunnerBase<MatrixType, VectorType>* runnerMpL; + + std::string name; + + double eps; + double gamma; + double* tau; +}; + + + +template <typename Vector> +itl::pc::solver<MTLPreconCh2Sub, Vector, false> +inline solve(const MTLPreconCh2Sub& P, const Vector& x) +{ + return itl::pc::solver<MTLPreconCh2Sub, Vector, false>(P, x); +} + + + +/// Block preconditioner for the Cahn-Hilliard equation +/** + * Based on the paper "Block-Preconditioners for Conforming and Non-conforming + * FEM Discretizations of the Cahn-Hilliard Equation", P.Boyanova, M.Do-Quang, M.Neytcheva + * + * The Cahn-Hilliard equation must be provided in the form: + * + * mu - Phi'(c) + eps^2*laplace(c) = 0 + * -gamma*tau*laplace(mu) + c + tau*(u*nabla)c = c^old + * + * respective in matrix form: + * + * [ M , -(J + eps^2*L) ] [mu] = [Phi'(c^old) - J*c^old] + * [ gamma*tau*L, M + tau*W ] [c ] = [M*c^old ] + * + * with M...mass matrix, L...laplace matrix, J...discretization of + * jacobian of Phi', W...discretization of transport term + */ +template<typename MatrixType> +struct MTLPreconCh2Base : BlockPreconditioner<MatrixType> +{ + typedef MTLTypes::MTLVector VectorType; + + typedef BlockPreconditioner<MatrixType> super; + typedef MTLPreconCh2Base<MatrixType> self; + typedef typename super::precon_base precon_base; + + struct Creator : public CreatorInterfaceName<precon_base> + { + virtual ~Creator() {} + precon_base* create() { return new self(this->name); } + }; + + + /// constructor + MTLPreconCh2Base(std::string name) + : name(name), + eps(0.1), gamma(1.0), tau(NULL), + preconS(name), PId(NULL), + solverM(NULL), runnerM(NULL) + { + super::createSubSolver(name + "->subsolver M", solverM, runnerM, "cg", "diag", 5, 1.e-3); + } + + + /// destructor + virtual ~MTLPreconCh2Base() + { + exit(); + if (PId) { delete PId; PId = NULL; } + delete solverM; + } + + /// prepare needed data, e.g. the matrix MpL = M + a*L and initialize the runners + virtual void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); + + /// apply the preconditioner P to a vector b, i.e. solve Px = b + virtual void solve(const VectorType& b, VectorType& x) const; + + virtual void exit() + { + runnerM->exit(); + preconS.exit(); + } + + const MatrixType& getM() const { return *matM; } // c + const MatrixType& getL() const { return *matL; } // laplace(c) + + /// return delta = \ref tau * \ref gamma + double getDelta() const { return (*tau) * gamma; } + + /// the preconditioner needs some data from the Cahn-Hilliard equation. + /// This is passed in the struct data. + template<typename Data> + void setData(Data* data) + { + tau = data->tau; + eps = data->eps; + gamma = data->gamma; + matM = &data->getM(); + matL = &data->getL(); + + preconS.setData(data); + } + +protected: + /// solve the mass equation Mx = b + template <typename VectorX, typename VectorB> + void solveM(VectorX& x, const VectorB& b) const + { + runnerM->solve(getM(), x, b); + } + + /// solve a diffusion equation (M+a*L)x = b + template <typename VectorX, typename VectorB> + void solveS(VectorX& x, const VectorB& b) const + { + int nIter = 20; + Parameters::get(name + "->subsolver S->solver->max iteration", nIter); + itl::basic_iteration<double> iter(b, nIter, 1.e-4, 0); + x = 0.0; + itl::fgmres(S, x, b, *PId, preconS, iter, 30); + } + +protected: + MatrixType* matM; + MatrixType* matL; + + MatrixType S; + MatrixType MInv; + + mutable VectorType y1; + mutable VectorType y2; + + double eps; + double gamma; + double* tau; + + MTLPreconCh2Sub preconS; + itl::pc::identity<MatrixType, double> *PId; + + LinearSolverInterface* solverM; + RunnerBase<MatrixType, VectorType>* runnerM; + + std::string name; +}; + + +typedef MTLPreconCh2Base<MTLTypes::MTLMatrix> MTLPreconCahnHilliard2; + +} } + +#include "MTLPreconCahnHilliard2.hh" + +#endif // MTL_CH_PRECONDITIONER2_H + diff --git a/extensions/preconditioner/MTLPreconCahnHilliard2.hh b/extensions/preconditioner/MTLPreconCahnHilliard2.hh new file mode 100644 index 0000000000000000000000000000000000000000..789bd925f08067a16e0b2a5fb8a596b329c83116 --- /dev/null +++ b/extensions/preconditioner/MTLPreconCahnHilliard2.hh @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +namespace AMDiS { namespace extensions { + +void MTLPreconCh2Sub::init(const SolverMatrix<Matrix<DOFMatrix*> >& A_, const MatrixType& fullMatrix_) +{ FUNCNAME("MTLPreconCh2Sub::init()"); + + super::init(A_, fullMatrix_); + assert(tau != NULL); + + // helper-matrix MpL = M + eps*sqrt(delta)*L + MpL.change_dim(num_rows(getM()), num_cols(getM())); + MpL = getM() + ( eps*std::sqrt(getDelta()) ) * getL(); + + y1.change_dim(num_rows(getM())); + y2.change_dim(num_rows(getM())); + + runnerMpL->init(A_, MpL); +} + + +void MTLPreconCh2Sub::solve(const VectorType& b, VectorType& x) const +{ FUNCNAME("MTLPreconCh2Sub::solve()"); + + x.change_dim(num_rows(b)); + + solveMpL(y1, b); + y2 = getM() * y1; + solveMpL(x, y2); +} + + +template< typename MatrixType > +void MTLPreconCh2Base< MatrixType >::init(const SolverMatrix<Matrix<DOFMatrix*> >& A_, const MatrixType& fullMatrix_) +{ FUNCNAME("MTLPreconCh2Base::init()"); + + super::init(A_, fullMatrix_); + assert(tau != NULL); + + mtl::dense_vector<double> diag_M = mtl::matrix::diagonal(getM()); + for (size_t i = 0; i < size(diag_M); i++) + diag_M[i] = 1.0 / diag_M[i]; + MInv = mtl::vector::diagonal(diag_M); + + S.change_dim(num_rows(getM()), num_cols(getM())); + S = getM() + ( sqr(eps)*getDelta() ) * getL() * MInv * getL(); + + PId = new itl::pc::identity<MatrixType, double>(getM()); + + // temporary variables + y1.change_dim(num_rows(getM())); + y2.change_dim(num_rows(getM())); + + runnerM->init(A_, getM()); + preconS.init(A_, S); +} + + +template< typename MatrixType > +void MTLPreconCh2Base< MatrixType >::solve(const VectorType& b, VectorType& x) const +{ FUNCNAME("MTLPreconCh2Base::solve()"); + + x.change_dim(num_rows(b)); + + const VectorType b1(b[super::getRowRange(0)]); + const VectorType b2(b[super::getRowRange(1)]); + + VectorType x1(x[super::getRowRange(0)]); + VectorType x2(x[super::getRowRange(1)]); + + solveM(y1, b1); + y2 = getL() * y1; + x1 = b2 - getDelta() * y2; + + solveS(x2, x1); + y1 = getL() * x2; + y2 = b1 + sqr(eps) * y1; + + solveM(x1, y2); +} + +} } \ No newline at end of file diff --git a/extensions/preconditioner/MTLPreconNavierStokes.h b/extensions/preconditioner/MTLPreconNavierStokes.h new file mode 100644 index 0000000000000000000000000000000000000000..3c1988b351cc14c856c5d00a2c2bd5024411dfe8 --- /dev/null +++ b/extensions/preconditioner/MTLPreconNavierStokes.h @@ -0,0 +1,211 @@ +/****************************************************************************** + * + * 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 MTL_NS_PRECONDITIONER_H +#define MTL_NS_PRECONDITIONER_H + +#include "AMDiS.h" +#include "BlockPreconditioner.h" + +namespace AMDiS { namespace extensions { + +struct MTLPreconNavierStokes : BlockPreconditioner<MTLTypes::MTLMatrix> +{ + typedef MTLTypes::MTLMatrix MatrixType; + typedef MTLTypes::MTLVector VectorType; + + typedef BlockPreconditioner<MatrixType> super; + typedef MTLPreconNavierStokes self; + typedef ITL_BasePreconditioner<MatrixType, VectorType> precon_base; + + class Creator : public CreatorInterfaceName<precon_base> + { + public: + virtual ~Creator() {} + + precon_base* create() { + return new self(this->name); + } + }; + + MTLPreconNavierStokes(std::string name) + : super(), + name(name), + tau(NULL), + pressureComponent(Global::getGeo(WORLD)), + velocitySolutionMode(""), + massSolutionMode(""), + laplaceSolutionMode(""), + massMatrix(NULL), laplaceMatrix(NULL), conDifMatrix(NULL) + massMatrix_(1,1), laplaceMatrix_(1,1), + velocityMatrix_(Global::getGeo(WORLD), Global::getGeo(WORLD)), + divMatrix_(1, Global::getGeo(WORLD)), + gradMatrix_(Global::getGeo(WORLD), 1), + solver_velocity(NULL), runner_velocity(NULL), + solver_mass(NULL), runner_mass(NULL), + solver_laplace(NULL), runner_laplace(NULL) + { + + Parameters::get(name + "->navierstokes->pressure component", + pressureComponent); + + std::string initFileStr_velocity = name + "navierstokes->velocity solver"; + Parameters::get(initFileStr_velocity, velocitySolutionMode); + + std::string initFileStr_mass = name + "navierstokes->mass solver"; + Parameters::get(initFileStr_mass, massSolutionMode); + + std::string initFileStr_laplace = name + "navierstokes->laplace solver"; + Parameters::get(initFileStr_laplace, laplaceSolutionMode); + + // === read solver-name === + std::string solverType_velocity = "mtl_" + velocitySolutionMode; + std::string solverType_mass = "mtl_" + massSolutionMode; + std::string solverType_laplace = "mtl_" + laplaceSolutionMode; + + // velocity solver + LinearSolverCreator *solverCreator_velocity = + dynamic_cast<LinearSolverCreator*>(CreatorMap<LinearSolver>::getCreator(solverType_velocity, initFileStr_velocity)); + TEST_EXIT(solverCreator_velocity) + ("No valid solver type found in parameter \"%s\"\n", initFileStr_velocity.c_str()); + solverCreator_velocity->setName(initFileStr_velocity); + solver_velocity = solverCreator_velocity->create(); + runner_velocity = dynamic_cast<RunnerBase< MatrixType, VectorType >*>(solver_velocity->getRunner()); + + // mass solver + LinearSolverCreator *solverCreator_mass = + dynamic_cast<LinearSolverCreator*>(CreatorMap<LinearSolver>::getCreator(solverType_mass, initFileStr_mass)); + TEST_EXIT(solverCreator_mass) + ("No valid solver type found in parameter \"%s\"\n", initFileStr_mass.c_str()); + solverCreator_mass->setName(initFileStr_mass); + solver_mass = solverCreator_mass->create(); + runner_mass = dynamic_cast<RunnerBase< MatrixType, VectorType >*>(solver_mass->getRunner()); + + // laplace solver + LinearSolverCreator *solverCreator_laplace = + dynamic_cast<LinearSolverCreator*>(CreatorMap<LinearSolver>::getCreator(solverType_laplace, initFileStr_laplace)); + TEST_EXIT(solverCreator_laplace) + ("No valid solver type found in parameter \"%s\"\n", initFileStr_laplace.c_str()); + solverCreator_laplace->setName(initFileStr_laplace); + solver_laplace = solverCreator_laplace->create(); + runner_laplace = dynamic_cast<RunnerBase< MatrixType, VectorType >*>(solver_laplace->getRunner()); + } + + virtual ~MTLPreconNavierStokes() + { + exit(); + } + + void setStokesData(double *invTauPtr, SystemVector *vec, double *nu1_=NULL, double *nu2_=NULL, double *rho1_=NULL, double *rho2_=NULL) + { + nu = new double; + (*nu) = 0.0; + invTau = invTauPtr; + solution = vec; + nu1=nu1_; + nu2=nu2_; + rho1=rho1_; + rho2=rho2_; + } + + void setStokesData(double *nuPtr, double *invTauPtr, SystemVector *vec) + { + nu = nuPtr; + invTau = invTauPtr; + solution = vec; + } + + + void setPhase(DOFVector<double> *d) + { + phase = d; + } + + virtual void init(const typename super::BlockMatrix& A, const MatrixType& fullMatrix); + + virtual void exit() + { + runner_laplace->exit(); + runner_mass->exit(); + runner_velocity->exit(); + + if (massMatrix) { delete massMatrix; massMatrix = NULL; } + if (laplaceMatrix) { delete laplaceMatrix; laplaceMatrix = NULL; } + if (conDifMatrix) { delete conDifMatrix; conDifMatrix = NULL; } + if (solver_velocity) { delete solver_velocity; solver_velocity = NULL; } + if (solver_mass) { delete solver_mass; solver_mass = NULL; } + if (solver_laplace) { delete solver_laplace; solver_laplace = NULL; } + } + + virtual void solve(const MTLVector& b, MTLVector& x) const; + + const MatrixType& getM() const { return massMatrix->getBaseMatrix(); } + const MatrixType& getL() const { return laplaceMatrix->getBaseMatrix(); } + const MatrixType& getConDif() const { return conDifMatrix->getBaseMatrix(); } + const MatrixType& getMatV() const { return blockVelocityMatrix->getMatrix(); } + + const MatrixType& getMatDiv() const { return blockDivMatrix->getMatrix(); } + const MatrixType& getMatGrad() const { return blockGradMatrix->getMatrix(); } + +protected: + DOFMatrix* massMatrix; + DOFMatrix* laplaceMatrix; + DOFMatrix* conDifMatrix; + + mtl::irange vel_rows; + + Matrix<DOFMatrix*> massMatrix_; + SolverMatrix<Matrix<DOFMatrix*> > blockMassMatrix; + + Matrix<DOFMatrix*> laplaceMatrix_; + SolverMatrix<Matrix<DOFMatrix*> > blockLaplaceMatrix; + + Matrix<DOFMatrix*> velocityMatrix_; + SolverMatrix<Matrix<DOFMatrix*> > blockVelocityMatrix; + + Matrix<DOFMatrix*> divMatrix_; + SolverMatrix<Matrix<DOFMatrix*> > blockDivMatrix; + + Matrix<DOFMatrix*> gradMatrix_; + SolverMatrix<Matrix<DOFMatrix*> > blockGradMatrix; + + mutable VectorType y01; + mutable VectorType y2; + + int pressureComponent; + std::string velocitySolutionMode; + std::string massSolutionMode; + std::string laplaceSolutionMode; + + LinearSolverInterface* solver_velocity; + LinearSolverInterface* solver_mass; + LinearSolverInterface* solver_laplace; + + RunnerBase< MatrixType, VectorType >* runner_velocity; + RunnerBase< MatrixType, VectorType >* runner_mass; + RunnerBase< MatrixType, VectorType >* runner_laplace; + + std::string name; + + double *nu, *invTau, *nu1,*nu2,*rho1,*rho2; +}; + +} } + +#include "MTLPreconNavierStokes.hh" + +#endif // MTL_NS_PRECONDITIONER_H + diff --git a/extensions/preconditioner/MTLPreconNavierStokes.hh b/extensions/preconditioner/MTLPreconNavierStokes.hh new file mode 100644 index 0000000000000000000000000000000000000000..c86b7afb1a19681a2bf92382ea808283c2ec462b --- /dev/null +++ b/extensions/preconditioner/MTLPreconNavierStokes.hh @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * 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. + * + ******************************************************************************/ + +namespace AMDiS { namespace extensions { + +void MTLPreconNavierStokes::init(const BlockMatrix& A_, const MatrixType& fullMatrix_) +{ + super::init(A_, fullMatrix_); + + // === extract velocity rows === + BlockMapper mapper(A_); + mapper.setRow(Global::getGeo(WORLD)); + vel_rows.set(0, mapper.row(0)); + + // === create submatrices === + Matrix<DOFMatrix*>* mat = A_.getOriginalMat(); + for (int i = 0; i < Global::getGeo(WORLD); i++) { + for (int j = 0; j < Global::getGeo(WORLD); j++) { + velocityMatrix_[i][j] = (*mat)[i][j]; + } + } + blockVelocityMatrix.setMatrix(velocityMatrix_); + runner_velocity.init(blockVelocityMatrix, getMatV()); // TODO: eventuell auf neues Erzeugen verzichten! + + for (int j = 0; j < Global::getGeo(WORLD); j++) + divMatrix_[0][j] = (*mat)[pressureComponent][j]; + blockDivMatrix.setMatrix(divMatrix_); + + for (int i = 0; i < Global::getGeo(WORLD); i++) + gradMatrix_[i][0] = (*mat)[i][pressureComponent]; + blockGradMatrix.setMatrix(gradMatrix_); + + + const FiniteElemSpace *pressureFeSpace = componentSpaces[pressureComponent]; + + // === Mass matrix solver === + massMatrix = new DOFMatrix(pressureFeSpace, pressureFeSpace); + { + Operator massOp(pressureFeSpace, pressureFeSpace); + if ((!phase) || (*nu == 0.0)) + addZOT(massOp, 1.0); + else + addZOT(massOp, valueOf(phase)); + massMatrix->assembleOperator(massOp); + } + massMatrix_(0,0) = massMatrix; + blockMassMatrix.setMatrix(massMatrix_); + runner_mass.init(blockMassMatrix, getM()); + + + // === Laplace matrix solver === + laplaceMatrix = new DOFMatrix(pressureFeSpace, pressureFeSpace); + { + Operator laplaceOp(pressureFeSpace, pressureFeSpace); + if ((!phase) || (*nu == 0.0)) + addSOT(laplaceOp, 1.0); + else + addSOT(laplaceOp, valueOf(phase)); + laplaceMatrix.assembleOperator(laplaceOp); + } + laplaceMatrix_(0,0) = laplaceMatrix; + blockLaplaceMatrix.setMatrix(laplaceMatrix_); + runner_laplace.init(blockLaplaceMatrix, getL()); + + + // === Create convection-diffusion operator === + conDifMatrix = new DOFMatrix(pressureFeSpace, pressureFeSpace); + { + Operator conDifOp(pressureFeSpace, pressureFeSpace); + + DOFVector<double> vp(pressureFeSpace, "vp"); + + WorldVector<DOFVector<double>*> V; + for (int i = 0; i < V.getSize(); i++) { + V[i] = new DOFVector<double>(pressureFeSpace, "v_i"); + V[i]->interpol(solution->getDOFVector(i)); + } + + if (!phase) { // no phase given + MSG("INIT WITHOUT PHASE!\n"); + addZOT(conDifOp, *invTau); + addZOT(conDifOp, *nu); + addFOT(conDifOp, valueOf(V), GRD_PHI); + } else { + vp.interpol(phase); + + if (*nu > 0.0) { + addZOT(conDifOp, valueOf(vp) * (*invTau)); + addSOT(conDifOp, valueOf(vp) * (*nu)); + addFOT(conDifOp, valueOf(vp) * valueOf(V), GRD_PHI); + } else { + addZOT(conDifOp, function_(wrap(new LinearInterpolation(*rho1,*rho2,*invTau)), valueOf(vp)) ); + addSOT(conDifOp, function_(wrap(new LinearInterpolation(*nu1,*nu2)), valueOf(vp)) ); + addFOT(conDifOp, valueOf(V) * function_(wrap(new LinearInterpolation(*rho1,*rho2)), valueOf(vp)), GRD_PHI ); + } + } + conDifMatrix->assembleOperator(conDifOp); + + for (int i = 0; i < V.getSize(); i++) + delete V[i]; + } + + // temporary variables + y01.change_dim(num_rows(getMatV())); + y2.change_dim(num_rows(getM())); +} + + +void MTLPreconNavierStokes::solve(const VectorType& b, VectorType& x) const +{ FUNCNAME("MTLPreconNavierStokes::solve()"); + + x.change_dim(num_rows(b)); + + const VectorType b01(b[vel_rows]); + const VectorType b2(b[rows[pressureComponent]]); + + VectorType x01(x[vel_rows]); + VectorType x2(x[rows[pressureComponent]]); + + runner_velocity->solve(getMatV(), y01, b01); // -> y01 + y2 = b2 - getMatDiv() * y01; // -> y2 + runner_laplace->solve(getL(), x2, y2); // -> x2 + + // project out constant Null-space + double vecSum = sum(x2) / size(x2); + x2 -= vecSum; // -> x2 -= sum(x2)/size(x2) + + y2 = getMatConDif() * x2; // -> y2 + runner_mass->solve(getM(), x2, y2); // => x2 + + y01 = b01 - getMatGrad() * x2; // -> y01 + runner_velocity->solve(getMatV(), x01, y01); // => x01 +} + +} } diff --git a/extensions/preconditioner/MTLPreconPfc.h b/extensions/preconditioner/MTLPreconPfc.h index 4294bbb93156cc3ce724c40bda7a92e7fdf7958e..21c16a66dd7b42207405b9f86299d78a8ba07d77 100644 --- a/extensions/preconditioner/MTLPreconPfc.h +++ b/extensions/preconditioner/MTLPreconPfc.h @@ -18,7 +18,7 @@ #define MTL_PFC_PRECONDITIONER_H #include "AMDiS.h" -#include "BlockPreconditioner.h" +#include "solver/BlockPreconditioner.h" #include <boost/numeric/mtl/interface/umfpack_solve.hpp> @@ -27,39 +27,45 @@ namespace AMDiS { namespace extensions { using namespace std; using namespace AMDiS::MTLTypes; -struct MTLPreconPfc : BlockPreconditioner +template<typename MatrixType> +struct MTLPreconPfcBase : BlockPreconditioner<MatrixType> { - typedef BlockPreconditioner super; + typedef BlockPreconditioner<MatrixType> super; + typedef ITL_BasePreconditioner<MatrixType, MTLTypes::MTLVector> precon_base; + typedef MTLPreconPfcBase<MatrixType> self; - class Creator : public PreconditionCreator + class Creator : public CreatorInterfaceName<precon_base> { public: virtual ~Creator() {} - BasePreconditioner* create() { - return new MTLPreconPfc(this->name); + precon_base* create() { + return new self(this->name); } }; - MTLPreconPfc(std::string name) - : BlockPreconditioner(), - name(name), - tau(NULL), - PId(NULL), PDiagM(NULL), PDiagMpL(NULL), PDiagMpL2(NULL), - solverM(NULL), solverMpL(NULL), solverMpL2(NULL) + MTLPreconPfcBase(std::string name) + : super(), + name(name), + tau(NULL), + PId(NULL), PDiagM(NULL), PDiagMpL(NULL), PDiagMpL2(NULL), + solverM(NULL), solverMpL(NULL), solverMpL2(NULL) { } - virtual ~MTLPreconPfc() + virtual ~MTLPreconPfcBase() { exit(); } - void setData(double* tau_) + template<typename Data> + void setData(Data* data) { - tau = tau_; + tau = data->tau; + matM = &data->getM(); + matL = &data->getL(); } - virtual void init(const typename super::BlockMatrix& A, const MTLTypes::MTLMatrix& fullMatrix); + virtual void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); virtual void exit() { @@ -132,11 +138,14 @@ struct MTLPreconPfc : BlockPreconditioner } - const MTLMatrix& getM() const { return A->getSubMatrix(2,2); } - const MTLMatrix& getL() const { return A->getSubMatrix(2,1); } + const MTLMatrix& getM() const { return *matM; } + const MTLMatrix& getL() const { return *matL; } double getTau() const { return *tau; } protected: + MTLMatrix* matM; + MTLMatrix* matL; + MTLMatrix MpL; MTLMatrix MpL2; @@ -144,20 +153,22 @@ protected: mutable MTLVector y1; mutable MTLVector tmp; - itl::pc::identity<MTLTypes::MTLMatrix, double> *PId; - itl::pc::diagonal<MTLTypes::MTLMatrix, double> *PDiagM; - itl::pc::diagonal<MTLTypes::MTLMatrix, double> *PDiagMpL; - itl::pc::diagonal<MTLTypes::MTLMatrix, double> *PDiagMpL2; + itl::pc::identity<MTLMatrix, double> *PId; + itl::pc::diagonal<MTLMatrix, double> *PDiagM; + itl::pc::diagonal<MTLMatrix, double> *PDiagMpL; + itl::pc::diagonal<MTLMatrix, double> *PDiagMpL2; - mtl::matrix::umfpack::solver<MTLTypes::MTLMatrix> *solverM; - mtl::matrix::umfpack::solver<MTLTypes::MTLMatrix> *solverMpL; - mtl::matrix::umfpack::solver<MTLTypes::MTLMatrix> *solverMpL2; + mtl::matrix::umfpack::solver<MTLMatrix> *solverM; + mtl::matrix::umfpack::solver<MTLMatrix> *solverMpL; + mtl::matrix::umfpack::solver<MTLMatrix> *solverMpL2; std::string name; double* tau; }; +typedef MTLPreconPfcBase<MTLTypes::MTLMatrix> MTLPreconPfc; + } } #include "MTLPreconPfc.hh" diff --git a/extensions/preconditioner/MTLPreconPfc.hh b/extensions/preconditioner/MTLPreconPfc.hh index 28ddde0e21a41ab3404a53f62eca20ac4995e3b9..d10df58f22208f586f24d0398fa0ae7085876148 100644 --- a/extensions/preconditioner/MTLPreconPfc.hh +++ b/extensions/preconditioner/MTLPreconPfc.hh @@ -17,7 +17,8 @@ namespace AMDiS { namespace extensions { -void MTLPreconPfc::init(const BlockMatrix& A_, const MTLMatrix& fullMatrix_) +template<typename MatrixType> +void MTLPreconPfcBase<MatrixType>::init(const SolverMatrix<Matrix<DOFMatrix*> >& A_, const MatrixType& fullMatrix_) { assert(tau != NULL); super::init(A_, fullMatrix_); @@ -66,18 +67,19 @@ void MTLPreconPfc::init(const BlockMatrix& A_, const MTLMatrix& fullMatrix_) } -void MTLPreconPfc::solve(const MTLVector& b, MTLVector& x) const +template<typename MatrixType> +void MTLPreconPfcBase<MatrixType>::solve(const MTLVector& b, MTLVector& x) const { FUNCNAME("MTLPreconPfc::solve()"); x.change_dim(num_rows(b)); - const MTLVector b0(b[rows[0]]); - const MTLVector b1(b[rows[1]]); - const MTLVector b2(b[rows[2]]); + MTLVector x0(x[super::getRowRange(0)]); + MTLVector x1(x[super::getRowRange(1)]); + MTLVector x2(x[super::getRowRange(2)]); - MTLVector x0(x[rows[0]]); - MTLVector x1(x[rows[1]]); - MTLVector x2(x[rows[2]]); + const MTLVector b0(b[super::getRowRange(0)]); + const MTLVector b1(b[super::getRowRange(1)]); + const MTLVector b2(b[super::getRowRange(2)]); double delta = std::sqrt(getTau()); diff --git a/extensions/preconditioner/PetscPreconCahnHilliard.cc b/extensions/preconditioner/PetscPreconCahnHilliard.cc index 684cf2f31ad3f0df631e8c027d6b1b3605ca9100..263472997393af910aa4a3a4b2efc6b897986e34 100644 --- a/extensions/preconditioner/PetscPreconCahnHilliard.cc +++ b/extensions/preconditioner/PetscPreconCahnHilliard.cc @@ -57,28 +57,26 @@ namespace AMDiS { } - void PetscPreconCahnHilliard::init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& src) - { - super::init(A, src); - - PCSetType(getPc(), PCSHELL); - PCShellSetApply(getPc(), pcChShell); - PCShellSetContext(getPc(), &data); + void PetscPreconCahnHilliard::init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >&, const MatrixType& A) + { + PCSetType(pc, PCSHELL); + PCShellSetApply(pc, pcChShell); + PCShellSetContext(pc, &data); - MatNestGetSubMat(src.matrix, 1, 0, &data.matM); + MatNestGetSubMat(A.matrix, 1, 0, &data.matM); MatDuplicate(data.matM, MAT_COPY_VALUES, &data.matMinusDeltaK); MatScale(data.matMinusDeltaK, -1.0); - MatNestGetSubMat(src.matrix, 0, 0, &data.matM); + MatNestGetSubMat(A.matrix, 0, 0, &data.matM); MatDuplicate(data.matM, MAT_COPY_VALUES, &MpK); MatAXPY(MpK, -(*eps)/sqrt(*delta), data.matMinusDeltaK, SAME_NONZERO_PATTERN); - createSubSolver(data.kspM, data.matM, "mass_"); - createSubSolver(data.kspMpK, MpK, "MpK_"); + Runner::createSubSolver(data.kspM, data.matM, "mass_"); + Runner::createSubSolver(data.kspMpK, MpK, "MpK_"); - setSolver(data.kspM, "mass_", KSPCG, PCJACOBI, 0.0, 1e-14, 15); - setSolver(data.kspMpK, "MpK_", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 15); + Runner::setSolver(data.kspM, "mass_", KSPCG, PCJACOBI, 0.0, 1e-14, 15); + Runner::setSolver(data.kspMpK, "MpK_", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 15); // === Setup preconditioner data === data.delta = *delta; @@ -93,7 +91,5 @@ namespace AMDiS { KSPDestroy(&data.kspM); KSPDestroy(&data.kspMpK); - - super::exit(); } } diff --git a/extensions/preconditioner/PetscPreconCahnHilliard.h b/extensions/preconditioner/PetscPreconCahnHilliard.h index efb208b57e7cd508504ccf28fd295ee83e62d42b..d9d9eb4d05d98587bd94992a8ce8c9d84d3e444e 100644 --- a/extensions/preconditioner/PetscPreconCahnHilliard.h +++ b/extensions/preconditioner/PetscPreconCahnHilliard.h @@ -31,18 +31,27 @@ namespace AMDiS { double delta, eps; }; - class PetscPreconCahnHilliard : public PetscRunner<PetscMatrixNested, PetscVectorNested> + class PetscPreconCahnHilliard : public PetscPreconditionerNested { public: - typedef PetscPreconCahnHilliard self; - typedef PetscRunner<PetscMatrixNested, PetscVectorNested> super; + typedef PetscMatrixNested MatrixType; + typedef PetscVectorNested VectorType; - PetscPreconCahnHilliard(LinearSolverInterface* oem_) - : super(oem_), + typedef PetscPreconditionerNested super; + typedef PetscPreconCahnHilliard self; + typedef PetscRunner<MatrixType, VectorType> Runner; + + struct Creator : CreatorInterfaceName<super> + { + virtual ~Creator() {} + super* create() { return new self(); } + }; + + PetscPreconCahnHilliard() + : super("ch_", "ch"), MpK(PETSC_NULL), eps(NULL), - delta(NULL) - { } + delta(NULL) { } void setData(double *epsPtr, double *deltaPtr) { @@ -50,7 +59,7 @@ namespace AMDiS { delta = deltaPtr; } - void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& fullMatrix); + void init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); void exit(); private: diff --git a/extensions/preconditioner/PetscPreconPfc.cc b/extensions/preconditioner/PetscPreconPfc.cc index 91a56e9cc31132a05e7dcab57cc29144d6b964ac..22b06545a28dd439c6913f46ba26aca621133423 100644 --- a/extensions/preconditioner/PetscPreconPfc.cc +++ b/extensions/preconditioner/PetscPreconPfc.cc @@ -14,8 +14,9 @@ * See also license.opensource.txt in the distribution. * ******************************************************************************/ + + #include "PetscPreconPfc.h" -// #include "TimeTracer.h" namespace AMDiS { @@ -71,21 +72,21 @@ namespace AMDiS { } - void PetscPreconPfc::init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& src) - { + void PetscPreconPfc::init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >&, const MatrixType& A) + { FUNCNAME("PetscPreconPfc::init()"); + assert(tau != NULL); - super::init(A, src); // init shell preconditioner - PCSetType(getPc(), PCSHELL); - PCShellSetApply(getPc(), pcPfcShell); - PCShellSetContext(getPc(), &data); + PCSetType(pc, PCSHELL); + PCShellSetApply(pc, pcPfcShell); + PCShellSetContext(pc, &data); double delta = sqrt(*tau); - MatNestGetSubMat(src.matrix, 2, 2, &data.matM); - MatNestGetSubMat(src.matrix, 2, 1, &data.matK); + MatNestGetSubMat(A.matrix, 2, 2, &data.matM); + MatNestGetSubMat(A.matrix, 2, 1, &data.matK); MatDuplicate(data.matM, MAT_COPY_VALUES, &MpK); MatAXPY(MpK, delta, data.matK, SAME_NONZERO_PATTERN); @@ -94,9 +95,9 @@ namespace AMDiS { MatAXPY(MpK2, sqrt(delta), data.matK, SAME_NONZERO_PATTERN); // init sub-solvers - createSubSolver(data.kspM, data.matM, "mass_"); - createSubSolver(data.kspMpK, MpK, "MpK_"); - createSubSolver(data.kspMpK2, MpK2, "MpK2_"); + Runner::createSubSolver(data.kspM, data.matM, "mass_"); + Runner::createSubSolver(data.kspMpK, MpK, "MpK_"); + Runner::createSubSolver(data.kspMpK2, MpK2, "MpK2_"); data.delta = delta; data.tau = *tau; @@ -118,12 +119,12 @@ namespace AMDiS { bool useAMG = false; Parameters::get("precon_pfc_MpL2->use AMG", useAMG); - setSolver(data.kspM, "M_", KSPCG, PCJACOBI, rtolM, tolM, nIterM); - setSolver(data.kspMpK, "MpK_", KSPCG, PCJACOBI, rtolMpL, tolMpL, nIterMpL); + Runner::setSolver(data.kspM, "M_", KSPCG, PCJACOBI, rtolM, tolM, nIterM); + Runner::setSolver(data.kspMpK, "MpK_", KSPCG, PCJACOBI, rtolMpL, tolMpL, nIterMpL); if (!useAMG) { - setSolver(data.kspMpK2, "MpK2_", KSPCG, PCJACOBI, rtolMpL2, tolMpL2, nIterMpL2); + Runner::setSolver(data.kspMpK2, "MpK2_", KSPCG, PCJACOBI, rtolMpL2, tolMpL2, nIterMpL2); } else { - setSolver(data.kspMpK2, "MpK2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); + Runner::setSolver(data.kspMpK2, "MpK2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); } } @@ -136,7 +137,5 @@ namespace AMDiS { KSPDestroy(&data.kspM); KSPDestroy(&data.kspMpK); KSPDestroy(&data.kspMpK2); - - super::exit(); } } diff --git a/extensions/preconditioner/PetscPreconPfc.h b/extensions/preconditioner/PetscPreconPfc.h index 1a6a7c8978b018aa590210ea7b3065bb9aeeeadb..a61ba554b2011950d58ab2b0ddbd7242bea04f91 100644 --- a/extensions/preconditioner/PetscPreconPfc.h +++ b/extensions/preconditioner/PetscPreconPfc.h @@ -30,15 +30,25 @@ namespace AMDiS { double delta, tau; }; - class PetscPreconPfc : public PetscRunner<PetscMatrixNested, PetscVectorNested> + class PetscPreconPfc : public PetscPreconditionerNested { public: - typedef PetscPreconPfc self; - typedef PetscRunner<PetscMatrixNested, PetscVectorNested> super; + typedef PetscMatrixNested MatrixType; + typedef PetscVectorNested VectorType; + typedef PetscPreconditionerNested super; + typedef PetscPreconPfc self; + typedef PetscRunner<MatrixType, VectorType> Runner; - PetscPreconPfc(LinearSolverInterface* oem_) - : super(oem_), + struct Creator : CreatorInterfaceName<super> + { + virtual ~Creator() {} + super* create() { return new self(); } + }; + + public: + PetscPreconPfc() + : super("pfc_", "pfc"), tau(NULL) { } @@ -47,8 +57,8 @@ namespace AMDiS { tau = tauPtr; } - void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& fullMatrix); - void exit(); + void init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix) override; + void exit() override; private: Mat MpK; diff --git a/extensions/preconditioner/PetscPreconPfcDiag.cc b/extensions/preconditioner/PetscPreconPfcDiag.cc index 36632edd6cff301b9aa1dea9e7c9186fe24c8e8a..2afb0ae30da6e1595bde9b95ebbe4265951053ca 100644 --- a/extensions/preconditioner/PetscPreconPfcDiag.cc +++ b/extensions/preconditioner/PetscPreconPfcDiag.cc @@ -23,7 +23,8 @@ namespace AMDiS { /// solve Pfc Preconditioner PetscErrorCode pcPfcDiagShell(PC pc, Vec b, Vec x) // solve Px=b - { + { FUNCNAME("pcPfcShell()"); + void *ctx; PCShellGetContext(pc, &ctx); PfcDiagData* data = static_cast<PfcDiagData*>(ctx); @@ -69,21 +70,19 @@ namespace AMDiS { } - void PetscPreconPfcDiag::init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& src) + void PetscPreconPfcDiag::init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >&, const MatrixType& A) { assert(tau != NULL); - super::init(A, src); // init shell preconditioner - PCSetType(getPc(), PCSHELL); - PCShellSetApply(getPc(), pcPfcDiagShell); - PCShellSetContext(getPc(), &data); - + PCSetType(pc, PCSHELL); + PCShellSetApply(pc, pcPfcDiagShell); + PCShellSetContext(pc, &data); double delta = sqrt(*tau); - MatNestGetSubMat(src.matrix, 2, 2, &data.matM); - MatNestGetSubMat(src.matrix, 2, 1, &data.matK); + MatNestGetSubMat(A.matrix, 2, 2, &data.matM); + MatNestGetSubMat(A.matrix, 2, 1, &data.matK); MatDuplicate(data.matM, MAT_COPY_VALUES, &MpK); MatAXPY(MpK, delta, data.matK, SAME_NONZERO_PATTERN); @@ -100,17 +99,17 @@ namespace AMDiS { MatGetDiagonal(data.matM, x); VecReciprocal(x); - MatDiagonalScale(DK, x, PETSC_NULL); // DK := M_D^(-1)*K + MatDiagonalScale(DK, x, PETSC_NULL); // DK := M_D^(-1)*K MatMatMult(data.matK, DK, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &matS); // S := K*DK MatAYPX(matS, delta, data.matM, DIFFERENT_NONZERO_PATTERN); // S = delta*S + M - MatAXPY(matS, (-2.0*delta), data.matK, DIFFERENT_NONZERO_PATTERN); // S = S - 2*delta*K + MatAXPY(matS, (-2.0*delta), data.matK, DIFFERENT_NONZERO_PATTERN); // S = S - 2*delta*K VecDestroy(&x); MatDestroy(&DK); // init sub-solvers - createSubSolver(data.kspM, data.matM, "mass_"); - createSubSolver(data.kspMpK, MpK, "MpK_"); - createSubSolver(data.kspS, matS, "MpK2_"); + Runner::createSubSolver(data.kspM, data.matM, "mass_"); + Runner::createSubSolver(data.kspMpK, MpK, "MpK_"); + Runner::createSubSolver(data.kspS, matS, "MpK2_"); data.delta = delta; data.tau = *tau; @@ -131,25 +130,25 @@ namespace AMDiS { bool useAMG = false; Parameters::get("precon_pfc_MpL2->use AMG", useAMG); - setSolver(data.kspM, "M_", KSPCG, PCJACOBI, rtolM, tolM, nIterM); - setSolver(data.kspMpK, "MpK_", KSPCG, PCJACOBI, rtolMpL, tolMpL, nIterMpL); + Runner::setSolver(data.kspM, "M_", KSPCG, PCJACOBI, rtolM, tolM, nIterM); + Runner::setSolver(data.kspMpK, "MpK_", KSPCG, PCJACOBI, rtolMpL, tolMpL, nIterMpL); if (!useAMG) { - setSolver(data.kspS, "MpK2_", KSPCG, PCJACOBI, rtolMpL2, tolMpL2, nIterMpL2); + Runner::setSolver(data.kspS, "MpK2_", KSPCG, PCJACOBI, rtolMpL2, tolMpL2, nIterMpL2); } else { - setSolver(data.kspS, "MpK2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); + Runner::setSolver(data.kspS, "MpK2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); } } void PetscPreconPfcDiag::exit() - { + { + FUNCNAME("PetscPreconPfcDiag::exit()"); + MatDestroy(&MpK); MatDestroy(&matS); KSPDestroy(&data.kspM); KSPDestroy(&data.kspMpK); KSPDestroy(&data.kspS); - - super::exit(); } } diff --git a/extensions/preconditioner/PetscPreconPfcDiag.h b/extensions/preconditioner/PetscPreconPfcDiag.h index 553548dab77ba45d06defa14147bd88806e81dd5..bf363bf1a408efd2f57ee6d8c4c0c7b06e8ff1de 100644 --- a/extensions/preconditioner/PetscPreconPfcDiag.h +++ b/extensions/preconditioner/PetscPreconPfcDiag.h @@ -30,14 +30,25 @@ namespace AMDiS { double delta, tau; }; - class PetscPreconPfcDiag : public PetscRunner<PetscMatrixNested, PetscVectorNested> + class PetscPreconPfcDiag : public PetscPreconditionerNested { public: - typedef PetscPreconPfcDiag self; - typedef PetscRunner<PetscMatrixNested, PetscVectorNested> super; + typedef PetscMatrixNested MatrixType; + typedef PetscVectorNested VectorType; - PetscPreconPfcDiag(LinearSolverInterface* oem_) - : super(oem_), + typedef PetscPreconditionerNested super; + typedef PetscPreconPfcDiag self; + typedef PetscRunner<MatrixType, VectorType> Runner; + + struct Creator : CreatorInterfaceName<super> + { + virtual ~Creator() {} + super* create() { return new self(); } + }; + + public: + PetscPreconPfcDiag() + : super("pfc_", "pfc_diag"), tau(NULL) { } @@ -46,7 +57,7 @@ namespace AMDiS { tau = tauPtr; } - void init(const SolverMatrix<Matrix<DOFMatrix*> >& A, const PetscMatrixNested& fullMatrix); + void init(PC pc, const SolverMatrix<Matrix<DOFMatrix*> >& A, const MatrixType& fullMatrix); void exit(); private: diff --git a/extensions/preconditioner/PetscSolverNavierStokes2.cc b/extensions/preconditioner/PetscSolverNavierStokes2.cc index 5792dd75b2eed2687b18c90cc7596cb3824cdc55..3e6e9209712682b176eebe473a9fec8d6995f146 100644 --- a/extensions/preconditioner/PetscSolverNavierStokes2.cc +++ b/extensions/preconditioner/PetscSolverNavierStokes2.cc @@ -133,7 +133,11 @@ namespace AMDiS { namespace Parallel { { // Create FGMRES based outer solver KSPCreate(domainComm, &ksp); +#if (PETSC_VERSION_MINOR >= 5) + KSPSetOperators(ksp, getMatInterior(), getMatInterior()); +#else KSPSetOperators(ksp, getMatInterior(), getMatInterior(), SAME_NONZERO_PATTERN); +#endif if (getInfo() >= 10) KSPMonitorSet(ksp, KSPMonitorDefault, PETSC_NULL, PETSC_NULL); else if (getInfo() >= 20) diff --git a/extensions/preconditioner/PetscSolverNavierStokes2.h b/extensions/preconditioner/PetscSolverNavierStokes2.h index 9fa2d05cccc93bc9af504a92a512ccf47b676f23..091ff96d0ebba01678942dfa7cccca797857d67a 100644 --- a/extensions/preconditioner/PetscSolverNavierStokes2.h +++ b/extensions/preconditioner/PetscSolverNavierStokes2.h @@ -105,7 +105,7 @@ namespace AMDiS { namespace Parallel { virtual ~Creator() {} /// Returns a new PetscSolver object. - LinearSolverInterface* create() + LinearSolver* create() { return new PetscSolverNavierStokes2(this->name); } diff --git a/extensions/preconditioner/PetscSolverPfc.cc b/extensions/preconditioner/PetscSolverPfc.cc index 7f618bc40bc886925ff4e1356f03cde73875be3d..6101c175092439fb047b295f3bf985e080366717 100644 --- a/extensions/preconditioner/PetscSolverPfc.cc +++ b/extensions/preconditioner/PetscSolverPfc.cc @@ -166,6 +166,7 @@ namespace AMDiS { namespace Parallel { int nIterM=5, nIterMpL=20, nIterMpL2=10; double tolM=PETSC_DEFAULT, tolMpL=PETSC_DEFAULT, tolMpL2=PETSC_DEFAULT; double rtolM=PETSC_DEFAULT, rtolMpL=PETSC_DEFAULT, rtolMpL2=PETSC_DEFAULT; + bool directM = false, directMpL = false, directMpL2 = false; Parameters::get("precon_pfc_M->max iteration", nIterM); Parameters::get("precon_pfc_MpL->max iteration", nIterMpL); Parameters::get("precon_pfc_MpL2->max iteration", nIterMpL2); @@ -176,16 +177,29 @@ namespace AMDiS { namespace Parallel { Parameters::get("precon_pfc_MpL->relative tolerance", rtolMpL); Parameters::get("precon_pfc_MpL2->relative tolerance", rtolMpL2); + Parameters::get("precon_pfc_M->use direct solver", directM); + Parameters::get("precon_pfc_MpL->use direct solver", directMpL); + Parameters::get("precon_pfc_MpL2->use direct solver", directMpL2); + bool useAMG = false; Parameters::get("precon_pfc_MpL2->use AMG", useAMG); - petsc_helper::setSolver(data.kspM, "M_", KSPCG, PCJACOBI, rtolM, tolM, nIterM); - petsc_helper::setSolver(data.kspMpK, "MpK_", KSPCG, PCJACOBI, rtolMpL, tolMpL, nIterMpL); - if (!useAMG) { - petsc_helper::setSolver(data.kspMpK2, "MpK2_", KSPCG, PCJACOBI, rtolMpL2, tolMpL2, nIterMpL2); - } else { - petsc_helper::setSolver(data.kspMpK2, "MpK2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); - } + if (directM) + petsc_helper::setSolverWithLu(data.kspM, "M_", KSPRICHARDSON, PCLU, MATSOLVERMUMPS , 0.0, 1e-14, 1); + else + petsc_helper::setSolver(data.kspM, "M_", KSPCG, PCBJACOBI, rtolM, tolM, nIterM); + + if (directMpL) + petsc_helper::setSolverWithLu(data.kspMpK, "MpL_", KSPRICHARDSON, PCLU, MATSOLVERMUMPS , 0.0, 1e-14, 1); + else + petsc_helper::setSolver(data.kspMpK, "MpL_", KSPCG, PCBJACOBI, rtolMpL, tolMpL, nIterMpL); + + if (directMpL2) + petsc_helper::setSolverWithLu(data.kspMpK2, "MpL2_", KSPRICHARDSON, PCLU, MATSOLVERMUMPS , 0.0, 1e-14, 1); + else if (useAMG) + petsc_helper::setSolver(data.kspMpK2, "MpL2_", KSPRICHARDSON, PCHYPRE, rtolMpL2, tolMpL2, nIterMpL2); + else + petsc_helper::setSolver(data.kspMpK2, "MpL2_", KSPCG, PCBJACOBI, rtolMpL2, tolMpL2, nIterMpL2); } diff --git a/extensions/preconditioner/PetscSolverPfc.h b/extensions/preconditioner/PetscSolverPfc.h index 0fb7674cbd08fb37e2626082cb51627d5bb265ca..b358410f3fc98d465fbdfea4ae874c300853ccf9 100644 --- a/extensions/preconditioner/PetscSolverPfc.h +++ b/extensions/preconditioner/PetscSolverPfc.h @@ -31,27 +31,24 @@ namespace AMDiS { namespace Parallel { class PetscSolverPfc : public PetscSolverGlobalBlockMatrix { public: + typedef PetscSolverPfc self; + typedef PetscSolverGlobalBlockMatrix super; + /// Creator class - class Creator : public LinearSolverCreator + struct Creator : public LinearSolverCreator { - public: virtual ~Creator() {} - - /// Returns a new PetscSolver object. - LinearSolverInterface* create() - { - return new PetscSolverPfc(this->name); - } + LinearSolverInterface* create() { return new self(this->name); } }; PetscSolverPfc(std::string name) - : PetscSolverGlobalBlockMatrix(name), - solverM(NULL), - solverK(NULL), - solverMpK(NULL), - solverMpK2(NULL), - useOldInitialGuess(false), - tau(NULL) + : super(name), + solverM(NULL), + solverK(NULL), + solverMpK(NULL), + solverMpK2(NULL), + useOldInitialGuess(false), + tau(NULL) { Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess); } diff --git a/extensions/preconditioner/PetscSolverPfc_diag.h b/extensions/preconditioner/PetscSolverPfc_diag.h index 5bba67897fe2c0e196efb852ff085ac5652ec7ea..449af4dba4cf4acf388be698245367ded837b47c 100644 --- a/extensions/preconditioner/PetscSolverPfc_diag.h +++ b/extensions/preconditioner/PetscSolverPfc_diag.h @@ -31,27 +31,24 @@ namespace AMDiS { namespace Parallel { class PetscSolverPfcDiag : public PetscSolverGlobalBlockMatrix { public: + typedef PetscSolverPfcDiag self; + typedef PetscSolverGlobalBlockMatrix super; + /// Creator class - class Creator : public LinearSolverCreator + struct Creator : public LinearSolverCreator { - public: virtual ~Creator() {} - - /// Returns a new PetscSolver object. - LinearSolverInterface* create() - { - return new PetscSolverPfcDiag(this->name); - } + LinearSolverInterface* create() { return new self(this->name); } }; PetscSolverPfcDiag(std::string name) - : PetscSolverGlobalBlockMatrix(name), - solverM(NULL), - solverK(NULL), - solverMpK(NULL), - solverS(NULL), - useOldInitialGuess(false), - tau(NULL) + : super(name), + solverM(NULL), + solverK(NULL), + solverMpK(NULL), + solverS(NULL), + useOldInitialGuess(false), + tau(NULL) { Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess); } diff --git a/extensions/preconditioner/PhaseFieldCrystal_.cc b/extensions/preconditioner/PhaseFieldCrystal_.cc deleted file mode 100644 index 8928d4c129a9d096960cd538a5a94fd5b53005b9..0000000000000000000000000000000000000000 --- a/extensions/preconditioner/PhaseFieldCrystal_.cc +++ /dev/null @@ -1,88 +0,0 @@ -#include "PhaseFieldCrystal_.h" - -namespace AMDiS { namespace base_problems { - -using namespace std; - -PhaseFieldCrystal_::PhaseFieldCrystal_(const std::string &name_, bool createProblem) : - super(name_, createProblem), - useMobility(false), - tempParameter(-0.6), - r(-0.4), // temperature deviation - rho0(1.0), // liquid density - density(-0.3), // mean density - two(2.0), - minus2(-2.0) -{ - Parameters::get(name + "->r",r); - Parameters::get(name + "->rho0", rho0); - Parameters::get(name + "->density", density); - Parameters::get(name + "->use mobility", useMobility); - tempParameter= -(1.0+r); -} - - -void PhaseFieldCrystal_::fillOperators() -{ - - int degree = prob->getFeSpace(0)->getBasisFcts()->getDegree(); - - // phi*rho - Operator *opMnew = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opMnew->addTerm(new Simple_ZOT); - Operator *opMold = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opMold->addTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(1), NULL)); - - // -nabla*(phi*grad(rho)) - Operator *opL = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opL->addTerm(new Simple_SOT); - - Operator *opLM = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - double M0 = 1.0; - Parameters::get(name + "->M0", M0); - if (useMobility) // non-constant mobility - opLM->addTerm(new VecAtQP_SOT( - prob->getSolution()->getDOFVector(1), - new MobilityPfc(density, M0, degree))); - else // constant mobility - opLM->addTerm(new Simple_SOT(M0)); - - // -(1+r)*phi*rho - Operator *opMTemp = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opMTemp->addZeroOrderTerm(new Simple_ZOT()); - // -2*rho_old^3 - Operator *opMPowExpl = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opMPowExpl->addZeroOrderTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(1),new AMDiS::Pow<3>(-2.0, 3*degree))); - // -3*rho_old^2 - Operator *opMPowImpl = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); - opMPowImpl->addZeroOrderTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(1),new AMDiS::Pow<2>(-3.0, 2*degree))); - - - // dt(rho) = laplace(mu) - u*grad(rho) - // ----------------------------------- - prob->addMatrixOperator(opMnew, 1, 1); - prob->addMatrixOperator(opLM, 1, 0, getTau(), getTau()); // -laplace(mu) - // . . . vectorOperators . . . . . . . . . . . . . . . - prob->addVectorOperator(opMold, 1); - - // mu-2*nu-laplace(nu)-(1+r)*rho = (rho_old^3) + ExtPot - eps^2/(rho_old+0.9) - // ---------------------------------------------------------------------- - prob->addMatrixOperator(opMTemp, 0, 1, getTempParameter(), getTempParameter()); // -phi*(1+r)*rho - prob->addMatrixOperator(opMPowImpl, 0, 1); // -3*rho*rho_old^2 - prob->addMatrixOperator(opL, 0, 1, &two, &two); // -2*phi*laplace(rho) * psi - prob->addMatrixOperator(opMnew, 0, 0); // phi*mu * psi - prob->addMatrixOperator(opL, 0, 2); // phi*grad(nu) * grad(psi) - // . . . vectorOperators . . . . . . . . . . . . . . . - prob->addVectorOperator(opMPowExpl, 0); // -2*phi^old*rho_old^3 - - // 0 = nu-laplace(rho) - // ------------------- - prob->addMatrixOperator(opL, 2, 1); // -laplace(rho) - prob->addMatrixOperator(opMnew, 2, 2); // nu -} - - -void PhaseFieldCrystal_::fillBoundaryConditions() -{} - -} } diff --git a/extensions/preconditioner/PhaseFieldCrystal_.h b/extensions/preconditioner/PhaseFieldCrystal_.h deleted file mode 100644 index 58fe938fdd9a6f20034228e232c8e6d5457c9b90..0000000000000000000000000000000000000000 --- a/extensions/preconditioner/PhaseFieldCrystal_.h +++ /dev/null @@ -1,80 +0,0 @@ -/** \file PhaseFieldCrystal_.h */ - -#ifndef PHASE_FIELD_CRYSTAL_PRECON_H_ -#define PHASE_FIELD_CRYSTAL_PRECON_H_ - -#include "AMDiS.h" -#include "BaseProblem.h" -#include "ExtendedProblemStat.h" - -namespace AMDiS { namespace base_problems { - -/** Phase-field Crystal problem - */ -class PhaseFieldCrystal_ : public BaseProblem<extensions::ExtendedProblemStat> -{ -public: // typedefs - - typedef BaseProblem<extensions::ExtendedProblemStat> super; - -public: - - PhaseFieldCrystal_(const std::string &name_, bool createProblem = true); - ~PhaseFieldCrystal_() {} - - double *getTempParameter() { return &tempParameter; } - - virtual void fillOperators(); - virtual void fillBoundaryConditions(); - -protected: - - bool useMobility; - - double tempParameter; - double r; - double rho0; - double density; - double two; - double minus2; -}; - - -/** \ingroup MainInstat - * \brief - * Abstract function to calculate the pure PFC-Energy - */ -class Energy : public BinaryAbstractFunction<double,double,double> -{ - public: - Energy() : BinaryAbstractFunction<double,double,double>(4) { } - - double operator()(const double &rho, const double &mu) const { - return -0.25*sqr(sqr(rho)) + 0.5*rho*mu; } -}; - - -class MobilityPfc : public AbstractFunction<double,double> -{ - public: - MobilityPfc(double density_ = -0.3, double factor_ = 1.0, int degree=1) : - AbstractFunction<double,double>(degree+1), - density(density_), - factor(factor_), - delta(1.e-6) { } - - double operator()(const double &rho) const - { - double mobility= std::abs(rho + 1.5)*factor; - return std::max(mobility, 0.0); - } - - protected: - double density; - double factor; - double delta; -}; - -} } - -#endif // PHASE_FIELD_CRYSTAL_PRECON_H_