static int write_tng_structure(void *v, int optflags, const molfile_atom_t *atoms) { /* VMD atoms do not contain molecule information, which * complicates TNG writing a bit. */ tng_molecule_t tng_mol; tng_chain_t tng_chain; tng_residue_t tng_residue; tng_atom_t tng_atom; tngdata *tng = (tngdata *)v; /* A dummy molecule must be added. All atoms will be added to it. */ tng_molecule_add(tng->tng_traj, "MOL", &tng_mol); for(int i = 0; i < tng->natoms; i++) { if(tng_molecule_chain_find(tng->tng_traj, tng_mol, atoms[i].chain, -1, &tng_chain) != TNG_SUCCESS) { tng_molecule_chain_add(tng->tng_traj, tng_mol, atoms[i].chain, &tng_chain); } if (tng_chain_residue_find(tng->tng_traj, tng_chain, atoms[i].resname, atoms[i].resid, &tng_residue) != TNG_SUCCESS) { tng_chain_residue_w_id_add(tng->tng_traj, tng_chain, atoms[i].resname, atoms[i].resid, &tng_residue); } tng_residue_atom_add(tng->tng_traj, tng_residue, atoms[i].name, atoms[i].type, &tng_atom); } return MOLFILE_SUCCESS; }
static void addTngMoleculeFromTopology(tng_trajectory_t tng, const char *moleculeName, const t_atoms *atoms, gmx_int64_t numMolecules, tng_molecule_t *tngMol) { if (tng_molecule_add(tng, moleculeName, tngMol) != TNG_SUCCESS) { gmx_file("Cannot add molecule to TNG molecular system."); } /* FIXME: The TNG atoms should contain mass and atomB info (for free * energy calculations), i.e. in when it's available in TNG (2.0). */ for (int atomIt = 0; atomIt < atoms->nr; atomIt++) { const t_atom *at = &atoms->atom[atomIt]; /* FIXME: Currently the TNG API can only add atoms belonging to a * residue and chain. Wait for TNG 2.0*/ if (atoms->nres > 0) { const t_resinfo *resInfo = &atoms->resinfo[at->resind]; char chainName[2] = {resInfo->chainid, 0}; tng_chain_t tngChain = NULL; tng_residue_t tngRes = NULL; tng_atom_t tngAtom = NULL; if (tng_molecule_chain_find (tng, *tngMol, chainName, (gmx_int64_t)-1, &tngChain) != TNG_SUCCESS) { tng_molecule_chain_add (tng, *tngMol, chainName, &tngChain); } /* FIXME: When TNG supports both residue index and residue * number the latter should be used. Wait for TNG 2.0*/ if (tng_chain_residue_find(tng, tngChain, *resInfo->name, at->resind + 1, &tngRes) != TNG_SUCCESS) { tng_chain_residue_add(tng, tngChain, *resInfo->name, &tngRes); } tng_residue_atom_add(tng, tngRes, *(atoms->atomname[atomIt]), *(atoms->atomtype[atomIt]), &tngAtom); } } tng_molecule_cnt_set(tng, *tngMol, numMolecules); }
/* Create a TNG molecule representing the selection groups * to write */ static void add_selection_groups(tng_trajectory_t tng, const gmx_mtop_t *mtop) { const gmx_moltype_t *molType; const t_atoms *atoms; const t_atom *at; const t_resinfo *resInfo; const t_ilist *ilist; int nAtoms = 0, i = 0, j, molIt, atomIt, nameIndex; int atom_offset = 0; tng_molecule_t mol, iterMol; tng_chain_t chain; tng_residue_t res; tng_atom_t atom; tng_bond_t tngBond; gmx_int64_t nMols; char *groupName; /* The name of the TNG molecule containing the selection group is the * same as the name of the selection group. */ nameIndex = *mtop->groups.grps[egcCompressedX].nm_ind; groupName = *mtop->groups.grpname[nameIndex]; tng_molecule_alloc(tng, &mol); tng_molecule_name_set(tng, mol, groupName); tng_molecule_chain_add(tng, mol, "", &chain); for (molIt = 0; molIt < mtop->nmoltype; molIt++) { molType = &mtop->moltype[mtop->molblock[molIt].type]; atoms = &molType->atoms; for (j = 0; j < mtop->molblock[molIt].nmol; j++) { bool bAtomsAdded = FALSE; for (atomIt = 0; atomIt < atoms->nr; atomIt++, i++) { char *res_name; int res_id; if (ggrpnr(&mtop->groups, egcCompressedX, i) != 0) { continue; } at = &atoms->atom[atomIt]; if (atoms->nres > 0) { resInfo = &atoms->resinfo[at->resind]; /* FIXME: When TNG supports both residue index and residue * number the latter should be used. */ res_name = *resInfo->name; res_id = at->resind + 1; } else { res_name = (char *)""; res_id = 0; } if (tng_chain_residue_find(tng, chain, res_name, res_id, &res) != TNG_SUCCESS) { /* Since there is ONE chain for selection groups do not keep the * original residue IDs - otherwise there might be conflicts. */ tng_chain_residue_add(tng, chain, res_name, &res); } tng_residue_atom_w_id_add(tng, res, *(atoms->atomname[atomIt]), *(atoms->atomtype[atomIt]), atom_offset + atomIt, &atom); nAtoms++; bAtomsAdded = TRUE; } /* Add bonds. */ if (bAtomsAdded) { for (int k = 0; k < F_NRE; k++) { if (IS_CHEMBOND(k)) { ilist = &molType->ilist[k]; if (ilist) { int l = 1; while (l < ilist->nr) { int atom1, atom2; atom1 = ilist->iatoms[l] + atom_offset; atom2 = ilist->iatoms[l+1] + atom_offset; if (ggrpnr(&mtop->groups, egcCompressedX, atom1) == 0 && ggrpnr(&mtop->groups, egcCompressedX, atom2) == 0) { tng_molecule_bond_add(tng, mol, ilist->iatoms[l], ilist->iatoms[l+1], &tngBond); } l += 3; } } } } /* Settle is described using three atoms */ ilist = &molType->ilist[F_SETTLE]; if (ilist) { int l = 1; while (l < ilist->nr) { int atom1, atom2, atom3; atom1 = ilist->iatoms[l] + atom_offset; atom2 = ilist->iatoms[l+1] + atom_offset; atom3 = ilist->iatoms[l+2] + atom_offset; if (ggrpnr(&mtop->groups, egcCompressedX, atom1) == 0) { if (ggrpnr(&mtop->groups, egcCompressedX, atom2) == 0) { tng_molecule_bond_add(tng, mol, atom1, atom2, &tngBond); } if (ggrpnr(&mtop->groups, egcCompressedX, atom3) == 0) { tng_molecule_bond_add(tng, mol, atom1, atom3, &tngBond); } } l += 4; } } } atom_offset += atoms->nr; } } if (nAtoms != i) { tng_molecule_existing_add(tng, &mol); tng_molecule_cnt_set(tng, mol, 1); tng_num_molecule_types_get(tng, &nMols); for (gmx_int64_t k = 0; k < nMols; k++) { tng_molecule_of_index_get(tng, k, &iterMol); if (iterMol == mol) { continue; } tng_molecule_cnt_set(tng, iterMol, 0); } } else { tng_molecule_free(tng, &mol); } }
void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng, const int nind, const int *ind, const char *name) { #if GMX_USE_TNG gmx_int64_t nAtoms, cnt, nMols; tng_molecule_t mol, iterMol; tng_chain_t chain; tng_residue_t res; tng_atom_t atom; tng_function_status stat; tng_num_particles_get(tng, &nAtoms); if (nAtoms == nind) { return; } stat = tng_molecule_find(tng, name, -1, &mol); if (stat == TNG_SUCCESS) { tng_molecule_num_atoms_get(tng, mol, &nAtoms); tng_molecule_cnt_get(tng, mol, &cnt); if (nAtoms == nind) { stat = TNG_SUCCESS; } else { stat = TNG_FAILURE; } } if (stat == TNG_FAILURE) { /* The indexed atoms are added to one separate molecule. */ tng_molecule_alloc(tng, &mol); tng_molecule_name_set(tng, mol, name); tng_molecule_chain_add(tng, mol, "", &chain); for (int i = 0; i < nind; i++) { char temp_name[256], temp_type[256]; /* Try to retrieve the residue name of the atom */ stat = tng_residue_name_of_particle_nr_get(tng, ind[i], temp_name, 256); if (stat != TNG_SUCCESS) { temp_name[0] = '\0'; } /* Check if the molecule of the selection already contains this residue */ if (tng_chain_residue_find(tng, chain, temp_name, -1, &res) != TNG_SUCCESS) { tng_chain_residue_add(tng, chain, temp_name, &res); } /* Try to find the original name and type of the atom */ stat = tng_atom_name_of_particle_nr_get(tng, ind[i], temp_name, 256); if (stat != TNG_SUCCESS) { temp_name[0] = '\0'; } stat = tng_atom_type_of_particle_nr_get(tng, ind[i], temp_type, 256); if (stat != TNG_SUCCESS) { temp_type[0] = '\0'; } tng_residue_atom_w_id_add(tng, res, temp_name, temp_type, ind[i], &atom); } tng_molecule_existing_add(tng, &mol); } /* Set the count of the molecule containing the selected atoms to 1 and all * other molecules to 0 */ tng_molecule_cnt_set(tng, mol, 1); tng_num_molecule_types_get(tng, &nMols); for (gmx_int64_t k = 0; k < nMols; k++) { tng_molecule_of_index_get(tng, k, &iterMol); if (iterMol == mol) { continue; } tng_molecule_cnt_set(tng, iterMol, 0); } #else GMX_UNUSED_VALUE(tng); GMX_UNUSED_VALUE(nind); GMX_UNUSED_VALUE(ind); GMX_UNUSED_VALUE(name); #endif }