v0.9.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  MoFEMErrorCode printVersion(std::string prefix = "",
61  MPI_Comm comm = PETSC_COMM_WORLD) {
63  if(!prefix.empty()) {
64  prefix += " ";
65  }
66  CHKERR PetscPrintf(comm, "%s%d.%d.%d\n", prefix.c_str(), majorVersion,
69  }
70 };
71 
72 /** \brief base class for all interface classes
73 * \ingroup mofem
74 **/
76 
77  virtual MoFEMErrorCode query_interface(const MOFEMuuid &uuid,
78  UnknownInterface **iface) const = 0;
79 
80  /**
81  * @brief Register interface
82  *
83  * Example:
84  * \code
85  * ierr = regSubInterface<Simple>(IDD_MOFEMSimple);
86  * CHKERRABORT(PETSC_COMM_SELF, ierr);
87  * \endcode
88  *
89  * @param uuid
90  * @param true
91  * @return MoFEMErrorCode
92  */
93  template <class IFACE>
95  bool error_if_registration_failed = true) {
97  std::pair<iFaceTypeMap_multiIndex::iterator, bool> p;
98  p = iFaceTypeMap.insert(
99  UIdTypeMap(uuid, boost::typeindex::type_id<IFACE>()));
100  if (error_if_registration_failed && (!p.second)) {
101  SETERRQ1(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
102  "Registration of interface typeid(IFACE).name() = %s failed",
103  typeid(IFACE).name());
104  }
106  }
107 
108  /**
109  * @brief Get interface by uuid and return reference to pointer of interface
110  *
111  * \note uuid of interface and interface are verified, if second template
112  * parameter is true. Function throw error if both do not match.
113  *
114  * \note Do not use this function directly, it is called by other overload
115  * getInterface methods.
116  *
117  * @param uuid
118  * @param iface reference to a interface pointer
119  * @return MoFEMErrorCode
120  */
121  template <class IFACE, bool VERIFY = false>
123  IFACE *&iface) const {
125  iface = NULL;
126  if (VERIFY) {
127  if (boost::typeindex::type_id<IFACE>()!=getClassIdx(uuid)) {
128  SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
129  "Inconsistency between interface Id and type");
130  }
131  }
132  UnknownInterface *ptr;
133  ierr = getInterface<UnknownInterface, false>(uuid, ptr);
134  CHKERRG(ierr);
135  iface = static_cast<IFACE *>(ptr);
137  }
138 
139  /**
140  * @brief Get interface refernce to pointer of interface
141  *
142  * \code
143  * // Create moab database
144  * moab::Core mb_instance;
145  * // Access moab database by interface
146  * moab::Interface &moab = mb_instance;
147  *
148  * // Create MoFEM database
149  * MoFEM::Core core(moab);
150  * // Acces MoFEM database by Interface
151  * MoFEM::Interface &m_field = core;
152  *
153  * // Get interface
154  * // Get simple interface is simplified version enabling quick and
155  * // easy construction of problem.
156  * Simple *simple_interface;
157  * // Query interface and get pointer to Simple interface
158  * CHKERR m_field.getInterface(simple_interface);
159  *
160  * \endcode
161  *
162  * @param iface reference to a interface pointer
163  * @return MoFEMErrorCode
164  */
165  template <class IFACE>
166  inline MoFEMErrorCode getInterface(IFACE *&iface) const {
167  return getInterface<IFACE, false>(
168  getUId(boost::typeindex::type_id<IFACE>()), iface);
169  }
170 
171  /**
172  * @brief Get interface pointer to pointer of interface
173  *
174  * \code
175  * // Create moab database
176  * moab::Core mb_instance;
177  * // Access moab database by interface
178  * moab::Interface &moab = mb_instance;
179  *
180  * // Create MoFEM database
181  * MoFEM::Core core(moab);
182  * // Acces MoFEM database by Interface
183  * MoFEM::Interface &m_field = core;
184  *
185  * // Get interface
186  * // Get simple interface is simplified version enabling quick and
187  * // easy construction of problem.
188  * Simple *simple_interface;
189  * // Query interface and get pointer to Simple interface
190  * CHKERR m_field.getInterface(&simple_interface);
191  *
192  * \endcode
193  *
194  *
195  * @param iface const pointer to a interface pointer
196  * @return MoFEMErrorCode
197  */
198  template <class IFACE>
199  inline MoFEMErrorCode getInterface(IFACE **const iface) const {
200  return getInterface<IFACE, false>(boost::typeindex::type_id<IFACE>(),
201  *iface);
202  }
203 
204  /**
205  * @brief Get interface pointer to pointer of interface
206  *
207  * \code
208  * // Create moab database
209  * moab::Core mb_instance;
210  * // Access moab database by interface
211  * moab::Interface &moab = mb_instance;
212  *
213  * // Create MoFEM database
214  * MoFEM::Core core(moab);
215  * // Acces MoFEM database by Interface
216  * MoFEM::Interface &m_field = core;
217  *
218  * // Get interface
219  * // Get simple interface is simplified version enabling quick and
220  * // easy construction of problem.
221  * Simple *simple_interface = m_field.getInterface<Simple*,0>();
222  *
223  * \endcode
224  *
225  * @return IFACE*
226  */
227  template <class IFACE,
228  typename boost::enable_if<boost::is_pointer<IFACE>, int>::type = 0>
229  inline IFACE getInterface() const {
230  typedef typename boost::remove_pointer<IFACE>::type IFaceType;
231  IFaceType* iface = NULL;
232  ierr = getInterface<IFaceType, false>(
233  getUId(boost::typeindex::type_id<IFaceType>()), iface);
234  CHKERRABORT(PETSC_COMM_SELF, ierr);
235  return iface;
236  }
237 
238  /**
239  * @brief Get reference to interface
240  *
241  * \code
242  * // Create moab database
243  * moab::Core mb_instance;
244  * // Access moab database by interface
245  * moab::Interface &moab = mb_instance;
246  *
247  * // Create MoFEM database
248  * MoFEM::Core core(moab);
249  * // Acces MoFEM database by Interface
250  * MoFEM::Interface &m_field = core;
251  *
252  * // Get interface
253  * // Get simple interface is simplified version enabling quick and
254  * // easy construction of problem.
255  * Simple &simple_interface = m_field.getInterface<Simple&,0>();
256  *
257  * \endcode
258  *
259  * @return IFACE&
260  */
261  template <class IFACE, typename boost::enable_if<boost::is_reference<IFACE>,
262  int>::type = 0>
263  inline IFACE getInterface() const {
264  typedef typename boost::remove_reference<IFACE>::type IFaceType;
265  IFaceType* iface = NULL;
266  ierr = getInterface<IFaceType, false>(
267  getUId(boost::typeindex::type_id<IFaceType>()), iface);
268  CHKERRABORT(PETSC_COMM_SELF, ierr);
269  return *iface;
270  }
271 
272  /**
273  * @brief Function returning pointer to interface
274  *
275  * \code
276  * // Create moab database
277  * moab::Core mb_instance;
278  * // Access moab database by interface
279  * moab::Interface &moab = mb_instance;
280  *
281  * // Create MoFEM database
282  * MoFEM::Core core(moab);
283  * // Acces MoFEM database by Interface
284  * MoFEM::Interface &m_field = core;
285  *
286  * // Get interface
287  * // Get simple interface is simplified version enabling quick and
288  * // easy construction of problem.
289  * Simple *simple_interface = m_field.getInterface<Simple,0>();
290  *
291  * \endcode
292  *
293  * @return IFACE*
294  */
295  template <class IFACE>
296  inline IFACE* getInterface() const {
297  return getInterface<IFACE*,0>();
298  }
299 
300  virtual ~UnknownInterface() = default;
301 
302  /**
303  * \brief Get library version
304  *
305  * This is library version.
306  *
307  * @return error code
308  */
309  virtual MoFEMErrorCode getLibVersion(Version &version) const {
311  version =
312  Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD);
314  }
315 
316  /**
317  * \brief Get database major version
318  *
319  * This is database version. MoFEM can read DataBase from file created by older
320  * version. Then library version and database version could be different.
321  *
322  * @return error code
323  */
324  virtual const MoFEMErrorCode getFileVersion(moab::Interface &moab,
325  Version &version) const {
327  const EntityHandle root_meshset = 0;
328  const int def_version[] = {-1, -1, -1};
329  Tag th;
330  rval = moab.tag_get_handle("MOFEM_VERSION", 3, MB_TYPE_INTEGER, th,
331  MB_TAG_CREAT | MB_TAG_MESH, &def_version);
332  int *version_ptr;
333  if (rval == MB_ALREADY_ALLOCATED) {
334  const void *tag_data[1];
335  CHKERR moab.tag_get_by_ptr(th, &root_meshset, 1, tag_data);
336  version_ptr = (int *)tag_data[0];
337  } else {
338  const void *tag_data[1];
339  CHKERR moab.tag_get_by_ptr(th, &root_meshset, 1, tag_data);
340  version_ptr = (int *)tag_data[0];
341  version_ptr[0] = MoFEM_VERSION_MAJOR;
342  version_ptr[1] = MoFEM_VERSION_MINOR;
343  version_ptr[2] = MoFEM_VERSION_BUILD;
344  }
345  version = Version(version_ptr);
347  }
348 
349  /**
350  * \brief Get database major version
351  *
352  * Implementation of particular interface could be different than main lib. For
353  * example user could use older interface, to keep back compatibility.
354  *
355  * @return error code
356  */
357  virtual MoFEMErrorCode getInterfaceVersion(Version &version) const {
359  version =
360  Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD);
362  }
363 
364 protected:
365 
366  struct NotKnownClass {};
367 
368  /**
369  * \brief Get type name for interface Id
370  * @param uid interface Id
371  * @return class name
372  */
373  inline boost::typeindex::type_index getClassIdx(const MOFEMuuid &uid) const {
374  iFaceTypeMap_multiIndex::nth_index<0>::type::iterator it;
375  it = iFaceTypeMap.get<0>().find(uid);
376  if (it != iFaceTypeMap.get<0>().end()) {
377  return it->classIdx;
378  }
379  return boost::typeindex::type_id<NotKnownClass>();
380  }
381 
382  /**
383  * \brief Get interface Id for class name
384  * @param class_name
385  * @return Id
386  */
387  inline MOFEMuuid getUId(const boost::typeindex::type_index &class_idx) const {
388  iFaceTypeMap_multiIndex::nth_index<1>::type::iterator it;
389  it = iFaceTypeMap.get<1>().find(class_idx);
390  if (it != iFaceTypeMap.get<1>().end()) {
391  return it->uID;
392  }
393  return IDD_MOFEMUnknown;
394  }
395 
396 private:
397 
398  struct UIdTypeMap {
400  boost::typeindex::type_index classIdx;
401  UIdTypeMap(const MOFEMuuid &uid, const boost::typeindex::type_index &idx)
402  : uID(uid), classIdx(idx) {}
403  };
404 
405  struct HashMOFEMuuid {
406  inline unsigned int operator()(const MOFEMuuid &value) const {
407  return value.uUId.to_ulong();
408  }
409  };
410 
411  /// Data structure for interfaces Id and class names
412  typedef multi_index_container<
413  UIdTypeMap,
414  indexed_by<
415  hashed_unique<
416  member<UIdTypeMap, MOFEMuuid, &UIdTypeMap::uID>,
417  HashMOFEMuuid
418  >,
419  hashed_unique<
420  member<UIdTypeMap, boost::typeindex::type_index, &UIdTypeMap::classIdx>
421  >
422  >
424 
426  iFaceTypeMap; ///< Maps MOFEMuuid to interface type name
427 };
428 
429 template <>
430 inline MoFEMErrorCode UnknownInterface::getInterface<UnknownInterface, false>(
431  const MOFEMuuid &uuid, UnknownInterface *&iface) const {
432  return query_interface(uuid, &iface);
433 }
434 }
435 
436 #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:501
Version(const int v[3])
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:477
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:544
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:508
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
virtual const MoFEMErrorCode getFileVersion(moab::Interface &moab, Version &version) const
Get database major version.
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
Definition: Exceptions.hpp:84
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.
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.
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:66
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:596
iFaceTypeMap_multiIndex iFaceTypeMap
Maps MOFEMuuid to interface type name.
virtual MoFEMErrorCode getLibVersion(Version &version) const
Get library version.
MoFEMErrorCode printVersion(std::string prefix="", MPI_Comm comm=PETSC_COMM_WORLD)
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:407
Version(const int minor, const int major, const int build)
UIdTypeMap(const MOFEMuuid &uid, const boost::typeindex::type_index &idx)
MOFEMuuid getUId(const boost::typeindex::type_index &class_idx) const
Get interface Id for class name.