4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
39 #include <libxml/parser.h>
40 #include <libxml/tree.h>
52 static const char *xyz_names
[] = {
55 static const char *tensor_names
[] = {
56 "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz"
60 int nx
,nv
,nf
,ntop
,nbox
,ninprec
;
74 static const char *xmltypes
[] = {
79 "XML_CDATA_SECTION_NODE",
80 "XML_ENTITY_REF_NODE",
85 "XML_DOCUMENT_TYPE_NODE",
86 "XML_DOCUMENT_FRAG_NODE",
88 "XML_HTML_DOCUMENT_NODE",
97 #define NXMLTYPES asize(xmltypes)
99 extern int xmlDoValidityCheckingDefaultValue
;
103 exmlINPUTREC
, exmlOUTPUT
, exmlCOUPLING
, exmlCUTOFF
,
104 exmlPMEPARM
, exmlTCOUPLING
, exmlPCOUPLING
, exmlTCPARM
,
105 exmlREFPRES
, exmlCOMPRESS
, exmlRVEC
,
106 exmlSYSTEM
, exmlCOMPOSITION
, exmlMOLECULE
, exmlATOM
,
107 exmlTOPOLOGY
, exmlBONDS
, exmlANGLES
, exmlDIHEDRALS
,
108 exmlFORCEFIELD
, exmlMASSTYPE
, exmlBOX
,
109 exmlCOORDINATES
, exmlVELOCITIES
, exmlFORCES
, exmlNR
112 static const char *exml_names
[] = {
115 "parameters", "output", "coupling", "cutoff", "pmeparm",
116 "tcoupling", "pcoupling", "tcparm", "p-ref", "compressibility", "rvec",
117 /* System description */
118 "system", "composition", "molecule","atom",
119 /* Topology description */
121 "bonds", "angles", "dihedrals",
123 "forcefield", "masstype", "cell",
124 /* Coordinates etc. */
125 "coordinates", "velocities", "forces"
128 static int find_elem(char *name
,int nr
,const char *names
[])
132 for(i
=0; (i
<nr
); i
++)
133 if (strcmp(name
,names
[i
]) == 0)
136 fatal_error(0,"Unknown element name %s",name
);
141 static char *sp(int n
, char buf
[], int maxindent
)
147 /* Don't indent more than maxindent characters */
155 static void process_attr(FILE *fp
,xmlAttrPtr attr
,int elem
,
156 int indent
,t_xmlrec
*xml
)
158 char *attrname
,*attrval
;
161 while (attr
!= NULL
) {
162 attrname
= (char *)attr
->name
;
163 attrval
= (char *)attr
->children
->content
;
165 #define atest(s) ((strcmp(attrname,s) == 0) && (attrval != NULL))
169 xml
->top
->name
= put_symtab(&xml
->top
->symtab
,attrval
);
172 if (atest("algorithm"))
173 xml
->ir
->eI
= find_elem(attrval
,eiNR
,ei_names
);
186 case exmlCOMPOSITION
:
195 case exmlCOORDINATES
:
200 fprintf(fp
,"%sProperty: '%s' Value: '%s'\n",sp(indent
,buf
,99),
208 static void process_tree(FILE *fp
,xmlNodePtr tree
,int indent
,t_xmlrec
*xml
)
213 while (tree
!= NULL
) {
214 switch (tree
->type
) {
215 case XML_ELEMENT_NODE
:
216 elem
= find_elem((char *)tree
->name
,exmlNR
,exml_names
);
218 fprintf(fp
,"%sElement node name %s\n",sp(indent
,buf
,99),(char *)tree
->name
);
220 process_attr(fp
,tree
->properties
,elem
,indent
+2,xml
);
223 process_tree(fp
,tree
->children
,indent
+2,xml
);
225 case XML_COMMENT_NODE
:
227 fprintf(fp
,"Comment node encountered\n");
231 /* Silently ignore these for now */
235 if ((tree
->type
> 0) && (tree
->type
< NXMLTYPES
))
236 fprintf(fp
,"Node type %s encountered with name %s\n",
237 xmltypes
[tree
->type
],(char *)tree
->name
);
239 fprintf(fp
,"Node type %d encountered\n",tree
->type
);
246 void read_xml(char *fn
,int *step
,real
*t
,real
*lambda
,
247 t_inputrec
*ir
,rvec
*box
,int *natoms
,
248 rvec
**x
,rvec
**v
,rvec
**f
,t_topology
*top
)
253 xmlDoValidityCheckingDefaultValue
= 1;
254 assert(asize(exml_names
) == exmlNR
);
255 if ((doc
= xmlParseFile(fn
)) == NULL
)
256 fatal_error(0,"Reading XML file %s. Run a syntax checker such as nsgmls.",
263 process_tree(debug
,doc
->children
,0,xml
);
269 static void add_xml_int(xmlNodePtr ptr
,const char *name
,int val
)
272 sprintf(buf
,"%d",val
);
273 if (xmlSetProp(ptr
,name
,buf
) == 0)
274 fatal_error(0,"Setting %s %d",name
,val
);
277 static void add_xml_real(xmlNodePtr ptr
,const char *name
,real val
)
280 sprintf(buf
,"%g",val
);
281 if (xmlSetProp(ptr
,name
,buf
) == 0)
282 fatal_error(0,"Setting %s %f",name
,val
);
285 static void add_xml_rvec(xmlNodePtr parent
,int id
,rvec val
)
291 if ((rvptr
= xmlNewChild(parent
,NULL
,"rvec",NULL
)) == NULL
)
292 fatal_error(0,"Creating rvec element");
293 add_xml_int(rvptr
,"id",id
);
294 for(m
=0; (m
<DIM
); m
++) {
295 sprintf(buf
,"%g",val
[m
]);
296 if (xmlSetProp(rvptr
,xyz_names
[m
],buf
) == 0)
297 fatal_error(0,"Setting %s %f",xyz_names
[m
],val
[m
]);
301 static void add_xml_tensor(xmlNodePtr parent
,tensor val
)
306 if ((tptr
= xmlNewChild(parent
,NULL
,"tensor",NULL
)) == NULL
)
307 fatal_error(0,"Creating tensor element");
309 for(m
=0; (m
<DIM
); m
++)
310 add_xml_real(tptr
,tensor_names
[m
*DIM
+m
],val
[m
][m
]);
311 if ((val
[XX
][YY
] != 0) || (val
[XX
][ZZ
] != 0) ||
312 (val
[YY
][XX
] != 0) || (val
[YY
][ZZ
] != 0) ||
313 (val
[ZZ
][XX
] != 0) || (val
[ZZ
][YY
] != 0)) {
314 for(m
=0; (m
<DIM
); m
++)
315 for(n
=0; (n
<DIM
); n
++)
317 add_xml_real(tptr
,tensor_names
[m
*DIM
+n
],val
[m
][n
]);
321 static void add_xml_char(xmlNodePtr ptr
,const char *name
,const char *val
)
323 if (xmlSetProp(ptr
,name
,val
) == 0)
324 fatal_error(0,"Setting %s %s",name
,val
);
327 static xmlNodePtr
add_xml_child(xmlNodePtr parent
,int type
)
331 if ((child
= xmlNewChild(parent
,NULL
,exml_names
[type
],NULL
)) == NULL
)
332 fatal_error(0,"Creating %s element",exml_names
[type
]);
337 static xmlNodePtr
add_xml_comment(xmlDocPtr doc
,
338 xmlNodePtr prev
,char *comment
)
342 if ((comm
= xmlNewComment((xmlChar
*)comment
)) == NULL
)
343 fatal_error(0,"Creating doc comment element");
345 while (ptr
->next
!= NULL
)
354 static void add_xml_inputrec(xmlNodePtr parent
,t_inputrec
*ir
,t_atoms
*atoms
)
357 xmlNodePtr irptr
,outputptr
,tcptr
,tcparm
,pcptr
,refpres
,compress
;
358 xmlNodePtr cutoffptr
,pmeptr
;
360 irptr
= add_xml_child(parent
,exmlINPUTREC
);
361 add_xml_char(irptr
,"algorithm",ei_names
[ir
->eI
]);
362 add_xml_int(irptr
,"nsteps",ir
->nsteps
);
363 add_xml_real(irptr
,"init-t",ir
->init_t
);
364 add_xml_real(irptr
,"delta-t",ir
->delta_t
);
366 outputptr
= add_xml_child(irptr
,exmlOUTPUT
);
367 add_xml_int(outputptr
,"log",ir
->nstlog
);
368 add_xml_int(outputptr
,"x-trr",ir
->nstxout
);
369 add_xml_int(outputptr
,"v-trr",ir
->nstvout
);
370 add_xml_int(outputptr
,"f-trr",ir
->nstfout
);
371 add_xml_int(outputptr
,"energy",ir
->nstenergy
);
372 add_xml_int(outputptr
,"x-xtc",ir
->nstxtcout
);
373 add_xml_int(outputptr
,"xtc-precision",ir
->xtcprec
);
374 add_xml_int(outputptr
,"andersen_seed",ir
->andersen_seed
);
376 tcptr
= add_xml_child(irptr
,exmlTCOUPLING
);
377 add_xml_char(tcptr
,"algorithm",etcoupl_names
[ir
->etc
]);
379 assert(ir
->opts
.ngtc
== atoms
->grps
[egcTC
].nr
);
380 for(i
=0; (i
<ir
->opts
.ngtc
); i
++) {
381 tcparm
= add_xml_child(tcptr
,exmlTCPARM
);
382 add_xml_char(tcparm
,"groupname",*atoms
->grpname
[atoms
->grps
[egcTC
].nm_ind
[i
]]);
383 add_xml_real(tcparm
,"t-ref",ir
->opts
.ref_t
[i
]);
384 add_xml_real(tcparm
,"tau-t",ir
->opts
.tau_t
[i
]);
387 pcptr
= add_xml_child(irptr
,exmlPCOUPLING
);
388 add_xml_char(pcptr
,"algorithm",epcoupl_names
[ir
->epc
]);
389 add_xml_char(pcptr
,"type",epcoupltype_names
[ir
->epct
]);
390 add_xml_real(pcptr
,"tau-p",ir
->tau_p
);
392 refpres
= add_xml_child(pcptr
,exmlREFPRES
);
393 add_xml_tensor(refpres
,ir
->ref_p
);
395 compress
= add_xml_child(pcptr
,exmlCOMPRESS
);
396 add_xml_tensor(compress
,ir
->compress
);
398 cutoffptr
= add_xml_child(irptr
,exmlCUTOFF
);
399 add_xml_real(cutoffptr
,"rlist",ir
->rlist
);
400 add_xml_real(cutoffptr
,"rvdw",ir
->rvdw
);
401 add_xml_real(cutoffptr
,"rcoulomb",ir
->rcoulomb
);
402 add_xml_real(cutoffptr
,"rcoulswitch",ir
->rcoulomb_switch
);
403 add_xml_real(cutoffptr
,"rvdwswitch",ir
->rvdw_switch
);
404 add_xml_real(cutoffptr
,"epsilonr",ir
->epsilon_r
);
405 add_xml_int(cutoffptr
,"nstlist",ir
->nstlist
);
406 add_xml_char(cutoffptr
,"nstype",ens_names
[ir
->ns_type
]);
407 add_xml_char(cutoffptr
,"domdecomp",yesno_names
[ir
->bDomDecomp
]);
408 add_xml_char(cutoffptr
,"decompdir",xyz_names
[ir
->decomp_dir
]);
409 add_xml_char(cutoffptr
,"coulombtype",eel_names
[ir
->coulombtype
]);
410 add_xml_char(cutoffptr
,"vdwtype",evdw_names
[ir
->vdwtype
]);
411 if (ir
->coulombtype
== eelPME
) {
412 pmeptr
= add_xml_child(cutoffptr
,exmlPMEPARM
);
413 add_xml_int(pmeptr
,"nkx",ir
->nkx
);
414 add_xml_int(pmeptr
,"nky",ir
->nky
);
415 add_xml_int(pmeptr
,"nkz",ir
->nkz
);
416 add_xml_int(pmeptr
,"pmeorder",ir
->pme_order
);
417 add_xml_real(pmeptr
,"ewaldrtol",ir
->ewald_rtol
);
418 add_xml_real(pmeptr
,"epssurface",ir
->epsilon_surface
);
419 add_xml_char(pmeptr
,"optfft",yesno_names
[ir
->bOptFFT
]);
423 static void add_xml_molecule(xmlNodePtr parent
,t_atoms
*atoms
,
424 int nmt
,t_masstype mt
[])
428 ptr
= add_xml_child(parent
,exmlMOLECULE
);
431 static void add_xml_idef(xmlNodePtr parent
,t_idef
*idef
)
436 static void add_xml_rvecs(xmlNodePtr parent
,int type
,int natoms
,rvec
*xvf
)
441 xptr
= add_xml_child(parent
,type
);
442 for(i
=0; (i
<natoms
); i
++)
443 add_xml_rvec(xptr
,i
+1,xvf
[i
]);
446 static t_masstype
*mk_masstype(int nmol
,t_atoms atoms
[],int *nmt
)
452 for(i
=0; (i
<nmol
); i
++) {
453 for(j
=0; (j
<atoms
[i
].nr
); j
++) {
454 for(k
=0; (k
<nm
); k
++)
455 if (strcmp(*atoms
[i
].atomname
[j
],mt
[k
].name
) == 0)
459 mt
[nm
].name
= strdup(*atoms
[i
].atomname
[j
]);
460 mt
[nm
].value
= atoms
[i
].atom
[j
].m
;
470 static void add_xml_masstype(xmlNodePtr parent
,int nmt
,t_masstype mt
[])
475 for(i
=0; (i
<nmt
); i
++) {
476 ptr
= add_xml_child(parent
,exmlMASSTYPE
);
477 add_xml_char(ptr
,"name",mt
[i
].name
);
478 add_xml_real(ptr
,"value",mt
[i
].value
);
482 void write_xml(char *fn
,char *title
,t_inputrec
*ir
,rvec
*box
,
483 int natoms
,rvec
*x
,rvec
*v
,rvec
*f
,
484 int nmol
,t_atoms atoms
[],t_idef
*idef
)
491 char *libdtdname
,*dtdname
;
493 dtdname
= "gromacs.dtd";
494 libdtdname
= libfn(dtdname
);
496 if ((doc
= xmlNewDoc("1.0")) == NULL
)
497 fatal_error(0,"Creating XML document");
499 if ((dtd
= xmlCreateIntSubset(doc
,"gromacs",libdtdname
,dtdname
)) == NULL
)
500 fatal_error(0,"Creating XML DTD");
502 if ((myroot
= xmlNewDocNode(doc
,NULL
,"gromacs",NULL
)) == NULL
)
503 fatal_error(0,"Creating root element");
505 myroot
->prev
= (xmlNodePtr
) dtd
;
507 /* Title of the system */
509 add_xml_char(myroot
,"title",title
);
513 xmlNodePtr ptr
= myroot
;
514 while(ptr
->next
!= NULL
)
516 ptr
->next
= xmlNewDocComment(doc
,(xmlChar
*)"Here starts parameter section");
517 ptr
->next
->prev
= ptr
;
518 fprintf(stderr
,"Comment type is %s\n",xmltypes
[ptr
->next
->type
]);
520 add_xml_inputrec(myroot
,ir
,&atoms
[0]);
522 /* Generate masstypes */
523 mt
= mk_masstype(nmol
,atoms
,&nmt
);
524 add_xml_masstype(myroot
,nmt
,mt
);
526 /* Add molecule definitions */
527 for(i
=0; (i
<nmol
); i
++)
528 add_xml_molecule(myroot
,&(atoms
[i
]),nmt
,mt
);
530 /* Add force field */
532 add_xml_idef(myroot
,idef
);
536 add_xml_tensor(add_xml_child(myroot
,exmlBOX
),box
);
540 add_xml_rvecs(myroot
,exmlCOORDINATES
,natoms
,x
);
544 add_xml_rvecs(myroot
,exmlVELOCITIES
,natoms
,v
);
548 add_xml_rvecs(myroot
,exmlFORCES
,natoms
,f
);
550 xmlSetDocCompressMode(doc
,0);
551 xmlIndentTreeOutput
= 1;
552 if (xmlSaveFormatFileEnc(fn
,doc
,"ISO-8859-1",2) == 0)
553 fatal_error(0,"Saving file %s",fn
);