diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1c27bb2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,110 @@ +# Copyright 2022 NWChemEx-Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +Language: Cpp +# BasedOnStyle: Mozilla +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakAfterJavaFieldAnnotations: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"' + Priority: 1 + - Regex: '^<' + Priority: 2 +IncludeIsMainRegex: '(Test)$' +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/.gitignore b/.gitignore index 1513a8d..1647875 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ # These are directories used by IDEs for storing settings .idea/ .vscode/ +.cache/ # These are common Python virtual enviornment directory names venv/ diff --git a/src/cxx/nux/nux.cpp b/src/cxx/nux/nux.cpp index 368a69e..0812604 100644 --- a/src/cxx/nux/nux.cpp +++ b/src/cxx/nux/nux.cpp @@ -21,6 +21,7 @@ namespace nux { void load_modules(pluginplay::ModuleManager &mm) { mm.add_module("Born-Oppenheimer Approximation"); + mm.add_module("XYZ To Molecule"); } -} // namespace nux \ No newline at end of file +} // namespace nux diff --git a/src/cxx/nux/nux_modules.hpp b/src/cxx/nux/nux_modules.hpp index a223e16..a6d64ba 100644 --- a/src/cxx/nux/nux_modules.hpp +++ b/src/cxx/nux/nux_modules.hpp @@ -20,5 +20,6 @@ namespace nux { DECLARE_MODULE(BOApproximation); +DECLARE_MODULE(XYZToMolecule); -} \ No newline at end of file +} diff --git a/src/cxx/nux/xyz_to_mol.cpp b/src/cxx/nux/xyz_to_mol.cpp new file mode 100644 index 0000000..ef42832 --- /dev/null +++ b/src/cxx/nux/xyz_to_mol.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2025 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nux_modules.hpp" +#include +#include +#include +#include + +namespace nux { + + MODULE_CTOR(XYZToMolecule) { + satisfies_property_type(); + add_submodule("Z from symbol"); + add_submodule("Atom from z"); + } + + MODULE_RUN(XYZToMolecule) { + const auto& [filename] = simde::MoleculeFromString::unwrap_inputs(inputs); + + auto& z_from_sym = submods.at("Z from symbol"); + auto& atom_from_z = submods.at("Atom from z"); + + chemist::Molecule mol; + + std::ifstream xyz_file(filename); + + if (!xyz_file) { + throw std::runtime_error("File not found: " + filename); + } + + std::string line; + + // Skips the 1st line of the file, associated with the number of + // atoms in the file, and the 2nd line, the comment line. + std::getline(xyz_file, line); + std::getline(xyz_file, line); + + while (std::getline(xyz_file, line)) { + std::istringstream iss(line); + std::vector tokens; + std::string token; + while (std::getline(iss, token, ' ')) { + if (token.size()) { tokens.emplace_back(token); } + } + auto Z = z_from_sym.run_as(tokens.at(0)); + auto x = std::stod(tokens.at(1)); + auto y = std::stod(tokens.at(2)); + auto z = std::stod(tokens.at(3)); + + auto atm = atom_from_z.run_as(Z); + atm.x() = x; + atm.y() = y; + atm.z() = z; + mol.push_back(atm); + } + + xyz_file.close(); + + auto rv = results(); + return simde::MoleculeFromString::wrap_results(rv, mol); + } + +} // namespace nux diff --git a/tests/cxx/unit_tests/xyz_to_mol.cpp b/tests/cxx/unit_tests/xyz_to_mol.cpp new file mode 100644 index 0000000..ce76c97 --- /dev/null +++ b/tests/cxx/unit_tests/xyz_to_mol.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2024 NWChemEx-Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../test_nux.hpp" +#include + +TEST_CASE("XYZToMolecule") { + pluginplay::ModuleManager mm; + nux::load_modules(mm); + + auto make_atoms = [=](auto&& Z) { + REQUIRE(Z == 1); + double h_mass = 1837.4260218693814; + return simde::type::atom{"H", 1, h_mass, 0.0, 0.0, 0.0}; + }; + + auto atom_mod = pluginplay::make_lambda(make_atoms); + + auto z_mod = pluginplay::make_lambda([=](auto&& symbol) { + return simde::type::atomic_number{1}; + }); + + auto& xyz_mod = mm.at("XYZ To Molecule"); + xyz_mod.change_submod("Z from symbol", z_mod); + xyz_mod.change_submod("Atom from z", atom_mod); + + SECTION("No XYZ file found") { + std::string file = "file.xyz"; + REQUIRE_THROWS_AS(xyz_mod.run_as(file), std::runtime_error); + } + + SECTION("Full XYZ To Molecule run") { + auto atom0{make_atoms(1)}; + auto atom1{make_atoms(1)}; + atom1.z() = 1; + + simde::type::molecule test_mol{atom0, atom1}; + + std::ofstream xyz_file; + xyz_file.open("h2.xyz"); + + xyz_file << "2\n"; + xyz_file << "This is a comment!\n"; + xyz_file << "H 0 0 0\n"; + xyz_file << "H 0 0 1\n"; + xyz_file.close(); + + std::string filename = "h2.xyz"; + + auto mol = xyz_mod.run_as(filename); + + remove("h2.xyz"); + std::ifstream del_file("h2.xyz"); + + REQUIRE(mol == test_mol); + REQUIRE(del_file.good() == false); + } +}