xref: /petsc/src/sys/objects/optionsyaml.c (revision f996e368d2756f6a7e2df466d998849f46aaf50f)
1*f996e368SLisandro Dalcin #include <petsc/private/petscimpl.h>        /*I  "petscsys.h"   I*/
2*f996e368SLisandro Dalcin #if defined(PETSC_HAVE_YAML)
3*f996e368SLisandro Dalcin #include <yaml.h>
4*f996e368SLisandro Dalcin #endif
5*f996e368SLisandro Dalcin 
6*f996e368SLisandro Dalcin static MPI_Comm petsc_yaml_comm = MPI_COMM_NULL; /* only used for parallel error handling */
7*f996e368SLisandro Dalcin 
8*f996e368SLisandro Dalcin PETSC_STATIC_INLINE MPI_Comm PetscYAMLGetComm(void)
9*f996e368SLisandro Dalcin {
10*f996e368SLisandro Dalcin   return PetscLikely(petsc_yaml_comm != MPI_COMM_NULL) ? petsc_yaml_comm : (petsc_yaml_comm = PETSC_COMM_SELF);
11*f996e368SLisandro Dalcin }
12*f996e368SLisandro Dalcin 
13*f996e368SLisandro Dalcin PETSC_STATIC_INLINE MPI_Comm PetscYAMLSetComm(MPI_Comm comm)
14*f996e368SLisandro Dalcin {
15*f996e368SLisandro Dalcin   MPI_Comm prev = PetscYAMLGetComm(); petsc_yaml_comm = comm; return prev;
16*f996e368SLisandro Dalcin }
17*f996e368SLisandro Dalcin 
18*f996e368SLisandro Dalcin #if defined(PETSC_HAVE_YAML)
19*f996e368SLisandro Dalcin 
20*f996e368SLisandro Dalcin #define TAG(node) ((const char *)((node)->tag))
21*f996e368SLisandro Dalcin #define STR(node) ((const char *)((node)->data.scalar.value))
22*f996e368SLisandro Dalcin #define SEQ(node) ((node)->data.sequence.items)
23*f996e368SLisandro Dalcin #define MAP(node) ((node)->data.mapping.pairs)
24*f996e368SLisandro Dalcin 
25*f996e368SLisandro Dalcin static PetscErrorCode PetscParseLayerYAML(PetscOptions options, yaml_document_t *doc, yaml_node_t *node)
26*f996e368SLisandro Dalcin {
27*f996e368SLisandro Dalcin   MPI_Comm         comm = PetscYAMLGetComm();
28*f996e368SLisandro Dalcin   char             name[PETSC_MAX_OPTION_NAME] = "", prefix[PETSC_MAX_OPTION_NAME] = "";
29*f996e368SLisandro Dalcin   PetscErrorCode   ierr;
30*f996e368SLisandro Dalcin 
31*f996e368SLisandro Dalcin   PetscFunctionBegin;
32*f996e368SLisandro Dalcin   if (node->type != YAML_MAPPING_NODE) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected mapping");
33*f996e368SLisandro Dalcin   for (yaml_node_pair_t *pair = MAP(node).start; pair < MAP(node).top; pair++) {
34*f996e368SLisandro Dalcin     yaml_node_t *keynode = yaml_document_get_node(doc, pair->key);
35*f996e368SLisandro Dalcin     yaml_node_t *valnode = yaml_document_get_node(doc, pair->value);
36*f996e368SLisandro Dalcin     PetscBool   isMergeKey,isDummyKey,isIncludeTag;
37*f996e368SLisandro Dalcin 
38*f996e368SLisandro Dalcin     if (!keynode) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
39*f996e368SLisandro Dalcin     if (!valnode) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
40*f996e368SLisandro Dalcin     if (keynode->type != YAML_SCALAR_NODE) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected scalar");
41*f996e368SLisandro Dalcin 
42*f996e368SLisandro Dalcin     /* "<<" is the merge key: don't increment the prefix */
43*f996e368SLisandro Dalcin     ierr = PetscStrcmp(STR(keynode), "<<", &isMergeKey);CHKERRQ(ierr);
44*f996e368SLisandro Dalcin     if (isMergeKey) {
45*f996e368SLisandro Dalcin       if (valnode->type == YAML_SEQUENCE_NODE) {
46*f996e368SLisandro Dalcin         for (yaml_node_item_t *item = SEQ(valnode).start; item < SEQ(valnode).top; item++) {
47*f996e368SLisandro Dalcin           yaml_node_t *itemnode = yaml_document_get_node(doc, *item);
48*f996e368SLisandro Dalcin           if (!itemnode) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
49*f996e368SLisandro Dalcin           if (itemnode->type != YAML_MAPPING_NODE) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected mapping");
50*f996e368SLisandro Dalcin           ierr = PetscParseLayerYAML(options, doc, itemnode);CHKERRQ(ierr);
51*f996e368SLisandro Dalcin         }
52*f996e368SLisandro Dalcin       } else if (valnode->type == YAML_MAPPING_NODE) {
53*f996e368SLisandro Dalcin         ierr = PetscParseLayerYAML(options, doc, valnode);CHKERRQ(ierr);
54*f996e368SLisandro Dalcin       } else SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected sequence or mapping");
55*f996e368SLisandro Dalcin       continue; /* to next pair */
56*f996e368SLisandro Dalcin     }
57*f996e368SLisandro Dalcin 
58*f996e368SLisandro Dalcin     /* "$$*" are treated as dummy keys, we use them for !include tags and to define anchors */
59*f996e368SLisandro Dalcin     ierr = PetscStrbeginswith(STR(keynode), "$$", &isDummyKey);CHKERRQ(ierr);
60*f996e368SLisandro Dalcin     if (isDummyKey) {
61*f996e368SLisandro Dalcin       ierr = PetscStrendswith(TAG(valnode), "!include", &isIncludeTag);CHKERRQ(ierr);CHKERRQ(ierr);
62*f996e368SLisandro Dalcin       if (isIncludeTag) { /* TODO: add proper support relative paths */
63*f996e368SLisandro Dalcin         ierr = PetscOptionsInsertFileYAML(comm, options, STR(valnode), PETSC_TRUE);CHKERRQ(ierr);
64*f996e368SLisandro Dalcin       }
65*f996e368SLisandro Dalcin       continue; /* to next pair */
66*f996e368SLisandro Dalcin     }
67*f996e368SLisandro Dalcin 
68*f996e368SLisandro Dalcin     if (valnode->type == YAML_SCALAR_NODE) {
69*f996e368SLisandro Dalcin       ierr = PetscSNPrintf(name, sizeof(name), "-%s", STR(keynode));CHKERRQ(ierr);
70*f996e368SLisandro Dalcin       ierr = PetscOptionsSetValue(options, name, STR(valnode));CHKERRQ(ierr);
71*f996e368SLisandro Dalcin 
72*f996e368SLisandro Dalcin     } else if (valnode->type == YAML_SEQUENCE_NODE) {
73*f996e368SLisandro Dalcin       PetscSegBuffer seg;
74*f996e368SLisandro Dalcin       char           *buf, *strlist;
75*f996e368SLisandro Dalcin       PetscBool      addSep = PETSC_FALSE;
76*f996e368SLisandro Dalcin 
77*f996e368SLisandro Dalcin       ierr = PetscSegBufferCreate(sizeof(char), PETSC_MAX_PATH_LEN, &seg);CHKERRQ(ierr);
78*f996e368SLisandro Dalcin       for (yaml_node_item_t *item = SEQ(valnode).start; item < SEQ(valnode).top; item++) {
79*f996e368SLisandro Dalcin         yaml_node_t *itemnode = yaml_document_get_node(doc, *item);
80*f996e368SLisandro Dalcin         const char  *itemstr = NULL;
81*f996e368SLisandro Dalcin         size_t       itemlen;
82*f996e368SLisandro Dalcin 
83*f996e368SLisandro Dalcin         if (!itemnode) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
84*f996e368SLisandro Dalcin 
85*f996e368SLisandro Dalcin         if (itemnode->type == YAML_SCALAR_NODE) {
86*f996e368SLisandro Dalcin           itemstr = STR(itemnode);
87*f996e368SLisandro Dalcin 
88*f996e368SLisandro Dalcin         } else if (itemnode->type == YAML_MAPPING_NODE) {
89*f996e368SLisandro Dalcin           yaml_node_pair_t *kvn = itemnode->data.mapping.pairs.start;
90*f996e368SLisandro Dalcin           yaml_node_pair_t *top = itemnode->data.mapping.pairs.top;
91*f996e368SLisandro Dalcin 
92*f996e368SLisandro Dalcin           if (top - kvn > 1) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node value: expected a single key:value pair");
93*f996e368SLisandro Dalcin           if (top - kvn > 0) {
94*f996e368SLisandro Dalcin             yaml_node_t *kn = yaml_document_get_node(doc, kvn->key);
95*f996e368SLisandro Dalcin             yaml_node_t *vn = yaml_document_get_node(doc, kvn->value);
96*f996e368SLisandro Dalcin 
97*f996e368SLisandro Dalcin             if (!kn) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
98*f996e368SLisandro Dalcin             if (!vn) SETERRQ(comm, PETSC_ERR_LIB, "Corrupt YAML document");
99*f996e368SLisandro Dalcin             if (kn->type != YAML_SCALAR_NODE) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected scalar");
100*f996e368SLisandro Dalcin 
101*f996e368SLisandro Dalcin             ierr = PetscStrcmp(STR(kn), "<<", &isMergeKey);CHKERRQ(ierr);
102*f996e368SLisandro Dalcin             if (isMergeKey) SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node value: merge key '<<' not supported here");
103*f996e368SLisandro Dalcin 
104*f996e368SLisandro Dalcin             ierr = PetscStrbeginswith(STR(kn), "$$", &isDummyKey);CHKERRQ(ierr);
105*f996e368SLisandro Dalcin             if (isDummyKey) continue;
106*f996e368SLisandro Dalcin             itemstr = STR(kn);
107*f996e368SLisandro Dalcin           }
108*f996e368SLisandro Dalcin 
109*f996e368SLisandro Dalcin           ierr = PetscSNPrintf(prefix,sizeof(prefix), "%s_", STR(keynode));CHKERRQ(ierr);
110*f996e368SLisandro Dalcin           ierr = PetscOptionsPrefixPush(options, prefix);CHKERRQ(ierr);
111*f996e368SLisandro Dalcin           ierr = PetscParseLayerYAML(options, doc, itemnode);CHKERRQ(ierr);
112*f996e368SLisandro Dalcin           ierr = PetscOptionsPrefixPop(options);CHKERRQ(ierr);
113*f996e368SLisandro Dalcin 
114*f996e368SLisandro Dalcin         } else SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected scalar or mapping");
115*f996e368SLisandro Dalcin 
116*f996e368SLisandro Dalcin         ierr = PetscStrlen(itemstr, &itemlen);CHKERRQ(ierr);
117*f996e368SLisandro Dalcin         if (itemlen) {
118*f996e368SLisandro Dalcin           if (addSep) {
119*f996e368SLisandro Dalcin             ierr = PetscSegBufferGet(seg, 1, &buf);CHKERRQ(ierr);
120*f996e368SLisandro Dalcin             ierr = PetscArraycpy(buf, ",", 1);CHKERRQ(ierr);
121*f996e368SLisandro Dalcin           }
122*f996e368SLisandro Dalcin           ierr = PetscSegBufferGet(seg, itemlen, &buf);CHKERRQ(ierr);
123*f996e368SLisandro Dalcin           ierr = PetscArraycpy(buf, itemstr, itemlen);CHKERRQ(ierr);
124*f996e368SLisandro Dalcin           addSep = PETSC_TRUE;
125*f996e368SLisandro Dalcin         }
126*f996e368SLisandro Dalcin       }
127*f996e368SLisandro Dalcin       ierr = PetscSegBufferGet(seg, 1, &buf);CHKERRQ(ierr);
128*f996e368SLisandro Dalcin       ierr = PetscArrayzero(buf, 1);CHKERRQ(ierr);
129*f996e368SLisandro Dalcin       ierr = PetscSegBufferExtractAlloc(seg, &strlist);CHKERRQ(ierr);
130*f996e368SLisandro Dalcin       ierr = PetscSegBufferDestroy(&seg);CHKERRQ(ierr);
131*f996e368SLisandro Dalcin 
132*f996e368SLisandro Dalcin       ierr = PetscSNPrintf(name, sizeof(name), "-%s", STR(keynode));CHKERRQ(ierr);
133*f996e368SLisandro Dalcin       ierr = PetscOptionsSetValue(options, name, strlist);CHKERRQ(ierr);
134*f996e368SLisandro Dalcin       ierr = PetscFree(strlist);CHKERRQ(ierr);
135*f996e368SLisandro Dalcin 
136*f996e368SLisandro Dalcin     } else if (valnode->type == YAML_MAPPING_NODE) {
137*f996e368SLisandro Dalcin       ierr = PetscSNPrintf(prefix,sizeof(prefix), "%s_", STR(keynode));CHKERRQ(ierr);
138*f996e368SLisandro Dalcin       ierr = PetscOptionsPrefixPush(options, prefix);CHKERRQ(ierr);
139*f996e368SLisandro Dalcin       ierr = PetscParseLayerYAML(options, doc, valnode);CHKERRQ(ierr);
140*f996e368SLisandro Dalcin       ierr = PetscOptionsPrefixPop(options);CHKERRQ(ierr);
141*f996e368SLisandro Dalcin 
142*f996e368SLisandro Dalcin     } else SETERRQ(comm, PETSC_ERR_SUP, "Unsupported YAML node type: expected scalar, sequence or mapping");
143*f996e368SLisandro Dalcin   }
144*f996e368SLisandro Dalcin   PetscFunctionReturn(0);
145*f996e368SLisandro Dalcin }
146*f996e368SLisandro Dalcin 
147*f996e368SLisandro Dalcin #endif
148*f996e368SLisandro Dalcin 
149*f996e368SLisandro Dalcin /*@C
150*f996e368SLisandro Dalcin    PetscOptionsInsertStringYAML - Inserts YAML-formatted options into the database from a string
151*f996e368SLisandro Dalcin 
152*f996e368SLisandro Dalcin    Logically Collective
153*f996e368SLisandro Dalcin 
154*f996e368SLisandro Dalcin    Input Parameter:
155*f996e368SLisandro Dalcin +  options - options database, use NULL for default global database
156*f996e368SLisandro Dalcin -  in_str - YAML-formatted string options
157*f996e368SLisandro Dalcin 
158*f996e368SLisandro Dalcin    Level: intermediate
159*f996e368SLisandro Dalcin 
160*f996e368SLisandro Dalcin .seealso: PetscOptionsSetValue(), PetscOptionsView(), PetscOptionsHasName(), PetscOptionsGetInt(),
161*f996e368SLisandro Dalcin           PetscOptionsGetReal(), PetscOptionsGetString(), PetscOptionsGetIntArray(), PetscOptionsBool(),
162*f996e368SLisandro Dalcin           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
163*f996e368SLisandro Dalcin           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
164*f996e368SLisandro Dalcin           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
165*f996e368SLisandro Dalcin           PetscOptionsFList(), PetscOptionsEList(), PetscOptionsInsertFile(), PetscOptionsInsertFileYAML()
166*f996e368SLisandro Dalcin @*/
167*f996e368SLisandro Dalcin PetscErrorCode PetscOptionsInsertStringYAML(PetscOptions options,const char in_str[])
168*f996e368SLisandro Dalcin {
169*f996e368SLisandro Dalcin #if defined(PETSC_HAVE_YAML)
170*f996e368SLisandro Dalcin   MPI_Comm        comm = PetscYAMLGetComm();
171*f996e368SLisandro Dalcin   yaml_parser_t   parser;
172*f996e368SLisandro Dalcin   yaml_document_t doc;
173*f996e368SLisandro Dalcin   yaml_node_t     *root;
174*f996e368SLisandro Dalcin   PetscErrorCode  ierr;
175*f996e368SLisandro Dalcin 
176*f996e368SLisandro Dalcin   PetscFunctionBegin;
177*f996e368SLisandro Dalcin   if (!in_str) in_str = "";
178*f996e368SLisandro Dalcin   ierr = !yaml_parser_initialize(&parser); if (ierr) SETERRQ(comm, PETSC_ERR_LIB, "YAML parser initialization error");
179*f996e368SLisandro Dalcin   yaml_parser_set_input_string(&parser, (const unsigned char *)in_str, strlen(in_str));
180*f996e368SLisandro Dalcin   do {
181*f996e368SLisandro Dalcin     ierr = !yaml_parser_load(&parser, &doc); if (ierr) SETERRQ(comm, PETSC_ERR_LIB, "YAML parser loading error");
182*f996e368SLisandro Dalcin     root = yaml_document_get_root_node(&doc);
183*f996e368SLisandro Dalcin     if (root) {
184*f996e368SLisandro Dalcin       ierr = PetscParseLayerYAML(options, &doc, root);CHKERRQ(ierr);
185*f996e368SLisandro Dalcin     }
186*f996e368SLisandro Dalcin     yaml_document_delete(&doc);
187*f996e368SLisandro Dalcin   } while (root);
188*f996e368SLisandro Dalcin   yaml_parser_delete(&parser);
189*f996e368SLisandro Dalcin   PetscFunctionReturn(0);
190*f996e368SLisandro Dalcin #else
191*f996e368SLisandro Dalcin   MPI_Comm comm = PetscYAMLGetComm();
192*f996e368SLisandro Dalcin   (void)options; (void)in_str; /* unused */
193*f996e368SLisandro Dalcin   SETERRQ(comm, PETSC_ERR_SUP, "YAML not supported in this build.\nPlease reconfigure using --download-yaml");
194*f996e368SLisandro Dalcin #endif
195*f996e368SLisandro Dalcin }
196*f996e368SLisandro Dalcin 
197*f996e368SLisandro Dalcin /*@C
198*f996e368SLisandro Dalcin   PetscOptionsInsertFileYAML - Insert a YAML-formatted file in the option database
199*f996e368SLisandro Dalcin 
200*f996e368SLisandro Dalcin   Collective
201*f996e368SLisandro Dalcin 
202*f996e368SLisandro Dalcin   Input Parameter:
203*f996e368SLisandro Dalcin +   comm - the processes that will share the options (usually PETSC_COMM_WORLD)
204*f996e368SLisandro Dalcin .   options - options database, use NULL for default global database
205*f996e368SLisandro Dalcin .   file - name of file
206*f996e368SLisandro Dalcin -   require - if PETSC_TRUE will generate an error if the file does not exist
207*f996e368SLisandro Dalcin 
208*f996e368SLisandro Dalcin   Only a small subset of the YAML standard is implemented. Non-scalar keys are NOT supported;
209*f996e368SLisandro Dalcin   aliases and the merge key "<<" are.
210*f996e368SLisandro Dalcin   The algorithm recursively parses the yaml file, pushing and popping prefixes
211*f996e368SLisandro Dalcin   and inserting key + values pairs using PetscOptionsSetValue().
212*f996e368SLisandro Dalcin 
213*f996e368SLisandro Dalcin   PETSc will generate an error condition that stops the program if a YAML error
214*f996e368SLisandro Dalcin   is detected, hence the user should check that the YAML file is valid before
215*f996e368SLisandro Dalcin   supplying it, for instance at http://www.yamllint.com/ .
216*f996e368SLisandro Dalcin 
217*f996e368SLisandro Dalcin   Inspired by https://stackoverflow.com/a/621451
218*f996e368SLisandro Dalcin 
219*f996e368SLisandro Dalcin   Level: intermediate
220*f996e368SLisandro Dalcin 
221*f996e368SLisandro Dalcin .seealso: PetscOptionsSetValue(), PetscOptionsView(), PetscOptionsHasName(), PetscOptionsGetInt(),
222*f996e368SLisandro Dalcin           PetscOptionsGetReal(), PetscOptionsGetString(), PetscOptionsGetIntArray(), PetscOptionsBool(),
223*f996e368SLisandro Dalcin           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
224*f996e368SLisandro Dalcin           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
225*f996e368SLisandro Dalcin           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
226*f996e368SLisandro Dalcin           PetscOptionsFList(), PetscOptionsEList(), PetscOptionsInsertFile(), PetscOptionsInsertStringYAML()
227*f996e368SLisandro Dalcin @*/
228*f996e368SLisandro Dalcin PetscErrorCode PetscOptionsInsertFileYAML(MPI_Comm comm,PetscOptions options,const char file[],PetscBool require)
229*f996e368SLisandro Dalcin {
230*f996e368SLisandro Dalcin   int            yamlLength = -1;
231*f996e368SLisandro Dalcin   char          *yamlString = NULL;
232*f996e368SLisandro Dalcin   MPI_Comm       prev;
233*f996e368SLisandro Dalcin   PetscMPIInt    rank;
234*f996e368SLisandro Dalcin   PetscErrorCode ierr;
235*f996e368SLisandro Dalcin 
236*f996e368SLisandro Dalcin   PetscFunctionBegin;
237*f996e368SLisandro Dalcin   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
238*f996e368SLisandro Dalcin   if (!rank) {
239*f996e368SLisandro Dalcin     char   fpath[PETSC_MAX_PATH_LEN];
240*f996e368SLisandro Dalcin     char   fname[PETSC_MAX_PATH_LEN];
241*f996e368SLisandro Dalcin     FILE  *fd;
242*f996e368SLisandro Dalcin     size_t rd;
243*f996e368SLisandro Dalcin 
244*f996e368SLisandro Dalcin     ierr = PetscStrreplace(PETSC_COMM_SELF, file, fpath, sizeof(fpath));CHKERRQ(ierr);
245*f996e368SLisandro Dalcin     ierr = PetscFixFilename(fpath, fname);CHKERRQ(ierr);
246*f996e368SLisandro Dalcin 
247*f996e368SLisandro Dalcin     fd = fopen(fname, "r");
248*f996e368SLisandro Dalcin     if (fd) {
249*f996e368SLisandro Dalcin       fseek(fd, 0, SEEK_END);
250*f996e368SLisandro Dalcin       yamlLength = (int)ftell(fd);
251*f996e368SLisandro Dalcin       fseek(fd, 0, SEEK_SET);
252*f996e368SLisandro Dalcin       if (yamlLength < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to query size of YAML file: %s", fname);
253*f996e368SLisandro Dalcin       ierr = PetscMalloc1(yamlLength+1, &yamlString);CHKERRQ(ierr);
254*f996e368SLisandro Dalcin       rd = fread(yamlString, 1, (size_t)yamlLength, fd);
255*f996e368SLisandro Dalcin       if (rd != (size_t)yamlLength) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Unable to read entire YAML file: %s", fname);
256*f996e368SLisandro Dalcin       yamlString[yamlLength] = 0;
257*f996e368SLisandro Dalcin       fclose(fd);
258*f996e368SLisandro Dalcin     }
259*f996e368SLisandro Dalcin   }
260*f996e368SLisandro Dalcin 
261*f996e368SLisandro Dalcin   ierr = MPI_Bcast(&yamlLength, 1, MPI_INT, 0, comm);CHKERRMPI(ierr);
262*f996e368SLisandro Dalcin   if (require && yamlLength < 0) SETERRQ1(comm, PETSC_ERR_FILE_OPEN, "Unable to open YAML option file: %s\n", file);
263*f996e368SLisandro Dalcin   if (yamlLength < 0) PetscFunctionReturn(0);
264*f996e368SLisandro Dalcin 
265*f996e368SLisandro Dalcin   if (rank) {ierr = PetscMalloc1(yamlLength+1, &yamlString);CHKERRQ(ierr);}
266*f996e368SLisandro Dalcin   ierr = MPI_Bcast(yamlString, yamlLength+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
267*f996e368SLisandro Dalcin 
268*f996e368SLisandro Dalcin   prev = PetscYAMLSetComm(comm);
269*f996e368SLisandro Dalcin   ierr = PetscOptionsInsertStringYAML(options, yamlString);CHKERRQ(ierr);
270*f996e368SLisandro Dalcin   (void) PetscYAMLSetComm(prev);
271*f996e368SLisandro Dalcin 
272*f996e368SLisandro Dalcin   ierr = PetscFree(yamlString);CHKERRQ(ierr);
273*f996e368SLisandro Dalcin   PetscFunctionReturn(0);
274*f996e368SLisandro Dalcin }
275