first of all, the cst file block you posted seems to be from the enzdes integration test, which is describing a cysteine esterase active site and not a kemp design.
as to the question, there is an easier way to do this, without having to regenerate the .params file / rerun molfile_to_params.py or changing input structures that you’ve already generated.
you can simply modify the .params file you already have, i.e. add the virtual atom to it. take a look at the D2N_aX.params file that is in the enzdes integration test.
there a 5 lines that relate to the virtual atom in this file (grep for ‘X1’), but only the following three a really necessary
ATOM X1 VIRT VIRT 0.00
BOND C10 X1
ICOOR_INTERNAL X1 0.039321 119.837865 1.401155 C12 C10 C11
the ‘ATOM’ record declares that there is a virtual atom, the ‘BOND’ one says that it’s bonded to another atom (doesn’t really matter which one), and the ICOOR_INTERNAL defines the internal coordinates for the virtual atom in relation to other atoms.
the internal coordiante format means that “atom X1 is 1.4 A away from C12, the angle C10-C12-X1 is 180-119.8 = 60.2 deg and the dihedral C11-C10-C12-X1 is 0.03, i.e. these four atoms are in the same plane. since C10, C12 and C11 are part of the aromatic ring, these internal coordinates put X1 into the middle of the ring.
so, to add a virtual atom to your .params, you can probably copy these three lines, and only exchange the C10,C12 and C11 names with names of atoms in your ring of interest. once you run jobs with this .params file, rosetta should automatically place the virtual atom correctly, even if it is not present in the input structure
now, once you’ve modified your .params file, you should doublecheck whether you placed the X1 atom in the right place. to do so, run a quick scoring calculation in rosetta (adding -output_virtual to the commandline options), and then check where the virtual atom ended up in the output structure.