v0.10.0
UnknownInterface.hpp
Go to the documentation of this file.
1 /** \file UnknownInterface.hpp
2  * \brief MoFEM interface
3  *
4  * Low level data structures not used directly by user
5  */
6 
7 /*
8  * MoFEM is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11  * License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with MoFEM. If not, see <http://www.gnu.org/licenses/>
15  */
16 
17 #ifndef __MOFEMUNKNOWNINTERFACE_HPP__
18 #define __MOFEMUNKNOWNINTERFACE_HPP__
19 
20 namespace MoFEM {
21 
22 /**
23  * \brief MoFEM interface unique ID
24  * \ingroup mofem
25  */
26 struct MOFEMuuid {
27 
28  MOFEMuuid() { memset(this, 0, sizeof(MOFEMuuid)); }
29  MOFEMuuid(const BitIntefaceId &uuid) { uUId = uuid; }
30 
31  /** \brief returns whether two uuid's are equal
32  **/
33  inline bool operator==(const MOFEMuuid &orig) const {
34  return (uUId & orig.uUId) == orig.uUId;
35  }
36 
37  // uuid
39 };
40 
41 /** uuid for an unknown interface
42  * this can be used to either return a default interface
43  * or a NULL interface
44  **/
47 
48 struct Version {
53  : majorVersion(MoFEM_VERSION_MAJOR), minorVersion(MoFEM_VERSION_MINOR),
54  buildVersion(MoFEM_VERSION_BUILD) {}
55  Version(const int v[3])
56  : majorVersion(v[0]), minorVersion(v[1]), buildVersion(v[2]) {}
57  Version(const int minor, const int major, const int build)
58  : majorVersion(minor), minorVersion(major), buildVersion(build) {}
59 
60  /**
61  * @deprecated Prints version
62  */
63  DEPRECATED MoFEMErrorCode printVersion(std::string prefix = "",
64  MPI_Comm comm = PETSC_COMM_WORLD) {
66  if (!prefix.empty()) {
67  prefix += " ";
68  }
69  CHKERR PetscPrintf(comm, "%s%d.%d.%d\n", prefix.c_str(), majorVersion,
72  }
73 
74  std::string strVersion() {
75  auto str = [](auto v) { return boost::lexical_cast<std::string>(v); };
76  return str(majorVersion) + "." + str(minorVersion) + "." +
77  str(buildVersion);
78  }
79 };
80 
81 /** \brief base class for all interface classes
82  * \ingroup mofem
83  **/
85 
86  virtual MoFEMErrorCode query_interface(const MOFEMuuid &uuid,
87  UnknownInterface **iface) const = 0;
88 
89  /**
90  * @brief Register interface
91  *
92  * Example:
93  * \code
94  * ierr = regSubInterface<Simple>(IDD_MOFEMSimple);
95  * CHKERRABORT(PETSC_COMM_SELF, ierr);
96  * \endcode
97  *
98  * @param uuid
99  * @param true
100  * @return MoFEMErrorCode
101  */
102  template <class IFACE>
104  bool error_if_registration_failed = true) {
106  auto p = iFaceTypeMap.insert(
107  UIdTypeMap(uuid, boost::typeindex::type_id<IFACE>()));
108  if (error_if_registration_failed && (!p.second)) {
109  SETERRQ1(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
110  "Registration of interface typeid(IFACE).name() = %s failed",
111  typeid(IFACE).name());
112  }
114  }
115 
116  /**
117  * @brief Get interface by uuid and return reference to pointer of interface
118  *
119  * \note uuid of interface and interface are verified, if second template
120  * parameter is true. Function throw error if both do not match.
121  *
122  * \note Do not use this function directly, it is called by other overload
123  * getInterface methods.
124  *
125  * @param uuid
126  * @param iface reference to a interface pointer
127  * @return MoFEMErrorCode
128  */
129  template <class IFACE, bool VERIFY = false>
131  IFACE *&iface) const {
133  iface = NULL;
134  if (VERIFY) {
135  if (boost::typeindex::type_id<IFACE>() != getClassIdx(uuid)) {
136  SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
137  "Inconsistency between interface Id and type");
138  }
139  }
140  UnknownInterface *ptr;
141  ierr = getInterface<UnknownInterface, false>(uuid, ptr);
142  CHKERRG(ierr);
143  iface = static_cast<IFACE *>(ptr);
145  }
146 
147  /**
148  * @brief Get interface refernce to pointer of interface
149  *
150  * \code
151  * // Create moab database
152  * moab::Core mb_instance;
153  * // Access moab database by interface
154  * moab::Interface &moab = mb_instance;
155  *
156  * // Create MoFEM database
157  * MoFEM::Core core(moab);
158  * // Acces MoFEM database by Interface
159  * MoFEM::Interface &m_field = core;
160  *
161  * // Get interface
162  * // Get simple interface is simplified version enabling quick and
163  * // easy construction of problem.
164  * Simple *simple_interface;
165  * // Query interface and get pointer to Simple interface
166  * CHKERR m_field.getInterface(simple_interface);
167  *
168  * \endcode
169  *
170  * @param iface reference to a interface pointer
171  * @return MoFEMErrorCode
172  */
173  template <class IFACE>
174  inline MoFEMErrorCode getInterface(IFACE *&iface) const {
175  return getInterface<IFACE, false>(
176  getUId(boost::typeindex::type_id<IFACE>()), iface);
177  }
178 
179  /**
180  * @brief Get interface pointer to pointer of interface
181  *
182  * \code
183  * // Create moab database
184  * moab::Core mb_instance;
185  * // Access moab database by interface
186  * moab::Interface &moab = mb_instance;
187  *
188  * // Create MoFEM database
189  * MoFEM::Core core(moab);
190  * // Acces MoFEM database by Interface
191  * MoFEM::Interface &m_field = core;
192  *
193  * // Get interface
194  * // Get simple interface is simplified version enabling quick and
195  * // easy construction of problem.
196  * Simple *simple_interface;
197  * // Query interface and get pointer to Simple interface
198  * CHKERR m_field.getInterface(&simple_interface);
199  *
200  * \endcode
201  *
202  *
203  * @param iface const pointer to a interface pointer
204  * @return MoFEMErrorCode
205  */
206  template <class IFACE>
207  inline MoFEMErrorCode getInterface(IFACE **const iface) const {
208  return getInterface<IFACE, false>(boost::typeindex::type_id<IFACE>(),
209  *iface);
210  }
211 
212  /**
213  * @brief Get interface pointer to pointer of interface
214  *
215  * \code
216  * // Create moab database
217  * moab::Core mb_instance;
218  * // Access moab database by interface
219  * moab::Interface &moab = mb_instance;
220  *
221  * // Create MoFEM database
222  * MoFEM::Core core(moab);
223  * // Acces MoFEM database by Interface
224  * MoFEM::Interface &m_field = core;
225  *
226  * // Get interface
227  * // Get simple interface is simplified version enabling quick and
228  * // easy construction of problem.
229  * Simple *simple_interface = m_field.getInterface<Simple*,0>();
230  *
231  * \endcode
232  *
233  * @return IFACE*
234  */
235  template <class IFACE,
236  typename boost::enable_if<boost::is_pointer<IFACE>, int>::type = 0>
237  inline IFACE getInterface() const {
238  typedef typename boost::remove_pointer<IFACE>::type IFaceType;
239  IFaceType *iface = NULL;
240  ierr = getInterface<IFaceType, false>(
241  getUId(boost::typeindex::type_id<IFaceType>()), iface);
242  CHKERRABORT(PETSC_COMM_SELF, ierr);
243  return iface;
244  }
245 
246  /**
247  * @brief Get reference to interface
248  *
249  * \code
250  * // Create moab database
251  * moab::Core mb_instance;
252  * // Access moab database by interface
253  * moab::Interface &moab = mb_instance;
254  *
255  * // Create MoFEM database
256  * MoFEM::Core core(moab);
257  * // Acces MoFEM database by Interface
258  * MoFEM::Interface &m_field = core;
259  *
260  * // Get interface
261  * // Get simple interface is simplified version enabling quick and
262  * // easy construction of problem.
263  * Simple &simple_interface = m_field.getInterface<Simple&,0>();
264  *
265  * \endcode
266  *
267  * @return IFACE&
268  */
269  template <class IFACE, typename boost::enable_if<boost::is_reference<IFACE>,
270  int>::type = 0>
271  inline IFACE getInterface() const {
272  typedef typename boost::remove_reference<IFACE>::type IFaceType;
273  IFaceType *iface = NULL;
274  ierr = getInterface<IFaceType, false>(
275  getUId(boost::typeindex::type_id<IFaceType>()), iface);
276  CHKERRABORT(PETSC_COMM_SELF, ierr);
277  return *iface;
278  }
279 
280  /**
281  * @brief Function returning pointer to interface
282  *
283  * \code
284  * // Create moab database
285  * moab::Core mb_instance;
286  * // Access moab database by interface
287  * moab::Interface &moab = mb_instance;
288  *
289  * // Create MoFEM database
290  * MoFEM::Core core(moab);
291  * // Acces MoFEM database by Interface
292  * MoFEM::Interface &m_field = core;
293  *
294  * // Get interface
295  * // Get simple interface is simplified version enabling quick and
296  * // easy construction of problem.
297  * Simple *simple_interface = m_field.getInterface<Simple,0>();
298  *
299  * \endcode
300  *
301  * @return IFACE*
302  */
303  template <class IFACE> inline IFACE *getInterface() const {
304  return getInterface<IFACE *, 0>();
305  }
306 
307  virtual ~UnknownInterface() = default;
308 
309  /**
310  * \brief Get library version
311  *
312  * This is library version.
313  *
314  * @return error code
315  */
316  virtual MoFEMErrorCode getLibVersion(Version &version) const {
318  version =
319  Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD);
321  }
322 
323  /**
324  * \brief Get database major version
325  *
326  * This is database version. MoFEM can read DataBase from file created by
327  * older version. Then library version and database version could be
328  * different.
329  *
330  * @return error code
331  */
333  Version &version) const {
335  const EntityHandle root_meshset = 0;
336  const int def_version[] = {-1, -1, -1};
337  Tag th;
338  rval = moab.tag_get_handle("MOFEM_VERSION", 3, MB_TYPE_INTEGER, th,
339  MB_TAG_CREAT | MB_TAG_MESH, &def_version);
340  int *version_ptr;
341  if (rval == MB_ALREADY_ALLOCATED) {
342  const void *tag_data[1];
343  CHKERR moab.tag_get_by_ptr(th, &root_meshset, 1, tag_data);
344  version_ptr = (int *)tag_data[0];
345  } else {
346  const void *tag_data[1];
347  CHKERR moab.tag_get_by_ptr(th, &root_meshset, 1, tag_data);
348  version_ptr = (int *)tag_data[0];
349  version_ptr[0] = MoFEM_VERSION_MAJOR;
350  version_ptr[1] = MoFEM_VERSION_MINOR;
351  version_ptr[2] = MoFEM_VERSION_BUILD;
352  }
353  version = Version(version_ptr);
355  }
356 
357  /**
358  * \brief Get database major version
359  *
360  * Implementation of particular interface could be different than main lib.
361  * For example user could use older interface, to keep back compatibility.
362  *
363  * @return error code
364  */
365  virtual MoFEMErrorCode getInterfaceVersion(Version &version) const {
367  version =
368  Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD);
370  }
371 
372 protected:
373  struct NotKnownClass {};
374 
375  /**
376  * \brief Get type name for interface Id
377  * @param uid interface Id
378  * @return class name
379  */
380  inline boost::typeindex::type_index getClassIdx(const MOFEMuuid &uid) const {
381  iFaceTypeMap_multiIndex::nth_index<0>::type::iterator it;
382  it = iFaceTypeMap.get<0>().find(uid);
383  if (it != iFaceTypeMap.get<0>().end()) {
384  return it->classIdx;
385  }
386  return boost::typeindex::type_id<NotKnownClass>();
387  }
388 
389  /**
390  * \brief Get interface Id for class name
391  * @param class_name
392  * @return Id
393  */
394  inline MOFEMuuid getUId(const boost::typeindex::type_index &class_idx) const {
395  iFaceTypeMap_multiIndex::nth_index<1>::type::iterator it;
396  it = iFaceTypeMap.get<1>().find(class_idx);
397  if (it != iFaceTypeMap.get<1>().end()) {
398  return it->uID;
399  }
400  return IDD_MOFEMUnknown;
401  }
402 
403 private:
404  struct UIdTypeMap {
406  boost::typeindex::type_index classIdx;
407  UIdTypeMap(const MOFEMuuid &uid, const boost::typeindex::type_index &idx)
408  : uID(uid), classIdx(idx) {}
409  };
410 
411  struct HashMOFEMuuid {
412  inline unsigned int operator()(const MOFEMuuid &value) const {
413  return value.uUId.to_ulong();
414  }
415  };
416 
417  /// Data structure for interfaces Id and class names
418  typedef multi_index_container<
419  UIdTypeMap,
420  indexed_by<
421 
422  hashed_unique<member<UIdTypeMap, MOFEMuuid, &UIdTypeMap::uID>,
423  HashMOFEMuuid>,
424 
425  hashed_unique<member<UIdTypeMap, boost::typeindex::type_index,
427 
428  >>
430 
432  iFaceTypeMap; ///< Maps MOFEMuuid to interface type name
433 };
434 
435 template <>
436 inline MoFEMErrorCode UnknownInterface::getInterface<UnknownInterface, false>(
437  const MOFEMuuid &uuid, UnknownInterface *&iface) const {
438  return query_interface(uuid, &iface);
439 }
440 } // namespace MoFEM
441 
442 #endif // __MOFEMUNKNOWNINTERFACE_HPP__
MoFEMErrorCode registerInterface(const MOFEMuuid &uuid, bool error_if_registration_failed=true)
Register interface.
virtual ~UnknownInterface()=default
MoFEM interface unique ID.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface refernce to pointer of interface.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:509
Version(const int v[3])
static Index< 'p', 3 > p
bool operator==(const MOFEMuuid &orig) const
returns whether two uuid's are equal
base class for all interface classes
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:485
static const MOFEMuuid IDD_MOFEMUnknown
IFACE getInterface() const
Get interface pointer to pointer of interface.
MoFEMErrorCode getInterface(IFACE **const iface) const
Get interface pointer to pointer of interface.
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:552
boost::typeindex::type_index classIdx
BitIntefaceId uUId
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:516
virtual MoFEMErrorCode getInterfaceVersion(Version &version) const
Get database major version.
std::bitset< BITINTERFACEUID_SIZE > BitIntefaceId
Definition: Types.hpp:56
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
DEPRECATED MoFEMErrorCode printVersion(std::string prefix="", MPI_Comm comm=PETSC_COMM_WORLD)
virtual const MoFEMErrorCode getFileVersion(moab::Interface &moab, Version &version) const
Get database major version.
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
Definition: Exceptions.hpp:85
MOFEMuuid(const BitIntefaceId &uuid)
IFACE * getInterface() const
Function returning pointer to interface.
MoFEMErrorCode getInterface(const MOFEMuuid &uuid, IFACE *&iface) const
Get interface by uuid and return reference to pointer of interface.
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
Definition: Exceptions.hpp:87
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:67
unsigned int operator()(const MOFEMuuid &value) const
boost::typeindex::type_index getClassIdx(const MOFEMuuid &uid) const
Get type name for interface Id.
#define CHKERR
Inline error check.
Definition: definitions.h:604
iFaceTypeMap_multiIndex iFaceTypeMap
Maps MOFEMuuid to interface type name.
#define DEPRECATED
Definition: definitions.h:29
virtual MoFEMErrorCode getLibVersion(Version &version) const
Get library version.
DeprecatedCoreInterface Interface
Definition: Interface.hpp:1943
virtual MoFEMErrorCode query_interface(const MOFEMuuid &uuid, UnknownInterface **iface) const =0
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:415
multi_index_container< UIdTypeMap, indexed_by< hashed_unique< member< UIdTypeMap, MOFEMuuid, &UIdTypeMap::uID >, HashMOFEMuuid >, hashed_unique< member< UIdTypeMap, boost::typeindex::type_index, &UIdTypeMap::classIdx > > > > iFaceTypeMap_multiIndex
Data structure for interfaces Id and class names.
Version(const int minor, const int major, const int build)
UIdTypeMap(const MOFEMuuid &uid, const boost::typeindex::type_index &idx)
std::string strVersion()
MOFEMuuid getUId(const boost::typeindex::type_index &class_idx) const
Get interface Id for class name.