func main() { var prmtopFilename, rstFilename, outFilename string var stride int var savePreprocessed bool flag.StringVar(&prmtopFilename, "p", "prmtop", "Prmtop filename (required)") flag.StringVar(&rstFilename, "c", "", "Inpcrd/rst filename") flag.IntVar(&stride, "s", 1, "Frame stride; 1 = don't skip any") flag.StringVar(&outFilename, "o", "energies.bin", "Energy decomposition output filename") flag.BoolVar(&savePreprocessed, "e", false, "Save prmtop preprocessed output (use with -c)") flag.Parse() trjFilenames := flag.Args() mol := amber.LoadSystem(prmtopFilename) if mol == nil { return } fmt.Println("Number of atoms:", mol.NumAtoms()) fmt.Println("Number of residues:", mol.NumResidues()) hasBox := false fmt.Print("Periodic box in prmtop: ") if mol.GetInt("POINTERS", amber.IFBOX) > 0 { hasBox = true fmt.Println("Yes") } else { fmt.Println("No") } // Set up nonbonded parameters. We load them here so we don't have to keep // doing it later var params NonbondedParamsCache params.Ntypes = mol.GetInt("POINTERS", amber.NTYPES) params.NBIndices = amber.VectorAsIntArray(mol.Blocks["NONBONDED_PARM_INDEX"]) // ICO params.AtomTypeIndices = amber.VectorAsIntArray(mol.Blocks["ATOM_TYPE_INDEX"]) // IAC params.LJ12 = amber.VectorAsFloat32Array(mol.Blocks["LENNARD_JONES_ACOEF"]) // CN1 params.LJ6 = amber.VectorAsFloat32Array(mol.Blocks["LENNARD_JONES_BCOEF"]) // CN2 params.Charges = amber.VectorAsFloat32Array(mol.Blocks["CHARGE"]) // If we were given a single snapshot, just do that one if rstFilename != "" || savePreprocessed { var request EnergyCalcRequest if rstFilename != "" { fmt.Printf("Calculating energies for single snapshot %s.\n", rstFilename) mol.LoadRst(rstFilename) request.Coords = mol.Coords[0] } request.NBParams = params request.Molecule = mol // Lookup table for bond types so we don't calculate electrostatics // and such between bonded atoms request.BondType = makeBondTypeTable(mol) request.ResidueMap = makeResidueMap(mol) request.Decomp = make([]float64, mol.NumResidues()*mol.NumResidues()) // Dump the preprocessed info to a file so a C version of this program can easily load and parse it if savePreprocessed { outFile, _ := os.OpenFile("solute.top.tom", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) defer outFile.Close() WriteInt32(outFile, mol.NumAtoms()) WriteInt32(outFile, mol.NumResidues()) WriteInt32(outFile, params.Ntypes) WriteInt32Array(outFile, params.NBIndices) WriteInt32Array(outFile, params.AtomTypeIndices) WriteFloat32Array(outFile, params.LJ12) WriteFloat32Array(outFile, params.LJ6) WriteFloat32Array(outFile, params.Charges) WriteInt8Array(outFile, request.BondType) WriteInt32Array(outFile, request.ResidueMap) if hasBox { WriteInt32(outFile, 1) } else { WriteInt32(outFile, 0) } fmt.Println("Wrote preprocessed prmtop data. Done!") os.Exit(0) } fmt.Println("Electrostatic energy:", Electro(&request), "kcal/mol") fmt.Println("van der Waals energy:", LennardJones(&request), "kcal/mol") fmt.Println(amber.Status()) amber.DumpFloat64MatrixAsText(request.Decomp, mol.NumResidues(), "decomp.txt") fmt.Println("Saved decomposition matrix to decomp.txt") } else if len(trjFilenames) > 0 { fmt.Println("Frame stride:", stride) // Lookup table for bond types so we don't calculate nonbonded energies // between bonded atoms bondType := makeBondTypeTable(mol) residueMap := makeResidueMap(mol) ch := make(chan int) decompCh := make(chan []float64, 32) // This goroutine will be fed the decomposition matrices made by the energy functions fmt.Println("Writing residue decomposition matrices to", outFilename) go decompProcessor(outFilename, mol.NumResidues(), decompCh, ch) numAtoms := mol.NumAtoms() fileId := 0 trj, err := openTrj(trjFilenames[fileId]) if err != nil { return } numKids := 0 frame := 0 strideCountdown := stride for { // If there was an error reading the next frame, move on to the next trajectory file coords, err := amber.GetNextFrameFromTrajectory(trj, numAtoms, hasBox) if err != nil { fileId++ if fileId >= len(trjFilenames) { break } trj, err = openTrj(trjFilenames[fileId]) if err != nil { fmt.Println("Error opening", trjFilenames[fileId]) break } coords, err = amber.GetNextFrameFromTrajectory(trj, numAtoms, hasBox) if err != nil { fmt.Printf("Trajectory file %s doesn't have even one valid frame\n", trjFilenames[fileId]) break } } frame++ // Only actually process the frames indicated by stride strideCountdown-- if strideCountdown == 0 { strideCountdown = stride go calcSingleTrjFrame(mol, params, coords, frame, bondType, residueMap, decompCh, ch) numKids++ } } if false { for i := 0; i < numKids; i++ { <-ch } } decompCh <- nil <-ch // Wait for decompProcessor to finish } }
func main() { var prmtopFilename, rstFilename, outFilename string var stride int var savePreprocessed bool flag.StringVar(&prmtopFilename, "p", "prmtop", "Prmtop filename (required)") flag.StringVar(&rstFilename, "c", "", "Inpcrd/rst filename") flag.IntVar(&stride, "s", 1, "Frame stride; 1 = don't skip any") flag.StringVar(&outFilename, "o", "energies.bin", "Energy decomposition output filename") flag.BoolVar(&savePreprocessed, "e", false, "Save prmtop preprocessed output (use with -c)") flag.Parse() mol := amber.LoadSystem(prmtopFilename) if mol == nil { return } fmt.Println("Number of atoms:", mol.NumAtoms()) fmt.Println("Number of residues:", mol.NumResidues()) hasBox := false fmt.Print("Periodic box in prmtop: ") if mol.GetInt("POINTERS", amber.IFBOX) > 0 { hasBox = true fmt.Println("Yes") } else { fmt.Println("No") } // Set up nonbonded parameters. We load them here so we don't have to keep // doing it later var params NonbondedParamsCache params.Ntypes = mol.GetInt("POINTERS", amber.NTYPES) params.NBIndices = amber.VectorAsIntArray(mol.Blocks["NONBONDED_PARM_INDEX"]) // ICO params.AtomTypeIndices = amber.VectorAsIntArray(mol.Blocks["ATOM_TYPE_INDEX"]) // IAC params.LJ12 = amber.VectorAsFloat32Array(mol.Blocks["LENNARD_JONES_ACOEF"]) // CN1 params.LJ6 = amber.VectorAsFloat32Array(mol.Blocks["LENNARD_JONES_BCOEF"]) // CN2 params.Charges = amber.VectorAsFloat32Array(mol.Blocks["CHARGE"]) var request EnergyCalcRequest request.NBParams = params request.Molecule = mol // Lookup table for bond types so we don't calculate electrostatics // and such between bonded atoms request.BondType = makeBondTypeTable(mol) request.ResidueMap = makeResidueMap(mol) request.Decomp = make([]float64, mol.NumResidues()*mol.NumResidues()) // Dump the preprocessed info to a file so a C version of this program can easily load and parse it outFile, _ := os.OpenFile("solute.top.tom", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) defer outFile.Close() WriteInt32(outFile, mol.NumAtoms()) WriteInt32(outFile, mol.NumResidues()) WriteInt32(outFile, params.Ntypes) WriteInt32Array(outFile, params.NBIndices) WriteInt32Array(outFile, params.AtomTypeIndices) WriteFloat32Array(outFile, params.LJ12) WriteFloat32Array(outFile, params.LJ6) WriteFloat32Array(outFile, params.Charges) WriteInt8Array(outFile, request.BondType) WriteInt32Array(outFile, request.ResidueMap) if hasBox { WriteInt32(outFile, 1) } else { WriteInt32(outFile, 0) } fmt.Println("Wrote preprocessed prmtop data. Done!") os.Exit(0) }