Building and using the library¶
Building¶
From the repository root:
cmake -S . -B build
cmake --build build
This builds libyaml_c_wrapper (.dylib/.so), a shared library that other
languages can load. CMake fetches the dependencies —
rapidyaml,
PCRE2, and
AtomicAndPhysicalConstantsCLib —
automatically. Rebuild after changing any source file, and before running the
tests. Put lattice files under lattice_files/.
Expanding a lattice¶
parse_and_expand_PALS reads a lattice file, resolves its includes and loads,
expands the selected lattice, and returns a lattices struct with five
independent views —
original, combined, expanded, full_expanded, and leftover (see
The five trees). Each is a YAMLTreeHandle and must be freed with
delete_tree.
#include "yaml_c_wrapper.h"
struct lattices lat = parse_and_expand_PALS("ex.pals.yaml", nullptr);
char* s = tree_to_string(lat.full_expanded);
std::puts(s);
yaml_free_string(s);
// Report any problems met while expanding (see below), then free everything.
for (size_t i = 0; i < lat.problems.count; ++i)
std::fprintf(stderr, " - %s\n", lat.problems.items[i]);
free_lattice_problems(lat.problems);
delete_tree(lat.original);
delete_tree(lat.combined);
delete_tree(lat.expanded);
delete_tree(lat.full_expanded);
delete_tree(lat.leftover);
The second argument names the lattice to expand. Pass nullptr (or an empty
string) to expand the lattice named by the last use statement, or — if there
is none — the last lattice defined in the file.
Problems found during expansion¶
Expansion does not abort on a recoverable problem. It leaves the offending
value as it found it, carries on with the rest of the lattice, and appends a
human‑readable message to lat.problems, an owning string_list. The list is
empty when expansion was clean. The library never prints — the caller decides
whether to report, save, or ignore the messages — and must release the list
with free_lattice_problems.
Expansion is therefore always worth reading: a lattice with problems still
comes back expanded as far as it could be, with the trees around the fault
intact. The one exception is a top‑level file that is not valid YAML, where
there is nothing to expand: all five handles come back NULL and the parse
error, with its location, is the single problem reported.
What gets reported falls into a few groups.
Structure. A lattice named in the call (or in use) that does not exist, a
line reference to an undefined element or line, a missing
inherit/repeat/Fork target, an invalid repeat count, a Fork whose
to_line cannot be resolved, a branch that never got expanded, and a load or
include that cannot be read or that conflicts with what it is merged into.
Expressions. A value that cannot be evaluated — an unknown constant or
species, a dangling element‑parameter reference, a reference cycle, a syntax
error — is left as text and reported. Only values that look like expressions
(an operator, a parenthesis, a > reference, or an explicit expr(...)) are
flagged, so a plain name or a label is not mistaken for broken math. See
Evaluating expressions.
Controllers. A control_type that is neither ABSOLUTE nor RELATIVE; a
controls entry with no parameter or no expression; a control target that
is malformed, names no element parameter, or matches nothing in the expanded
lattice; a reference to a variable a named controller does not have; a
controller variable whose initial value is not a constant expression; a
circular control hierarchy; a parameter driven by both an ABSOLUTE and a
RELATIVE controller; and a parameter that is both controlled and assigned a
delayed (expr(...)) expression.
Sets. A set with no parameter or no value; a target that is
malformed, names no element parameter, or matches nothing (for a
pre‑expand_lattice set, nothing defined before it); a value that cannot be
evaluated; and a value that reads a parameter whose value is still to be
derived during expansion.
Bookkeeping. A branch whose first element gives neither a reference species nor a reference energy, so the reference parameters cannot be computed; and a parameter the author wrote that is inconsistent with what the rest of its family or the bend geometry implies — the authored value is kept and the disagreement reported rather than silently overwritten.
Vocabulary. An element kind or parameter group name that is not one the
standard defines — a FlorP group is valid YAML and would otherwise go
unrecognised in silence — reported with a “did you mean” suggestion where a
near match exists.
Deliberately not computed. Where the standard fixes a value’s magnitude but
not how to produce it, this library reports rather than guesses: an
absolute_error/relative_error on a set (the error distribution is
unspecified, so the deterministic value is written and the error is not), and a
Foil element’s downstream species change (the stripping model is undefined,
so the species is left as the upstream one).
Reading the expanded lattice¶
Which of the five trees answers a given question, and what the expansion adds to
full_expanded that appears nowhere else — element_index, s_position,
ReferenceP, FloorP, the derived parameter families, the branch_end cap —
is covered in The five trees.
Examples¶
The examples/ directory contains runnable programs:
examples/example_rw.cpp— read a lattice, do basic manipulations (add, remove, rename), print, and write it back out../example_rwexamples/print_lattices— expand a lattice and print all five views. It takes a file name and an optional-lat <name>flag naming the lattice to expand:./print_lattices ex.pals.yaml -lat lat2The file name is resolved under
../lattice_files/, so run it from a directory that sits besidelattice_files/—build/, say — and put the lattice inlattice_files/.
Extensions¶
PALSJulia extends pals-cpp with a Julia interface to the C API and translators from PALS to Bmad and SciBmad lattice files.