Skip to content

Commit 7436c15

Browse files
conradhueblerclaude
andcommitted
Fix MSVC portability: popen, missing include, OpenMP index, UTF-8
- rmsd.cpp: popen/pclose are POSIX-only; guard with _popen/_pclose on Windows (matching the existing pattern in orcainterface.cpp). Also replace the alternative operator token "and" with "&&" (MSVC needs /permissive- or <ciso646> for those; GCC/Clang accept them natively). - trajectory_writer.cpp: uses std::ostringstream/stringstream without including <sstream> -- only worked because GCC's libstdc++ pulls it in transitively via other headers; MSVC's STL doesn't. - d4param_generator.cpp: three #pragma omp for loops used size_t counters; MSVC's OpenMP (2.0 semantics) requires signed loop indices, unlike GCC/Clang's OpenMP implementations. - CMakeLists.txt: add /utf-8 for MSVC. The codebase uses non-ASCII UTF-8 characters in a few identifiers/comments (e.g. "double Δqraw[6];" in xtb_gradient.cpp); without /utf-8, MSVC falls back to the system codepage and misreads the multi-byte UTF-8 sequence as unrelated characters (observed: "error C3872: 'U+201d' is not allowed in an identifier" for what is actually Δ). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent df63675 commit 7436c15

4 files changed

Lines changed: 27 additions & 6 deletions

File tree

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ project(curcuma)
77
# set this project-wide instead of patching every translation unit.
88
if(MSVC)
99
add_compile_definitions(_USE_MATH_DEFINES)
10+
# Claude Generated 2026 - the codebase uses non-ASCII UTF-8 characters in a few
11+
# identifiers/comments (e.g. "double Δqraw[6];" in xtb_gradient.cpp). Without
12+
# /utf-8, MSVC falls back to the system codepage to interpret the source file,
13+
# misreading the multi-byte UTF-8 sequence as unrelated characters (observed:
14+
# "error C3872: 'U+201d' is not allowed in an identifier" for what is actually Δ).
15+
add_compile_options(/utf-8)
1016
endif()
1117

1218
option (USE_XTB

src/capabilities/rmsd.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1659,7 +1659,11 @@ bool RMSDDriver::MolAlignLib()
16591659
std::string command = m_molalign + m_molalignarg + " " + ref_tmp + " " + tar_tmp + " 2>&1";
16601660
if (m_verbosity >= 3)
16611661
CurcumaLogger::info_fmt("MolAlign command: {}", command);
1662+
#ifdef _WIN32
1663+
FileOpen = _popen(command.c_str(), "r");
1664+
#else
16621665
FileOpen = popen(command.c_str(), "r");
1666+
#endif
16631667
bool ok = true;
16641668
bool rndm = false;
16651669
bool error = false;
@@ -1674,10 +1678,14 @@ bool RMSDDriver::MolAlignLib()
16741678
CurcumaLogger::debug(2, fmt::format("MolAlign output: {}", std::string(line).substr(0, std::string(line).find('\n'))));
16751679
#endif
16761680
}
1681+
#ifdef _WIN32
1682+
_pclose(FileOpen);
1683+
#else
16771684
pclose(FileOpen);
1685+
#endif
16781686

16791687
std::string aligned_tmp = outputPath("aligned.xyz");
1680-
if (std::filesystem::exists(aligned_tmp) and !rndm) {
1688+
if (std::filesystem::exists(aligned_tmp) && !rndm) {
16811689
CurcumaLogger::citation("molalign");
16821690
FileIterator file(aligned_tmp, true);
16831691
m_reference_centered = file.Next();

src/core/energy_calculators/dispersion/d4param_generator.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,11 @@ void D4ParameterGenerator::GenerateParameters(const std::vector<int>& atoms, con
434434

435435
// NOTE: Cannot use collapse(2) with triangular loops (j = i + 1)
436436
// Parallelize outer loop only, still provides good speedup
437+
// Claude Generated 2026 - MSVC's OpenMP (2.0 semantics) requires a signed
438+
// loop index; GCC/Clang accept size_t fine, so this was never caught before.
437439
#pragma omp for schedule(dynamic, 10)
438-
for (size_t i = 0; i < m_atoms.size(); ++i) {
439-
for (size_t j = i + 1; j < m_atoms.size(); ++j) {
440+
for (int i = 0; i < static_cast<int>(m_atoms.size()); ++i) {
441+
for (int j = i + 1; j < static_cast<int>(m_atoms.size()); ++j) {
440442
int atom_i = m_atoms[i];
441443
int atom_j = m_atoms[j];
442444

@@ -747,8 +749,10 @@ void D4ParameterGenerator::GenerateParameters(const std::vector<int>& atoms, con
747749
{
748750
std::vector<json> local_triples;
749751

752+
// Claude Generated 2026 - MSVC's OpenMP (2.0 semantics) requires a signed
753+
// loop index; GCC/Clang accept size_t fine, so this was never caught before.
750754
#pragma omp for schedule(dynamic, 10)
751-
for (size_t idx = 0; idx < triplet_vec.size(); ++idx) {
755+
for (int idx = 0; idx < static_cast<int>(triplet_vec.size()); ++idx) {
752756
int i = std::get<0>(triplet_vec[idx]);
753757
int j = std::get<1>(triplet_vec[idx]);
754758
int k = std::get<2>(triplet_vec[idx]);
@@ -2018,9 +2022,11 @@ std::vector<GFNFFDispersion> D4ParameterGenerator::GenerateDispersionPairsNative
20182022
{
20192023
std::vector<GFNFFDispersion> local_pairs;
20202024

2025+
// Claude Generated 2026 - MSVC's OpenMP (2.0 semantics) requires a signed
2026+
// loop index; GCC/Clang accept size_t fine, so this was never caught before.
20212027
#pragma omp for schedule(dynamic, 10)
2022-
for (size_t i = 0; i < m_atoms.size(); ++i) {
2023-
for (size_t j = i + 1; j < m_atoms.size(); ++j) {
2028+
for (int i = 0; i < static_cast<int>(m_atoms.size()); ++i) {
2029+
for (int j = i + 1; j < static_cast<int>(m_atoms.size()); ++j) {
20242030
double r2 = (geometry_bohr.row(i) - geometry_bohr.row(j)).squaredNorm();
20252031
if (r2 > disp_cutoff_sq) continue;
20262032

src/tools/trajectory_writer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "trajectory_writer.h"
88
#include "../capabilities/trajectory_statistics.h"
99
#include <iomanip>
10+
#include <sstream>
1011
#include <algorithm>
1112
#include "../core/curcuma_logger.h"
1213

0 commit comments

Comments
 (0)