diff --git a/apps/tools/povrayFileCompressor/main.cpp b/apps/tools/povrayFileCompressor/main.cpp
index a66acbf5d14379a9d43f566da4350f34e56af582..3fd306b3e734c421eb2d039fcd8d8f91867d91a8 100644
--- a/apps/tools/povrayFileCompressor/main.cpp
+++ b/apps/tools/povrayFileCompressor/main.cpp
@@ -26,10 +26,9 @@
 #include <fstream>
 #include <iomanip>
 #include <iostream>
+#include <string>
 
 
-#include <boost/algorithm/string.hpp>
-
 namespace filesystem = walberla::filesystem;
 
 bool verbose;
@@ -51,7 +50,7 @@ namespace walberla{
 
 int main(int argc, char** argv)
 {
-   if( argc == 1 || boost::equals(argv[1], "-h" ) ){
+   if( argc == 1 || std::string(argv[1]) == "-h" ){
       PRINT_DEF( "Usage: PovrayFileCompressor [OPTIONS] <inDir> <outDir>\n"
          << "compresses povray mesh2 files mode\n"
          << "OPTIONS (optional):\n -h help\n -q quiet: no output\n -v verbose: most output\n -n number of vertices per mesh\n -s number of unconnected meshes beginning with biggest mest\n -o maximum distance between two vertices to be merged" )
@@ -69,15 +68,15 @@ int main(int argc, char** argv)
 
    if( argc > 3 ) {
       for( walberla::uint_t i = 1; i < walberla::uint_c(argc-2); ++i ) {
-         if( boost::equals(argv[i], "-q" ) )
+         if( std::string(argv[i]) == "-q" )
             quiet = true;
-         else if( boost::equals(argv[i], "-v" ) )
+         else if( std::string(argv[i]) == "-v" )
             verbose = true;
-         else if( boost::equals(argv[i], "-n" ) )
+         else if( std::string(argv[i]) == "-n" )
             n = walberla::numeric_cast< size_t >( atoi( argv[++i] ) );
-         else if( boost::equals(argv[i], "-s" ) )
+         else if( std::string(argv[i]) == "-s" )
             s = walberla::numeric_cast< size_t >( atoi( argv[++i] ) );
-         else if( boost::equals(argv[i], "-o" ) )
+         else if( std::string(argv[i]) == "-o" )
             o = walberla::real_c( atof( argv[++i] ) );
          else if( argv[i][0] != '-' )
             PRINT_ERR( "Usage: PovrayFileCompressor [-q|-v] <inDir> <outDir>\n" )
diff --git a/src/blockforest/loadbalancing/DynamicParMetis.cpp b/src/blockforest/loadbalancing/DynamicParMetis.cpp
index 59d43a364ef725d985c97c96ea021a69a4124280..ddc0cbe4cb67a9fc5f252897e1fddc90e7164724 100644
--- a/src/blockforest/loadbalancing/DynamicParMetis.cpp
+++ b/src/blockforest/loadbalancing/DynamicParMetis.cpp
@@ -33,9 +33,7 @@
 #include "core/mpi/Reduce.h"
 
 #include "core/timing/Timer.h"
-
-#include <boost/algorithm/string/case_conv.hpp>
-#include <boost/algorithm/string/trim.hpp>
+#include "core/StringUtility.h"
 
 #include <array>
 #include <vector>
@@ -305,8 +303,8 @@ bool DynamicParMetis::operator()( std::vector< std::pair< const PhantomBlock *,
 
 DynamicParMetis::Algorithm DynamicParMetis::stringToAlgorithm( std::string s )
 {
-   boost::algorithm::to_upper( s );
-   boost::algorithm::trim( s );
+   string_to_upper( s );
+   string_trim( s );
 
    if( s == "PART_GEOM_KWAY" )
       return PARMETIS_PART_GEOM_KWAY;
@@ -325,8 +323,8 @@ DynamicParMetis::Algorithm DynamicParMetis::stringToAlgorithm( std::string s )
 
 DynamicParMetis::WeightsToUse DynamicParMetis::stringToWeightsToUse( std::string s )
 {
-   boost::algorithm::to_upper( s );
-   boost::algorithm::trim( s );
+   string_to_upper( s );
+   string_trim( s );
 
    if( s == "NO_WEIGHTS" )
       return PARMETIS_NO_WEIGHTS;
@@ -343,8 +341,8 @@ DynamicParMetis::WeightsToUse DynamicParMetis::stringToWeightsToUse( std::string
 
 DynamicParMetis::EdgeSource DynamicParMetis::stringToEdgeSource( std::string s )
 {
-   boost::algorithm::to_upper( s );
-   boost::algorithm::trim( s );
+   string_to_upper( s );
+   string_trim( s );
 
    if( s == "EDGES_FROM_FOREST" )
       return PARMETIS_EDGES_FROM_FOREST;
diff --git a/src/blockforest/loadbalancing/StaticParMetis.cpp b/src/blockforest/loadbalancing/StaticParMetis.cpp
index 5853cdf1ee62f3eefaff557847f2aea4095ebd83..c94d81b8720eb3a3a9763f70bbdcfe8f5e86145e 100644
--- a/src/blockforest/loadbalancing/StaticParMetis.cpp
+++ b/src/blockforest/loadbalancing/StaticParMetis.cpp
@@ -33,8 +33,7 @@
 
 #include "core/timing/Timer.h"
 
-#include <boost/algorithm/string/case_conv.hpp>
-#include <boost/algorithm/string/trim.hpp>
+#include "core/StringUtility.h"
 
 namespace walberla {
 namespace blockforest {
@@ -204,8 +203,8 @@ uint_t StaticLevelwiseParMetis::operator()( SetupBlockForest & forest, const uin
 
 StaticLevelwiseParMetis::Algorithm StaticLevelwiseParMetis::stringToAlgorithm( std::string s )
 {
-   boost::algorithm::to_upper( s );
-   boost::algorithm::trim( s );
+   string_to_upper( s );
+   string_trim( s );
 
    if( s == "PART_GEOM_KWAY" )
       return PARMETIS_PART_GEOM_KWAY;
@@ -218,8 +217,8 @@ StaticLevelwiseParMetis::Algorithm StaticLevelwiseParMetis::stringToAlgorithm( s
 
 StaticLevelwiseParMetis::WeightsToUse StaticLevelwiseParMetis::stringToWeightsToUse( std::string s )
 {
-   boost::algorithm::to_upper( s );
-   boost::algorithm::trim( s );
+   string_to_upper( s );
+   string_trim( s );
 
    if( s == "NO_WEIGHTS" )
       return PARMETIS_NO_WEIGHTS;
diff --git a/src/blockforest/python/Exports.cpp b/src/blockforest/python/Exports.cpp
index 181d14bf1197e457a596f53ee4ddb834c144ff7e..cd4419689565be345c325c78d52dd7d14221d82e 100644
--- a/src/blockforest/python/Exports.cpp
+++ b/src/blockforest/python/Exports.cpp
@@ -32,6 +32,7 @@
 #include "blockforest/loadbalancing/StaticCurve.h"
 
 #include "core/logging/Logging.h"
+#include "core/StringUtility.h"
 #include "domain_decomposition/StructuredBlockStorage.h"
 #include "python_coupling/Manager.h"
 #include "python_coupling/helper/ConfigFromDict.h"
@@ -40,7 +41,6 @@
 #include "stencil/D3Q19.h"
 #include "stencil/D3Q27.h"
 
-#include <boost/algorithm/string.hpp>
 #include <sstream>
 
 #ifdef _MSC_VER
@@ -246,11 +246,11 @@ shared_ptr<StructuredBlockForest> createStructuredBlockForest( Vector3<uint_t> b
 object createUniformNeighborScheme(  const shared_ptr<StructuredBlockForest> & bf,
                                      const std::string & stencil )
 {
-   if ( boost::iequals(stencil, "D3Q7") )
+   if ( string_icompare(stencil, "D3Q7") == 0 )
       return object ( make_shared< UniformBufferedScheme<stencil::D3Q7> > ( bf ) );
-   if ( boost::iequals(stencil, "D3Q19") )
+   if ( string_icompare(stencil, "D3Q19") == 0 )
       return object ( make_shared< UniformBufferedScheme<stencil::D3Q19> > ( bf ) );
-   if ( boost::iequals(stencil, "D3Q27") )
+   if ( string_icompare(stencil, "D3Q27") == 0 )
       return object ( make_shared< UniformBufferedScheme<stencil::D3Q27> > ( bf ) );
    else {
       PyErr_SetString( PyExc_RuntimeError, "Unknown stencil. Allowed values 'D3Q27', 'D3Q19', 'D3Q7'");
diff --git a/src/core/Environment.cpp b/src/core/Environment.cpp
index b39a0b304c58ebe65356a587ec4264c7fe3c2754..015687ce3bba28e3ffc393d6df1e3b788621f49d 100644
--- a/src/core/Environment.cpp
+++ b/src/core/Environment.cpp
@@ -27,11 +27,10 @@
 #include "core/logging/Logging.h"
 #include "core/logging/Tracing.h"
 #include "core/mpi/MPIManager.h"
+#include "core/StringUtility.h"
 #include "core/uid/GlobalState.h"
 #include "core/uid/SUID.h"
 
-#include <boost/algorithm/string.hpp>
-
 #include <algorithm>
 #include <functional>
 #include <sstream>
@@ -82,8 +81,7 @@ void configureGlobalState( const shared_ptr<Config> & config ) {
 
       std::string suids = config->getParameter< std::string >( "GlobalState" );
 
-      std::vector< std::string > states;
-      boost::split( states, suids, boost::is_any_of(", \t") );
+      std::vector< std::string > states = string_split( suids, ", \t" );
       states.erase( std::remove_if( states.begin(), states.end(), std::bind( &std::string::empty, std::placeholders::_1 ) ), states.end() );
 
       Set<SUID> state;
diff --git a/src/core/MultiArrayIO.impl.h b/src/core/MultiArrayIO.impl.h
index 922edf37821c80d6289f021284fb372015329b74..c33edc6a43ee52040ed3d153e8f5cc5b8fcba58d 100644
--- a/src/core/MultiArrayIO.impl.h
+++ b/src/core/MultiArrayIO.impl.h
@@ -22,9 +22,9 @@
 #pragma once
 
 #include "core/DataTypes.h"
+#include "core/StringUtility.h"
 
 #include <sstream>
-#include <boost/algorithm/string.hpp>
 
 namespace boost {
 
@@ -53,8 +53,7 @@ bool parseArray1D( std::vector<T> & arr, std::istream & is,
       return false;
 
 
-   std::vector<std::string> stringArr;
-   boost::split( stringArr,line, boost::is_any_of( delimiter ), boost::token_compress_on );
+   std::vector<std::string> stringArr = walberla::string_split( line, delimiter );
 
    arr.clear();
    arr.reserve( stringArr.size() );
diff --git a/src/core/StringUtility.h b/src/core/StringUtility.h
new file mode 100644
index 0000000000000000000000000000000000000000..780cfb9de146f2eb82c9dcee247b6b47d34cd3e8
--- /dev/null
+++ b/src/core/StringUtility.h
@@ -0,0 +1,80 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file StringUtility.h
+//! \ingroup core
+//! \author Christoph Schwarzmeier <christoph.schwarzmeier@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+#include <algorithm>
+#include <cctype>
+#include <string>
+#include <vector>
+
+namespace walberla
+{
+
+// Convert (in place) every character in string to uppercase.
+inline void string_to_upper(std::string &s);
+
+// Convert (copy) every character in string to uppercase.
+inline std::string string_to_upper_copy(const std::string &s);
+
+// Convert (in place) every character in string to lowercase.
+inline void string_to_lower(std::string &s);
+
+// Convert (in place) every character in string to lowercase.
+inline std::string string_to_lower_copy(const std::string &s);
+
+// Remove (in place) all whitespaces at the beginning of a string.
+inline void string_trim_left(std::string &s);
+
+// Remove (in place) all whitespaces at the end of a string.
+inline void string_trim_right(std::string &s);
+
+// Remove (in place) all whitespaces at the beginning and at the end of a string.
+inline void string_trim(std::string &s);
+
+// Remove (copy) all whitespaces at the beginning of a string.
+inline std::string string_trim_left_copy(const std::string &s);
+
+// Remove (copy) all whitespaces at the end of a string.
+inline std::string string_trim_right_copy(const std::string &s);
+
+// Remove (copy) all whitespaces at the beginning and at the end of a string.
+inline std::string string_trim_copy(const std::string &s);
+
+// Split a string at the given delimiters into a vector of substrings.
+// E.g. specify std::string(" |,") in order to split at characters ' ' and ','.
+inline std::vector<std::string> string_split(std::string s, const std::string &delimiters);
+
+// Replace (in place) all occurrences of substring "old" with substring "new".
+inline void string_replace_all(std::string &s, const std::string &oldSubstr, const std::string &newSubstr);
+
+// Replace (copy) all occurrences of substring "old" with substring "new".
+inline std::string string_replace_all_copy(const std::string &s, const std::string &oldSubstr, const std::string &newSubstr);
+
+// Check whether a string ends with a certain substring.
+inline bool string_ends_with(const std::string &s, const std::string &substr);
+
+// Case-insensitive std::string::compare.
+inline int string_icompare(const std::string &s1, const std::string &s2);
+
+} // namespace walberla
+
+#include "core/StringUtility.impl.h"
\ No newline at end of file
diff --git a/src/core/StringUtility.impl.h b/src/core/StringUtility.impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddc5f748275dc04e3500793e83758f658d58aa92
--- /dev/null
+++ b/src/core/StringUtility.impl.h
@@ -0,0 +1,150 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file StringUtility.impl.h
+//! \ingroup core
+//! \author Christoph Schwarzmeier <christoph.schwarzmeier@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+#include "core/StringUtility.h"
+
+#include <algorithm>
+#include <cctype>
+#include <string>
+#include <vector>
+
+namespace walberla
+{
+// Convert (in place) every character in string to uppercase.
+inline void string_to_upper(std::string &s) {
+   std::transform(s.begin(), s.end(), s.begin(), [](char c){ return static_cast<char>(std::toupper(static_cast<unsigned char>(c))); });
+}
+
+// Convert (copy) every character in string to uppercase.
+inline std::string string_to_upper_copy(const std::string &s) {
+   std::string result = s;
+   string_to_upper(result);
+   return result;
+}
+
+// Convert (in place) every character in string to lowercase.
+inline void string_to_lower(std::string &s) {
+   std::transform(s.begin(), s.end(), s.begin(), [](char c){ return static_cast<char>(std::tolower(static_cast<unsigned char>(c))); });
+}
+
+// Convert (copy) every character in string to lowercase.
+inline std::string string_to_lower_copy(const std::string &s) {
+   std::string result = s;
+   string_to_lower(result);
+   return result;
+}
+
+// Remove (in place) all whitespaces at the beginning of a string.
+inline void string_trim_left(std::string &s) {
+   s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return ! std::isspace(static_cast<unsigned char>(c)); }));
+}
+
+// Remove (in place) all whitespaces at the end of a string.
+inline void string_trim_right(std::string &s) {
+   s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return ! std::isspace(static_cast<unsigned char>(c)); }).base(), s.end());
+}
+
+// Remove (in place) all whitespaces at the beginning and at the end of a string.
+inline void string_trim(std::string &s) {
+   string_trim_left(s);
+   string_trim_right(s);
+}
+
+// Remove (copy) all whitespaces at the beginning of a string.
+inline std::string string_trim_left_copy(const std::string &s) {
+   std::string result = s;
+   string_trim_left(result);
+   return result;
+}
+
+// Remove (copy) all whitespaces at the end of a string.
+inline std::string string_trim_right_copy(const std::string &s) {
+   std::string result = s;
+   string_trim_left(result);
+   return result;
+}
+
+// Remove (copy) all whitespaces at the beginning and at the end of a string.
+inline std::string string_trim_copy(const std::string &s) {
+   std::string result = s;
+   string_trim_left(result);
+   return result;
+}
+
+// Split a string at the given delimiters into a vector of substrings.
+// E.g. specify std::string(" ,") in order to split at characters ' ' and ','.
+inline std::vector<std::string> string_split(std::string s, const std::string &delimiters) {
+   std::vector<std::string> substrings;
+
+   auto sub_begin = s.begin();   // iterator to the begin and end of a substring
+   auto sub_end = sub_begin;
+
+   for (auto it = s.begin(); it != s.end(); ++it) {
+      for (auto d : delimiters) {
+         if (*it == d) {   // current character in s is a delimiter
+            sub_end = it;
+            if (sub_begin < sub_end) { // make sure that the substring is not empty
+               substrings.push_back(std::string(sub_begin, sub_end));
+            }
+            sub_begin = ++sub_end;
+            continue;
+         }
+      }
+   }
+
+   // add substring from last delimiter to the end of s
+   if (sub_begin < s.end()) {
+      substrings.push_back(std::string(sub_begin, s.end()));
+   }
+
+   return substrings;
+}
+
+// Replace (in place) all occurrences of substring "old" with substring "new".
+inline void string_replace_all(std::string &s, const std::string &oldSubstr, const std::string &newSubstr) {
+   // loop written to avoid infinite-loops when newSubstr contains oldSubstr
+   for (size_t pos = s.find(oldSubstr); pos != std::string::npos;) {
+      s.replace(pos, oldSubstr.length(), newSubstr);
+      pos = s.find(oldSubstr, pos + newSubstr.length());
+   }
+}
+
+// Replace (copy) all occurrences of substring "old" with substring "new".
+inline std::string string_replace_all_copy(const std::string &s, const std::string &oldSubstr, const std::string &newSubstr) {
+   std::string result = s;
+   string_replace_all(result, oldSubstr, newSubstr);
+   return result;
+}
+
+// Check whether a string ends with a certain substring.
+inline bool string_ends_with(const std::string &s, const std::string &substr) {
+   return s.rfind(substr) == (s.length() - substr.length());
+}
+
+// Case-insensitive wrapper for std::string::compare (return values as for std::string::compare).
+inline int string_icompare(const std::string &s1, const std::string &s2) {
+   // function std::string::compare returns 0 in case of equality => invert result to obtain expected bool behavior
+   return string_to_lower_copy(s1).compare(string_to_lower_copy(s2));
+}
+
+} // namespace walberla
diff --git a/src/core/all.h b/src/core/all.h
index bc7ca12dd4a7f6d4dc1683888bd978805ce600e3..e15f23d38a366a824984bd1e3536c36ad86c7083 100644
--- a/src/core/all.h
+++ b/src/core/all.h
@@ -29,6 +29,7 @@
 #include "Deprecated.h"
 #include "EndianIndependentSerialization.h"
 #include "Environment.h"
+#include "FunctionTraits.h"
 #include "GetPID.h"
 #include "Hostname.h"
 #include "Macros.h"
@@ -39,6 +40,7 @@
 #include "Set.h"
 #include "SharedFunctor.h"
 #include "Sleep.h"
+#include "StringUtility.h"
 #include "VectorTrait.h"
 
 #include "cell/all.h"
diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp
index ee6e03f058ea651b23bd2ce4785a91d1fae1d6de..d850e6c5a3b51c8f6db443cabbe67c6e88e88922 100644
--- a/src/core/config/Config.cpp
+++ b/src/core/config/Config.cpp
@@ -22,13 +22,12 @@
 
 #include "Config.h"
 #include "core/mpi/MPIManager.h"
+#include "core/StringUtility.h"
 
 #include <fstream>
 #include <iostream>
 #include <stdexcept>
 
-#include <boost/algorithm/string/trim.hpp>
-
 namespace walberla {
 namespace config {
 
@@ -247,7 +246,7 @@ void Config::parseFromFile( const char* filename, Block& block, unsigned int lev
                        getLineNumber( lineNumbers, input.tellg() ), level );
       }
 
-      else if( boost::algorithm::iequals( key, "include" ) )
+      else if( string_icompare( key, "include" ) == 0 )
       {
          if( std::getline( input, value, ';' ) && !input.eof() )
          {
@@ -362,7 +361,7 @@ void Config::extractBlock( const char* filename, std::stringstream& input, Block
 
    while( input >> key )
    {
-      if(  boost::algorithm::iequals( key, "}" ) ) {
+      if( string_icompare( key, "}" ) == 0 ) {
          return;
       }
       else if( input >> std::ws && input.eof() ) {
@@ -380,7 +379,7 @@ void Config::extractBlock( const char* filename, std::stringstream& input, Block
                getLineNumber( lineNumbers, input.tellg() ), level );
       }
 
-      else if(  boost::algorithm::iequals( key, "include" ) )
+      else if( string_icompare( key, "include" ) == 0 )
       {
          if( std::getline( input, value, ';' ) && !input.eof() )
          {
@@ -515,7 +514,7 @@ Config::size_type Config::Block::getNumBlocks( const std::string& key ) const
 {
    size_type c = 0;
    for( List::const_iterator it=blocks_.begin(); it!=blocks_.end(); ++it ) {
-      if(  boost::algorithm::iequals( key, it->getKey() ) ) {
+      if( string_icompare( key, it->getKey() ) == 0 ) {
          ++c;
       }
    }
@@ -569,7 +568,7 @@ void Config::Block::getBlocks( const std::string& key, Blocks& blocks, size_t mi
 {
    size_t c = 0;
    for( List::const_iterator it=blocks_.begin(); it!=blocks_.end(); ++it ) {
-      if(  boost::algorithm::iequals( key, it->getKey() ) ) {
+      if( string_icompare( key, it->getKey() ) == 0 ) {
          blocks.push_back( BlockHandle( &*it ) );
          ++c;
       }
@@ -627,7 +626,7 @@ void Config::Block::getWritableBlocks( const std::string & key, std::vector<Bloc
 {
    size_t c = 0;
    for( List::iterator it=blocks_.begin(); it!=blocks_.end(); ++it ) {
-      if(  boost::algorithm::iequals( key, it->getKey() ) ) {
+      if( string_icompare( key, it->getKey() ) == 0 ) {
          blocks.push_back(  &*it );
          ++c;
       }
@@ -735,7 +734,7 @@ static void printConfig( std::ostream & os, const Config::BlockHandle & block, i
    if ( depth >=0 )
    {
       std::string blockName = block.getKey();
-      boost::algorithm::trim( blockName );
+      string_trim( blockName );
       os << prefix.str() << blockName << "\n";
       os << prefix.str() << "{\n";
    }
@@ -746,8 +745,8 @@ static void printConfig( std::ostream & os, const Config::BlockHandle & block, i
    for( auto paramIt = block.begin(); paramIt != block.end(); ++paramIt ) {
       std::string key = paramIt->first;
       std::string value = paramIt->second;
-      boost::algorithm::trim( key );
-      boost::algorithm::trim( value );
+      string_trim( key );
+      string_trim( value );
       os << prefix.str() << "   " << key << " " << value << ";\n";
    }
 
diff --git a/src/core/config/Config.h b/src/core/config/Config.h
index 2aa4513080cd67a23e7b81f88dcd85e8af4d43e3..88ef3ae20d9b0761ebb9e87b10bd76cbd2305efe 100644
--- a/src/core/config/Config.h
+++ b/src/core/config/Config.h
@@ -22,7 +22,9 @@
 #pragma once
 
 #include "core/Abort.h"
+#include "core/Filesystem.h"
 #include "core/debug/CheckFunctions.h"
+#include "core/StringUtility.h"
 
 #include <cctype>
 #include <iostream>
@@ -35,9 +37,7 @@
 #include <vector>
 
 
-// boost includes
-#include <boost/algorithm/string/predicate.hpp>
-#include "core/Filesystem.h"
+
 
 
 
@@ -50,7 +50,7 @@ struct CaseInsensitiveCompare
 {
    bool operator()( const std::string & lhs, const std::string & rhs) const
    {
-      return boost::algorithm::ilexicographical_compare(lhs, rhs);
+      return ( string_icompare(lhs, rhs) < 0 );
    }
 };
 
@@ -905,17 +905,17 @@ inline Config::Parameter<bool> Config::Block::getParameter<bool>( std::string ke
 
    if( it != params_.end() )
    {
-      if( ( it->second.length() == 1u && it->second[0] == '1' )        ||
-          boost::algorithm::iequals( it->second, std::string("true") ) ||
-          boost::algorithm::iequals( it->second, std::string("yes") )  ||
-          boost::algorithm::iequals( it->second, std::string("on") ) )
+      if( ( it->second.length() == 1u && it->second[0] == '1' )   ||
+          string_icompare( it->second, std::string("true") ) == 0 ||
+          string_icompare( it->second, std::string("yes") ) == 0  ||
+          string_icompare( it->second, std::string("on") ) == 0 )
       {
          return Parameter<bool>( true, noerror, key );
       }
-      else if( ( it->second.length() == 1u && it->second[0] == '0' )         ||
-               boost::algorithm::iequals( it->second, std::string("false") ) ||
-               boost::algorithm::iequals( it->second, std::string("no") )    ||
-               boost::algorithm::iequals( it->second, std::string("off") ) )
+      else if( ( it->second.length() == 1u && it->second[0] == '0' )    ||
+               string_icompare( it->second, std::string("false") ) == 0 ||
+               string_icompare( it->second, std::string("no") ) == 0    ||
+               string_icompare( it->second, std::string("off") ) ==0 )
       {
          return Parameter<bool>( false, noerror, key );
       }
diff --git a/src/core/config/Create.cpp b/src/core/config/Create.cpp
index 8e90173e7c480fe8538b664020494d21e32e235e..6bc78a70209c9aedb69d825531677fa3c3f5bbc0 100644
--- a/src/core/config/Create.cpp
+++ b/src/core/config/Create.cpp
@@ -22,11 +22,7 @@
 #include "Create.h"
 #include "core/logging/Tracing.h"
 #include "core/Abort.h"
-
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/trim.hpp>
+#include "core/StringUtility.h"
 
 #include <iomanip>
 
@@ -109,14 +105,10 @@ namespace config {
    {
       using std::vector;
       using std::string;
-      using boost::algorithm::split;
-      using boost::algorithm::is_any_of;
-      using boost::algorithm::trim;
 
       for( auto param = params.begin(); param != params.end(); ++param )
       {
-         vector< string > equalitySignSplitResult;
-         split( equalitySignSplitResult, *param,  is_any_of("=") );
+         vector< string > equalitySignSplitResult = string_split( *param, "=" );
 
          std::string value;
          if ( equalitySignSplitResult.size() == 0 )
@@ -138,8 +130,7 @@ namespace config {
 
          const std::string & blockDescriptor = equalitySignSplitResult[0];
 
-         vector< string > blocks;
-         split( blocks, blockDescriptor, is_any_of(".") );
+         vector< string > blocks = string_split( blockDescriptor, "." );
 
          if ( blocks.empty() ) {
             WALBERLA_LOG_WARNING( "Ignoring Parameter: Missing block descriptor on left hand side: '" << *param <<"'" );
@@ -150,7 +141,7 @@ namespace config {
          for( uint_t i=0; i < blocks.size() -1; ++i )
          {
             std::string & blockName = blocks[i];
-            trim( blockName );
+            string_trim( blockName );
 
             if ( blockName.empty() )
             {
@@ -177,7 +168,7 @@ namespace config {
          if ( ! currentBlock )
             continue;
 
-         trim( blocks.back() );
+         string_trim( blocks.back() );
          if ( blocks.back().empty() )
          {
             WALBERLA_LOG_WARNING( "Ignoring Parameter '" << *param << "' since key is empty");
diff --git a/src/core/logging/Initialization.cpp b/src/core/logging/Initialization.cpp
index cc50de9ceab8d160c5d2fd59c86b88f66bb5d6e8..f38e07c379589041d1df8f8cf18e56fad69ec60a 100644
--- a/src/core/logging/Initialization.cpp
+++ b/src/core/logging/Initialization.cpp
@@ -21,8 +21,7 @@
 
 #include "Initialization.h"
 #include "Logging.h"
-
-#include <boost/algorithm/string.hpp>
+#include "core/StringUtility.h"
 
 #include <algorithm>
 #include <sstream>
@@ -42,7 +41,7 @@ static void parseIgnoreBlocks( const Config::Blocks & ignoreBlocks, std::vector<
       {
          std::string regexString = ignoreBlock->getParameter<std::string>( "callerPathPattern" );
          // Replace slashes with a regex to allow for windows/linux compatibility
-         boost::algorithm::replace_all( regexString, "/", "(\\\\|/)" );
+         string_replace_all( regexString, "/", "(\\\\|/)" );
          try
          {
             walberla::regex regex( regexString );
@@ -140,7 +139,7 @@ void configureLogging( const Config::BlockHandle & loggingBlock )
    if( loggingBlock.isDefined( "logLevel" ) )
    {
       std::string type = loggingBlock.getParameter< std::string >( "logLevel" );
-      boost::algorithm::to_lower( type );
+      string_to_lower( type );
 
       if( type == "warning" ){
          logging::Logging::instance()->setLogLevel( logging::Logging::WARNING );
@@ -159,7 +158,7 @@ void configureLogging( const Config::BlockHandle & loggingBlock )
    if( loggingBlock.isDefined( "streamLogLevel" ) )
    {
       std::string type = loggingBlock.getParameter< std::string >( "streamLogLevel" );
-      boost::algorithm::to_lower( type );
+      string_to_lower( type );
 
       if( type == "warning" ){
          logging::Logging::instance()->setStreamLogLevel( logging::Logging::WARNING );
@@ -178,7 +177,7 @@ void configureLogging( const Config::BlockHandle & loggingBlock )
    if( loggingBlock.isDefined( "fileLogLevel" ) )
    {
       std::string type = loggingBlock.getParameter< std::string >( "fileLogLevel" );
-      boost::algorithm::to_lower( type );
+      string_to_lower( type );
 
       if( type == "warning" ){
          logging::Logging::instance()->setFileLogLevel( logging::Logging::WARNING );
diff --git a/src/core/logging/Logging.h b/src/core/logging/Logging.h
index 603b944142e3dd564bd57ffaa7b2e03b5dc1e84a..d3671e0ea3910bc7736710bfb7110930ff299600 100644
--- a/src/core/logging/Logging.h
+++ b/src/core/logging/Logging.h
@@ -29,8 +29,8 @@
 #include "core/singleton/Singleton.h"
 #include "core/timing/WcPolicy.h"
 #include "core/Regex.h"
+#include "core/StringUtility.h"
 
-#include <boost/algorithm/string/replace.hpp>
 #include <functional>
 
 #include <cmath>
@@ -485,7 +485,7 @@ inline std::string Logging::resetLinebreaks( const std::string & message ) const
    std::string newline = std::string("\n") + getRankStamp();
    newline.append( TAG_WIDTH + ( showTimeStamp_ ? TIMESTAMP_WIDTH : uint_c(0) )
                              + ( additionalStamp_ ? additionalStamp_->maxStampWidth() : uint_c(0) ) + uint_c(1), ' ' );
-   return boost::algorithm::replace_all_copy( message, "\n", newline );
+   return string_replace_all_copy( message, "\n", newline );
 }
 
 
diff --git a/src/core/math/DistributedSample.cpp b/src/core/math/DistributedSample.cpp
index 3a1d40a7f191fc304bfd567a1532227248057e84..965ab81692dbdc74d6a58814d0c8ff7329c89490 100644
--- a/src/core/math/DistributedSample.cpp
+++ b/src/core/math/DistributedSample.cpp
@@ -23,8 +23,10 @@
 #include "DistributedSample.h"
 #include "core/mpi/MPIManager.h"
 #include "core/mpi/Reduce.h"
+#include "core/StringUtility.h"
 
-#include <boost/algorithm/string/replace.hpp>
+#include <algorithm>
+#include <string>
 
 
 
@@ -166,43 +168,33 @@ void DistributedSample::mpiGatherRoot()
  *    %relstddev by relativeStdDeviation()
  *    %size      by size()
  *
- * \returns  The formated string.
+ * \returns  The formatted string.
  **********************************************************************************************************************/
 std::string DistributedSample::format( const std::string & formatString ) const
 {
-   using boost::algorithm::replace_all;
-
    std::string result = formatString;
 
    if( size_ > uint_t(0) )
    {
-      if( result.find( "%min" ) != std::string::npos )
-         replace_all(result, "%min", std::to_string( min_ ) );
-      if( result.find( "%max" ) != std::string::npos )
-         replace_all(result, "%max", std::to_string( max_ ) );
-      if( result.find( "%sum" ) != std::string::npos )
-         replace_all(result, "%sum",std::to_string( sum_ ) );
-      if( result.find( "%mean" ) != std::string::npos )
-         replace_all(result, "%mean", std::to_string( mean_ ) );
-      if( result.find( "%var" ) != std::string::npos )
-         replace_all(result, "%var", std::to_string( variance_ ) );
-      if( result.find( "%stddev" ) != std::string::npos )
-         replace_all(result, "%stddev", std::to_string( stdDeviation() ) );
-      if( result.find( "%relstddev" ) != std::string::npos )
-         replace_all(result, "%relstddev", std::to_string( relativeStdDeviation() ) );
-      if( result.find( "%size" ) != std::string::npos )
-         replace_all(result, "%size", std::to_string( size_ ) );
+      string_replace_all( result, "%min", std::to_string( min_ ) );
+      string_replace_all( result, "%max", std::to_string( max_ ) );
+      string_replace_all( result, "%sum", std::to_string( sum_ ) );
+      string_replace_all( result, "%mean", std::to_string( mean_ ) );
+      string_replace_all( result, "%var", std::to_string( variance_ ) );
+      string_replace_all( result, "%stddev", std::to_string( stdDeviation() ) );
+      string_replace_all( result, "%relstddev", std::to_string( relativeStdDeviation() ) );
+      string_replace_all( result, "%size", std::to_string( size_ ) );
    }
    else // empty()
    {
-      replace_all(result, "%min",       "N/A" );
-      replace_all(result, "%max",       "N/A" );
-      replace_all(result, "%sum",       "N/A" );
-      replace_all(result, "%mean",      "N/A" );
-      replace_all(result, "%var",       "N/A" );
-      replace_all(result, "%stddev",    "N/A" );
-      replace_all(result, "%relstddev", "N/A" );
-      replace_all(result, "%size",      "0"   );
+      string_replace_all( result, "%min", "N/A" );
+      string_replace_all( result, "%max", "N/A" );
+      string_replace_all( result, "%sum", "N/A" );
+      string_replace_all( result, "%mean", "N/A" );
+      string_replace_all( result, "%var", "N/A" );
+      string_replace_all( result, "%stddev", "N/A" );
+      string_replace_all( result, "%relstddev", "N/A" );
+      string_replace_all( result, "%size", "0" );
    }
 
    return result;
diff --git a/src/core/math/Sample.cpp b/src/core/math/Sample.cpp
index 8e376edf74f71b5f8bdfb68f97ea8515a33c34c7..bdd9e068973c9177e0e48ca65617f253bf566e8a 100644
--- a/src/core/math/Sample.cpp
+++ b/src/core/math/Sample.cpp
@@ -23,8 +23,7 @@
 #include "Sample.h"
 #include "core/mpi/Gatherv.h"
 #include "core/mpi/MPIManager.h"
-
-#include <boost/algorithm/string/replace.hpp>
+#include "core/StringUtility.h"
 
 #include <functional>
 #include <iterator>
@@ -269,44 +268,34 @@ real_t Sample::quantile(const real_t p) const
  **********************************************************************************************************************/
 std::string Sample::format(const std::string & formatString) const
 {
-   using boost::algorithm::replace_all;
 
    std::string result = formatString;
 
    if( !empty() )
    {
-      if( result.find( "%min" ) != std::string::npos )
-         replace_all(result, "%min", std::to_string( min() ) );
-      if( result.find( "%max" ) != std::string::npos )
-         replace_all(result, "%max", std::to_string( max() ) );
-      if( result.find( "%sum" ) != std::string::npos )
-         replace_all(result, "%sum",std::to_string( sum() ) );
-      if( result.find( "%mean" ) != std::string::npos )
-         replace_all(result, "%mean", std::to_string( mean() ) );
-      if( result.find( "%med" ) != std::string::npos )
-         replace_all(result, "%med", std::to_string( median() ) );
-      if( result.find( "%var" ) != std::string::npos )
-         replace_all(result, "%var", std::to_string( variance() ) );
-      if( result.find( "%stddev" ) != std::string::npos )
-         replace_all(result, "%stddev", std::to_string( stdDeviation() ) );
-      if( result.find( "%relstddev" ) != std::string::npos )
-         replace_all(result, "%relstddev", std::to_string( relativeStdDeviation() ) );
-      if( result.find( "%mad" ) != std::string::npos )
-         replace_all(result, "%mad", std::to_string( mad() ) );
-      if( result.find( "%size" ) != std::string::npos )
-         replace_all(result, "%size", std::to_string( size() ) );
+      string_replace_all( result, "%min", std::to_string( min() ) );
+      string_replace_all( result, "%max", std::to_string( max() ) );
+      string_replace_all( result, "%sum", std::to_string( sum() ) );
+      string_replace_all( result, "%mean", std::to_string( mean() ) );
+      string_replace_all( result, "%med", std::to_string( median() ) );
+      string_replace_all( result, "%var", std::to_string( variance() ) );
+      string_replace_all( result, "%stddev", std::to_string( stdDeviation() ) );
+      string_replace_all( result, "%relstddev", std::to_string( relativeStdDeviation() ) );
+      string_replace_all( result, "%mad", std::to_string( mad() ) );
+      string_replace_all( result, "%size", std::to_string( size() ) );
    }
    else // empty()
    {
-      replace_all(result, "%min",       "N/A" );
-      replace_all(result, "%max",       "N/A" );
-      replace_all(result, "%sum",       "N/A" );
-      replace_all(result, "%mean",      "N/A" );
-      replace_all(result, "%med",       "N/A" );
-      replace_all(result, "%var",       "N/A" );
-      replace_all(result, "%stddev",    "N/A" );
-      replace_all(result, "%relstddev", "N/A" );
-      replace_all(result, "%mad",       "N/A" );
+      string_replace_all( result, "%min",       "N/A" );
+      string_replace_all( result, "%max",       "N/A" );
+      string_replace_all( result, "%sum",       "N/A" );
+      string_replace_all( result, "%mean",      "N/A" );
+      string_replace_all( result, "%med",       "N/A" );
+      string_replace_all( result, "%var",       "N/A" );
+      string_replace_all( result, "%stddev",    "N/A" );
+      string_replace_all( result, "%relstddev", "N/A" );
+      string_replace_all( result, "%mad",       "N/A" );
+      string_replace_all( result, "%size", "0" );
    }
 
    return result;
diff --git a/src/core/math/equation_system/EquationParser.cpp b/src/core/math/equation_system/EquationParser.cpp
index cba3f45b1f7cde60118bca90b8723d54f80d92c4..5f064d79c073d1b9e85261018b7acd6c2ad3a835 100644
--- a/src/core/math/equation_system/EquationParser.cpp
+++ b/src/core/math/equation_system/EquationParser.cpp
@@ -24,8 +24,8 @@
 #include "Operator.h"
 #include "Variable.h"
 #include "core/math/Constants.h"
+#include "core/StringUtility.h"
 
-#include <boost/algorithm/string/trim.hpp>
 #include <memory>
 
 
@@ -321,7 +321,7 @@ NodePtr EquationParser::parseExpression( const std::string& str, size_t& index )
 EquationPtr EquationParser::parseEquation( const std::string& str, size_t& index )
 {
    // removing leading and trailing spaces of input string
-   std::string trimmedStr = boost::algorithm::trim_copy(str);
+   std::string trimmedStr = string_trim_copy(str);
    // removing spaces inside the trimmed string
    trimmedStr.erase(std::remove(trimmedStr.begin(), trimmedStr.end(), ' '), trimmedStr.end());
    NodePtr leftPtr = parseExpression(trimmedStr, index);
diff --git a/src/geometry/bodies/BodyFromConfig.cpp b/src/geometry/bodies/BodyFromConfig.cpp
index 0b9d1947c67ac5d85312be760139b75038f47733..111de46aedc88a72593356e8e4f4ea8ca33d581d 100644
--- a/src/geometry/bodies/BodyFromConfig.cpp
+++ b/src/geometry/bodies/BodyFromConfig.cpp
@@ -23,6 +23,7 @@
 
 #include <memory>
 #include "core/Abort.h"
+#include "core/StringUtility.h"
 
 
 namespace walberla {
@@ -138,27 +139,27 @@ shared_ptr<AbstractBody> bodyFromConfig (const Config::BlockHandle & block )
 {
    std::string shape = block.getParameter<std::string>("shape");
    
-   if      ( boost::iequals( shape, "Sphere"   ) )
+   if      ( string_icompare( shape, "Sphere"   ) == 0 )
       return make_DynamicBody(sphereFromConfig   ( block ) );
-   else if ( boost::iequals( shape, "Cylinder" ) )
+   else if ( string_icompare( shape, "Cylinder" ) == 0 )
       return make_DynamicBody(cylinderFromConfig ( block ) );
-   else if ( boost::iequals( shape, "Torus"    ) )
+   else if ( string_icompare( shape, "Torus"    ) == 0 )
       return make_DynamicBody(torusFromConfig    ( block ) );
-   else if ( boost::iequals( shape, "Ellipsoid") )
+   else if ( string_icompare( shape, "Ellipsoid") == 0 )
       return make_DynamicBody(ellipsoidFromConfig( block ) );
-   else if ( boost::iequals( shape, "Box"      ) )
+   else if ( string_icompare( shape, "Box"      ) == 0 )
       return make_DynamicBody(AABBFromConfig     ( block ) );
-   else if ( boost::iequals( shape, "SphereSlice") )
+   else if ( string_icompare( shape, "SphereSlice") == 0 )
       return make_DynamicBody(sphereSliceFromConfig   ( block ) );
-   else if ( boost::iequals( shape, "HollowSphere") )
+   else if ( string_icompare( shape, "HollowSphere") == 0 )
       return make_DynamicBody(hollowSphereFromConfig  ( block ) );
-   else if ( boost::iequals( shape, "LogicalAND") )
+   else if ( string_icompare( shape, "LogicalAND") == 0 )
       return bodyANDFromConfig ( block );
-   else if ( boost::iequals( shape, "LogicalOR") )
+   else if ( string_icompare( shape, "LogicalOR") == 0 )
       return bodyORFromConfig  ( block );
-   else if ( boost::iequals( shape, "LogicalXOR") )
+   else if ( string_icompare( shape, "LogicalXOR") == 0 )
       return bodyXORFromConfig  ( block );
-   else if ( boost::iequals( shape, "LogicalNOT") )
+   else if ( string_icompare( shape, "LogicalNOT") == 0 )
       return bodyNOTFromConfig  ( block );
 
    WALBERLA_ABORT( "Unknown Block " << block.getKey() << "\nAllowed blocks are 'Sphere', 'Cylinder', 'Torus' and 'Ellipsoid'" );
diff --git a/src/geometry/initializer/BoundaryFromDomainBorder.h b/src/geometry/initializer/BoundaryFromDomainBorder.h
index cc2ecb9e98705dbbc25a657135335f184b0bcf46..9fa9937815e640880c2722cf3df1b58f1cad864c 100644
--- a/src/geometry/initializer/BoundaryFromDomainBorder.h
+++ b/src/geometry/initializer/BoundaryFromDomainBorder.h
@@ -34,8 +34,6 @@
 #include "stencil/D3Q7.h"
 #include "stencil/Directions.h"
 
-#include <boost/algorithm/string/predicate.hpp>
-
 
 namespace walberla {
 namespace geometry {
diff --git a/src/geometry/initializer/BoundaryFromDomainBorder.impl.h b/src/geometry/initializer/BoundaryFromDomainBorder.impl.h
index dca93f84d01ce55b345fe585b1b34263856249f8..38a97d82451d6fc114541f892aa023660c3a9b02 100644
--- a/src/geometry/initializer/BoundaryFromDomainBorder.impl.h
+++ b/src/geometry/initializer/BoundaryFromDomainBorder.impl.h
@@ -19,8 +19,9 @@
 //
 //======================================================================================================================
 
+#include "core/StringUtility.h"
 
-#include <boost/algorithm/string.hpp>
+#include <algorithm>
 
 namespace walberla {
 namespace geometry {
@@ -68,15 +69,15 @@ void BoundaryFromDomainBorder<Handling>::init( const Config::BlockHandle & block
    cell_idx_t  wallDistance            = blockHandle.getParameter<cell_idx_t>( "walldistance", 0 );
    cell_idx_t  ghostLayersToInitialize = blockHandle.getParameter<cell_idx_t>( "ghostLayersToInitialize", std::numeric_limits<cell_idx_t>::max() );
 
-   std::set<std::string> directionStrings;
-   boost::split( directionStrings, directionStr,boost::is_any_of(","));
+   std::vector<std::string> directionStrings = string_split( directionStr, "," );
 
    bool atLeastOneBoundarySet = false;
    using stencil::D3Q7;
    for( auto dirIt = D3Q7::beginNoCenter(); dirIt != D3Q7::end(); ++dirIt )
    {
-      bool isAll = boost::algorithm::iequals( directionStr, "all" );
-      bool isInDirectionStrings = directionStrings.find( stencil::dirToString[*dirIt] ) != directionStrings.end();
+      bool isAll = string_icompare( directionStr, "all" ) == 0;
+      bool isInDirectionStrings = std::find( directionStrings.begin(), directionStrings.end(),
+                                             stencil::dirToString[*dirIt] ) != directionStrings.end();
 
       if( isAll || isInDirectionStrings )
       {
diff --git a/src/geometry/initializer/BoundaryFromVoxelFile.h b/src/geometry/initializer/BoundaryFromVoxelFile.h
index 619a72d7eaf74db336e17793282ffb358aa26f87..6bef2c8c3c2260b1b728fdce1158f08f3c838a9c 100644
--- a/src/geometry/initializer/BoundaryFromVoxelFile.h
+++ b/src/geometry/initializer/BoundaryFromVoxelFile.h
@@ -44,7 +44,6 @@
 
 #include "field/FlagField.h"
 
-#include <boost/algorithm/string/predicate.hpp>
 #include <map>
 #include <utility>
 #include <vector>
diff --git a/src/geometry/initializer/OverlapFieldFromBody.cpp b/src/geometry/initializer/OverlapFieldFromBody.cpp
index 457fc2cb5265d130a854969990d1325c7ac2c8eb..9452a0563c29f28670267c4913a26e4ad9e8b28d 100644
--- a/src/geometry/initializer/OverlapFieldFromBody.cpp
+++ b/src/geometry/initializer/OverlapFieldFromBody.cpp
@@ -32,10 +32,9 @@
 #include "core/Abort.h"
 #include "core/config/Config.h"
 #include "core/logging/Logging.h"
+#include "core/StringUtility.h"
 #include "field/GhostLayerField.h"
 
-#include <boost/algorithm/string.hpp>
-
 
 namespace walberla {
 namespace geometry {
@@ -92,11 +91,11 @@ namespace initializer {
 
          uint_t superSamplingDepth = subBlock.getParameter<uint_t>("superSamplingDepth", uint_t(4) );
 
-         if      ( boost::iequals( shape, "Sphere"   ) )  init ( sphereFromConfig   ( subBlock ), addOrSubtract, superSamplingDepth );
-         else if ( boost::iequals( shape, "Cylinder" ) )  init ( cylinderFromConfig ( subBlock ), addOrSubtract, superSamplingDepth );
-         else if ( boost::iequals( shape, "Torus"    ) )  init ( torusFromConfig    ( subBlock ), addOrSubtract, superSamplingDepth );
-         else if ( boost::iequals( shape, "Ellipsoid") )  init ( ellipsoidFromConfig( subBlock ), addOrSubtract, superSamplingDepth );
-         else if ( boost::iequals( shape, "Box"      ) )  init ( AABBFromConfig     ( subBlock ), addOrSubtract, superSamplingDepth );
+         if      ( string_icompare( shape, "Sphere"   ) == 0 )  init ( sphereFromConfig   ( subBlock ), addOrSubtract, superSamplingDepth );
+         else if ( string_icompare( shape, "Cylinder" ) == 0 )  init ( cylinderFromConfig ( subBlock ), addOrSubtract, superSamplingDepth );
+         else if ( string_icompare( shape, "Torus"    ) == 0 )  init ( torusFromConfig    ( subBlock ), addOrSubtract, superSamplingDepth );
+         else if ( string_icompare( shape, "Ellipsoid") == 0 )  init ( ellipsoidFromConfig( subBlock ), addOrSubtract, superSamplingDepth );
+         else if ( string_icompare( shape, "Box"      ) == 0 )  init ( AABBFromConfig     ( subBlock ), addOrSubtract, superSamplingDepth );
          else
          {
             WALBERLA_ABORT( "Unknown Block " << subBlock.getKey() << " in block " << blockHandle.getKey() << "\n"
diff --git a/src/geometry/initializer/OverlapFieldFromBody.h b/src/geometry/initializer/OverlapFieldFromBody.h
index 3671049ace5727d153abd98c41b717cd24672c81..b12b9e2bc097b25a52fa20274c4a49fd96fab84f 100644
--- a/src/geometry/initializer/OverlapFieldFromBody.h
+++ b/src/geometry/initializer/OverlapFieldFromBody.h
@@ -32,8 +32,6 @@
 #include "core/logging/Logging.h"
 #include "field/GhostLayerField.h"
 
-#include <boost/algorithm/string.hpp>
-
 
 namespace walberla {
 namespace geometry {
diff --git a/src/geometry/initializer/ScalarFieldFromBody.impl.h b/src/geometry/initializer/ScalarFieldFromBody.impl.h
index 0a166fd0ef58eec0a610370415a5aee9ff6c968b..25f459552406edb2d5accf5c88117e0fead84697 100644
--- a/src/geometry/initializer/ScalarFieldFromBody.impl.h
+++ b/src/geometry/initializer/ScalarFieldFromBody.impl.h
@@ -31,8 +31,6 @@
 #include "core/logging/Logging.h"
 #include "core/mpi/Reduce.h"
 
-#include <boost/algorithm/string.hpp>
-
 
 namespace walberla {
 namespace geometry {
diff --git a/src/geometry/mesh/TriangleMeshIO.cpp b/src/geometry/mesh/TriangleMeshIO.cpp
index ad3c1349c6f59185eee11386a78b7d171f369b80..3581637e30e278fa638b72a7cbbf0d466c2f229b 100644
--- a/src/geometry/mesh/TriangleMeshIO.cpp
+++ b/src/geometry/mesh/TriangleMeshIO.cpp
@@ -29,8 +29,7 @@
 #include "core/math/AABB.h"
 #include "core/mpi/Broadcast.h"
 #include "core/Regex.h"
-
-#include <boost/algorithm/string.hpp>
+#include "core/StringUtility.h"
 
 #include <cmath>
 #include <fstream>
@@ -52,11 +51,11 @@ namespace geometry {
       if( is.fail() )
          WALBERLA_ABORT( "Error while opening file " << meshFilename << "!" );
 
-      if ( boost::algorithm::ends_with( meshFilename, ".obj")  )
+      if ( string_ends_with( meshFilename, ".obj")  )
          readMeshObj( is, mesh );
-      else if ( boost::algorithm::ends_with( meshFilename, ".pov") )
+      else if ( string_ends_with( meshFilename, ".pov") )
          readMeshPov( is, mesh );
-      else if ( boost::algorithm::ends_with( meshFilename, ".off") )
+      else if ( string_ends_with( meshFilename, ".off") )
          readMeshOff( is, mesh );
       else
          WALBERLA_ABORT( "Unknown mesh file format when loading " << meshFilename << ". Supported formats are obj, pov and off." );
@@ -75,13 +74,13 @@ namespace geometry {
       if( os.fail() )
          WALBERLA_ABORT( "Error while opening file " << meshFilename << "!" );
 
-      if ( boost::algorithm::ends_with( meshFilename, ".obj")  )
+      if ( string_ends_with( meshFilename, ".obj")  )
          writeMeshObj( os, mesh );
-      else if ( boost::algorithm::ends_with( meshFilename, ".pov") )
+      else if ( string_ends_with( meshFilename, ".pov") )
          writeMeshPov( os, mesh );
-      else if ( boost::algorithm::ends_with( meshFilename, ".off") )
+      else if ( string_ends_with( meshFilename, ".off") )
          writeMeshOff( os, mesh );
-      else if ( boost::algorithm::ends_with( meshFilename, ".vtp") )
+      else if ( string_ends_with( meshFilename, ".vtp") )
          writeMeshVtp( os, mesh );
       else
          WALBERLA_ABORT( "Unknown mesh file format when writing " << meshFilename << ". Supported formats are: obj,pov,off and vtp.");
@@ -354,8 +353,7 @@ namespace geometry {
       else
          faceOffset = mesh.getNumVertices();
 
-      std::vector< string > splitVec;
-      boost::split( splitVec, stripped, boost::is_any_of("{}"), boost::token_compress_on );
+      std::vector< string > splitVec = string_split( stripped, "{}" );
 
       State state;
 
@@ -363,7 +361,7 @@ namespace geometry {
 
       for( size_t i=1; i<splitVec.size(); ++i )
       {
-         boost::trim(splitVec[i]);
+         string_trim(splitVec[i]);
          if( splitVec[i] == "vertex_vectors" ) {
             state = VERTEX;
          } else if ( splitVec[i] == "normal_vectors" ) {
diff --git a/src/python_coupling/CreateConfig.cpp b/src/python_coupling/CreateConfig.cpp
index 61054f4f1492450bce962000650280ac931e5156..b3d1e512251a2c89a2f42f468365b133fdd0a95c 100644
--- a/src/python_coupling/CreateConfig.cpp
+++ b/src/python_coupling/CreateConfig.cpp
@@ -25,8 +25,8 @@
 #include "core/config/Config.h"
 #include "core/config/Create.h"
 #include "core/logging/Logging.h"
+#include "core/StringUtility.h"
 
-#include <boost/algorithm/string.hpp>
 #include <exception>
 
 
@@ -223,7 +223,7 @@ namespace python_coupling {
 
       auto argVec = std::vector<std::string> (argv+1, argv + argc);
 
-      if ( boost::algorithm::ends_with( filename, ".py")  ) {
+      if ( string_ends_with( filename, ".py")  ) {
          config = createConfigFromPythonScript( filename, "config", argVec );
       }
       else {
@@ -242,7 +242,7 @@ namespace python_coupling {
          throw std::runtime_error( config::usageString(argv[0]) );
 
       std::string filename( argv[1] );
-      if ( boost::algorithm::ends_with( filename, ".py")  ) {
+      if ( string_ends_with( filename, ".py")  ) {
          auto argVec = std::vector<std::string> (argv+1, argv + argc);
          return createConfigIteratorFromPythonScript( filename, "config", argVec );
       }
diff --git a/src/python_coupling/Shell.cpp b/src/python_coupling/Shell.cpp
index 1a34e91a4c4b0d717ec8201cc82c7db47eafd791..85cb228121ae7814b0afadee4a7f386a9de7df1e 100644
--- a/src/python_coupling/Shell.cpp
+++ b/src/python_coupling/Shell.cpp
@@ -30,8 +30,7 @@
 #include "Manager.h"
 
 #include "core/logging/Logging.h"
-
-#include <boost/algorithm/string.hpp>
+#include "core/StringUtility.h"
 
 
 namespace walberla {
@@ -124,7 +123,7 @@ namespace python_coupling {
 
          std::string strLine ( line );
          std::string strTrimmedLine( line );
-         boost::algorithm::trim( strTrimmedLine );
+         string_trim( strTrimmedLine );
 
          PyMem_Free( line );
 
diff --git a/src/vtk/Initialization.cpp b/src/vtk/Initialization.cpp
index 7109d9e294c23cd310f88b0cd51297ed8d595eed..d25529731cfb30547aec0854e56529f7b2dfe45e 100644
--- a/src/vtk/Initialization.cpp
+++ b/src/vtk/Initialization.cpp
@@ -23,12 +23,8 @@
 #include "Initialization.h"
 
 #include "core/Abort.h"
-
 #include "core/logging/Logging.h"
-
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/predicate.hpp>
-#include <boost/algorithm/string/split.hpp>
+#include "core/StringUtility.h"
 
 #include <functional>
 
@@ -43,7 +39,8 @@ static void splitVector( T& x, T& y, T& z, const Config::BlockHandle& bb, const
 {
    std::vector< std::string > coordinates;
    std::string vector = bb.getParameter< std::string >( vertex );
-   boost::split( coordinates, vector, boost::is_any_of("<,> \t") );
+   coordinates = string_split( vector, "<,> \t" );
+
    coordinates.erase( std::remove_if( coordinates.begin(), coordinates.end(), std::bind( &std::string::empty,  std::placeholders::_1 ) ), coordinates.end() );
 
    if( coordinates.size() != 3 )
@@ -60,7 +57,7 @@ static std::vector< std::string > splitList( const std::string& string )
 {
    std::vector< std::string > list;
 
-   boost::split( list, string, boost::is_any_of(", \t") );
+   list = string_split( string, ", \t" );
    list.erase( std::remove_if( list.begin(), list.end(), std::bind( &std::string::empty,  std::placeholders::_1 ) ), list.end() );
 
    return list;
@@ -71,7 +68,7 @@ static std::vector< std::string > splitList( const std::string& string )
 static void addStates( Set<SUID>& set, const std::string& string )
 {
    std::vector< std::string > states;
-   boost::split( states, string, boost::is_any_of(", \t") );
+   states = string_split( string, ", \t" );
    states.erase( std::remove_if( states.begin(), states.end(), std::bind( &std::string::empty,  std::placeholders::_1 ) ), states.end() );
 
    for( auto it = states.begin(); it != states.end(); ++it )
@@ -94,7 +91,7 @@ void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & ou
 
 
 struct CaseInsensitiveCompare {
-   bool operator()( const std::string& lhs, const std::string& rhs ) const { return boost::ilexicographical_compare( lhs, rhs ); }
+   bool operator()( const std::string& lhs, const std::string& rhs ) const { return ( string_icompare(lhs, rhs) < 0 ); }
 }; // only required in 'initializeVTKOutput' below
 
 void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & outputFunctions,
@@ -238,10 +235,10 @@ void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & ou
 
       for( auto subBlock = subBlocks.begin(); subBlock != subBlocks.end(); ++subBlock )
       {
-         if( boost::algorithm::iequals( std::string( subBlock->getKey(), 0, 11 ), std::string("AABB_filter") ) )
+         if( string_icompare( std::string( subBlock->getKey(), 0, 11 ), std::string("AABB_filter") ) == 0 )
             aabbBlocks.push_back( *subBlock );
 
-         if( boost::algorithm::iequals( std::string( subBlock->getKey(), 0, 13 ), std::string("CellBB_filter") ) )
+         if( string_icompare( std::string( subBlock->getKey(), 0, 13 ), std::string("CellBB_filter") ) == 0 )
             cellBBBlocks.push_back( *subBlock );
       }
 
@@ -557,7 +554,7 @@ void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & ou
 *   \endcode
 *
 *   \param outputFunctions           The output functions which correspond to the just created VTKOutput objects
-*   \param registerVTKOutputFunction A boost function / function pointer that the user must provide and that is used for
+*   \param registerVTKOutputFunction A function pointer that the user must provide and that is used for
 *                                    registering cell filters and block data writers which then can be referenced in the
 *                                    configuration file and which are used to assemble the VTKOutput objects
 *   \param storage                   The structured block storage the VTKOutput object shall be associated with
diff --git a/tests/lbm/DiffusionTest.cpp b/tests/lbm/DiffusionTest.cpp
index bdcb97ff68a2ce57a9a32a15671d5986a63024c5..cdb6c71a057d209f0c3f4a9c38797ec4a486c34d 100644
--- a/tests/lbm/DiffusionTest.cpp
+++ b/tests/lbm/DiffusionTest.cpp
@@ -79,6 +79,7 @@
 #include "vtk/VTKOutput.h"
 
 #include <functional>
+#include <string>
 
 
 namespace walberla {
@@ -197,18 +198,18 @@ int run( int argc, char **argv )
    if( argc > 1 ) {
       std::vector<std::string> args( argv, argv + argc );
       for( uint_t i = 1; i < uint_c(argc); ++i ) {
-              if( boost::equals(argv[i], "-d"      ) )   d      = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-dim"    ) )   dim    = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-dx"     ) )   dx     = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-dt"     ) )   dt     = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-dv"     ) )   dv     = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-v"      ) )   u_in   = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-t"      ) )   time   = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-err"    ) )   err    = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "--gui"   ) )   useGui = true;
-         else if( boost::equals(argv[i], "--quiet" ) )   quiet  = true;
-         else if( boost::equals(argv[i], "--vtk"   ) )   useVTK = true;
-         else if( boost::equals(argv[i], "-c"      ) )   ++i;
+              if( std::string(argv[i]) == "-d"      )   d      = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-dim"    )   dim    = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-dx"     )   dx     = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-dt"     )   dt     = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-dv"     )   dv     = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-v"      )   u_in   = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-t"      )   time   = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-err"    )   err    = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "--gui"   )   useGui = true;
+         else if( std::string(argv[i]) == "--quiet" )   quiet  = true;
+         else if( std::string(argv[i]) == "--vtk"   )   useVTK = true;
+         else if( std::string(argv[i]) == "-c"      )   ++i;
          else if( argv[i][0] != '-' ){
             WALBERLA_ABORT( "Usage: -option value" );
          } else
@@ -345,7 +346,7 @@ int main(int argc, char **argv)
    mpi::Environment env( argc, argv );
    bool corr = true;
    for( int i=0; i<argc; ++i ){
-      if( boost::equals(argv[i], "-c" ) ){
+      if( std::string(argv[i]) == "-c" ){
          corr = std::atoi( argv[++i] ) != 0;
          break;
       }
diff --git a/tests/lbm/boundary/DiffusionDirichlet.cpp b/tests/lbm/boundary/DiffusionDirichlet.cpp
index 9e2b0819cfcfb5a188b6cb007a36c9345f015389..ec0f1c51071aaa14108a97313b833df34e027e18 100644
--- a/tests/lbm/boundary/DiffusionDirichlet.cpp
+++ b/tests/lbm/boundary/DiffusionDirichlet.cpp
@@ -81,6 +81,7 @@
 #include "vtk/VTKOutput.h"
 
 #include <complex>
+#include <string>
 
 
 namespace walberla {
@@ -221,14 +222,14 @@ int main( int argc, char **argv )
    if( argc > 1 ) {
       std::vector<std::string> args( argv, argv + argc );
       for( uint_t i = 1; i < uint_c(argc); ++i ) {
-              if( boost::equals(argv[i], "-o"    ) ) omega  = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-l"    ) ) length = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-w"    ) ) width  = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-v"    ) ) velx   = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-t"    ) ) time   = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-e"    ) ) error  = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "--gui" ) ) useGui = true;
-         else if( boost::equals(argv[i], "--vtk" ) ) useVTK = true;
+              if( std::string(argv[i]) == "-o" ) omega  = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-l" ) length = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-w" ) width  = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-v" ) velx   = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-t" ) time   = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-e" ) error  = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "--gui" ) useGui = true;
+         else if( std::string(argv[i]) == "--vtk" ) useVTK = true;
          else if( argv[i][0] != '-' ){
             WALBERLA_ABORT( "Usage: --option or -option value" );
          } else
diff --git a/tests/lbm/boundary/SimpleDiffusionDirichlet.cpp b/tests/lbm/boundary/SimpleDiffusionDirichlet.cpp
index bb86d552a3262adfeb99a121f94ed480d7ac9002..699d2fe1bff055b51fa00c2f0adbdd499976bbff 100644
--- a/tests/lbm/boundary/SimpleDiffusionDirichlet.cpp
+++ b/tests/lbm/boundary/SimpleDiffusionDirichlet.cpp
@@ -76,6 +76,7 @@
 #include <stdexcept>
 #include <array>
 #include <functional>
+#include <string>
 
 #include "gather/GnuPlotGraphWriter.h"
 #include "field/vtk/FlagFieldCellFilter.h"
@@ -429,14 +430,14 @@ int main( int argc, char **argv )
    if( argc > 1 ) {
       std::vector<std::string> args( argv, argv + argc );
       for( uint_t i = 1; i < uint_c(argc); ++i ) {
-              if( boost::equals(argv[i], "-l"    ) )   length  = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-w"    ) )   width   = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-t"    ) )   time    = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-d"    ) )   dv      = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-o"    ) )   omega   = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-c"    ) )   closed  = string_to_num<int>( args[++i] ) != 0;
-         else if( boost::equals(argv[i], "-r"    ) )   levels += string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "--vtk" ) )   useVTK  = true;
+              if( std::string(argv[i]) == "-l"    )   length  = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-w"    )   width   = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-t"    )   time    = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-d"    )   dv      = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-o"    )   omega   = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-c"    )   closed  = string_to_num<int>( args[++i] ) != 0;
+         else if( std::string(argv[i]) == "-r"    )   levels += string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "--vtk" )   useVTK  = true;
          else if( argv[i][0] != '-' ){
             std::cerr << "Usage: -option value" << std::endl; return EXIT_FAILURE;
          } else
diff --git a/tests/lbm/refinement/NonConstantDiffusion.cpp b/tests/lbm/refinement/NonConstantDiffusion.cpp
index 592d23ce7fbe9e8535e0076d95960b0b40d23778..d931cb35eacde2a34399d3f264dbfa20356cb96b 100644
--- a/tests/lbm/refinement/NonConstantDiffusion.cpp
+++ b/tests/lbm/refinement/NonConstantDiffusion.cpp
@@ -74,6 +74,7 @@
 
 #include <stdexcept>
 #include <functional>
+#include <string>
 
 #include "gather/GnuPlotGraphWriter.h"
 #include "field/vtk/FlagFieldCellFilter.h"
@@ -273,16 +274,16 @@ int main( int argc, char **argv )
    if( argc > 1 ) {
       std::vector<std::string> args( argv, argv + argc );
       for( uint_t i = 1; i < uint_c(argc); ++i ) {
-              if( boost::equals(argv[i], "-l"    ) )   length  = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-w"    ) )   width   = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-t"    ) )   time    = string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "-dv"   ) )   dv      = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-v"    ) )   v       = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-do"   ) )   domega  = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-o"    ) )   omega   = string_to_num<real_t>( args[++i] );
-         else if( boost::equals(argv[i], "-c"    ) )   closed  = string_to_num<int>( args[++i] ) != 0;
-         else if( boost::equals(argv[i], "-r"    ) )   levels += string_to_num<uint_t>( args[++i] );
-         else if( boost::equals(argv[i], "--vtk" ) )   useVTK  = true;
+              if( std::string(argv[i]) == "-l"    )   length  = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-w"    )   width   = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-t"    )   time    = string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "-dv"   )   dv      = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-v"    )   v       = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-do"   )   domega  = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-o"    )   omega   = string_to_num<real_t>( args[++i] );
+         else if( std::string(argv[i]) == "-c"    )   closed  = string_to_num<int>( args[++i] ) != 0;
+         else if( std::string(argv[i]) == "-r"    )   levels += string_to_num<uint_t>( args[++i] );
+         else if( std::string(argv[i]) == "--vtk" )   useVTK  = true;
          else if( argv[i][0] != '-' ){
             std::cerr << "Usage: -option value" << std::endl; return EXIT_FAILURE;
          } else