1 /* MACHINE GENERATED FILE, DO NOT EDIT! */
2
3 #define VMDPLUGIN molfile_basissetplugin
4 #define STATIC_PLUGIN 1
5
6 /***************************************************************************
7 *cr
8 *cr (C) Copyright 1995-2016 The Board of Trustees of the
9 *cr University of Illinois
10 *cr All Rights Reserved
11 *cr
12 ***************************************************************************/
13
14 /***************************************************************************
15 * RCS INFORMATION:
16 *
17 * $RCSfile: basissetplugin.c,v $
18 * $Author: johns $ $Locker: $ $State: Exp $
19 * $Revision: 1.14 $ $Date: 2016/11/28 05:01:53 $
20 *
21 ***************************************************************************/
22
23 /* *******************************************************
24 *
25 * B A S I S S E T P L U G I N
26 *
27 * This plugin reads basis sets for quantum chemical
28 * calculations. The basis set must be in the GAMESS format.
29 * Such files can be downloaded for virtually any basis set
30 * from the EMSL basis set exchange website:
31 * https://bse.pnl.gov/bse/portal
32 *
33 * ********************************************************/
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <time.h>
40 #include <math.h>
41
42 #include "qmplugin.h"
43 #include "unit_conversion.h"
44
45 #define ANGSTROM 0
46 #define BOHR 1
47 #define SPIN_ALPHA 0
48 #define SPIN_BETA 1
49
50 /*
51 * Error reporting macro for use in DEBUG mode
52 */
53 #ifdef GAMESS_DEBUG
54 #define PRINTERR fprintf(stderr, "\n In file %s, line %d: \n %s \n \n", \
55 __FILE__, __LINE__, strerror(errno))
56 #else
57 #define PRINTERR (void)(0)
58 #endif
59
60 /*
61 * Error reporting macro for the multiple fgets calls in
62 * the code
63 */
64 #define GET_LINE(x,y) if (!fgets(x, sizeof(x), y)) return FALSE
65
66 #define UNK_SHELL -666
67 #define SPD_D_SHELL -5
68 #define SPD_P_SHELL -4
69 #define SPD_S_SHELL -3
70 #define SP_S_SHELL -2
71 #define SP_P_SHELL -1
72 #define S_SHELL 0
73 #define P_SHELL 1
74 #define D_SHELL 2
75 #define F_SHELL 3
76 #define G_SHELL 4
77 #define H_SHELL 5
78
79 #define FOUND 1
80 #define STOPPED 2
81
82 #define NUM_ELEMENTS 109
83
84 /* Translation table for element to atomic numbers for element
85 * names used Gamess format files from EMSL */
86 static const char *elements[] = {
87 "(unknown)", "HYDROGEN", "HELIUM", "LITHIUM", "BERYLLIUM", "BORON",
88 "CARBON", "NITROGEN", "OXYGEN", "FLUORINE", "NEON",
89 "SODIUM", "MAGNESIUM", "ALUMINUM", "SILICON", "PHOSPHOROUS",
90 "SULFUR", "CHLORINE", "ARGON", "POTASSIUM", "CALCIUM", "SCANDIUM",
91 "TITANIUM", "VANADIUM", "CHROMIUM", "MANGANESE", "IRON", "COBALT",
92 "NICKEL", "COPPER", "ZINC", "GALLIUM", "GERMANIUM", "ARSENIC",
93 "SELENIUM", "BROMINE", "KRYPTON",
94 "RUBIDIUM", "STRONTIUM", "YTTRIUM", "ZIRCONIUM", "NIOBIUM",
95 "MOLYBDENUM", "TECHNETIUM", "RUTHENIUM", "RHODIUM", "PALLADIUM",
96 "SILVER", "CADMIUM", "INDIUM", "TIN", "ANTIMONY", "TELLURIUM",
97 "IODINE", "XENON",
98 "CESIUM", "BARIUM", "LANTHANUM", "CER", "PRASEODYMIUM", "NEODYMIUM",
99 "PROMETIUM", "SAMARIUM", "EUROPIUM", "GADOLIUM", "TERBIUM",
100 "DYSPROSIUM", "HOLMIUM", "ERBIUM", "THULIUM", "YTTERBIUM",
101 "LUTETIUM", "HAFNIUM", "TANTALUM", "TUNGSTEN", "RHENIUM", "OSMIUM",
102 "IRIDIUM", "PLATINUM", "GOLD", "MERCURY", "THALLIUM", "LEAD",
103 "BISMUTH", "POLONIUM", "ASTATINE", "RADON",
104 "FRANCIUM", "RADIUM", "ACTINIUM", "THORIUM", "PROTACTINIUM",
105 "URANIUM", "NEPTUNIUM", "PLUTONIUM", "AMERICIUM", "CURIUM",
106 "BERKELIUM", "CALIFORNIUM", "EINSTEINIUM", "FERMIUM", "MENDELEVIUM",
107 "NOBELIUM", "LAWRENCIUM", "RUTHERFORDIUM", "DUBNIUM", "SEABORGIUM",
108 "BOHRIUM", "HASSIUM", "MEITNERIUM"};
109
110
111
112 /* ######################################################## */
113 /* declaration/documentation of internal (static) functions */
114 /* ######################################################## */
115
116 static void print_input_data(qmdata_t *);
117
118
119 /* the function get_basis we also parse the basis function section to
120 * determine the number of basis functions, contraction
121 * coefficients. For Pople/Huzinga style basis sets
122 * this numbers are in principle fixed, and could hence
123 * be provided by the the plugin itself; however, the user might
124 * define his own basis/contraction coeffients and hence reading
125 * them from the input file seem to be somewhat more general. */
126 static int get_basis (qmdata_t *);
127
128
129 /* read all primitives for the current shell */
130 static int read_shell_primitives(qmdata_t *, prim_t **prim,
131 char *shellsymm, int icoeff);
132
133 /* convert shell type from char to int */
134 static int shelltype_int(char type);
135
136 /* Populate the flat arrays containing the basis set data */
137 static int fill_basis_arrays(qmdata_t *);
138
139
140 /* ######################################################## */
141 /* Functions that are needed by the molfile_plugin */
142 /* interface to provide VMD with the parsed data */
143 /* ######################################################## */
144
145
146 /***************************************************************
147 *
148 * Called by VMD to open the file and get the number
149 * of atoms.
150 *
151 * *************************************************************/
open_basis_read(const char * filename,const char * filetype,int * natoms)152 static void *open_basis_read(const char *filename,
153 const char *filetype, int *natoms) {
154
155 FILE *fd;
156 qmdata_t *data;
157
158
159 /* open the input file */
160 fd = fopen(filename, "rb");
161
162 if (!fd) {
163 PRINTERR;
164 return NULL;
165 }
166
167 /* allocate memory for main data structure */
168 data = (qmdata_t *)calloc(1,sizeof(qmdata_t));
169
170 /* make sure memory was allocated properly */
171 if (data == NULL) {
172 PRINTERR;
173 return NULL;
174 }
175
176 data->num_shells = 0;
177 data->num_basis_funcs = 0;
178 data->num_basis_atoms = 0;
179
180 /* initialize some of the character arrays */
181 memset(data->basis_string,0,sizeof(data->basis_string));
182
183 /* store file pointer in qmdata_t struct */
184 data->file = fd;
185
186 /* Read the basis set */
187 if (!get_basis(data)) return NULL;
188
189
190 /* provide VMD with the proper number of atoms */
191 *natoms = 0;
192
193 /* Test print the parsed data in same format as logfile */
194 print_input_data(data);
195
196 return data;
197 }
198
199
200
201
202 /*****************************************************
203 *
204 * provide VMD with the sizes of the QM related
205 * data structure arrays that need to be made
206 * available
207 *
208 *****************************************************/
read_basis_metadata(void * mydata,molfile_qm_metadata_t * metadata)209 static int read_basis_metadata(void *mydata,
210 molfile_qm_metadata_t *metadata) {
211
212 qmdata_t *data = (qmdata_t *)mydata;
213
214 metadata->ncart = 0;
215 metadata->nimag = 0;
216 metadata->nintcoords = 0;
217
218 metadata->have_sysinfo = 0;
219 metadata->have_carthessian = 0;
220 metadata->have_inthessian = 0;
221 metadata->have_normalmodes = 0;
222
223 /* orbital + basis set data */
224 metadata->num_basis_funcs = data->num_basis_funcs;
225 metadata->num_basis_atoms = data->num_basis_atoms;
226 metadata->num_shells = data->num_shells;
227 metadata->wavef_size = 0;
228
229 return MOLFILE_SUCCESS;
230 }
231
232
233 /******************************************************
234 *
235 * Provide VMD with the static (i.e. non-trajectory)
236 * data. That means we are filling the molfile_plugin
237 * data structures.
238 *
239 ******************************************************/
read_basis_rundata(void * mydata,molfile_qm_t * qm_data)240 static int read_basis_rundata(void *mydata,
241 molfile_qm_t *qm_data) {
242
243 qmdata_t *data = (qmdata_t *)mydata;
244 int i;
245 molfile_qm_basis_t *basis_data = &qm_data->basis;
246
247 /* strncpy(sys_data->basis_string, data->basis_string, */
248 /* sizeof(sys_data->basis_string)); */
249
250
251 #if vmdplugin_ABIVERSION > 11
252 /* fill in molfile_qm_basis_t */
253 if (data->num_basis_funcs) {
254 for (i=0; i<data->num_basis_atoms; i++) {
255 basis_data->num_shells_per_atom[i] = data->num_shells_per_atom[i];
256 basis_data->atomic_number[i] = data->atomicnum_per_basisatom[i];
257 }
258
259 for (i=0; i<data->num_shells; i++) {
260 basis_data->num_prim_per_shell[i] = data->num_prim_per_shell[i];
261 basis_data->shell_types[i] = data->shell_types[i];
262 }
263
264 for (i=0; i<2*data->num_basis_funcs; i++) {
265 basis_data->basis[i] = data->basis[i];
266 }
267 }
268 #endif
269
270 return MOLFILE_SUCCESS;
271 }
272
273
274
275 /**********************************************************
276 *
277 * clean up when done and free all the memory do avoid
278 * memory leaks
279 *
280 **********************************************************/
close_basis_read(void * mydata)281 static void close_basis_read(void *mydata) {
282
283 qmdata_t *data = (qmdata_t *)mydata;
284 int i, j;
285 fclose(data->file);
286
287 free(data->basis);
288 free(data->shell_types);
289 free(data->atomicnum_per_basisatom);
290 free(data->num_shells_per_atom);
291 free(data->num_prim_per_shell);
292 free(data->angular_momentum);
293 free(data->filepos_array);
294
295 if (data->basis_set) {
296 for(i=0; i<data->num_basis_atoms; i++) {
297 for (j=0; j<data->basis_set[i].numshells; j++) {
298 free(data->basis_set[i].shell[j].prim);
299 }
300 free(data->basis_set[i].shell);
301 }
302 free(data->basis_set);
303 }
304
305 free(data);
306 }
307
308 /* ####################################################### */
309 /* End of API functions */
310 /* The following functions actually do the file parsing. */
311 /* ####################################################### */
312
313
314 #define TORF(x) (x ? "T" : "F")
315
print_input_data(qmdata_t * data)316 static void print_input_data(qmdata_t *data) {
317 int i, j, k;
318 int primcount=0;
319 int shellcount=0;
320
321 /* printf("\n"); */
322 /* printf(" BASIS OPTIONS\n"); */
323 /* printf(" -------------\n"); */
324 /* printf("%s\n", data->basis_string); */
325 /* printf("\n\n\n"); */
326 printf("\n");
327 printf(" ATOMIC BASIS SET\n");
328 printf(" ----------------\n");
329 printf(" THE CONTRACTED PRIMITIVE FUNCTIONS HAVE BEEN UNNORMALIZED\n");
330 printf(" THE CONTRACTED BASIS FUNCTIONS ARE NOW NORMALIZED TO UNITY\n");
331 printf("\n");
332 printf(" SHELL TYPE PRIMITIVE EXPONENT CONTRACTION COEFFICIENT(S)\n");
333 printf("\n");
334
335 printf(" =================================================================\n");
336 for (i=0; i<data->num_basis_atoms; i++) {
337 printf("%-8d (%10s)\n\n", data->basis_set[i].atomicnum, data->basis_set[i].name);
338 printf("\n");
339
340 for (j=0; j<data->basis_set[i].numshells; j++) {
341
342 for (k=0; k<data->basis_set[i].shell[j].numprims; k++) {
343 printf("%6d %d %7d %22f%22f\n", j,
344 data->basis_set[i].shell[j].type,
345 primcount+1,
346 data->basis_set[i].shell[j].prim[k].exponent,
347 data->basis_set[i].shell[j].prim[k].contraction_coeff);
348 primcount++;
349 }
350
351 printf("\n");
352 shellcount++;
353 }
354 }
355 printf("\n");
356 printf(" TOTAL NUMBER OF BASIS SET SHELLS =%5d\n", data->num_shells);
357 printf(" TOTAL NUMBER OF ATOMS =%5i\n", data->numatoms);
358 printf("\n");
359 }
360
361
362
363
364 /*******************************************************
365 *
366 * this function reads in the basis set data
367 *
368 * ******************************************************/
get_basis(qmdata_t * data)369 int get_basis(qmdata_t *data) {
370
371 char buffer[BUFSIZ];
372 char word[4][BUFSIZ];
373 int i = 0;
374 int success = 0;
375 int numread, numshells;
376 shell_t *shell;
377 long filepos;
378
379 /* initialize buffers */
380 buffer[0] = '\0';
381 for (i=0; i<3; i++) word[i][0] = '\0';
382
383 if (!pass_keyline(data->file, "$DATA", NULL))
384 printf("basissetplugin) No basis set found!\n");
385
386
387 /* Allocate space for the basis for all atoms */
388 /* When the molecule is symmetric the actual number atoms with
389 * a basis set could be smaller */
390 data->basis_set = (basis_atom_t*)calloc(1, sizeof(basis_atom_t));
391
392
393 i = 0; /* basis atom counter */
394
395 do {
396 prim_t *prim = NULL;
397 char shelltype;
398 int numprim = 0;
399 int icoeff = 0;
400 filepos = ftell(data->file);
401 GET_LINE(buffer, data->file);
402
403 /* Count the number of relevant words in the line. */
404 numread = sscanf(buffer,"%s %s %s %s",&word[0][0], &word[1][0],
405 &word[2][0], &word[3][0]);
406
407 if (!strcmp(&word[0][0], "$END")) break;
408
409 switch (numread) {
410 case 1:
411 /* Next atom */
412 if (i>0) {
413 data->basis_set = (basis_atom_t*)realloc(data->basis_set, (i+1)*sizeof(basis_atom_t));
414 }
415
416 strcpy(data->basis_set[i].name, &word[0][0]);
417
418
419 /* read the basis set for the current atom */
420 shell = (shell_t*)calloc(1, sizeof(shell_t));
421 numshells = 0;
422
423 do {
424 filepos = ftell(data->file);
425 numprim = read_shell_primitives(data, &prim, &shelltype, icoeff);
426
427 if (numprim>0) {
428 /* make sure we have eiter S, L, P, D, F or G shells */
429 if ( (shelltype!='S' && shelltype!='L' && shelltype!='P' &&
430 shelltype!='D' && shelltype!='F' && shelltype!='G') ) {
431 printf("basissetplugin) WARNING ... %c shells are not supported \n", shelltype);
432 }
433
434 /* create new shell */
435 if (numshells) {
436 shell = (shell_t*)realloc(shell, (numshells+1)*sizeof(shell_t));
437 }
438 shell[numshells].numprims = numprim;
439 shell[numshells].type = shelltype_int(shelltype);
440 shell[numshells].prim = prim;
441 data->num_basis_funcs += numprim;
442
443 /* We split L-shells into one S and one P-shell.
444 * I.e. for L-shells we have to go back read the shell again
445 * this time using the second contraction coefficients. */
446 if (shelltype=='L' && !icoeff) {
447 fseek(data->file, filepos, SEEK_SET);
448 icoeff++;
449 } else if (shelltype=='L' && icoeff) {
450 shell[numshells].type = SP_P_SHELL;
451 icoeff = 0;
452 }
453
454 numshells++;
455 }
456 } while (numprim);
457
458 /* store shells in atom */
459 data->basis_set[i].numshells = numshells;
460 data->basis_set[i].shell = shell;
461
462 /* store the total number of basis functions */
463 data->num_shells += numshells;
464 i++;
465
466 /* go back one line so that we can read the name of the
467 * next atom */
468 fseek(data->file, filepos, SEEK_SET);
469
470 break;
471
472 }
473
474 } while (!success);
475
476
477 printf("basissetplugin) Parsed %d uncontracted basis functions for %d atoms.\n",
478 data->num_basis_funcs, i);
479
480 data->num_basis_atoms = i;
481
482 /* allocate and populate flat arrays needed for molfileplugin */
483 return fill_basis_arrays(data);
484 }
485
486
487 /**************************************************
488 *
489 * Convert shell type from char to int.
490 *
491 ************************************************ */
shelltype_int(char type)492 static int shelltype_int(char type) {
493 int shelltype;
494
495 switch (type) {
496 case 'L':
497 shelltype = SP_S_SHELL;
498 break;
499 case 'M':
500 shelltype = SP_P_SHELL;
501 break;
502 case 'S':
503 shelltype = S_SHELL;
504 break;
505 case 'P':
506 shelltype = P_SHELL;
507 break;
508 case 'D':
509 shelltype = D_SHELL;
510 break;
511 case 'F':
512 shelltype = F_SHELL;
513 break;
514 case 'G':
515 shelltype = G_SHELL;
516 break;
517 default:
518 shelltype = UNK_SHELL;
519 break;
520 }
521
522 return shelltype;
523 }
524
525
526
527 /******************************************************
528 *
529 * Populate the flat arrays containing the basis
530 * set data.
531 *
532 ******************************************************/
fill_basis_arrays(qmdata_t * data)533 static int fill_basis_arrays(qmdata_t *data) {
534 int i, j, k;
535 int shellcount = 0;
536 int primcount = 0;
537 float *basis;
538 int *num_shells_per_atom;
539 int *num_prim_per_shell;
540 int *shell_types;
541 int *atomicnum_per_basisatom;
542
543 /* Count the total number of primitives which
544 * determines the size of the basis array. */
545 for(i=0; i<data->num_basis_atoms; i++) {
546 for (j=0; j<data->basis_set[i].numshells; j++) {
547 primcount += data->basis_set[i].shell[j].numprims;
548 }
549 }
550
551 /* reserve space for pointer to array containing basis
552 * info, i.e. contraction coeficients and expansion
553 * coefficients; need 2 entries per basis function, i.e.
554 * exponent and contraction coefficient; also,
555 * allocate space for the array holding the orbital symmetry
556 * information per primitive Gaussian.
557 * Finally, initialize the arrays holding the number of
558 * shells per atom and the number of primitives per shell*/
559 basis = (float *)calloc(2*primcount,sizeof(float));
560
561 /* make sure memory was allocated properly */
562 if (basis == NULL) {
563 PRINTERR;
564 return MOLFILE_ERROR;
565 }
566
567 shell_types = (int *)calloc(data->num_shells, sizeof(int));
568
569 /* make sure memory was allocated properly */
570 if (shell_types == NULL) {
571 PRINTERR;
572 return MOLFILE_ERROR;
573 }
574
575 num_shells_per_atom = (int *)calloc(data->num_basis_atoms, sizeof(int));
576
577 /* make sure memory was allocated properly */
578 if (num_shells_per_atom == NULL) {
579 PRINTERR;
580 return MOLFILE_ERROR;
581 }
582
583 num_prim_per_shell = (int *)calloc(data->num_shells, sizeof(int));
584
585 /* make sure memory was allocated properly */
586 if (num_prim_per_shell == NULL) {
587 PRINTERR;
588 return MOLFILE_ERROR;
589 }
590
591 atomicnum_per_basisatom = (int *)calloc(data->num_basis_atoms, sizeof(int));
592
593 /* make sure memory was allocated properly */
594 if (atomicnum_per_basisatom == NULL) {
595 PRINTERR;
596 return MOLFILE_ERROR;
597 }
598
599
600 /* store pointers in struct qmdata_t */
601 data->basis = basis;
602 data->shell_types = shell_types;
603 data->num_shells_per_atom = num_shells_per_atom;
604 data->num_prim_per_shell = num_prim_per_shell;
605 data->atomicnum_per_basisatom = atomicnum_per_basisatom;
606
607 primcount = 0;
608 for (i=0; i<data->num_basis_atoms; i++) {
609 int j;
610 /* assign atomic number from element name */
611 data->basis_set[i].atomicnum = 0;
612 for (j=0; j<NUM_ELEMENTS; j++) {
613 if (!strcmp(elements[j], data->basis_set[i].name)) {
614 data->basis_set[i].atomicnum = j;
615 break;
616 }
617 }
618 atomicnum_per_basisatom[i] = data->basis_set[i].atomicnum;
619
620 num_shells_per_atom[i] = data->basis_set[i].numshells;
621
622 for (j=0; j<data->basis_set[i].numshells; j++) {
623 shell_types[shellcount] = data->basis_set[i].shell[j].type;
624 num_prim_per_shell[shellcount] = data->basis_set[i].shell[j].numprims;
625
626 for (k=0; k<data->basis_set[i].shell[j].numprims; k++) {
627 basis[2*primcount ] = data->basis_set[i].shell[j].prim[k].exponent;
628 basis[2*primcount+1] = data->basis_set[i].shell[j].prim[k].contraction_coeff;
629 primcount++;
630 }
631 shellcount++;
632 }
633 }
634
635 return TRUE;
636 }
637
638
639 /******************************************************
640 *
641 * read all primitives for the current shell
642 *
643 ******************************************************/
read_shell_primitives(qmdata_t * data,prim_t ** prim,char * shelltype,int icoeff)644 static int read_shell_primitives(qmdata_t *data, prim_t **prim, char *shelltype,
645 int icoeff) {
646 char buffer[BUFSIZ];
647 float exponent = 0.0;
648 float contract[2] = {0.0, 0.0};
649 int i, success;
650 int primcounter = 0, nprim = 0;;
651
652 GET_LINE(buffer, data->file);
653 success = sscanf(buffer,"%c %d", shelltype, &nprim);
654
655 (*prim) = (prim_t*)calloc(nprim, sizeof(prim_t));
656
657 for (i=0; i<nprim; i++) {
658 GET_LINE(buffer, data->file);
659 success = sscanf(buffer,"%*d %f %f %f",
660 &exponent, &contract[0], &contract[1]);
661
662 /* store in basis array and increase the counter */
663 switch (success) {
664 case 2:
665 /* store exponent */
666 (*prim)[i].exponent = exponent;
667
668 /* store coefficient */
669 (*prim)[i].contraction_coeff = contract[0];
670
671 primcounter++;
672 break;
673
674 case 3:
675 /* store exponent */
676 (*prim)[i].exponent = exponent;
677
678 /* store coefficient */
679 (*prim)[i].contraction_coeff = contract[icoeff];
680
681 primcounter++;
682 break;
683
684 case -1:
685 /* otherwise it's an empty line which represents the end of the shell */
686 break;
687
688 case 1:
689 /* the user had given the next atom a numeric name */
690 break;
691 }
692
693 }
694
695 if (!primcounter) free(*prim);
696
697 return primcounter;
698 }
699
700
701
702
703 /*************************************************************
704 *
705 * plugin registration
706 *
707 **************************************************************/
708 static molfile_plugin_t plugin;
709
VMDPLUGIN_init(void)710 VMDPLUGIN_API int VMDPLUGIN_init(void) {
711 memset(&plugin, 0, sizeof(molfile_plugin_t));
712 plugin.abiversion = vmdplugin_ABIVERSION;
713 plugin.type = MOLFILE_PLUGIN_TYPE;
714 plugin.name = "basisset";
715 plugin.prettyname = "Basis Set";
716 plugin.author = "Jan Saam";
717 plugin.majorv = 0;
718 plugin.minorv = 1;
719 plugin.is_reentrant = VMDPLUGIN_THREADUNSAFE;
720 plugin.filename_extension = "basis";
721 plugin.open_file_read = open_basis_read;
722 plugin.close_file_read = close_basis_read;
723 plugin.read_structure = NULL;
724
725 plugin.read_qm_metadata = read_basis_metadata;
726 plugin.read_qm_rundata = read_basis_rundata;
727
728 #if vmdplugin_ABIVERSION > 11
729 plugin.read_timestep_metadata = NULL;
730 plugin.read_qm_timestep_metadata = NULL;
731 plugin.read_timestep = NULL;
732 #endif
733
734 return VMDPLUGIN_SUCCESS;
735 }
736
VMDPLUGIN_register(void * v,vmdplugin_register_cb cb)737 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
738 (*cb)(v, (vmdplugin_t *)&plugin);
739 return VMDPLUGIN_SUCCESS;
740 }
741
VMDPLUGIN_fini(void)742 VMDPLUGIN_API int VMDPLUGIN_fini(void) {
743 return VMDPLUGIN_SUCCESS;
744 }
745