Skip to content

[Code scan] Avoid mutating CP2K default_config across input generations #1907

Description

@njzjz

This issue is from a Codex global scan of the repository.

CP2K input generation mutates the module-level default_config, so settings from one generated input can leak into later inputs in the same Python process.

Evidence:

default_config = {
"GLOBAL": {"PROJECT": "DPGEN"},
"FORCE_EVAL": {
"METHOD": "QS",
"STRESS_TENSOR": "ANALYTICAL",
"DFT": {
"BASIS_SET_FILE_NAME": "./cp2k_basis_pp_file/BASIS_MOLOPT",
"POTENTIAL_FILE_NAME": "./cp2k_basis_pp_file/GTH_POTENTIALS",
"CHARGE": 0,
"UKS": "F",
"MULTIPLICITY": 1,
"MGRID": {"CUTOFF": 400, "REL_CUTOFF": 50, "NGRIDS": 4},
"QS": {"EPS_DEFAULT": "1.0E-12"},
"SCF": {"SCF_GUESS": "ATOMIC", "EPS_SCF": "1.0E-6", "MAX_SCF": 50},
"XC": {"XC_FUNCTIONAL": {"_": "PBE"}},
},
"SUBSYS": {
"CELL": {"A": "10 .0 .0", "B": ".0 10 .0", "C": ".0 .0 10"},
"COORD": {"@include": "coord.xyz"},
"KIND": {
"_": ["H", "C", "N"],
"POTENTIAL": ["GTH-PBE-q1", "GTH-PBE-q4", "GTH-PBE-q5"],
"BASIS_SET": ["DZVP-MOLOPT-GTH", "DZVP-MOLOPT-GTH", "DZVP-MOLOPT-GTH"],
},
},
"PRINT": {"FORCES": {"_": "ON"}, "STRESS_TENSOR": {"_": "ON"}},
},
}

def update_dict(old_d, update_d):
"""A method to recursive update dict
:old_d: old dictionary
:update_d: some update value written in dictionary form.
"""
import collections.abc
for k, v in update_d.items():
if (
k in old_d
and isinstance(old_d[k], dict)
and isinstance(update_d[k], collections.abc.Mapping)
):
update_dict(old_d[k], update_d[k])
else:
old_d[k] = update_d[k]

# get update from user
user_config = fp_params
# get update from cell
cell_config = {
"FORCE_EVAL": {"SUBSYS": {"CELL": {"A": cell_a, "B": cell_b, "C": cell_c}}}
}
# get update for multiplicity
multiplicity_config = {"FORCE_EVAL": {"DFT": {"MULTIPLICITY": multiplicity}}}
update_dict(default_config, user_config)
update_dict(default_config, cell_config)
update_dict(default_config, multiplicity_config)
# output list
input_str = []
iterdict(default_config, input_str)
string = "\n".join(input_str)

update_dict() mutates its first argument in place, and make_cp2k_input() calls it directly on the module global default_config. Any user override, generated cell, or multiplicity value remains in default_config for the next call unless overwritten again.

Expected behavior: each make_cp2k_input() call should start from a deep copy of default_config before applying user and structure-specific updates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions