diff --git a/ProcessLib/BoundaryCondition/BoundaryCondition.cpp b/ProcessLib/BoundaryCondition/BoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..29d94a7fa0eb214af2aae30554092b532611ca81
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/BoundaryCondition.cpp
@@ -0,0 +1,46 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "BoundaryCondition.h"
+#include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+#include "BoundaryConditionConfig.h"
+#include "UniformDirichletBoundaryCondition.h"
+#include "UniformNeumannBoundaryCondition.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<BoundaryCondition> createBoundaryCondition(
+    const BoundaryConditionConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table,
+    const MeshLib::Mesh& mesh,
+    const int variable_id,
+    const unsigned integration_order)
+{
+    MeshGeoToolsLib::MeshNodeSearcher& mesh_node_searcher =
+        MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher(mesh);
+
+    MeshGeoToolsLib::BoundaryElementsSearcher boundary_element_searcher(
+        mesh, mesh_node_searcher);
+
+    auto const type = config.config.peekConfigParameter<std::string>("type");
+
+    if (type == "UniformDirichlet") {
+        return createUniformDirichletBoundaryCondition(
+            config, mesh_node_searcher, dof_table, variable_id);
+    } else if (type == "UniformNeumann") {
+        return createUniformNeumannBoundaryCondition(
+            config, boundary_element_searcher, dof_table, variable_id,
+            integration_order, mesh.getDimension());
+    } else {
+        OGS_FATAL("Unknown boundary condition type: `%s'.", type.c_str());
+    }
+}
+
+}  // ProcessLib
diff --git a/ProcessLib/BoundaryCondition/BoundaryCondition.h b/ProcessLib/BoundaryCondition/BoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..674bcd324840377b3ac6b43f8e73f551cca73cc9
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/BoundaryCondition.h
@@ -0,0 +1,46 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_BOUNDARYCONDITION_H
+#define PROCESSLIB_BOUNDARYCONDITION_H
+
+#include "NumLib/NumericsConfig.h"
+
+namespace MeshLib
+{
+class Mesh;
+}
+
+namespace NumLib
+{
+class LocalToGlobalIndexMap;
+}
+
+namespace ProcessLib
+{
+struct BoundaryConditionConfig;
+
+class BoundaryCondition
+{
+public:
+    virtual void apply(const double t, GlobalVector const& x, GlobalMatrix& K,
+                       GlobalVector& b) = 0;
+    virtual ~BoundaryCondition() = default;
+};
+
+std::unique_ptr<BoundaryCondition> createBoundaryCondition(
+    const BoundaryConditionConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table,
+    const MeshLib::Mesh& mesh,
+    const int variable_id,
+    const unsigned integration_order);
+
+}  // ProcessLib
+
+#endif  // PROCESSLIB_BOUNDARYCONDITION_H
diff --git a/ProcessLib/BoundaryCondition/BoundaryConditionCollection.cpp b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..759e09adc0d222af886665e5498ecd62573f6241
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.cpp
@@ -0,0 +1,57 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "BoundaryConditionCollection.h"
+
+void initializeDirichletBCs(
+    std::vector<std::unique_ptr<ProcessLib::BoundaryCondition>> const&
+        boundary_conditions,
+    std::vector<NumLib::IndexValueVector<GlobalIndexType>>&
+        dirichlet_bcs)
+{
+    for (auto const& bc : boundary_conditions) {
+        if (auto* dirichlet_bc =
+                dynamic_cast<ProcessLib::DirichletBoundaryCondition*>(
+                    bc.get())) {
+            dirichlet_bcs.emplace_back(dirichlet_bc->getBCValues());
+        }
+    }
+}
+
+namespace ProcessLib
+{
+void BoundaryConditionCollection::apply(const double t, GlobalVector const& x,
+                                        GlobalMatrix& K,
+                                        GlobalVector& b)
+{
+    for (auto const& bc : _boundary_conditions)
+        bc->apply(t, x, K, b);
+}
+
+void BoundaryConditionCollection::addBCsForProcessVariables(
+    std::vector<std::reference_wrapper<ProcessVariable>> const&
+        process_variables,
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    unsigned const integration_order)
+{
+    for (int variable_id = 0;
+         variable_id < static_cast<int>(process_variables.size());
+         ++variable_id)
+    {
+        ProcessVariable& pv = process_variables[variable_id];
+        auto bcs = pv.getBoundaryConditions(dof_table, variable_id,
+                                            integration_order);
+
+        std::move(bcs.begin(), bcs.end(),
+                  std::back_inserter(_boundary_conditions));
+    }
+
+    initializeDirichletBCs(_boundary_conditions, _dirichlet_bcs);
+}
+}
diff --git a/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h
new file mode 100644
index 0000000000000000000000000000000000000000..48e899c594cc829af7de26f4b51dcf3a99c24392
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/BoundaryConditionCollection.h
@@ -0,0 +1,46 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_BOUNDARYCONDITIONCOLLECTION_H
+#define PROCESSLIB_BOUNDARYCONDITIONCOLLECTION_H
+
+#include "DirichletBoundaryCondition.h"
+#include "ProcessLib/ProcessVariable.h"
+
+namespace ProcessLib
+{
+
+class BoundaryConditionCollection : public BoundaryCondition
+{
+public:
+    void apply(const double t, GlobalVector const& x, GlobalMatrix& K,
+               GlobalVector& b) override;
+
+    std::vector<NumLib::IndexValueVector<GlobalIndexType>> const*
+    getKnownSolutions(double const /*t*/) const
+    {
+        // TODO time-dependent Dirichlet BCs.
+        return &_dirichlet_bcs;
+    }
+
+    void addBCsForProcessVariables(
+        std::vector<std::reference_wrapper<ProcessVariable>> const&
+            process_variables,
+        NumLib::LocalToGlobalIndexMap const& dof_table,
+        unsigned const integration_order);
+
+private:
+    std::vector<NumLib::IndexValueVector<GlobalIndexType>> _dirichlet_bcs;
+    std::vector<std::unique_ptr<BoundaryCondition>> _boundary_conditions;
+};
+
+
+}  // ProcessLib
+
+#endif  // PROCESSLIB_BOUNDARYCONDITIONCOLLECTION_H
diff --git a/ProcessLib/BoundaryCondition/BoundaryConditionConfig.h b/ProcessLib/BoundaryCondition/BoundaryConditionConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9c6d98e350dc747939bcca89fb67576d461e0de
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/BoundaryConditionConfig.h
@@ -0,0 +1,44 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_BOUNDARYCONDITIONCONFIG_H
+#define PROCESSLIB_BOUNDARYCONDITIONCONFIG_H
+
+#include "BaseLib/ConfigTree.h"
+#include "GeoLib/GEOObjects.h"
+
+namespace ProcessLib
+{
+
+struct BoundaryConditionConfig final
+{
+    BoundaryConditionConfig(BaseLib::ConfigTree&& config_,
+                            GeoLib::GeoObject const& geometry_,
+                            int const component_id_)
+        : config(std::move(config_)),
+          geometry(geometry_),
+          component_id(component_id_)
+    {
+    }
+
+    BoundaryConditionConfig(BoundaryConditionConfig&& other)
+        : config(std::move(other.config)),
+          geometry(other.geometry),
+          component_id(other.component_id)
+    {
+    }
+
+    BaseLib::ConfigTree config;
+    GeoLib::GeoObject const& geometry;
+    int const component_id;
+};
+
+}  // ProcessLib
+
+#endif  // PROCESSLIB_BOUNDARYCONDITIONCONFIG_H
diff --git a/ProcessLib/BoundaryCondition/CMakeLists.txt b/ProcessLib/BoundaryCondition/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ProcessLib/BoundaryCondition/DirichletBoundaryCondition.h b/ProcessLib/BoundaryCondition/DirichletBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..9dccf2e1820404e44f22783026e41a37ed8ee0d0
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/DirichletBoundaryCondition.h
@@ -0,0 +1,34 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESS_LIB_DIRICHLETBC_H
+#define PROCESS_LIB_DIRICHLETBC_H
+
+#include "NumLib/IndexValueVector.h"
+#include "BoundaryCondition.h"
+
+namespace ProcessLib
+{
+class DirichletBoundaryCondition : public BoundaryCondition
+{
+public:
+    virtual NumLib::IndexValueVector<GlobalIndexType> getBCValues() = 0;
+
+    void apply(const double /*t*/,
+               GlobalVector const& /*x*/,
+               GlobalMatrix& /*K*/,
+               GlobalVector& /*b*/) override final
+    {
+        // Do nothing. Dirichlet BCs are handled specially.
+    }
+};
+
+}  // namespace ProcessLib
+
+#endif  // PROCESS_LIB_DIRICHLETBC_H
diff --git a/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition-impl.h b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition-impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..3bcf89bc256e31878849f3bb7eceb2be368e4d7b
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition-impl.h
@@ -0,0 +1,90 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "GenericNaturalBoundaryCondition.h"
+#include "ProcessLib/Utils/CreateLocalAssemblers.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
+#include "GenericNaturalBoundaryConditionLocalAssembler.h"
+
+namespace ProcessLib
+{
+template <typename BoundaryConditionData,
+          template <typename, typename, unsigned>
+          class LocalAssemblerImplementation>
+template <typename Data>
+GenericNaturalBoundaryCondition<BoundaryConditionData,
+                                LocalAssemblerImplementation>::
+    GenericNaturalBoundaryCondition(
+        typename std::enable_if<
+            std::is_same<typename std::decay<BoundaryConditionData>::type,
+                         typename std::decay<Data>::type>::value,
+            unsigned const>::type integration_order,
+        NumLib::LocalToGlobalIndexMap const& dof_table_bulk,
+        int const variable_id, int const component_id,
+        unsigned const global_dim,
+        std::vector<MeshLib::Element*> const& elements, Data&& data)
+    : _data(std::forward<Data>(data)), _integration_order(integration_order)
+{
+    assert(component_id <
+           static_cast<int>(dof_table_bulk.getNumberOfComponents()));
+
+    // deep copy because the neumann bc config destroys the elements.
+    std::transform(elements.begin(), elements.end(),
+                   std::back_inserter(_elements),
+                   std::mem_fn(&MeshLib::Element::clone));
+
+    std::vector<MeshLib::Node*> nodes = MeshLib::getUniqueNodes(_elements);
+
+    auto const& mesh_subsets =
+        dof_table_bulk.getMeshSubsets(variable_id, component_id);
+
+    // TODO extend the node intersection to all parts of mesh_subsets, i.e.
+    // to each of the MeshSubset in the mesh_subsets.
+    _mesh_subset_all_nodes.reset(
+        mesh_subsets.getMeshSubset(0).getIntersectionByNodes(nodes));
+    std::unique_ptr<MeshLib::MeshSubsets> all_mesh_subsets{
+        new MeshLib::MeshSubsets{_mesh_subset_all_nodes.get()}};
+
+    // Create local DOF table from intersected mesh subsets for the given
+    // variable and component ids.
+    _dof_table_boundary.reset(dof_table_bulk.deriveBoundaryConstrainedMap(
+        variable_id, component_id, std::move(all_mesh_subsets), _elements));
+
+    createLocalAssemblers<LocalAssemblerImplementation>(
+        global_dim, _elements, *_dof_table_boundary, _integration_order,
+        _local_assemblers, _data);
+}
+
+template <typename BoundaryConditionData,
+          template <typename, typename, unsigned>
+          class LocalAssemblerImplementation>
+GenericNaturalBoundaryCondition<
+    BoundaryConditionData,
+    LocalAssemblerImplementation>::~GenericNaturalBoundaryCondition()
+{
+    for (auto e : _elements)
+        delete e;
+}
+
+template <typename BoundaryConditionData,
+          template <typename, typename, unsigned>
+          class LocalAssemblerImplementation>
+void GenericNaturalBoundaryCondition<
+    BoundaryConditionData,
+    LocalAssemblerImplementation>::apply(const double t,
+                                         const GlobalVector& x,
+                                         GlobalMatrix& K,
+                                         GlobalVector& b)
+{
+    GlobalExecutor::executeMemberOnDereferenced(
+        &GenericNaturalBoundaryConditionLocalAssemblerInterface::assemble,
+        _local_assemblers, *_dof_table_boundary, t, x, K, b);
+}
+
+}  // ProcessLib
diff --git a/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition.h b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b29a94960da5e194006e5a3dec6f40daec4c9c7
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryCondition.h
@@ -0,0 +1,77 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_GENERICNATURALBOUNDARYCONDITION_H
+#define PROCESSLIB_GENERICNATURALBOUNDARYCONDITION_H
+
+#include "MeshLib/MeshSubset.h"
+#include "BoundaryCondition.h"
+
+namespace ProcessLib
+{
+class GenericNaturalBoundaryConditionLocalAssemblerInterface;
+
+template <typename BoundaryConditionData,
+          template <typename, typename, unsigned>
+          class LocalAssemblerImplementation>
+class GenericNaturalBoundaryCondition final : public BoundaryCondition
+{
+public:
+    /// Create a boundary condition process from given config,
+    /// DOF-table, and a mesh subset for a given variable and its component.
+    /// A local DOF-table, a subset of the given one, is constructed.
+    template <typename Data>
+    GenericNaturalBoundaryCondition(
+        typename std::enable_if<
+            std::is_same<typename std::decay<BoundaryConditionData>::type,
+                         typename std::decay<Data>::type>::value,
+            unsigned const>::type integration_order,
+        NumLib::LocalToGlobalIndexMap const& dof_table_bulk,
+        int const variable_id, int const component_id,
+        unsigned const global_dim,
+        std::vector<MeshLib::Element*> const& elements, Data&& data);
+
+    ~GenericNaturalBoundaryCondition() override;
+
+    /// Calls local assemblers which calculate their contributions to the global
+    /// matrix and the right-hand-side.
+    void apply(const double t,
+               GlobalVector const& x,
+               GlobalMatrix& K,
+               GlobalVector& b) override;
+
+private:
+    /// Data used in the assembly of the specific boundary condition.
+    BoundaryConditionData _data;
+
+    /// Vector of lower-dimensional elements on which the boundary condition is
+    /// defined.
+    std::vector<MeshLib::Element*> _elements;
+
+    std::unique_ptr<MeshLib::MeshSubset const> _mesh_subset_all_nodes;
+
+    /// Local dof table, a subset of the global one restricted to the
+    /// participating #_elements of the boundary condition.
+    std::unique_ptr<NumLib::LocalToGlobalIndexMap> _dof_table_boundary;
+
+    /// Integration order for integration over the lower-dimensional elements of
+    /// the #_function.
+    unsigned const _integration_order;
+
+    /// Local assemblers for each element of #_elements.
+    std::vector<
+        std::unique_ptr<GenericNaturalBoundaryConditionLocalAssemblerInterface>>
+        _local_assemblers;
+};
+
+}  // ProcessLib
+
+#include "GenericNaturalBoundaryCondition-impl.h"
+
+#endif  // PROCESSLIB_GENERICNATURALBOUNDARYCONDITION_H
diff --git a/ProcessLib/BoundaryCondition/GenericNaturalBoundaryConditionLocalAssembler.h b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryConditionLocalAssembler.h
new file mode 100644
index 0000000000000000000000000000000000000000..0469b00f96a8870395f573cf0f5d68241be34e21
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/GenericNaturalBoundaryConditionLocalAssembler.h
@@ -0,0 +1,56 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_GENERICNATURALBOUNDARYCONDITIONLOCALASSEMBLER_H
+#define PROCESSLIB_GENERICNATURALBOUNDARYCONDITIONLOCALASSEMBLER_H
+
+#include "NumLib/Fem/ShapeMatrixPolicy.h"
+#include "ProcessLib/Utils/InitShapeMatrices.h"
+
+namespace ProcessLib
+{
+class GenericNaturalBoundaryConditionLocalAssemblerInterface
+{
+public:
+    virtual ~GenericNaturalBoundaryConditionLocalAssemblerInterface() = default;
+
+    virtual void assemble(
+        std::size_t const id,
+        NumLib::LocalToGlobalIndexMap const& dof_table_boundary, double const t,
+        const GlobalVector& x, GlobalMatrix& K, GlobalVector& b) = 0;
+};
+
+template <typename ShapeFunction, typename IntegrationMethod,
+          unsigned GlobalDim>
+class GenericNaturalBoundaryConditionLocalAssembler
+    : public GenericNaturalBoundaryConditionLocalAssemblerInterface
+{
+protected:
+    using ShapeMatricesType = ShapeMatrixPolicyType<ShapeFunction, GlobalDim>;
+    using NodalMatrixType = typename ShapeMatricesType::NodalMatrixType;
+    using NodalVectorType = typename ShapeMatricesType::NodalVectorType;
+
+public:
+    GenericNaturalBoundaryConditionLocalAssembler(
+        MeshLib::Element const& e, unsigned const integration_order)
+        : _shape_matrices(initShapeMatrices<ShapeFunction, ShapeMatricesType,
+                                            IntegrationMethod, GlobalDim>(
+              e, integration_order)),
+          _integration_order(integration_order)
+    {
+    }
+
+protected:
+    std::vector<typename ShapeMatricesType::ShapeMatrices> _shape_matrices;
+    unsigned const _integration_order;
+};
+
+}  // ProcessLib
+
+#endif  // PROCESSLIB_GENERICNATURALBOUNDARYCONDITIONLOCALASSEMBLER_H
diff --git a/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.cpp b/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe6ce1e9bf7b86a8393972c257fd2ab5e52ecddb
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.cpp
@@ -0,0 +1,67 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "UniformDirichletBoundaryCondition.h"
+
+#include <algorithm>
+#include <vector>
+#include <logog/include/logog.hpp>
+
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+#include "BoundaryConditionConfig.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<UniformDirichletBoundaryCondition>
+createUniformDirichletBoundaryCondition(
+    BoundaryConditionConfig const& config,
+    MeshGeoToolsLib::MeshNodeSearcher& searcher,
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    int const variable_id)
+{
+    DBUG("Constructing UniformDirichletBoundaryCondition from config.");
+    //! \ogs_file_param{boundary_condition__type}
+    config.config.checkConfigParameter("type", "UniformDirichlet");
+
+    //! \ogs_file_param{boundary_condition__UniformDirichlet__value}
+    auto const value = config.config.getConfigParameter<double>("value");
+    DBUG("Using value %g", value);
+
+    // Find nodes' ids on the given mesh on which this boundary condition
+    // is defined.
+    std::vector<std::size_t> ids = searcher.getMeshNodeIDs(config.geometry);
+
+    NumLib::IndexValueVector<GlobalIndexType> bc;
+
+    // convert mesh node ids to global index for the given component
+    bc.ids.reserve(bc.ids.size() + ids.size());
+    bc.values.reserve(bc.values.size() + ids.size());
+    for (auto& id : ids) {
+        MeshLib::Location l(searcher.getMeshId(), MeshLib::MeshItemType::Node,
+                            id);
+        // TODO: that might be slow, but only done once
+        const auto g_idx =
+            dof_table.getGlobalIndex(l, variable_id, config.component_id);
+        // For the DDC approach (e.g. with PETSc option), the negative
+        // index of g_idx means that the entry by that index is a ghost one,
+        // which should be dropped. Especially for PETSc routines MatZeroRows
+        // and MatZeroRowsColumns, which are called to apply the Dirichlet BC,
+        // the negative index is not accepted like other matrix or vector
+        // PETSc routines. Therefore, the following if-condition is applied.
+        if (g_idx >= 0) {
+            bc.ids.emplace_back(g_idx);
+            bc.values.emplace_back(value);
+        }
+    }
+
+    return std::unique_ptr<UniformDirichletBoundaryCondition>(
+        new UniformDirichletBoundaryCondition(std::move(bc)));
+}
+
+}  // namespace ProcessLib
diff --git a/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.h b/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2c6e6b54a5774e3090bf1b2128ea92f9e2c787c
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/UniformDirichletBoundaryCondition.h
@@ -0,0 +1,64 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESS_LIB_BOUNDARY_CONDITION_H_
+#define PROCESS_LIB_BOUNDARY_CONDITION_H_
+
+#include "BaseLib/ConfigTree.h"
+#include "NumLib/DOF/LocalToGlobalIndexMap.h"
+#include "NumLib/NumericsConfig.h" // for GlobalIndexType
+
+#include "DirichletBoundaryCondition.h"
+
+namespace GeoLib
+{
+class GeoObject;
+}
+
+namespace MeshGeoToolsLib
+{
+class MeshNodeSearcher;
+}
+
+namespace ProcessLib
+{
+struct BoundaryConditionConfig;
+
+/// The UniformDirichletBoundaryCondition class describes a constant in space
+/// and time Dirichlet boundary condition.
+/// The expected parameter in the passed configuration is "value" which, when
+/// not present defaults to zero.
+class UniformDirichletBoundaryCondition : public DirichletBoundaryCondition
+{
+public:
+    UniformDirichletBoundaryCondition(
+        NumLib::IndexValueVector<GlobalIndexType>&& bc)
+        : _bc(std::move(bc))
+    {
+    }
+
+    NumLib::IndexValueVector<GlobalIndexType> getBCValues()
+    {
+        return std::move(_bc);
+    }
+
+private:
+    NumLib::IndexValueVector<GlobalIndexType> _bc;
+};
+
+std::unique_ptr<UniformDirichletBoundaryCondition>
+createUniformDirichletBoundaryCondition(
+    BoundaryConditionConfig const& config,
+    MeshGeoToolsLib::MeshNodeSearcher& searcher,
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    int const variable_id);
+
+}  // namespace ProcessLib
+
+#endif  // PROCESS_LIB_BOUNDARY_CONDITION_H_
diff --git a/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.cpp b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d14754f29a61c4b10fe7e57482d619c9d2374cba
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.cpp
@@ -0,0 +1,41 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "UniformNeumannBoundaryCondition.h"
+#include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
+#include "MeshLib/MeshSearch/NodeSearch.h"
+#include "ProcessLib/Utils/CreateLocalAssemblers.h"
+#include "BoundaryConditionConfig.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<UniformNeumannBoundaryCondition>
+createUniformNeumannBoundaryCondition(
+    BoundaryConditionConfig const& config,
+    MeshGeoToolsLib::BoundaryElementsSearcher& searcher,
+    NumLib::LocalToGlobalIndexMap const& dof_table, int const variable_id,
+    unsigned const integration_order, const unsigned global_dim)
+{
+    DBUG("Constructing NeumannBcConfig from config.");
+    //! \ogs_file_param{boundary_condition__type}
+    config.config.checkConfigParameter("type", "UniformNeumann");
+
+    //! \ogs_file_param{boundary_condition__UniformNeumann__value}
+    double const value = config.config.getConfigParameter<double>("value");
+    DBUG("Using value %g", value);
+
+    auto& elems = searcher.getBoundaryElements(config.geometry);
+
+    return std::unique_ptr<UniformNeumannBoundaryCondition>(
+        new UniformNeumannBoundaryCondition(integration_order, dof_table,
+                                            variable_id, config.component_id,
+                                            global_dim, elems, value));
+}
+
+}  // ProcessLib
diff --git a/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.h b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.h
new file mode 100644
index 0000000000000000000000000000000000000000..9764f2686bc4373868cf48b9cb03c39fc24d32ad
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryCondition.h
@@ -0,0 +1,35 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITION_H
+#define PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITION_H
+
+#include "GenericNaturalBoundaryCondition.h"
+#include "UniformNeumannBoundaryConditionLocalAssembler.h"
+
+namespace MeshGeoToolsLib
+{
+class BoundaryElementsSearcher;
+}
+
+namespace ProcessLib
+{
+using UniformNeumannBoundaryCondition = GenericNaturalBoundaryCondition<
+    double, UniformNeumannBoundaryConditionLocalAssembler>;
+
+std::unique_ptr<UniformNeumannBoundaryCondition>
+createUniformNeumannBoundaryCondition(
+    BoundaryConditionConfig const& config,
+    MeshGeoToolsLib::BoundaryElementsSearcher& searcher,
+    NumLib::LocalToGlobalIndexMap const& dof_table, int const variable_id,
+    unsigned const integration_order, unsigned const global_dim);
+
+}  // ProcessLib
+
+#endif  // PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITION_H
diff --git a/ProcessLib/BoundaryCondition/UniformNeumannBoundaryConditionLocalAssembler.h b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryConditionLocalAssembler.h
new file mode 100644
index 0000000000000000000000000000000000000000..2256c5d448567fffb3163a436f1b4ae7fae6b2cb
--- /dev/null
+++ b/ProcessLib/BoundaryCondition/UniformNeumannBoundaryConditionLocalAssembler.h
@@ -0,0 +1,71 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITIONLOCALASSEMBLER_H
+#define PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITIONLOCALASSEMBLER_H
+
+#include "NumLib/DOF/DOFTableUtil.h"
+
+namespace ProcessLib
+{
+template <typename ShapeFunction, typename IntegrationMethod,
+          unsigned GlobalDim>
+class UniformNeumannBoundaryConditionLocalAssembler final
+    : public GenericNaturalBoundaryConditionLocalAssembler<
+          ShapeFunction, IntegrationMethod, GlobalDim>
+{
+    using Base = GenericNaturalBoundaryConditionLocalAssembler<
+        ShapeFunction, IntegrationMethod, GlobalDim>;
+
+public:
+    /// The neumann_bc_value factor is directly integrated into the local
+    /// element matrix.
+    UniformNeumannBoundaryConditionLocalAssembler(
+        MeshLib::Element const& e,
+        std::size_t const local_matrix_size,
+        unsigned const integration_order,
+        double neumann_bc_value)
+        : Base(e, integration_order),
+          _neumann_bc_value(neumann_bc_value),
+          _local_rhs(local_matrix_size)
+    {
+    }
+
+    void assemble(std::size_t const id,
+                  NumLib::LocalToGlobalIndexMap const& dof_table_boundary,
+                  double const t, const GlobalVector& /*x*/,
+                  GlobalMatrix& /*K*/, GlobalVector& b) override
+    {
+        (void)t;  // TODO time-dependent Neumann BCs
+
+        _local_rhs.setZero();
+
+        IntegrationMethod integration_method(Base::_integration_order);
+        std::size_t const n_integration_points =
+            integration_method.getNumberOfPoints();
+
+        for (std::size_t ip(0); ip < n_integration_points; ip++) {
+            auto const& sm = Base::_shape_matrices[ip];
+            auto const& wp = integration_method.getWeightedPoint(ip);
+            _local_rhs.noalias() +=
+                sm.N * _neumann_bc_value * sm.detJ * wp.getWeight();
+        }
+
+        auto const indices = NumLib::getIndices(id, dof_table_boundary);
+        b.add(indices, _local_rhs);
+    }
+
+private:
+    double const _neumann_bc_value;
+    typename Base::NodalVectorType _local_rhs;
+};
+
+}   // namespace ProcessLib
+
+#endif  // PROCESSLIB_UNIFORMNEUMANNBOUNDARYCONDITIONLOCALASSEMBLER_H