Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Gaussian job and handlers #328

Merged
merged 93 commits into from
Apr 24, 2024
Merged

New Gaussian job and handlers #328

merged 93 commits into from
Apr 24, 2024

Conversation

janosh
Copy link
Member

@janosh janosh commented Apr 3, 2024

merging working branch gaussian into master. follow-up to #325. all credit to @rashatwi

Summary by CodeRabbit

  • New Features

    • Introduced a new Gaussian Jobs package for managing Gaussian runs, including error handling and job setup.
    • Added a range of mock input files for Gaussian calculations covering various molecular optimization scenarios.
    • Enhanced pre-commit configuration to include more aggressive linting options.
  • Bug Fixes

    • Implemented error handlers for common issues in Gaussian calculations such as wall time limits and SCF convergence.
  • Tests

    • Added comprehensive test cases for Gaussian job management and error handling functionalities.
  • Chores

    • Included new dependencies necessary for Gaussian-related functionalities in the project setup.

@janosh janosh added enhancement handler Error handler gaussian Gaussian package labels Apr 3, 2024
@janosh
Copy link
Member Author

janosh commented Apr 3, 2024

@rashatwi could you have a quick look at the CI logs why the test files can no longer be found?

@rashatwi
Copy link
Contributor

rashatwi commented Apr 3, 2024

@janosh The mentioned files in the error messages are in the correct location (under tests/files/gaussian), I'm not sure why this error is occurring. When I run locally, all the tests succeed. The .out.gz files are getting replaced by .out files (decompressed) before the tests run, which is causing the FileNotFoundError.

@rashatwi
Copy link
Contributor

@janosh I fixed the issue with the test files on my forked repo. Should I create a new PR?

@janosh
Copy link
Member Author

janosh commented Apr 23, 2024

that would be great, thanks! sorry for letting this slip. was hoping to get back to it sooner

Copy link

coderabbitai bot commented Apr 24, 2024

Walkthrough

The latest update enhances the custodian package with new Gaussian computational chemistry capabilities, including job handling and error management. It introduces new modules for Gaussian jobs and handlers, along with extensive test cases and mock files for simulations. Additionally, the .pre-commit-config.yaml file has been updated to include more aggressive linting options.

Changes

Files Summary
.pre-commit-config.yaml Updated ruff hook arguments to include --unsafe-fixes.
custodian/gaussian/... Introduced Gaussian job handling and error management modules.
pyproject.toml Added dependencies for Gaussian functionality.
tests/files/gaussian/... (multiple .com files) Added various Gaussian input files for testing different computational scenarios.
tests/gaussian/... Added new test modules for Gaussian job and error handling functionalities.

Poem

🐇💻
In the world of code, where logic is king,
A rabbit hopped in, bringing Gaussian things.
With jobs and errors, it danced and twirled,
Crafting a domain where molecules unfurled.
Cheers to changes, big and small,
In the land of atoms, we now stand tall! 🎉🔬


Recent Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 866661d and 67c79dd.
Files ignored due to path filters (21)
  • tests/files/gaussian/bad_file.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/coord_inputs.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/coords_dict_geom.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/coords_string_geom.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/found_coords.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/insufficient_memory.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/linear_bend.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/missing_file.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/missing_mol.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/mol_opt.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/opt_steps_better_guess.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/opt_steps_cycles.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/opt_steps_from_structure.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/opt_steps_int_grid.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/scf_convergence_algorithm.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/scf_convergence_better_guess.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/scf_convergence_cycles.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/solute_solvent_surface.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/syntax.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/walltime.out.gz is excluded by !**/*.gz
  • tests/files/gaussian/zmatrix.out.gz is excluded by !**/*.gz
Files selected for processing (32)
  • .pre-commit-config.yaml (1 hunks)
  • custodian/gaussian/init.py (1 hunks)
  • custodian/gaussian/handlers.py (1 hunks)
  • custodian/gaussian/jobs.py (1 hunks)
  • pyproject.toml (1 hunks)
  • tests/files/gaussian/Checkpoint.chk (1 hunks)
  • tests/files/gaussian/Gau-mock.rwf (1 hunks)
  • tests/files/gaussian/Optimization.chk (1 hunks)
  • tests/files/gaussian/bad_file.com (1 hunks)
  • tests/files/gaussian/coord_inputs.com (1 hunks)
  • tests/files/gaussian/coords_dict_geom.com (1 hunks)
  • tests/files/gaussian/coords_string_geom.com (1 hunks)
  • tests/files/gaussian/found_coords.com (1 hunks)
  • tests/files/gaussian/insufficient_memory.com (1 hunks)
  • tests/files/gaussian/linear_bend.com (1 hunks)
  • tests/files/gaussian/missing_file.com (1 hunks)
  • tests/files/gaussian/missing_mol.com (1 hunks)
  • tests/files/gaussian/mol_opt.com (1 hunks)
  • tests/files/gaussian/opt_steps_better_guess.com (1 hunks)
  • tests/files/gaussian/opt_steps_cycles.com (1 hunks)
  • tests/files/gaussian/opt_steps_from_structure.com (1 hunks)
  • tests/files/gaussian/opt_steps_int_grid.com (1 hunks)
  • tests/files/gaussian/scf_convergence_algorithm.com (1 hunks)
  • tests/files/gaussian/scf_convergence_better_guess.com (1 hunks)
  • tests/files/gaussian/scf_convergence_cycles.com (1 hunks)
  • tests/files/gaussian/solute_solvent_surface.com (1 hunks)
  • tests/files/gaussian/syntax.com (1 hunks)
  • tests/files/gaussian/walltime.com (1 hunks)
  • tests/files/gaussian/zmatrix.com (1 hunks)
  • tests/gaussian/init.py (1 hunks)
  • tests/gaussian/test_handlers.py (1 hunks)
  • tests/gaussian/test_jobs.py (1 hunks)
Files skipped from review due to trivial changes (4)
  • tests/files/gaussian/Checkpoint.chk
  • tests/files/gaussian/Gau-mock.rwf
  • tests/files/gaussian/Optimization.chk
  • tests/gaussian/init.py
Additional Context Used
Ruff (1)
custodian/gaussian/__init__.py (1)

1-3: One-line docstring should fit on one line

Additional comments not posted (36)
tests/files/gaussian/bad_file.com (1)

1-9: The Gaussian input file parameters and structure appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/missing_file.com (1)

1-11: The Gaussian input file parameters and structure appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/missing_mol.com (1)

1-12: The Gaussian input file parameters and structure appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/zmatrix.com (1)

1-24: The Gaussian input file parameters and z-matrix structure appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/mol_opt.com (1)

1-24: The Gaussian input file parameters and molecular configuration appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/opt_steps_cycles.com (1)

1-24: The Gaussian input file parameters and optimization settings appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/opt_steps_from_structure.com (1)

1-24: The Gaussian input file parameters and optimization settings appear correctly formatted and consistent with typical Gaussian job requirements.

tests/files/gaussian/scf_convergence_algorithm.com (1)

1-27: Configuration setup for Gaussian job appears correct and well-defined.

tests/files/gaussian/scf_convergence_cycles.com (1)

1-27: Configuration setup for Gaussian job appears correct and well-defined.

tests/files/gaussian/scf_convergence_better_guess.com (1)

1-27: Configuration setup for Gaussian job with improved initial guess settings appears correct and beneficial.

tests/files/gaussian/opt_steps_int_grid.com (1)

1-27: Configuration setup for Gaussian job with specific optimization and integration grid settings appears correct.

tests/files/gaussian/coord_inputs.com (1)

1-27: Configuration setup for Gaussian job using z-matrix coordinates appears correct and well-defined.

tests/files/gaussian/found_coords.com (1)

1-27: Configuration setup for Gaussian job to use geometry from a checkpoint file appears correct and useful for continuing previous calculations.

tests/files/gaussian/opt_steps_better_guess.com (1)

1-27: Configuration setup for Gaussian job with optimization steps and a better initial guess appears correct and aimed at enhancing calculation efficiency.

tests/files/gaussian/coords_string_geom.com (1)

1-27: Configuration setup for Gaussian job using string-based geometry connectivity appears correct and well-defined.

tests/files/gaussian/coords_dict_geom.com (2)

1-4: Ensure the Gaussian directives are correctly configured for the intended computations.


6-24: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

.pre-commit-config.yaml (1)

13-13: Confirm the inclusion of --unsafe-fixes aligns with the project's coding standards and safety requirements.

tests/files/gaussian/insufficient_memory.com (1)

6-34: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

tests/files/gaussian/linear_bend.com (2)

1-4: Ensure the Gaussian directives are correctly configured for the intended computations.


6-47: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

tests/files/gaussian/syntax.com (1)

6-47: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

tests/files/gaussian/solute_solvent_surface.com (2)

1-4: Ensure the Gaussian directives are correctly configured for the intended computations, especially given the complexity of the solute-solvent system.


6-61: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

tests/files/gaussian/walltime.com (2)

1-4: Ensure the Gaussian directives are correctly configured for the intended computations, especially in the context of wall time testing.


6-68: Verify the molecular geometry and charge/multiplicity settings are appropriate for the intended chemical computations.

tests/gaussian/test_jobs.py (1)

22-83: Ensure the test cases for GaussianJob are comprehensive and cover all necessary scenarios, including error handling and edge cases.

pyproject.toml (1)

44-44: Dependency addition approved.

The addition of the gaussian dependency with pymatgen and matplotlib is consistent with the PR's objectives to enhance Gaussian computational chemistry functionalities.

custodian/gaussian/jobs.py (2)

30-120: Implementation of GaussianJob class approved.

The GaussianJob class is well-structured and includes appropriate methods for managing Gaussian jobs. The use of subprocess for running commands and the file management functionalities (backup and suffix) are well implemented.


120-202: Implementation of generate_better_guess method approved.

The generate_better_guess method is well-designed, using a generator to yield GaussianJob instances for better initial guesses. The integration with GaussianErrorHandler and the management of input and output files are handled appropriately.

tests/gaussian/test_handlers.py (1)

31-374: Test cases implementation approved.

The test cases in tests/gaussian/test_handlers.py are comprehensive and well-implemented. They appropriately test various Gaussian error handlers across different scenarios, ensuring robust error handling in Gaussian jobs.

custodian/gaussian/handlers.py (5)

43-47: Class definition and documentation are clear and concise.


158-188: Method implementation for recursive lowercase conversion is efficient and correct.


815-820: Class definition and documentation for WallTimeErrorHandler are clear and concise.


824-848: Initialization of WallTimeErrorHandler is robust and correctly handles the setup of wall time and buffer time.


864-871: Method for checking wall time is correctly implemented and efficiently calculates time remaining.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Comment on lines +1 to +3
"""
This package implements various Gaussian Jobs and Error Handlers.
"""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condense the multi-line docstring into a single line to adhere to Python best practices.

- """
- This package implements various Gaussian Jobs and Error Handlers.
- """
+ """This package implements various Gaussian Jobs and Error Handlers."""

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
"""
This package implements various Gaussian Jobs and Error Handlers.
"""
"""This package implements various Gaussian Jobs and Error Handlers."""

Comment on lines +98 to +111
def __init__(
self,
input_file: str,
output_file: str,
stderr_file: str = "stderr.txt",
cart_coords: bool = True,
scf_max_cycles: int = 100,
opt_max_cycles: int = 100,
job_type: str = "normal",
lower_functional: str | None = None,
lower_basis_set: str | None = None,
prefix: str = "error",
check_convergence: bool = True,
):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider setting default values for parameters like lower_functional and lower_basis_set to enhance robustness.

Comment on lines +190 to +219
@staticmethod
def _recursive_remove_space(obj: dict[str, Any]) -> dict[str, Any]:
"""
Recursively remove leading and trailing whitespace from keys and string values
in a dictionary.

This method processes each key-value pair in the given dictionary. If a value
is a string, it strips leading and trailing whitespace from it. If a value is
a dictionary, it applies the same stripping process recursively to that
dictionary. The keys of the dictionary are also stripped of leading and trailing
whitespace. Non-string values are included in the output without modification.

Args:
obj (dict): The dictionary whose keys and string values will have whitespace
removed. It can be nested, with dictionaries as values, which will
also be processed.

Returns:
dict:
A new dictionary with all keys and string values stripped of leading
and trailing whitespace. The structure of the dictionary is preserved.
"""
return {
key.strip(): GaussianErrorHandler._recursive_remove_space(value)
if isinstance(value, dict)
else value.strip()
if isinstance(value, str)
else value
for key, value in obj.items()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimize the method by reducing unnecessary recursion for non-dictionary types.

Comment on lines +221 to +246
@staticmethod
def _update_route_params(route_params: dict, key: str, value: str | dict) -> dict:
"""
Update Gaussian route parameters with new key-value pairs, handling nested
structures.

Args:
route_params (dict): The dictionary of route parameters to be updated.
key (str): The key in the route parameters to update or add.
value (str | dict): The new value to set or add to the route parameters.
This can be a string or a dictionary. If it is a dictionary, it is
merged with the existing dictionary at `key`.

Returns:
dict:
The updated route parameters.
"""
obj = route_params.get(key, {})
if not obj:
route_params[key] = value
elif isinstance(obj, str):
update = {key: {obj: None, **value}} if isinstance(value, dict) else {key: {obj: None, value: None}}
route_params.update(update)
elif isinstance(obj, dict):
route_params[key].update(value if isinstance(value, dict) else {value: None})
return route_params
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure type safety and error handling in the _update_route_params method to prevent runtime errors.

Comment on lines +472 to +526
def check(self, directory: str = "./") -> bool:
"""Check for errors in the Gaussian output file."""
# TODO: this backups the original file instead of the actual one
if "linear_bend" in self.errors:
os.rename(
os.path.join(directory, self.input_file + ".prev"),
os.path.join(directory, self.input_file),
)

self.gin = GaussianInput.from_file(os.path.join(directory, self.input_file))
self.gin.route_parameters = GaussianErrorHandler._recursive_lowercase(self.gin.route_parameters)
assert isinstance(self.gin.route_parameters, dict)
self.gin.route_parameters = GaussianErrorHandler._recursive_remove_space(self.gin.route_parameters)
self.gout = GaussianOutput(os.path.join(directory, self.output_file))
self.errors = set()
error_patts = set()
# TODO: move this to pymatgen?
self.conv_data = {"values": {}, "thresh": {}}
with zopen(os.path.join(directory, self.output_file)) as f:
for line in f:
error_match = GaussianErrorHandler.error_patt.search(line)
mem_match = GaussianErrorHandler.recom_mem_patt.search(line)
if error_match:
patt = error_match.group(0)
error_patts.add(patt)
for pattern, error_key in GaussianErrorHandler.error_defs.items():
if re.match(pattern, patt):
self.errors.add(error_key)
break
# self.errors.add(GaussianErrorHandler.error_defs[patt])
if mem_match:
mem = mem_match.group(1)
self.recom_mem = GaussianErrorHandler.convert_mem(float(mem), "mw")

if self.check_convergence and "opt" in self.gin.route_parameters:
for k, v in GaussianErrorHandler.conv_critera.items():
m = v.search(line)
if m:
if k not in self.conv_data["values"]:
self.conv_data["values"][k] = [m.group(2)]
self.conv_data["thresh"][k] = float(m.group(3))
else:
self.conv_data["values"][k].append(m.group(2))

# TODO: it only plots after the job finishes, modify?
if self.conv_data["values"] and all(len(v) >= 2 for v in self.conv_data["values"].values()):
for k, v in self.conv_data["values"].items():
# convert strings to float taking into account the
# possibility of having ******** values
self.conv_data["values"][k] = np.genfromtxt(np.array(v))
GaussianErrorHandler._monitor_convergence(self.conv_data)
for patt in error_patts:
self.logger.error(patt)
return len(self.errors) > 0

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address the TODO about moving functionality to the pymatgen module to maintain separation of concerns.

Would you like me to help refactor this part of the code or open a GitHub issue to track this task?

Comment on lines +527 to +800
self.logger.info("Missing blank line at the end of the input file.")
actions.append({"blank_lines": "rewrite_input_file"})
else:
self.logger.info("Not sure how to fix zmatrix error. Check manually?")
return {"errors": [self.errors], "actions": None}

elif "coords" in self.errors:
if "connectivity" in self.gin.route_parameters.get("geom"):
self.logger.info("Explicit atom bonding is requested but no such input is provided")
if isinstance(self.gin.route_parameters["geom"], dict) and len(self.gin.route_parameters["geom"]) > 1:
self.gin.route_parameters["geom"].pop("connectivity", None)
else:
del self.gin.route_parameters["geom"]
actions.append({"coords": "remove_connectivity"})
else:
self.logger.info("Missing connectivity info. Not sure how to fix this error. Exiting!")
return {"errors": [self.errors], "actions": None}

elif "found_coords" in self.errors:
if self.gin.molecule and any(
key in self.gin.route_parameters.get("geom", {}) for key in ["checkpoint", "check", "allcheck"]
):
# if coords are found in the input and the user chooses to read
# the molecule specification from the checkpoint file,
# remove mol
self.gin._mol = None
actions.append({"mol": "remove_from_input"})
else:
self.logger.info("Not sure why atom specifications should not be found in the input. Examine manually!")
return {"errors": [self.errors], "actions": None}

elif "coord_inputs" in self.errors:
if (
any(key in self.gin.route_parameters.get("opt", {}) for key in ["z-matrix", "zmatrix"])
and self.cart_coords
):
# if molecule is specified in xyz format, but the user chooses
# to perform the optimization using internal coordinates,
# switch to z-matrix format
self.cart_coords = False
actions.append({"coords": "use_zmatrix_format"})
else:
# error cannot be fixed automatically. Return None for actions
self.logger.info(
"Not sure how to fix problem with z-matrix "
"optimization if coords are already input in"
"z-matrix format. Examine manually!"
)
return {"errors": [self.errors], "actions": None}

elif "missing_mol" in self.errors:
if (
not self.gin.molecule
and "read" in self.gin.route_parameters.get("guess")
and not any(
key in self.gin.route_parameters.get("geom", {}) for key in ["checkpoint", "check", "allcheck"]
)
):
# if molecule is not specified and the user requests that the
# initial guess be read from the checkpoint file but forgot to
# take the geom from the checkpoint file, add geom=check
if not glob.glob("*.[Cc][Hh][Kk]"):
raise FileNotFoundError("This remedy reads geometry from checkpoint file. This file is missing!")
GaussianErrorHandler._update_route_params(self.gin.route_parameters, "geom", "check")
self.gin.route_parameters["geom"] = "check"
actions.append({"mol": "get_from_checkpoint"})
else:
# error cannot be fixed automatically. Return None for actions
self.logger.info("Molecule is not found in the input file. Fix manually!")
# TODO: check if logger.info is enough here or return is needed
return {"errors": list(self.errors), "actions": None}

elif any(err in self.errors for err in ["empty_file", "bad_file"]):
self.logger.error("Required checkpoint file is bad. Fix manually!")
return {"errors": list(self.errors), "actions": None}

elif "missing_file" in self.errors:
self.logger.error("Could not find the required file. Fix manually!")
return {"errors": list(self.errors), "actions": None}

elif "syntax" in self.errors:
# error cannot be fixed automatically. Return None for actions
self.logger.info("A syntax error was detected in the input file. Fix manually!")
return {"errors": list(self.errors), "actions": None}

elif "insufficient_mem" in self.errors:
mem_key, dynamic_mem = GaussianErrorHandler._find_dynamic_memory_allocated(self.gin.link0_parameters)
if dynamic_mem and self.recom_mem and dynamic_mem < self.recom_mem:
# this assumes that 1.5*minimum required memory is available
mem = math.ceil(self.recom_mem * 1.5)
self.gin.link0_parameters[mem_key] = f"{mem}MB"
actions.append({"memory": "increase_to_gaussian_recommendation"})
else:
self.logger.info("Check job memory requirements manually and set as needed.")
return {"errors": list(self.errors), "actions": None}

else:
self.logger.info("Must have gotten an error that is parsed but not handled yet. Fix manually!")
return {"errors": list(self.errors), "actions": None}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolve TODOs in the correct method to ensure all edge cases and potential issues are handled.

Would you like assistance in addressing these TODOs or should I open a GitHub issue for further discussion?

Comment on lines +873 to +893
def correct(self, directory: str = "./") -> dict:
"""Perform the corrections."""
# TODO: when using restart, the rwf file might be in a different dir
backup_files = [self.input_file, self.output_file, self.stderr_file, *BACKUP_FILES.values()]
backup(backup_files, prefix=self.prefix, directory=directory)
if glob.glob(os.path.join(directory, BACKUP_FILES["rwf"])):
rwf = glob.glob(os.path.join(directory, BACKUP_FILES["rwf"]))[0]
gin = GaussianInput.from_file(os.path.join(directory, self.input_file))
# TODO: check if rwf is already there like RWF or Rwf or ...
# gin.link0_parameters.update({'%rwf': rwf})
# gin.route_parameters = {'Restart': None}
# os.rename(self.input_file, self.input_file + '.prev')
input_str = [f"%rwf={rwf}"] + [f"{i}={j}" for i, j in gin.link0_parameters.items()]
input_str.append(f"{gin.dieze_tag} Restart\n\n")
with open(os.path.join(directory, self.input_file + ".wt"), "w") as f:
f.write("\n".join(input_str))
return {"errors": ["wall_time_limit"], "actions": None}
self.logger.info(
"Wall time handler requires a read-write gaussian file to be available. No such file is found."
)
return {"errors": ["Walltime reached but not rwf file found"], "actions": None}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address the TODO about handling file locations during restarts to ensure robustness in file management.

Would you like me to help refactor this part of the code or open a GitHub issue to track this task?

@@ -0,0 +1,34 @@
%chk=Optimization.chk
%Mem=1MB
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The memory setting of 1MB is likely insufficient for any Gaussian computation. Consider increasing this to a more realistic value.

%chk=Optimization.chk
%mem=100GB
%NProcShared=28
#P B3LYP/6-311++G** Opt=(MaxCycless=100) SCF SCRF=(PCM, Solvent=TetraHydroFuran)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the typo in the Gaussian directive from MaxCycless to MaxCycles.

- #P B3LYP/6-311++G** Opt=(MaxCycless=100) SCF SCRF=(PCM, Solvent=TetraHydroFuran)
+ #P B3LYP/6-311++G** Opt=(MaxCycles=100) SCF SCRF=(PCM, Solvent=TetraHydroFuran)

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
#P B3LYP/6-311++G** Opt=(MaxCycless=100) SCF SCRF=(PCM, Solvent=TetraHydroFuran)
#P B3LYP/6-311++G** Opt=(MaxCycles=100) SCF SCRF=(PCM, Solvent=TetraHydroFuran)

@janosh janosh merged commit 8f83e59 into master Apr 24, 2024
7 of 8 checks passed
@janosh janosh deleted the gaussian branch April 24, 2024 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement gaussian Gaussian package handler Error handler
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants