Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/module/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ EnumOptions<ModuleTypes::ModuleType> moduleTypes_("ModuleType", {{ModuleTypes::A
{ModuleTypes::Checks, "Checks"},
{ModuleTypes::CheckSpecies, "CheckSpecies"},
{ModuleTypes::Clustering, "Clustering"},
{ModuleTypes::CGNeutronSQ, "CGNeutronSQ"},
{ModuleTypes::Compare, "Compare"},
{ModuleTypes::DAngle, "DAngle"},
{ModuleTypes::DataTest, "DataTest"},
Expand Down
1 change: 1 addition & 0 deletions src/module/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum ModuleType
Checks,
CheckSpecies,
Clustering,
CGNeutronSQ,
Compare,
DAngle,
DataTest,
Expand Down
1 change: 1 addition & 0 deletions src/modules/cgNeutronSQ/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dissolve_add_module(cgNeutronSQ.h cgNeutronSQ)
79 changes: 79 additions & 0 deletions src/modules/cgNeutronSQ/cgNeutronSQ.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 Team Dissolve and contributors

#include "modules/cgNeutronSQ/cgNeutronSQ.h"
#include "keywords/atomTypeVector.h"
#include "keywords/bool.h"
#include "keywords/double.h"
#include "keywords/fileAndFormat.h"
#include "keywords/isotopologueSet.h"
#include "keywords/module.h"
#include "keywords/optionalDouble.h"
#include "modules/sq/sq.h"

CGNeutronSQModule::CGNeutronSQModule() : Module(ModuleTypes::NeutronSQ)
{
keywords_.addTarget<ModuleKeyword<const SQModule>>(
"SourceSQs", "Source unweighted S(Q) to transform into neutron-weighted S(Q)", sourceSQ_, ModuleTypes::SQ);

keywords_.setOrganisation("Options", "Isotopes & Normalisation",
"Specify isotopologues to use for specific species, and which atoms are exchangeable.");
keywords_.add<AtomTypeVectorKeyword>(
"Exchangeable", "A set of atom types in the system that are exchangeable with each other", exchangeable_);
keywords_.add<IsotopologueSetKeyword>("Isotopologue", "Set/add an isotopologue and its population for a particular species",
isotopologueSet_);
keywords_
.add<EnumOptionsKeyword<StructureFactors::NormalisationType>>("NormaliseTo",
"Normalisation to apply to total weighted F(Q)",
normaliseTo_, StructureFactors::normalisationTypes())
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});

keywords_.setOrganisation("Options", "Reference Data",
"Reference (typically experimental) data set to display. The experimental data may be used by "
"other modules if present. The normalisation already applied to the reference data should be "
"specified here, and will be removed internally.");
keywords_.add<FileAndFormatKeyword>("Reference", "F(Q) reference data", referenceFQ_, "EndReference")
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});
keywords_
.add<EnumOptionsKeyword<StructureFactors::NormalisationType>>(
"ReferenceNormalisedTo", "Normalisation that has been applied to the reference data", referenceNormalisedTo_,
StructureFactors::normalisationTypes())
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});
keywords_
.add<OptionalDoubleKeyword>("ReferenceFTQMin",
"Minimum Q value to use when Fourier-transforming reference data (0.0 for no minimum)",
referenceFTQMin_, 0.0, std::nullopt, 0.1, "No Minimum Limit")
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});
keywords_
.add<OptionalDoubleKeyword>("ReferenceFTQMax",
"Maximum Q value to use when Fourier-transforming reference data (0.0 for no maximum)",
referenceFTQMax_, 0.0, std::nullopt, 0.1, "No Maximum Limit")
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});
keywords_
.add<DoubleKeyword>("ReferenceFTDeltaR", "Spacing in r to use when generating the Fourier-transformed data",
referenceFTDeltaR_, 1.0e-4, 1.0)
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});
keywords_
.add<EnumOptionsKeyword<WindowFunction::Form>>(
"ReferenceWindowFunction", "Window function to apply when Fourier-transforming reference S(Q) to g(r)",
referenceWindowFunction_, WindowFunction::forms())
->setEditSignals({KeywordBase::ReloadExternalData, KeywordBase::RecreateRenderables});

keywords_.setOrganisation("Export");
keywords_.add<BoolKeyword>("SaveGR", "Save weighted g(r) and G(r)", saveGR_);
keywords_.add<BoolKeyword>("SaveReference", "Save the reference data and its Fourier transform", saveReference_);
keywords_.add<BoolKeyword>("SaveRepresentativeGR",
"Save representative G(r), obtained from Fourier transform of the calculated F(Q)",
saveRepresentativeGR_);
keywords_.add<BoolKeyword>("SaveSQ", "Save weighted partial and total structure factors", saveSQ_);

// Deprecated keywords
keywords_.addDeprecated<EnumOptionsKeyword<StructureFactors::NormalisationType>>(
"Normalisation", "Normalisation to apply to total weighted F(Q)", normaliseTo_, StructureFactors::normalisationTypes());
keywords_.addDeprecated<EnumOptionsKeyword<StructureFactors::NormalisationType>>(
"ReferenceNormalisation", "Normalisation to remove from reference data before use", referenceNormalisedTo_,
StructureFactors::normalisationTypes());
}

// Return file and format for reference total F(Q)
const Data1DImportFileFormat &CGNeutronSQModule::referenceFQFileAndFormat() { return referenceFQ_; }
95 changes: 95 additions & 0 deletions src/modules/cgNeutronSQ/cgNeutronSQ.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2025 Team Dissolve and contributors

#pragma once

#include "classes/isotopologueSet.h"
#include "classes/partialSet.h"
#include "data/structureFactors.h"
#include "io/import/data1D.h"
#include "math/windowFunction.h"
#include "module/module.h"

// Forward Declarations
class PartialSet;
class GRModule;
class SQModule;

// Neutron SQ Module
class CGNeutronSQModule : public Module
{
public:
CGNeutronSQModule();
~CGNeutronSQModule() override = default;

/*
* Definition
*/
private:
// Exchangeable atom types
std::vector<std::shared_ptr<AtomType>> exchangeable_;
// Isotopologues to use in weighting
IsotopologueSet isotopologueSet_;
// Normalisation to apply to calculated total F(Q)
StructureFactors::NormalisationType normaliseTo_{StructureFactors::NoNormalisation};
// Reference F(Q) file and format
Data1DImportFileFormat referenceFQ_{"", Data1DImportFileFormat::Data1DImportFormat::GudrunMint};
// Minimum Q value to use when Fourier-transforming the data
std::optional<double> referenceFTQMin_{0.3};
// Maximum Q value to use when Fourier-transforming the data
std::optional<double> referenceFTQMax_{30.0};
// Spacing in r to use when generating the Fourier-transformed data
double referenceFTDeltaR_{0.05};
// Normalisation to remove from reference total F(Q)
StructureFactors::NormalisationType referenceNormalisedTo_{StructureFactors::NoNormalisation};
// Window function to use when Fourier transforming reference total F(Q) into g(r)
WindowFunction::Form referenceWindowFunction_{WindowFunction::Form::Lorch0};
// Save weighted g(r) and G(r)
bool saveGR_{false};
// Save the reference data and its Fourier transform
bool saveReference_{false};
// Save representative G(r), obtained from Fourier transform of the calculated F(Q)
bool saveRepresentativeGR_{false};
// Save weighted partial and total structure factors
bool saveSQ_{false};
// Source module for calculation
const SQModule *sourceSQ_{nullptr};

public:
// Return file and format for reference total F(Q)
const Data1DImportFileFormat &referenceFQFileAndFormat();

/*
* Functions
*/
public:
// Calculate weighted g(r) from supplied unweighted g(r) and neutron weights
bool calculateWeightedGR(const PartialSet &unweightedgr, PartialSet &weightedgr, NeutronWeights &weights,
StructureFactors::NormalisationType normalisation);
// Calculate weighted S(Q) from supplied unweighted S(Q) and neutron weights
bool calculateWeightedSQ(const PartialSet &unweightedsq, PartialSet &weightedsq, NeutronWeights &weights,
const std::vector<Data1D> &ff, const std::vector<Data1D> &singleBead,
StructureFactors::NormalisationType normalisation);
// Calculate neutron weights for relevant Configuration targets
void calculateWeights(const GRModule *rdfModule, NeutronWeights &weights) const;
// Calculate the per bead form factor
bool calculateBeadFormFactor(const std::vector<double> &qvals, std::vector<Data1D> &ff,
const NeutronWeights &weights) const;
// Calculate the single bead internal scattering term
bool calculateSingleBead(std::vector<Data1D> &singleBead, const std::vector<Data1D> &ff,
const NeutronWeights &weights) const;

/*
* Processing
*/
private:
// Run main processing
Module::ExecutionResult process(ModuleContext &moduleContext) override;

public:
// Set target data
void setTargets(const std::vector<std::unique_ptr<Configuration>> &configurations,
const std::map<ModuleTypes::ModuleType, std::vector<const Module *>> &moduleMap) override;
// Run set-up stage
bool setUp(ModuleContext &moduleContext, Flags<KeywordBase::KeywordSignal> actionSignals) override;
};
Loading
Loading