4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * Gnomes, ROck Monsters And Chili Sauce
34 #include <libxml/parser.h>
35 #include <libxml/tree.h>
49 static const char *xyz_names
[] = {
52 static const char *tensor_names
[] = {
53 "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz"
57 int nx
,nv
,nf
,ntop
,nbox
,ninprec
;
71 static const char *xmltypes
[] = {
76 "XML_CDATA_SECTION_NODE",
77 "XML_ENTITY_REF_NODE",
82 "XML_DOCUMENT_TYPE_NODE",
83 "XML_DOCUMENT_FRAG_NODE",
85 "XML_HTML_DOCUMENT_NODE",
94 #define NXMLTYPES asize(xmltypes)
96 extern int xmlDoValidityCheckingDefaultValue
;
100 exmlINPUTREC
, exmlOUTPUT
, exmlCOUPLING
, exmlCUTOFF
,
101 exmlPMEPARM
, exmlTCOUPLING
, exmlPCOUPLING
, exmlTCPARM
,
102 exmlREFPRES
, exmlCOMPRESS
, exmlRVEC
,
103 exmlSYSTEM
, exmlCOMPOSITION
, exmlMOLECULE
, exmlATOM
,
104 exmlTOPOLOGY
, exmlBONDS
, exmlANGLES
, exmlDIHEDRALS
,
105 exmlFORCEFIELD
, exmlMASSTYPE
, exmlBOX
,
106 exmlCOORDINATES
, exmlVELOCITIES
, exmlFORCES
, exmlNR
109 static const char *exml_names
[] = {
112 "parameters", "output", "coupling", "cutoff", "pmeparm",
113 "tcoupling", "pcoupling", "tcparm", "p-ref", "compressibility", "rvec",
114 /* System description */
115 "system", "composition", "molecule","atom",
116 /* Topology description */
118 "bonds", "angles", "dihedrals",
120 "forcefield", "masstype", "cell",
121 /* Coordinates etc. */
122 "coordinates", "velocities", "forces"
125 static int find_elem(char *name
,int nr
,char *names
[])
129 for(i
=0; (i
<nr
); i
++)
130 if (strcmp(name
,names
[i
]) == 0)
133 fatal_error(0,"Unknown element name %s",name
);
138 static char *sp(int n
, char buf
[], int maxindent
)
144 /* Don't indent more than maxindent characters */
152 static void process_attr(FILE *fp
,xmlAttrPtr attr
,int elem
,
153 int indent
,t_xmlrec
*xml
)
155 char *attrname
,*attrval
;
158 while (attr
!= NULL
) {
159 attrname
= (char *)attr
->name
;
160 attrval
= (char *)attr
->children
->content
;
162 #define atest(s) ((strcmp(attrname,s) == 0) && (attrval != NULL))
166 xml
->top
->name
= put_symtab(&xml
->top
->symtab
,attrval
);
169 if (atest("algorithm"))
170 xml
->ir
->eI
= find_elem(attrval
,eiNR
,ei_names
);
183 case exmlCOMPOSITION
:
192 case exmlCOORDINATES
:
197 fprintf(fp
,"%sProperty: '%s' Value: '%s'\n",sp(indent
,buf
,99),
205 static void process_tree(FILE *fp
,xmlNodePtr tree
,int indent
,t_xmlrec
*xml
)
210 while (tree
!= NULL
) {
211 switch (tree
->type
) {
212 case XML_ELEMENT_NODE
:
213 elem
= find_elem((char *)tree
->name
,exmlNR
,exml_names
);
215 fprintf(fp
,"%sElement node name %s\n",sp(indent
,buf
,99),(char *)tree
->name
);
217 process_attr(fp
,tree
->properties
,elem
,indent
+2,xml
);
220 process_tree(fp
,tree
->children
,indent
+2,xml
);
222 case XML_COMMENT_NODE
:
224 fprintf(fp
,"Comment node encountered\n");
228 /* Silently ignore these for now */
232 if ((tree
->type
> 0) && (tree
->type
< NXMLTYPES
))
233 fprintf(fp
,"Node type %s encountered with name %s\n",
234 xmltypes
[tree
->type
],(char *)tree
->name
);
236 fprintf(fp
,"Node type %d encountered\n",tree
->type
);
243 void read_xml(char *fn
,int *step
,real
*t
,real
*lambda
,
244 t_inputrec
*ir
,rvec
*box
,int *natoms
,
245 rvec
**x
,rvec
**v
,rvec
**f
,t_topology
*top
)
250 xmlDoValidityCheckingDefaultValue
= 1;
251 assert(asize(exml_names
) == exmlNR
);
252 if ((doc
= xmlParseFile(fn
)) == NULL
)
253 fatal_error(0,"Reading XML file %s. Run a syntax checker such as nsgmls.",
260 process_tree(debug
,doc
->children
,0,xml
);
266 static void add_xml_int(xmlNodePtr ptr
,char *name
,int val
)
269 sprintf(buf
,"%d",val
);
270 if (xmlSetProp(ptr
,name
,buf
) == 0)
271 fatal_error(0,"Setting %s %d",name
,val
);
274 static void add_xml_real(xmlNodePtr ptr
,char *name
,real val
)
277 sprintf(buf
,"%g",val
);
278 if (xmlSetProp(ptr
,name
,buf
) == 0)
279 fatal_error(0,"Setting %s %f",name
,val
);
282 static void add_xml_rvec(xmlNodePtr parent
,int id
,rvec val
)
287 if ((rvptr
= xmlNewChild(parent
,NULL
,"rvec",NULL
)) == NULL
)
288 fatal_error(0,"Creating rvec element");
289 add_xml_int(rvptr
,"id",id
);
290 for(m
=0; (m
<DIM
); m
++)
291 if (xmlSetProp(rvptr
,xyz_names
[m
],dtoa(val
[m
])) == 0)
292 fatal_error(0,"Setting %s %f",xyz_names
[m
],val
[m
]);
295 static void add_xml_tensor(xmlNodePtr parent
,tensor val
)
300 if ((tptr
= xmlNewChild(parent
,NULL
,"tensor",NULL
)) == NULL
)
301 fatal_error(0,"Creating tensor element");
303 for(m
=0; (m
<DIM
); m
++)
304 add_xml_real(tptr
,tensor_names
[m
*DIM
+m
],val
[m
][m
]);
305 if ((val
[XX
][YY
] != 0) || (val
[XX
][ZZ
] != 0) ||
306 (val
[YY
][XX
] != 0) || (val
[YY
][ZZ
] != 0) ||
307 (val
[ZZ
][XX
] != 0) || (val
[ZZ
][YY
] != 0)) {
308 for(m
=0; (m
<DIM
); m
++)
309 for(n
=0; (n
<DIM
); n
++)
311 add_xml_real(tptr
,tensor_names
[m
*DIM
+n
],val
[m
][n
]);
315 static void add_xml_char(xmlNodePtr ptr
,char *name
,char *val
)
317 if (xmlSetProp(ptr
,name
,val
) == 0)
318 fatal_error(0,"Setting %s %s",name
,val
);
321 static xmlNodePtr
add_xml_child(xmlNodePtr parent
,int type
)
325 if ((child
= xmlNewChild(parent
,NULL
,exml_names
[type
],NULL
)) == NULL
)
326 fatal_error(0,"Creating %s element",exml_names
[type
]);
331 static xmlNodePtr
add_xml_comment(xmlDocPtr doc
,
332 xmlNodePtr prev
,char *comment
)
336 if ((comm
= xmlNewComment((xmlChar
*)comment
)) == NULL
)
337 fatal_error(0,"Creating doc comment element");
339 while (ptr
->next
!= NULL
)
348 static void add_xml_inputrec(xmlNodePtr parent
,t_inputrec
*ir
,t_atoms
*atoms
)
351 xmlNodePtr irptr
,outputptr
,tcptr
,tcparm
,pcptr
,refpres
,compress
;
352 xmlNodePtr cutoffptr
,pmeptr
;
354 irptr
= add_xml_child(parent
,exmlINPUTREC
);
355 add_xml_char(irptr
,"algorithm",ei_names
[ir
->eI
]);
356 add_xml_int(irptr
,"nsteps",ir
->nsteps
);
357 add_xml_real(irptr
,"init-t",ir
->init_t
);
358 add_xml_real(irptr
,"delta-t",ir
->delta_t
);
360 outputptr
= add_xml_child(irptr
,exmlOUTPUT
);
361 add_xml_int(outputptr
,"log",ir
->nstlog
);
362 add_xml_int(outputptr
,"x-trr",ir
->nstxout
);
363 add_xml_int(outputptr
,"v-trr",ir
->nstvout
);
364 add_xml_int(outputptr
,"f-trr",ir
->nstfout
);
365 add_xml_int(outputptr
,"energy",ir
->nstenergy
);
366 add_xml_int(outputptr
,"x-xtc",ir
->nstxtcout
);
367 add_xml_int(outputptr
,"xtc-precision",ir
->xtcprec
);
368 add_xml_int(outputptr
,"andersen_seed",ir
->andersen_seed
);
370 tcptr
= add_xml_child(irptr
,exmlTCOUPLING
);
371 add_xml_char(tcptr
,"algorithm",etcoupl_names
[ir
->etc
]);
372 add_xml_char(tcptr
,"annealing",yesno_names
[ir
->bSimAnn
]);
373 add_xml_real(tcptr
,"annealtime",ir
->zero_temp_time
);
375 assert(ir
->opts
.ngtc
== atoms
->grps
[egcTC
].nr
);
376 for(i
=0; (i
<ir
->opts
.ngtc
); i
++) {
377 tcparm
= add_xml_child(tcptr
,exmlTCPARM
);
378 add_xml_char(tcparm
,"groupname",*atoms
->grpname
[atoms
->grps
[egcTC
].nm_ind
[i
]]);
379 add_xml_real(tcparm
,"t-ref",ir
->opts
.ref_t
[i
]);
380 add_xml_real(tcparm
,"tau-t",ir
->opts
.tau_t
[i
]);
383 pcptr
= add_xml_child(irptr
,exmlPCOUPLING
);
384 add_xml_char(pcptr
,"algorithm",epcoupl_names
[ir
->epc
]);
385 add_xml_char(pcptr
,"type",epcoupltype_names
[ir
->epct
]);
386 add_xml_real(pcptr
,"tau-p",ir
->tau_p
);
388 refpres
= add_xml_child(pcptr
,exmlREFPRES
);
389 add_xml_tensor(refpres
,ir
->ref_p
);
391 compress
= add_xml_child(pcptr
,exmlCOMPRESS
);
392 add_xml_tensor(compress
,ir
->compress
);
394 cutoffptr
= add_xml_child(irptr
,exmlCUTOFF
);
395 add_xml_real(cutoffptr
,"rlist",ir
->rlist
);
396 add_xml_real(cutoffptr
,"rvdw",ir
->rvdw
);
397 add_xml_real(cutoffptr
,"rcoulomb",ir
->rcoulomb
);
398 add_xml_real(cutoffptr
,"rcoulswitch",ir
->rcoulomb_switch
);
399 add_xml_real(cutoffptr
,"rvdwswitch",ir
->rvdw_switch
);
400 add_xml_real(cutoffptr
,"epsilonr",ir
->epsilon_r
);
401 add_xml_int(cutoffptr
,"nstlist",ir
->nstlist
);
402 add_xml_char(cutoffptr
,"nstype",ens_names
[ir
->ns_type
]);
403 add_xml_char(cutoffptr
,"domdecomp",yesno_names
[ir
->bDomDecomp
]);
404 add_xml_char(cutoffptr
,"decompdir",xyz_names
[ir
->decomp_dir
]);
405 add_xml_char(cutoffptr
,"coulombtype",eel_names
[ir
->coulombtype
]);
406 add_xml_char(cutoffptr
,"vdwtype",evdw_names
[ir
->vdwtype
]);
407 if (ir
->coulombtype
== eelPME
) {
408 pmeptr
= add_xml_child(cutoffptr
,exmlPMEPARM
);
409 add_xml_int(pmeptr
,"nkx",ir
->nkx
);
410 add_xml_int(pmeptr
,"nky",ir
->nky
);
411 add_xml_int(pmeptr
,"nkz",ir
->nkz
);
412 add_xml_int(pmeptr
,"pmeorder",ir
->pme_order
);
413 add_xml_real(pmeptr
,"ewaldrtol",ir
->ewald_rtol
);
414 add_xml_real(pmeptr
,"epssurface",ir
->epsilon_surface
);
415 add_xml_char(pmeptr
,"optfft",yesno_names
[ir
->bOptFFT
]);
419 static void add_xml_molecule(xmlNodePtr parent
,t_atoms
*atoms
,
420 int nmt
,t_masstype mt
[])
424 ptr
= add_xml_child(parent
,exmlMOLECULE
);
427 static void add_xml_idef(xmlNodePtr parent
,t_idef
*idef
)
432 static void add_xml_rvecs(xmlNodePtr parent
,int type
,int natoms
,rvec
*xvf
)
437 xptr
= add_xml_child(parent
,type
);
438 for(i
=0; (i
<natoms
); i
++)
439 add_xml_rvec(xptr
,i
+1,xvf
[i
]);
442 static t_masstype
*mk_masstype(int nmol
,t_atoms atoms
[],int *nmt
)
448 for(i
=0; (i
<nmol
); i
++) {
449 for(j
=0; (j
<atoms
[i
].nr
); j
++) {
450 for(k
=0; (k
<nm
); k
++)
451 if (strcmp(*atoms
[i
].atomname
[j
],mt
[k
].name
) == 0)
455 mt
[nm
].name
= strdup(*atoms
[i
].atomname
[j
]);
456 mt
[nm
].value
= atoms
[i
].atom
[j
].m
;
466 static void add_xml_masstype(xmlNodePtr parent
,int nmt
,t_masstype mt
[])
471 for(i
=0; (i
<nmt
); i
++) {
472 ptr
= add_xml_child(parent
,exmlMASSTYPE
);
473 add_xml_char(ptr
,"name",mt
[i
].name
);
474 add_xml_real(ptr
,"value",mt
[i
].value
);
478 void write_xml(char *fn
,char *title
,t_inputrec
*ir
,rvec
*box
,
479 int natoms
,rvec
*x
,rvec
*v
,rvec
*f
,
480 int nmol
,t_atoms atoms
[],t_idef
*idef
)
487 char *libdtdname
,*dtdname
;
489 dtdname
= "gromacs.dtd";
490 libdtdname
= libfn(dtdname
);
492 if ((doc
= xmlNewDoc("1.0")) == NULL
)
493 fatal_error(0,"Creating XML document");
495 if ((dtd
= xmlCreateIntSubset(doc
,"gromacs",libdtdname
,dtdname
)) == NULL
)
496 fatal_error(0,"Creating XML DTD");
498 if ((myroot
= xmlNewDocNode(doc
,NULL
,"gromacs",NULL
)) == NULL
)
499 fatal_error(0,"Creating root element");
501 myroot
->prev
= (xmlNodePtr
) dtd
;
503 /* Title of the system */
505 add_xml_char(myroot
,"title",title
);
509 xmlNodePtr ptr
= myroot
;
510 while(ptr
->next
!= NULL
)
512 ptr
->next
= xmlNewDocComment(doc
,(xmlChar
*)"Here starts parameter section");
513 ptr
->next
->prev
= ptr
;
514 fprintf(stderr
,"Comment type is %s\n",xmltypes
[ptr
->next
->type
]);
516 add_xml_inputrec(myroot
,ir
,&atoms
[0]);
518 /* Generate masstypes */
519 mt
= mk_masstype(nmol
,atoms
,&nmt
);
520 add_xml_masstype(myroot
,nmt
,mt
);
522 /* Add molecule definitions */
523 for(i
=0; (i
<nmol
); i
++)
524 add_xml_molecule(myroot
,&(atoms
[i
]),nmt
,mt
);
526 /* Add force field */
528 add_xml_idef(myroot
,idef
);
532 add_xml_tensor(add_xml_child(myroot
,exmlBOX
),box
);
536 add_xml_rvecs(myroot
,exmlCOORDINATES
,natoms
,x
);
540 add_xml_rvecs(myroot
,exmlVELOCITIES
,natoms
,v
);
544 add_xml_rvecs(myroot
,exmlFORCES
,natoms
,f
);
546 xmlSetDocCompressMode(doc
,0);
547 xmlIndentTreeOutput
= 1;
548 if (xmlSaveFormatFileEnc(fn
,doc
,"ISO-8859-1",2) == 0)
549 fatal_error(0,"Saving file %s",fn
);