Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 :
62 : Handlers to the plumed object can be converted among different representations,
63 : to allow inter-operability among languages. In C, there are tools to convert
64 : to/from FORTRAN, whereas in C++ there are tools to convert to/from FORTRAN and C.
65 :
66 : These handlers only contain a pointer to the real structure, so that
67 : when a plumed object is brought from one language to another,
68 : it brings a reference to the same environment.
69 :
70 : Moreover, to simplify life in all cases where a single Plumed object is
71 : required for the entire simulation (which covers most of the practical
72 : applications with conventional MD codes) it is possible to take advantage
73 : of a global interface, which is implicitly referring to a unique global instance.
74 : The global object should still be initialized and finalized properly.
75 :
76 : The basic method to send a message to plumed is
77 : \verbatim
78 : (C) plumed_cmd
79 : (C++) PLMD::Plumed::cmd
80 : (FORTRAN) PLUMED_F_CMD
81 : \endverbatim
82 :
83 : To initialize a plumed object, use:
84 : \verbatim
85 : (C) plumed_create
86 : (C++) (constructor of PLMD::Plumed)
87 : (FORTRAN) PLUMED_F_CREATE
88 : \endverbatim
89 :
90 : To finalize it, use
91 : \verbatim
92 : (C) plumed_finalize
93 : (C++) (destructor of PLMD::Plumed)
94 : (FORTRAN) PLUMED_F_FINALIZE
95 : \endverbatim
96 :
97 : To access to the global-object, use
98 : \verbatim
99 : (C) plumed_gcreate, plumed_gfinalize, plumed_gcmd
100 : (C++) PLMD::Plumed::gcreate, PLMD::Plumed::gfinalize, PLMD::Plumed::gcmd
101 : (FORTRAN) PLUMED_F_GCREATE, PLUMED_F_GFINALIZE, PLUMED_F_GCMD
102 : \endverbatim
103 :
104 : To check if the global object has been initialized, use
105 : \verbatim
106 : (C) plumed_ginitialized
107 : (C++) PLMD::Plumed::ginitialized
108 : (FORTRAN) PLUMED_F_GINITIALIZED
109 : \endverbatim
110 :
111 : To check if plumed library is available (this is useful for runtime linking), use
112 : \verbatim
113 : (C) plumed_installed
114 : (C++) PLMD::Plumed::installed
115 : (FORTRAN) PLUMED_F_INSTALLED
116 : \endverbatim
117 :
118 : To convert handlers use
119 : \verbatim
120 : (C) plumed_c2f (C to FORTRAN)
121 : (C) plumed_f2c (FORTRAN to C)
122 : (C++) Plumed(plumed) constructor (C to C++)
123 : (C++) operator plumed() cast (C++ to C)
124 : (C++) Plumed(char*) constructor (FORTRAN to C++)
125 : (C++) toFortran(char*) (C++ to FORTRAN)
126 : \endverbatim
127 :
128 : \verbatim
129 : FORTRAN interface
130 : SUBROUTINE PLUMED_F_INSTALLED(i)
131 : INTEGER, INTENT(OUT) :: i
132 : SUBROUTINE PLUMED_F_GINITIALIZED(i)
133 : INTEGER, INTENT(OUT) :: i
134 : SUBROUTINE PLUMED_F_GCREATE()
135 : SUBROUTINE PLUMED_F_GCMD(key,val)
136 : CHARACTER(LEN=*), INTENT(IN) :: key
137 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
138 : SUBROUTINE PLUMED_F_GFINALIZE()
139 : SUBROUTINE PLUMED_F_GLOBAL(p)
140 : CHARACTER(LEN=32), INTENT(OUT) :: p
141 : SUBROUTINE PLUMED_F_CREATE(p)
142 : CHARACTER(LEN=32), INTENT(OUT) :: p
143 : SUBROUTINE PLUMED_F_CMD(p,key,val)
144 : CHARACTER(LEN=32), INTENT(IN) :: p
145 : CHARACTER(LEN=*), INTENT(IN) :: key
146 : UNSPECIFIED_TYPE, INTENT(INOUT) :: val(*)
147 : SUBROUTINE PLUMED_F_FINALIZE(p)
148 : CHARACTER(LEN=32), INTENT(IN) :: p
149 : \endverbatim
150 :
151 : The main routine is "cmd", which accepts two arguments:
152 : key is a string containing the name of the command
153 : val is the argument. it is declared const so as to use allow passing const objects, but in practice plumed
154 : is going to modify val in several cases (using a const_cast).
155 : In some cases val can be omitted: just pass a NULL pointer (in C++, val is optional and can be omitted).
156 : The set of possible keys is the real API of the plumed library, and will be expanded with time.
157 : New commands will be added, but backward compatibility will be retained as long as possible.
158 :
159 : To pass plumed a callback function use the following syntax (not available in FORTRAN yet)
160 : \verbatim
161 : plumed_function_holder ff;
162 : ff.p=your_function;
163 : plumed_cmd(plumed,"xxxx",&ff);
164 : \endverbatim
165 : (this is passing the your_function() function to the "xxxx" command)
166 : */
167 :
168 : #ifdef __cplusplus
169 : extern "C" {
170 : #endif
171 :
172 : /* Generic function pointer */
173 : typedef void (*plumed_function_pointer)(void);
174 :
175 : /**
176 : \brief Holder for function pointer.
177 :
178 : To pass plumed a callback function use the following syntax:
179 : \verbatim
180 : plumed_function_holder ff;
181 : ff.p=your_function;
182 : plumed_cmd(plumed,"xxxx",&ff);
183 : \endverbatim
184 : (this is going to pass the your_function() function to the "xxxx" command)
185 : */
186 :
187 : typedef struct {
188 : plumed_function_pointer p;
189 : } plumed_function_holder;
190 :
191 : /**
192 : \brief Main plumed object
193 :
194 : This is an object containing a Plumed instance, which should be used in
195 : the MD engine. It should first be initialized with plumed_create(),
196 : then it communicates with the MD engine using plumed_cmd(). Finally,
197 : before the termination, it should be deallocated with plumed_finalize().
198 : Its interface is very simple and general, and is expected
199 : not to change across plumed versions. See \ref ReferencePlumedH.
200 : */
201 : typedef struct {
202 : /**
203 : \private
204 : \brief Void pointer holding the real PlumedMain structure
205 : */
206 : void*p;
207 : } plumed;
208 :
209 : /** \relates plumed
210 : \brief Constructor
211 :
212 : \return The constructed plumed object
213 : */
214 : plumed plumed_create(void);
215 :
216 : /** \relates plumed
217 : \brief Tells p to execute a command
218 :
219 : \param p The plumed object on which command is acting
220 : \param key The name of the command to be executed
221 : \param val The argument. It is declared as const to allow calls like plumed_cmd(p,"A","B"),
222 : but for some choice of key it can change the content
223 : */
224 : void plumed_cmd(plumed p,const char*key,const void*val);
225 :
226 : /** \relates plumed
227 : \brief Destructor
228 :
229 : \param p The plumed object to be deallocated
230 : */
231 : void plumed_finalize(plumed p);
232 :
233 : /** \relates plumed
234 : \brief Check if plumed is installed (for runtime binding)
235 :
236 : \return 1 if plumed is installed, 0 otherwise
237 : */
238 : int plumed_installed(void);
239 :
240 : /** \relates plumed
241 : \brief Retrieves an handler to the global structure.
242 : */
243 : plumed plumed_global(void);
244 :
245 : /** \relates plumed
246 : \brief Check if the global interface has been initialized
247 :
248 : \return 1 if plumed has been initialized, 0 otherwise
249 : */
250 : int plumed_ginitialized(void);
251 :
252 : /* global C interface, working on a global object */
253 :
254 : /** \relates plumed
255 : \brief Constructor for the global interface.
256 :
257 : \note Equivalent to plumed_create(), but initialize the static global plumed object
258 : */
259 : void plumed_gcreate(void);
260 :
261 : /** \relates plumed
262 : \brief Tells to the global interface to execute a command.
263 :
264 : \param key The name of the command to be executed
265 : \param val The argument. It is declared as const to allow calls like plumed_gcmd("A","B"),
266 : but for some choice of key it can change the content
267 :
268 : \note Equivalent to plumed_cmd(), but acting on the global plumed object.
269 : It thus does not require the plumed object to be specified.
270 : */
271 : void plumed_gcmd(const char* key,const void* val);
272 :
273 : /** \relates plumed
274 : \brief Destructor for the global interface.
275 :
276 : \note Equivalent to plumed_finalize(), but acting on the global plumed object.
277 : It thus does not require the plumed object to be specified.
278 : */
279 : void plumed_gfinalize(void);
280 :
281 : /* routines to convert char handler from/to plumed objects */
282 :
283 : /** \related plumed
284 : \brief Converts a C handler to a FORTRAN handler
285 :
286 : \param p The C handler
287 : \param c The FORTRAN handler (a char[32])
288 :
289 : This function can be used to convert a plumed object created in C to
290 : a plumed handler that can be used in FORTRAN.
291 : \verbatim
292 : #include <plumed/wrapper/Plumed.h>
293 : int main(int argc,char*argv[]){
294 : plumed p;
295 : p=plumed_create();
296 : char fortran_handler[32];
297 : plumed_c2f(p,fortran_handler);
298 : printf("DEBUG: this is a string representation for the plumed handler: %s\n",fortran_handler);
299 : fortran_routine(fortran_handler);
300 : plumed_finalize(p);
301 : return 0;
302 : }
303 : \endverbatim
304 : Here `fortran_routine` is a routine implemented in FORTRAN that manipulates the
305 : fortran_handler.
306 : */
307 : void plumed_c2f(plumed p,char* c);
308 :
309 : /** \related plumed
310 : \brief Converts a FORTRAN handler to a C handler
311 : \param c The FORTRAN handler (a char[32])
312 : \return The C handler
313 :
314 : This function can be used to convert a plumed object created in FORTRAN
315 : to a plumed handler that can be used in C.
316 : \verbatim
317 : void c_routine(char handler[32]){
318 : plumed p;
319 : p=plumed_f2c(handler);
320 : plumed_cmd(p,"init",NULL);
321 : }
322 : \endverbatim
323 : Here `c_routine` is a C function that can be called from FORTRAN
324 : and interact with the provided plumed handler.
325 : */
326 : plumed plumed_f2c(const char* c);
327 :
328 : #ifdef __cplusplus
329 : }
330 : #endif
331 :
332 : #ifdef __cplusplus
333 :
334 : /* this is to include the NULL pointer */
335 : #include <cstdlib>
336 :
337 : /* C++ interface is hidden in PLMD namespace (same as plumed library) */
338 : namespace PLMD {
339 :
340 : /**
341 : C++ wrapper for \ref plumed.
342 :
343 : This class provides a C++ interface to PLUMED.
344 : */
345 :
346 : class Plumed {
347 : /**
348 : C structure.
349 : */
350 : plumed main;
351 : /**
352 : keeps track if the object was created from scratch using
353 : the defaults destructor (reference=false) or if it was imported
354 : from C or FORTRAN (reference=true). In the latter case, the
355 : plumed_finalize() method is not called when destructing the object,
356 : since it is expected to be finalized in the C/FORTRAN code
357 : */
358 : bool reference;
359 : public:
360 : /**
361 : Check if plumed is installed (for runtime binding)
362 : \return true if plumed is installed, false otherwise
363 : \note Equivalent to plumed_installed() but returns a bool
364 : */
365 : static bool installed();
366 : /**
367 : Check if global-plumed has been initialized
368 : \return true if global plumed object (see global()) is initialized (i.e. if gcreate() has been
369 : called), false otherwise.
370 : \note Equivalent to plumed_ginitialized() but returns a bool
371 : */
372 : static bool ginitialized();
373 : /**
374 : Initialize global-plumed.
375 : \note Equivalent to plumed_gcreate()
376 : */
377 : static void gcreate();
378 : /**
379 : Send a command to global-plumed
380 : \param key The name of the command to be executed
381 : \param val The argument. It is declared as const to allow calls like gcmd("A","B"),
382 : but for some choice of key it can change the content
383 : \note Equivalent to plumed_gcmd()
384 : */
385 : static void gcmd(const char* key,const void* val=NULL);
386 : /**
387 : Finalize global-plumed
388 : */
389 : static void gfinalize();
390 : /**
391 : Returns the Plumed global object
392 : \return The Plumed global object
393 : */
394 : static Plumed global();
395 : /**
396 : Constructor.
397 : \note Performs the same task a plumed_create()
398 : */
399 : Plumed();
400 : /**
401 : Clone a Plumed object from a FORTRAN char* handler
402 : \param c The FORTRAN handler (a char[32]).
403 :
404 : \attention The Plumed object created in this manner
405 : will not finalize the corresponding plumed structure.
406 : It is expected that the FORTRAN code calls plumed_c_finalize for it
407 : */
408 : // to have maximum portability of this file I do not use the explicit keyword here
409 : // I thus add a suppress command for cppcheck
410 : // cppcheck-suppress noExplicitConstructor
411 : Plumed(const char*c);
412 : /**
413 : Clone a Plumed object from a C plumed structure
414 : \param p The C plumed structure.
415 :
416 : \attention The Plumed object created in this manner
417 : will not finalize the corresponding plumed structure.
418 : It is expected that the C code calls plumed_finalize for it
419 : */
420 : // to have maximum portability of this file I do not use the explicit keyword here
421 : // I thus add a suppress command for cppcheck
422 : // cppcheck-suppress noExplicitConstructor
423 : Plumed(plumed p);
424 : private:
425 : /** Copy constructor is disabled (private and unimplemented)
426 : The problem here is that after copying it will not be clear who is
427 : going to finalize the corresponding plumed structure.
428 : */
429 : Plumed(const Plumed&);
430 : /** Assignment operator is disabled (private and unimplemented)
431 : The problem here is that after copying it will not be clear who is
432 : going to finalize the corresponding plumed structure.
433 : */
434 : Plumed&operator=(const Plumed&);
435 : public:
436 : /**
437 : Retrieve the C plumed structure for this object
438 : */
439 : operator plumed()const;
440 : /**
441 : Retrieve a FORTRAN handler for this object
442 : \param c The FORTRAN handler (a char[32]).
443 : */
444 : void toFortran(char*c)const;
445 : /**
446 : Send a command to this plumed object
447 : \param key The name of the command to be executed
448 : \param val The argument. It is declared as const to allow calls like p.cmd("A","B"),
449 : but for some choice of key it can change the content
450 : \note Equivalent to plumed_cmd()
451 : */
452 : void cmd(const char*key,const void*val=NULL);
453 : /**
454 : Destructor
455 :
456 : Destructor is virtual so as to allow correct inheritance from Plumed object.
457 : To avoid linking problems with g++, I specify "inline" also here (in principle
458 : it should be enough to specify it down in the definition of the function, but
459 : for some reason that I do not understand g++ does not inline it properly in that
460 : case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the
461 : way it is done here seems to work properly).
462 : */
463 : inline virtual ~Plumed();
464 : };
465 :
466 : /* All methods are inlined so as to avoid the compilation of an extra c++ file */
467 :
468 : inline
469 : bool Plumed::installed() {
470 : return plumed_installed();
471 : }
472 :
473 : inline
474 1120 : Plumed::Plumed():
475 : main(plumed_create()),
476 1120 : reference(false)
477 1120 : {}
478 :
479 : inline
480 : Plumed::Plumed(const char*c):
481 : main(plumed_f2c(c)),
482 : reference(true)
483 : {}
484 :
485 : inline
486 : Plumed::Plumed(plumed p):
487 : main(p),
488 : reference(true)
489 : {}
490 :
491 : inline
492 : Plumed::operator plumed()const {
493 : return main;
494 : }
495 :
496 : inline
497 : void Plumed::toFortran(char*c)const {
498 : plumed_c2f(main,c);
499 : }
500 :
501 : inline
502 194623 : void Plumed::cmd(const char*key,const void*val) {
503 194623 : plumed_cmd(main,key,val);
504 194623 : }
505 :
506 : inline
507 1952 : Plumed::~Plumed() {
508 1120 : if(!reference)plumed_finalize(main);
509 1952 : }
510 :
511 : inline
512 : bool Plumed::ginitialized() {
513 : return plumed_ginitialized();
514 : }
515 :
516 : inline
517 : void Plumed::gcreate() {
518 : plumed_gcreate();
519 : }
520 :
521 : inline
522 : void Plumed::gcmd(const char* key,const void* val) {
523 : plumed_gcmd(key,val);
524 : }
525 :
526 : inline
527 : void Plumed::gfinalize() {
528 : plumed_gfinalize();
529 : }
530 :
531 : inline
532 : Plumed Plumed::global() {
533 : return plumed_global();
534 : }
535 :
536 : }
537 :
538 : #endif
539 :
540 :
541 : #endif
|