PARTONS: PARtonic Tomography Of Nucleon Software
This page:
about
instalation
usage
development
license
acknowledgements
contact
View GitHub repository:
link
View Docker repository:
link
PARTONS was designed with the philosophy that users should be able to “plug in” their own models at any level of the computation chain. This is achieved without modifying the core PARTONS library. A developer simply needs to create a class (direcly in PARTONS or within their own project) that inherits from an abstract class of a given type and implements the required virtual functions.
This tutorial provides guidance on creating these new modules and includes templates that illustrate the structures developers must understand and complete.
BaseObjectRegistry::registerBaseObject().clone() function so the Factory can issue instances.resolveObjectDependencies() rather than the constructor.= 0 in the abstract class definition):
virtual void f() = 0;
You do not need to implement other virtual functions unless you wish to override the default behavior defined in the parent class.
C++
#include <iostream>
class A {
public:
virtual void f() {
std::cout << "Base definition in A" << std::endl;
}
};
class B : public A {
public:
virtual void f() {
A::f(); // Call parent implementation
}
};
class C : public B {
public:
virtual void f() {
B::f(); // Call parent implementation
std::cout << "Something new in C" << std::endl;
}
};
int main() {
A* pA = new C();
pA->f();
delete pA;
}
Output:
Base definition in A
Something new in C
While the implementation of B::f() isn’t strictly necessary here (as it only calls A::f()), you should ensure C::f() calls its parent to avoid losing functionality, unless you specifically intend to override the entire chain.
class MyGPDModel: public GPDModule, public MathIntegratorModule {
// ...
NumA::FunctionType1D* m_pFunctorForIntegrationFunction;
};
Initialize these functors in the constructor and set the default integration method in resolveObjectDependencies():
MyGPDModel::MyGPDModel(const std::string &className)
: GPDModule(className), MathIntegratorModule() {
m_pFunctorForIntegrationFunction = NumA::Integrator1D::newIntegrationFunctor(this, &MyGPDModel::integrationFunction);
}
void MyGPDModel::resolveObjectDependencies() {
setIntegrator(NumA::IntegratorType1D::DEXP);
}
The function to be integrated must follow this specific signature:
double MyGPDModel::integrationFunction(double x, std::vector<double> par) {
// Implementation...
}
To perform the integration:
// Additional parameters passed to the function
std::vector<double> parameters;
double min = 0.;
double max = 1.;
// Do the integration
double integrationResult = integrate(m_pFunctorForIntegrationFunction, min, max, parameters);
DVCSProcessBMJ12, GPDVinnikov06).DVCSAULMinus, DVCSAULMinusSin2Phi).Once your project is compiled, you can use your new module just like any other in PARTONS. For more details, see this tutorial. To instantiate a clone of your new GPD module, use the following:
// Clone GPD module using the ModuleObjectFactory with your custom module's classId
PARTONS::GPDModule* pGPDModel = PARTONS::Partons::getInstance()->getModuleObjectFactory()->newGPDModule(MyGPDModel::classId);
class MyGPDModel : public PARTONS::GPDModule {
public:
/** * Unique ID assigned by the BaseObjectRegistry.
*/
static const unsigned int classId;
/** * Default constructor.
* @param className Name of the class.
*/
MyGPDModel(const std::string& className);
/** * Destructor.
*/
virtual ~MyGPDModel();
virtual MyGPDModel* clone() const;
virtual void resolveObjectDependencies();
virtual void configure(const ElemUtils::Parameters ¶meters);
protected:
/** * Copy constructor.
* @param other Object to be copied.
*/
MyGPDModel(const MyGPDModel& other);
virtual void isModuleWellConfigured();
virtual void initModule();
// Specific GPD implementations
virtual PARTONS::PartonDistribution computeH();
virtual PARTONS::PartonDistribution computeE();
};
// Register the module in the PARTONS Registry
const unsigned int MyGPDModel::classId =
PARTONS::BaseObjectRegistry::getInstance()->registerBaseObject(new MyGPDModel("MyGPDModel"));
MyGPDModel::MyGPDModel(const std::string &className) : PARTONS::GPDModule(className) {
// Map specific GPD types to their corresponding calculation functions
m_listGPDComputeTypeAvailable.insert(
std::make_pair(PARTONS::GPDType::H, &PARTONS::GPDModule::computeH));
m_listGPDComputeTypeAvailable.insert(
std::make_pair(PARTONS::GPDType::E, &PARTONS::GPDModule::computeE));
}
MyGPDModel::MyGPDModel(const MyGPDModel& other) : PARTONS::GPDModule(other) {
}
MyGPDModel::~MyGPDModel() {
}
MyGPDModel* MyGPDModel::clone() const {
return new MyGPDModel(*this);
}
void MyGPDModel::resolveObjectDependencies() {
// Initialize sub-modules here if necessary
}
void MyGPDModel::configure(const ElemUtils::Parameters ¶meters) {
PARTONS::GPDModule::configure(parameters);
}
void MyGPDModel::isModuleWellConfigured() {
PARTONS::GPDModule::isModuleWellConfigured();
}
void MyGPDModel::initModule() {
PARTONS::GPDModule::initModule();
}
PARTONS::PartonDistribution MyGPDModel::computeH() {
// Initialize result container
PARTONS::PartonDistribution result;
// TODO: Your model implementation comes here
// Use kinematics variables (m_x, m_xi, etc.) to perform calculations
return result;
}
PARTONS::PartonDistribution MyGPDModel::computeE() {
// Implementation follows the same logic as computeH()
PARTONS::PartonDistribution result;
return result;
}
The following variables are defined in the parent abstract classes and are essential for implementing your GPD calculations. They store the current kinematic state for the evaluation:
double m_x; (x)double m_xi;(xi)double m_t; (t)double m_MuF2; (factorization scale squared)double m_MuR2; (renormalization scale squared)GPDType::Type m_gpdType; (indicates the specific GPD type currently being evaluated)