Task 219: .FCHK File Format
Task 219: .FCHK File Format
1. List of All Properties Intrinsic to the .FCHK File Format
The .FCHK (Gaussian Formatted Checkpoint) file format is a plain-text, machine-independent structure for storing quantum chemistry calculation results from Gaussian software. It consists of a header (two lines: title and calculation metadata) followed by labeled sections. Each section starts with a descriptive keyword/label followed by data type indicators ('I' for integer, 'R' for real/Fortran double precision) and, for arrays, 'N=<number_of_elements>'. Data for scalars is on the same line; for arrays, subsequent lines contain 5 (for integers) or 6 (for reals) values per line, in free-format Fortran style (atomic units, standard orientation).
The intrinsic properties (fields/keywords) are extensible but include the following standard ones, grouped by category for clarity. This list is compiled from the Gaussian 09/16 formatted checkpoint specifications:
Header Properties
- Title: String (first 72 characters of line 1).
- Calculation Type: String (e.g., 'SP', 'FOPT', 'FREQ'; indicates job type like single point, optimization, frequency calculation).
- Method: String (e.g., 'RHF', 'B3LYP', 'MP2'; computational method).
- Basis Set: String (e.g., 'STO-3G', '6-31G*'; basis set used).
Molecular System Properties (Scalars)
- Number of atoms (I).
- Charge (I).
- Multiplicity (I).
- Number of electrons (I).
- Number of alpha electrons (I).
- Number of beta electrons (I).
- Number of basis functions (I).
- Number of independent functions (I).
Energy and Thermodynamic Properties (Reals)
- Virial ratio (R).
- SCF energy (R).
- MP2 energy (R).
- Total energy (R).
- Zero-point energy (R, if available from frequency calc).
- Thermal energy corrections (R, e.g., translational, rotational, vibrational).
Atomic Properties (Arrays, N=number of atoms)
- Atomic numbers (I, N=).
- Nuclear charges (R, N=).
- Current Cartesian coordinates (R, N=3*natoms; x,y,z flattened).
- Mulliken charges (R, N=).
- Natural population analysis (NPA) charges (R, N=; if computed).
- Electrostatic potential (ESP) charges (R, N=; if computed).
Orbital and Wavefunction Properties (Arrays)
- Alpha orbital energies (R, N=number of alpha orbitals).
- Alpha MO coefficients (R, N=number of basis functions * number of alpha orbitals; column-major).
- Beta orbital energies (R, N=number of beta orbitals; unrestricted cases).
- Beta MO coefficients (R, N=number of basis functions * number of beta orbitals; column-major).
Density Matrix Properties (Arrays)
- Total SCF density (R, N=nbasis*(nbasis+1)/2; upper triangular).
- Spin SCF density (R, N=nbasis*(nbasis+1)/2; if unrestricted).
- MP2 density (full/spin, R, N=; if MP2 computed).
- CCSD density (full/spin, R, N=; if coupled-cluster).
Gradient and Force Properties (Arrays)
- Cartesian gradient (R, N=3*natoms).
- Internal forces (R, N=; if internal coordinates used).
Hessian and Frequency Properties (Arrays, if frequency calculation)
- Force constants (R, N=3natoms3*natoms; Cartesian Hessian).
Basis Set Properties (Scalars and Arrays)
- Number of shells (I).
- Largest degree of contraction (I).
- Highest angular momentum present (I).
- Number of primitive shells (I).
- Shell types (I, N=number of shells; e.g., 1=S, 3=P, 4=SP).
- Number of primitives per shell (I, N=).
- Shell to atom map (I, N=).
- Primitive exponents (R, N=total primitives).
- Contraction coefficients (R, N=total contractions).
- P(S=P) contraction coefficients (R, N=; for SP shells).
- Shell coordinates (R, N=3*number of shells; center of each shell).
These properties are not all present in every file (depends on calculation type), but they define the format's structure. The format is forward-compatible: unknown fields can be skipped.
2. Two Direct Download Links for .FCHK Files
- H2O molecule (water, HF/6-31G basis, single-point calculation): https://raw.githubusercontent.com/RyokoKuga/psi4_tut/main/Output/H2O.fchk
- He atom (helium, HF/STO-3G basis, test calculation): https://raw.githubusercontent.com/theochem/grid/refs/heads/master/examples/He_t.fchk
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .FCHK Parsing
This is a self-contained HTML snippet embeddable in a Ghost blog post (use in an HTML card). It allows drag-and-drop of a .FCHK file, parses it client-side, and dumps all detected properties to a <pre>
element on the page. Parsing logic reads lines, identifies labels/types/N, and extracts data (scalars inline, arrays by consuming subsequent lines with 5-6 values).
Drop a file to see properties...
4. Python Class for .FCHK Handling
This class opens a .fchk file, parses all properties into a dict, supports writing back to a new .fchk file (reconstructing header and sections), and prints them to console.
import re
import os
class FCHKParser:
def __init__(self, filename):
with open(filename, 'r') as f:
self.content = f.read()
self.properties = {}
self.parse()
def parse(self):
lines = self.content.splitlines()
line_idx = 0
# Header
self.properties['title'] = lines[line_idx].strip()[:72]
line_idx += 1
header = re.split(r'\s+', lines[line_idx].strip())
self.properties['type'] = header[0]
self.properties['method'] = header[1]
self.properties['basis'] = header[2]
line_idx += 1
while line_idx < len(lines):
line = lines[line_idx].strip()
line_idx += 1
if not line:
continue
match = re.match(r'([A-Za-z\s]+?)(I|R)(?:\s+N=(\d+))?', line)
if not match:
continue
label, dtype, n_str = match.groups()
key = re.sub(r'\s+', '_', label.strip().lower())
is_array = n_str is not None
n = int(n_str) if is_array else 1
value = []
if not is_array:
# Scalar
scalar_match = re.search(rf'{dtype}\s+([\-\d.eE+-]+)', line)
value = float(scalar_match.group(1)) if scalar_match else None
else:
# Array
cols = 6 if dtype == 'R' else 5
remaining = n
while remaining > 0 and line_idx < len(lines):
data_line = re.findall(r'[\-\d.eE+-]+', lines[line_idx].strip())
data_line = [float(x) for x in data_line[:cols]]
take = min(len(data_line), remaining)
value.extend(data_line[:take])
remaining -= take
line_idx += 1
self.properties[key] = value
def write(self, output_filename):
with open(output_filename, 'w') as f:
f.write(self.properties['title'] + '\n')
f.write(f"{self.properties['type']:10} {self.properties['method']:30} {self.properties['basis']:30}\n")
for key, value in self.properties.items():
if key in ['title', 'type', 'method', 'basis']:
continue
label = key.replace('_', ' ').title()
if isinstance(value, (int, float)):
dtype = 'I' if isinstance(value, int) else 'R'
f.write(f"{label} {dtype} {value}\n")
else:
n = len(value)
dtype = 'I' if all(isinstance(v, int) for v in value[:min(5, n)]) else 'R'
f.write(f"{label} {dtype} N={n}\n")
cols = 5 if dtype == 'I' else 6
for i in range(0, n, cols):
chunk = value[i:i+cols]
f.write(' '.join(f"{v:16.8E}" if dtype == 'R' else f"{int(v)}" for v in chunk) + '\n')
def print_properties(self):
import json
print(json.dumps(self.properties, indent=2, default=str))
# Usage: parser = FCHKParser('sample.fchk'); parser.print_properties(); parser.write('output.fchk')
5. Java Class for .FCHK Handling
This Java class reads a .fchk file, parses properties into a Map<String, Object>, supports writing to a new file, and prints to console (System.out).
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class FCHKParser {
private Map<String, Object> properties = new HashMap<>();
private String content;
public FCHKParser(String filename) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(filename));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
content = sb.toString();
reader.close();
parse();
}
private void parse() {
String[] lines = content.split("\n");
int lineIdx = 0;
// Header
properties.put("title", lines[lineIdx].trim().substring(0, 72));
lineIdx++;
String[] header = lines[lineIdx].trim().split("\\s+");
properties.put("type", header[0]);
properties.put("method", header[1]);
properties.put("basis", header[2]);
lineIdx++;
Pattern labelPattern = Pattern.compile("([A-Za-z\\s]+?)(I|R)(?:\\s+N=(\\d+))?");
while (lineIdx < lines.length) {
String line = lines[lineIdx++].trim();
if (line.isEmpty()) continue;
Matcher matcher = labelPattern.matcher(line);
if (!matcher.find()) continue;
String label = matcher.group(1).trim().toLowerCase().replaceAll("\\s+", "_");
String dtype = matcher.group(2);
String nStr = matcher.group(3);
boolean isArray = nStr != null;
int n = isArray ? Integer.parseInt(nStr) : 1;
Object value;
if (!isArray) {
// Scalar
Pattern scalarPat = Pattern.compile(dtype + "\\s+([\\-\\d.eE+-]+)");
Matcher scalarM = scalarPat.matcher(line);
value = scalarM.find() ? Double.parseDouble(scalarM.group(1)) : null;
} else {
// Array
List<Double> arr = new ArrayList<>();
int remaining = n;
int cols = "R".equals(dtype) ? 6 : 5;
while (remaining > 0 && lineIdx < lines.length) {
String dataLine = lines[lineIdx++].trim();
String[] parts = dataLine.split("\\s+");
for (int i = 0; i < Math.min(parts.length, remaining); i++) {
arr.add(Double.parseDouble(parts[i]));
}
remaining -= Math.min(parts.length, remaining);
}
value = arr;
}
properties.put(label, value);
}
}
public void write(String outputFilename) throws IOException {
try (PrintWriter writer = new PrintWriter(new FileWriter(outputFilename))) {
writer.println((String) properties.get("title"));
writer.printf("%-10s %-30s %-30s%n", properties.get("type"), properties.get("method"), properties.get("basis"));
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object val = entry.getValue();
if (key.equals("title") || key.equals("type") || key.equals("method") || key.equals("basis")) continue;
String label = key.replace("_", " ").toUpperCase();
if (val instanceof Number) {
String dtype = (val instanceof Integer) ? "I" : "R";
writer.printf("%s %s %s%n", label, dtype, val);
} else if (val instanceof List) {
List<?> arr = (List<?>) val;
int n = arr.size();
String dtype = "R"; // Assume real for simplicity
writer.printf("%s %s N=%d%n", label, dtype, n);
int cols = 6;
for (int i = 0; i < n; i += cols) {
for (int j = 0; j < cols && i + j < n; j++) {
writer.printf("%16.8E ", arr.get(i + j));
}
writer.println();
}
}
}
}
}
public void printProperties() {
System.out.println(properties);
}
// Usage: new FCHKParser("sample.fchk").printProperties();
}
6. JavaScript Class for .FCHK Handling (Node.js)
This Node.js class uses fs
to open a .fchk file, parses properties into an object, supports writing to a new file, and prints to console.
const fs = require('fs');
class FCHKParser {
constructor(filename) {
this.content = fs.readFileSync(filename, 'utf8');
this.properties = {};
this.parse();
}
parse() {
const lines = this.content.split('\n');
let lineIdx = 0;
// Header
this.properties.title = lines[lineIdx].trim().substring(0, 72);
lineIdx++;
const header = lines[lineIdx].trim().split(/\s+/);
this.properties.type = header[0];
this.properties.method = header[1];
this.properties.basis = header[2];
lineIdx++;
const labelRegex = /^([A-Za-z\s]+?)(I|R)(?:\s+N=(\d+))?/;
while (lineIdx < lines.length) {
let line = lines[lineIdx++].trim();
if (!line) continue;
const match = line.match(labelRegex);
if (!match) continue;
const [, label, dtype, nStr] = match;
const key = label.trim().toLowerCase().replace(/\s+/g, '_');
const isArray = !!nStr;
const n = isArray ? parseInt(nStr) : 1;
let value;
if (!isArray) {
// Scalar
const scalarMatch = line.match(new RegExp(`${dtype}\\s+([\\-\\d.eE+-]+)`));
value = scalarMatch ? parseFloat(scalarMatch[1]) : null;
} else {
// Array
value = [];
let remaining = n;
const cols = dtype === 'R' ? 6 : 5;
while (remaining > 0 && lineIdx < lines.length) {
const dataLine = lines[lineIdx++].trim().split(/\s+/).map(v => parseFloat(v)).filter(v => !isNaN(v));
const take = Math.min(dataLine.length, remaining);
value.push(...dataLine.slice(0, take));
remaining -= take;
}
}
this.properties[key] = value;
}
}
write(outputFilename) {
let output = this.properties.title + '\n';
output += `${this.properties.type.padEnd(10)}${this.properties.method.padEnd(30)}${this.properties.basis.padEnd(30)}\n`;
for (const [key, value] of Object.entries(this.properties)) {
if (['title', 'type', 'method', 'basis'].includes(key)) continue;
const label = key.replace(/_/g, ' ').toUpperCase();
if (typeof value === 'number') {
const dtype = Number.isInteger(value) ? 'I' : 'R';
output += `${label} ${dtype} ${value}\n`;
} else if (Array.isArray(value)) {
const n = value.length;
const dtype = 'R'; // Assume real
output += `${label} ${dtype} N=${n}\n`;
const cols = 6;
for (let i = 0; i < n; i += cols) {
const chunk = value.slice(i, i + cols);
output += chunk.map(v => v.toExponential(8).padStart(16)).join(' ') + '\n';
}
}
}
fs.writeFileSync(outputFilename, output);
}
printProperties() {
console.log(JSON.stringify(this.properties, null, 2));
}
}
// Usage: const parser = new FCHKParser('sample.fchk'); parser.printProperties(); parser.write('output.fchk');
7. C Code for .FCHK Handling (Struct-Based "Class")
This C implementation uses a struct for properties (simplified dict as key-value pairs), functions to open/parse/write/print. Compile with gcc fchk.c -o fchk -lm
. Handles basic parsing (assumes reals for arrays).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h> // For regex, or implement simple parsing
// Simplified: Use arrays for properties (up to 100 keys, values as double* or int)
#define MAX_PROPS 100
#define MAX_LINE 1024
#define MAX_KEY 256
typedef struct {
char keys[MAX_PROPS][MAX_KEY];
void* values[MAX_PROPS]; // double* for arrays/scalars (cast)
int types[MAX_PROPS]; // 0: scalar int, 1: scalar double, 2: array double
int ns[MAX_PROPS]; // size for arrays, 1 for scalars
int count;
char title[73];
char type[11];
char method[31];
char basis[31];
} FCHKProperties;
void parse_fchk(FCHKProperties* props, const char* filename) {
FILE* fp = fopen(filename, "r");
if (!fp) return;
char line[MAX_LINE];
fgets(line, sizeof(line), fp);
strncpy(props->title, line, 72);
fgets(line, sizeof(line), fp);
sscanf(line, "%10s %30s %30s", props->type, props->method, props->basis);
props->count = 0;
regex_t regex;
regcomp(®ex, "^([A-Za-z ]+?)(I|R)( N=([0-9]+))?$", REG_EXTENDED);
while (fgets(line, sizeof(line), fp)) {
size_t len = strlen(line);
if (len < 2 || line[0] == '\n') continue;
regmatch_t matches[5];
if (regexec(®ex, line, 5, matches, 0) != 0) continue;
char label[256], dtype[2], nstr[16];
int label_start = matches[1].rm_so;
int label_end = matches[1].rm_eo;
strncpy(label, line + label_start, label_end - label_start);
label[label_end - label_start] = '\0';
strncpy(dtype, line + matches[2].rm_so, 1);
int is_array = (matches[3].rm_so != -1);
int n = 1;
if (is_array) {
strncpy(nstr, line + matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so);
n = atoi(nstr);
}
strncpy(props->keys[props->count], label, sizeof(label));
for (int i = 0; i < strlen(props->keys[props->count]); i++) {
if (props->keys[props->count][i] == ' ') props->keys[props->count][i] = '_';
}
tolower(props->keys[props->count]);
double* val = malloc((is_array ? n : 1) * sizeof(double));
if (!is_array) {
// Scalar: parse from line
sscanf(line + matches[2].rm_eo, "%lf", val);
props->types[props->count] = 1; // double scalar
} else {
// Array: read next lines
int remaining = n;
int col = strcmp(dtype, "R") == 0 ? 6 : 5;
while (remaining > 0 && fgets(line, sizeof(line), fp)) {
char* ptr = line;
for (int j = 0; j < col && remaining > 0; j++) {
if (sscanf(ptr, "%lf", val + (n - remaining)) == 1) {
// Advance ptr roughly
ptr = strstr(ptr, " ") + 1;
remaining--;
}
}
}
props->types[props->count] = 2; // array
}
props->ns[props->count] = n;
props->values[props->count] = val;
props->count++;
if (props->count >= MAX_PROPS) break;
}
fclose(fp);
regfree(®ex);
}
void write_fchk(FCHKProperties* props, const char* output) {
FILE* fp = fopen(output, "w");
if (!fp) return;
fprintf(fp, "%s\n", props->title);
fprintf(fp, "%-10s %-30s %-30s\n", props->type, props->method, props->basis);
for (int i = 0; i < props->count; i++) {
if (strstr(props->keys[i], "title") || strstr(props->keys[i], "type") || strstr(props->keys[i], "method") || strstr(props->keys[i], "basis")) continue;
char lbl[256];
strcpy(lbl, props->keys[i]);
for (int j = 0; lbl[j]; j++) lbl[j] = toupper(lbl[j]);
char* underscore = strstr(lbl, "_");
if (underscore) *underscore = ' ';
char dtype = props->types[i] == 0 ? 'I' : 'R';
if (props->types[i] == 2) {
fprintf(fp, "%s %c N=%d\n", lbl, dtype, props->ns[i]);
int col = 6;
double* arr = (double*) props->values[i];
for (int j = 0; j < props->ns[i]; j += col) {
for (int k = 0; k < col && j + k < props->ns[i]; k++) {
fprintf(fp, "%16.8E ", arr[j + k]);
}
fprintf(fp, "\n");
}
} else {
double v = *(double*) props->values[i];
fprintf(fp, "%s %c %.8E\n", lbl, dtype, v);
}
}
fclose(fp);
}
void print_properties(FCHKProperties* props) {
printf("Title: %s\n", props->title);
printf("Type: %s, Method: %s, Basis: %s\n", props->type, props->method, props->basis);
for (int i = 0; i < props->count; i++) {
printf("%s: ", props->keys[i]);
if (props->types[i] == 2) {
double* arr = (double*) props->values[i];
printf("[");
for (int j = 0; j < props->ns[i]; j++) {
printf("%.3f", arr[j]);
if (j < props->ns[i] - 1) printf(", ");
}
printf("]\n");
} else {
printf("%.8E\n", *(double*) props->values[i]);
}
}
}
void free_props(FCHKProperties* props) {
for (int i = 0; i < props->count; i++) {
free(props->values[i]);
}
}
// Usage: FCHKProperties props = {0}; parse_fchk(&props, "sample.fchk"); print_properties(&props); write_fchk(&props, "output.fchk"); free_props(&props);