- An MR ENANTIOMORPH decision is taken into the answer's label only as --model takes a model's enantiomorph: ValidateAgainstModel runs on the placed model (in a scratch directory, removed after) and its adopted_model_enantiomorph - fit over its null, anomalous map at the atoms not inverted - decides; otherwise ENANTIOMORPH_VETOED. The hand-check numbers go to the MODEL PRIOR section. - Rotation and translation functions on the GPU (MolecularReplacementGPU.cu): one block per orientation for the rotation function; per orientation the copies, the bin weights, a gather of the Crowther-Blow coefficients (CSR lists, fixed order, no atomics) and a cuFFT C2R, block-reduced statistics finished on the host in a fixed order. The CPU path (FFTW) is unchanged in what it computes; the orientation-independent part of the translation function (TranslationSetup) is now built once per group on either path. - Rescoring: a placement clashing with its mates over twice the limit is not refined, one rigid-body engine per group, and the null is built only for the candidate the choice falls on. Measured MR step on the RTX 5080 (before -> after, seconds; hand check extra where it runs): 3r6o 1.77 -> 0.67, neg 2.14 -> 0.37, 11if 1.20 -> 0.51 (+0.6 hand check), 7ris 1.46 -> 0.56 (+0.6), 9zmu 4.71 -> 1.07 (+0.9). Rotation 0.50 -> 0.02 s and translation 1.17 -> 0.13 s on 9zmu. Mirrored-detector runs of two anomalous lysozyme sets: the hand check vetoes (map inverted at the model's atoms); the unmirrored runs adopt. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
38 lines
1.7 KiB
C++
38 lines
1.7 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
// The molecular-replacement search on a GPU (CUDA builds only; the header itself needs no CUDA): the
|
|
// rotation function and the translation function of MolecularReplacement.h, the same functions as the
|
|
// CPU computes - the same trilinear interpolation of the same molecular transform, the same bins, the
|
|
// same coefficients on the same grid - in float on the device, with cuFFT for FFTW. The two agree to
|
|
// rounding, not bit for bit. Every reduction runs in a fixed order and nothing is summed with an
|
|
// atomic, so the GPU is deterministic on its own.
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "MolecularReplacement.h"
|
|
|
|
struct MolecularReplacementGPUState;
|
|
struct MolecularReplacementGPUGroup;
|
|
|
|
class MolecularReplacementGPU {
|
|
public:
|
|
// Uploads the molecular transform, on the calling thread's current device. Throws JFJochException on
|
|
// a CUDA failure, as every call below does.
|
|
explicit MolecularReplacementGPU(const MolecularTransform &ft);
|
|
~MolecularReplacementGPU();
|
|
|
|
std::vector<double> RotationFunction(const SearchReflections &refl, const gemmi::UnitCell &cell,
|
|
const gemmi::SpaceGroup &sg, const std::vector<gemmi::Mat33> &rotations);
|
|
|
|
// The translation function of one group at each of `rotations`.
|
|
std::vector<TranslationPeak> TranslationFunction(const TranslationSetup &setup,
|
|
const std::vector<gemmi::Mat33> &rotations);
|
|
|
|
private:
|
|
std::unique_ptr<MolecularReplacementGPUState> state_;
|
|
};
|