]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add a class to perform GeneralDataStorage
authorJean-Paul Pelteret <jppelteret@gmail.com>
Mon, 1 Apr 2019 19:59:29 +0000 (21:59 +0200)
committerJean-Paul Pelteret <jppelteret@gmail.com>
Thu, 4 Apr 2019 05:45:28 +0000 (07:45 +0200)
doc/news/changes/minor/20190402LucaHeltaiJean-PaulPelteret [new file with mode: 0644]
include/deal.II/algorithms/general_data_storage.h [new file with mode: 0644]
source/algorithms/CMakeLists.txt
source/algorithms/general_data_storage.cc [new file with mode: 0644]
tests/algorithms/general_data_storage_01.cc [new file with mode: 0644]
tests/algorithms/general_data_storage_01.debug.output [new file with mode: 0644]
tests/algorithms/general_data_storage_01.release.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20190402LucaHeltaiJean-PaulPelteret b/doc/news/changes/minor/20190402LucaHeltaiJean-PaulPelteret
new file mode 100644 (file)
index 0000000..9429683
--- /dev/null
@@ -0,0 +1,5 @@
+New: The GeneralDataStorage class facilitates the storage of any general data.
+It offers the ability to store any amount of data, of any type, which is then 
+made accessible by an identifier string.
+<br>
+(Luca Heltai, Jean-Paul Pelteret, 2019/04/02)
diff --git a/include/deal.II/algorithms/general_data_storage.h b/include/deal.II/algorithms/general_data_storage.h
new file mode 100644 (file)
index 0000000..ed29057
--- /dev/null
@@ -0,0 +1,473 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii_algorithms_general_data_storage_h
+#define dealii_algorithms_general_data_storage_h
+
+#include <deal.II/base/config.h>
+
+#include <deal.II/base/exceptions.h>
+#include <deal.II/base/subscriptor.h>
+
+#include <boost/any.hpp>
+#include <boost/core/demangle.hpp>
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <typeinfo>
+
+DEAL_II_NAMESPACE_OPEN
+
+
+/**
+ * This class facilitates the storage of any general data.
+ * It offers a mechanism to store any amount of data, of any type,
+ * which is then made accessible by an identifier string.
+ *
+ * When using this class, please cite
+ *
+ * @code{.bib}
+ * @article{SartoriGiulianiBardelloni-2018-a,
+ *  Author = {Sartori, Alberto and Giuliani, Nicola and
+ *            Bardelloni, Mauro and Heltai, Luca},
+ *  Journal = {SoftwareX},
+ *  Pages = {318--327},
+ *  Title = {{deal2lkit: A toolkit library for high performance
+ *            programming in deal.II}},
+ *  Volume = {7},
+ *  Year = {2018}}
+ * @endcode
+ *
+ * @author Luca Heltai, Jean-Paul Pelteret, 2019
+ */
+class GeneralDataStorage : public Subscriptor
+{
+public:
+  /**
+   * Default constructor.
+   */
+  GeneralDataStorage() = default;
+
+  /**
+   * Copy constructor.
+   */
+  GeneralDataStorage(const GeneralDataStorage &) = default;
+
+  /**
+   * Move constructor.
+   */
+  GeneralDataStorage(GeneralDataStorage &&) = default;
+
+  /**
+   * Number of objects stored by this class instance.
+   */
+  std::size_t
+  size() const;
+
+  /**
+   *  Merge the contents of @p other_data with this object.
+   */
+  void
+  merge(const GeneralDataStorage &other_data);
+
+  /**
+   * Print the contents of the internal cache to the @p stream.
+   *
+   * Each key and value pair in the @p any_data map are printed on an
+   * individual line, with the <tt>std::string<\tt> key listed first
+   * followed by the demangled <tt>type_id</tt> of the associated mapped
+   * type.
+   */
+  template <class Stream>
+  void
+  print_info(Stream &stream);
+
+  /**
+   * Clear all data stored in this class instance.
+   *
+   * After this function is called, all copied data owned by this class will
+   * go out of scope. Furthermore, all scoping requirements for data referenced
+   * by this class instance will be lifted.
+   *
+   * To clarify this point, consider the following small example:
+   *
+   * @code
+   *   GeneralDataStorage data;
+   *
+   *   {
+   *     const double some_number = ...;
+   *     data.add_unique_reference("value", some_number);
+   *
+   *     // Adding either of these next two lines could fix the
+   *     // issue, by removing the association of some_number with data:
+   *     // data.remove_object_with_name("value");
+   *     // data.reset();
+   *   } // some_number goes out of scope here
+   *
+   *   const double some_other_number
+   *     = data.get_object_with_name<double>("value"); // Invalid call
+   * @endcode
+   *
+   * In the code above, the @p data  object has a longer scope than
+   * <tt>some_number</tt>. By the time we fetch the <tt>"value"</tt> from
+   * @p data , the reference to @p some_number is no longer valid.
+   *
+   * Similarly, for data copied into a GeneralDataStorage object one should
+   * consider the scope under which it remains valid:
+   *
+   * @code
+   *   double* ptr_to_some_number = null_ptr;
+   *
+   *   {
+   *     GeneralDataStorage data;
+   *     const double some_number = ...;
+   *     data.add_unique_copy("value", some_number);
+   *
+   *     ptr_to_some_number = &(data.get_object_with_name<double>("value"));
+   *   } // The copy to some_number goes out of scope here
+   *
+   *   const double some_other_number
+   *     = *ptr_to_some_number; // Invalid call
+   * @endcode
+   *
+   * Similar to the first example, we must be concious of the fact that the
+   * copies of any @p Type stored by @p data only remains valid while the
+   * GeneralDataStorage instance in which it is stored is alive.
+   *
+   * Furthermore, as elucidated in the last example, the copy of the
+   * class instance (owned by GeneralDataStorage) that is being pointed to
+   * is no longer alive when the reset() function is called, or when it is
+   * removed via a call to remove_object_with_name().
+   *
+   * @code
+   *   GeneralDataStorage data;
+   *   double* ptr_to_some_number = null_ptr;
+   *
+   *   {
+   *     const double some_number = ...;
+   *     data.add_unique_copy("value", some_number);
+   *
+   *     ptr_to_some_number = &(data.get_object_with_name<double>("value"));
+   *
+   *     // The copy to some_number would go out of scope when either of
+   *     // following two calls are made:
+   *     data.remove_object_with_name("value");
+   *     data.reset();
+   *   }
+   *
+   *   const double some_other_number
+   *     = *ptr_to_some_number; // Invalid call
+   * @endcode
+   */
+  void
+  reset();
+
+  /**
+   * @name Data storage and access
+   */
+  //@{
+
+  /**
+   * Store internally a copy of the given object. The copied object is
+   * owned by this class, and is accessible via reference through the
+   * get_object_with_name() method.
+   *
+   * This function ensures that no @p entry with the given @name is
+   * already stored by this class instance.
+   */
+  template <typename Type>
+  void
+  add_unique_copy(const std::string &name, const Type &entry);
+
+  /**
+   * Store internally a copy of the given object. The copied object is
+   * owned by this class, and is accessible via reference through the
+   * get_object_with_name() method.
+   *
+   * This function does not perform any checks to ensure that the @p entry
+   * with the given @name is already stored by this class instance. If the
+   * @p name does in fact point to existing data, then this is overwritten.
+   */
+  template <typename Type>
+  void
+  add_or_overwrite_copy(const std::string &name, const Type &entry);
+
+  /**
+   * Add a reference to an already existing object. The object is not
+   * owned by this class, and the user has to guarantee that the
+   * referenced object lives longer than this class instance. The stored
+   * reference is accessible through the get_object_with_name() method.
+   *
+   * This function ensures that no @p entry with the given @name is
+   * already stored by this class instance.
+   */
+  template <typename Type>
+  void
+  add_unique_reference(const std::string &name, Type &entry);
+
+  /**
+   * Add a reference to an already existing object. The object is not
+   * owned by this class, and the user has to guarantee that the
+   * referenced object lives longer than this class instance. The stored
+   * reference is accessible through the get_object_with_name() method.
+   *
+   * This function does not perform any checks to ensure that the @p entry
+   * with the given @name is already stored by this class instance. If the
+   * @p name does in fact point to existing data, then this is overwritten.
+   */
+  template <typename Type>
+  void
+  add_or_overwrite_reference(const std::string &name, Type &entry);
+
+  /**
+   * Return a reference to the object with given name. If the object does
+   * not exist, then the input @p arguments will be used to construct an object
+   * of the given @p Type and a reference to this new object then be returned.
+   *
+   * A copy of an object of type @p Type , which is owned by this class
+   * instance, is generated by calling its constructor with the given set of
+   * arguments. For this function, the @p arguments are passed as
+   * <tt>lvalue</tt> references.
+   */
+  template <typename Type, typename... Args>
+  Type &
+  get_or_add_object_with_name(const std::string &name, Args &... arguments);
+
+  /**
+   * Return a reference to the object with given name. If the object does
+   * not exist, then the input @p arguments will be used to construct an object
+   * of the given @p Type and a reference to this new object then be returned.
+   *
+   * A copy of an object of type @p Type , which is owned by this class
+   * instance, is generated by calling its constructor with the given set of
+   * arguments. In contrast to the previous function of the same name, for
+   * this function the @p arguments are passed as <tt>rvalue</tt> references.
+   */
+  template <typename Type, typename... Args>
+  Type &
+  get_or_add_object_with_name(const std::string &name, Args &&... arguments);
+
+  /**
+   * Return a reference to the object with given name.
+   *
+   * This function throws an exception if either an object with the given name
+   * is not stored in this class, or if the object with the given name is
+   * neither of the exact specified @p Type nor a pointer to the @p Type.
+   */
+  template <typename Type>
+  Type &
+  get_object_with_name(const std::string &name);
+
+  /**
+   * Return a constant reference to the object with the given name.
+   *
+   * This function throws an exception if either an object with the given name
+   * is not stored in this class, or if the object with the given name is
+   * neither of the exact specified @p Type nor a pointer to the @p Type.
+   */
+  template <typename Type>
+  const Type &
+  get_object_with_name(const std::string &name) const;
+
+  /**
+   * Find out if we store an object with given name.
+   */
+  bool
+  stores_object_with_name(const std::string &name) const;
+
+  /**
+   * Find out if we store an object with given name.
+   */
+  void
+  remove_object_with_name(const std::string &name);
+
+  //@}
+
+  /**
+   * An entry with this name does not exist in the internal boost::any map.
+   */
+  DeclException1(ExcNameNotFound,
+                 std::string,
+                 << "No entry with the name " << arg1 << " exists.");
+
+  /**
+   * An entry with this name does not exist in the internal boost::any map.
+   */
+  DeclException1(ExcNameHasBeenFound,
+                 std::string,
+                 << "An entry with the name " << arg1 << " already exists.");
+
+  /**
+   * The requested type and the stored type are different.
+   */
+  DeclException3(ExcTypeMismatch,
+                 std::string,
+                 const char *,
+                 const char *,
+                 << "The stored type for entry with name \"" << arg1 << "\" is "
+                 << arg2 << " but you requested type " << arg3 << ".");
+
+private:
+  /**
+   * Arbitrary user data, identified by a string.
+   */
+  std::map<std::string, boost::any> any_data;
+};
+
+
+/*----------------- Inline and template methods -----------------*/
+
+
+#ifndef DOXYGEN
+
+
+template <class Stream>
+void
+GeneralDataStorage::print_info(Stream &os)
+{
+  for (auto it : any_data)
+    {
+      os << it.first << '\t' << '\t'
+         << boost::core::demangle(it.second.type().name()) << std::endl;
+    }
+}
+
+
+template <typename Type>
+void
+GeneralDataStorage::add_unique_copy(const std::string &name, const Type &entry)
+{
+  Assert(!stores_object_with_name(name), ExcNameHasBeenFound(name));
+  add_or_overwrite_copy(name, entry);
+}
+
+
+template <typename Type>
+void
+GeneralDataStorage::add_or_overwrite_copy(const std::string &name,
+                                          const Type &       entry)
+{
+  any_data[name] = entry;
+}
+
+
+template <typename Type>
+void
+GeneralDataStorage::add_unique_reference(const std::string &name, Type &entry)
+{
+  Assert(!stores_object_with_name(name), ExcNameHasBeenFound(name));
+  add_or_overwrite_reference(name, entry);
+}
+
+
+template <typename Type>
+void
+GeneralDataStorage::add_or_overwrite_reference(const std::string &name,
+                                               Type &             entry)
+{
+  Type *ptr      = &entry;
+  any_data[name] = ptr;
+}
+
+
+template <typename Type>
+Type &
+GeneralDataStorage::get_object_with_name(const std::string &name)
+{
+  Assert(stores_object_with_name(name), ExcNameNotFound(name));
+
+  Type *p = nullptr;
+
+  if (any_data[name].type() == typeid(Type *))
+    {
+      p = boost::any_cast<Type *>(any_data[name]);
+    }
+  else if (any_data[name].type() == typeid(Type))
+    {
+      p = boost::any_cast<Type>(&any_data[name]);
+    }
+  else
+    {
+      Assert(false,
+             ExcTypeMismatch(name,
+                             any_data[name].type().name(),
+                             typeid(Type).name()));
+    }
+
+  return *p;
+}
+
+
+template <typename Type>
+const Type &
+GeneralDataStorage::get_object_with_name(const std::string &name) const
+{
+  AssertThrow(stores_object_with_name(name), ExcNameNotFound(name));
+
+  const auto it = any_data.find(name);
+
+  if (it->second.type() == typeid(Type *))
+    {
+      const Type *p = boost::any_cast<Type *>(it->second);
+      return *p;
+    }
+  else if (it->second.type() == typeid(Type))
+    {
+      const Type *p = boost::any_cast<Type>(&it->second);
+      return *p;
+    }
+  else
+    {
+      Assert(false,
+             ExcTypeMismatch(name,
+                             it->second.type().name(),
+                             typeid(Type).name()));
+      const Type *p = nullptr;
+      return *p;
+    }
+}
+
+
+template <typename Type, typename... Args>
+Type &
+GeneralDataStorage::get_or_add_object_with_name(const std::string &name,
+                                                Args &... arguments)
+{
+  if (!stores_object_with_name(name))
+    add_unique_copy(name, Type(arguments...));
+
+  return get_object_with_name<Type>(name);
+}
+
+
+template <typename Type, typename... Args>
+Type &
+GeneralDataStorage::get_or_add_object_with_name(const std::string &name,
+                                                Args &&... arguments)
+{
+  if (!stores_object_with_name(name))
+    add_unique_copy(name, Type(std::forward<Args>(arguments)...));
+
+  return get_object_with_name<Type>(name);
+}
+
+
+#endif // DOXYGEN
+
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif // dealii_algorithms_general_data_storage_h
index 2eb6e268dbcc1a7337d97de4a9ce492b7fd9f7ea..030b6f36cd3afe70333c157ccab43e391eb623a0 100644 (file)
@@ -16,6 +16,7 @@
 INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
 
 SET(_src
+  general_data_storage.cc
   operator.cc
   timestep_control.cc
   )
diff --git a/source/algorithms/general_data_storage.cc b/source/algorithms/general_data_storage.cc
new file mode 100644 (file)
index 0000000..85ff371
--- /dev/null
@@ -0,0 +1,61 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+#include <deal.II/algorithms/general_data_storage.h>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+
+std::size_t
+GeneralDataStorage::size() const
+{
+  return any_data.size();
+}
+
+
+void
+GeneralDataStorage::merge(const GeneralDataStorage &other)
+{
+  any_data.insert(other.any_data.begin(), other.any_data.end());
+}
+
+
+void
+GeneralDataStorage::reset()
+{
+  any_data.clear();
+}
+
+
+bool
+GeneralDataStorage::stores_object_with_name(const std::string &name) const
+{
+  return any_data.find(name) != any_data.end();
+}
+
+
+void
+GeneralDataStorage::remove_object_with_name(const std::string &name)
+{
+  const auto it = any_data.find(name);
+  if (it != any_data.end())
+    any_data.erase(it);
+}
+
+
+
+DEAL_II_NAMESPACE_CLOSE
diff --git a/tests/algorithms/general_data_storage_01.cc b/tests/algorithms/general_data_storage_01.cc
new file mode 100644 (file)
index 0000000..fc421e7
--- /dev/null
@@ -0,0 +1,228 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+// Test the core functionality of the GeneralDataStorage class
+
+
+#include <deal.II/algorithms/general_data_storage.h>
+
+#include <utility>
+
+#include "../tests.h"
+
+int
+main()
+{
+  initlog();
+
+  GeneralDataStorage data;
+
+  deallog << "Add by copy" << std::endl;
+  {
+    data.reset();
+
+    // Create new data instance
+    const double val_1 = 1.0;
+    data.add_unique_copy("value", val_1);
+    const double &val_2 = data.get_object_with_name<double>("value");
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_2 == val_1, ExcInternalError());
+    Assert(&val_2 != &val_1, ExcInternalError());
+
+    // Allowed overwrite of existing data
+    const double val_3 = 2.0;
+    data.add_or_overwrite_copy("value", val_3);
+    const double &val_4 = data.get_object_with_name<double>("value");
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_4 == val_3, ExcInternalError());
+    Assert(&val_4 != &val_3, ExcInternalError());
+
+    // Create new data instance using alternative function
+    const double val_5 = 3.0;
+    data.add_or_overwrite_copy("value_2", val_5);
+    const double &val_6 = data.get_object_with_name<double>("value_2");
+    Assert(data.stores_object_with_name("value_2"), ExcInternalError());
+    Assert(val_6 == val_5, ExcInternalError());
+    Assert(&val_6 != &val_5, ExcInternalError());
+
+    deallog << "Size: " << data.size() << std::endl;
+  }
+
+  deallog << "Add by reference" << std::endl;
+  {
+    data.reset();
+
+    // Create new data instance
+    const double val_1 = 1.0;
+    data.add_unique_reference("value", val_1);
+    const double &val_2 = data.get_object_with_name<const double>("value");
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_2 == val_1, ExcInternalError());
+    Assert(&val_2 == &val_1, ExcInternalError());
+
+    // Allowed overwrite of existing data
+    const double val_3 = 2.0;
+    data.add_or_overwrite_reference("value", val_3);
+    const double &val_4 = data.get_object_with_name<const double>("value");
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_4 == val_3, ExcInternalError());
+    Assert(&val_4 == &val_3, ExcInternalError());
+
+    // Create new data instance using alternative function
+    const double val_5 = 3.0;
+    data.add_or_overwrite_reference("value_2", val_5);
+    const double &val_6 = data.get_object_with_name<const double>("value_2");
+    Assert(data.stores_object_with_name("value_2"), ExcInternalError());
+    Assert(val_6 == val_5, ExcInternalError());
+    Assert(&val_6 == &val_5, ExcInternalError());
+
+    deallog << "Size: " << data.size() << std::endl;
+  }
+
+  deallog << "Add or construct" << std::endl;
+  {
+    data.reset();
+
+    using Type = std::pair<double, double>;
+
+    // Create new data instance
+    const Type &val_1 =
+      data.get_or_add_object_with_name<Type>("value", 1.0, 2.0);
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_1 == Type({1.0, 2.0}), ExcInternalError());
+
+    // Should not overwrite existing data
+    const Type &val_2 =
+      data.get_or_add_object_with_name<Type>("value", Type(3.0, 4.0));
+    Assert(data.stores_object_with_name("value"), ExcInternalError());
+    Assert(val_2 == Type({1.0, 2.0}), ExcInternalError());
+
+    deallog << "Size: " << data.size() << std::endl;
+  }
+
+  deallog << "Merge" << std::endl;
+  {
+    data.reset();
+
+    const double val_1 = 1.0;
+    data.add_unique_copy("value", val_1);
+
+    GeneralDataStorage data_2;
+    data_2.add_unique_copy("value", 2.0); // Duplicate
+    data_2.add_unique_copy("value_2", 3.0);
+
+    deallog << "Data pre-merge:" << std::endl;
+    data.print_info(deallog);
+    deallog << "Size: " << data.size() << std::endl;
+    deallog << "Data 2 pre-merge:" << std::endl;
+    data_2.print_info(deallog);
+    deallog << "Size: " << data_2.size() << std::endl;
+
+    data.merge(data_2);
+
+    deallog << "Data post-merge:" << std::endl;
+    data.print_info(deallog);
+    deallog << "Size: " << data.size() << std::endl;
+  }
+
+
+  deal_II_exceptions::disable_abort_on_exception();
+
+  deallog << "Try to overwrite existing entry: Copy" << std::endl;
+  {
+    data.reset();
+
+    const double val_1 = 1.0;
+    data.add_unique_copy("value", val_1);
+
+    try
+      {
+        const double val_2 = 1.0;
+        data.add_unique_copy("value", val_2);
+      }
+    catch (const GeneralDataStorage::ExcNameHasBeenFound &exc)
+      {
+        deallog << exc.what() << std::endl;
+      }
+  }
+
+  deallog << "Try to overwrite existing entry: Reference" << std::endl;
+  {
+    data.reset();
+
+    const double val_1 = 1.0;
+    data.add_unique_reference("value", val_1);
+
+    try
+      {
+        const double val_2 = 2.0;
+        data.add_unique_reference("value", val_2);
+      }
+    catch (const GeneralDataStorage::ExcNameHasBeenFound &exc)
+      {
+        deallog << exc.what() << std::endl;
+      }
+  }
+
+  deallog << "Fetch non-existing entry" << std::endl;
+  {
+    data.reset();
+
+    try
+      {
+        data.get_object_with_name<double>("value");
+      }
+    catch (const GeneralDataStorage::ExcNameNotFound &exc)
+      {
+        deallog << exc.what() << std::endl;
+      }
+  }
+
+  deallog << "Access removed entry (reference)" << std::endl;
+  {
+    data.reset();
+
+    const double val_1 = 1.0;
+    data.add_unique_reference("value", val_1);
+    data.remove_object_with_name("value");
+
+    try
+      {
+        data.get_object_with_name<double>("value");
+      }
+    catch (const GeneralDataStorage::ExcNameNotFound &exc)
+      {
+        deallog << exc.what() << std::endl;
+      }
+  }
+
+  deallog << "Access removed entry (copy)" << std::endl;
+  {
+    data.reset();
+
+    data.add_unique_copy("value", 1.0);
+    data.remove_object_with_name("value");
+
+    try
+      {
+        data.get_object_with_name<double>("value");
+      }
+    catch (const GeneralDataStorage::ExcNameNotFound &exc)
+      {
+        deallog << exc.what() << std::endl;
+      }
+  }
+}
diff --git a/tests/algorithms/general_data_storage_01.debug.output b/tests/algorithms/general_data_storage_01.debug.output
new file mode 100644 (file)
index 0000000..4583c5e
--- /dev/null
@@ -0,0 +1,74 @@
+
+DEAL::Add by copy
+DEAL::Size: 2
+DEAL::Add by reference
+DEAL::Size: 2
+DEAL::Add or construct
+DEAL::Size: 1
+DEAL::Merge
+DEAL::Data pre-merge:
+DEAL::value            double
+DEAL::Size: 1
+DEAL::Data 2 pre-merge:
+DEAL::value            double
+DEAL::value_2          double
+DEAL::Size: 2
+DEAL::Data post-merge:
+DEAL::value            double
+DEAL::value_2          double
+DEAL::Size: 2
+DEAL::Try to overwrite existing entry: Copy
+DEAL::
+--------------------------------------------------------
+An error occurred in file <general_data_storage.h> in function
+    void dealii::GeneralDataStorage::add_unique_copy(const std::string &, const Type &) [Type = double]
+The violated condition was: 
+    !stores_object_with_name(name)
+Additional information: 
+    An entry with the name value already exists.
+--------------------------------------------------------
+
+DEAL::Try to overwrite existing entry: Reference
+DEAL::
+--------------------------------------------------------
+An error occurred in file <general_data_storage.h> in function
+    void dealii::GeneralDataStorage::add_unique_reference(const std::string &, Type &) [Type = const double]
+The violated condition was: 
+    !stores_object_with_name(name)
+Additional information: 
+    An entry with the name value already exists.
+--------------------------------------------------------
+
+DEAL::Fetch non-existing entry
+DEAL::
+--------------------------------------------------------
+An error occurred in file <general_data_storage.h> in function
+    Type &dealii::GeneralDataStorage::get_object_with_name(const std::string &) [Type = double]
+The violated condition was: 
+    stores_object_with_name(name)
+Additional information: 
+    No entry with the name value exists.
+--------------------------------------------------------
+
+DEAL::Access removed entry (reference)
+DEAL::
+--------------------------------------------------------
+An error occurred in file <general_data_storage.h> in function
+    Type &dealii::GeneralDataStorage::get_object_with_name(const std::string &) [Type = double]
+The violated condition was: 
+    stores_object_with_name(name)
+Additional information: 
+    No entry with the name value exists.
+--------------------------------------------------------
+
+DEAL::Access removed entry (copy)
+DEAL::
+--------------------------------------------------------
+An error occurred in file <general_data_storage.h> in function
+    Type &dealii::GeneralDataStorage::get_object_with_name(const std::string &) [Type = double]
+The violated condition was: 
+    stores_object_with_name(name)
+Additional information: 
+    No entry with the name value exists.
+--------------------------------------------------------
+
diff --git a/tests/algorithms/general_data_storage_01.release.output b/tests/algorithms/general_data_storage_01.release.output
new file mode 100644 (file)
index 0000000..b10d091
--- /dev/null
@@ -0,0 +1,24 @@
+
+DEAL::Add by copy
+DEAL::Size: 2
+DEAL::Add by reference
+DEAL::Size: 2
+DEAL::Add or construct
+DEAL::Size: 1
+DEAL::Merge
+DEAL::Data pre-merge:
+DEAL::value            double
+DEAL::Size: 1
+DEAL::Data 2 pre-merge:
+DEAL::value            double
+DEAL::value_2          double
+DEAL::Size: 2
+DEAL::Data post-merge:
+DEAL::value            double
+DEAL::value_2          double
+DEAL::Size: 2
+DEAL::Try to overwrite existing entry: Copy
+DEAL::Try to overwrite existing entry: Reference
+DEAL::Fetch non-existing entry
+DEAL::Access removed entry (reference)
+DEAL::Access removed entry (copy)

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.