Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #ifndef __PLUMED_wrapper_Plumed_h
23 : #define __PLUMED_wrapper_Plumed_h
24 :
25 : /**
26 : \page ReferencePlumedH Reference for interfacing MD codes with PLUMED
27 :
28 : Plumed.h and Plumed.c contain the external plumed interface, which is used to
29 : integrate it with MD engines. This interface is very general, and is expected
30 : not to change across plumed versions. Plumed.c also implements a dummy version
31 : of the interface, so as to allow a code to be fully linked even if the plumed
32 : library is not available yet. These files could be directly included in the official
33 : host MD distribution. In this manner, it will be sufficient to link the plumed
34 : library at link time (on all systems) or directly at runtime (on system where
35 : dynamic loading is enabled) to include plumed features.
36 :
37 : Why is Plumed.c written in C and not C++? The reason is that the resulting Plumed.o
38 : needs to be linked with the host MD code immediately (whereas the rest of plumed
39 : could be linked a posteriori). Imagine the MD code is written in FORTRAN: when we
40 : link the Plumed.o file we would like not to need any C++ library linked. In this
41 : manner, we do not need to know which C++ compiler will be used to compile plumed.
42 : The C++ library is only linked to the "rest" of plumed, which actually use it.
43 : Anyway, Plumed.c is written in such a manner to allow its compilation also in C++
44 : (C++ is a bit stricter than C; compatibility is checked when PlumedStatic.cpp,
45 : which basically includes Plumed.c, is compiled with the C++ compiler). This will
46 : allow e.g. MD codes written in C++ to just incorporate Plumed.c (maybe renamed into
47 : Plumed.cpp), without the need of configuring a plain C compiler.
48 :
49 : Plumed interface can be used from C, C++ and FORTRAN. Everything concerning plumed
50 : is hidden inside a single object type, which is described in C by a structure
51 : (struct \ref plumed), in C++ by a class (PLMD::Plumed) and in FORTRAN by a
52 : fixed-length string (CHARACTER(LEN=32)). Obviously C++ can use both struct
53 : and class interfaces, but the first should be preferred. The reference interface
54 : is the C one, whereas FORTRAN and C++ interfaces are implemented as wrappers
55 : around it.
56 :
57 : In the C++ interface, all the routines are implemented as methods of PLMD::Plumed.
58 : In the C and FORTRAN interfaces, all the routines are named plumed_*, to
59 : avoid potential name clashes. Notice that the entire plumed library
60 : is implemented in C++, and it is hidden inside the PLMD namespace.
61 : If the used C++ compiler supports C++11, PLMD::Plumed object defines move semantics
62 : so as to be usable in STL containers. That is, you can declare a std::vector<PLMD::Plumed>.
63 :
64 : Handlers to the plumed object can be converted among different representations,
65 : to allow inter-operability among languages. In C, there are tools to convert
66 : to/from FORTRAN, whereas in C++ there are tools to convert to/from FORTRAN and C.
67 :
68 : These handlers only contain a pointer to the real structure, so that
69 : when a plumed object is brought from one language to another,
70 : it brings a reference to the same environment.
71 :
72 : Moreover, to simplify life in all cases where a single Plumed object is
73 : required for the entire simulation (which covers most of the practical
74 : applications with conventional MD codes) it is possible to take advantage
75 : of a global interface, which is implicitly referring to a unique global instance.
76 : The global object should still be initialized and finalized properly.
77 :
78 : The basic method to send a message to plumed is
79 : \verbatim
80 : (C) plumed_cmd
81 : (C++) PLMD::Plumed::cmd
82 : (FORTRAN) PLUMED_F_CMD
83 : \endverbatim
84 :
85 : To initialize a plumed object, use:
86 : \verbatim
87 : (C) plumed_create
88 : (C++) (constructor of PLMD::Plumed)
89 : (FORTRAN) PLUMED_F_CREATE
90 : \endverbatim
91 :
92 : To finalize it, use
93 : \verbatim
94 : (C) plumed_finalize
95 : (C++) (destructor of PLMD::Plumed)
96 : (FORTRAN) PLUMED_F_FINALIZE
97 : \endverbatim
98 :
99 : To access to the global-object, use
100 : \verbatim
101 : (C) plumed_gcreate, plumed_gfinalize, plumed_gcmd
102 : (C++) PLMD::Plumed::gcreate, PLMD::Plumed::gfinalize, PLMD::Plumed::gcmd
103 : (FORTRAN) PLUMED_F_GCREATE, PLUMED_F_GFINALIZE, PLUMED_F_GCMD
104 : \endverbatim
105 :
106 : To check if the global object has been initialized, use
107 : \verbatim
108 : (C) plumed_ginitialized
109 : (C++) PLMD::Plumed::ginitialized
110 : (FORTRAN) PLUMED_F_GINITIALIZED
111 : \endverbatim
112 :
113 : To check if plumed library is available (this is useful for runtime linking), use
114 : \verbatim
115 : (C) plumed_installed
116 : (C++) PLMD::Plumed::installed
117 : (FORTRAN) PLUMED_F_INSTALLED
118 : \endverbatim
119 :
120 : To convert handlers use
121 : \verbatim
122 : (C) plumed_c2f (C to FORTRAN)
123 : (C) plumed_f2c (FORTRAN to C)
124 : (C++) Plumed(plumed) constructor (C to C++)
125 : (C++) operator plumed() cast (C++ to C)
126 : (C++) Plumed(char*) constructor (FORTRAN to C++)
127 : (C++) toFortran(char*) (C++ to FORTRAN)
128 : \endverbatim
129 :
130 : \verbatim
131 : FORTRAN interface
132 : SUBROUTINE PLUMED_F_INSTALLED(i)
133 : INTEGER, INTENT(OUT) :: i
134 : SUBROUTINE PLUMED_F_GINITIALIZED(i)
135 : INTEGER, INTENT(OUT) :: i
136 : SUBROUTINE PLUMED_F_GCREATE()
137 : SUBROUTINE PLUMED_F_GCMD(key,val)
138 : CHARACTER(LEN=*), INTENT(IN) :: key
139 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
140 : SUBROUTINE PLUMED_F_GFINALIZE()
141 : SUBROUTINE PLUMED_F_GLOBAL(p)
142 : CHARACTER(LEN=32), INTENT(OUT) :: p
143 : SUBROUTINE PLUMED_F_CREATE(p)
144 : CHARACTER(LEN=32), INTENT(OUT) :: p
145 : SUBROUTINE PLUMED_F_CMD(p,key,val)
146 : CHARACTER(LEN=32), INTENT(IN) :: p
147 : CHARACTER(LEN=*), INTENT(IN) :: key
148 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
149 : SUBROUTINE PLUMED_F_FINALIZE(p)
150 : CHARACTER(LEN=32), INTENT(IN) :: p
151 : \endverbatim
152 :
153 : The main routine is "cmd", which accepts two arguments:
154 : key is a string containing the name of the command
155 : val is the argument. it is declared const so as to use allow passing const objects, but in practice plumed
156 : is going to modify val in several cases (using a const_cast).
157 : In some cases val can be omitted: just pass a NULL pointer (in C++, val is optional and can be omitted).
158 : The set of possible keys is the real API of the plumed library, and will be expanded with time.
159 : New commands will be added, but backward compatibility will be retained as long as possible.
160 :
161 : To pass plumed a callback function use the following syntax (not available in FORTRAN yet)
162 : \verbatim
163 : plumed_function_holder ff;
164 : ff.p=your_function;
165 : plumed_cmd(plumed,"xxxx",&ff);
166 : \endverbatim
167 : (this is passing the your_function() function to the "xxxx" command)
168 : */
169 :
170 : #ifdef __cplusplus
171 : extern "C" {
172 : #endif
173 :
174 : /* Generic function pointer */
175 : typedef void (*plumed_function_pointer)(void);
176 :
177 : /**
178 : \brief Holder for function pointer.
179 :
180 : To pass plumed a callback function use the following syntax:
181 : \verbatim
182 : plumed_function_holder ff;
183 : ff.p=your_function;
184 : plumed_cmd(plumed,"xxxx",&ff);
185 : \endverbatim
186 : (this is going to pass the your_function() function to the "xxxx" command)
187 : */
188 :
189 : typedef struct {
190 : plumed_function_pointer p;
191 : } plumed_function_holder;
192 :
193 : /**
194 : \brief Main plumed object
195 :
196 : This is an object containing a Plumed instance, which should be used in
197 : the MD engine. It should first be initialized with plumed_create(),
198 : then it communicates with the MD engine using plumed_cmd(). Finally,
199 : before the termination, it should be deallocated with plumed_finalize().
200 : Its interface is very simple and general, and is expected
201 : not to change across plumed versions. See \ref ReferencePlumedH.
202 : */
203 : typedef struct {
204 : /**
205 : \private
206 : \brief Void pointer holding the real PlumedMain structure
207 : */
208 : void*p;
209 : } plumed;
210 :
211 : /** \relates plumed
212 : \brief Constructor
213 :
214 : \return The constructed plumed object
215 : */
216 : plumed plumed_create(void);
217 :
218 : /** \relates plumed
219 : \brief Tells p to execute a command
220 :
221 : \param p The plumed object on which command is acting
222 : \param key The name of the command to be executed
223 : \param val The argument. It is declared as const to allow calls like plumed_cmd(p,"A","B"),
224 : but for some choice of key it can change the content
225 : */
226 : void plumed_cmd(plumed p,const char*key,const void*val);
227 :
228 : /** \relates plumed
229 : \brief Destructor
230 :
231 : \param p The plumed object to be deallocated
232 : */
233 : void plumed_finalize(plumed p);
234 :
235 : /** \relates plumed
236 : \brief Check if plumed is installed (for runtime binding)
237 :
238 : \return 1 if plumed is installed, 0 otherwise
239 : */
240 : int plumed_installed(void);
241 :
242 : /** \relates plumed
243 : \brief Retrieves an handler to the global structure.
244 : */
245 : plumed plumed_global(void);
246 :
247 : /** \relates plumed
248 : \brief Check if the global interface has been initialized
249 :
250 : \return 1 if plumed has been initialized, 0 otherwise
251 : */
252 : int plumed_ginitialized(void);
253 :
254 : /* global C interface, working on a global object */
255 :
256 : /** \relates plumed
257 : \brief Constructor for the global interface.
258 :
259 : \note Equivalent to plumed_create(), but initialize the static global plumed object
260 : */
261 : void plumed_gcreate(void);
262 :
263 : /** \relates plumed
264 : \brief Tells to the global interface to execute a command.
265 :
266 : \param key The name of the command to be executed
267 : \param val The argument. It is declared as const to allow calls like plumed_gcmd("A","B"),
268 : but for some choice of key it can change the content
269 :
270 : \note Equivalent to plumed_cmd(), but acting on the global plumed object.
271 : It thus does not require the plumed object to be specified.
272 : */
273 : void plumed_gcmd(const char* key,const void* val);
274 :
275 : /** \relates plumed
276 : \brief Destructor for the global interface.
277 :
278 : \note Equivalent to plumed_finalize(), but acting on the global plumed object.
279 : It thus does not require the plumed object to be specified.
280 : */
281 : void plumed_gfinalize(void);
282 :
283 : /* routines to convert char handler from/to plumed objects */
284 :
285 : /** \related plumed
286 : \brief Converts a C handler to a FORTRAN handler
287 :
288 : \param p The C handler
289 : \param c The FORTRAN handler (a char[32])
290 :
291 : This function can be used to convert a plumed object created in C to
292 : a plumed handler that can be used in FORTRAN.
293 : \verbatim
294 : #include <plumed/wrapper/Plumed.h>
295 : int main(int argc,char*argv[]){
296 : plumed p;
297 : p=plumed_create();
298 : char fortran_handler[32];
299 : plumed_c2f(p,fortran_handler);
300 : printf("DEBUG: this is a string representation for the plumed handler: %s\n",fortran_handler);
301 : fortran_routine(fortran_handler);
302 : plumed_finalize(p);
303 : return 0;
304 : }
305 : \endverbatim
306 : Here `fortran_routine` is a routine implemented in FORTRAN that manipulates the
307 : fortran_handler.
308 : */
309 : void plumed_c2f(plumed p,char* c);
310 :
311 : /** \related plumed
312 : \brief Converts a FORTRAN handler to a C handler
313 : \param c The FORTRAN handler (a char[32])
314 : \return The C handler
315 :
316 : This function can be used to convert a plumed object created in FORTRAN
317 : to a plumed handler that can be used in C.
318 : \verbatim
319 : void c_routine(char handler[32]){
320 : plumed p;
321 : p=plumed_f2c(handler);
322 : plumed_cmd(p,"init",NULL);
323 : }
324 : \endverbatim
325 : Here `c_routine` is a C function that can be called from FORTRAN
326 : and interact with the provided plumed handler.
327 : */
328 : plumed plumed_f2c(const char* c);
329 :
330 : #ifdef __cplusplus
331 : }
332 : #endif
333 :
334 : #ifdef __cplusplus
335 :
336 : /* this is to include the NULL pointer */
337 : #include <cstdlib>
338 :
339 : /* C++ interface is hidden in PLMD namespace (same as plumed library) */
340 : namespace PLMD {
341 :
342 : /**
343 : C++ wrapper for \ref plumed.
344 :
345 : This class provides a C++ interface to PLUMED.
346 : */
347 :
348 : class Plumed {
349 : /**
350 : C structure.
351 : */
352 : plumed main;
353 : /**
354 : keeps track if the object was created from scratch using
355 : the defaults destructor (reference=false) or if it was imported
356 : from C or FORTRAN (reference=true). In the latter case, the
357 : plumed_finalize() method is not called when destructing the object,
358 : since it is expected to be finalized in the C/FORTRAN code
359 : */
360 : bool reference;
361 : public:
362 : /**
363 : Check if plumed is installed (for runtime binding)
364 : \return true if plumed is installed, false otherwise
365 : \note Equivalent to plumed_installed() but returns a bool
366 : */
367 : static bool installed();
368 : /**
369 : Check if global-plumed has been initialized
370 : \return true if global plumed object (see global()) is initialized (i.e. if gcreate() has been
371 : called), false otherwise.
372 : \note Equivalent to plumed_ginitialized() but returns a bool
373 : */
374 : static bool ginitialized();
375 : /**
376 : Initialize global-plumed.
377 : \note Equivalent to plumed_gcreate()
378 : */
379 : static void gcreate();
380 : /**
381 : Send a command to global-plumed
382 : \param key The name of the command to be executed
383 : \param val The argument. It is declared as const to allow calls like gcmd("A","B"),
384 : but for some choice of key it can change the content
385 : \note Equivalent to plumed_gcmd()
386 : */
387 : static void gcmd(const char* key,const void* val=NULL);
388 : /**
389 : Finalize global-plumed
390 : */
391 : static void gfinalize();
392 : /**
393 : Returns the Plumed global object
394 : \return The Plumed global object
395 : */
396 : static Plumed global();
397 : /**
398 : Constructor.
399 : \note Performs the same task a plumed_create()
400 : */
401 : Plumed();
402 : /**
403 : Clone a Plumed object from a FORTRAN char* handler
404 : \param c The FORTRAN handler (a char[32]).
405 :
406 : \attention The Plumed object created in this manner
407 : will not finalize the corresponding plumed structure.
408 : It is expected that the FORTRAN code calls plumed_c_finalize for it
409 : */
410 : // to have maximum portability of this file I do not use the explicit keyword here
411 : // I thus add a suppress command for cppcheck
412 : // cppcheck-suppress noExplicitConstructor
413 : Plumed(const char*c);
414 : /**
415 : Clone a Plumed object from a C plumed structure
416 : \param p The C plumed structure.
417 :
418 : \attention The Plumed object created in this manner
419 : will not finalize the corresponding plumed structure.
420 : It is expected that the C code calls plumed_finalize for it
421 : */
422 : // to have maximum portability of this file I do not use the explicit keyword here
423 : // I thus add a suppress command for cppcheck
424 : // cppcheck-suppress noExplicitConstructor
425 : Plumed(plumed p);
426 : private:
427 : /** Copy constructor is disabled (private and unimplemented)
428 : The problem here is that after copying it will not be clear who is
429 : going to finalize the corresponding plumed structure.
430 : */
431 : Plumed(const Plumed&);
432 : /** Assignment operator is disabled (private and unimplemented)
433 : The problem here is that after copying it will not be clear who is
434 : going to finalize the corresponding plumed structure.
435 : */
436 : Plumed&operator=(const Plumed&);
437 : public:
438 : /*
439 : PLUMED 2.4 requires a C++11 compiler.
440 : Anyway, since Plumed.h file might be redistributed with other codes
441 : and it should be possible to combine it with earlier PLUMED versions,
442 : we here explicitly check if C+11 is available before enabling move semantics.
443 : This could still create problems if a compiler 'cheats', setting __cplusplus > 199711L
444 : but not supporting move semantics. Hopefully will not happen!
445 : */
446 : #if __cplusplus > 199711L
447 : /** Move constructor.
448 : Only if move semantics is enabled.
449 : It allows storing PLMD::Plumed objects in STL containers.
450 : */
451 : Plumed(Plumed&&);
452 : /** Move assignment.
453 : Only if move semantics is enabled.
454 : */
455 : Plumed& operator=(Plumed&&);
456 : #endif
457 : /**
458 : Retrieve the C plumed structure for this object
459 : */
460 : operator plumed()const;
461 : /**
462 : Retrieve a FORTRAN handler for this object
463 : \param c The FORTRAN handler (a char[32]).
464 : */
465 : void toFortran(char*c)const;
466 : /**
467 : Send a command to this plumed object
468 : \param key The name of the command to be executed
469 : \param val The argument. It is declared as const to allow calls like p.cmd("A","B"),
470 : but for some choice of key it can change the content
471 : \note Equivalent to plumed_cmd()
472 : */
473 : void cmd(const char*key,const void*val=NULL);
474 : /**
475 : Destructor
476 :
477 : Destructor is virtual so as to allow correct inheritance from Plumed object.
478 : To avoid linking problems with g++, I specify "inline" also here (in principle
479 : it should be enough to specify it down in the definition of the function, but
480 : for some reason that I do not understand g++ does not inline it properly in that
481 : case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the
482 : way it is done here seems to work properly).
483 : */
484 : inline virtual ~Plumed();
485 : };
486 :
487 : /* All methods are inlined so as to avoid the compilation of an extra c++ file */
488 :
489 : inline
490 : bool Plumed::installed() {
491 : return plumed_installed();
492 : }
493 :
494 : inline
495 2115 : Plumed::Plumed():
496 : main(plumed_create()),
497 2115 : reference(false)
498 : {}
499 :
500 : inline
501 : Plumed::Plumed(const char*c):
502 : main(plumed_f2c(c)),
503 : reference(true)
504 : {}
505 :
506 : inline
507 : Plumed::Plumed(plumed p):
508 : main(p),
509 : reference(true)
510 : {}
511 :
512 : #if __cplusplus > 199711L
513 : inline
514 : Plumed::Plumed(Plumed&& p):
515 : main(p.main),
516 : reference(p.reference)
517 : {
518 : p.main.p=nullptr;
519 : p.reference=true; // make sure the moved plumed is not finalized
520 : }
521 :
522 : inline
523 : Plumed& Plumed::operator=(Plumed&& p) {
524 : if(this != &p) {
525 : if(!reference) plumed_finalize(main);
526 : main=p.main;
527 : reference=p.reference;
528 : p.main.p=nullptr;
529 : p.reference=true; // make sure the moved plumed is not finalized
530 : }
531 : return *this;
532 : }
533 :
534 : #endif
535 :
536 : inline
537 : Plumed::operator plumed()const {
538 : return main;
539 : }
540 :
541 : inline
542 : void Plumed::toFortran(char*c)const {
543 : plumed_c2f(main,c);
544 : }
545 :
546 : inline
547 : void Plumed::cmd(const char*key,const void*val) {
548 189456 : plumed_cmd(main,key,val);
549 : }
550 :
551 : inline
552 4230 : Plumed::~Plumed() {
553 2115 : if(!reference)plumed_finalize(main);
554 1603 : }
555 :
556 : inline
557 : bool Plumed::ginitialized() {
558 : return plumed_ginitialized();
559 : }
560 :
561 : inline
562 : void Plumed::gcreate() {
563 : plumed_gcreate();
564 : }
565 :
566 : inline
567 : void Plumed::gcmd(const char* key,const void* val) {
568 : plumed_gcmd(key,val);
569 : }
570 :
571 : inline
572 : void Plumed::gfinalize() {
573 : plumed_gfinalize();
574 : }
575 :
576 : inline
577 : Plumed Plumed::global() {
578 : return plumed_global();
579 : }
580 :
581 : }
582 :
583 : #endif
584 :
585 :
586 : #endif
|