diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index bc341bc981b4e10dae14da0d13f5051e4cd7e615..7a41194c3e3f9c7840fbfa686979a5d7d5f53e6e 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -1,6 +1,7 @@
 #include <language/modules/SchemeModule.hpp>
 
 #include <language/utils/BuiltinFunctionEmbedder.hpp>
+#include <language/utils/TypeDescriptor.hpp>
 #include <mesh/Mesh.hpp>
 #include <scheme/AcousticSolver.hpp>
 
@@ -36,8 +37,8 @@ struct MeshDimensionAdapter
     MeshDataType mesh_data(m_mesh);
     std::vector<std::shared_ptr<BoundaryConditionDescriptor>> bc_descriptor_list;
     for (const auto& sym_boundary_name : sym_boundary_name_list) {
-      std::shared_ptr<BoundaryDescriptor> boudary_descriptor =
-        std::shared_ptr<BoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
+      std::shared_ptr<IBoundaryDescriptor> boudary_descriptor =
+        std::shared_ptr<IBoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
       SymmetryBoundaryConditionDescriptor* sym_bc_descriptor =
         new SymmetryBoundaryConditionDescriptor(boudary_descriptor);
 
@@ -132,6 +133,30 @@ struct MeshDimensionAdapter
 
 SchemeModule::SchemeModule()
 {
+  this->_addTypeDescriptor(
+    std::make_shared<TypeDescriptor>(ast_node_data_type_from<std::shared_ptr<IBoundaryDescriptor>>.typeName()));
+
+  this
+    ->_addBuiltinFunction("boundaryName",
+                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<IBoundaryDescriptor>, std::string>>(
+                            std::function<std::shared_ptr<IBoundaryDescriptor>(std::string)>{
+
+                              [](const std::string& boundary_name) -> std::shared_ptr<IBoundaryDescriptor> {
+                                return std::make_shared<NamedBoundaryDescriptor>(boundary_name);
+                              }}
+
+                            ));
+
+  this->_addBuiltinFunction("boundaryTag",
+                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<IBoundaryDescriptor>, int64_t>>(
+                              std::function<std::shared_ptr<IBoundaryDescriptor>(int64_t)>{
+
+                                [](int64_t boundary_tag) -> std::shared_ptr<IBoundaryDescriptor> {
+                                  return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag);
+                                }}
+
+                              ));
+
   this->_addBuiltinFunction("glace", std::make_shared<BuiltinFunctionEmbedder<void, std::shared_ptr<IMesh>>>(
                                        std::function<void(std::shared_ptr<IMesh>)>{
 
diff --git a/src/language/modules/SchemeModule.hpp b/src/language/modules/SchemeModule.hpp
index 73d675cda9688134709e92a78aaff8fd82d8abbe..94259862493b8a232d9067ad8c26f34615b73f03 100644
--- a/src/language/modules/SchemeModule.hpp
+++ b/src/language/modules/SchemeModule.hpp
@@ -2,8 +2,14 @@
 #define SCHEME_MODULE_HPP
 
 #include <language/modules/BuiltinModule.hpp>
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
 #include <utils/PugsMacros.hpp>
 
+class IBoundaryDescriptor;
+template <>
+inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<IBoundaryDescriptor>> = {ASTNodeDataType::type_id_t,
+                                                                                        "boundary"};
+
 class SchemeModule : public BuiltinModule
 {
  public:
diff --git a/src/main.cpp b/src/main.cpp
index f6bec4d51f043af23cf6c3db655fa99d9b214fef..76f822d21f1162c369d2aca9b188246841467c85 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -65,8 +65,8 @@ main(int argc, char* argv[])
         std::vector<std::string> sym_boundary_name_list = {"XMIN", "XMAX"};
         std::vector<std::shared_ptr<BoundaryConditionDescriptor>> bc_descriptor_list;
         for (const auto& sym_boundary_name : sym_boundary_name_list) {
-          std::shared_ptr<BoundaryDescriptor> boudary_descriptor =
-            std::shared_ptr<BoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
+          std::shared_ptr<IBoundaryDescriptor> boudary_descriptor =
+            std::shared_ptr<IBoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
           SymmetryBoundaryConditionDescriptor* sym_bc_descriptor =
             new SymmetryBoundaryConditionDescriptor(boudary_descriptor);
 
@@ -184,8 +184,8 @@ main(int argc, char* argv[])
         std::vector<std::string> sym_boundary_name_list = {"XMIN", "XMAX", "YMIN", "YMAX"};
         std::vector<std::shared_ptr<BoundaryConditionDescriptor>> bc_descriptor_list;
         for (const auto& sym_boundary_name : sym_boundary_name_list) {
-          std::shared_ptr<BoundaryDescriptor> boudary_descriptor =
-            std::shared_ptr<BoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
+          std::shared_ptr<IBoundaryDescriptor> boudary_descriptor =
+            std::shared_ptr<IBoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
           SymmetryBoundaryConditionDescriptor* sym_bc_descriptor =
             new SymmetryBoundaryConditionDescriptor(boudary_descriptor);
 
@@ -290,8 +290,8 @@ main(int argc, char* argv[])
         std::vector<std::string> sym_boundary_name_list = {"XMIN", "XMAX", "YMIN", "YMAX", "ZMIN", "ZMAX"};
         std::vector<std::shared_ptr<BoundaryConditionDescriptor>> bc_descriptor_list;
         for (const auto& sym_boundary_name : sym_boundary_name_list) {
-          std::shared_ptr<BoundaryDescriptor> boudary_descriptor =
-            std::shared_ptr<BoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
+          std::shared_ptr<IBoundaryDescriptor> boudary_descriptor =
+            std::shared_ptr<IBoundaryDescriptor>(new NamedBoundaryDescriptor(sym_boundary_name));
           SymmetryBoundaryConditionDescriptor* sym_bc_descriptor =
             new SymmetryBoundaryConditionDescriptor(boudary_descriptor);
 
diff --git a/src/scheme/BoundaryConditionDescriptor.hpp b/src/scheme/BoundaryConditionDescriptor.hpp
index 8f4911ad940c56b335fabb1e002582f5d61ddd34..4fd5ae1d78fc6869ee3f7e92950091f798d0954b 100644
--- a/src/scheme/BoundaryConditionDescriptor.hpp
+++ b/src/scheme/BoundaryConditionDescriptor.hpp
@@ -5,7 +5,7 @@
 
 #include <memory>
 
-class BoundaryDescriptor
+class IBoundaryDescriptor
 {
  public:
   enum class Type
@@ -19,27 +19,27 @@ class BoundaryDescriptor
 
  public:
   friend std::ostream&
-  operator<<(std::ostream& os, const BoundaryDescriptor& bd)
+  operator<<(std::ostream& os, const IBoundaryDescriptor& bd)
   {
     return bd._write(os);
   }
 
   virtual bool operator==(const RefId& ref_id) const = 0;
   friend bool
-  operator==(const RefId& ref_id, const BoundaryDescriptor& bcd)
+  operator==(const RefId& ref_id, const IBoundaryDescriptor& bcd)
   {
     return bcd == ref_id;
   }
   virtual Type type() const = 0;
 
-  BoundaryDescriptor(const BoundaryDescriptor&) = delete;
-  BoundaryDescriptor(BoundaryDescriptor&&)      = delete;
-  BoundaryDescriptor()                          = default;
+  IBoundaryDescriptor(const IBoundaryDescriptor&) = delete;
+  IBoundaryDescriptor(IBoundaryDescriptor&&)      = delete;
+  IBoundaryDescriptor()                           = default;
 
-  virtual ~BoundaryDescriptor() = default;
+  virtual ~IBoundaryDescriptor() = default;
 };
 
-class NamedBoundaryDescriptor : public BoundaryDescriptor
+class NamedBoundaryDescriptor : public IBoundaryDescriptor
 {
  private:
   std::string m_name;
@@ -73,7 +73,7 @@ class NamedBoundaryDescriptor : public BoundaryDescriptor
   virtual ~NamedBoundaryDescriptor() = default;
 };
 
-class NumberedBoundaryDescriptor : public BoundaryDescriptor
+class NumberedBoundaryDescriptor : public IBoundaryDescriptor
 {
  private:
   unsigned int m_number;
@@ -116,7 +116,7 @@ class BoundaryConditionDescriptor
   };
 
  protected:
-  std::shared_ptr<BoundaryDescriptor> m_boundary_descriptor;
+  std::shared_ptr<IBoundaryDescriptor> m_boundary_descriptor;
 
   virtual std::ostream& _write(std::ostream& os) const = 0;
 
@@ -129,13 +129,13 @@ class BoundaryConditionDescriptor
 
   virtual Type type() const = 0;
 
-  const BoundaryDescriptor&
+  const IBoundaryDescriptor&
   boundaryDescriptor() const
   {
     return *m_boundary_descriptor;
   }
 
-  BoundaryConditionDescriptor(std::shared_ptr<BoundaryDescriptor> boundary_descriptor)
+  BoundaryConditionDescriptor(std::shared_ptr<IBoundaryDescriptor> boundary_descriptor)
     : m_boundary_descriptor(boundary_descriptor)
   {
     ;
@@ -164,7 +164,7 @@ class SymmetryBoundaryConditionDescriptor : public BoundaryConditionDescriptor
     return Type::symmetry;
   }
 
-  SymmetryBoundaryConditionDescriptor(std::shared_ptr<BoundaryDescriptor> boundary_descriptor)
+  SymmetryBoundaryConditionDescriptor(std::shared_ptr<IBoundaryDescriptor> boundary_descriptor)
     : BoundaryConditionDescriptor(boundary_descriptor)
   {
     ;